2014-10-14 12:21:05

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 0/8] power_supply: Add API for safe access of get_property-like function attrs

Hi,


After fixing issue with referencing old power supply after driver
unbind in charger manager [1] I noticed that the race condition in such
case may still exist. It would be harder to trigger but still possible.

The race is between using a reference to power supply (obtained
with power_supply_get_by_name()) and removing the driver.

This patchset aims to fix the race by introducing wrappers for
accessing the power supply function attributes.

Patch 1 introduces new API. Other patches replace direct calls in
drivers.

Rebased on next-20141007.
Tested on Trats2 board (max77693 + charger manager).


Kindly asking for reviewing/testing the drivers, although the changes
are straightforward.


Best regards,
Krzysztof


[1] https://lkml.org/lkml/2014/10/13/272



Krzysztof Kozlowski (8):
power_supply: Add API for safe access of power supply function attrs
power_supply: sysfs: Use power_supply_*() API for accessing function
attrs
power: 88pm860x_charger: Use power_supply_*() API for accessing
function attrs
power: ab8500: Use power_supply_*() API for accessing function attrs
mfd: ab8500: Use power_supply_*() API for accessing function attrs
power: apm_power: Use power_supply_*() API for accessing function
attrs
power: bq2415x_charger: Use power_supply_*() API for accessing
function attrs
power: charger-manager: Use power_supply_*() API for accessing
function attrs

drivers/mfd/ab8500-sysctrl.c | 7 +++--
drivers/power/88pm860x_charger.c | 13 +++++----
drivers/power/ab8500_btemp.c | 2 +-
drivers/power/ab8500_charger.c | 2 +-
drivers/power/ab8500_fg.c | 2 +-
drivers/power/abx500_chargalg.c | 4 +--
drivers/power/apm_power.c | 4 +--
drivers/power/bq2415x_charger.c | 3 +-
drivers/power/charger-manager.c | 37 +++++++++++++------------
drivers/power/power_supply_core.c | 57 ++++++++++++++++++++++++++++++++++++--
drivers/power/power_supply_sysfs.c | 6 ++--
include/linux/power_supply.h | 16 +++++++++++
12 files changed, 115 insertions(+), 38 deletions(-)

--
1.9.1


2014-10-14 12:21:08

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 1/8] power_supply: Add API for safe access of power supply function attrs

Add simple wrappers for accessing power supply's function attributes:
- get_property -> power_supply_get_property
- set_property -> power_supply_set_property
- property_is_writeable -> power_supply_property_is_writeable
- external_power_changed -> power_supply_external_power_changed
- set_charged -> power_supply_set_charged

This API adds a safe way of accessing a power supply from another
driver. Particularly it solves invalid memory references (and lockup) in
following race condition scenario:

Thread 1: charger manager
Thread 2: power supply driver, used by charger manager

THREAD 1 (charger manager) THREAD 2 (power supply driver)
========================== ==============================
psy = power_supply_get_by_name()
Driver unbind, .remove
power_supply_unregister
Device fully removed
psy->get_property()

The 'get_property' callback is still valid and leads to actual calling of
Thread2->get_property() but now in invalid context because the driver was
unbound.

This could be observed easily with charger manager driver (here compiled
with max17042 fuel gauge):
$ echo "12-0036" > /sys/bus/i2c/drivers/max17042/unbind
$ cat /sys/devices/virtual/power_supply/battery/temp
[ 240.505998] INFO: task cat:1394 blocked for more than 120 seconds.
[ 240.510762] Not tainted 3.17.0-next-20141007-00028-ge60b6dd79570-dirty #183
[ 240.518208] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 240.526025] cat D c0469548 0 1394 1 0x00000000
[ 240.532384] [<c0469548>] (__schedule) from [<c0469d54>] (schedule_preempt_disabled+0x14/0x20)
[ 240.540885] [<c0469d54>] (schedule_preempt_disabled) from [<c046af20>] (mutex_lock_nested+0x1bc/0x458)
[ 240.550171] [<c046af20>] (mutex_lock_nested) from [<c0287a98>] (regmap_read+0x30/0x60)
[ 240.558079] [<c0287a98>] (regmap_read) from [<c032238c>] (max17042_get_property+0x2e8/0x350)
[ 240.566490] [<c032238c>] (max17042_get_property) from [<c0324b60>] (charger_get_property+0x238/0x31c)
[ 240.575688] [<c0324b60>] (charger_get_property) from [<c0320764>] (power_supply_show_property+0x48/0x1e0)
[ 240.585241] [<c0320764>] (power_supply_show_property) from [<c027308c>] (dev_attr_show+0x1c/0x48)
[ 240.594100] [<c027308c>] (dev_attr_show) from [<c0141fb0>] (sysfs_kf_seq_show+0x84/0x104)
[ 240.602251] [<c0141fb0>] (sysfs_kf_seq_show) from [<c0140b18>] (kernfs_seq_show+0x24/0x28)
[ 240.610497] [<c0140b18>] (kernfs_seq_show) from [<c0104574>] (seq_read+0x1b0/0x484)
[ 240.618138] [<c0104574>] (seq_read) from [<c00e1e24>] (vfs_read+0x88/0x144)
[ 240.625127] [<c00e1e24>] (vfs_read) from [<c00e1f20>] (SyS_read+0x40/0x8c)
[ 240.631941] [<c00e1f20>] (SyS_read) from [<c000e760>] (ret_fast_syscall+0x0/0x48)

Or:
[ 17.277605] Division by zero in kernel.
[ 17.280043] CPU: 2 PID: 1384 Comm: cat Not tainted 3.17.0-next-20141007-00028-ge60b6dd79570-dirty #181
[ 17.289348] [<c00140f0>] (unwind_backtrace) from [<c0011228>] (show_stack+0x10/0x14)
[ 17.297055] [<c0011228>] (show_stack) from [<c04680d0>] (dump_stack+0x70/0xbc)
[ 17.304264] [<c04680d0>] (dump_stack) from [<c01f7a28>] (Ldiv0+0x8/0x10)
[ 17.310933] [<c01f7a28>] (Ldiv0) from [<c01f79f8>] (__aeabi_uidivmod+0x8/0x18)
[ 17.318132] [<c01f79f8>] (__aeabi_uidivmod) from [<c0287a84>] (regmap_read+0x1c/0x60)
[ 17.325956] [<c0287a84>] (regmap_read) from [<c0322260>] (max17042_get_property+0x1bc/0x350)
[ 17.334361] [<c0322260>] (max17042_get_property) from [<c0324734>] (charger_get_property+0x198/0x328)
[ 17.343560] [<c0324734>] (charger_get_property) from [<c0320764>] (power_supply_show_property+0x48/0x1e0)
[ 17.353108] [<c0320764>] (power_supply_show_property) from [<c03209d4>] (power_supply_uevent+0x9c/0x1c4)
[ 17.362575] [<c03209d4>] (power_supply_uevent) from [<c02745d0>] (dev_uevent+0xb8/0x1c8)
[ 17.370639] [<c02745d0>] (dev_uevent) from [<c0272c4c>] (uevent_show+0xa8/0x104)
[ 17.378015] [<c0272c4c>] (uevent_show) from [<c027308c>] (dev_attr_show+0x1c/0x48)
[ 17.385579] [<c027308c>] (dev_attr_show) from [<c0141fb0>] (sysfs_kf_seq_show+0x84/0x104)
[ 17.393731] [<c0141fb0>] (sysfs_kf_seq_show) from [<c0140b18>] (kernfs_seq_show+0x24/0x28)
[ 17.401979] [<c0140b18>] (kernfs_seq_show) from [<c0104574>] (seq_read+0x1b0/0x484)
[ 17.409619] [<c0104574>] (seq_read) from [<c00e1e24>] (vfs_read+0x88/0x144)
[ 17.416557] [<c00e1e24>] (vfs_read) from [<c00e1f20>] (SyS_read+0x40/0x8c)
[ 17.423416] [<c00e1f20>] (SyS_read) from [<c000e760>] (ret_fast_syscall+0x0/0x48)
[ 17.430880] power_supply battery: driver failed to report `voltage_now' property: -22

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/power_supply_core.c | 57 +++++++++++++++++++++++++++++++++++++--
include/linux/power_supply.h | 16 +++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 6cb7fe5c022d..8e36986a73e1 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -366,6 +366,56 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
EXPORT_SYMBOL_GPL(power_supply_get_by_phandle);
#endif /* CONFIG_OF */

+int power_supply_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ if (!psy || !psy->dev)
+ return -ENODEV;
+
+ return psy->get_property(psy, psp, val);
+}
+EXPORT_SYMBOL_GPL(power_supply_get_property);
+
+int power_supply_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ if (!psy || !psy->dev || !psy->set_property)
+ return -ENODEV;
+
+ return psy->set_property(psy, psp, val);
+}
+EXPORT_SYMBOL_GPL(power_supply_set_property);
+
+int power_supply_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ if (!psy || !psy->dev || !psy->property_is_writeable)
+ return -ENODEV;
+
+ return psy->property_is_writeable(psy, psp);
+}
+EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
+
+void power_supply_external_power_changed(struct power_supply *psy)
+{
+ if (!psy || !psy->dev || !psy->external_power_changed)
+ return;
+
+ psy->external_power_changed(psy);
+}
+EXPORT_SYMBOL_GPL(power_supply_external_power_changed);
+
+void power_supply_set_charged(struct power_supply *psy)
+{
+ if (!psy || !psy->dev || !psy->set_charged)
+ return;
+
+ psy->set_charged(psy);
+}
+EXPORT_SYMBOL_GPL(power_supply_set_charged);
+
int power_supply_powers(struct power_supply *psy, struct device *dev)
{
return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
@@ -616,13 +666,16 @@ EXPORT_SYMBOL_GPL(power_supply_register_no_ws);

void power_supply_unregister(struct power_supply *psy)
{
+ struct device *dev = psy->dev;
+
cancel_work_sync(&psy->changed_work);
sysfs_remove_link(&psy->dev->kobj, "powers");
+ psy->dev = NULL;
power_supply_remove_triggers(psy);
psy_unregister_cooler(psy);
psy_unregister_thermal(psy);
- device_init_wakeup(psy->dev, false);
- device_unregister(psy->dev);
+ device_init_wakeup(dev, false);
+ device_unregister(dev);
}
EXPORT_SYMBOL_GPL(power_supply_unregister);

diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 3ed049673022..44e749c65505 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -189,6 +189,12 @@ struct power_supply {
size_t num_supplies;
struct device_node *of_node;

+ /*
+ * Functions for drivers implementing power supply class.
+ * These shouldn't be called directly by other drivers for accessing
+ * this power supply. Instead use power_supply_*() functions (for
+ * example power_supply_get_property()).
+ */
int (*get_property)(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val);
@@ -268,6 +274,16 @@ extern int power_supply_is_system_supplied(void);
static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
#endif

+extern int power_supply_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
+extern int power_supply_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val);
+extern int power_supply_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp);
+extern void power_supply_external_power_changed(struct power_supply *psy);
+extern void power_supply_set_charged(struct power_supply *psy);
extern int power_supply_register(struct device *parent,
struct power_supply *psy);
extern int power_supply_register_no_ws(struct device *parent,
--
1.9.1

2014-10-14 12:21:14

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 7/8] power: bq2415x_charger: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/bq2415x_charger.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index d9c457217b6a..81a3a78b92d8 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -816,7 +816,8 @@ static int bq2415x_notifier_call(struct notifier_block *nb,

dev_dbg(bq->dev, "notifier call was called\n");

- ret = psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX,
+ &prop);
if (ret != 0)
return NOTIFY_OK;

--
1.9.1

2014-10-14 12:21:11

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 8/8] power: charger-manager: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/charger-manager.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index b5d272cb7c4a..9e01074d3169 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -112,8 +112,8 @@ static bool is_batt_present(struct charger_manager *cm)
if (!psy)
break;

- ret = psy->get_property(psy,
- POWER_SUPPLY_PROP_PRESENT, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT,
+ &val);
if (ret == 0 && val.intval)
present = true;
break;
@@ -127,8 +127,8 @@ static bool is_batt_present(struct charger_manager *cm)
continue;
}

- ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT,
- &val);
+ ret = power_supply_get_property(psy,
+ POWER_SUPPLY_PROP_PRESENT, &val);
if (ret == 0 && val.intval) {
present = true;
break;
@@ -164,7 +164,8 @@ static bool is_ext_pwr_online(struct charger_manager *cm)
continue;
}

- ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+ &val);
if (ret == 0 && val.intval) {
online = true;
break;
@@ -192,7 +193,7 @@ static int get_batt_uV(struct charger_manager *cm, int *uV)
if (!fuel_gauge)
return -ENODEV;

- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
if (ret)
return ret;
@@ -232,7 +233,8 @@ static bool is_charging(struct charger_manager *cm)
}

/* 2. The charger should be online (ext-power) */
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+ &val);
if (ret) {
dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
cm->desc->psy_charger_stat[i]);
@@ -245,7 +247,8 @@ static bool is_charging(struct charger_manager *cm)
* 3. The charger should not be FULL, DISCHARGING,
* or NOT_CHARGING.
*/
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS,
+ &val);
if (ret) {
dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
cm->desc->psy_charger_stat[i]);
@@ -288,7 +291,7 @@ static bool is_full_charged(struct charger_manager *cm)
val.intval = 0;

/* Not full if capacity of fuel gauge isn't full */
- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_FULL, &val);
if (!ret && val.intval > desc->fullbatt_full_capacity)
return true;
@@ -305,7 +308,7 @@ static bool is_full_charged(struct charger_manager *cm)
if (desc->fullbatt_soc > 0) {
val.intval = 0;

- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CAPACITY, &val);
if (!ret && val.intval >= desc->fullbatt_soc)
return true;
@@ -589,7 +592,7 @@ static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
if (!fuel_gauge)
return -ENODEV;

- return fuel_gauge->get_property(fuel_gauge,
+ return power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_TEMP,
(union power_supply_propval *)temp);
}
@@ -909,7 +912,7 @@ static int charger_get_property(struct power_supply *psy,
ret = -ENODEV;
break;
}
- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CURRENT_NOW, val);
break;
case POWER_SUPPLY_PROP_TEMP:
@@ -928,7 +931,7 @@ static int charger_get_property(struct power_supply *psy,
break;
}

- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CAPACITY, val);
if (ret)
break;
@@ -984,7 +987,7 @@ static int charger_get_property(struct power_supply *psy,
break;
}

- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_NOW,
val);
if (ret) {
@@ -1553,7 +1556,7 @@ static int cm_init_thermal_data(struct charger_manager *cm,
int ret;

/* Verify whether fuel gauge provides battery temperature */
- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_TEMP, &val);

if (!ret) {
@@ -1845,13 +1848,13 @@ static int charger_manager_probe(struct platform_device *pdev)
cm->charger_psy.num_properties = psy_default.num_properties;

/* Find which optional psy-properties are available */
- if (!fuel_gauge->get_property(fuel_gauge,
+ if (!power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
cm->charger_psy.properties[cm->charger_psy.num_properties] =
POWER_SUPPLY_PROP_CHARGE_NOW;
cm->charger_psy.num_properties++;
}
- if (!fuel_gauge->get_property(fuel_gauge,
+ if (!power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CURRENT_NOW,
&val)) {
cm->charger_psy.properties[cm->charger_psy.num_properties] =
--
1.9.1

2014-10-14 12:22:03

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 6/8] power: apm_power: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/apm_power.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index 39763015b360..2206f9ff6488 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -15,10 +15,10 @@
#include <linux/apm-emulation.h>


-#define PSY_PROP(psy, prop, val) (psy->get_property(psy, \
+#define PSY_PROP(psy, prop, val) (power_supply_get_property(psy, \
POWER_SUPPLY_PROP_##prop, val))

-#define _MPSY_PROP(prop, val) (main_battery->get_property(main_battery, \
+#define _MPSY_PROP(prop, val) (power_supply_get_property(main_battery, \
prop, val))

#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
--
1.9.1

2014-10-14 12:22:33

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 4/8] power: ab8500: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/ab8500_btemp.c | 2 +-
drivers/power/ab8500_charger.c | 2 +-
drivers/power/ab8500_fg.c | 2 +-
drivers/power/abx500_chargalg.c | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 7f9a4547dccd..8161960ee78c 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -938,7 +938,7 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
enum power_supply_property prop;
prop = ext->properties[j];

- if (ext->get_property(ext, prop, &ret))
+ if (power_supply_get_property(ext, prop, &ret))
continue;

switch (prop) {
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 19110aa613a1..38d61523227f 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -1957,7 +1957,7 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
enum power_supply_property prop;
prop = ext->properties[j];

- if (ext->get_property(ext, prop, &ret))
+ if (power_supply_get_property(ext, prop, &ret))
continue;

switch (prop) {
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 217da4b2ca86..ed2aca42f968 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2199,7 +2199,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
enum power_supply_property prop;
prop = ext->properties[j];

- if (ext->get_property(ext, prop, &ret))
+ if (power_supply_get_property(ext, prop, &ret))
continue;

switch (prop) {
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 6d2723664a01..f3d9dbac3568 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1001,7 +1001,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
* property because of handling that sysfs entry on its own, this is
* the place to get the battery capacity.
*/
- if (!ext->get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
+ if (!power_supply_get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
di->batt_data.percent = ret.intval;
capacity_updated = true;
}
@@ -1019,7 +1019,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
ext->type == POWER_SUPPLY_TYPE_USB)
di->usb_chg = psy_to_ux500_charger(ext);

- if (ext->get_property(ext, prop, &ret))
+ if (power_supply_get_property(ext, prop, &ret))
continue;
switch (prop) {
case POWER_SUPPLY_PROP_PRESENT:
--
1.9.1

2014-10-14 12:22:31

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 5/8] mfd: ab8500: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/mfd/ab8500-sysctrl.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index 8e0dae59844d..93b2d2c32ca3 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -49,7 +49,8 @@ static void ab8500_power_off(void)
if (!psy)
continue;

- ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+ &val);

if (!ret && val.intval) {
charger_present = true;
@@ -63,8 +64,8 @@ static void ab8500_power_off(void)
/* Check if battery is known */
psy = power_supply_get_by_name("ab8500_btemp");
if (psy) {
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY,
- &val);
+ ret = power_supply_get_property(psy,
+ POWER_SUPPLY_PROP_TECHNOLOGY, &val);
if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) {
printk(KERN_INFO
"Charger \"%s\" is connected with known battery."
--
1.9.1

2014-10-14 12:22:28

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 3/8] power: 88pm860x_charger: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property
- set_property -> power_supply_set_property

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/88pm860x_charger.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index de029bbc1cc1..534b3e2e3487 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -296,12 +296,13 @@ static int set_charging_fsm(struct pm860x_charger_info *info)
psy = power_supply_get_by_name(pm860x_supplied_to[0]);
if (!psy)
return -EINVAL;
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &data);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ &data);
if (ret)
return ret;
vbatt = data.intval / 1000;

- ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
if (ret)
return ret;

@@ -430,7 +431,7 @@ static irqreturn_t pm860x_temp_handler(int irq, void *data)
psy = power_supply_get_by_name(pm860x_supplied_to[0]);
if (!psy)
goto out;
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp);
if (ret)
goto out;
value = temp.intval / 10;
@@ -485,7 +486,8 @@ static irqreturn_t pm860x_done_handler(int irq, void *data)
psy = power_supply_get_by_name(pm860x_supplied_to[0]);
if (!psy)
goto out;
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+ ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ &val);
if (ret)
goto out;
vbatt = val.intval / 1000;
@@ -500,7 +502,8 @@ static irqreturn_t pm860x_done_handler(int irq, void *data)
if (ret < 0)
goto out;
if (vbatt > CHARGE_THRESHOLD && ret & STATUS2_CHG)
- psy->set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &val);
+ power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL,
+ &val);

out:
mutex_unlock(&info->lock);
--
1.9.1

2014-10-14 12:23:29

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 2/8] power_supply: sysfs: Use power_supply_*() API for accessing function attrs

Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe access access in case of unregistering the power
supply (.e.g by removing the driver). Replace:
- get_property -> power_supply_get_property
- set_property -> power_supply_set_property
- property_is_writeable -> power_supply_property_is_writeable

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/power/power_supply_sysfs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 62653f50a524..f817aab80813 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -76,7 +76,7 @@ static ssize_t power_supply_show_property(struct device *dev,
if (off == POWER_SUPPLY_PROP_TYPE) {
value.intval = psy->type;
} else {
- ret = psy->get_property(psy, off, &value);
+ ret = power_supply_get_property(psy, off, &value);

if (ret < 0) {
if (ret == -ENODATA)
@@ -125,7 +125,7 @@ static ssize_t power_supply_store_property(struct device *dev,

value.intval = long_val;

- ret = psy->set_property(psy, off, &value);
+ ret = power_supply_set_property(psy, off, &value);
if (ret < 0)
return ret;

@@ -223,7 +223,7 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj,

if (property == attrno) {
if (psy->property_is_writeable &&
- psy->property_is_writeable(psy, property) > 0)
+ power_supply_property_is_writeable(psy, property) > 0)
mode |= S_IWUSR;

return mode;
--
1.9.1

2014-10-15 02:22:17

by Jonghwa Lee

[permalink] [raw]
Subject: Re: [PATCH 0/8] power_supply: Add API for safe access of get_property-like function attrs

Hi,
On 2014년 10월 14일 21:20, Krzysztof Kozlowski wrote:

> Hi,
>
>
> After fixing issue with referencing old power supply after driver
> unbind in charger manager [1] I noticed that the race condition in such
> case may still exist. It would be harder to trigger but still possible.
>
> The race is between using a reference to power supply (obtained
> with power_supply_get_by_name()) and removing the driver.
>
> This patchset aims to fix the race by introducing wrappers for
> accessing the power supply function attributes.
>
> Patch 1 introduces new API. Other patches replace direct calls in
> drivers.
>
> Rebased on next-20141007.
> Tested on Trats2 board (max77693 + charger manager).
>
>
> Kindly asking for reviewing/testing the drivers, although the changes
> are straightforward.
>


Looks good to me, but need someone to comment on this.

Acked-by : Jonghwa Lee <[email protected]>

Thanks,
Jonghwa

>
> Best regards,
> Krzysztof
>
>
> [1] https://lkml.org/lkml/2014/10/13/272
>
>
>
> Krzysztof Kozlowski (8):
> power_supply: Add API for safe access of power supply function attrs
> power_supply: sysfs: Use power_supply_*() API for accessing function
> attrs
> power: 88pm860x_charger: Use power_supply_*() API for accessing
> function attrs
> power: ab8500: Use power_supply_*() API for accessing function attrs
> mfd: ab8500: Use power_supply_*() API for accessing function attrs
> power: apm_power: Use power_supply_*() API for accessing function
> attrs
> power: bq2415x_charger: Use power_supply_*() API for accessing
> function attrs
> power: charger-manager: Use power_supply_*() API for accessing
> function attrs
>
> drivers/mfd/ab8500-sysctrl.c | 7 +++--
> drivers/power/88pm860x_charger.c | 13 +++++----
> drivers/power/ab8500_btemp.c | 2 +-
> drivers/power/ab8500_charger.c | 2 +-
> drivers/power/ab8500_fg.c | 2 +-
> drivers/power/abx500_chargalg.c | 4 +--
> drivers/power/apm_power.c | 4 +--
> drivers/power/bq2415x_charger.c | 3 +-
> drivers/power/charger-manager.c | 37 +++++++++++++------------
> drivers/power/power_supply_core.c | 57 ++++++++++++++++++++++++++++++++++++--
> drivers/power/power_supply_sysfs.c | 6 ++--
> include/linux/power_supply.h | 16 +++++++++++
> 12 files changed, 115 insertions(+), 38 deletions(-)
>

2014-10-15 09:07:19

by Lee Jones

[permalink] [raw]
Subject: Re: [PATCH 5/8] mfd: ab8500: Use power_supply_*() API for accessing function attrs

On Tue, 14 Oct 2014, Krzysztof Kozlowski wrote:

> Replace direct calls to power supply function attributes with wrappers.
> Wrappers provide safe access access in case of unregistering the power
> supply (.e.g by removing the driver). Replace:
> - get_property -> power_supply_get_property
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>
> ---
> drivers/mfd/ab8500-sysctrl.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)

Acked-by: Lee Jones <[email protected]>

> diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
> index 8e0dae59844d..93b2d2c32ca3 100644
> --- a/drivers/mfd/ab8500-sysctrl.c
> +++ b/drivers/mfd/ab8500-sysctrl.c
> @@ -49,7 +49,8 @@ static void ab8500_power_off(void)
> if (!psy)
> continue;
>
> - ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
> + ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
> + &val);
>
> if (!ret && val.intval) {
> charger_present = true;
> @@ -63,8 +64,8 @@ static void ab8500_power_off(void)
> /* Check if battery is known */
> psy = power_supply_get_by_name("ab8500_btemp");
> if (psy) {
> - ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY,
> - &val);
> + ret = power_supply_get_property(psy,
> + POWER_SUPPLY_PROP_TECHNOLOGY, &val);
> if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) {
> printk(KERN_INFO
> "Charger \"%s\" is connected with known battery."

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2014-10-15 10:30:41

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 1/8] power_supply: Add API for safe access of power supply function attrs

On Tue 2014-10-14 14:20:39, Krzysztof Kozlowski wrote:
> Add simple wrappers for accessing power supply's function attributes:
> - get_property -> power_supply_get_property
> - set_property -> power_supply_set_property
> - property_is_writeable -> power_supply_property_is_writeable
> - external_power_changed -> power_supply_external_power_changed
> - set_charged -> power_supply_set_charged
>
> This API adds a safe way of accessing a power supply from another
> driver. Particularly it solves invalid memory references (and lockup) in
> following race condition scenario:
>
> Thread 1: charger manager
> Thread 2: power supply driver, used by charger manager
>
> THREAD 1 (charger manager) THREAD 2 (power supply driver)
> ========================== ==============================
> psy = power_supply_get_by_name()
> Driver unbind, .remove
> power_supply_unregister
> Device fully removed
> psy->get_property()
>
> The 'get_property' callback is still valid and leads to actual calling of
> Thread2->get_property() but now in invalid context because the driver was
> unbound.
>
> This could be observed easily with charger manager driver (here compiled
> with max17042 fuel gauge):
> $ echo "12-0036" > /sys/bus/i2c/drivers/max17042/unbind
> $ cat /sys/devices/virtual/power_supply/battery/temp
> [ 240.505998] INFO: task cat:1394 blocked for more than 120 seconds.
> [ 240.510762] Not tainted 3.17.0-next-20141007-00028-ge60b6dd79570-dirty #183
> [ 240.518208] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [ 240.526025] cat D c0469548 0 1394 1 0x00000000
> [ 240.532384] [<c0469548>] (__schedule) from [<c0469d54>] (schedule_preempt_disabled+0x14/0x20)
> [ 240.540885] [<c0469d54>] (schedule_preempt_disabled) from [<c046af20>] (mutex_lock_nested+0x1bc/0x458)
> [ 240.550171] [<c046af20>] (mutex_lock_nested) from [<c0287a98>] (regmap_read+0x30/0x60)
> [ 240.558079] [<c0287a98>] (regmap_read) from [<c032238c>] (max17042_get_property+0x2e8/0x350)
> [ 240.566490] [<c032238c>] (max17042_get_property) from [<c0324b60>] (charger_get_property+0x238/0x31c)
> [ 240.575688] [<c0324b60>] (charger_get_property) from [<c0320764>] (power_supply_show_property+0x48/0x1e0)
> [ 240.585241] [<c0320764>] (power_supply_show_property) from [<c027308c>] (dev_attr_show+0x1c/0x48)
> [ 240.594100] [<c027308c>] (dev_attr_show) from [<c0141fb0>] (sysfs_kf_seq_show+0x84/0x104)
> [ 240.602251] [<c0141fb0>] (sysfs_kf_seq_show) from [<c0140b18>] (kernfs_seq_show+0x24/0x28)
> [ 240.610497] [<c0140b18>] (kernfs_seq_show) from [<c0104574>] (seq_read+0x1b0/0x484)
> [ 240.618138] [<c0104574>] (seq_read) from [<c00e1e24>] (vfs_read+0x88/0x144)
> [ 240.625127] [<c00e1e24>] (vfs_read) from [<c00e1f20>] (SyS_read+0x40/0x8c)
> [ 240.631941] [<c00e1f20>] (SyS_read) from [<c000e760>] (ret_fast_syscall+0x0/0x48)
>
> Or:
> [ 17.277605] Division by zero in kernel.
> [ 17.280043] CPU: 2 PID: 1384 Comm: cat Not tainted 3.17.0-next-20141007-00028-ge60b6dd79570-dirty #181
> [ 17.289348] [<c00140f0>] (unwind_backtrace) from [<c0011228>] (show_stack+0x10/0x14)
> [ 17.297055] [<c0011228>] (show_stack) from [<c04680d0>] (dump_stack+0x70/0xbc)
> [ 17.304264] [<c04680d0>] (dump_stack) from [<c01f7a28>] (Ldiv0+0x8/0x10)
> [ 17.310933] [<c01f7a28>] (Ldiv0) from [<c01f79f8>] (__aeabi_uidivmod+0x8/0x18)
> [ 17.318132] [<c01f79f8>] (__aeabi_uidivmod) from [<c0287a84>] (regmap_read+0x1c/0x60)
> [ 17.325956] [<c0287a84>] (regmap_read) from [<c0322260>] (max17042_get_property+0x1bc/0x350)
> [ 17.334361] [<c0322260>] (max17042_get_property) from [<c0324734>] (charger_get_property+0x198/0x328)
> [ 17.343560] [<c0324734>] (charger_get_property) from [<c0320764>] (power_supply_show_property+0x48/0x1e0)
> [ 17.353108] [<c0320764>] (power_supply_show_property) from [<c03209d4>] (power_supply_uevent+0x9c/0x1c4)
> [ 17.362575] [<c03209d4>] (power_supply_uevent) from [<c02745d0>] (dev_uevent+0xb8/0x1c8)
> [ 17.370639] [<c02745d0>] (dev_uevent) from [<c0272c4c>] (uevent_show+0xa8/0x104)
> [ 17.378015] [<c0272c4c>] (uevent_show) from [<c027308c>] (dev_attr_show+0x1c/0x48)
> [ 17.385579] [<c027308c>] (dev_attr_show) from [<c0141fb0>] (sysfs_kf_seq_show+0x84/0x104)
> [ 17.393731] [<c0141fb0>] (sysfs_kf_seq_show) from [<c0140b18>] (kernfs_seq_show+0x24/0x28)
> [ 17.401979] [<c0140b18>] (kernfs_seq_show) from [<c0104574>] (seq_read+0x1b0/0x484)
> [ 17.409619] [<c0104574>] (seq_read) from [<c00e1e24>] (vfs_read+0x88/0x144)
> [ 17.416557] [<c00e1e24>] (vfs_read) from [<c00e1f20>] (SyS_read+0x40/0x8c)
> [ 17.423416] [<c00e1f20>] (SyS_read) from [<c000e760>] (ret_fast_syscall+0x0/0x48)
> [ 17.430880] power_supply battery: driver failed to report `voltage_now' property: -22
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>

