VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / scsi / scsi_error.c
index 58ac231..288f2fd 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
-#include <scsi/scsi_ioctl.h>
 
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
-#ifdef DEBUG
-#define SENSE_TIMEOUT SCSI_TIMEOUT
-#else
-#define SENSE_TIMEOUT (10*HZ)
-#endif
-
-#define START_UNIT_TIMEOUT (30*HZ)
+#define SENSE_TIMEOUT          (10*HZ)
+#define START_UNIT_TIMEOUT     (30*HZ)
 
 /*
  * These should *probably* be handled by the host itself.
  * Since it is allowed to sleep, it probably should.
  */
-#define BUS_RESET_SETTLE_TIME   10*HZ
-#define HOST_RESET_SETTLE_TIME  10*HZ
+#define BUS_RESET_SETTLE_TIME   (10*HZ)
+#define HOST_RESET_SETTLE_TIME  (10*HZ)
 
 /* called with shost->host_lock held */
 void scsi_eh_wakeup(struct Scsi_Host *shost)
@@ -167,6 +166,24 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
 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)) {
+               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;
+               case EH_NOT_HANDLED:
+                       break;
+               }
+
        if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
                panic("Error handler thread not present at %p %p %s %d",
                      scmd, scmd->device->host, __FILE__, __LINE__);
@@ -660,7 +677,7 @@ static int scsi_eh_get_sense(struct list_head *work_q,
                SCSI_LOG_ERROR_RECOVERY(3, printk("sense requested for %p"
                                                  " result %x\n", scmd,
                                                  scmd->result));
-               SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", scmd));
+               SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd));
 
                rtn = scsi_decide_disposition(scmd);
 
@@ -1026,7 +1043,8 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
        spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
        if (rtn == SUCCESS) {
-               scsi_sleep(BUS_RESET_SETTLE_TIME);
+               if (!scmd->device->host->hostt->skip_settle_delay)
+                       scsi_sleep(BUS_RESET_SETTLE_TIME);
                spin_lock_irqsave(scmd->device->host->host_lock, flags);
                scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
                spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1057,7 +1075,8 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
        spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
        if (rtn == SUCCESS) {
-               scsi_sleep(HOST_RESET_SETTLE_TIME);
+               if (!scmd->device->host->hostt->skip_settle_delay)
+                       scsi_sleep(HOST_RESET_SETTLE_TIME);
                spin_lock_irqsave(scmd->device->host->host_lock, flags);
                scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
                spin_unlock_irqrestore(scmd->device->host->host_lock, flags);