Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regulator: qcom_spmi-regulator: Clean-up by using managed work init

Few drivers implement remove call-back only for ensuring a delayed
work gets cancelled prior driver removal. Clean-up these by switching
to use devm_delayed_work_autocancel() instead.

Additionally, this helps avoiding mixing devm and manual resource
management and cleans up a (theoretical?) bug where devm managed
over-current IRQ might schedule a new work item after wq was cleaned
at remove().

This change is compile-tested only. All testing is appreciated.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Link: https://lore.kernel.org/r/3bd35bb43257f4bf5b99f75d207ed5e1e08d1d38.1616506559.git.matti.vaittinen@fi.rohmeurope.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Matti Vaittinen and committed by
Greg Kroah-Hartman
b6688015 6d0c5de2

+8 -26
+8 -26
drivers/regulator/qcom_spmi-regulator.c
··· 5 5 6 6 #include <linux/module.h> 7 7 #include <linux/delay.h> 8 + #include <linux/devm-helpers.h> 8 9 #include <linux/err.h> 9 10 #include <linux/kernel.h> 10 11 #include <linux/interrupt.h> ··· 1843 1842 return ret; 1844 1843 } 1845 1844 1846 - INIT_DELAYED_WORK(&vreg->ocp_work, spmi_regulator_vs_ocp_work); 1845 + ret = devm_delayed_work_autocancel(dev, &vreg->ocp_work, 1846 + spmi_regulator_vs_ocp_work); 1847 + if (ret) 1848 + return ret; 1847 1849 } 1848 1850 1849 1851 return 0; ··· 2161 2157 vreg->regmap = regmap; 2162 2158 if (reg->ocp) { 2163 2159 vreg->ocp_irq = platform_get_irq_byname(pdev, reg->ocp); 2164 - if (vreg->ocp_irq < 0) { 2165 - ret = vreg->ocp_irq; 2166 - goto err; 2167 - } 2160 + if (vreg->ocp_irq < 0) 2161 + return vreg->ocp_irq; 2168 2162 } 2169 2163 vreg->desc.id = -1; 2170 2164 vreg->desc.owner = THIS_MODULE; ··· 2205 2203 rdev = devm_regulator_register(dev, &vreg->desc, &config); 2206 2204 if (IS_ERR(rdev)) { 2207 2205 dev_err(dev, "failed to register %s\n", name); 2208 - ret = PTR_ERR(rdev); 2209 - goto err; 2206 + return PTR_ERR(rdev); 2210 2207 } 2211 2208 2212 2209 INIT_LIST_HEAD(&vreg->node); 2213 2210 list_add(&vreg->node, vreg_list); 2214 2211 } 2215 - 2216 - return 0; 2217 - 2218 - err: 2219 - list_for_each_entry(vreg, vreg_list, node) 2220 - if (vreg->ocp_irq) 2221 - cancel_delayed_work_sync(&vreg->ocp_work); 2222 - return ret; 2223 - } 2224 - 2225 - static int qcom_spmi_regulator_remove(struct platform_device *pdev) 2226 - { 2227 - struct spmi_regulator *vreg; 2228 - struct list_head *vreg_list = platform_get_drvdata(pdev); 2229 - 2230 - list_for_each_entry(vreg, vreg_list, node) 2231 - if (vreg->ocp_irq) 2232 - cancel_delayed_work_sync(&vreg->ocp_work); 2233 2212 2234 2213 return 0; 2235 2214 } ··· 2221 2238 .of_match_table = qcom_spmi_regulator_match, 2222 2239 }, 2223 2240 .probe = qcom_spmi_regulator_probe, 2224 - .remove = qcom_spmi_regulator_remove, 2225 2241 }; 2226 2242 module_platform_driver(qcom_spmi_regulator_driver); 2227 2243