]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hwmon: (raspberrypi) Fix delayed-work teardown race
authorShubham Chakraborty <chakrabortyshubham66@gmail.com>
Sun, 17 May 2026 08:04:45 +0000 (13:34 +0530)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 9 Jun 2026 15:23:05 +0000 (08:23 -0700)
The delayed polling work rearms itself from the work function, so use
explicit delayed-work setup and cleanup instead of
devm_delayed_work_autocancel().

Initialize the delayed work with INIT_DELAYED_WORK() and register a
devres cleanup action that calls disable_delayed_work_sync() during
teardown.

This addresses the concern raised during review about the polling work
being able to requeue itself while the driver is being removed.

Signed-off-by: Shubham Chakraborty <chakrabortyshubham66@gmail.com>
Link: https://lore.kernel.org/r/20260517080445.103962-4-chakrabortyshubham66@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/raspberrypi-hwmon.c

index a458a858b0ac5850e90854c81e620aaf0147545e..7b1d2829f012f75f7957ac6bde584b28397b0fdb 100644 (file)
@@ -8,7 +8,6 @@
  * Copyright (C) 2026 Shubham Chakraborty <chakrabortyshubham66@gmail.com>
  */
 #include <linux/device.h>
-#include <linux/devm-helpers.h>
 #include <linux/err.h>
 #include <linux/hwmon.h>
 #include <linux/module.h>
@@ -97,6 +96,13 @@ static void get_values_poll(struct work_struct *work)
        schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
 }
 
+static void rpi_hwmon_cancel_poll_work(void *res)
+{
+       struct rpi_hwmon_data *data = res;
+
+       disable_delayed_work_sync(&data->get_values_poll_work);
+}
+
 static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
                    u32 attr, int channel, long *val)
 {
@@ -238,8 +244,8 @@ static int rpi_hwmon_probe(struct platform_device *pdev)
        if (IS_ERR(data->hwmon_dev))
                return PTR_ERR(data->hwmon_dev);
 
-       ret = devm_delayed_work_autocancel(dev, &data->get_values_poll_work,
-                                          get_values_poll);
+       INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+       ret = devm_add_action_or_reset(dev, rpi_hwmon_cancel_poll_work, data);
        if (ret)
                return ret;
        platform_set_drvdata(pdev, data);