aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r--drivers/scsi/libsas/sas_ata.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index a59fcdc8fd63..905ae45133fc 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -700,6 +700,92 @@ void sas_probe_sata(struct asd_sas_port *port)
700 if (ata_dev_disabled(sas_to_ata_dev(dev))) 700 if (ata_dev_disabled(sas_to_ata_dev(dev)))
701 sas_fail_probe(dev, __func__, -ENODEV); 701 sas_fail_probe(dev, __func__, -ENODEV);
702 } 702 }
703
704}
705
706static bool sas_ata_flush_pm_eh(struct asd_sas_port *port, const char *func)
707{
708 struct domain_device *dev, *n;
709 bool retry = false;
710
711 list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) {
712 int rc;
713
714 if (!dev_is_sata(dev))
715 continue;
716
717 sas_ata_wait_eh(dev);
718 rc = dev->sata_dev.pm_result;
719 if (rc == -EAGAIN)
720 retry = true;
721 else if (rc) {
722 /* since we don't have a
723 * ->port_{suspend|resume} routine in our
724 * ata_port ops, and no entanglements with
725 * acpi, suspend should just be mechanical trip
726 * through eh, catch cases where these
727 * assumptions are invalidated
728 */
729 WARN_ONCE(1, "failed %s %s error: %d\n", func,
730 dev_name(&dev->rphy->dev), rc);
731 }
732
733 /* if libata failed to power manage the device, tear it down */
734 if (ata_dev_disabled(sas_to_ata_dev(dev)))
735 sas_fail_probe(dev, func, -ENODEV);
736 }
737
738 return retry;
739}
740
741void sas_suspend_sata(struct asd_sas_port *port)
742{
743 struct domain_device *dev;
744
745 retry:
746 mutex_lock(&port->ha->disco_mutex);
747 list_for_each_entry(dev, &port->dev_list, dev_list_node) {
748 struct sata_device *sata;
749
750 if (!dev_is_sata(dev))
751 continue;
752
753 sata = &dev->sata_dev;
754 if (sata->ap->pm_mesg.event == PM_EVENT_SUSPEND)
755 continue;
756
757 sata->pm_result = -EIO;
758 ata_sas_port_async_suspend(sata->ap, &sata->pm_result);
759 }
760 mutex_unlock(&port->ha->disco_mutex);
761
762 if (sas_ata_flush_pm_eh(port, __func__))
763 goto retry;
764}
765
766void sas_resume_sata(struct asd_sas_port *port)
767{
768 struct domain_device *dev;
769
770 retry:
771 mutex_lock(&port->ha->disco_mutex);
772 list_for_each_entry(dev, &port->dev_list, dev_list_node) {
773 struct sata_device *sata;
774
775 if (!dev_is_sata(dev))
776 continue;
777
778 sata = &dev->sata_dev;
779 if (sata->ap->pm_mesg.event == PM_EVENT_ON)
780 continue;
781
782 sata->pm_result = -EIO;
783 ata_sas_port_async_resume(sata->ap, &sata->pm_result);
784 }
785 mutex_unlock(&port->ha->disco_mutex);
786
787 if (sas_ata_flush_pm_eh(port, __func__))
788 goto retry;
703} 789}
704 790
705/** 791/**