summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx/aic94xx_init.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2006-11-15 03:02:07 +0100
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 18:10:02 +0100
commit7b4feee973ca7be63345b92a987ef7ef879b179b (patch)
tree565295b48d73446358a1c36dab55eec102dffed8 /drivers/scsi/aic94xx/aic94xx_init.c
parent[PATCH] aic94xx: handle REQ_DEVICE_RESET (diff)
downloadlinux-7b4feee973ca7be63345b92a987ef7ef879b179b.tar.xz
linux-7b4feee973ca7be63345b92a987ef7ef879b179b.zip
[PATCH] aic94xx: delete ascb timers when freeing queues
When the aic94xx driver creates ascbs, each ascb is initialized with a timeout timer. If there are any ascbs left over when the driver is being torn down, these timers need to be deleted. In particular, we seem to hit this case when ascbs are issued yet never end up on the done list. Right now there's a sequencer bug that results in this happening every so often. CONTROL PHY commands are typically sent when things are really messed up with the sequencer; however, any other leftover ascb should produce loud warnings. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic94xx/aic94xx_init.c')
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 99743ca29ca1..3a5bbba3976e 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -724,6 +724,15 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha)
list_for_each_safe(pos, n, &pending) {
struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list);
+ /*
+ * Delete unexpired ascb timers. This may happen if we issue
+ * a CONTROL PHY scb to an adapter and rmmod before the scb
+ * times out. Apparently we don't wait for the CONTROL PHY
+ * to complete, so it doesn't matter if we kill the timer.
+ */
+ del_timer_sync(&ascb->timer);
+ WARN_ON(ascb->scb->header.opcode != CONTROL_PHY);
+
list_del_init(pos);
ASD_DPRINTK("freeing from pending\n");
asd_ascb_free(ascb);