aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx/aic94xx_task.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-24 00:44:19 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-24 01:40:57 -0500
commite2396f1e4ecd438a15fa653a028b93e95013caa3 (patch)
tree8cc11b28b64fbf3a7a22d1636467d35174092e27 /drivers/scsi/aic94xx/aic94xx_task.c
parent8de3ef25a1fcd28d270b69417a41b424826d4f89 (diff)
[SCSI] aic94xx: fix TMF ascb handling to prevent sequencer panic
This is a particularly nasty bug. The problem is that if any internal ascb times out, currently we free it even though it's pending at the sequencer. This results in the sequencer getting terminally confused and the error message: BUG:sequencer:dl:no ascb Being returned when it comes back. The way to fix this is to manage freeing the ascb from the tasklet completion routine, so that we only free it when the sequencer actually returns it. The code is also altered to use on stack completions and transfer variables. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/aic94xx/aic94xx_task.c')
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index 965d4bb999d9..008df9ab92a5 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -343,11 +343,13 @@ Again:
343 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; 343 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
344 task->task_state_flags |= SAS_TASK_STATE_DONE; 344 task->task_state_flags |= SAS_TASK_STATE_DONE;
345 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { 345 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
346 struct completion *completion = ascb->completion;
346 spin_unlock_irqrestore(&task->task_state_lock, flags); 347 spin_unlock_irqrestore(&task->task_state_lock, flags);
347 ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x " 348 ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x "
348 "stat 0x%x but aborted by upper layer!\n", 349 "stat 0x%x but aborted by upper layer!\n",
349 task, opcode, ts->resp, ts->stat); 350 task, opcode, ts->resp, ts->stat);
350 complete(&ascb->completion); 351 if (completion)
352 complete(completion);
351 } else { 353 } else {
352 spin_unlock_irqrestore(&task->task_state_lock, flags); 354 spin_unlock_irqrestore(&task->task_state_lock, flags);
353 task->lldd_task = NULL; 355 task->lldd_task = NULL;