gdth driver is modified NOT to use scp->eh_timeout. Now, it has
eh_timed_out (gdth_timed_out) to handle command timeouts for locked
I/O's. Have not tested as I don't have needed hardware! Patch is
against 2.6.23-mm1.
Thank you Matthew Wilcox for your input on the IRC channel.
Signed-off-by: Malahal Naineni <[EMAIL PROTECTED]>
diff -r dbb45a1edd2a drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c Mon Nov 05 21:32:26 2007 -0800
+++ b/drivers/scsi/gdth.c Mon Nov 05 21:54:27 2007 -0800
@@ -2056,22 +2056,12 @@ static void gdth_putq(gdth_ha_str *ha, S
register Scsi_Cmnd *pscp;
register Scsi_Cmnd *nscp;
ulong flags;
- unchar b, t;
TRACE(("gdth_putq() priority %d\n",priority));
spin_lock_irqsave(&ha->smp_lock, flags);
if (!cmndinfo->internal_command) {
cmndinfo->priority = priority;
- b = scp->device->channel;
- t = scp->device->id;
- if (priority >= DEFAULT_PRI) {
- if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
- (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
- TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
- cmndinfo->timeout = gdth_update_timeout(scp, 0);
- }
- }
}
if (ha->req_first==NULL) {
@@ -2359,7 +2349,7 @@ static void gdth_copy_internal_data(gdth
{
ushort cpcount,i, max_sg = gdth_sg_count(scp);
ushort cpsum,cpnow;
- struct scatterlist *sl, *sg;
+ struct scatterlist *sl;
char *address;
cpcount = min_t(ushort, count, gdth_bufflen(scp));
@@ -3938,6 +3928,38 @@ static const char *gdth_info(struct Scsi
return ((const char *)ha->binfo.type_string);
}
+static enum scsi_eh_timer_return gdth_timed_out(struct scsi_cmnd *scp)
+{
+ gdth_ha_str *ha = shost_priv(scp->device->host);
+ struct gdth_cmndinfo *cmndinfo = gdth_get_cmndinfo(ha);
+ unchar b, t;
+ ulong flags;
+ enum scsi_eh_timer_return retval = EH_NOT_HANDLED;
+
+ TRACE(("%s() cmd 0x%x\n", scp->cmnd[0], __FUNCTION__));
+ b = scp->device->channel;
+ t = scp->device->id;
+
+ /*
+ * We don't really honor the command timeout, but we try to
+ * honor 6 times of the actual command timeout! So reset the
+ * timer if this is less than 6th timeout on this command!
+ */
+ if (++cmndinfo->timeout_count < 6)
+ retval = EH_RESET_TIMER;
+
+ /* Reset the timeout if it is locked IO */
+ spin_lock_irqsave(&ha->smp_lock, flags);
+ if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha, b)].lock) ||
+ (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
+ TRACE2(("%s(): locked IO, reset timeout\n", __FUNCTION__));
+ retval = EH_RESET_TIMER;
+ }
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
+
+ return retval;
+}
+
static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
{
gdth_ha_str *ha = shost_priv(scp->device->host);
@@ -4031,7 +4053,7 @@ static int gdth_queuecommand(struct scsi
BUG_ON(!cmndinfo);
scp->scsi_done = done;
- gdth_update_timeout(scp, scp->timeout_per_command * 6);
+ cmndinfo->timeout_count = 0;
cmndinfo->priority = DEFAULT_PRI;
gdth_set_bufflen(scp, scsi_bufflen(scp));
@@ -4137,12 +4159,10 @@ static int ioc_lockdrv(void __user *arg)
ha->hdr[j].lock = 1;
spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_wait_completion(ha, ha->bus_cnt, j);
- gdth_stop_timeout(ha, ha->bus_cnt, j);
} else {
spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 0;
spin_unlock_irqrestore(&ha->smp_lock, flags);
- gdth_start_timeout(ha, ha->bus_cnt, j);
gdth_next(ha);
}
}
@@ -4582,14 +4602,12 @@ static int gdth_ioctl(struct inode *inod
spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_wait_completion(ha, i, j);
- gdth_stop_timeout(ha, i, j);
}
} else {
spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 0;
spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
- gdth_start_timeout(ha, i, j);
gdth_next(ha);
}
}
@@ -4724,6 +4742,7 @@ static struct scsi_host_template gdth_te
.slave_configure = gdth_slave_configure,
.bios_param = gdth_bios_param,
.proc_info = gdth_proc_info,
+ .eh_timed_out = gdth_timed_out,
.proc_name = "gdth",
.can_queue = GDTH_MAXCMDS,
.this_id = -1,
diff -r dbb45a1edd2a drivers/scsi/gdth.h
--- a/drivers/scsi/gdth.h Mon Nov 05 21:32:26 2007 -0800
+++ b/drivers/scsi/gdth.h Mon Nov 05 21:55:15 2007 -0800
@@ -917,7 +917,7 @@ typedef struct {
int internal_command; /* don't call scsi_done */
dma_addr_t sense_paddr; /* sense dma-addr */
unchar priority;
- int timeout;
+ int timeout_count; /* # of timeout calls */
volatile int wait_for_completion;
ushort status;
ulong32 info;
diff -r dbb45a1edd2a drivers/scsi/gdth_proc.c
--- a/drivers/scsi/gdth_proc.c Mon Nov 05 21:32:26 2007 -0800
+++ b/drivers/scsi/gdth_proc.c Mon Nov 05 21:32:31 2007 -0800
@@ -750,69 +750,3 @@ static void gdth_wait_completion(gdth_ha
}
spin_unlock_irqrestore(&ha->smp_lock, flags);
}
-
-static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id)
-{
- ulong flags;
- Scsi_Cmnd *scp;
- unchar b, t;
-
- spin_lock_irqsave(&ha->smp_lock, flags);
-
- for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
- if (!cmndinfo->internal_command) {
- b = scp->device->channel;
- t = scp->device->id;
- if (t == (unchar)id && b == (unchar)busnum) {
- TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
- cmndinfo->timeout = gdth_update_timeout(scp, 0);
- }
- }
- }
- spin_unlock_irqrestore(&ha->smp_lock, flags);
-}
-
-static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id)
-{
- ulong flags;
- Scsi_Cmnd *scp;
- unchar b, t;
-
- spin_lock_irqsave(&ha->smp_lock, flags);
-
- for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
- if (!cmndinfo->internal_command) {
- b = scp->device->channel;
- t = scp->device->id;
- if (t == (unchar)id && b == (unchar)busnum) {
- TRACE2(("gdth_start_timeout(): update_timeout()\n"));
- gdth_update_timeout(scp, cmndinfo->timeout);
- }
- }
- }
- spin_unlock_irqrestore(&ha->smp_lock, flags);
-}
-
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout)
-{
- int oldto;
-
- oldto = scp->timeout_per_command;
- scp->timeout_per_command = timeout;
-
- if (timeout == 0) {
- del_timer(&scp->eh_timeout);
- scp->eh_timeout.data = (unsigned long) NULL;
- scp->eh_timeout.expires = 0;
- } else {
- if (scp->eh_timeout.data != (unsigned long) NULL)
- del_timer(&scp->eh_timeout);
- scp->eh_timeout.data = (unsigned long) scp;
- scp->eh_timeout.expires = jiffies + timeout;
- add_timer(&scp->eh_timeout);
- }
-
- return oldto;
-}
diff -r dbb45a1edd2a drivers/scsi/gdth_proc.h
--- a/drivers/scsi/gdth_proc.h Mon Nov 05 21:32:26 2007 -0800
+++ b/drivers/scsi/gdth_proc.h Mon Nov 05 21:32:31 2007 -0800
@@ -20,9 +20,6 @@ static char *gdth_ioctl_alloc(gdth_ha_st
ulong64 *paddr);
static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64
paddr);
static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id);
-static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id);
-static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id);
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout);
#endif
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html