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

power_supply: sysfs: Bring back write to writeable properties

The fix for NULL pointer exception related to calling uevent for not
finished probe caused to set all writeable properties as non-writeable.
This was caused by checking if property is writeable before the initial
increase of power supply usage counter and in the same time using
wrapper over property_is_writeable(). The wrapper returns ENODEV if the
usage counter is still 0.

The call trace looked like:
device probe:
power_supply_register()
use_cnt = 0;
device_add()
create sysfs entries
power_supply_attr_is_visible()
power_supply_property_is_writeable()
if (use_cnt == 0) return -ENODEV;
use_cnt++;

Replace the usage of wrapper with direct call to property_is_writeable()
from driver. This should be safe call during device probe because
implementations of this callback just return 0/1 for different
properties and they do not access any of the driver's internal data.

Fixes: 8e59c7f23410 ("power_supply: Fix NULL pointer dereference during bq27x00_battery probe")
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Sebastian Reichel
5c6e3a97 fb323ecc

+6 -1
+1 -1
drivers/power/power_supply_sysfs.c
··· 223 223 224 224 if (property == attrno) { 225 225 if (psy->desc->property_is_writeable && 226 - power_supply_property_is_writeable(psy, property) > 0) 226 + psy->desc->property_is_writeable(psy, property) > 0) 227 227 mode |= S_IWUSR; 228 228 229 229 return mode;
+5
include/linux/power_supply.h
··· 206 206 int (*set_property)(struct power_supply *psy, 207 207 enum power_supply_property psp, 208 208 const union power_supply_propval *val); 209 + /* 210 + * property_is_writeable() will be called during registration 211 + * of power supply. If this happens during device probe then it must 212 + * not access internal data of device (because probe did not end). 213 + */ 209 214 int (*property_is_writeable)(struct power_supply *psy, 210 215 enum power_supply_property psp); 211 216 void (*external_power_changed)(struct power_supply *psy);