]> err.no Git - linux-2.6/blobdiff - drivers/scsi/scsi_error.c
[PATCH] ahci: convert to new probing mechanism and add hotplug support
[linux-2.6] / drivers / scsi / scsi_error.c
index ff82ccfbb106b528539e112168a1aba8d250294c..346ab72ebf86e2ba7b8b438edb0e60fb230c75d3 100644 (file)
@@ -29,6 +29,7 @@
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_transport.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
@@ -56,6 +57,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
        }
 }
 
+/**
+ * scsi_schedule_eh - schedule EH for SCSI host
+ * @shost:     SCSI host to invoke error handling on.
+ *
+ * Schedule SCSI EH without scmd.
+ **/
+void scsi_schedule_eh(struct Scsi_Host *shost)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(shost->host_lock, flags);
+
+       if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
+           scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
+               shost->host_eh_scheduled++;
+               scsi_eh_wakeup(shost);
+       }
+
+       spin_unlock_irqrestore(shost->host_lock, flags);
+}
+EXPORT_SYMBOL_GPL(scsi_schedule_eh);
+
 /**
  * scsi_eh_scmd_add - add scsi cmd to error handling.
  * @scmd:      scmd to run eh on.
@@ -163,16 +186,12 @@ void scsi_times_out(struct scsi_cmnd *scmd)
 {
        scsi_log_completion(scmd, TIMEOUT_ERROR);
 
-       if (scmd->device->host->hostt->eh_timed_out)
-               switch (scmd->device->host->hostt->eh_timed_out(scmd)) {
+       if (scmd->device->host->transportt->eh_timed_out)
+               switch (scmd->device->host->transportt->eh_timed_out(scmd)) {
                case EH_HANDLED:
                        __scsi_done(scmd);
                        return;
                case EH_RESET_TIMER:
-                       /* This allows a single retry even of a command
-                        * with allowed == 0 */
-                       if (scmd->retries++ > scmd->allowed)
-                               break;
                        scsi_add_timer(scmd, scmd->timeout_per_command,
                                       scsi_times_out);
                        return;
@@ -584,8 +603,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
  *    keep a list of pending commands for final completion, and once we
  *    are ready to leave error handling we handle completion for real.
  **/
-static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
-                              struct list_head *done_q)
+void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
 {
        scmd->device->host->host_failed--;
        scmd->eh_eflags = 0;
@@ -597,6 +615,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
        scsi_setup_cmd_retry(scmd);
        list_move_tail(&scmd->eh_entry, done_q);
 }
+EXPORT_SYMBOL(scsi_eh_finish_cmd);
 
 /**
  * scsi_eh_get_sense - Get device sense data.
@@ -1425,7 +1444,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
  * @done_q:    list_head of processed commands.
  *
  **/
-static void scsi_eh_flush_done_q(struct list_head *done_q)
+void scsi_eh_flush_done_q(struct list_head *done_q)
 {
        struct scsi_cmnd *scmd, *next;
 
@@ -1454,6 +1473,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
                }
        }
 }
+EXPORT_SYMBOL(scsi_eh_flush_done_q);
 
 /**
  * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
@@ -1519,7 +1539,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",
@@ -1539,8 +1559,8 @@ int scsi_error_handler(void *data)
                 * what we need to do to get it up and online again (if we can).
                 * If we fail, we end up taking the thing offline.
                 */
-               if (shost->hostt->eh_strategy_handler) 
-                       shost->hostt->eh_strategy_handler(shost);
+               if (shost->transportt->eh_strategy_handler)
+                       shost->transportt->eh_strategy_handler(shost);
                else
                        scsi_unjam_host(shost);