]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PM: sleep: Avoid unnecessary checks in device_prepare_smart_suspend()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 18 Feb 2025 20:20:46 +0000 (21:20 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 3 Mar 2025 12:29:00 +0000 (13:29 +0100)
Add an optimization (on top of previous changes) to avoid calling
pm_runtime_blocked(), which involves acquiring the device's PM spinlock,
for devices with no PM callbacks and runtime PM "blocked".

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://patch.msgid.link/2978873.e9J7NaK4W3@rjwysocki.net
drivers/base/power/main.c
drivers/base/power/runtime.c
include/linux/pm_runtime.h

index cc9903065900d108bbc6860fb48dbc20bd2b78dc..a06ef91fbdb935c4faf096a280e5deaa5ffb8e18 100644 (file)
@@ -1796,16 +1796,14 @@ static void device_prepare_smart_suspend(struct device *dev)
 
        /*
         * The "smart suspend" feature is enabled for devices whose drivers ask
-        * for it and for devices without PM callbacks unless runtime PM is
-        * disabled and enabling it is blocked for them.
+        * for it and for devices without PM callbacks.
         *
         * However, if "smart suspend" is not enabled for the device's parent
         * or any of its suppliers that take runtime PM into account, it cannot
         * be enabled for the device either.
         */
-       dev->power.smart_suspend = (dev->power.no_pm_callbacks ||
-               dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) &&
-               !pm_runtime_blocked(dev);
+       dev->power.smart_suspend = dev->power.no_pm_callbacks ||
+               dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND);
 
        if (!dev_pm_smart_suspend(dev))
                return;
@@ -1843,6 +1841,7 @@ static void device_prepare_smart_suspend(struct device *dev)
 static int device_prepare(struct device *dev, pm_message_t state)
 {
        int (*callback)(struct device *) = NULL;
+       bool no_runtime_pm;
        int ret = 0;
 
        /*
@@ -1858,7 +1857,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
         * suspend-resume cycle is complete, so prepare to trigger a warning on
         * subsequent attempts to enable it.
         */
-       pm_runtime_block_if_disabled(dev);
+       no_runtime_pm = pm_runtime_block_if_disabled(dev);
 
        if (dev->power.syscore)
                return 0;
@@ -1893,7 +1892,10 @@ unlock:
                pm_runtime_put(dev);
                return ret;
        }
-       device_prepare_smart_suspend(dev);
+       /* Do not enable "smart suspend" for devices without runtime PM. */
+       if (!no_runtime_pm)
+               device_prepare_smart_suspend(dev);
+
        /*
         * A positive return value from ->prepare() means "this device appears
         * to be runtime-suspended and its state is fine, so if it really is
index c0f5a9f892997e4d766312bb8fb6375fc2e4edee..e772e45d30f3156551c3cff19ddc9e3e08a514f5 100644 (file)
@@ -1460,14 +1460,19 @@ int pm_runtime_barrier(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(pm_runtime_barrier);
 
-void pm_runtime_block_if_disabled(struct device *dev)
+bool pm_runtime_block_if_disabled(struct device *dev)
 {
+       bool ret;
+
        spin_lock_irq(&dev->power.lock);
 
-       if (dev->power.disable_depth && dev->power.last_status == RPM_INVALID)
+       ret = dev->power.disable_depth && dev->power.last_status == RPM_INVALID;
+       if (ret)
                dev->power.last_status = RPM_BLOCKED;
 
        spin_unlock_irq(&dev->power.lock);
+
+       return ret;
 }
 
 void pm_runtime_unblock(struct device *dev)
index aea0395c10a14100adba81632a4a8233b014b893..01ead602aedd30634f3b6fcfdd40779be63b07f4 100644 (file)
@@ -77,7 +77,7 @@ extern int pm_runtime_get_if_in_use(struct device *dev);
 extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
 extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
 extern int pm_runtime_barrier(struct device *dev);
-extern void pm_runtime_block_if_disabled(struct device *dev);
+extern bool pm_runtime_block_if_disabled(struct device *dev);
 extern void pm_runtime_unblock(struct device *dev);
 extern void pm_runtime_enable(struct device *dev);
 extern void __pm_runtime_disable(struct device *dev, bool check_resume);
@@ -274,7 +274,7 @@ static inline int pm_runtime_get_if_active(struct device *dev)
 static inline int __pm_runtime_set_status(struct device *dev,
                                            unsigned int status) { return 0; }
 static inline int pm_runtime_barrier(struct device *dev) { return 0; }
-static inline void pm_runtime_block_if_disabled(struct device *dev) {}
+static inline bool pm_runtime_block_if_disabled(struct device *dev) { return true; }
 static inline void pm_runtime_unblock(struct device *dev) {}
 static inline void pm_runtime_enable(struct device *dev) {}
 static inline void __pm_runtime_disable(struct device *dev, bool c) {}