aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-29 15:08:50 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 15:07:15 -0500
commit3944f50995f947558c35fb16ae0288354756762c (patch)
tree59100b5e0a6aaef675bab78a31838356a3554a95
parent9095a64a9aead653df320e3a6fc70835c15d46e4 (diff)
[SCSI] libsas: let libata handle command timeouts
libsas-eh if it successfully aborts an ata command will hide the timeout condition (AC_ERR_TIMEOUT) from libata. The command likely completes with the all-zero task->task_status it started with. Instead, interpret a TMF_RESP_FUNC_COMPLETE as the end of the sas_task but keep the scmd around for libata-eh to handle. Tested-by: Andrzej Jakowski <andrzej.jakowski@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/libsas/sas_init.c1
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c22
-rw-r--r--include/scsi/libsas.h3
3 files changed, 23 insertions, 3 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 52cd11d76664..e17fe35af30c 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -146,6 +146,7 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
146 } 146 }
147 147
148 INIT_LIST_HEAD(&sas_ha->eh_done_q); 148 INIT_LIST_HEAD(&sas_ha->eh_done_q);
149 INIT_LIST_HEAD(&sas_ha->eh_ata_q);
149 150
150 return 0; 151 return 0;
151 152
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 0e3fdba7b510..e02ca3d570f5 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -265,6 +265,22 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
265 scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); 265 scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
266} 266}
267 267
268static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
269{
270 struct sas_task *task = TO_SAS_TASK(cmd);
271 struct domain_device *dev = task->dev;
272 struct sas_ha_struct *ha = dev->port->ha;
273
274 if (!dev_is_sata(dev)) {
275 sas_eh_finish_cmd(cmd);
276 return;
277 }
278
279 /* report the timeout to libata */
280 sas_end_task(cmd, task);
281 list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
282}
283
268static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) 284static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
269{ 285{
270 struct scsi_cmnd *cmd, *n; 286 struct scsi_cmnd *cmd, *n;
@@ -562,12 +578,12 @@ Again:
562 case TASK_IS_DONE: 578 case TASK_IS_DONE:
563 SAS_DPRINTK("%s: task 0x%p is done\n", __func__, 579 SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
564 task); 580 task);
565 sas_eh_finish_cmd(cmd); 581 sas_eh_defer_cmd(cmd);
566 continue; 582 continue;
567 case TASK_IS_ABORTED: 583 case TASK_IS_ABORTED:
568 SAS_DPRINTK("%s: task 0x%p is aborted\n", 584 SAS_DPRINTK("%s: task 0x%p is aborted\n",
569 __func__, task); 585 __func__, task);
570 sas_eh_finish_cmd(cmd); 586 sas_eh_defer_cmd(cmd);
571 continue; 587 continue;
572 case TASK_IS_AT_LU: 588 case TASK_IS_AT_LU:
573 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); 589 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -635,12 +651,14 @@ Again:
635 goto clear_q; 651 goto clear_q;
636 } 652 }
637 } 653 }
654 list_splice_tail_init(&ha->eh_ata_q, work_q);
638 return list_empty(work_q); 655 return list_empty(work_q);
639clear_q: 656clear_q:
640 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__); 657 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__);
641 list_for_each_entry_safe(cmd, n, work_q, eh_entry) 658 list_for_each_entry_safe(cmd, n, work_q, eh_entry)
642 sas_eh_finish_cmd(cmd); 659 sas_eh_finish_cmd(cmd);
643 660
661 list_splice_tail_init(&ha->eh_ata_q, work_q);
644 return list_empty(work_q); 662 return list_empty(work_q);
645} 663}
646 664
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index aa7192ff4355..6b80310e08af 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -382,7 +382,8 @@ struct sas_ha_struct {
382 382
383 void *lldd_ha; /* not touched by sas class code */ 383 void *lldd_ha; /* not touched by sas class code */
384 384
385 struct list_head eh_done_q; 385 struct list_head eh_done_q; /* complete via scsi_eh_flush_done_q */
386 struct list_head eh_ata_q; /* scmds to promote from sas to ata eh */
386}; 387};
387 388
388#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) 389#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata)