]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
power: supply: axp288_charger: Do not cancel work before initializing it
authorKrzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Fri, 20 Feb 2026 17:49:39 +0000 (18:49 +0100)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Tue, 3 Mar 2026 22:58:08 +0000 (23:58 +0100)
Driver registered devm handler to cancel_work_sync() before even the
work was initialized, thus leading to possible warning from
kernel/workqueue.c on (!work->func) check, if the error path was hit
before the initialization happened.

Use devm_work_autocancel() on each work item independently, which
handles the initialization and handler to cancel work.

Fixes: 165c2357744e ("power: supply: axp288_charger: Properly stop work on probe-error / remove")
Cc: stable@vger.kernel.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Link: https://patch.msgid.link/20260220174938.672883-5-krzysztof.kozlowski@oss.qualcomm.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/axp288_charger.c

index ac05942e4e6ac1f5610a7217857465136a695601..ca52c2c82b2cf2fcd68d6d52d92a9e05b8942c22 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
+#include <linux/devm-helpers.h>
 #include <linux/device.h>
 #include <linux/regmap.h>
 #include <linux/workqueue.h>
@@ -821,14 +822,6 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
        return 0;
 }
 
-static void axp288_charger_cancel_work(void *data)
-{
-       struct axp288_chrg_info *info = data;
-
-       cancel_work_sync(&info->otg.work);
-       cancel_work_sync(&info->cable.work);
-}
-
 static int axp288_charger_probe(struct platform_device *pdev)
 {
        int ret, i, pirq;
@@ -911,12 +904,12 @@ static int axp288_charger_probe(struct platform_device *pdev)
        }
 
        /* Cancel our work on cleanup, register this before the notifiers */
-       ret = devm_add_action(dev, axp288_charger_cancel_work, info);
+       ret = devm_work_autocancel(dev, &info->cable.work,
+                                  axp288_charger_extcon_evt_worker);
        if (ret)
                return ret;
 
        /* Register for extcon notification */
-       INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
        info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
        ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
                                                &info->cable.nb);
@@ -926,8 +919,12 @@ static int axp288_charger_probe(struct platform_device *pdev)
        }
        schedule_work(&info->cable.work);
 
+       ret = devm_work_autocancel(dev, &info->otg.work,
+                                  axp288_charger_otg_evt_worker);
+       if (ret)
+               return ret;
+
        /* Register for OTG notification */
-       INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
        info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
        if (info->otg.cable) {
                ret = devm_extcon_register_notifier(dev, info->otg.cable,