diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 86 |
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 | |||
706 | static 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 | |||
741 | void 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 | |||
766 | void 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 | /** |