[PATCH] SCSI: implement shost->host_eh_scheduled
libata needs to invoke EH without scmd. This patch adds shost->host_eh_scheduled to implement such behavior. Currently the only user of this feature is libata and no general interface is defined. This patch simply adds handling for host_eh_scheduled where needed and exports scsi_eh_wakeup() to modules. The rest is upto libata. This is the result of the following discussion. http://thread.gmane.org/gmane.linux.scsi/23853/focus=9760 In short, SCSI host is not supposed to know about exceptions unrelated to specific device or command. Such exceptions should be handled by transport layer proper. However, the distinction is not essential to ATA and libata is planning to depart from SCSI, so, for the time being, libata will be using SCSI EH to handle such exceptions. Signed-off-by: Tejun Heo <htejun@gmail.com>
This commit is contained in:
parent
89f48c4d67
commit
ee7863bc68
|
@ -56,6 +56,7 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
|
|||
printk("Waking error handler thread\n"));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(scsi_eh_wakeup);
|
||||
|
||||
/**
|
||||
* scsi_eh_scmd_add - add scsi cmd to error handling.
|
||||
|
@ -1517,7 +1518,7 @@ int scsi_error_handler(void *data)
|
|||
*/
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
while (!kthread_should_stop()) {
|
||||
if (shost->host_failed == 0 ||
|
||||
if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
|
||||
shost->host_failed != shost->host_busy) {
|
||||
SCSI_LOG_ERROR_RECOVERY(1,
|
||||
printk("Error handler scsi_eh_%d sleeping\n",
|
||||
|
|
|
@ -566,7 +566,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
|
|||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
shost->host_busy--;
|
||||
if (unlikely(scsi_host_in_recovery(shost) &&
|
||||
shost->host_failed))
|
||||
(shost->host_failed || shost->host_eh_scheduled)))
|
||||
scsi_eh_wakeup(shost);
|
||||
spin_unlock(shost->host_lock);
|
||||
spin_lock(sdev->request_queue->queue_lock);
|
||||
|
|
|
@ -63,7 +63,6 @@ extern int scsi_delete_timer(struct scsi_cmnd *);
|
|||
extern void scsi_times_out(struct scsi_cmnd *cmd);
|
||||
extern int scsi_error_handler(void *host);
|
||||
extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
|
||||
extern void scsi_eh_wakeup(struct Scsi_Host *shost);
|
||||
extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
|
||||
|
||||
/* scsi_lib.c */
|
||||
|
|
|
@ -35,6 +35,7 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
|
|||
}
|
||||
|
||||
|
||||
extern void scsi_eh_wakeup(struct Scsi_Host *shost);
|
||||
extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
|
||||
struct list_head *done_q);
|
||||
extern void scsi_eh_flush_done_q(struct list_head *done_q);
|
||||
|
|
|
@ -472,6 +472,7 @@ struct Scsi_Host {
|
|||
*/
|
||||
unsigned int host_busy; /* commands actually active on low-level */
|
||||
unsigned int host_failed; /* commands that failed. */
|
||||
unsigned int host_eh_scheduled; /* EH scheduled without command */
|
||||
|
||||
unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
|
||||
int resetting; /* if set, it means that last_reset is a valid value */
|
||||
|
|
Loading…
Reference in New Issue