* [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply
@ 2015-01-05 15:47 Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 01/19] power_supply: Add driver private data Krzysztof Kozlowski
` (19 more replies)
0 siblings, 20 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This is RFC, please don't apply yet but let me know if this approach
is OK.
TLDR
====
Patchset tries to fix following race scenario:
Thread 1: charger manager, CONSUMER
Thread 2: power supply driver, PROVIDER
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()
To properly fix the race the patchset:
1. Adds power_supply_get_property()-like API for safe access by consumer.
2. Moves ownership of power_supply structure from driver (provider) to
power supply core.
3. Adds power_supply_put() which will reclaim memory.
Description
===========
This is a little different than my previous approaches [1][2] for fixing
usage of power supply by some consumer, if driver implementing it is
unbound.
The patchset is quite big and touches power supply API so a lot of
changes in drivers are needed. These changes *are not finished yet*.
I've done them only for:
- bq24190_charger.c
- charger-manager.c
- max14577_charger.c
- max17040_battery.c
- max17042_battery.c
- sbs-battery.c
- tps65090-charger.c
So allyesconfig won't build.
If this approach is OK, I'll prepare full patchset changing all the
drivers.
My previous approach [1][2] limited the race but did not close it.
Still the consumer of power supply by calling power_supply_get_propert(psy...)
may reference invalid memory because the producer freed it.
Actually, because struct power_supply is exposed to consumers, the
core should be the owner of it. This is accomplished in patch 11/19
("power_supply: Change ownership from driver to core").
What the patchset does in steps
===============================
1. Some preparation steps are necessary - patch 1 and 2. The driver
implementing power supply won't be able to fill structure before
calling power_supply_register(). So 'power_supply_config'
is introduced in patch 2 ("power_supply: Move run-time configuration
to separate structure"). Unfortunately this touches all drivers.
2. Safe API wrappers (and usage counter) are added (power_supply_*()).
3. Patch 11: ownership of 'struct power_supply' is moved from driver
to the core.
4. power_supply_put() is added which reclaims resources.
The patchset is rebased on next-20141226. It should be pulled at once.
Bisectability is preserved.
Changes since v1
================
1. Add new patches (1, 2, 11, 19).
2. Preserved ack-s where there weren't any changes.
3. Patch 3: Add use counter.
4. Patch 3: Don't add wrapper for set_charged() because already exists
one.
[1] https://lkml.org/lkml/2014/11/4/527
[2] https://lkml.org/lkml/2014/10/16/89
Best regards,
Krzysztof
Krzysztof Kozlowski (19):
power_supply: Add driver private data
power_supply: Move run-time configuration to separate structure
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
power_supply: Change ownership from driver to core
power_supply: Add power_supply_put for decrementing device reference
counter
power: charger-manager: Decrement the power supply's device reference
counter
x86/olpc/xo1/sci: Use newly added power_supply_put API
x86/olpc/xo15/sci: Use newly added power_supply_put API
power: 88pm860x_charger: Decrement the power supply's device reference
counter
power: bq2415x_charger: Decrement the power supply's device reference
counter
mfd: ab8500: Decrement the power supply's device reference counter
arm: mach-pxa: Decrement the power supply's device reference counter
arch/arm/mach-pxa/raumfeld.c | 4 +-
arch/x86/platform/olpc/olpc-xo1-sci.c | 4 +-
arch/x86/platform/olpc/olpc-xo15-sci.c | 4 +-
drivers/acpi/battery.c | 3 +-
drivers/mfd/ab8500-sysctrl.c | 9 +-
drivers/power/88pm860x_charger.c | 24 ++--
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 | 9 +-
drivers/power/bq24190_charger.c | 103 ++++++++-------
drivers/power/charger-manager.c | 158 +++++++++++++----------
drivers/power/max14577_charger.c | 34 ++---
drivers/power/max17040_battery.c | 31 ++---
drivers/power/max17042_battery.c | 45 ++++---
drivers/power/power_supply_core.c | 223 ++++++++++++++++++++++++---------
drivers/power/power_supply_leds.c | 25 ++--
drivers/power/power_supply_sysfs.c | 24 ++--
drivers/power/sbs-battery.c | 71 +++++------
drivers/power/tps65090-charger.c | 43 ++++---
include/linux/power/charger-manager.h | 3 +-
include/linux/power_supply.h | 70 ++++++++---
24 files changed, 562 insertions(+), 339 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 01/19] power_supply: Add driver private data
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 02/19] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
` (18 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Allow drivers to store private data inside power_supply structure for
later usage in power supply operations.
Usage of driver private data is necessary to access driver's state
container object from power supply calls (like get_property()) if struct
'power_supply' is a stored there as a pointer, for example:
struct some_driver_info {
struct i2c_client *client;
struct power_supply *power_supply;
...
}
In such case one cannot use container_of() and must store pointer to
state container as private data.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
drivers/power/power_supply_core.c | 6 ++++++
include/linux/power_supply.h | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 694e8cddd5c1..84ef3f40e7bf 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -629,6 +629,12 @@ void power_supply_unregister(struct power_supply *psy)
}
EXPORT_SYMBOL_GPL(power_supply_unregister);
+void *power_supply_get_drvdata(struct power_supply *psy)
+{
+ return psy->drv_data;
+}
+EXPORT_SYMBOL_GPL(power_supply_get_drvdata);
+
static int __init power_supply_class_init(void)
{
power_supply_class = class_create(THIS_MODULE, "power_supply");
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 096dbced02ac..a5743f24e03e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -209,6 +209,9 @@ struct power_supply {
/* For APM emulation, think legacy userspace. */
int use_for_apm;
+ /* Driver private data */
+ void *drv_data;
+
/* private */
struct device *dev;
struct work_struct changed_work;
@@ -281,6 +284,7 @@ extern int power_supply_register_no_ws(struct device *parent,
extern void power_supply_unregister(struct power_supply *psy);
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
+extern void *power_supply_get_drvdata(struct power_supply *psy);
/* For APM emulation, think legacy userspace. */
extern struct class *power_supply_class;
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 02/19] power_supply: Move run-time configuration to separate structure
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 01/19] power_supply: Add driver private data Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 03/19] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
` (17 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Add new structure 'power_supply_config' for holding run-time
initiazation data like of_node, supplies and private driver data.
When registering the power supply this config should be used instead of
directly initializing 'struct power_supply'.
This allows changing the ownership of power_supply structure from driver
to the power supply core in next patches.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
drivers/acpi/battery.c | 3 ++-
drivers/power/bq24190_charger.c | 4 ++--
drivers/power/charger-manager.c | 2 +-
drivers/power/max14577_charger.c | 2 +-
drivers/power/max17040_battery.c | 2 +-
drivers/power/max17042_battery.c | 2 +-
drivers/power/power_supply_core.c | 20 +++++++++++++++-----
drivers/power/sbs-battery.c | 6 ++++--
drivers/power/tps65090-charger.c | 2 +-
include/linux/power_supply.h | 16 ++++++++++++++--
10 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index d98ba4355819..fd8c06f492a1 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -624,7 +624,8 @@ static int sysfs_add_battery(struct acpi_battery *battery)
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat.get_property = acpi_battery_get_property;
- result = power_supply_register_no_ws(&battery->device->dev, &battery->bat);
+ result = power_supply_register_no_ws(&battery->device->dev,
+ &battery->bat, NULL);
if (result)
return result;
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c
index e4c95e1a6733..f736c4c7c8fe 100644
--- a/drivers/power/bq24190_charger.c
+++ b/drivers/power/bq24190_charger.c
@@ -1418,7 +1418,7 @@ static int bq24190_probe(struct i2c_client *client,
bq24190_charger_init(&bdi->charger);
- ret = power_supply_register(dev, &bdi->charger);
+ ret = power_supply_register(dev, &bdi->charger, NULL);
if (ret) {
dev_err(dev, "Can't register charger\n");
goto out2;
@@ -1426,7 +1426,7 @@ static int bq24190_probe(struct i2c_client *client,
bq24190_battery_init(&bdi->battery);
- ret = power_supply_register(dev, &bdi->battery);
+ ret = power_supply_register(dev, &bdi->battery, NULL);
if (ret) {
dev_err(dev, "Can't register battery\n");
goto out3;
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index ae1032dba86f..034c77bf0fc0 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1873,7 +1873,7 @@ static int charger_manager_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
- ret = power_supply_register(NULL, &cm->charger_psy);
+ ret = power_supply_register(NULL, &cm->charger_psy, NULL);
if (ret) {
dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n",
cm->charger_psy.name);
diff --git a/drivers/power/max14577_charger.c b/drivers/power/max14577_charger.c
index ef4103ee6021..8f113ed73e6c 100644
--- a/drivers/power/max14577_charger.c
+++ b/drivers/power/max14577_charger.c
@@ -562,7 +562,7 @@ static int max14577_charger_probe(struct platform_device *pdev)
return ret;
}
- ret = power_supply_register(&pdev->dev, &chg->charger);
+ ret = power_supply_register(&pdev->dev, &chg->charger, NULL);
if (ret) {
dev_err(&pdev->dev, "failed: power supply register\n");
goto err;
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 14d44706327b..bf42c57a4247 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -223,7 +223,7 @@ static int max17040_probe(struct i2c_client *client,
chip->battery.properties = max17040_battery_props;
chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props);
- ret = power_supply_register(&client->dev, &chip->battery);
+ ret = power_supply_register(&client->dev, &chip->battery, NULL);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
return ret;
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 1da6c5fbdff5..c62d1428803e 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -733,7 +733,7 @@ static int max17042_probe(struct i2c_client *client,
regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
}
- ret = power_supply_register(&client->dev, &chip->battery);
+ ret = power_supply_register(&client->dev, &chip->battery, NULL);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
return ret;
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 84ef3f40e7bf..b748391c3e17 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -536,7 +536,9 @@ static void psy_unregister_cooler(struct power_supply *psy)
#endif
static int __power_supply_register(struct device *parent,
- struct power_supply *psy, bool ws)
+ struct power_supply *psy,
+ const struct power_supply_config *cfg,
+ bool ws)
{
struct device *dev;
int rc;
@@ -553,6 +555,12 @@ static int __power_supply_register(struct device *parent,
dev->release = power_supply_dev_release;
dev_set_drvdata(dev, psy);
psy->dev = dev;
+ if (cfg) {
+ psy->drv_data = cfg->drv_data;
+ psy->of_node = cfg->of_node;
+ psy->supplied_to = cfg->supplied_to;
+ psy->num_supplicants = cfg->num_supplicants;
+ }
rc = dev_set_name(dev, "%s", psy->name);
if (rc)
@@ -605,15 +613,17 @@ dev_set_name_failed:
return rc;
}
-int power_supply_register(struct device *parent, struct power_supply *psy)
+int power_supply_register(struct device *parent, struct power_supply *psy,
+ const struct power_supply_config *cfg)
{
- return __power_supply_register(parent, psy, true);
+ return __power_supply_register(parent, psy, cfg, true);
}
EXPORT_SYMBOL_GPL(power_supply_register);
-int power_supply_register_no_ws(struct device *parent, struct power_supply *psy)
+int power_supply_register_no_ws(struct device *parent, struct power_supply *psy,
+ const struct power_supply_config *cfg)
{
- return __power_supply_register(parent, psy, false);
+ return __power_supply_register(parent, psy, cfg, false);
}
EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index c7b7b4018df3..879f1448fc4a 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -801,6 +801,7 @@ static int sbs_probe(struct i2c_client *client,
{
struct sbs_info *chip;
struct sbs_platform_data *pdata = client->dev.platform_data;
+ struct power_supply_config psy_cfg = {};
int rc;
int irq;
char *name;
@@ -825,7 +826,7 @@ static int sbs_probe(struct i2c_client *client,
chip->power_supply.properties = sbs_properties;
chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
chip->power_supply.get_property = sbs_get_property;
- chip->power_supply.of_node = client->dev.of_node;
+ psy_cfg.of_node = client->dev.of_node;
/* ignore first notification of external change, it is generated
* from the power_supply_register call back
*/
@@ -892,7 +893,8 @@ skip_gpio:
goto exit_psupply;
}
- rc = power_supply_register(&client->dev, &chip->power_supply);
+ rc = power_supply_register(&client->dev, &chip->power_supply,
+ &psy_cfg);
if (rc) {
dev_err(&client->dev,
"%s: Failed to register power supply\n", __func__);
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 0f4e5971dff5..37629affcd34 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -268,7 +268,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
cdata->ac.num_supplicants = pdata->num_supplicants;
cdata->ac.of_node = pdev->dev.of_node;
- ret = power_supply_register(&pdev->dev, &cdata->ac);
+ ret = power_supply_register(&pdev->dev, &cdata->ac, NULL);
if (ret) {
dev_err(&pdev->dev, "failed: power supply register\n");
return ret;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index a5743f24e03e..b203a26d5c54 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -176,6 +176,16 @@ union power_supply_propval {
struct device;
struct device_node;
+/* Power supply instance specific configuration */
+struct power_supply_config {
+ struct device_node *of_node;
+ /* Driver private data */
+ void *drv_data;
+
+ char **supplied_to;
+ size_t num_supplicants;
+};
+
struct power_supply {
const char *name;
enum power_supply_type type;
@@ -278,9 +288,11 @@ static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
#endif
extern int power_supply_register(struct device *parent,
- struct power_supply *psy);
+ struct power_supply *psy,
+ const struct power_supply_config *cfg);
extern int power_supply_register_no_ws(struct device *parent,
- struct power_supply *psy);
+ struct power_supply *psy,
+ const struct power_supply_config *cfg);
extern void power_supply_unregister(struct power_supply *psy);
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 03/19] power_supply: Add API for safe access of power supply function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 01/19] power_supply: Add driver private data Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 02/19] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 04/19] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
` (16 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
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
This API along with usage counter adds a safe way of accessing a power
supply from another driver. If power supply is unregistered after
obtaining reference to it by some driver, then the API wrappers won't be
executed in invalid (freed) context.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
drivers/power/power_supply_core.c | 47 ++++++++++++++++++++++++++++++++++++++-
include/linux/power_supply.h | 16 +++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index b748391c3e17..fdec3c29fc3c 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -314,7 +314,8 @@ EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
int power_supply_set_battery_charged(struct power_supply *psy)
{
- if (psy->type == POWER_SUPPLY_TYPE_BATTERY && psy->set_charged) {
+ if (psy->use_cnt >= 0 && psy->type == POWER_SUPPLY_TYPE_BATTERY &&
+ psy->set_charged) {
psy->set_charged(psy);
return 0;
}
@@ -366,6 +367,47 @@ 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->use_cnt <= 0)
+ 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->use_cnt <= 0 || !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->use_cnt <= 0 || !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->use_cnt <= 0 || !psy->external_power_changed)
+ return;
+
+ psy->external_power_changed(psy);
+}
+EXPORT_SYMBOL_GPL(power_supply_external_power_changed);
+
int power_supply_powers(struct power_supply *psy, struct device *dev)
{
return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
@@ -555,6 +597,7 @@ static int __power_supply_register(struct device *parent,
dev->release = power_supply_dev_release;
dev_set_drvdata(dev, psy);
psy->dev = dev;
+ psy->use_cnt++;
if (cfg) {
psy->drv_data = cfg->drv_data;
psy->of_node = cfg->of_node;
@@ -629,6 +672,8 @@ EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
void power_supply_unregister(struct power_supply *psy)
{
+ psy->use_cnt--;
+ WARN_ON(psy->use_cnt);
cancel_work_sync(&psy->changed_work);
sysfs_remove_link(&psy->dev->kobj, "powers");
power_supply_remove_triggers(psy);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index b203a26d5c54..c2c17ac3a608 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -199,6 +199,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);
@@ -227,6 +233,7 @@ struct power_supply {
struct work_struct changed_work;
spinlock_t changed_lock;
bool changed;
+ int use_cnt;
#ifdef CONFIG_THERMAL
struct thermal_zone_device *tzd;
struct thermal_cooling_device *tcd;
@@ -287,6 +294,15 @@ 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 int power_supply_register(struct device *parent,
struct power_supply *psy,
const struct power_supply_config *cfg);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 04/19] power_supply: sysfs: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (2 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 03/19] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 05/19] power: 88pm860x_charger: " Krzysztof Kozlowski
` (15 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 05/19] power: 88pm860x_charger: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (3 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 04/19] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 06/19] power: ab8500: " Krzysztof Kozlowski
` (14 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
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 650930e4fa79..59d62665b526 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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 06/19] power: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (4 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 05/19] power: 88pm860x_charger: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 07/19] mfd: " Krzysztof Kozlowski
` (13 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
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 4ebf7b0819f7..78207ca5871f 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 8c8d170ff0f8..b6566d7d41d8 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 69b80bcaa9e7..5f4f900bfcb9 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2200,7 +2200,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 ab54b8dea670..2049813d740d 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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (5 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 06/19] power: ab8500: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-20 13:36 ` Lee Jones
2015-01-05 15:47 ` [RFC PATCHv2 08/19] power: apm_power: " Krzysztof Kozlowski
` (12 subsequent siblings)
19 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
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 cfff0b643f1b..d4a4b24be7c6 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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 08/19] power: apm_power: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (6 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 07/19] mfd: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 09/19] power: bq2415x_charger: " Krzysztof Kozlowski
` (11 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 09/19] power: bq2415x_charger: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (7 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 08/19] power: apm_power: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 10/19] power: charger-manager: " Krzysztof Kozlowski
` (10 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
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 1f49986fc605..2f80de0410d9 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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 10/19] power: charger-manager: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (8 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 09/19] power: bq2415x_charger: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 11/19] power_supply: Change ownership from driver to core Krzysztof Kozlowski
` (9 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct calls to power supply function attributes with wrappers.
Wrappers provide safe 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 <k.kozlowski@samsung.com>
Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
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 034c77bf0fc0..1d5065ebbd83 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);
}
@@ -910,7 +913,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:
@@ -933,7 +936,7 @@ static int charger_get_property(struct power_supply *psy,
mdelay(2000);
pr_err("End wait...\n");
- ret = fuel_gauge->get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CAPACITY, val);
if (ret)
break;
@@ -989,7 +992,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) {
@@ -1559,7 +1562,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) {
@@ -1851,13 +1854,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
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 11/19] power_supply: Change ownership from driver to core
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (9 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 10/19] power: charger-manager: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 12/19] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
` (8 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Change the ownership of power_supply structure from each driver
implementing the class to the power supply core.
Each driver provides the implementation of power supply. However it
should not be the owner of 'power_supply' instance because it is exposed
by core to other subsystems with power_supply_get_by_name(). These
other subsystems have no knowledge when the driver will unregister the
power supply. This leads to several issues when driver is unbound -
mostly because user of power supply accesses freed memory.
Instead let the core own the instance of struct 'power_supply'. Other
users of this power supply will still access valid memory because it
will be freed when device reference count reaches 0. Currently this
means "it will leak" but power_supply_put() call in next patches will
solve it.
This is a partial way of solving invalid memory references 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' call is executed in invalid context because the driver was
unbound and struct 'power_supply' memory was freed.
This could be observed easily with charger manager driver (here compiled
with max17040 fuel gauge):
$ cat /sys/devices/virtual/power_supply/cm-battery/capacity &
$ echo "1-0036" > /sys/bus/i2c/drivers/max17040/unbind
[ 55.725123] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 55.732584] pgd = d98d4000
[ 55.734060] [00000000] *pgd=5afa2831, *pte=00000000, *ppte=00000000
[ 55.740318] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM
[ 55.746210] Modules linked in:
[ 55.749259] CPU: 1 PID: 2936 Comm: cat Tainted: G W 3.19.0-rc1-next-20141226-00048-gf79f475f3c44-dirty #1496
[ 55.760190] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 55.766270] task: d9b76f00 ti: daf54000 task.ti: daf54000
[ 55.771647] PC is at 0x0
[ 55.774182] LR is at charger_get_property+0x2f4/0x36c
[ 55.779201] pc : [<00000000>] lr : [<c034b0b4>] psr: 60000013
[ 55.779201] sp : daf55e90 ip : 00000003 fp : 00000000
[ 55.790657] r10: 00000000 r9 : c06e2878 r8 : d9b26c68
[ 55.795865] r7 : dad81610 r6 : daec7410 r5 : daf55ebc r4 : 00000000
[ 55.802367] r3 : 00000000 r2 : daf55ebc r1 : 0000002a r0 : d9b26c68
[ 55.808879] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 55.815994] Control: 10c5387d Table: 598d406a DAC: 00000015
[ 55.821723] Process cat (pid: 2936, stack limit = 0xdaf54210)
[ 55.827451] Stack: (0xdaf55e90 to 0xdaf56000)
[ 55.831795] 5e80: 60000013 c01459c4 0000002a c06f8ef8
[ 55.839956] 5ea0: db651000 c06f8ef8 daebac00 c04cb668 daebac08 c0346864 00000000 c01459c4
[ 55.848115] 5ec0: d99eaa80 c06f8ef8 00000fff 00001000 db651000 c027f25c c027f240 d99eaa80
[ 55.856274] 5ee0: d9a06c00 c0146218 daf55f18 00001000 d99eaa80 db4c18c0 00000001 00000001
[ 55.864468] 5f00: daf55f80 c0144c78 c0144c54 c0107f90 00015000 d99eaab0 00000000 00000000
[ 55.872603] 5f20: 000051c7 00000000 db4c18c0 c04a9370 00015000 00001000 daf55f80 00001000
[ 55.880763] 5f40: daf54000 00015000 00000000 c00e53dc db4c18c0 c00e548c 0000000d 00008124
[ 55.888937] 5f60: 00000001 00000000 00000000 db4c18c0 db4c18c0 00001000 00015000 c00e5550
[ 55.897099] 5f80: 00000000 00000000 00001000 00001000 00015000 00000003 00000003 c000f364
[ 55.905239] 5fa0: 00000000 c000f1a0 00001000 00015000 00000003 00015000 00001000 0001333c
[ 55.913399] 5fc0: 00001000 00015000 00000003 00000003 00000002 00000000 00000000 00000000
[ 55.921560] 5fe0: 7fffe000 be999850 0000a225 b6f3c19c 60000010 00000003 00000000 00000000
[ 55.929744] [<c034b0b4>] (charger_get_property) from [<c0346864>] (power_supply_show_property+0x48/0x20c)
[ 55.939286] [<c0346864>] (power_supply_show_property) from [<c027f25c>] (dev_attr_show+0x1c/0x48)
[ 55.948130] [<c027f25c>] (dev_attr_show) from [<c0146218>] (sysfs_kf_seq_show+0x84/0x104)
[ 55.956298] [<c0146218>] (sysfs_kf_seq_show) from [<c0144c78>] (kernfs_seq_show+0x24/0x28)
[ 55.964536] [<c0144c78>] (kernfs_seq_show) from [<c0107f90>] (seq_read+0x1b0/0x484)
[ 55.972172] [<c0107f90>] (seq_read) from [<c00e53dc>] (__vfs_read+0x18/0x4c)
[ 55.979188] [<c00e53dc>] (__vfs_read) from [<c00e548c>] (vfs_read+0x7c/0x100)
[ 55.986304] [<c00e548c>] (vfs_read) from [<c00e5550>] (SyS_read+0x40/0x8c)
[ 55.993164] [<c00e5550>] (SyS_read) from [<c000f1a0>] (ret_fast_syscall+0x0/0x48)
[ 56.000626] Code: bad PC value
[ 56.011652] ---[ end trace 7b64343fbdae8ef1 ]---
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
drivers/power/bq24190_charger.c | 103 ++++++++++++-------------
drivers/power/charger-manager.c | 53 ++++++-------
drivers/power/max14577_charger.c | 34 ++++----
drivers/power/max17040_battery.c | 31 ++++----
drivers/power/max17042_battery.c | 45 +++++++----
drivers/power/power_supply_core.c | 141 ++++++++++++++++++----------------
drivers/power/power_supply_leds.c | 25 +++---
drivers/power/power_supply_sysfs.c | 18 ++---
drivers/power/sbs-battery.c | 69 ++++++++---------
drivers/power/tps65090-charger.c | 43 ++++++-----
include/linux/power/charger-manager.h | 3 +-
include/linux/power_supply.h | 39 ++++++----
12 files changed, 323 insertions(+), 281 deletions(-)
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c
index f736c4c7c8fe..9215bc66fa88 100644
--- a/drivers/power/bq24190_charger.c
+++ b/drivers/power/bq24190_charger.c
@@ -152,8 +152,8 @@
struct bq24190_dev_info {
struct i2c_client *client;
struct device *dev;
- struct power_supply charger;
- struct power_supply battery;
+ struct power_supply *charger;
+ struct power_supply *battery;
char model_name[I2C_NAME_SIZE];
kernel_ulong_t model;
unsigned int gpio_int;
@@ -423,8 +423,7 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct power_supply *psy = dev_get_drvdata(dev);
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, charger);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
struct bq24190_sysfs_field_info *info;
int ret;
u8 v;
@@ -444,8 +443,7 @@ static ssize_t bq24190_sysfs_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct power_supply *psy = dev_get_drvdata(dev);
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, charger);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
struct bq24190_sysfs_field_info *info;
int ret;
u8 v;
@@ -469,13 +467,13 @@ static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
{
bq24190_sysfs_init_attrs();
- return sysfs_create_group(&bdi->charger.dev->kobj,
+ return sysfs_create_group(&bdi->charger->dev.kobj,
&bq24190_sysfs_attr_group);
}
static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi)
{
- sysfs_remove_group(&bdi->charger.dev->kobj, &bq24190_sysfs_attr_group);
+ sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group);
}
#else
static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
@@ -807,8 +805,7 @@ static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,
static int bq24190_charger_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, charger);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
int ret;
dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -861,8 +858,7 @@ static int bq24190_charger_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, charger);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
int ret;
dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -922,18 +918,15 @@ static char *bq24190_charger_supplied_to[] = {
"main-battery",
};
-static void bq24190_charger_init(struct power_supply *charger)
-{
- charger->name = "bq24190-charger";
- charger->type = POWER_SUPPLY_TYPE_USB;
- charger->properties = bq24190_charger_properties;
- charger->num_properties = ARRAY_SIZE(bq24190_charger_properties);
- charger->supplied_to = bq24190_charger_supplied_to;
- charger->num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to);
- charger->get_property = bq24190_charger_get_property;
- charger->set_property = bq24190_charger_set_property;
- charger->property_is_writeable = bq24190_charger_property_is_writeable;
-}
+static const struct power_supply_desc bq24190_charger_desc = {
+ .name = "bq24190-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = bq24190_charger_properties,
+ .num_properties = ARRAY_SIZE(bq24190_charger_properties),
+ .get_property = bq24190_charger_get_property,
+ .set_property = bq24190_charger_set_property,
+ .property_is_writeable = bq24190_charger_property_is_writeable,
+};
/* Battery power supply property routines */
@@ -1102,8 +1095,7 @@ static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
static int bq24190_battery_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, battery);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
int ret;
dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -1144,8 +1136,7 @@ static int bq24190_battery_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
- struct bq24190_dev_info *bdi =
- container_of(psy, struct bq24190_dev_info, battery);
+ struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
int ret;
dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -1193,16 +1184,15 @@ static enum power_supply_property bq24190_battery_properties[] = {
POWER_SUPPLY_PROP_SCOPE,
};
-static void bq24190_battery_init(struct power_supply *battery)
-{
- battery->name = "bq24190-battery";
- battery->type = POWER_SUPPLY_TYPE_BATTERY;
- battery->properties = bq24190_battery_properties;
- battery->num_properties = ARRAY_SIZE(bq24190_battery_properties);
- battery->get_property = bq24190_battery_get_property;
- battery->set_property = bq24190_battery_set_property;
- battery->property_is_writeable = bq24190_battery_property_is_writeable;
-}
+static const struct power_supply_desc bq24190_battery_desc = {
+ .name = "bq24190-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = bq24190_battery_properties,
+ .num_properties = ARRAY_SIZE(bq24190_battery_properties),
+ .get_property = bq24190_battery_get_property,
+ .set_property = bq24190_battery_set_property,
+ .property_is_writeable = bq24190_battery_property_is_writeable,
+};
static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
{
@@ -1269,8 +1259,8 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
* interrupt received).
*/
if (alert_userspace && !bdi->first_time) {
- power_supply_changed(&bdi->charger);
- power_supply_changed(&bdi->battery);
+ power_supply_changed(bdi->charger);
+ power_supply_changed(bdi->battery);
bdi->first_time = false;
}
@@ -1362,6 +1352,7 @@ static int bq24190_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct device *dev = &client->dev;
struct bq24190_platform_data *pdata = client->dev.platform_data;
+ struct power_supply_config charger_cfg = {}, battery_cfg = {};
struct bq24190_dev_info *bdi;
int ret;
@@ -1416,19 +1407,23 @@ static int bq24190_probe(struct i2c_client *client,
goto out2;
}
- bq24190_charger_init(&bdi->charger);
-
- ret = power_supply_register(dev, &bdi->charger, NULL);
- if (ret) {
+ charger_cfg.drv_data = bdi;
+ charger_cfg.supplied_to = bq24190_charger_supplied_to;
+ charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to),
+ bdi->charger = power_supply_register(dev, &bq24190_charger_desc,
+ &charger_cfg);
+ if (IS_ERR(bdi->charger)) {
dev_err(dev, "Can't register charger\n");
+ ret = PTR_ERR(bdi->charger);
goto out2;
}
- bq24190_battery_init(&bdi->battery);
-
- ret = power_supply_register(dev, &bdi->battery, NULL);
- if (ret) {
+ battery_cfg.drv_data = bdi;
+ bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
+ &battery_cfg);
+ if (IS_ERR(bdi->battery)) {
dev_err(dev, "Can't register battery\n");
+ ret = PTR_ERR(bdi->battery);
goto out3;
}
@@ -1441,9 +1436,9 @@ static int bq24190_probe(struct i2c_client *client,
return 0;
out4:
- power_supply_unregister(&bdi->battery);
+ power_supply_unregister(bdi->battery);
out3:
- power_supply_unregister(&bdi->charger);
+ power_supply_unregister(bdi->charger);
out2:
pm_runtime_disable(dev);
out1:
@@ -1462,8 +1457,8 @@ static int bq24190_remove(struct i2c_client *client)
pm_runtime_put_sync(bdi->dev);
bq24190_sysfs_remove_group(bdi);
- power_supply_unregister(&bdi->battery);
- power_supply_unregister(&bdi->charger);
+ power_supply_unregister(bdi->battery);
+ power_supply_unregister(bdi->charger);
pm_runtime_disable(bdi->dev);
if (bdi->gpio_int)
@@ -1499,8 +1494,8 @@ static int bq24190_pm_resume(struct device *dev)
pm_runtime_put_sync(bdi->dev);
/* Things may have changed while suspended so alert upper layer */
- power_supply_changed(&bdi->charger);
- power_supply_changed(&bdi->battery);
+ power_supply_changed(bdi->charger);
+ power_supply_changed(bdi->battery);
return 0;
}
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 1d5065ebbd83..a9870b9ff571 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -874,8 +874,7 @@ static int charger_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct charger_manager *cm = container_of(psy,
- struct charger_manager, charger_psy);
+ struct charger_manager *cm = power_supply_get_drvdata(psy);
struct charger_desc *desc = cm->desc;
struct power_supply *fuel_gauge;
int ret = 0;
@@ -1032,7 +1031,7 @@ static enum power_supply_property default_charger_props[] = {
*/
};
-static struct power_supply psy_default = {
+static const struct power_supply_desc psy_default = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = default_charger_props,
@@ -1534,7 +1533,7 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
dev_info(cm->dev, "'%s' regulator's externally_control is %d\n",
charger->regulator_name, charger->externally_control);
- ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
+ ret = sysfs_create_group(&cm->charger_psy->dev.kobj,
&charger->attr_g);
if (ret < 0) {
dev_err(cm->dev, "Cannot create sysfs entry of %s regulator\n",
@@ -1566,9 +1565,9 @@ static int cm_init_thermal_data(struct charger_manager *cm,
POWER_SUPPLY_PROP_TEMP, &val);
if (!ret) {
- cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
POWER_SUPPLY_PROP_TEMP;
- cm->charger_psy.num_properties++;
+ cm->charger_psy_desc.num_properties++;
cm->desc->measure_battery_temp = true;
}
#ifdef CONFIG_THERMAL
@@ -1579,9 +1578,9 @@ static int cm_init_thermal_data(struct charger_manager *cm,
return PTR_ERR(cm->tzd_batt);
/* Use external thermometer */
- cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
POWER_SUPPLY_PROP_TEMP_AMBIENT;
- cm->charger_psy.num_properties++;
+ cm->charger_psy_desc.num_properties++;
cm->desc->measure_battery_temp = true;
ret = 0;
}
@@ -1735,6 +1734,7 @@ static int charger_manager_probe(struct platform_device *pdev)
int j = 0;
union power_supply_propval val;
struct power_supply *fuel_gauge;
+ struct power_supply_config psy_cfg = {};
if (g_desc && !rtc_dev && g_desc->rtc_name) {
rtc_dev = rtc_class_open(g_desc->rtc_name);
@@ -1759,6 +1759,7 @@ static int charger_manager_probe(struct platform_device *pdev)
/* Basic Values. Unspecified are Null or 0 */
cm->dev = &pdev->dev;
cm->desc = desc;
+ psy_cfg.drv_data = cm;
/*
* The following two do not need to be errors.
@@ -1832,40 +1833,40 @@ static int charger_manager_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, cm);
- memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
+ memcpy(&cm->charger_psy_desc, &psy_default, sizeof(psy_default));
if (!desc->psy_name)
strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX);
else
strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
- cm->charger_psy.name = cm->psy_name_buf;
+ cm->charger_psy_desc.name = cm->psy_name_buf;
/* Allocate for psy properties because they may vary */
- cm->charger_psy.properties = devm_kzalloc(&pdev->dev,
+ cm->charger_psy_desc.properties = devm_kzalloc(&pdev->dev,
sizeof(enum power_supply_property)
* (ARRAY_SIZE(default_charger_props) +
NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
- if (!cm->charger_psy.properties)
+ if (!cm->charger_psy_desc.properties)
return -ENOMEM;
- memcpy(cm->charger_psy.properties, default_charger_props,
+ memcpy(cm->charger_psy_desc.properties, default_charger_props,
sizeof(enum power_supply_property) *
ARRAY_SIZE(default_charger_props));
- cm->charger_psy.num_properties = psy_default.num_properties;
+ cm->charger_psy_desc.num_properties = psy_default.num_properties;
/* Find which optional psy-properties are available */
if (!power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
- cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
POWER_SUPPLY_PROP_CHARGE_NOW;
- cm->charger_psy.num_properties++;
+ cm->charger_psy_desc.num_properties++;
}
if (!power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CURRENT_NOW,
&val)) {
- cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
POWER_SUPPLY_PROP_CURRENT_NOW;
- cm->charger_psy.num_properties++;
+ cm->charger_psy_desc.num_properties++;
}
ret = cm_init_thermal_data(cm, fuel_gauge);
@@ -1876,11 +1877,11 @@ static int charger_manager_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
- ret = power_supply_register(NULL, &cm->charger_psy, NULL);
- if (ret) {
+ cm->charger_psy = power_supply_register(NULL, &cm->charger_psy_desc, &psy_cfg);
+ if (IS_ERR(cm->charger_psy)) {
dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n",
- cm->charger_psy.name);
- return ret;
+ cm->charger_psy->desc->name);
+ return PTR_ERR(cm->charger_psy);
}
/* Register extcon device for charger cable */
@@ -1926,7 +1927,7 @@ err_reg_sysfs:
struct charger_regulator *charger;
charger = &desc->charger_regulators[i];
- sysfs_remove_group(&cm->charger_psy.dev->kobj,
+ sysfs_remove_group(&cm->charger_psy->dev.kobj,
&charger->attr_g);
}
err_reg_extcon:
@@ -1944,7 +1945,7 @@ err_reg_extcon:
regulator_put(desc->charger_regulators[i].consumer);
}
- power_supply_unregister(&cm->charger_psy);
+ power_supply_unregister(cm->charger_psy);
return ret;
}
@@ -1976,7 +1977,7 @@ static int charger_manager_remove(struct platform_device *pdev)
for (i = 0 ; i < desc->num_charger_regulators ; i++)
regulator_put(desc->charger_regulators[i].consumer);
- power_supply_unregister(&cm->charger_psy);
+ power_supply_unregister(cm->charger_psy);
try_charger_enable(cm, false);
@@ -2132,7 +2133,7 @@ static bool find_power_supply(struct charger_manager *cm,
bool found = false;
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
- if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) {
+ if (!strcmp(psy->desc->name, cm->desc->psy_charger_stat[i])) {
found = true;
break;
}
diff --git a/drivers/power/max14577_charger.c b/drivers/power/max14577_charger.c
index 8f113ed73e6c..70d601f82098 100644
--- a/drivers/power/max14577_charger.c
+++ b/drivers/power/max14577_charger.c
@@ -22,9 +22,9 @@
#include <linux/mfd/max14577.h>
struct max14577_charger {
- struct device *dev;
- struct max14577 *max14577;
- struct power_supply charger;
+ struct device *dev;
+ struct max14577 *max14577;
+ struct power_supply *charger;
unsigned int charging_state;
unsigned int battery_state;
@@ -389,9 +389,7 @@ static int max14577_charger_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct max14577_charger *chg = container_of(psy,
- struct max14577_charger,
- charger);
+ struct max14577_charger *chg = power_supply_get_drvdata(psy);
int ret = 0;
switch (psp) {
@@ -424,6 +422,14 @@ static int max14577_charger_get_property(struct power_supply *psy,
return ret;
}
+static const struct power_supply_desc max14577_charger_desc = {
+ .name = "max14577-charger",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = max14577_charger_props,
+ .num_properties = ARRAY_SIZE(max14577_charger_props),
+ .get_property = max14577_charger_get_property,
+};
+
#ifdef CONFIG_OF
static struct max14577_charger_platform_data *max14577_charger_dt_init(
struct platform_device *pdev)
@@ -531,6 +537,7 @@ static DEVICE_ATTR(fast_charge_timer, S_IRUGO | S_IWUSR,
static int max14577_charger_probe(struct platform_device *pdev)
{
struct max14577_charger *chg;
+ struct power_supply_config psy_cfg = {};
struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
int ret;
@@ -550,21 +557,18 @@ static int max14577_charger_probe(struct platform_device *pdev)
if (ret)
return ret;
- chg->charger.name = "max14577-charger",
- chg->charger.type = POWER_SUPPLY_TYPE_BATTERY,
- chg->charger.properties = max14577_charger_props,
- chg->charger.num_properties = ARRAY_SIZE(max14577_charger_props),
- chg->charger.get_property = max14577_charger_get_property,
-
ret = device_create_file(&pdev->dev, &dev_attr_fast_charge_timer);
if (ret) {
dev_err(&pdev->dev, "failed: create sysfs entry\n");
return ret;
}
- ret = power_supply_register(&pdev->dev, &chg->charger, NULL);
- if (ret) {
+ psy_cfg.drv_data = chg;
+ chg->charger = power_supply_register(&pdev->dev, &max14577_charger_desc,
+ &psy_cfg);
+ if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n");
+ ret = PTR_ERR(chg->charger);
goto err;
}
@@ -585,7 +589,7 @@ static int max14577_charger_remove(struct platform_device *pdev)
struct max14577_charger *chg = platform_get_drvdata(pdev);
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
- power_supply_unregister(&chg->charger);
+ power_supply_unregister(chg->charger);
return 0;
}
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index bf42c57a4247..2bfe4bbbc29a 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -40,7 +40,7 @@
struct max17040_chip {
struct i2c_client *client;
struct delayed_work work;
- struct power_supply battery;
+ struct power_supply *battery;
struct max17040_platform_data *pdata;
/* State Of Connect */
@@ -57,8 +57,7 @@ static int max17040_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct max17040_chip *chip = container_of(psy,
- struct max17040_chip, battery);
+ struct max17040_chip *chip = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
@@ -198,12 +197,20 @@ static enum power_supply_property max17040_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
};
+static const struct power_supply_desc max17040_battery_desc = {
+ .name = "battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = max17040_get_property,
+ .properties = max17040_battery_props,
+ .num_properties = ARRAY_SIZE(max17040_battery_props),
+};
+
static int max17040_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct power_supply_config psy_cfg = {};
struct max17040_chip *chip;
- int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
return -EIO;
@@ -216,17 +223,13 @@ static int max17040_probe(struct i2c_client *client,
chip->pdata = client->dev.platform_data;
i2c_set_clientdata(client, chip);
+ psy_cfg.drv_data = chip;
- chip->battery.name = "battery";
- chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
- chip->battery.get_property = max17040_get_property;
- chip->battery.properties = max17040_battery_props;
- chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props);
-
- ret = power_supply_register(&client->dev, &chip->battery, NULL);
- if (ret) {
+ chip->battery = power_supply_register(&client->dev,
+ &max17040_battery_desc, &psy_cfg);
+ if (IS_ERR(chip->battery)) {
dev_err(&client->dev, "failed: power supply register\n");
- return ret;
+ return PTR_ERR(chip->battery);
}
max17040_reset(client);
@@ -242,7 +245,7 @@ static int max17040_remove(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
- power_supply_unregister(&chip->battery);
+ power_supply_unregister(chip->battery);
cancel_delayed_work(&chip->work);
return 0;
}
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index c62d1428803e..40e7056d211e 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -69,7 +69,7 @@
struct max17042_chip {
struct i2c_client *client;
struct regmap *regmap;
- struct power_supply battery;
+ struct power_supply *battery;
enum max170xx_chip_type chip_type;
struct max17042_platform_data *pdata;
struct work_struct work;
@@ -96,8 +96,7 @@ static int max17042_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct max17042_chip *chip = container_of(psy,
- struct max17042_chip, battery);
+ struct max17042_chip *chip = power_supply_get_drvdata(psy);
struct regmap *map = chip->regmap;
int ret;
u32 data;
@@ -604,7 +603,7 @@ static irqreturn_t max17042_thread_handler(int id, void *dev)
max17042_set_soc_threshold(chip, 1);
}
- power_supply_changed(&chip->battery);
+ power_supply_changed(chip->battery);
return IRQ_HANDLED;
}
@@ -664,10 +663,28 @@ static const struct regmap_config max17042_regmap_config = {
.val_format_endian = REGMAP_ENDIAN_NATIVE,
};
+static const struct power_supply_desc max17042_psy_desc = {
+ .name = "max170xx_battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = max17042_get_property,
+ .properties = max17042_battery_props,
+ .num_properties = ARRAY_SIZE(max17042_battery_props),
+};
+
+static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
+ .name = "max170xx_battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = max17042_get_property,
+ .properties = max17042_battery_props,
+ .num_properties = ARRAY_SIZE(max17042_battery_props) - 2,
+};
+
static int max17042_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
+ struct power_supply_config psy_cfg = {};
struct max17042_chip *chip;
int ret;
int i;
@@ -694,6 +711,7 @@ static int max17042_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, chip);
+ psy_cfg.drv_data = chip;
regmap_read(chip->regmap, MAX17042_DevName, &val);
if (val == MAX17042_IC_VERSION) {
@@ -707,16 +725,10 @@ static int max17042_probe(struct i2c_client *client,
return -EIO;
}
- chip->battery.name = "max170xx_battery";
- chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
- chip->battery.get_property = max17042_get_property;
- chip->battery.properties = max17042_battery_props;
- chip->battery.num_properties = ARRAY_SIZE(max17042_battery_props);
-
/* When current is not measured,
* CURRENT_NOW and CURRENT_AVG properties should be invisible. */
if (!chip->pdata->enable_current_sense)
- chip->battery.num_properties -= 2;
+ max17042_desc = &max17042_no_current_sense_psy_desc;
if (chip->pdata->r_sns == 0)
chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
@@ -733,17 +745,18 @@ static int max17042_probe(struct i2c_client *client,
regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
}
- ret = power_supply_register(&client->dev, &chip->battery, NULL);
- if (ret) {
+ chip->battery = power_supply_register(&client->dev, max17042_desc,
+ &psy_cfg);
+ if (IS_ERR(chip->battery)) {
dev_err(&client->dev, "failed: power supply register\n");
- return ret;
+ return PTR_ERR(chip->battery);
}
if (client->irq) {
ret = request_threaded_irq(client->irq, NULL,
max17042_thread_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- chip->battery.name, chip);
+ chip->battery->desc->name, chip);
if (!ret) {
regmap_read(chip->regmap, MAX17042_CONFIG, &val);
val |= CONFIG_ALRT_BIT_ENBL;
@@ -773,7 +786,7 @@ static int max17042_remove(struct i2c_client *client)
if (client->irq)
free_irq(client->irq, chip);
- power_supply_unregister(&chip->battery);
+ power_supply_unregister(chip->battery);
return 0;
}
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index fdec3c29fc3c..ec9ac01074c7 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -40,16 +40,16 @@ static bool __power_supply_is_supplied_by(struct power_supply *supplier,
/* Support both supplied_to and supplied_from modes */
if (supply->supplied_from) {
- if (!supplier->name)
+ if (!supplier->desc->name)
return false;
for (i = 0; i < supply->num_supplies; i++)
- if (!strcmp(supplier->name, supply->supplied_from[i]))
+ if (!strcmp(supplier->desc->name, supply->supplied_from[i]))
return true;
} else {
- if (!supply->name)
+ if (!supply->desc->name)
return false;
for (i = 0; i < supplier->num_supplicants; i++)
- if (!strcmp(supplier->supplied_to[i], supply->name))
+ if (!strcmp(supplier->supplied_to[i], supply->desc->name))
return true;
}
@@ -62,8 +62,8 @@ static int __power_supply_changed_work(struct device *dev, void *data)
struct power_supply *pst = dev_get_drvdata(dev);
if (__power_supply_is_supplied_by(psy, pst)) {
- if (pst->external_power_changed)
- pst->external_power_changed(pst);
+ if (pst->desc->external_power_changed)
+ pst->desc->external_power_changed(pst);
}
return 0;
@@ -75,7 +75,7 @@ static void power_supply_changed_work(struct work_struct *work)
struct power_supply *psy = container_of(work, struct power_supply,
changed_work);
- dev_dbg(psy->dev, "%s\n", __func__);
+ dev_dbg(&psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags);
/*
@@ -93,7 +93,7 @@ static void power_supply_changed_work(struct work_struct *work)
power_supply_update_leds(psy);
atomic_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy);
- kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+ kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE);
spin_lock_irqsave(&psy->changed_lock, flags);
}
@@ -103,7 +103,7 @@ static void power_supply_changed_work(struct work_struct *work)
* to true.
*/
if (likely(!psy->changed))
- pm_relax(psy->dev);
+ pm_relax(&psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags);
}
@@ -111,11 +111,11 @@ void power_supply_changed(struct power_supply *psy)
{
unsigned long flags;
- dev_dbg(psy->dev, "%s\n", __func__);
+ dev_dbg(&psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags);
psy->changed = true;
- pm_stay_awake(psy->dev);
+ pm_stay_awake(&psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags);
schedule_work(&psy->changed_work);
}
@@ -138,9 +138,9 @@ static int __power_supply_populate_supplied_from(struct device *dev,
break;
if (np == epsy->of_node) {
- dev_info(psy->dev, "%s: Found supply : %s\n",
- psy->name, epsy->name);
- psy->supplied_from[i-1] = (char *)epsy->name;
+ dev_info(&psy->dev, "%s: Found supply : %s\n",
+ psy->desc->name, epsy->desc->name);
+ psy->supplied_from[i-1] = (char *)epsy->desc->name;
psy->num_supplies++;
of_node_put(np);
break;
@@ -158,7 +158,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
error = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_populate_supplied_from);
- dev_dbg(psy->dev, "%s %d\n", __func__, error);
+ dev_dbg(&psy->dev, "%s %d\n", __func__, error);
return error;
}
@@ -220,7 +220,7 @@ static int power_supply_check_supplies(struct power_supply *psy)
of_node_put(np);
if (ret) {
- dev_dbg(psy->dev, "Failed to find supply!\n");
+ dev_dbg(&psy->dev, "Failed to find supply!\n");
return ret;
}
} while (np);
@@ -230,17 +230,18 @@ static int power_supply_check_supplies(struct power_supply *psy)
return 0;
/* All supplies found, allocate char ** array for filling */
- psy->supplied_from = devm_kzalloc(psy->dev, sizeof(psy->supplied_from),
+ psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from),
GFP_KERNEL);
if (!psy->supplied_from) {
- dev_err(psy->dev, "Couldn't allocate memory for supply list\n");
+ dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
return -ENOMEM;
}
- *psy->supplied_from = devm_kzalloc(psy->dev, sizeof(char *) * (cnt - 1),
+ *psy->supplied_from = devm_kzalloc(&psy->dev,
+ sizeof(char *) * (cnt - 1),
GFP_KERNEL);
if (!*psy->supplied_from) {
- dev_err(psy->dev, "Couldn't allocate memory for supply list\n");
+ dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
return -ENOMEM;
}
@@ -260,7 +261,8 @@ static int __power_supply_am_i_supplied(struct device *dev, void *data)
struct power_supply *epsy = dev_get_drvdata(dev);
if (__power_supply_is_supplied_by(epsy, psy))
- if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret))
+ if (!epsy->desc->get_property(epsy, POWER_SUPPLY_PROP_ONLINE,
+ &ret))
return ret.intval;
return 0;
@@ -273,7 +275,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
error = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_am_i_supplied);
- dev_dbg(psy->dev, "%s %d\n", __func__, error);
+ dev_dbg(&psy->dev, "%s %d\n", __func__, error);
return error;
}
@@ -286,8 +288,9 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
unsigned int *count = data;
(*count)++;
- if (psy->type != POWER_SUPPLY_TYPE_BATTERY)
- if (!psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
+ if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
+ if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+ &ret))
return ret.intval;
return 0;
@@ -314,9 +317,9 @@ EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
int power_supply_set_battery_charged(struct power_supply *psy)
{
- if (psy->use_cnt >= 0 && psy->type == POWER_SUPPLY_TYPE_BATTERY &&
- psy->set_charged) {
- psy->set_charged(psy);
+ if (psy->use_cnt >= 0 && psy->desc->type == POWER_SUPPLY_TYPE_BATTERY &&
+ psy->desc->set_charged) {
+ psy->desc->set_charged(psy);
return 0;
}
@@ -329,7 +332,7 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
const char *name = data;
struct power_supply *psy = dev_get_drvdata(dev);
- return strcmp(psy->name, name) == 0;
+ return strcmp(psy->desc->name, name) == 0;
}
struct power_supply *power_supply_get_by_name(const char *name)
@@ -374,7 +377,7 @@ int power_supply_get_property(struct power_supply *psy,
if (psy->use_cnt <= 0)
return -ENODEV;
- return psy->get_property(psy, psp, val);
+ return psy->desc->get_property(psy, psp, val);
}
EXPORT_SYMBOL_GPL(power_supply_get_property);
@@ -382,42 +385,43 @@ int power_supply_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
- if (psy->use_cnt <= 0 || !psy->set_property)
+ if (psy->use_cnt <= 0 || !psy->desc->set_property)
return -ENODEV;
- return psy->set_property(psy, psp, val);
+ return psy->desc->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->use_cnt <= 0 || !psy->property_is_writeable)
+ if (psy->use_cnt <= 0 || !psy->desc->property_is_writeable)
return -ENODEV;
- return psy->property_is_writeable(psy, psp);
+ return psy->desc->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->use_cnt <= 0 || !psy->external_power_changed)
+ if (psy->use_cnt <= 0 || !psy->desc->external_power_changed)
return;
- psy->external_power_changed(psy);
+ psy->desc->external_power_changed(psy);
}
EXPORT_SYMBOL_GPL(power_supply_external_power_changed);
int power_supply_powers(struct power_supply *psy, struct device *dev)
{
- return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
+ return sysfs_create_link(&psy->dev.kobj, &dev->kobj, "powers");
}
EXPORT_SYMBOL_GPL(power_supply_powers);
static void power_supply_dev_release(struct device *dev)
{
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
- kfree(dev);
+ kfree(psy);
}
int power_supply_reg_notifier(struct notifier_block *nb)
@@ -442,7 +446,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
WARN_ON(tzd == NULL);
psy = tzd->devdata;
- ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
+ ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
/* Convert tenths of degree Celsius to milli degree Celsius. */
if (!ret)
@@ -459,14 +463,14 @@ static int psy_register_thermal(struct power_supply *psy)
{
int i;
- if (psy->no_thermal)
+ if (psy->desc->no_thermal)
return 0;
/* Register battery zone device psy reports temperature */
- for (i = 0; i < psy->num_properties; i++) {
- if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
- psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
- psy, &psy_tzd_ops, NULL, 0, 0);
+ for (i = 0; i < psy->desc->num_properties; i++) {
+ if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) {
+ psy->tzd = thermal_zone_device_register(psy->desc->name,
+ 0, 0, psy, &psy_tzd_ops, NULL, 0, 0);
return PTR_ERR_OR_ZERO(psy->tzd);
}
}
@@ -489,7 +493,7 @@ static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
int ret;
psy = tcd->devdata;
- ret = psy->get_property(psy,
+ ret = psy->desc->get_property(psy,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
if (!ret)
*state = val.intval;
@@ -505,7 +509,7 @@ static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
int ret;
psy = tcd->devdata;
- ret = psy->get_property(psy,
+ ret = psy->desc->get_property(psy,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
if (!ret)
*state = val.intval;
@@ -522,7 +526,7 @@ static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
psy = tcd->devdata;
val.intval = state;
- ret = psy->set_property(psy,
+ ret = psy->desc->set_property(psy,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
return ret;
@@ -539,11 +543,11 @@ static int psy_register_cooler(struct power_supply *psy)
int i;
/* Register for cooling device if psy can control charging */
- for (i = 0; i < psy->num_properties; i++) {
- if (psy->properties[i] ==
+ for (i = 0; i < psy->desc->num_properties; i++) {
+ if (psy->desc->properties[i] ==
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) {
psy->tcd = thermal_cooling_device_register(
- (char *)psy->name,
+ (char *)psy->desc->name,
psy, &psy_tcd_ops);
return PTR_ERR_OR_ZERO(psy->tcd);
}
@@ -577,17 +581,21 @@ static void psy_unregister_cooler(struct power_supply *psy)
}
#endif
-static int __power_supply_register(struct device *parent,
- struct power_supply *psy,
+static struct power_supply *__must_check
+__power_supply_register(struct device *parent,
+ const struct power_supply_desc *desc,
const struct power_supply_config *cfg,
bool ws)
{
struct device *dev;
+ struct power_supply *psy;
int rc;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
+ psy = kzalloc(sizeof(*psy), GFP_KERNEL);
+ if (!psy)
+ return ERR_PTR(-ENOMEM);
+
+ dev = &psy->dev;
device_initialize(dev);
@@ -596,7 +604,7 @@ static int __power_supply_register(struct device *parent,
dev->parent = parent;
dev->release = power_supply_dev_release;
dev_set_drvdata(dev, psy);
- psy->dev = dev;
+ psy->desc = desc;
psy->use_cnt++;
if (cfg) {
psy->drv_data = cfg->drv_data;
@@ -605,7 +613,7 @@ static int __power_supply_register(struct device *parent,
psy->num_supplicants = cfg->num_supplicants;
}
- rc = dev_set_name(dev, "%s", psy->name);
+ rc = dev_set_name(dev, "%s", desc->name);
if (rc)
goto dev_set_name_failed;
@@ -640,7 +648,7 @@ static int __power_supply_register(struct device *parent,
power_supply_changed(psy);
- return 0;
+ return psy;
create_triggers_failed:
psy_unregister_cooler(psy);
@@ -653,20 +661,23 @@ wakeup_init_failed:
check_supplies_failed:
dev_set_name_failed:
put_device(dev);
- return rc;
+ return ERR_PTR(rc);
}
-int power_supply_register(struct device *parent, struct power_supply *psy,
+struct power_supply *__must_check power_supply_register(struct device *parent,
+ const struct power_supply_desc *desc,
const struct power_supply_config *cfg)
{
- return __power_supply_register(parent, psy, cfg, true);
+ return __power_supply_register(parent, desc, cfg, true);
}
EXPORT_SYMBOL_GPL(power_supply_register);
-int power_supply_register_no_ws(struct device *parent, struct power_supply *psy,
+struct power_supply *__must_check
+power_supply_register_no_ws(struct device *parent,
+ const struct power_supply_desc *desc,
const struct power_supply_config *cfg)
{
- return __power_supply_register(parent, psy, cfg, false);
+ return __power_supply_register(parent, desc, cfg, false);
}
EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
@@ -675,12 +686,12 @@ void power_supply_unregister(struct power_supply *psy)
psy->use_cnt--;
WARN_ON(psy->use_cnt);
cancel_work_sync(&psy->changed_work);
- sysfs_remove_link(&psy->dev->kobj, "powers");
+ sysfs_remove_link(&psy->dev.kobj, "powers");
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(&psy->dev, false);
+ device_unregister(&psy->dev);
}
EXPORT_SYMBOL_GPL(power_supply_unregister);
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
index effa093c37b0..2d41a43fc81a 100644
--- a/drivers/power/power_supply_leds.c
+++ b/drivers/power/power_supply_leds.c
@@ -25,10 +25,10 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
unsigned long delay_on = 0;
unsigned long delay_off = 0;
- if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+ if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
return;
- dev_dbg(psy->dev, "%s %d\n", __func__, status.intval);
+ dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval);
switch (status.intval) {
case POWER_SUPPLY_STATUS_FULL:
@@ -58,21 +58,21 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
static int power_supply_create_bat_triggers(struct power_supply *psy)
{
psy->charging_full_trig_name = kasprintf(GFP_KERNEL,
- "%s-charging-or-full", psy->name);
+ "%s-charging-or-full", psy->desc->name);
if (!psy->charging_full_trig_name)
goto charging_full_failed;
psy->charging_trig_name = kasprintf(GFP_KERNEL,
- "%s-charging", psy->name);
+ "%s-charging", psy->desc->name);
if (!psy->charging_trig_name)
goto charging_failed;
- psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->name);
+ psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->desc->name);
if (!psy->full_trig_name)
goto full_failed;
psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL,
- "%s-charging-blink-full-solid", psy->name);
+ "%s-charging-blink-full-solid", psy->desc->name);
if (!psy->charging_blink_full_solid_trig_name)
goto charging_blink_full_solid_failed;
@@ -115,10 +115,10 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
{
union power_supply_propval online;
- if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+ if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
return;
- dev_dbg(psy->dev, "%s %d\n", __func__, online.intval);
+ dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval);
if (online.intval)
led_trigger_event(psy->online_trig, LED_FULL);
@@ -128,7 +128,8 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
static int power_supply_create_gen_triggers(struct power_supply *psy)
{
- psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online", psy->name);
+ psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online",
+ psy->desc->name);
if (!psy->online_trig_name)
return -ENOMEM;
@@ -147,7 +148,7 @@ static void power_supply_remove_gen_triggers(struct power_supply *psy)
void power_supply_update_leds(struct power_supply *psy)
{
- if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
power_supply_update_bat_leds(psy);
else
power_supply_update_gen_leds(psy);
@@ -155,14 +156,14 @@ void power_supply_update_leds(struct power_supply *psy)
int power_supply_create_triggers(struct power_supply *psy)
{
- if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
return power_supply_create_bat_triggers(psy);
return power_supply_create_gen_triggers(psy);
}
void power_supply_remove_triggers(struct power_supply *psy)
{
- if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
power_supply_remove_bat_triggers(psy);
else
power_supply_remove_gen_triggers(psy);
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index f817aab80813..af026806cba5 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -74,7 +74,7 @@ static ssize_t power_supply_show_property(struct device *dev,
union power_supply_propval value;
if (off == POWER_SUPPLY_PROP_TYPE) {
- value.intval = psy->type;
+ value.intval = psy->desc->type;
} else {
ret = power_supply_get_property(psy, off, &value);
@@ -218,11 +218,11 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj,
if (attrno == POWER_SUPPLY_PROP_TYPE)
return mode;
- for (i = 0; i < psy->num_properties; i++) {
- int property = psy->properties[i];
+ for (i = 0; i < psy->desc->num_properties; i++) {
+ int property = psy->desc->properties[i];
if (property == attrno) {
- if (psy->property_is_writeable &&
+ if (psy->desc->property_is_writeable &&
power_supply_property_is_writeable(psy, property) > 0)
mode |= S_IWUSR;
@@ -279,14 +279,14 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
dev_dbg(dev, "uevent\n");
- if (!psy || !psy->dev) {
+ if (!psy || !psy->desc) {
dev_dbg(dev, "No power supply yet\n");
return ret;
}
- dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+ dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->desc->name);
- ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);
+ ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->desc->name);
if (ret)
return ret;
@@ -294,11 +294,11 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
if (!prop_buf)
return -ENOMEM;
- for (j = 0; j < psy->num_properties; j++) {
+ for (j = 0; j < psy->desc->num_properties; j++) {
struct device_attribute *attr;
char *line;
- attr = &power_supply_attrs[psy->properties[j]];
+ attr = &power_supply_attrs[psy->desc->properties[j]];
ret = power_supply_show_property(dev, attr, prop_buf);
if (ret == -ENODEV || ret == -ENODATA) {
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index 879f1448fc4a..de1178659d4b 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -156,7 +156,7 @@ static enum power_supply_property sbs_properties[] = {
struct sbs_info {
struct i2c_client *client;
- struct power_supply power_supply;
+ struct power_supply *power_supply;
struct sbs_platform_data *pdata;
bool is_present;
bool gpio_detect;
@@ -391,7 +391,7 @@ static int sbs_get_battery_property(struct i2c_client *client,
chip->last_state = val->intval;
else if (chip->last_state != val->intval) {
cancel_delayed_work_sync(&chip->work);
- power_supply_changed(&chip->power_supply);
+ power_supply_changed(chip->power_supply);
chip->poll_time = 0;
}
} else {
@@ -556,8 +556,7 @@ static int sbs_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
int ret = 0;
- struct sbs_info *chip = container_of(psy,
- struct sbs_info, power_supply);
+ struct sbs_info *chip = power_supply_get_drvdata(psy);
struct i2c_client *client = chip->client;
switch (psp) {
@@ -638,7 +637,7 @@ static int sbs_get_property(struct power_supply *psy,
if (!chip->gpio_detect &&
chip->is_present != (ret >= 0)) {
chip->is_present = (ret >= 0);
- power_supply_changed(&chip->power_supply);
+ power_supply_changed(chip->power_supply);
}
done:
@@ -671,9 +670,7 @@ static irqreturn_t sbs_irq(int irq, void *devid)
static void sbs_external_power_changed(struct power_supply *psy)
{
- struct sbs_info *chip;
-
- chip = container_of(psy, struct sbs_info, power_supply);
+ struct sbs_info *chip = power_supply_get_drvdata(psy);
if (chip->ignore_changes > 0) {
chip->ignore_changes--;
@@ -712,7 +709,7 @@ static void sbs_delayed_work(struct work_struct *work)
if (chip->last_state != ret) {
chip->poll_time = 0;
- power_supply_changed(&chip->power_supply);
+ power_supply_changed(chip->power_supply);
return;
}
if (chip->poll_time > 0) {
@@ -796,43 +793,48 @@ static struct sbs_platform_data *sbs_of_populate_pdata(
}
#endif
+static const struct power_supply_desc sbs_default_desc = {
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = sbs_properties,
+ .num_properties = ARRAY_SIZE(sbs_properties),
+ .get_property = sbs_get_property,
+ .external_power_changed = sbs_external_power_changed,
+};
+
static int sbs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct sbs_info *chip;
+ struct power_supply_desc *sbs_desc;
struct sbs_platform_data *pdata = client->dev.platform_data;
struct power_supply_config psy_cfg = {};
int rc;
int irq;
- char *name;
- name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev));
- if (!name) {
- dev_err(&client->dev, "Failed to allocate device name\n");
+ sbs_desc = devm_kmemdup(&client->dev, &sbs_default_desc,
+ sizeof(*sbs_desc), GFP_KERNEL);
+ if (!sbs_desc)
+ return -ENOMEM;
+
+ sbs_desc->name = devm_kasprintf(&client->dev, GFP_KERNEL, "sbs-%s",
+ dev_name(&client->dev));
+ if (!sbs_desc->name)
return -ENOMEM;
- }
chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL);
- if (!chip) {
- rc = -ENOMEM;
- goto exit_free_name;
- }
+ if (!chip)
+ return -ENOMEM;
chip->client = client;
chip->enable_detection = false;
chip->gpio_detect = false;
- chip->power_supply.name = name;
- chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
- chip->power_supply.properties = sbs_properties;
- chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
- chip->power_supply.get_property = sbs_get_property;
psy_cfg.of_node = client->dev.of_node;
+ psy_cfg.drv_data = chip;
/* ignore first notification of external change, it is generated
* from the power_supply_register call back
*/
chip->ignore_changes = 1;
chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
- chip->power_supply.external_power_changed = sbs_external_power_changed;
pdata = sbs_of_populate_pdata(client);
@@ -871,7 +873,7 @@ static int sbs_probe(struct i2c_client *client,
rc = request_irq(irq, sbs_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- dev_name(&client->dev), &chip->power_supply);
+ dev_name(&client->dev), chip->power_supply);
if (rc) {
dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
gpio_free(pdata->battery_detect);
@@ -893,11 +895,12 @@ skip_gpio:
goto exit_psupply;
}
- rc = power_supply_register(&client->dev, &chip->power_supply,
- &psy_cfg);
- if (rc) {
+ chip->power_supply = power_supply_register(&client->dev, sbs_desc,
+ &psy_cfg);
+ if (IS_ERR(chip->power_supply)) {
dev_err(&client->dev,
"%s: Failed to register power supply\n", __func__);
+ rc = PTR_ERR(chip->power_supply);
goto exit_psupply;
}
@@ -912,15 +915,12 @@ skip_gpio:
exit_psupply:
if (chip->irq)
- free_irq(chip->irq, &chip->power_supply);
+ free_irq(chip->irq, chip->power_supply);
if (chip->gpio_detect)
gpio_free(pdata->battery_detect);
kfree(chip);
-exit_free_name:
- kfree(name);
-
return rc;
}
@@ -929,15 +929,14 @@ static int sbs_remove(struct i2c_client *client)
struct sbs_info *chip = i2c_get_clientdata(client);
if (chip->irq)
- free_irq(chip->irq, &chip->power_supply);
+ free_irq(chip->irq, chip->power_supply);
if (chip->gpio_detect)
gpio_free(chip->pdata->battery_detect);
- power_supply_unregister(&chip->power_supply);
+ power_supply_unregister(chip->power_supply);
cancel_delayed_work_sync(&chip->work);
- kfree(chip->power_supply.name);
kfree(chip);
chip = NULL;
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 37629affcd34..dcf9a3ca53d5 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -43,7 +43,7 @@ struct tps65090_charger {
int irq;
struct task_struct *poll_task;
bool passive_mode;
- struct power_supply ac;
+ struct power_supply *ac;
struct tps65090_platform_data *pdata;
};
@@ -135,8 +135,7 @@ static int tps65090_ac_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct tps65090_charger *charger = container_of(psy,
- struct tps65090_charger, ac);
+ struct tps65090_charger *charger = power_supply_get_drvdata(psy);
if (psp == POWER_SUPPLY_PROP_ONLINE) {
val->intval = charger->ac_online;
@@ -190,7 +189,7 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
}
if (charger->prev_ac_online != charger->ac_online)
- power_supply_changed(&charger->ac);
+ power_supply_changed(charger->ac);
return IRQ_HANDLED;
}
@@ -229,10 +228,19 @@ static int tps65090_charger_poll_task(void *data)
return 0;
}
+static const struct power_supply_desc tps65090_charger_desc = {
+ .name = "tps65090-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .get_property = tps65090_ac_get_property,
+ .properties = tps65090_ac_props,
+ .num_properties = ARRAY_SIZE(tps65090_ac_props),
+};
+
static int tps65090_charger_probe(struct platform_device *pdev)
{
struct tps65090_charger *cdata;
struct tps65090_platform_data *pdata;
+ struct power_supply_config psy_cfg = {};
uint8_t status1 = 0;
int ret;
int irq;
@@ -259,19 +267,16 @@ static int tps65090_charger_probe(struct platform_device *pdev)
cdata->dev = &pdev->dev;
cdata->pdata = pdata;
- cdata->ac.name = "tps65090-ac";
- cdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
- cdata->ac.get_property = tps65090_ac_get_property;
- cdata->ac.properties = tps65090_ac_props;
- cdata->ac.num_properties = ARRAY_SIZE(tps65090_ac_props);
- cdata->ac.supplied_to = pdata->supplied_to;
- cdata->ac.num_supplicants = pdata->num_supplicants;
- cdata->ac.of_node = pdev->dev.of_node;
-
- ret = power_supply_register(&pdev->dev, &cdata->ac, NULL);
- if (ret) {
+ psy_cfg.supplied_to = pdata->supplied_to;
+ psy_cfg.num_supplicants = pdata->num_supplicants;
+ psy_cfg.of_node = pdev->dev.of_node;
+ psy_cfg.drv_data = cdata;
+
+ cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
+ &psy_cfg);
+ if (IS_ERR(cdata->ac)) {
dev_err(&pdev->dev, "failed: power supply register\n");
- return ret;
+ return PTR_ERR(cdata->ac);
}
irq = platform_get_irq(pdev, 0);
@@ -301,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
goto fail_unregister_supply;
}
cdata->ac_online = 1;
- power_supply_changed(&cdata->ac);
+ power_supply_changed(cdata->ac);
}
if (irq != -ENXIO) {
@@ -328,7 +333,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
return 0;
fail_unregister_supply:
- power_supply_unregister(&cdata->ac);
+ power_supply_unregister(cdata->ac);
return ret;
}
@@ -339,7 +344,7 @@ static int tps65090_charger_remove(struct platform_device *pdev)
if (cdata->irq == -ENXIO)
kthread_stop(cdata->poll_task);
- power_supply_unregister(&cdata->ac);
+ power_supply_unregister(cdata->ac);
return 0;
}
diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h
index e97fc656a058..bde1a24b1f16 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -264,7 +264,8 @@ struct charger_manager {
int emergency_stop;
char psy_name_buf[PSY_NAME_MAX + 1];
- struct power_supply charger_psy;
+ struct power_supply_desc charger_psy_desc;
+ struct power_supply *charger_psy;
bool status_save_ext_pwr_inserted;
bool status_save_batt;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index c2c17ac3a608..4afbba073c4a 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -13,6 +13,7 @@
#ifndef __LINUX_POWER_SUPPLY_H__
#define __LINUX_POWER_SUPPLY_H__
+#include <linux/device.h>
#include <linux/workqueue.h>
#include <linux/leds.h>
#include <linux/spinlock.h>
@@ -173,10 +174,10 @@ union power_supply_propval {
const char *strval;
};
-struct device;
struct device_node;
+struct power_supply;
-/* Power supply instance specific configuration */
+/* Run-time specific power supply configuration */
struct power_supply_config {
struct device_node *of_node;
/* Driver private data */
@@ -186,19 +187,13 @@ struct power_supply_config {
size_t num_supplicants;
};
-struct power_supply {
+/* Description of power supply */
+struct power_supply_desc {
const char *name;
enum power_supply_type type;
enum power_supply_property *properties;
size_t num_properties;
- char **supplied_to;
- size_t num_supplicants;
-
- char **supplied_from;
- 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
@@ -224,12 +219,23 @@ struct power_supply {
bool no_thermal;
/* For APM emulation, think legacy userspace. */
int use_for_apm;
+};
+
+struct power_supply {
+ const struct power_supply_desc *desc;
+
+ char **supplied_to;
+ size_t num_supplicants;
+
+ char **supplied_from;
+ size_t num_supplies;
+ struct device_node *of_node;
/* Driver private data */
void *drv_data;
/* private */
- struct device *dev;
+ struct device dev;
struct work_struct changed_work;
spinlock_t changed_lock;
bool changed;
@@ -303,11 +309,14 @@ extern int power_supply_set_property(struct power_supply *psy,
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 int power_supply_register(struct device *parent,
- struct power_supply *psy,
+
+extern struct power_supply *__must_check
+power_supply_register(struct device *parent,
+ const struct power_supply_desc *desc,
const struct power_supply_config *cfg);
-extern int power_supply_register_no_ws(struct device *parent,
- struct power_supply *psy,
+extern struct power_supply *__must_check
+power_supply_register_no_ws(struct device *parent,
+ const struct power_supply_desc *desc,
const struct power_supply_config *cfg);
extern void power_supply_unregister(struct power_supply *psy);
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 12/19] power_supply: Add power_supply_put for decrementing device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (10 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 11/19] power_supply: Change ownership from driver to core Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 13/19] power: charger-manager: Decrement the power supply's " Krzysztof Kozlowski
` (7 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
The power_supply_get_by_phandle() and power_supply_get_by_name() use
function class_find_device() for obtaining the reference to power
supply. Each use of class_find_device() increases the power supply's
device reference counter.
However the reference counter was not decreased by users of this API.
Thus final device_unregister() call from power_supply_unregister() could
not release the device and clean up its resources. This lead to memory
leak if at least once power_supply_get_by_*() was called between
registering and unregistering the power supply.
Add and document new API power_supply_put() for decrementing the
reference counter.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
drivers/power/power_supply_core.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/power_supply.h | 1 +
2 files changed, 39 insertions(+)
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index ec9ac01074c7..074aedf6b2f2 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -335,6 +335,17 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
return strcmp(psy->desc->name, name) == 0;
}
+/**
+ * power_supply_get_by_name() - Search for a power supply and returns its ref
+ * @name: Power supply name to fetch
+ *
+ * If power supply was found, it increases reference count for the
+ * internal power supply's device. The user should power_supply_put()
+ * after usage.
+ *
+ * Return: On success returns a reference to a power supply with
+ * matching name equals to @name, a NULL otherwise.
+ */
struct power_supply *power_supply_get_by_name(const char *name)
{
struct device *dev = class_find_device(power_supply_class, NULL, name,
@@ -344,12 +355,39 @@ struct power_supply *power_supply_get_by_name(const char *name)
}
EXPORT_SYMBOL_GPL(power_supply_get_by_name);
+/**
+ * power_supply_put() - Drop reference obtained with power_supply_get_by_name
+ * @psy: Reference to put
+ *
+ * The reference to power supply should be put before unregistering
+ * the power supply.
+ */
+void power_supply_put(struct power_supply *psy)
+{
+ might_sleep();
+
+ put_device(&psy->dev);
+}
+EXPORT_SYMBOL_GPL(power_supply_put);
+
#ifdef CONFIG_OF
static int power_supply_match_device_node(struct device *dev, const void *data)
{
return dev->parent && dev->parent->of_node == data;
}
+/**
+ * power_supply_get_by_phandle() - Search for a power supply and returns its ref
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a power supply name
+ *
+ * If power supply was found, it increases reference count for the
+ * internal power supply's device. The user should power_supply_put()
+ * after usage.
+ *
+ * Return: On success returns a reference to a power supply with
+ * matching name equals to value under @property, NULL or ERR_PTR otherwise.
+ */
struct power_supply *power_supply_get_by_phandle(struct device_node *np,
const char *property)
{
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 4afbba073c4a..56e68c9156ce 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -282,6 +282,7 @@ extern struct atomic_notifier_head power_supply_notifier;
extern int power_supply_reg_notifier(struct notifier_block *nb);
extern void power_supply_unreg_notifier(struct notifier_block *nb);
extern struct power_supply *power_supply_get_by_name(const char *name);
+extern void power_supply_put(struct power_supply *psy);
#ifdef CONFIG_OF
extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
const char *property);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 13/19] power: charger-manager: Decrement the power supply's device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (11 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 12/19] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 14/19] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
` (6 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Use power_supply_put() to decrement the power supply's device reference
counter.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
drivers/power/charger-manager.c | 70 +++++++++++++++++++++++++++--------------
1 file changed, 47 insertions(+), 23 deletions(-)
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index a9870b9ff571..648b84289749 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -116,6 +116,7 @@ static bool is_batt_present(struct charger_manager *cm)
&val);
if (ret == 0 && val.intval)
present = true;
+ power_supply_put(psy);
break;
case CM_CHARGER_STAT:
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
@@ -129,6 +130,7 @@ static bool is_batt_present(struct charger_manager *cm)
ret = power_supply_get_property(psy,
POWER_SUPPLY_PROP_PRESENT, &val);
+ power_supply_put(psy);
if (ret == 0 && val.intval) {
present = true;
break;
@@ -166,6 +168,7 @@ static bool is_ext_pwr_online(struct charger_manager *cm)
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
&val);
+ power_supply_put(psy);
if (ret == 0 && val.intval) {
online = true;
break;
@@ -195,6 +198,7 @@ static int get_batt_uV(struct charger_manager *cm, int *uV)
ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+ power_supply_put(fuel_gauge);
if (ret)
return ret;
@@ -238,10 +242,13 @@ static bool is_charging(struct charger_manager *cm)
if (ret) {
dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
cm->desc->psy_charger_stat[i]);
+ power_supply_put(psy);
continue;
}
- if (val.intval == 0)
+ if (val.intval == 0) {
+ power_supply_put(psy);
continue;
+ }
/*
* 3. The charger should not be FULL, DISCHARGING,
@@ -249,6 +256,7 @@ static bool is_charging(struct charger_manager *cm)
*/
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS,
&val);
+ power_supply_put(psy);
if (ret) {
dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
cm->desc->psy_charger_stat[i]);
@@ -276,6 +284,7 @@ static bool is_full_charged(struct charger_manager *cm)
struct charger_desc *desc = cm->desc;
union power_supply_propval val;
struct power_supply *fuel_gauge;
+ bool is_full = false;
int ret = 0;
int uV;
@@ -293,15 +302,19 @@ static bool is_full_charged(struct charger_manager *cm)
/* Not full if capacity of fuel gauge isn't full */
ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_FULL, &val);
- if (!ret && val.intval > desc->fullbatt_full_capacity)
- return true;
+ if (!ret && val.intval > desc->fullbatt_full_capacity) {
+ is_full = true;
+ goto out;
+ }
}
/* Full, if it's over the fullbatt voltage */
if (desc->fullbatt_uV > 0) {
ret = get_batt_uV(cm, &uV);
- if (!ret && uV >= desc->fullbatt_uV)
- return true;
+ if (!ret && uV >= desc->fullbatt_uV) {
+ is_full = true;
+ goto out;
+ }
}
/* Full, if the capacity is more than fullbatt_soc */
@@ -310,11 +323,15 @@ static bool is_full_charged(struct charger_manager *cm)
ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CAPACITY, &val);
- if (!ret && val.intval >= desc->fullbatt_soc)
- return true;
+ if (!ret && val.intval >= desc->fullbatt_soc) {
+ is_full = true;
+ goto out;
+ }
}
- return false;
+out:
+ power_supply_put(fuel_gauge);
+ return is_full;
}
/**
@@ -587,14 +604,18 @@ static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
int *temp)
{
struct power_supply *fuel_gauge;
+ int ret;
fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
if (!fuel_gauge)
return -ENODEV;
- return power_supply_get_property(fuel_gauge,
+ ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_TEMP,
(union power_supply_propval *)temp);
+ power_supply_put(fuel_gauge);
+
+ return ret;
}
static int cm_get_battery_temperature(struct charger_manager *cm,
@@ -876,7 +897,7 @@ static int charger_get_property(struct power_supply *psy,
{
struct charger_manager *cm = power_supply_get_drvdata(psy);
struct charger_desc *desc = cm->desc;
- struct power_supply *fuel_gauge;
+ struct power_supply *fuel_gauge = NULL;
int ret = 0;
int uV;
@@ -919,12 +940,6 @@ static int charger_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
return cm_get_battery_temperature(cm, &val->intval);
case POWER_SUPPLY_PROP_CAPACITY:
- fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
- if (!fuel_gauge) {
- ret = -ENODEV;
- break;
- }
-
if (!is_batt_present(cm)) {
/* There is no battery. Assume 100% */
val->intval = 100;
@@ -935,6 +950,12 @@ static int charger_get_property(struct power_supply *psy,
mdelay(2000);
pr_err("End wait...\n");
+ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+ if (!fuel_gauge) {
+ ret = -ENODEV;
+ break;
+ }
+
ret = power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CAPACITY, val);
if (ret)
@@ -1009,6 +1030,8 @@ static int charger_get_property(struct power_supply *psy,
default:
return -EINVAL;
}
+ if (fuel_gauge)
+ power_supply_put(fuel_gauge);
return ret;
}
@@ -1809,13 +1832,7 @@ static int charger_manager_probe(struct platform_device *pdev)
desc->psy_charger_stat[i]);
return -ENODEV;
}
- }
-
- fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
- if (!fuel_gauge) {
- dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
- desc->psy_fuel_gauge);
- return -ENODEV;
+ power_supply_put(psy);
}
if (desc->polling_interval_ms == 0 ||
@@ -1855,6 +1872,12 @@ static int charger_manager_probe(struct platform_device *pdev)
cm->charger_psy_desc.num_properties = psy_default.num_properties;
/* Find which optional psy-properties are available */
+ fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
+ if (!fuel_gauge) {
+ dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
+ desc->psy_fuel_gauge);
+ return -ENODEV;
+ }
if (!power_supply_get_property(fuel_gauge,
POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
@@ -1874,6 +1897,7 @@ static int charger_manager_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to initialize thermal data\n");
cm->desc->measure_battery_temp = false;
}
+ power_supply_put(fuel_gauge);
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 14/19] x86/olpc/xo1/sci: Use newly added power_supply_put API
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (12 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 13/19] power: charger-manager: Decrement the power supply's " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 15/19] x86/olpc/xo15/sci: " Krzysztof Kozlowski
` (5 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct usage of put_device() with new API: power_supply_put().
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
arch/x86/platform/olpc/olpc-xo1-sci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
index 9a2e590dd202..7fa8b3b53bc0 100644
--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -61,7 +61,7 @@ static void battery_status_changed(void)
if (psy) {
power_supply_changed(psy);
- put_device(psy->dev);
+ power_supply_put(psy);
}
}
@@ -71,7 +71,7 @@ static void ac_status_changed(void)
if (psy) {
power_supply_changed(psy);
- put_device(psy->dev);
+ power_supply_put(psy);
}
}
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 15/19] x86/olpc/xo15/sci: Use newly added power_supply_put API
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (13 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 14/19] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 16/19] power: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
` (4 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Replace direct usage of put_device() with new API: power_supply_put().
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
arch/x86/platform/olpc/olpc-xo15-sci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
index 08e350e757dc..55130846ac87 100644
--- a/arch/x86/platform/olpc/olpc-xo15-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -83,7 +83,7 @@ static void battery_status_changed(void)
if (psy) {
power_supply_changed(psy);
- put_device(psy->dev);
+ power_supply_put(psy);
}
}
@@ -93,7 +93,7 @@ static void ac_status_changed(void)
if (psy) {
power_supply_changed(psy);
- put_device(psy->dev);
+ power_supply_put(psy);
}
}
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 16/19] power: 88pm860x_charger: Decrement the power supply's device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (14 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 15/19] x86/olpc/xo15/sci: " Krzysztof Kozlowski
@ 2015-01-05 15:47 ` Krzysztof Kozlowski
2015-01-05 15:48 ` [RFC PATCHv2 17/19] power: bq2415x_charger: " Krzysztof Kozlowski
` (3 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:47 UTC (permalink / raw)
To: linux-arm-kernel
Use power_supply_put() to decrement the power supply's device reference
counter.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
drivers/power/88pm860x_charger.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index 59d62665b526..f88caee01ee9 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -298,13 +298,18 @@ static int set_charging_fsm(struct pm860x_charger_info *info)
return -EINVAL;
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
&data);
- if (ret)
+ if (ret) {
+ power_supply_put(psy);
return ret;
+ }
vbatt = data.intval / 1000;
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
- if (ret)
+ if (ret) {
+ power_supply_put(psy);
return ret;
+ }
+ power_supply_put(psy);
mutex_lock(&info->lock);
info->present = data.intval;
@@ -447,6 +452,7 @@ static irqreturn_t pm860x_temp_handler(int irq, void *data)
set_charging_fsm(info);
out:
+ power_supply_put(psy);
return IRQ_HANDLED;
}
@@ -507,6 +513,7 @@ static irqreturn_t pm860x_done_handler(int irq, void *data)
out:
mutex_unlock(&info->lock);
+ power_supply_put(psy);
dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
set_charging_fsm(info);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 17/19] power: bq2415x_charger: Decrement the power supply's device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (15 preceding siblings ...)
2015-01-05 15:47 ` [RFC PATCHv2 16/19] power: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
@ 2015-01-05 15:48 ` Krzysztof Kozlowski
2015-01-05 15:48 ` [RFC PATCHv2 18/19] mfd: ab8500: " Krzysztof Kozlowski
` (2 subsequent siblings)
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:48 UTC (permalink / raw)
To: linux-arm-kernel
Use power_supply_put() to decrement the power supply's device reference
counter (increased by power_supply_get_by_name() or
power_supply_get_by_phandle()).
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
drivers/power/bq2415x_charger.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 2f80de0410d9..00809dcdd34e 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1686,6 +1686,8 @@ error_4:
error_3:
bq2415x_power_supply_exit(bq);
error_2:
+ if (!IS_ERR(bq->notify_psy))
+ power_supply_put(bq->notify_psy);
kfree(name);
error_1:
mutex_lock(&bq2415x_id_mutex);
@@ -1701,8 +1703,10 @@ static int bq2415x_remove(struct i2c_client *client)
{
struct bq2415x_device *bq = i2c_get_clientdata(client);
- if (bq->notify_psy)
+ if (bq->notify_psy) {
power_supply_unreg_notifier(&bq->nb);
+ power_supply_put(bq->notify_psy);
+ }
bq2415x_sysfs_exit(bq);
bq2415x_power_supply_exit(bq);
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 18/19] mfd: ab8500: Decrement the power supply's device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (16 preceding siblings ...)
2015-01-05 15:48 ` [RFC PATCHv2 17/19] power: bq2415x_charger: " Krzysztof Kozlowski
@ 2015-01-05 15:48 ` Krzysztof Kozlowski
2015-01-20 13:36 ` Lee Jones
2015-01-05 15:48 ` [RFC PATCHv2 19/19] arm: mach-pxa: " Krzysztof Kozlowski
2015-01-21 15:22 ` [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Sebastian Reichel
19 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:48 UTC (permalink / raw)
To: linux-arm-kernel
Use power_supply_put() to decrement the power supply's device reference
counter.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/ab8500-sysctrl.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index d4a4b24be7c6..0d1825696153 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -51,6 +51,7 @@ static void ab8500_power_off(void)
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
&val);
+ power_supply_put(psy);
if (!ret && val.intval) {
charger_present = true;
@@ -73,6 +74,7 @@ static void ab8500_power_off(void)
pss[i]);
machine_restart("charging");
}
+ power_supply_put(psy);
}
shutdown:
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 19/19] arm: mach-pxa: Decrement the power supply's device reference counter
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (17 preceding siblings ...)
2015-01-05 15:48 ` [RFC PATCHv2 18/19] mfd: ab8500: " Krzysztof Kozlowski
@ 2015-01-05 15:48 ` Krzysztof Kozlowski
2015-01-21 15:22 ` [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Sebastian Reichel
19 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-05 15:48 UTC (permalink / raw)
To: linux-arm-kernel
Use power_supply_put() to decrement the power supply's device reference
counter.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
arch/arm/mach-pxa/raumfeld.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index a762b23ac830..6dc4f025e674 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -758,8 +758,10 @@ static void raumfeld_power_signal_charged(void)
struct power_supply *psy =
power_supply_get_by_name(raumfeld_power_supplicants[0]);
- if (psy)
+ if (psy) {
power_supply_set_battery_charged(psy);
+ power_supply_put(psy);
+ }
}
static int raumfeld_power_resume(void)
--
1.9.1
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-05 15:47 ` [RFC PATCHv2 07/19] mfd: " Krzysztof Kozlowski
@ 2015-01-20 13:36 ` Lee Jones
2015-01-20 14:16 ` Krzysztof Kozlowski
0 siblings, 1 reply; 29+ messages in thread
From: Lee Jones @ 2015-01-20 13:36 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> Replace direct calls to power supply function attributes with wrappers.
> Wrappers provide safe 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 <k.kozlowski@samsung.com>
> Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> Acked-by: Pavel Machek <pavel@ucw.cz>
> Acked-by: Lee Jones <lee.jones@linaro.org>
You've sent this to me already Acked. I don't see 00/00, so I have no
idea what's going on. Do you want me to take this patch? Can it be
taking on its own?
> ---
> 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 cfff0b643f1b..d4a4b24be7c6 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
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 18/19] mfd: ab8500: Decrement the power supply's device reference counter
2015-01-05 15:48 ` [RFC PATCHv2 18/19] mfd: ab8500: " Krzysztof Kozlowski
@ 2015-01-20 13:36 ` Lee Jones
0 siblings, 0 replies; 29+ messages in thread
From: Lee Jones @ 2015-01-20 13:36 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> Use power_supply_put() to decrement the power supply's device reference
> counter.
>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Acked-by: Pavel Machek <pavel@ucw.cz>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> Acked-by: Lee Jones <lee.jones@linaro.org>
You've sent this to me already Acked. I don't see 00/00, so I have no
idea what's going on. Do you want me to take this patch? Can it be
taking on its own?
> ---
> drivers/mfd/ab8500-sysctrl.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
> index d4a4b24be7c6..0d1825696153 100644
> --- a/drivers/mfd/ab8500-sysctrl.c
> +++ b/drivers/mfd/ab8500-sysctrl.c
> @@ -51,6 +51,7 @@ static void ab8500_power_off(void)
>
> ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
> &val);
> + power_supply_put(psy);
>
> if (!ret && val.intval) {
> charger_present = true;
> @@ -73,6 +74,7 @@ static void ab8500_power_off(void)
> pss[i]);
> machine_restart("charging");
> }
> + power_supply_put(psy);
> }
>
> shutdown:
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-20 13:36 ` Lee Jones
@ 2015-01-20 14:16 ` Krzysztof Kozlowski
2015-01-20 15:51 ` Lee Jones
0 siblings, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-20 14:16 UTC (permalink / raw)
To: linux-arm-kernel
On wto, 2015-01-20 at 13:36 +0000, Lee Jones wrote:
> On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
>
> > Replace direct calls to power supply function attributes with wrappers.
> > Wrappers provide safe 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 <k.kozlowski@samsung.com>
> > Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> > Acked-by: Pavel Machek <pavel@ucw.cz>
> > Acked-by: Lee Jones <lee.jones@linaro.org>
>
> You've sent this to me already Acked. I don't see 00/00, so I have no
> idea what's going on. Do you want me to take this patch? Can it be
> taking on its own?
git send-email automatically CC-you because you acked this. The depends
on previous patches adding this API so please do not pick it up.
Everything (with respective acks) should go through one power supply
tree.
The same applies to patch 18/19.
Best regards,
Krzysztof
>
> > ---
> > 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 cfff0b643f1b..d4a4b24be7c6 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."
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-20 14:16 ` Krzysztof Kozlowski
@ 2015-01-20 15:51 ` Lee Jones
2015-01-20 16:01 ` Krzysztof Kozlowski
2015-01-20 16:06 ` Pavel Machek
0 siblings, 2 replies; 29+ messages in thread
From: Lee Jones @ 2015-01-20 15:51 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 20 Jan 2015, Krzysztof Kozlowski wrote:
> On wto, 2015-01-20 at 13:36 +0000, Lee Jones wrote:
> > On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> >
> > > Replace direct calls to power supply function attributes with wrappers.
> > > Wrappers provide safe 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 <k.kozlowski@samsung.com>
> > > Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> > > Acked-by: Pavel Machek <pavel@ucw.cz>
> > > Acked-by: Lee Jones <lee.jones@linaro.org>
> >
> > You've sent this to me already Acked. I don't see 00/00, so I have no
> > idea what's going on. Do you want me to take this patch? Can it be
> > taking on its own?
>
> git send-email automatically CC-you because you acked this. The depends
> on previous patches adding this API so please do not pick it up.
You should always send MFD related patches to me (either
automatically, or manually).
> Everything (with respective acks) should go through one power supply
> tree.
That's not how it works. We need to decide that amongst ourselves
and it needs to culminate in pull-requests being sent out to all of
the effected Maintainers.
> The same applies to patch 18/19.
>
> Best regards,
> Krzysztof
>
> >
> > > ---
> > > 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 cfff0b643f1b..d4a4b24be7c6 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
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-20 15:51 ` Lee Jones
@ 2015-01-20 16:01 ` Krzysztof Kozlowski
2015-01-20 16:26 ` Lee Jones
2015-01-20 16:06 ` Pavel Machek
1 sibling, 1 reply; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-20 16:01 UTC (permalink / raw)
To: linux-arm-kernel
On wto, 2015-01-20 at 15:51 +0000, Lee Jones wrote:
> On Tue, 20 Jan 2015, Krzysztof Kozlowski wrote:
>
> > On wto, 2015-01-20 at 13:36 +0000, Lee Jones wrote:
> > > On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> > >
> > > > Replace direct calls to power supply function attributes with wrappers.
> > > > Wrappers provide safe 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 <k.kozlowski@samsung.com>
> > > > Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> > > > Acked-by: Pavel Machek <pavel@ucw.cz>
> > > > Acked-by: Lee Jones <lee.jones@linaro.org>
> > >
> > > You've sent this to me already Acked. I don't see 00/00, so I have no
> > > idea what's going on. Do you want me to take this patch? Can it be
> > > taking on its own?
> >
> > git send-email automatically CC-you because you acked this. The depends
> > on previous patches adding this API so please do not pick it up.
>
> You should always send MFD related patches to me (either
> automatically, or manually).
>
> > Everything (with respective acks) should go through one power supply
> > tree.
>
> That's not how it works. We need to decide that amongst ourselves
> and it needs to culminate in pull-requests being sent out to all of
> the effected Maintainers.
OK, I understand. My reply sounded kind a imperative but that was not
what I wanted to say... The patchset adds some API first so most of
patches cannot be picked independently.
Thank you for proactive concern about the patch.
Best regards,
Krzysztof
>
> > The same applies to patch 18/19.
> >
> > Best regards,
> > Krzysztof
> >
> > >
> > > > ---
> > > > 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 cfff0b643f1b..d4a4b24be7c6 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."
> > >
> >
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-20 15:51 ` Lee Jones
2015-01-20 16:01 ` Krzysztof Kozlowski
@ 2015-01-20 16:06 ` Pavel Machek
1 sibling, 0 replies; 29+ messages in thread
From: Pavel Machek @ 2015-01-20 16:06 UTC (permalink / raw)
To: linux-arm-kernel
On Tue 2015-01-20 15:51:49, Lee Jones wrote:
> On Tue, 20 Jan 2015, Krzysztof Kozlowski wrote:
>
> > On wto, 2015-01-20 at 13:36 +0000, Lee Jones wrote:
> > > On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> > >
> > > > Replace direct calls to power supply function attributes with wrappers.
> > > > Wrappers provide safe 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 <k.kozlowski@samsung.com>
> > > > Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> > > > Acked-by: Pavel Machek <pavel@ucw.cz>
> > > > Acked-by: Lee Jones <lee.jones@linaro.org>
> > >
> > > You've sent this to me already Acked. I don't see 00/00, so I have no
> > > idea what's going on. Do you want me to take this patch? Can it be
> > > taking on its own?
> >
> > git send-email automatically CC-you because you acked this. The depends
> > on previous patches adding this API so please do not pick it up.
>
> You should always send MFD related patches to me (either
> automatically, or manually).
>
> > Everything (with respective acks) should go through one power supply
> > tree.
>
> That's not how it works. We need to decide that amongst ourselves
> and it needs to culminate in pull-requests being sent out to all of
> the effected Maintainers.
So go ahead and decide. If the patches are ok, I see no problem in it
going through power supply tree, and neither should you. I feel you
are making it more complex than it is.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 07/19] mfd: ab8500: Use power_supply_*() API for accessing function attrs
2015-01-20 16:01 ` Krzysztof Kozlowski
@ 2015-01-20 16:26 ` Lee Jones
0 siblings, 0 replies; 29+ messages in thread
From: Lee Jones @ 2015-01-20 16:26 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 20 Jan 2015, Krzysztof Kozlowski wrote:
> On wto, 2015-01-20 at 15:51 +0000, Lee Jones wrote:
> > On Tue, 20 Jan 2015, Krzysztof Kozlowski wrote:
> >
> > > On wto, 2015-01-20 at 13:36 +0000, Lee Jones wrote:
> > > > On Mon, 05 Jan 2015, Krzysztof Kozlowski wrote:
> > > >
> > > > > Replace direct calls to power supply function attributes with wrappers.
> > > > > Wrappers provide safe 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 <k.kozlowski@samsung.com>
> > > > > Acked-by: Jonghwa Lee <jonghwa3.lee@samusng.com>
> > > > > Acked-by: Pavel Machek <pavel@ucw.cz>
> > > > > Acked-by: Lee Jones <lee.jones@linaro.org>
> > > >
> > > > You've sent this to me already Acked. I don't see 00/00, so I have no
> > > > idea what's going on. Do you want me to take this patch? Can it be
> > > > taking on its own?
> > >
> > > git send-email automatically CC-you because you acked this. The depends
> > > on previous patches adding this API so please do not pick it up.
> >
> > You should always send MFD related patches to me (either
> > automatically, or manually).
> >
> > > Everything (with respective acks) should go through one power supply
> > > tree.
> >
> > That's not how it works. We need to decide that amongst ourselves
> > and it needs to culminate in pull-requests being sent out to all of
> > the effected Maintainers.
>
> OK, I understand. My reply sounded kind a imperative but that was not
> what I wanted to say...
It did, hence my response. Thanks for the clarification.
> The patchset adds some API first so most of
> patches cannot be picked independently.
I appreciate that and I'm happy for the patches to go in via whichever
tree is the most appropriate.
> Thank you for proactive concern about the patch.
You are welcome.
> So go ahead and decide. If the patches are ok, I see no problem in it
> going through power supply tree, and neither should you. I feel you
> are making it more complex than it is.
I think you are missing the point -- Krzysztof got it. It's probably
okay for some patches from one subsystem to go in via another, but
it's usually prudent to at least tag them and offer others the chance
of pulling them in to other trees. This significantly aids in
lessening the chances of a merge conflict during the merge-window and
mitigates the possibility of an upset Linus.
As I've already said, I'm happy for this set to go in via the Power
Supply tree, but assumptions shouldn't be made and all affected
Maintainers should at least have a vote in cases like this.
> > > The same applies to patch 18/19.
> > >
> > > Best regards,
> > > Krzysztof
> > >
> > > >
> > > > > ---
> > > > > 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 cfff0b643f1b..d4a4b24be7c6 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
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
` (18 preceding siblings ...)
2015-01-05 15:48 ` [RFC PATCHv2 19/19] arm: mach-pxa: " Krzysztof Kozlowski
@ 2015-01-21 15:22 ` Sebastian Reichel
2015-01-21 15:42 ` Krzysztof Kozlowski
19 siblings, 1 reply; 29+ messages in thread
From: Sebastian Reichel @ 2015-01-21 15:22 UTC (permalink / raw)
To: linux-arm-kernel
Hi Krzysztof,
On Mon, Jan 05, 2015 at 04:47:43PM +0100, Krzysztof Kozlowski wrote:
> This is RFC, please don't apply yet but let me know if this approach
> is OK.
I just reviewed the patchset. It looks fine to me.
> TLDR
> ====
> Patchset tries to fix following race scenario:
>
> Thread 1: charger manager, CONSUMER
> Thread 2: power supply driver, PROVIDER
>
> 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()
>
> To properly fix the race the patchset:
> 1. Adds power_supply_get_property()-like API for safe access by consumer.
> 2. Moves ownership of power_supply structure from driver (provider) to
> power supply core.
> 3. Adds power_supply_put() which will reclaim memory.
Looks fine to me, thanks for doing this :)
> Description
> ===========
> This is a little different than my previous approaches [1][2] for fixing
> usage of power supply by some consumer, if driver implementing it is
> unbound.
>
> The patchset is quite big and touches power supply API so a lot of
> changes in drivers are needed. These changes *are not finished yet*.
> I've done them only for:
> - bq24190_charger.c
> - charger-manager.c
> - max14577_charger.c
> - max17040_battery.c
> - max17042_battery.c
> - sbs-battery.c
> - tps65090-charger.c
> So allyesconfig won't build.
>
> If this approach is OK, I'll prepare full patchset changing all the
> drivers.
Please do :)
> My previous approach [1][2] limited the race but did not close it.
> Still the consumer of power supply by calling power_supply_get_propert(psy...)
> may reference invalid memory because the producer freed it.
>
> Actually, because struct power_supply is exposed to consumers, the
> core should be the owner of it. This is accomplished in patch 11/19
> ("power_supply: Change ownership from driver to core").
>
> What the patchset does in steps
> ===============================
> 1. Some preparation steps are necessary - patch 1 and 2. The driver
> implementing power supply won't be able to fill structure before
> calling power_supply_register(). So 'power_supply_config'
> is introduced in patch 2 ("power_supply: Move run-time configuration
> to separate structure"). Unfortunately this touches all drivers.
$ grep -l power_supply_register **/*.c | grep -v mod.c | grep -v drivers/power
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/sbs.c
drivers/hid/hid-input.c
drivers/hid/hid-sony.c
drivers/hid/hid-wiimote-modules.c
drivers/hid/wacom_sys.c
drivers/platform/x86/compal-laptop.c
drivers/staging/nvec/nvec_power.c
Please make sure to CC the respective maintainers for the patchset
(e.g. current patch 14 and 15 should have CC'd x86 maintainers), so
that they can Acknowledge the patchset.
> 2. Safe API wrappers (and usage counter) are added (power_supply_*()).
> 3. Patch 11: ownership of 'struct power_supply' is moved from driver
> to the core.
> 4. power_supply_put() is added which reclaims resources.
Looks fine to me.
> The patchset is rebased on next-20141226. It should be pulled at once.
> Bisectability is preserved.
Fine with me, but I need acks from all involved maintainers. So for the
patchset:
Reviewed-By: Sebastian Reichel <sre@kernel.org>
-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150121/92ef74fa/attachment.sig>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply
2015-01-21 15:22 ` [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Sebastian Reichel
@ 2015-01-21 15:42 ` Krzysztof Kozlowski
0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-21 15:42 UTC (permalink / raw)
To: linux-arm-kernel
On ?ro, 2015-01-21 at 16:22 +0100, Sebastian Reichel wrote:
> Hi Krzysztof,
>
> On Mon, Jan 05, 2015 at 04:47:43PM +0100, Krzysztof Kozlowski wrote:
> > This is RFC, please don't apply yet but let me know if this approach
> > is OK.
>
> I just reviewed the patchset. It looks fine to me.
Great! Thanks for looking at patchset. I'll start working on next
version adjusting all drivers.
>
> > TLDR
> > ====
> > Patchset tries to fix following race scenario:
> >
> > Thread 1: charger manager, CONSUMER
> > Thread 2: power supply driver, PROVIDER
> >
> > 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()
> >
> > To properly fix the race the patchset:
> > 1. Adds power_supply_get_property()-like API for safe access by consumer.
> > 2. Moves ownership of power_supply structure from driver (provider) to
> > power supply core.
> > 3. Adds power_supply_put() which will reclaim memory.
>
> Looks fine to me, thanks for doing this :)
>
> > Description
> > ===========
> > This is a little different than my previous approaches [1][2] for fixing
> > usage of power supply by some consumer, if driver implementing it is
> > unbound.
> >
> > The patchset is quite big and touches power supply API so a lot of
> > changes in drivers are needed. These changes *are not finished yet*.
> > I've done them only for:
> > - bq24190_charger.c
> > - charger-manager.c
> > - max14577_charger.c
> > - max17040_battery.c
> > - max17042_battery.c
> > - sbs-battery.c
> > - tps65090-charger.c
> > So allyesconfig won't build.
> >
> > If this approach is OK, I'll prepare full patchset changing all the
> > drivers.
>
> Please do :)
>
> > My previous approach [1][2] limited the race but did not close it.
> > Still the consumer of power supply by calling power_supply_get_propert(psy...)
> > may reference invalid memory because the producer freed it.
> >
> > Actually, because struct power_supply is exposed to consumers, the
> > core should be the owner of it. This is accomplished in patch 11/19
> > ("power_supply: Change ownership from driver to core").
> >
> > What the patchset does in steps
> > ===============================
> > 1. Some preparation steps are necessary - patch 1 and 2. The driver
> > implementing power supply won't be able to fill structure before
> > calling power_supply_register(). So 'power_supply_config'
> > is introduced in patch 2 ("power_supply: Move run-time configuration
> > to separate structure"). Unfortunately this touches all drivers.
>
> $ grep -l power_supply_register **/*.c | grep -v mod.c | grep -v drivers/power
> drivers/acpi/ac.c
> drivers/acpi/battery.c
> drivers/acpi/sbs.c
> drivers/hid/hid-input.c
> drivers/hid/hid-sony.c
> drivers/hid/hid-wiimote-modules.c
> drivers/hid/wacom_sys.c
> drivers/platform/x86/compal-laptop.c
> drivers/staging/nvec/nvec_power.c
>
> Please make sure to CC the respective maintainers for the patchset
> (e.g. current patch 14 and 15 should have CC'd x86 maintainers), so
> that they can Acknowledge the patchset.
Right. Probably maintainers should receive full patchset anyway. The
address list will be quite big.
>
> > 2. Safe API wrappers (and usage counter) are added (power_supply_*()).
> > 3. Patch 11: ownership of 'struct power_supply' is moved from driver
> > to the core.
> > 4. power_supply_put() is added which reclaims resources.
>
> Looks fine to me.
>
> > The patchset is rebased on next-20141226. It should be pulled at once.
> > Bisectability is preserved.
>
> Fine with me, but I need acks from all involved maintainers. So for the
> patchset:
>
> Reviewed-By: Sebastian Reichel <sre@kernel.org>
Thanks!
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2015-01-21 15:42 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-05 15:47 [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 01/19] power_supply: Add driver private data Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 02/19] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 03/19] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 04/19] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 05/19] power: 88pm860x_charger: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 06/19] power: ab8500: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 07/19] mfd: " Krzysztof Kozlowski
2015-01-20 13:36 ` Lee Jones
2015-01-20 14:16 ` Krzysztof Kozlowski
2015-01-20 15:51 ` Lee Jones
2015-01-20 16:01 ` Krzysztof Kozlowski
2015-01-20 16:26 ` Lee Jones
2015-01-20 16:06 ` Pavel Machek
2015-01-05 15:47 ` [RFC PATCHv2 08/19] power: apm_power: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 09/19] power: bq2415x_charger: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 10/19] power: charger-manager: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 11/19] power_supply: Change ownership from driver to core Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 12/19] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 13/19] power: charger-manager: Decrement the power supply's " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 14/19] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 15/19] x86/olpc/xo15/sci: " Krzysztof Kozlowski
2015-01-05 15:47 ` [RFC PATCHv2 16/19] power: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
2015-01-05 15:48 ` [RFC PATCHv2 17/19] power: bq2415x_charger: " Krzysztof Kozlowski
2015-01-05 15:48 ` [RFC PATCHv2 18/19] mfd: ab8500: " Krzysztof Kozlowski
2015-01-20 13:36 ` Lee Jones
2015-01-05 15:48 ` [RFC PATCHv2 19/19] arm: mach-pxa: " Krzysztof Kozlowski
2015-01-21 15:22 ` [RFC PATCHv2 00/19] power_supply: Allow safe usage of power supply Sebastian Reichel
2015-01-21 15:42 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).