mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
[SCSI] libsas: Don't give scsi_cmnds to the EH if they never made it to the SAS LLDD or have already returned
On a system with many SAS targets, it appears possible that a scsi_cmnd can time out without ever making it to the SAS LLDD or at the same time that a completion is occurring. In both of these cases, telling the LLDD to abort the sas_task makes no sense because the LLDD won't know about the sas_task; what we really want to do is to increase the timer. Note that this involves creating another sas_task bit to indicate whether or not the task has been sent to the LLDD; I could have implemented this by slightly redefining SAS_TASK_STATE_PENDING, but this way seems cleaner. This second version amends the aic94xx portion to set the TASK_AT_INITIATOR flag for all sas_tasks that were passed to lldd_execute_task. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
bf45120751
commit
b218a0d8e2
@ -349,6 +349,7 @@ Again:
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
|
||||
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))) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
@ -557,6 +558,7 @@ int asd_execute_task(struct sas_task *task, const int num,
|
||||
struct sas_task *t = task;
|
||||
struct asd_ascb *ascb = NULL, *a;
|
||||
struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
|
||||
unsigned long flags;
|
||||
|
||||
res = asd_can_queue(asd_ha, num);
|
||||
if (res)
|
||||
@ -599,6 +601,10 @@ int asd_execute_task(struct sas_task *task, const int num,
|
||||
}
|
||||
if (res)
|
||||
goto out_err_unmap;
|
||||
|
||||
spin_lock_irqsave(&t->task_state_lock, flags);
|
||||
t->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&t->task_state_lock, flags);
|
||||
}
|
||||
list_del_init(&alist);
|
||||
|
||||
@ -617,6 +623,9 @@ out_err_unmap:
|
||||
if (a == b)
|
||||
break;
|
||||
t = a->uldd_task;
|
||||
spin_lock_irqsave(&t->task_state_lock, flags);
|
||||
t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&t->task_state_lock, flags);
|
||||
switch (t->task_proto) {
|
||||
case SATA_PROTO:
|
||||
case SAS_PROTO_STP:
|
||||
|
@ -542,6 +542,13 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
|
||||
cmd, task);
|
||||
return EH_HANDLED;
|
||||
}
|
||||
if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
|
||||
"EH_RESET_TIMER\n",
|
||||
cmd, task);
|
||||
return EH_RESET_TIMER;
|
||||
}
|
||||
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
|
@ -554,6 +554,7 @@ struct sas_task {
|
||||
#define SAS_TASK_STATE_DONE 2
|
||||
#define SAS_TASK_STATE_ABORTED 4
|
||||
#define SAS_TASK_INITIATOR_ABORTED 8
|
||||
#define SAS_TASK_AT_INITIATOR 16
|
||||
|
||||
static inline struct sas_task *sas_alloc_task(gfp_t flags)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user