Acked-by: Pavel Machek <[email protected]>

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2014-10-15 10:32:21

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 2/8] power_supply: sysfs: Use power_supply_*() API for accessing function attrs

On Tue 2014-10-14 14:20:40, Krzysztof Kozlowski wrote:
> Replace direct calls to power supply function attributes with wrappers.
> Wrappers provide safe access access in case of unregistering the power
> supply (.e.g by removing the driver). Replace:
> - get_property -> power_supply_get_property
> - set_property -> power_supply_set_property
> - property_is_writeable -> power_supply_property_is_writeable
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>

Acked-by: Pavel Machek <[email protected]>

> @@ -76,7 +76,7 @@ static ssize_t power_supply_show_property(struct device *dev,
> if (off == POWER_SUPPLY_PROP_TYPE) {
> value.intval = psy->type;
> } else {
> - ret = psy->get_property(psy, off, &value);
> + ret = power_supply_get_property(psy, off, &value);
>

One thing.. Your power_supply_get_property (and friends) check for psy
== NULL. Is it neccessary / good idea? As far as I can tell, it should
not really be NULL...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2014-10-15 10:33:09

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 3/8] power: 88pm860x_charger: Use power_supply_*() API for accessing function attrs

On Tue 2014-10-14 14:20:41, Krzysztof Kozlowski wrote:
> Replace direct calls to power supply function attributes with wrappers.
> Wrappers provide safe access access in case of unregistering the power
> supply (.e.g by removing the driver). Replace:
> - get_property -> power_supply_get_property
> - set_property -> power_supply_set_property
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>

Acked-by: Pavel Machek <[email protected]>

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2014-10-15 10:35:06

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 0/8] power_supply: Add API for safe access of get_property-like function attrs

