[PATCH 12/28] mfd: max8907: Manage power-off handler via devm_register_sys_off_handler()

From: Lee Jones

Date: Wed Oct 21 2026 - 08:19:11 EST


When the MAX8907 device is configured as the system power controller,
max8907_i2c_probe() assigns the devres-managed device context to
max8907_pm_off and registers max8907_power_off() as the global
pm_power_off handler. However, max8907_i2c_remove() does not clear
these pointers upon device unbind, leaving pm_power_off and
max8907_pm_off dangling after devres frees the driver state.

Convert max8907_power_off() to a sys_off_handler callback registered via
devm_register_sys_off_handler() so the handler is automatically
unregistered on device unbind and the global max8907_pm_off pointer can
be dropped.

Fixes: 9582fdcb6fcf ("mfd: max8907: Add power off control")
Closes: https://sashiko.dev/#/bug/linux-d73d6689-d160-447f-9b3c-710fd4c4b6fb
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Lee Jones <lee@xxxxxxxxxx>
---
drivers/mfd/max8907.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 7bac1d651771..dab5706d4115 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -15,6 +15,7 @@
#include <linux/mfd/max8907.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/slab.h>

@@ -173,11 +174,14 @@ static const struct regmap_irq_chip max8907_rtc_irq_chip = {
.num_irqs = ARRAY_SIZE(max8907_rtc_irqs),
};

-static struct max8907 *max8907_pm_off;
-static void max8907_power_off(void)
+static int max8907_power_off(struct sys_off_data *data)
{
- regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG,
- MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+ struct max8907 *max8907 = data->cb_data;
+
+ regmap_update_bits(max8907->regmap_gen, MAX8907_REG_RESET_CNFG,
+ MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+
+ return NOTIFY_DONE;
}

static int max8907_i2c_probe(struct i2c_client *i2c)
@@ -256,13 +260,23 @@ static int max8907_i2c_probe(struct i2c_client *i2c)
goto err_add_devices;
}

- if (pm_off && !pm_power_off) {
- max8907_pm_off = max8907;
- pm_power_off = max8907_power_off;
+ if (pm_off) {
+ ret = devm_register_sys_off_handler(&i2c->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ max8907_power_off, max8907);
+ if (ret) {
+ dev_err(&i2c->dev,
+ "failed to register sys-off handler: %d\n",
+ ret);
+ goto err_sys_off;
+ }
}

return 0;

+err_sys_off:
+ mfd_remove_devices(max8907->dev);
err_add_devices:
regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
err_irqc_rtc:
--
2.56.0.218.g1ec904b173-goog