diff mbox series

[RFC/RFT] PM: sleep: Ignore device driver suspend() callback return values

Message ID 7e3092234617e8479d3020e5fed7ff47ac750014.1731522552.git.len.brown@intel.com
State New
Headers show
Series [RFC/RFT] PM: sleep: Ignore device driver suspend() callback return values | expand

Commit Message

Len Brown Nov. 13, 2024, 6:35 p.m. UTC
From: Len Brown <len.brown@intel.com>

Drivers commonly return non-zero values from their suspend()
callbacks due to transient errors, not realizing that doing so
aborts system-wide suspend.

Ignore those return values.

Both before and after this patch, the correct method for a
device driver to abort system-wide suspend is to invoke
pm_system_wakeup() during the suspend flow.

Legacy behaviour can be restored by adding this line to your .config:
CONFIG_PM_SLEEP_LEGACY_CALLBACK_ABORT=y

Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/base/power/main.c |  4 ++++
 kernel/power/Kconfig      | 14 ++++++++++++++
 2 files changed, 18 insertions(+)
diff mbox series

Patch

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 4a67e83300e1..56b7c9c752b4 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1678,7 +1678,11 @@  static int device_suspend(struct device *dev, pm_message_t state, bool async)
 		callback = pm_op(dev->driver->pm, state);
 	}
 
+#if CONFIG_PM_SLEEP_LEGACY_CALLBACK_ABORT
 	error = dpm_run_callback(callback, dev, state, info);
+#else
+	dpm_run_callback(callback, dev, state, info);
+#endif
 
  End:
 	if (!error) {
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index afce8130d8b9..51b5d6c9bf1a 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -141,6 +141,20 @@  config PM_SLEEP
 	depends on SUSPEND || HIBERNATE_CALLBACKS
 	select PM
 
+config PM_SLEEP_LEGACY_CALLBACK_ABORT
+	def_bool n
+	depends on PM_SLEEP
+	help
+	This option enables the legacy API for device .suspend() callbacks.
+	That API empowered any driver to abort system-wide suspend
+	by returning any non-zero value from its .suspend() callback.
+	In practice, these aborts are almost always spurious and unwanted.
+
+	Disabling this option (default) ignores .suspend() callback return values.
+
+	In both cases, any driver can abort system wide suspend by invoking
+	pm_system_wakeup() during the suspend flow.
+
 config PM_SLEEP_SMP
 	def_bool y
 	depends on SMP