Skip to content

Commit

Permalink
[SCSI] aic94xx: fix TMF ascb handling to prevent sequencer panic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Bottomley authored and James Bottomley committed Feb 24, 2008
1 parent 8de3ef2 commit e2396f1
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 114 deletions.
3 changes: 1 addition & 2 deletions drivers/scsi/aic94xx/aic94xx_hwi.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ struct asd_ascb {

/* internally generated command */
struct timer_list timer;
struct completion completion;
struct completion *completion;
u8 tag_valid:1;
__be16 tag; /* error recovery only */

Expand Down Expand Up @@ -294,7 +294,6 @@ static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
ascb->timer.function = NULL;
init_timer(&ascb->timer);
ascb->tc_index = -1;
init_completion(&ascb->completion);
}

/* Must be called with the tc_index_lock held!
Expand Down
4 changes: 3 additions & 1 deletion drivers/scsi/aic94xx/aic94xx_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,13 @@ static void asd_task_tasklet_complete(struct asd_ascb *ascb,
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
task->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
struct completion *completion = ascb->completion;
spin_unlock_irqrestore(&task->task_state_lock, flags);
ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x "
"stat 0x%x but aborted by upper layer!\n",
task, opcode, ts->resp, ts->stat);
complete(&ascb->completion);
if (completion)
complete(completion);
} else {
spin_unlock_irqrestore(&task->task_state_lock, flags);
task->lldd_task = NULL;
Expand Down
Loading

0 comments on commit e2396f1

Please sign in to comment.