aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libsas/sas_ata.c87
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c14
-rw-r--r--include/scsi/sas_ata.h22
3 files changed, 115 insertions, 8 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index e1a395b438ee..8f56d5fbf6ec 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -238,37 +238,43 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
238 return true; 238 return true;
239} 239}
240 240
241static void sas_ata_phy_reset(struct ata_port *ap) 241static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
242 unsigned long deadline)
242{ 243{
244 struct ata_port *ap = link->ap;
243 struct domain_device *dev = ap->private_data; 245 struct domain_device *dev = ap->private_data;
244 struct sas_internal *i = 246 struct sas_internal *i =
245 to_sas_internal(dev->port->ha->core.shost->transportt); 247 to_sas_internal(dev->port->ha->core.shost->transportt);
246 int res = TMF_RESP_FUNC_FAILED; 248 int res = TMF_RESP_FUNC_FAILED;
249 int ret = 0;
247 250
248 if (i->dft->lldd_I_T_nexus_reset) 251 if (i->dft->lldd_I_T_nexus_reset)
249 res = i->dft->lldd_I_T_nexus_reset(dev); 252 res = i->dft->lldd_I_T_nexus_reset(dev);
250 253
251 if (res != TMF_RESP_FUNC_COMPLETE) 254 if (res != TMF_RESP_FUNC_COMPLETE) {
252 SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__); 255 SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
256 ret = -EAGAIN;
257 }
253 258
254 switch (dev->sata_dev.command_set) { 259 switch (dev->sata_dev.command_set) {
255 case ATA_COMMAND_SET: 260 case ATA_COMMAND_SET:
256 SAS_DPRINTK("%s: Found ATA device.\n", __func__); 261 SAS_DPRINTK("%s: Found ATA device.\n", __func__);
257 ap->link.device[0].class = ATA_DEV_ATA; 262 *class = ATA_DEV_ATA;
258 break; 263 break;
259 case ATAPI_COMMAND_SET: 264 case ATAPI_COMMAND_SET:
260 SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); 265 SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
261 ap->link.device[0].class = ATA_DEV_ATAPI; 266 *class = ATA_DEV_ATAPI;
262 break; 267 break;
263 default: 268 default:
264 SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", 269 SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
265 __func__, 270 __func__,
266 dev->sata_dev.command_set); 271 dev->sata_dev.command_set);
267 ap->link.device[0].class = ATA_DEV_UNKNOWN; 272 *class = ATA_DEV_UNKNOWN;
268 break; 273 break;
269 } 274 }
270 275
271 ap->cbl = ATA_CBL_SATA; 276 ap->cbl = ATA_CBL_SATA;
277 return ret;
272} 278}
273 279
274static void sas_ata_post_internal(struct ata_queued_cmd *qc) 280static void sas_ata_post_internal(struct ata_queued_cmd *qc)
@@ -349,7 +355,11 @@ static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in,
349} 355}
350 356
351static struct ata_port_operations sas_sata_ops = { 357static struct ata_port_operations sas_sata_ops = {
352 .phy_reset = sas_ata_phy_reset, 358 .prereset = ata_std_prereset,
359 .softreset = NULL,
360 .hardreset = sas_ata_hard_reset,
361 .postreset = ata_std_postreset,
362 .error_handler = ata_std_error_handler,
353 .post_internal_cmd = sas_ata_post_internal, 363 .post_internal_cmd = sas_ata_post_internal,
354 .qc_defer = ata_std_qc_defer, 364 .qc_defer = ata_std_qc_defer,
355 .qc_prep = ata_noop_qc_prep, 365 .qc_prep = ata_noop_qc_prep,
@@ -781,3 +791,68 @@ int sas_discover_sata(struct domain_device *dev)
781 791
782 return res; 792 return res;
783} 793}
794
795void sas_ata_strategy_handler(struct Scsi_Host *shost)
796{
797 struct scsi_device *sdev;
798
799 shost_for_each_device(sdev, shost) {
800 struct domain_device *ddev = sdev_to_domain_dev(sdev);
801 struct ata_port *ap = ddev->sata_dev.ap;
802
803 if (!dev_is_sata(ddev))
804 continue;
805
806 ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
807 ata_scsi_port_error_handler(shost, ap);
808 }
809}
810
811int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
812 enum blk_eh_timer_return *rtn)
813{
814 struct domain_device *ddev = cmd_to_domain_dev(cmd);
815
816 if (!dev_is_sata(ddev) || task)
817 return 0;
818
819 /* we're a sata device with no task, so this must be a libata
820 * eh timeout. Ideally should hook into libata timeout
821 * handling, but there's no point, it just wants to activate
822 * the eh thread */
823 *rtn = BLK_EH_NOT_HANDLED;
824 return 1;
825}
826
827int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
828 struct list_head *done_q)
829{
830 int rtn = 0;
831 struct scsi_cmnd *cmd, *n;
832 struct ata_port *ap;
833
834 do {
835 LIST_HEAD(sata_q);
836
837 ap = NULL;
838
839 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
840 struct domain_device *ddev = cmd_to_domain_dev(cmd);
841
842 if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
843 continue;
844 if(ap && ap != ddev->sata_dev.ap)
845 continue;
846 ap = ddev->sata_dev.ap;
847 rtn = 1;
848 list_move(&cmd->eh_entry, &sata_q);
849 }
850
851 if (!list_empty(&sata_q)) {
852 ata_port_printk(ap, KERN_DEBUG,"sas eh calling libata cmd error handler\n");
853 ata_scsi_cmd_error_handler(shost, ap, &sata_q);
854 }
855 } while (ap);
856
857 return rtn;
858}
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 9a7aaf5f1311..67758ea8eb7f 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -663,11 +663,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
663 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any 663 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
664 * command we see here has no sas_task and is thus unknown to the HA. 664 * command we see here has no sas_task and is thus unknown to the HA.
665 */ 665 */
666 if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q)) 666 if (!sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q))
667 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); 667 if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
668 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
668 669
669out: 670out:
671 /* now link into libata eh --- if we have any ata devices */
672 sas_ata_strategy_handler(shost);
673
670 scsi_eh_flush_done_q(&ha->eh_done_q); 674 scsi_eh_flush_done_q(&ha->eh_done_q);
675
671 SAS_DPRINTK("--- Exit %s\n", __func__); 676 SAS_DPRINTK("--- Exit %s\n", __func__);
672 return; 677 return;
673} 678}
@@ -676,6 +681,11 @@ enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
676{ 681{
677 struct sas_task *task = TO_SAS_TASK(cmd); 682 struct sas_task *task = TO_SAS_TASK(cmd);
678 unsigned long flags; 683 unsigned long flags;
684 enum blk_eh_timer_return rtn;
685
686 if (sas_ata_timed_out(cmd, task, &rtn))
687 return rtn;
688
679 689
680 if (!task) { 690 if (!task) {
681 cmd->request->timeout /= 2; 691 cmd->request->timeout /= 2;
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index c583193ae929..9c159f74c6d0 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -39,6 +39,11 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
39 struct scsi_target *starget); 39 struct scsi_target *starget);
40 40
41void sas_ata_task_abort(struct sas_task *task); 41void sas_ata_task_abort(struct sas_task *task);
42void sas_ata_strategy_handler(struct Scsi_Host *shost);
43int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
44 enum blk_eh_timer_return *rtn);
45int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
46 struct list_head *done_q);
42 47
43#else 48#else
44 49
@@ -55,6 +60,23 @@ static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
55static inline void sas_ata_task_abort(struct sas_task *task) 60static inline void sas_ata_task_abort(struct sas_task *task)
56{ 61{
57} 62}
63
64static inline void sas_ata_strategy_handler(struct Scsi_Host *shost)
65{
66}
67
68static inline int sas_ata_timed_out(struct scsi_cmnd *cmd,
69 struct sas_task *task,
70 enum blk_eh_timer_return *rtn)
71{
72 return 0;
73}
74static inline int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
75 struct list_head *done_q)
76{
77 return 0;
78}
79
58#endif 80#endif
59 81
60#endif /* _SAS_ATA_H_ */ 82#endif /* _SAS_ATA_H_ */