[PATCH 2/2] PM: Add shutdown=legacy command line option
From: Mario Limonciello
Date: Mon Nov 02 2026 - 09:10:37 EST
Powering off now uses the hibernation callback flow when it is available.
Add an escape valve for systems that fail with this flow.
The shutdown=legacy option restores the device_shutdown() path. Document
it in the kernel parameter reference and the shutdown debugging guide.
Tested-by: Bartu Alev <bartualev@xxxxxxxxx>
Tested-by: Merthan Karakaş <m3rthn.k@xxxxxxxxx>
Signed-off-by: Mario Limonciello <superm1@xxxxxxxxxx>
---
Bartu specifically tested his ASUS FA507 with this series. His laptop
got really hot in S5 before the series. He also intentionally used
this debug knob to verify the problem comes back.
Merthan tested on his ASUS laptop and it fixed system getting hot at
S5.
---
Documentation/admin-guide/kernel-parameters.txt | 4 ++++
Documentation/power/shutdown-debugging.rst | 7 ++++++-
kernel/reboot.c | 10 +++++++++-
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 0b3c140babd94..16d584bdbb73d 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6981,6 +6981,10 @@ Kernel parameters
shapers= [NET]
Maximal number of shapers.
+ shutdown=legacy [KNL]
+ Use the legacy device shutdown callbacks when powering off
+ the system instead of the hibernation power-off callbacks.
+
show_lapic= [APIC,X86] Advanced Programmable Interrupt Controller
Limit apic dumping. The parameter defines the maximal
number of local apics being dumped. Also it is possible
diff --git a/Documentation/power/shutdown-debugging.rst b/Documentation/power/shutdown-debugging.rst
index c510122e0bbc2..254cd3e0b5907 100644
--- a/Documentation/power/shutdown-debugging.rst
+++ b/Documentation/power/shutdown-debugging.rst
@@ -33,7 +33,7 @@ some potential options include:
Kernel Command-line Parameters
==============================
-Add these parameters to your kernel command line:
+Add these parameters to your kernel command line to capture shutdown logs:
* ``printk.always_kmsg_dump=Y``
* Forces the kernel to dump the entire message buffer to pstore during
@@ -41,6 +41,11 @@ Add these parameters to your kernel command line:
* ``efi_pstore.pstore_disable=N``
* For EFI-based systems, ensures the EFI backend is active
+If the system fails while running the hibernation power-off callbacks, add
+``shutdown=legacy`` to use the legacy device shutdown callbacks instead. This
+can be used to work around the failure and confirm which callback flow caused
+it.
+
Userspace Interaction and Log Retrieval
=======================================
On the next boot after a hang, pstore logs will be available in the pstore
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 1ad8629fde4d9..6c80356b9a85f 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -70,6 +70,7 @@ struct sys_off_handler {
* of that.
*/
static bool poweroff_fallback_to_halt;
+static bool shutdown_legacy;
/*
* Temporary stub that prevents linkage failure while we're in process
@@ -317,7 +318,7 @@ static void kernel_shutdown_prepare(enum system_states state)
system_state = state;
usermodehelper_disable();
#ifdef CONFIG_HIBERNATE_CALLBACKS
- if (state == SYSTEM_POWER_OFF) {
+ if (state == SYSTEM_POWER_OFF && !shutdown_legacy) {
if (!dpm_suspend_start(PMSG_POWEROFF) && !dpm_suspend_end(PMSG_POWEROFF))
return;
pr_emerg("Failed to power off devices, using shutdown instead.\n");
@@ -1112,6 +1113,13 @@ static ssize_t hw_protection_store(struct kobject *kobj,
static struct kobj_attribute hw_protection_attr = __ATTR_RW(hw_protection);
#endif
+static int __init shutdown_setup(char *str)
+{
+ shutdown_legacy = true;
+ return 1;
+}
+__setup("shutdown=legacy", shutdown_setup);
+
static int __init reboot_setup(char *str)
{
for (;;) {
--
2.53.0