[PATCH v2] power: supply: ds2760_battery: convert to devm-managed workqueue and pm_notifier
From: Ivy Lopez
Date: Wed Aug 12 2026 - 20:42:07 EST
Following review feedback, convert the driver to use devm-managed
resources instead of manual cleanup in w1_ds2760_remove_slave():
- devm_alloc_ordered_workqueue() for the monitor workqueue
- devm_delayed_work_autocancel() for the monitor delayed work
- devm_add_action_or_reset() to unregister the pm_notifier
This removes the need for w1_ds2760_remove_slave() entirely, along
with the NULL checks it required to safely handle a partially
initialized di on an add_slave() failure path.
Fixes: bf4973553737 ("power: supply: ds2760_battery: merge ds2760 supply driver with its w1 slave companion")
Suggested-by: Sebastian Reichel <sre@xxxxxxxxxx>
Signed-off-by: Ivy Lopez <skunkolee@xxxxxxxxx>
---
drivers/power/supply/ds2760_battery.c | 54 +++++++++++----------------
1 file changed, 21 insertions(+), 33 deletions(-)
diff --git a/drivers/power/supply/ds2760_battery.c b/drivers/power/supply/ds2760_battery.c
index 3c2433f6b5e9..901aaaf916c4 100644
--- a/drivers/power/supply/ds2760_battery.c
+++ b/drivers/power/supply/ds2760_battery.c
@@ -23,6 +23,7 @@
#include <linux/param.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
+#include <linux/devm-helpers.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
@@ -621,6 +622,11 @@ static int ds2760_pm_notifier(struct notifier_block *notifier,
return NOTIFY_DONE;
}
+static void ds2760_battery_unregister_pm_notifier(void *notifier)
+{
+ unregister_pm_notifier(notifier);
+}
+
static int w1_ds2760_add_slave(struct w1_slave *sl)
{
struct power_supply_config psy_cfg = {};
@@ -631,10 +637,8 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
char status;
di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
- if (!di) {
- retval = -ENOMEM;
- goto di_alloc_failed;
- }
+ if (!di)
+ return -ENOMEM;
snprintf(name, sizeof(name), "ds2760-battery.%d", dev->id);
@@ -695,41 +699,26 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
di->bat = devm_power_supply_register(dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n");
- retval = PTR_ERR(di->bat);
- goto batt_failed;
+ return PTR_ERR(di->bat);
}
- INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
- di->monitor_wqueue = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
- if (!di->monitor_wqueue) {
- retval = -ESRCH;
- goto workqueue_failed;
- }
+ di->monitor_wqueue = devm_alloc_ordered_workqueue(dev, name, WQ_MEM_RECLAIM);
+ if (!di->monitor_wqueue)
+ return -ESRCH;
+
+ retval = devm_delayed_work_autocancel(dev, &di->monitor_work,
+ ds2760_battery_work);
+ if (retval)
+ return retval;
+
queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
di->pm_notifier.notifier_call = ds2760_pm_notifier;
register_pm_notifier(&di->pm_notifier);
- goto success;
-
-workqueue_failed:
-batt_failed:
-di_alloc_failed:
-success:
- return retval;
-}
-
-static void w1_ds2760_remove_slave(struct w1_slave *sl)
-{
- struct ds2760_device_info *di = sl->family_data;
-
- if (!di)
- return;
-
- unregister_pm_notifier(&di->pm_notifier);
- cancel_delayed_work_sync(&di->monitor_work);
- if (di->monitor_wqueue)
- destroy_workqueue(di->monitor_wqueue);
+ return devm_add_action_or_reset(dev,
+ ds2760_battery_unregister_pm_notifier,
+ &di->pm_notifier);
}
#ifdef CONFIG_OF
@@ -741,7 +730,6 @@ static const struct of_device_id w1_ds2760_of_ids[] = {
static const struct w1_family_ops w1_ds2760_fops = {
.add_slave = w1_ds2760_add_slave,
- .remove_slave = w1_ds2760_remove_slave,
.groups = w1_ds2760_groups,
};
--
2.55.0