aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-08-05 22:45:40 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-08-08 10:55:39 -0400
commitb21a41385118f9a6af3cd96ce71090c5ada52eb5 (patch)
tree4eb9124ae72e1a905094c259465718793698e603 /drivers/scsi
parentf03a567054fea4f9d43c50ec91338266c0bd588d (diff)
[SCSI] add global timeout to the scsi mid-layer
There are certain rogue devices (and the aic7xxx driver) that return BUSY or QUEUE_FULL forever. This code will apply a global timeout (of the total number of retries times the per command timer) to a given command. If it is exceeded, the command is completed regardless of its state. The patch also removes the unused field in the command: timeout and timeout_total. This solves the problem of detecting an endless loop in the mid-layer because of BUSY/QUEUE_FULL bouncing, but will not recover the device. In the aic7xxx case, the driver can be recovered by sending a bus reset, so possibly this should be tied into the error handler? Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/advansys.c4
-rw-r--r--drivers/scsi/scsi.c15
2 files changed, 17 insertions, 2 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0fb93363eb22..37ec5411e325 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
9200 (unsigned) s->serial_number, s->retries, s->allowed); 9200 (unsigned) s->serial_number, s->retries, s->allowed);
9201 9201
9202 printk( 9202 printk(
9203" timeout_per_command %d, timeout_total %d, timeout %d\n", 9203" timeout_per_command %d\n",
9204 s->timeout_per_command, s->timeout_total, s->timeout); 9204 s->timeout_per_command);
9205 9205
9206 printk( 9206 printk(
9207" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", 9207" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d1aa95d45a70..4befbc275f94 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
268 } else 268 } else
269 put_device(&dev->sdev_gendev); 269 put_device(&dev->sdev_gendev);
270 270
271 cmd->jiffies_at_alloc = jiffies;
271 return cmd; 272 return cmd;
272} 273}
273EXPORT_SYMBOL(scsi_get_command); 274EXPORT_SYMBOL(scsi_get_command);
@@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_action *h)
798 while (!list_empty(&local_q)) { 799 while (!list_empty(&local_q)) {
799 struct scsi_cmnd *cmd = list_entry(local_q.next, 800 struct scsi_cmnd *cmd = list_entry(local_q.next,
800 struct scsi_cmnd, eh_entry); 801 struct scsi_cmnd, eh_entry);
802 /* The longest time any command should be outstanding is the
803 * per command timeout multiplied by the number of retries.
804 *
805 * For a typical command, this is 2.5 minutes */
806 unsigned long wait_for
807 = cmd->allowed * cmd->timeout_per_command;
801 list_del_init(&cmd->eh_entry); 808 list_del_init(&cmd->eh_entry);
802 809
803 disposition = scsi_decide_disposition(cmd); 810 disposition = scsi_decide_disposition(cmd);
811 if (disposition != SUCCESS &&
812 time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
813 dev_printk(KERN_ERR, &cmd->device->sdev_gendev,
814 "timing out command, waited %ds\n",
815 wait_for/HZ);
816 disposition = SUCCESS;
817 }
818
804 scsi_log_completion(cmd, disposition); 819 scsi_log_completion(cmd, disposition);
805 switch (disposition) { 820 switch (disposition) {
806 case SUCCESS: 821 case SUCCESS: