summaryrefslogtreecommitdiff
path: root/drivers/base/power/runtime.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2025-06-27 21:23:42 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2025-07-03 17:10:40 +0200
commitffda4ca4608ea811aee2aace211bbf27c68a8853 (patch)
tree6606cdc7e16857cad5709b3287a67fdaa815ee3f /drivers/base/power/runtime.c
parent2b2dcf08116d6e96a446c8f3216b2479701e39aa (diff)
PM: sleep: Add strict_midlayer flag to struct dev_pm_info
Add a new flag, called strict_midlayer, to struct dev_pm_info, along with helper functions for updating and reading its value, to allow middle layer code that provides proper callbacks for device suspend- resume during system-wide PM transitions to let pm_runtime_force_suspend() and and pm_runtime_force_resume() know that they should only invoke runtime PM callbacks coming from the device's driver. Namely, if this flag is set, pm_runtime_force_suspend() and and pm_runtime_force_resume() will invoke runtime PM callbacks provided by the device's driver directly with the assumption that they have been called via a middle layer callback for device suspend or resume, respectively. For instance, acpi_general_pm_domain provides specific callback functions for system suspend, acpi_subsys_suspend(), acpi_subsys_suspend_late() and acpi_subsys_suspend_noirq(), and it does not expect its runtime suspend callback function, acpi_subsys_runtime_suspend(), to be invoked at any point during system suspend. In particular, it does not expect that function to be called from within any of the system suspend callback functions mentioned above which would happen if a device driver collaborating with acpi_general_pm_domain used pm_runtime_force_suspend() as its callback function for any system suspend phase later than "prepare". The new flag allows this expectation of acpi_general_pm_domain to be formally expressed, which is going to be done subsequently. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://patch.msgid.link/24017035.6Emhk5qWAg@rjwysocki.net
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r--drivers/base/power/runtime.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 8cd1a4db5e84..05ff3d2209e6 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1958,6 +1958,23 @@ void pm_runtime_drop_link(struct device_link *link)
pm_request_idle(link->supplier);
}
+static pm_callback_t get_callback(struct device *dev, size_t cb_offset)
+{
+ /*
+ * Setting power.strict_midlayer means that the middle layer
+ * code does not want its runtime PM callbacks to be invoked via
+ * pm_runtime_force_suspend() and pm_runtime_force_resume(), so
+ * return a direct pointer to the driver callback in that case.
+ */
+ if (dev_pm_strict_midlayer_is_set(dev))
+ return __rpm_get_driver_callback(dev, cb_offset);
+
+ return __rpm_get_callback(dev, cb_offset);
+}
+
+#define GET_CALLBACK(dev, callback) \
+ get_callback(dev, offsetof(struct dev_pm_ops, callback))
+
/**
* pm_runtime_force_suspend - Force a device into suspend state if needed.
* @dev: Device to suspend.
@@ -1984,7 +2001,7 @@ int pm_runtime_force_suspend(struct device *dev)
if (pm_runtime_status_suspended(dev) || dev->power.needs_force_resume)
return 0;
- callback = RPM_GET_CALLBACK(dev, runtime_suspend);
+ callback = GET_CALLBACK(dev, runtime_suspend);
dev_pm_enable_wake_irq_check(dev, true);
ret = callback ? callback(dev) : 0;
@@ -2046,7 +2063,7 @@ int pm_runtime_force_resume(struct device *dev)
pm_runtime_status_suspended(dev)))
goto out;
- callback = RPM_GET_CALLBACK(dev, runtime_resume);
+ callback = GET_CALLBACK(dev, runtime_resume);
dev_pm_disable_wake_irq_check(dev, false);
ret = callback ? callback(dev) : 0;