Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac
[deliverable/linux.git] / drivers / scsi / scsi_error.c
index d0f71e5d065f901c3070e7d07f6c03aa42baceaa..4a6381c87253ec4be307eb47dc8d1ff6ebad4dc3 100644 (file)
@@ -1687,6 +1687,20 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
         * requests are started.
         */
        scsi_run_host_queues(shost);
+
+       /*
+        * if eh is active and host_eh_scheduled is pending we need to re-run
+        * recovery.  we do this check after scsi_run_host_queues() to allow
+        * everything pent up since the last eh run a chance to make forward
+        * progress before we sync again.  Either we'll immediately re-run
+        * recovery or scsi_device_unbusy() will wake us again when these
+        * pending commands complete.
+        */
+       spin_lock_irqsave(shost->host_lock, flags);
+       if (shost->host_eh_scheduled)
+               if (scsi_host_set_state(shost, SHOST_RECOVERY))
+                       WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY));
+       spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
 /**
@@ -1804,15 +1818,14 @@ int scsi_error_handler(void *data)
         * We never actually get interrupted because kthread_run
         * disables signal delivery for the created thread.
         */
-       set_current_state(TASK_INTERRUPTIBLE);
        while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
                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",
                                        shost->host_no));
                        schedule();
-                       set_current_state(TASK_INTERRUPTIBLE);
                        continue;
                }
 
@@ -1849,7 +1862,6 @@ int scsi_error_handler(void *data)
                scsi_restart_operations(shost);
                if (!shost->eh_noresume)
                        scsi_autopm_put_host(shost);
-               set_current_state(TASK_INTERRUPTIBLE);
        }
        __set_current_state(TASK_RUNNING);
 
This page took 0.024822 seconds and 5 git commands to generate.