aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-15 10:28:43 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-18 09:57:15 -0500
commitcb84e2d2ff3b50c0da5a7604a6d8634294a00a01 (patch)
treed94f524f967583bbe26da0bb15ea48f230d83f43 /drivers/scsi
parent691b4773aa556d0975dbc25c93e6c8b839dad325 (diff)
[SCSI] aic94xx: fix REQ_TASK_ABORT and REQ_DEVICE_RESET
This driver has been failing under heavy load with aic94xx: escb_tasklet_complete: REQ_TASK_ABORT, reason=0x6 aic94xx: escb_tasklet_complete: Can't find task (tc=4) to abort! The second message is because the driver fails to identify the task it's being asked to abort. On closer inpection, there's a thinko in the for each task loop over pending tasks in both the REQ_TASK_ABORT and REQ_DEVICE_RESET cases where it doesn't look at the task on the pending list but at the one on the ESCB (which is always NULL). Fix by looking at the right task. Also add a print for the case where the pending SCB doesn't have a task attached. Not sure if this will fix all the problems, but it's a definite first step. Cc: Stable Tree <stable@kernel.org> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 0febad4dd75f..ab350504ca5a 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -458,13 +458,19 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
458 tc_abort = le16_to_cpu(tc_abort); 458 tc_abort = le16_to_cpu(tc_abort);
459 459
460 list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { 460 list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
461 struct sas_task *task = ascb->uldd_task; 461 struct sas_task *task = a->uldd_task;
462
463 if (a->tc_index != tc_abort)
464 continue;
462 465
463 if (task && a->tc_index == tc_abort) { 466 if (task) {
464 failed_dev = task->dev; 467 failed_dev = task->dev;
465 sas_task_abort(task); 468 sas_task_abort(task);
466 break; 469 } else {
470 ASD_DPRINTK("R_T_A for non TASK scb 0x%x\n",
471 a->scb->header.opcode);
467 } 472 }
473 break;
468 } 474 }
469 475
470 if (!failed_dev) { 476 if (!failed_dev) {
@@ -478,7 +484,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
478 * that the EH will wake up and do something. 484 * that the EH will wake up and do something.
479 */ 485 */
480 list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { 486 list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
481 struct sas_task *task = ascb->uldd_task; 487 struct sas_task *task = a->uldd_task;
482 488
483 if (task && 489 if (task &&
484 task->dev == failed_dev && 490 task->dev == failed_dev &&