]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ACPI: PM: Simplify and fix PM domain hibernation callbacks
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 1 Jul 2019 10:54:10 +0000 (12:54 +0200)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 14 Feb 2020 05:29:37 +0000 (00:29 -0500)
BugLink: https://bugs.launchpad.net/bugs/1863019
[ Upstream commit 3cd7957e85e67120bb9f6bfb75d81dcc19af282b ]

First, after a previous change causing all runtime-suspended devices
in the ACPI PM domain (and ACPI LPSS devices) to be resumed before
creating a snapshot image of memory during hibernation, it is not
necessary to worry about the case in which them might be left in
runtime-suspend any more, so get rid of the code related to that from
ACPI PM domain and ACPI LPSS hibernation callbacks.

Second, it is not correct to use pm_generic_resume_early() and
acpi_subsys_resume_noirq() in hibernation "restore" callbacks (which
currently happens in the ACPI PM domain and ACPI LPSS), so introduce
proper _restore_late and _restore_noirq callbacks for the ACPI PM
domain and ACPI LPSS.

Fixes: 05087360fd7a (ACPI / PM: Take SMART_SUSPEND driver flag into account)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/acpi/acpi_lpss.c
drivers/acpi/device_pm.c
include/linux/acpi.h

index a37ee41d8cdcaa9d495c2aba2fb92da457cbbbf2..86e81850c122c4a9752b713488749187df73ec41 100644 (file)
@@ -942,16 +942,62 @@ static int acpi_lpss_resume_noirq(struct device *dev)
        struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
        int ret;
 
-       ret = acpi_subsys_resume_noirq(dev);
+       /* Follow acpi_subsys_resume_noirq(). */
+       if (dev_pm_may_skip_resume(dev))
+               return 0;
+
+       if (dev_pm_smart_suspend_and_suspended(dev))
+               pm_runtime_set_active(dev);
+
+       ret = pm_generic_resume_noirq(dev);
        if (ret)
                return ret;
 
-       if (!dev_pm_may_skip_resume(dev) && pdata->dev_desc->resume_from_noirq)
-               ret = acpi_lpss_do_resume_early(dev);
+       if (!pdata->dev_desc->resume_from_noirq)
+               return 0;
 
-       return ret;
+       /*
+        * The driver's ->resume_early callback will be invoked by
+        * acpi_lpss_do_resume_early(), with the assumption that the driver
+        * really wanted to run that code in ->resume_noirq, but it could not
+        * run before acpi_dev_resume() and the driver expected the latter to be
+        * called in the "early" phase.
+        */
+       return acpi_lpss_do_resume_early(dev);
+}
+
+static int acpi_lpss_do_restore_early(struct device *dev)
+{
+       int ret = acpi_lpss_resume(dev);
+
+       return ret ? ret : pm_generic_restore_early(dev);
+}
+
+static int acpi_lpss_restore_early(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+
+       if (pdata->dev_desc->resume_from_noirq)
+               return 0;
+
+       return acpi_lpss_do_restore_early(dev);
 }
 
+static int acpi_lpss_restore_noirq(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+       int ret;
+
+       ret = pm_generic_restore_noirq(dev);
+       if (ret)
+               return ret;
+
+       if (!pdata->dev_desc->resume_from_noirq)
+               return 0;
+
+       /* This is analogous to what happens in acpi_lpss_resume_noirq(). */
+       return acpi_lpss_do_restore_early(dev);
+}
 #endif /* CONFIG_PM_SLEEP */
 
 static int acpi_lpss_runtime_suspend(struct device *dev)
@@ -985,14 +1031,11 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
                .resume_noirq = acpi_lpss_resume_noirq,
                .resume_early = acpi_lpss_resume_early,
                .freeze = acpi_subsys_freeze,
-               .freeze_late = acpi_subsys_freeze_late,
-               .freeze_noirq = acpi_subsys_freeze_noirq,
-               .thaw_noirq = acpi_subsys_thaw_noirq,
                .poweroff = acpi_subsys_suspend,
                .poweroff_late = acpi_lpss_suspend_late,
                .poweroff_noirq = acpi_lpss_suspend_noirq,
-               .restore_noirq = acpi_lpss_resume_noirq,
-               .restore_early = acpi_lpss_resume_early,
+               .restore_noirq = acpi_lpss_restore_noirq,
+               .restore_early = acpi_lpss_restore_early,
 #endif
                .runtime_suspend = acpi_lpss_runtime_suspend,
                .runtime_resume = acpi_lpss_runtime_resume,
index fae6c6f361474568a89598033e2e9e56504b182e..39f616d65ec734391b54403152d57074ee764031 100644 (file)
@@ -1059,7 +1059,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq);
  * acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback.
  * @dev: Device to handle.
  */