Hi!

> Kindly asking for reviewing/testing the drivers, although the changes
> are straightforward.

You can add

Acked-by: Pavel Machek <[email protected]>

to whole series.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2014-10-15 10:50:07

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH 2/8] power_supply: sysfs: Use power_supply_*() API for accessing function attrs

On śro, 2014-10-15 at 12:32 +0200, Pavel Machek wrote:
> On Tue 2014-10-14 14:20:40, Krzysztof Kozlowski wrote:
> > Replace direct calls to power supply function attributes with wrappers.
> > Wrappers provide safe access access in case of unregistering the power
> > supply (.e.g by removing the driver). Replace:
> > - get_property -> power_supply_get_property
> > - set_property -> power_supply_set_property
> > - property_is_writeable -> power_supply_property_is_writeable
> >
> > Signed-off-by: Krzysztof Kozlowski <[email protected]>
>
> Acked-by: Pavel Machek <[email protected]>

Thanks for looking at patches.


> > @@ -76,7 +76,7 @@ static ssize_t power_supply_show_property(struct device *dev,
> > if (off == POWER_SUPPLY_PROP_TYPE) {
> > value.intval = psy->type;
> > } else {
> > - ret = psy->get_property(psy, off, &value);
> > + ret = power_supply_get_property(psy, off, &value);
> >
>
> One thing.. Your power_supply_get_property (and friends) check for psy
> == NULL. Is it neccessary / good idea? As far as I can tell, it should
> not really be NULL...

It is not necessary. I thought it would be a good behavior of such
exported function. You're right that this shouldn't be NULL especially
because previously it was dereferenced.

Other existing power supply exported functions don't check this so maybe
I shouldn't introduce inconsistency.

I'll remove the check and re-spin. I'll found ugly typos in commit
message anyway.

Best regards,
Krzysztof

2014-10-15 12:19:33

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 2/8] power_supply: sysfs: Use power_supply_*() API for accessing function attrs


> > > @@ -76,7 +76,7 @@ static ssize_t power_supply_show_property(struct device *dev,
> > > if (off == POWER_SUPPLY_PROP_TYPE) {
> > > value.intval = psy->type;
> > > } else {
> > > - ret = psy->get_property(psy, off, &value);
> > > + ret = power_supply_get_property(psy, off, &value);
> > >
> >
> > One thing.. Your power_supply_get_property (and friends) check for psy
> > == NULL. Is it neccessary / good idea? As far as I can tell, it should
> > not really be NULL...
>
> It is not necessary. I thought it would be a good behavior of such
> exported function. You're right that this shouldn't be NULL especially
> because previously it was dereferenced.
>
> Other existing power supply exported functions don't check this so maybe
> I shouldn't introduce inconsistency.
>
> I'll remove the check and re-spin. I'll found ugly typos in commit
> message anyway.

Thanks!
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2014-10-28 09:59:00

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 4/8] power: ab8500: Use power_supply_*() API for accessing function attrs

On Tue, Oct 14, 2014 at 2:20 PM, Krzysztof Kozlowski
<[email protected]> wrote:

> Replace direct calls to power supply function attributes with wrappers.
> Wrappers provide safe access access in case of unregistering the power
> supply (.e.g by removing the driver). Replace:
> - get_property -> power_supply_get_property
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij