|
@@ -5351,22 +5351,17 @@ bool ata_link_offline(struct ata_link *link)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
-static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
|
|
- unsigned int action, unsigned int ehi_flags,
|
|
|
- int *async)
|
|
|
+static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
|
|
+ unsigned int action, unsigned int ehi_flags,
|
|
|
+ bool async)
|
|
|
{
|
|
|
struct ata_link *link;
|
|
|
unsigned long flags;
|
|
|
- int rc = 0;
|
|
|
|
|
|
/* Previous resume operation might still be in
|
|
|
* progress. Wait for PM_PENDING to clear.
|
|
|
*/
|
|
|
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
|
|
|
- if (async) {
|
|
|
- *async = -EAGAIN;
|
|
|
- return 0;
|
|
|
- }
|
|
|
ata_port_wait_eh(ap);
|
|
|
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
|
|
}
|
|
@@ -5375,11 +5370,6 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
|
|
spin_lock_irqsave(ap->lock, flags);
|
|
|
|
|
|
ap->pm_mesg = mesg;
|
|
|
- if (async)
|
|
|
- ap->pm_result = async;
|
|
|
- else
|
|
|
- ap->pm_result = &rc;
|
|
|
-
|
|
|
ap->pflags |= ATA_PFLAG_PM_PENDING;
|
|
|
ata_for_each_link(link, ap, HOST_FIRST) {
|
|
|
link->eh_info.action |= action;
|
|
@@ -5390,87 +5380,81 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
|
|
|
|
|
spin_unlock_irqrestore(ap->lock, flags);
|
|
|
|
|
|
- /* wait and check result */
|
|
|
if (!async) {
|
|
|
ata_port_wait_eh(ap);
|
|
|
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
|
|
}
|
|
|
-
|
|
|
- return rc;
|
|
|
}
|
|
|
|
|
|
-static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int *async)
|
|
|
+/*
|
|
|
+ * On some hardware, device fails to respond after spun down for suspend. As
|
|
|
+ * the device won't be used before being resumed, we don't need to touch the
|
|
|
+ * device. Ask EH to skip the usual stuff and proceed directly to suspend.
|
|
|
+ *
|
|
|
+ * http://thread.gmane.org/gmane.linux.ide/46764
|
|
|
+ */
|
|
|
+static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
|
|
|
+ | ATA_EHI_NO_AUTOPSY
|
|
|
+ | ATA_EHI_NO_RECOVERY;
|
|
|
+
|
|
|
+static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
|
|
{
|
|
|
- /*
|
|
|
- * On some hardware, device fails to respond after spun down
|
|
|
- * for suspend. As the device won't be used before being
|
|
|
- * resumed, we don't need to touch the device. Ask EH to skip
|
|
|
- * the usual stuff and proceed directly to suspend.
|
|
|
- *
|
|
|
- * http://thread.gmane.org/gmane.linux.ide/46764
|
|
|
- */
|
|
|
- unsigned int ehi_flags = ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY |
|
|
|
- ATA_EHI_NO_RECOVERY;
|
|
|
- return ata_port_request_pm(ap, mesg, 0, ehi_flags, async);
|
|
|
+ ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
|
|
|
}
|
|
|
|
|
|
-static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
|
|
|
+static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
|
|
|
{
|
|
|
- struct ata_port *ap = to_ata_port(dev);
|
|
|
-
|
|
|
- return __ata_port_suspend_common(ap, mesg, NULL);
|
|
|
+ ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
|
|
|
}
|
|
|
|
|
|
-static int ata_port_suspend(struct device *dev)
|
|
|
+static int ata_port_pm_suspend(struct device *dev)
|
|
|
{
|
|
|
+ struct ata_port *ap = to_ata_port(dev);
|
|
|
+
|
|
|
if (pm_runtime_suspended(dev))
|
|
|
return 0;
|
|
|
|
|
|
- return ata_port_suspend_common(dev, PMSG_SUSPEND);
|
|
|
+ ata_port_suspend(ap, PMSG_SUSPEND);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static int ata_port_do_freeze(struct device *dev)
|
|
|
+static int ata_port_pm_freeze(struct device *dev)
|
|
|
{
|
|
|
+ struct ata_port *ap = to_ata_port(dev);
|
|
|
+
|
|
|
if (pm_runtime_suspended(dev))
|
|
|
return 0;
|
|
|
|
|
|
- return ata_port_suspend_common(dev, PMSG_FREEZE);
|
|
|
+ ata_port_suspend(ap, PMSG_FREEZE);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static int ata_port_poweroff(struct device *dev)
|
|
|
+static int ata_port_pm_poweroff(struct device *dev)
|
|
|
{
|
|
|
- return ata_port_suspend_common(dev, PMSG_HIBERNATE);
|
|
|
+ ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg,
|
|
|
- int *async)
|
|
|
-{
|
|
|
- int rc;
|
|
|
+static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
|
|
|
+ | ATA_EHI_QUIET;
|
|
|
|
|
|
- rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET,
|
|
|
- ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async);
|
|
|
- return rc;
|
|
|
+static void ata_port_resume(struct ata_port *ap, pm_message_t mesg)
|
|
|
+{
|
|
|
+ ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false);
|
|
|
}
|
|
|
|
|
|
-static int ata_port_resume_common(struct device *dev, pm_message_t mesg)
|
|
|
+static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg)
|
|
|
{
|
|
|
- struct ata_port *ap = to_ata_port(dev);
|
|
|
-
|
|
|
- return __ata_port_resume_common(ap, mesg, NULL);
|
|
|
+ ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true);
|
|
|
}
|
|
|
|
|
|
-static int ata_port_resume(struct device *dev)
|
|
|
+static int ata_port_pm_resume(struct device *dev)
|
|
|
{
|
|
|
- int rc;
|
|
|
-
|
|
|
- rc = ata_port_resume_common(dev, PMSG_RESUME);
|
|
|
- if (!rc) {
|
|
|
- pm_runtime_disable(dev);
|
|
|
- pm_runtime_set_active(dev);
|
|
|
- pm_runtime_enable(dev);
|
|
|
- }
|
|
|
-
|
|
|
- return rc;
|
|
|
+ ata_port_resume(to_ata_port(dev), PMSG_RESUME);
|
|
|
+ pm_runtime_disable(dev);
|
|
|
+ pm_runtime_set_active(dev);
|
|
|
+ pm_runtime_enable(dev);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5499,21 +5483,23 @@ static int ata_port_runtime_idle(struct device *dev)
|
|
|
|
|
|
static int ata_port_runtime_suspend(struct device *dev)
|
|
|
{
|
|
|
- return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND);
|
|
|
+ ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int ata_port_runtime_resume(struct device *dev)
|
|
|
{
|
|
|
- return ata_port_resume_common(dev, PMSG_AUTO_RESUME);
|
|
|
+ ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static const struct dev_pm_ops ata_port_pm_ops = {
|
|
|
- .suspend = ata_port_suspend,
|
|
|
- .resume = ata_port_resume,
|
|
|
- .freeze = ata_port_do_freeze,
|
|
|
- .thaw = ata_port_resume,
|
|
|
- .poweroff = ata_port_poweroff,
|
|
|
- .restore = ata_port_resume,
|
|
|
+ .suspend = ata_port_pm_suspend,
|
|
|
+ .resume = ata_port_pm_resume,
|
|
|
+ .freeze = ata_port_pm_freeze,
|
|
|
+ .thaw = ata_port_pm_resume,
|
|
|
+ .poweroff = ata_port_pm_poweroff,
|
|
|
+ .restore = ata_port_pm_resume,
|
|
|
|
|
|
.runtime_suspend = ata_port_runtime_suspend,
|
|
|
.runtime_resume = ata_port_runtime_resume,
|
|
@@ -5525,18 +5511,17 @@ static const struct dev_pm_ops ata_port_pm_ops = {
|
|
|
* level. sas suspend/resume is async to allow parallel port recovery
|
|
|
* since sas has multiple ata_port instances per Scsi_Host.
|
|
|
*/
|
|
|
-int ata_sas_port_async_suspend(struct ata_port *ap, int *async)
|
|
|
+void ata_sas_port_suspend(struct ata_port *ap)
|
|
|
{
|
|
|
- return __ata_port_suspend_common(ap, PMSG_SUSPEND, async);
|
|
|
+ ata_port_suspend_async(ap, PMSG_SUSPEND);
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend);
|
|
|
+EXPORT_SYMBOL_GPL(ata_sas_port_suspend);
|
|
|
|
|
|
-int ata_sas_port_async_resume(struct ata_port *ap, int *async)
|
|
|
+void ata_sas_port_resume(struct ata_port *ap)
|
|
|
{
|
|
|
- return __ata_port_resume_common(ap, PMSG_RESUME, async);
|
|
|
+ ata_port_resume_async(ap, PMSG_RESUME);
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(ata_sas_port_async_resume);
|
|
|
-
|
|
|
+EXPORT_SYMBOL_GPL(ata_sas_port_resume);
|
|
|
|
|
|
/**
|
|
|
* ata_host_suspend - suspend host
|