aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2007-01-11 17:14:55 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-01-13 17:12:39 -0500
commitb218a0d8e250e0ae8fd4d4e45bd66a588b380752 (patch)
tree6c60dc11ef8d064404eb2fd6a3b4f37529a2c72f
parentbf451207511d049189ddb0a4eae3acdb086a3c82 (diff)
[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>
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c9
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c7
-rw-r--r--include/scsi/libsas.h1
3 files changed, 17 insertions, 0 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index d202ed5a6709..e2ad5bed9403 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -349,6 +349,7 @@ Again:
349 349
350 spin_lock_irqsave(&task->task_state_lock, flags); 350 spin_lock_irqsave(&task->task_state_lock, flags);
351 task->task_state_flags &= ~SAS_TASK_STATE_PENDING; 351 task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
352 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
352 task->task_state_flags |= SAS_TASK_STATE_DONE; 353 task->task_state_flags |= SAS_TASK_STATE_DONE;
353 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { 354 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
354 spin_unlock_irqrestore(&task->task_state_lock, flags); 355 spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -557,6 +558,7 @@ int asd_execute_task(struct sas_task *task, const int num,
557 struct sas_task *t = task; 558 struct sas_task *t = task;
558 struct asd_ascb *ascb = NULL, *a; 559 struct asd_ascb *ascb = NULL, *a;
559 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; 560 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
561 unsigned long flags;
560 562
561 res = asd_can_queue(asd_ha, num); 563 res = asd_can_queue(asd_ha, num);
562 if (res) 564 if (res)
@@ -599,6 +601,10 @@ int asd_execute_task(struct sas_task *task, const int num,
599 } 601 }
600 if (res) 602 if (res)
601 goto out_err_unmap; 603 goto out_err_unmap;
604
605 spin_lock_irqsave(&t->task_state_lock, flags);
606 t->task_state_flags |= SAS_TASK_AT_INITIATOR;
607 spin_unlock_irqrestore(&t->task_state_lock, flags);
602 } 608 }
603 list_del_init(&alist); 609 list_del_init(&alist);
604 610
@@ -617,6 +623,9 @@ out_err_unmap:
617 if (a == b) 623 if (a == b)
618 break; 624 break;
619 t = a->uldd_task; 625 t = a->uldd_task;
626 spin_lock_irqsave(&t->task_state_lock, flags);
627 t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
628 spin_unlock_irqrestore(&t->task_state_lock, flags);
620 switch (t->task_proto) { 629 switch (t->task_proto) {
621 case SATA_PROTO: 630 case SATA_PROTO:
622 case SAS_PROTO_STP: 631 case SAS_PROTO_STP:
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 22672d54aa27..21bd24775980 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -542,6 +542,13 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
542 cmd, task); 542 cmd, task);
543 return EH_HANDLED; 543 return EH_HANDLED;
544 } 544 }
545 if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
546 spin_unlock_irqrestore(&task->task_state_lock, flags);
547 SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
548 "EH_RESET_TIMER\n",
549 cmd, task);
550 return EH_RESET_TIMER;
551 }
545 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 552 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
546 spin_unlock_irqrestore(&task->task_state_lock, flags); 553 spin_unlock_irqrestore(&task->task_state_lock, flags);
547 554
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 0c775fceb675..da96bcfb9e46 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -554,6 +554,7 @@ struct sas_task {
554#define SAS_TASK_STATE_DONE 2 554#define SAS_TASK_STATE_DONE 2
555#define SAS_TASK_STATE_ABORTED 4 555#define SAS_TASK_STATE_ABORTED 4
556#define SAS_TASK_INITIATOR_ABORTED 8 556#define SAS_TASK_INITIATOR_ABORTED 8
557#define SAS_TASK_AT_INITIATOR 16
557 558
558static inline struct sas_task *sas_alloc_task(gfp_t flags) 559static inline struct sas_task *sas_alloc_task(gfp_t flags)
559{ 560{