aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2024-12-15 18:21:24 +0100
committerSebastian Reichel <sebastian.reichel@collabora.com>2024-12-20 00:36:05 +0100
commit04d9741493e7a1d17d2109f4c9ea21f3314666b4 (patch)
tree4feba54e728726511388457e9a29727c117ef318
parentpower: supply: core: fix build of extension sysfs group if CONFIG_SYSFS=n (diff)
downloadlinux-rng-04d9741493e7a1d17d2109f4c9ea21f3314666b4.tar.xz
linux-rng-04d9741493e7a1d17d2109f4c9ea21f3314666b4.zip
power: supply: Use power_supply_external_power_changed() in __power_supply_changed_work()
The power-supply core is designed so that power-supply driver callbacks such as get_property() and external_power_changed() will not be called until the power-supply's parent driver's probe() function has completed. There is a race where power_supply_changed() can be called for a supplier of a power-supply which is being probed after the device_add() in __power_supply_register() but before the parent driver's probe() function has completed. Hitting this race breaks the power-supply core's design to not call power-supply driver callbacks before probe() completion. This problem is caused by __power_supply_changed_work() calling the external_power_changed() directly rather then going through the power_supply_external_power_changed() helper which correcly checks psy->use_cnt . Switch to using power_supply_external_power_changed() to fix this race. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20241215172133.178460-2-hdegoede@redhat.com Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
-rw-r--r--drivers/power/supply/power_supply_core.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index eeeed1216e22..d0bb52a7a036 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -70,10 +70,8 @@ static int __power_supply_changed_work(struct power_supply *pst, void *data)
{
struct power_supply *psy = data;
- if (__power_supply_is_supplied_by(psy, pst)) {
- if (pst->desc->external_power_changed)
- pst->desc->external_power_changed(pst);
- }
+ if (__power_supply_is_supplied_by(psy, pst))
+ power_supply_external_power_changed(pst);
return 0;
}