I need to use "reboot=p" on my desktop because one of the PCIe devices does not appear after a warm boot. This results in a very cold boot because the BIOS turns the PSU off and on. The scsi sd shutdown process does not send a stop command to disks before the reboot happens (stop commands are only sent for a shutdown). The result is that all of my SSDs experience a sudden power loss on every reboot, which is undesirable behaviour because it could cause data to be corrupted. These events are recorded in the SMART attributes. Add a "power cycle" quirk to the reboot options to prepare all devices for a power off by setting the system_state to SYSTEM_POWER_OFF instead of SYSTEM_RESTART while still performing a restart as requested. This uses the letter "C" for the parameter because of numerous uses of "reboot=pci" that would otherwise trigger this behaviour if "c" was used. Signed-off-by: Simon Arlott <simon@xxxxxxxxxxx> --- Previous patches to make scsi/sd stop before a reboot: https://lore.kernel.org/lkml/499138c8-b6d5-ef4a-2780-4f750ed337d3@0882a8b5-c6c3-11e9-b005-00805fc181fe/ https://lore.kernel.org/lkml/e726ffd8-8897-4a79-c3d6-6271eda8aebb@0882a8b5-c6c3-11e9-b005-00805fc181fe/ Documentation/admin-guide/kernel-parameters.txt | 8 ++++++-- include/linux/reboot.h | 4 ++++ kernel/reboot.c | 15 ++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index bee3b83d6f84..91359fd4fbcc 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4422,9 +4422,10 @@ reboot= [KNL] Format (x86 or x86_64): [w[arm] | c[old] | h[ard] | s[oft] | g[pio]] \ - [[,]s[mp]#### \ + [[,]s[mp]####] \ [[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] | p[ci]] \ - [[,]f[orce] + [[,]f[orce]] \ + [[,]C] Where reboot_mode is one of warm (soft) or cold (hard) or gpio (prefix with 'panic_' to set mode for panic reboot only), @@ -4432,6 +4433,9 @@ reboot_force is either force or not specified, reboot_cpu is s[mp]#### with #### being the processor to be used for rebooting. + Quirks: + C = Rebooting includes a power cycle, prepare + for a power off instead of a restart. refscale.holdoff= [KNL] Set test-start holdoff period. The purpose of diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 3734cd8f38a8..b49559ba825a 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -39,6 +39,10 @@ extern int reboot_default; extern int reboot_cpu; extern int reboot_force; +#define REBOOT_QUIRK_POWER_CYCLE BIT(0) + +extern int reboot_quirks; + extern int register_reboot_notifier(struct notifier_block *); extern int unregister_reboot_notifier(struct notifier_block *); diff --git a/kernel/reboot.c b/kernel/reboot.c index 491f1347bf43..5605c2894f2b 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -45,6 +45,7 @@ int reboot_default = 1; int reboot_cpu; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; +int reboot_quirks; /* * If set, this is used for preparing the system to power off. @@ -71,7 +72,15 @@ EXPORT_SYMBOL_GPL(emergency_restart); void kernel_restart_prepare(char *cmd) { blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); - system_state = SYSTEM_RESTART; + if (reboot_quirks & REBOOT_QUIRK_POWER_CYCLE) { + /* + * The reboot will include a power cycle, so prepare all + * devices for a power off. + */ + system_state = SYSTEM_POWER_OFF; + } else { + system_state = SYSTEM_RESTART; + } usermodehelper_disable(); device_shutdown(); } @@ -583,6 +592,10 @@ static int __init reboot_setup(char *str) case 'f': reboot_force = 1; break; + + case 'C': + reboot_quirks |= REBOOT_QUIRK_POWER_CYCLE; + break; } str = strchr(str, ','); -- 2.17.1 -- Simon Arlott