-int acpi_subsys_resume_noirq(struct device *dev)
+static int acpi_subsys_resume_noirq(struct device *dev)
 {
        /*
         * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend
@@ -1071,7 +1071,6 @@ int acpi_subsys_resume_noirq(struct device *dev)
 
        return pm_generic_resume_noirq(dev);
 }
-EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);
 
 /**
  * acpi_subsys_resume_early - Resume device using ACPI.
@@ -1081,12 +1080,11 @@ EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);
  * generic early resume procedure for it during system transition into the
  * working state.
  */
-int acpi_subsys_resume_early(struct device *dev)
+static int acpi_subsys_resume_early(struct device *dev)
 {
        int ret = acpi_dev_resume(dev);
        return ret ? ret : pm_generic_resume_early(dev);
 }
-EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);
 
 /**
  * acpi_subsys_freeze - Run the device driver's freeze callback.
@@ -1109,52 +1107,15 @@ int acpi_subsys_freeze(struct device *dev)
 EXPORT_SYMBOL_GPL(acpi_subsys_freeze);
 
 /**
- * acpi_subsys_freeze_late - Run the device driver's "late" freeze callback.
- * @dev: Device to handle.
- */
-int acpi_subsys_freeze_late(struct device *dev)
-{
-
-       if (dev_pm_smart_suspend_and_suspended(dev))
-               return 0;
-
-       return pm_generic_freeze_late(dev);
-}
-EXPORT_SYMBOL_GPL(acpi_subsys_freeze_late);
-
-/**
- * acpi_subsys_freeze_noirq - Run the device driver's "noirq" freeze callback.
- * @dev: Device to handle.
+ * acpi_subsys_restore_early - Restore device using ACPI.
+ * @dev: Device to restore.
  */
-int acpi_subsys_freeze_noirq(struct device *dev)
+int acpi_subsys_restore_early(struct device *dev)
 {
-
-       if (dev_pm_smart_suspend_and_suspended(dev))
-               return 0;
-
-       return pm_generic_freeze_noirq(dev);
-}
-EXPORT_SYMBOL_GPL(acpi_subsys_freeze_noirq);
-
-/**
- * acpi_subsys_thaw_noirq - Run the device driver's "noirq" thaw callback.
- * @dev: Device to handle.
- */
-int acpi_subsys_thaw_noirq(struct device *dev)
-{
-       /*
-        * If the device is in runtime suspend, the "thaw" code may not work
-        * correctly with it, so skip the driver callback and make the PM core
-        * skip all of the subsequent "thaw" callbacks for the device.
-        */
-       if (dev_pm_smart_suspend_and_suspended(dev)) {
-               dev_pm_skip_next_resume_phases(dev);
-               return 0;
-       }
-
-       return pm_generic_thaw_noirq(dev);
+       int ret = acpi_dev_resume(dev);
+       return ret ? ret : pm_generic_restore_early(dev);
 }
-EXPORT_SYMBOL_GPL(acpi_subsys_thaw_noirq);
+EXPORT_SYMBOL_GPL(acpi_subsys_restore_early);
 #endif /* CONFIG_PM_SLEEP */
 
 static struct dev_pm_domain acpi_general_pm_domain = {
@@ -1170,14 +1131,10 @@ static struct dev_pm_domain acpi_general_pm_domain = {
                .resume_noirq = acpi_subsys_resume_noirq,
                .resume_early = acpi_subsys_resume_early,
                .freeze = acpi_subsys_freeze,
-               .freeze_late = acpi_subsys_freeze_late,
-               .freeze_noirq = acpi_subsys_freeze_noirq,
-               .thaw_noirq = acpi_subsys_thaw_noirq,
                .poweroff = acpi_subsys_suspend,
                .poweroff_late = acpi_subsys_suspend_late,
                .poweroff_noirq = acpi_subsys_suspend_noirq,
-               .restore_noirq = acpi_subsys_resume_noirq,
-               .restore_early = acpi_subsys_resume_early,
+               .restore_early = acpi_subsys_restore_early,
 #endif
        },
 };
index a972067832e99bb7c298ae965ee2cda656fab127..a6f208a44da889c63920517acd4416b5ea4935c9 100644 (file)
@@ -892,26 +892,16 @@ int acpi_subsys_prepare(struct device *dev);
 void acpi_subsys_complete(struct device *dev);
 int acpi_subsys_suspend_late(struct device *dev);
 int acpi_subsys_suspend_noirq(struct device *dev);
-int acpi_subsys_resume_noirq(struct device *dev);
-int acpi_subsys_resume_early(struct device *dev);
 int acpi_subsys_suspend(struct device *dev);
 int acpi_subsys_freeze(struct device *dev);
-int acpi_subsys_freeze_late(struct device *dev);
-int acpi_subsys_freeze_noirq(struct device *dev);
-int acpi_subsys_thaw_noirq(struct device *dev);
 #else
 static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
 static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
 static inline void acpi_subsys_complete(struct device *dev) {}
 static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
 static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; }
-static inline int acpi_subsys_resume_noirq(struct device *dev) { return 0; }
-static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
 static inline int acpi_subsys_suspend(struct device *dev) { return 0; }
 static inline int acpi_subsys_freeze(struct device *dev) { return 0; }
-static inline int acpi_subsys_freeze_late(struct device *dev) { return 0; }
-static inline int acpi_subsys_freeze_noirq(struct device *dev) { return 0; }
-static inline int acpi_subsys_thaw_noirq(struct device *dev) { return 0; }
 #endif
 
 #ifdef CONFIG_ACPI