* [PATCH 1/4] firmware: psci: switch SYSTEM_OFF to sys-off handler API
2026-05-14 14:47 [PATCH 0/4] power: sys-off: fix Pixel C shutdown via MAX77620 Diogo Ivo
@ 2026-05-14 14:47 ` Diogo Ivo
2026-05-14 19:48 ` sashiko-bot
2026-05-14 14:47 ` [PATCH 2/4] mfd: max77620: convert poweroff support to sys-off API Diogo Ivo
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Diogo Ivo @ 2026-05-14 14:47 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter
Cc: linux-arm-kernel, linux-kernel, devicetree, linux-tegra,
Diogo Ivo
Replace the legacy pm_power_off hook with the generic sys-off
handler infrastructure.
Convert psci_sys_poweroff() to the sys-off callback prototype and
register it through register_sys_off_handler() with firmware
priority. This removes the direct dependency on pm_power_off and
drops the now-unused <linux/pm.h> include.
This aligns the PSCI poweroff path with the modern system-off
framework used by other firmware and platform drivers.
Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
drivers/firmware/psci/psci.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 38ca190d4a22..d6e9721d11e5 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -13,7 +13,6 @@
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/of.h>
-#include <linux/pm.h>
#include <linux/printk.h>
#include <linux/psci.h>
#include <linux/reboot.h>
@@ -329,9 +328,11 @@ static struct notifier_block psci_sys_reset_nb = {
.priority = 129,
};
-static void psci_sys_poweroff(void)
+static int psci_sys_poweroff(struct sys_off_data *data)
{
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+
+ return NOTIFY_DONE;
}
#ifdef CONFIG_HIBERNATION
@@ -671,7 +672,8 @@ static void __init psci_0_2_set_functions(void)
register_restart_handler(&psci_sys_reset_nb);
- pm_power_off = psci_sys_poweroff;
+ register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE,
+ psci_sys_poweroff, NULL);
}
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 1/4] firmware: psci: switch SYSTEM_OFF to sys-off handler API
2026-05-14 14:47 ` [PATCH 1/4] firmware: psci: switch SYSTEM_OFF to sys-off handler API Diogo Ivo
@ 2026-05-14 19:48 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-14 19:48 UTC (permalink / raw)
To: Diogo Ivo; +Cc: devicetree, robh, conor+dt, krzk+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Premature memory allocation during early boot causing kernel panic
--
commit ef783d7ffab1683b74c28865d23fcb00064437a6
Author: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
firmware: psci: switch SYSTEM_OFF to sys-off handler API
This commit replaces the legacy pm_power_off hook with the generic sys-off
handler infrastructure. It converts psci_sys_poweroff to the sys-off callback
prototype and registers it through register_sys_off_handler.
> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index 38ca190d4a22d..d6e9721d11e54 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
[ ... ]
> @@ -671,7 +672,8 @@ static void __init psci_0_2_set_functions(void)
>
> register_restart_handler(&psci_sys_reset_nb);
>
> - pm_power_off = psci_sys_poweroff;
> + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE,
> + psci_sys_poweroff, NULL);
> }
Can this cause a regression during early boot?
The function psci_0_2_set_functions() is called extremely early via
psci_dt_init() or psci_acpi_init() from setup_arch(). This happens before
mm_core_init() brings up the slab memory allocator.
Because the priority passed is SYS_OFF_PRIO_FIRMWARE, alloc_sys_off_handler()
falls back to dynamically allocating the handler using kzalloc().
Could calling kzalloc() before the slab allocator is initialized result in a
kernel panic?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514-smaug-poweroff-v1-0-30f9a4688966@tecnico.ulisboa.pt?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/4] mfd: max77620: convert poweroff support to sys-off API
2026-05-14 14:47 [PATCH 0/4] power: sys-off: fix Pixel C shutdown via MAX77620 Diogo Ivo
2026-05-14 14:47 ` [PATCH 1/4] firmware: psci: switch SYSTEM_OFF to sys-off handler API Diogo Ivo
@ 2026-05-14 14:47 ` Diogo Ivo
2026-05-14 20:05 ` sashiko-bot
2026-05-14 14:47 ` [PATCH 3/4] mfd: max77620: override PSCI poweroff handler on Pixel C Diogo Ivo
2026-05-14 14:47 ` [PATCH 4/4] arm64: tegra: smaug: mark MAX77620 as system power controller Diogo Ivo
3 siblings, 1 reply; 7+ messages in thread
From: Diogo Ivo @ 2026-05-14 14:47 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter
Cc: linux-arm-kernel, linux-kernel, devicetree, linux-tegra,
Diogo Ivo
Convert max77620_pm_power_off() to the sys-off callback prototype and
register it with the sys-off API when the device tree marks the PMIC as
a system power controller. This also removes the global max77620_scratch
pointer by passing the chip instance through the callback data.
This modernizes the driver's poweroff handling and aligns it with
the kernel sys-off infrastructure.
Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
drivers/mfd/max77620.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index 3af2974b3023..c4f89a9681f3 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -31,11 +31,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-static struct max77620_chip *max77620_scratch;
-
static const struct resource gpio_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
};
@@ -484,13 +483,15 @@ static int max77620_read_es_version(struct max77620_chip *chip)
return ret;
}
-static void max77620_pm_power_off(void)
+static int max77620_pm_power_off(struct sys_off_data *data)
{
- struct max77620_chip *chip = max77620_scratch;
+ struct max77620_chip *chip = data->cb_data;
regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
MAX77620_ONOFFCNFG1_SFT_RST,
MAX77620_ONOFFCNFG1_SFT_RST);
+
+ return NOTIFY_DONE;
}
static int max77620_probe(struct i2c_client *client)
@@ -501,7 +502,6 @@ static int max77620_probe(struct i2c_client *client)
struct regmap_irq_chip *chip_desc;
const struct mfd_cell *mfd_cells;
int n_mfd_cells;
- bool pm_off;
int ret;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
@@ -573,10 +573,14 @@ static int max77620_probe(struct i2c_client *client)
return ret;
}
- pm_off = of_device_is_system_power_controller(client->dev.of_node);
- if (pm_off && !pm_power_off) {
- max77620_scratch = chip;
- pm_power_off = max77620_pm_power_off;
+ if (of_device_is_system_power_controller(client->dev.of_node)) {
+ ret = devm_register_sys_off_handler(&client->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ max77620_pm_power_off, chip);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to register power-off handler\n");
}
return 0;
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 2/4] mfd: max77620: convert poweroff support to sys-off API
2026-05-14 14:47 ` [PATCH 2/4] mfd: max77620: convert poweroff support to sys-off API Diogo Ivo
@ 2026-05-14 20:05 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-14 20:05 UTC (permalink / raw)
To: Diogo Ivo; +Cc: conor+dt, devicetree, robh, krzk+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] max77620_pm_power_off() acquires a mutex inside an atomic context (RCU read-side critical section and disabled IRQs), leading to a potential deadlock during system power-off.
--
commit b3bd2ca1c0c28ed17c99ae76d84c114260a5a844
Author: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
mfd: max77620: convert poweroff support to sys-off API
This commit converts max77620_pm_power_off() to the sys-off callback prototype
and registers it with the sys-off API when the device tree marks the PMIC as
a system power controller. It also removes the global max77620_scratch pointer
by passing the chip instance through the callback data.
> diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
> --- a/drivers/mfd/max77620.c
> +++ b/drivers/mfd/max77620.c
[ ... ]
> @@ -484,13 +483,15 @@ static int max77620_read_es_version(struct max77620_chip *chip)
> return ret;
> }
>
> -static void max77620_pm_power_off(void)
> +static int max77620_pm_power_off(struct sys_off_data *data)
> {
> - struct max77620_chip *chip = max77620_scratch;
> + struct max77620_chip *chip = data->cb_data;
>
> regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
> MAX77620_ONOFFCNFG1_SFT_RST,
> MAX77620_ONOFFCNFG1_SFT_RST);
> +
> + return NOTIFY_DONE;
> }
[ ... ]
> @@ -573,10 +573,14 @@ static int max77620_probe(struct i2c_client *client)
> return ret;
> }
>
> - pm_off = of_device_is_system_power_controller(client->dev.of_node);
> - if (pm_off && !pm_power_off) {
> - max77620_scratch = chip;
> - pm_power_off = max77620_pm_power_off;
> + if (of_device_is_system_power_controller(client->dev.of_node)) {
> + ret = devm_register_sys_off_handler(&client->dev,
> + SYS_OFF_MODE_POWER_OFF,
Does this code risk deadlocking during system power-off?
Handlers registered with SYS_OFF_MODE_POWER_OFF execute via an atomic
notifier call chain inside do_kernel_power_off() holding rcu_read_lock(),
and with local IRQs completely disabled.
However, the max77620_pm_power_off() callback invokes regmap_update_bits()
on an I2C regmap, which relies on a standard mutex.
If another CPU held this PMIC regmap mutex when smp_send_stop() was issued,
attempting to acquire it here will hang the power-off sequence indefinitely.
Would it be safer to register this handler using
SYS_OFF_MODE_POWER_OFF_PREPARE instead? That mode uses a blocking notifier
call chain and executes before CPUs are stopped and IRQs are disabled.
> + SYS_OFF_PRIO_DEFAULT,
> + max77620_pm_power_off, chip);
> + if (ret)
> + return dev_err_probe(&client->dev, ret,
> + "failed to register power-off handler\n");
> }
>
> return 0;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260514-smaug-poweroff-v1-0-30f9a4688966@tecnico.ulisboa.pt?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/4] mfd: max77620: override PSCI poweroff handler on Pixel C
2026-05-14 14:47 [PATCH 0/4] power: sys-off: fix Pixel C shutdown via MAX77620 Diogo Ivo
2026-05-14 14:47 ` [PATCH 1/4] firmware: psci: switch SYSTEM_OFF to sys-off handler API Diogo Ivo
2026-05-14 14:47 ` [PATCH 2/4] mfd: max77620: convert poweroff support to sys-off API Diogo Ivo
@ 2026-05-14 14:47 ` Diogo Ivo
2026-05-14 14:47 ` [PATCH 4/4] arm64: tegra: smaug: mark MAX77620 as system power controller Diogo Ivo
3 siblings, 0 replies; 7+ messages in thread
From: Diogo Ivo @ 2026-05-14 14:47 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter
Cc: linux-arm-kernel, linux-kernel, devicetree, linux-tegra,
Diogo Ivo
On Pixel C, shutdown must be handled by the MAX77620 PMIC rather
than the PSCI SYSTEM_OFF call, whose firmware implementation is:
__dead2 void tegra_system_off(void)
{
ERROR("Tegra System Off: operation not handled.\n");
panic();
}
Raise the MAX77620 sys-off handler priority above SYS_OFF_PRIO_FIRMWARE
on Pixel C systems so it takes precedence over the PSCI poweroff handler.
Other systems continue to use the default sys-off priority.
Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
drivers/mfd/max77620.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index c4f89a9681f3..3b1f3a2f3566 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -494,6 +494,18 @@ static int max77620_pm_power_off(struct sys_off_data *data)
return NOTIFY_DONE;
}
+static int max77620_power_off_priority(void)
+{
+ /*
+ * For Smaug we need to override the PSCI poweroff handler
+ * which is registered at priority SYS_OFF_PRIO_FIRMWARE.
+ */
+ if (of_machine_is_compatible("google,smaug"))
+ return SYS_OFF_PRIO_FIRMWARE + 1;
+
+ return SYS_OFF_PRIO_DEFAULT;
+}
+
static int max77620_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -502,6 +514,7 @@ static int max77620_probe(struct i2c_client *client)
struct regmap_irq_chip *chip_desc;
const struct mfd_cell *mfd_cells;
int n_mfd_cells;
+ int priority;
int ret;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
@@ -574,10 +587,11 @@ static int max77620_probe(struct i2c_client *client)
}
if (of_device_is_system_power_controller(client->dev.of_node)) {
+ priority = max77620_power_off_priority();
ret = devm_register_sys_off_handler(&client->dev,
SYS_OFF_MODE_POWER_OFF,
- SYS_OFF_PRIO_DEFAULT,
- max77620_pm_power_off, chip);
+ priority, max77620_pm_power_off,
+ chip);
if (ret)
return dev_err_probe(&client->dev, ret,
"failed to register power-off handler\n");
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/4] arm64: tegra: smaug: mark MAX77620 as system power controller
2026-05-14 14:47 [PATCH 0/4] power: sys-off: fix Pixel C shutdown via MAX77620 Diogo Ivo
` (2 preceding siblings ...)
2026-05-14 14:47 ` [PATCH 3/4] mfd: max77620: override PSCI poweroff handler on Pixel C Diogo Ivo
@ 2026-05-14 14:47 ` Diogo Ivo
3 siblings, 0 replies; 7+ messages in thread
From: Diogo Ivo @ 2026-05-14 14:47 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter
Cc: linux-arm-kernel, linux-kernel, devicetree, linux-tegra,
Diogo Ivo
Register the MAX77620 PMIC as the system power controller on
Pixel C so the driver can install its sys-off handler.
This allows the PMIC poweroff sequence to override the non-working
PSCI SYSTEM_OFF implementation on this platform.
Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
index f0b8c2c80aa5..1791b47f0a73 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
@@ -1467,6 +1467,8 @@ pmic: pmic@3c {
gpio-controller;
#gpio-cells = <2>;
+ system-power-controller;
+
pinctrl-names = "default";
pinctrl-0 = <&max77620_default>;
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread