[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <f4a7b539-eeac-1a59-2350-3eefc8c17801@0882a8b5-c6c3-11e9-b005-00805fc181fe>
Date: Mon, 29 Jun 2020 21:56:49 +0100
From: Simon Arlott <simon@...iron.net>
To: Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
x86@...nel.org, "H. Peter Anvin" <hpa@...or.com>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Jonathan Corbet <corbet@....net>, linux-doc@...r.kernel.org
Cc: "James E.J. Bottomley" <jejb@...ux.ibm.com>,
"Martin K. Petersen" <martin.petersen@...cle.com>,
linux-scsi@...r.kernel.org, Bart Van Assche <bvanassche@....org>,
Christoph Hellwig <hch@...radead.org>,
Damien Le Moal <Damien.LeMoal@....com>,
Pavel Machek <pavel@....cz>,
Henrique de Moraes Holschuh <hmh@....eng.br>
Subject: [PATCH 1/2] reboot: add a "power cycle" quirk to prepare for a power
off on reboot
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@...iron.net>
---
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
Powered by blists - more mailing lists