aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libsas/sas_ata.c87
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c14
2 files changed, 93 insertions, 8 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index c2a5cc75b407..16c5094bc86c 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -240,37 +240,43 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
240 return true; 240 return true;
241} 241}
242 242
243static void sas_ata_phy_reset(struct ata_port *ap) 243static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
244 unsigned long deadline)
244{ 245{
246 struct ata_port *ap = link->ap;
245 struct domain_device *dev = ap->private_data; 247 struct domain_device *dev = ap->private_data;
246 struct sas_internal *i = 248 struct sas_internal *i =
247 to_sas_internal(dev->port->ha->core.shost->transportt); 249 to_sas_internal(dev->port->ha->core.shost->transportt);
248 int res = TMF_RESP_FUNC_FAILED; 250 int res = TMF_RESP_FUNC_FAILED;
251 int ret = 0;
249 252
250 if (i->dft->lldd_I_T_nexus_reset) 253 if (i->dft->lldd_I_T_nexus_reset)
251 res = i->dft->lldd_I_T_nexus_reset(dev); 254 res = i->dft->lldd_I_T_nexus_reset(dev);
252 255
253 if (res != TMF_RESP_FUNC_COMPLETE) 256 if (res != TMF_RESP_FUNC_COMPLETE) {
254 SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__); 257 SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
258 ret = -EAGAIN;
259 }
255 260
256 switch (dev->sata_dev.command_set) { 261 switch (dev->sata_dev.command_set) {
257 case ATA_COMMAND_SET: 262 case ATA_COMMAND_SET:
258 SAS_DPRINTK("%s: Found ATA device.\n", __func__); 263 SAS_DPRINTK("%s: Found ATA device.\n", __func__);
259 ap->link.device[0].class = ATA_DEV_ATA; 264 *class = ATA_DEV_ATA;
260 break; 265 break;
261 case ATAPI_COMMAND_SET: 266 case ATAPI_COMMAND_SET:
262 SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); 267 SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
263 ap->link.device[0].class = ATA_DEV_ATAPI; 268 *class = ATA_DEV_ATAPI;
264 break; 269 break;
265 default: 270 default:
266 SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", 271 SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
267 __func__, 272 __func__,
268 dev->sata_dev.command_set); 273 dev->sata_dev.command_set);
269 ap->link.device[0].class = ATA_DEV_UNKNOWN; 274 *class = ATA_DEV_UNKNOWN;
270 break; 275 break;
271 } 276 }
272 277
273 ap->cbl = ATA_CBL_SATA; 278 ap->cbl = ATA_CBL_SATA;
279 return ret;
274} 280}
275 281
276static void sas_ata_post_internal(struct ata_queued_cmd *qc) 282static void sas_ata_post_internal(struct ata_queued_cmd *qc)
@@ -302,7 +308,11 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
302} 308}
303 309
304static struct ata_port_operations sas_sata_ops = { 310static struct ata_port_operations sas_sata_ops = {
305 .phy_reset = sas_ata_phy_reset, 311 .prereset = ata_std_prereset,
312 .softreset = NULL,
313 .hardreset = sas_ata_hard_reset,
314 .postreset = ata_std_postreset,
315 .error_handler = ata_std_error_handler,
306 .post_internal_cmd = sas_ata_post_internal, 316 .post_internal_cmd = sas_ata_post_internal,
307 .qc_defer = ata_std_qc_defer, 317 .qc_defer = ata_std_qc_defer,
308 .qc_prep = ata_noop_qc_prep, 318 .qc_prep = ata_noop_qc_prep,
@@ -732,3 +742,68 @@ int sas_discover_sata(struct domain_device *dev)
732 742
733 return res; 743 return res;
734} 744}
745
746void sas_ata_strategy_handler(struct Scsi_Host *shost)
747{
748 struct scsi_device *sdev;
749
750 shost_for_each_device(sdev, shost) {
751 struct domain_device *ddev = sdev_to_domain_dev(sdev);
752 struct ata_port *ap = ddev->sata_dev.ap;
753
754 if (!dev_is_sata(ddev))
755 continue;
756
757 ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
758 ata_scsi_port_error_handler(shost, ap);
759 }
760}
761
762int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
763 enum blk_eh_timer_return *rtn)
764{
765 struct domain_device *ddev = cmd_to_domain_dev(cmd);
766
767 if (!dev_is_sata(ddev) || task)
768 return 0;
769
770 /* we're a sata device with no task, so this must be a libata
771 * eh timeout. Ideally should hook into libata timeout
772 * handling, but there's no point, it just wants to activate
773 * the eh thread */
774 *rtn = BLK_EH_NOT_HANDLED;
775 return 1;
776}
777
778int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
779 struct list_head *done_q)
780{
781 int rtn = 0;
782 struct scsi_cmnd *cmd, *n;
783 struct ata_port *ap;
784
785 do {
786 LIST_HEAD(sata_q);
787
788 ap = NULL;
789
790 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
791 struct domain_device *ddev = cmd_to_domain_dev(cmd);
792
793 if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
794 continue;
795 if (ap && ap != ddev->sata_dev.ap)
796 continue;
797 ap = ddev->sata_dev.ap;
798 rtn = 1;
799 list_move(&cmd->eh_entry, &sata_q);
800 }
801
802 if (!list_empty(&sata_q)) {
803 ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n");
804 ata_scsi_cmd_error_handler(shost, ap, &sata_q);
805 }
806 } while (ap);
807
808 return rtn;
809}
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 5815cbeb27a6..2119871aed3e 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -662,11 +662,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
662 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any 662 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
663 * command we see here has no sas_task and is thus unknown to the HA. 663 * command we see here has no sas_task and is thus unknown to the HA.
664 */ 664 */
665 if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q)) 665 if (!sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q))
666 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); 666 if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
667 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
667 668
668out: 669out:
670 /* now link into libata eh --- if we have any ata devices */
671 sas_ata_strategy_handler(shost);
672
669 scsi_eh_flush_done_q(&ha->eh_done_q); 673 scsi_eh_flush_done_q(&ha->eh_done_q);
674
670 SAS_DPRINTK("--- Exit %s\n", __func__); 675 SAS_DPRINTK("--- Exit %s\n", __func__);
671 return; 676 return;
672} 677}
@@ -675,6 +680,11 @@ enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
675{ 680{
676 struct sas_task *task = TO_SAS_TASK(cmd); 681 struct sas_task *task = TO_SAS_TASK(cmd);
677 unsigned long flags; 682 unsigned long flags;
683 enum blk_eh_timer_return rtn;
684
685 if (sas_ata_timed_out(cmd, task, &rtn))
686 return rtn;
687
678 688
679 if (!task) { 689 if (!task) {
680 cmd->request->timeout /= 2; 690 cmd->request->timeout /= 2;