linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/20] power_supply: Allow safe usage of power supply
@ 2015-01-30 14:47 Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 01/20] power_supply: Add driver private data Krzysztof Kozlowski
                   ` (19 more replies)
  0 siblings, 20 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

The patchset changes power supply API and drivers implementing
power supply class.


TLDR for driver and subsystem maintainers
=========================================
Two patches of patchset change power_supply_register() function so in
the same time they touch all drivers. I am kindly asking for acks,
review and help in testing.

Please look at:
 - patch 2: power_supply: Move run-time configuration to separate structure
 - patch 11: power_supply: Change ownership from driver to core

These are huge.


Introduction
============
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. Moves ownership of power_supply structure from driver (provider) to
   power supply core.
2. Adds power_supply_get_property()-like API for safe access by consumer.
3. Adds power_supply_put() which will reclaim memory.


Description
=========== 
The patchset is quite big and touches power supply API so a lot of
changes in drivers are needed.

I modifed all drivers I found. However I only compile tested them
(plus Smatch, Sparse and coccicheck). I did not test them on real
hardware (except max14577, max77693, max17040, max17042
and charger-manager).

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.

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/20
("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.
   *All drivers touched.*

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.
   *All drivers touched.*

4. power_supply_put() is added which reclaims resources.


The patchset is rebased on next-20150129. Bisectability is preserved.
All later patches depend on previous ones so it could be pulled in
steps, but cherry-picking won't work.

Changes since v2
================
1. Rewrite all drivers to new power_supply_register().
2. Add reviewed-by Bartlomiej Zolnierkiewicz (internal review)
3. Add reviewed-by Sebastian Reichel [3] (to patches which I did not
   change in major way between v2 and v3).
4. Use atomic usage counter of power supply on each of:
   a. register/unregister,
   b. get/put.

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
[3] https://lkml.org/lkml/2015/1/21/471

Best regards,
Krzysztof


Krzysztof Kozlowski (20):
  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_supply: 88pm860x_charger: Use power_supply_*() API for accessing
    function attrs
  power_supply: ab8500: Use power_supply_*() API for accessing function
    attrs
  mfd: ab8500: Use power_supply_*() API for accessing function attrs
  power_supply: apm_power: Use power_supply_*() API for accessing
    function attrs
  power_supply: bq2415x_charger: Use power_supply_*() API for accessing
    function attrs
  power_supply: 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_supply: Increment power supply use counter when obtaining
    references
  power_supply: 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_supply: 88pm860x_charger: Decrement the power supply's device
    reference counter
  power_supply: 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/ac.c                         |  32 ++--
 drivers/acpi/battery.c                    |  54 ++++---
 drivers/acpi/sbs.c                        |  68 +++++----
 drivers/hid/hid-input.c                   |  51 ++++---
 drivers/hid/hid-sony.c                    |  43 +++---
 drivers/hid/hid-wiimote-modules.c         |  41 ++---
 drivers/hid/hid-wiimote.h                 |   3 +-
 drivers/hid/wacom.h                       |   8 +-
 drivers/hid/wacom_sys.c                   |  70 +++++----
 drivers/mfd/ab8500-sysctrl.c              |   9 +-
 drivers/platform/x86/compal-laptop.c      |  29 ++--
 drivers/power/88pm860x_battery.c          |  40 ++---
 drivers/power/88pm860x_charger.c          |  61 +++++---
 drivers/power/ab8500_btemp.c              |  75 +++++----
 drivers/power/ab8500_charger.c            | 139 +++++++++--------
 drivers/power/ab8500_fg.c                 | 129 +++++++---------
 drivers/power/abx500_chargalg.c           |  98 ++++++------
 drivers/power/apm_power.c                 |   6 +-
 drivers/power/bq2415x_charger.c           | 107 +++++++------
 drivers/power/bq24190_charger.c           | 103 ++++++-------
 drivers/power/bq24735-charger.c           |  53 ++++---
 drivers/power/bq27x00_battery.c           |  70 ++++-----
 drivers/power/charger-manager.c           | 158 +++++++++++--------
 drivers/power/collie_battery.c            |  75 +++++----
 drivers/power/da9030_battery.c            |  32 ++--
 drivers/power/da9052-battery.c            |  25 +--
 drivers/power/ds2760_battery.c            |  56 +++----
 drivers/power/ds2780_battery.c            |  45 +++---
 drivers/power/ds2781_battery.c            |  46 +++---
 drivers/power/ds2782_battery.c            |  30 ++--
 drivers/power/generic-adc-battery.c       |  54 ++++---
 drivers/power/goldfish_battery.c          |  62 ++++----
 drivers/power/gpio-charger.c              |  42 +++---
 drivers/power/intel_mid_battery.c         |  57 ++++---
 drivers/power/ipaq_micro_battery.c        |  34 +++--
 drivers/power/isp1704_charger.c           |  49 +++---
 drivers/power/jz4740-battery.c            |  37 +++--
 drivers/power/lp8727_charger.c            |  94 ++++++------
 drivers/power/lp8788-charger.c            |  62 +++++---
 drivers/power/ltc2941-battery-gauge.c     |  51 ++++---
 drivers/power/max14577_charger.c          |  34 +++--
 drivers/power/max17040_battery.c          |  31 ++--
 drivers/power/max17042_battery.c          |  45 ++++--
 drivers/power/max77693_charger.c          |  32 ++--
 drivers/power/max8903_charger.c           |  52 ++++---
 drivers/power/max8925_power.c             |  98 ++++++------
 drivers/power/max8997_charger.c           |  31 ++--
 drivers/power/max8998_charger.c           |  32 ++--
 drivers/power/olpc_battery.c              |  54 ++++---
 drivers/power/pcf50633-charger.c          | 105 +++++++------
 drivers/power/pda_power.c                 |  65 ++++----
 drivers/power/pm2301_charger.c            |  48 +++---
 drivers/power/pm2301_charger.h            |   1 +
 drivers/power/pmu_battery.c               |  42 ++++--
 drivers/power/power_supply_core.c         | 243 ++++++++++++++++++++++--------
 drivers/power/power_supply_leds.c         |  25 +--
 drivers/power/power_supply_sysfs.c        |  24 +--
 drivers/power/rt5033_battery.c            |  27 ++--
 drivers/power/rx51_battery.c              |  27 ++--
 drivers/power/s3c_adc_battery.c           |  76 +++++-----
 drivers/power/sbs-battery.c               |  71 ++++-----
 drivers/power/smb347-charger.c            | 108 +++++++------
 drivers/power/test_power.c                |  53 ++++---
 drivers/power/tosa_battery.c              | 112 ++++++++------
 drivers/power/tps65090-charger.c          |  43 +++---
 drivers/power/twl4030_charger.c           |  65 ++++----
 drivers/power/twl4030_madc_battery.c      |  41 ++---
 drivers/power/wm831x_backup.c             |  26 ++--
 drivers/power/wm831x_power.c              |  95 ++++++------
 drivers/power/wm8350_power.c              |  89 ++++++-----
 drivers/power/wm97xx_battery.c            |  37 ++---
 drivers/power/z2_battery.c                |  60 ++++----
 drivers/staging/nvec/nvec_power.c         |  34 +++--
 include/linux/hid.h                       |   6 +-
 include/linux/mfd/abx500/ux500_chargalg.h |  11 +-
 include/linux/mfd/rt5033.h                |   2 +-
 include/linux/mfd/wm8350/supply.h         |   6 +-
 include/linux/power/charger-manager.h     |   3 +-
 include/linux/power_supply.h              |  70 +++++++--
 82 files changed, 2467 insertions(+), 1867 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 01/20] power_supply: Add driver private data
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 01/20] power_supply: Add driver private data Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-02-07  2:19   ` Darren Hart
  2015-01-30 14:47 ` [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Add new structure 'power_supply_config' for holding run-time
initialization data like of_node, supplies and private driver data.

The power_supply_register() function is changed so all power supply
drivers need updating.

When registering the power supply this new 'power_supply_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.

When a driver does not use of_node or supplies then it should use NULL
as config. If driver uses of_node or supplies then it should allocate
config on stack and initialize it with proper values.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/acpi/ac.c                     |  2 +-
 drivers/acpi/battery.c                |  3 ++-
 drivers/acpi/sbs.c                    |  4 ++--
 drivers/hid/hid-input.c               |  2 +-
 drivers/hid/hid-sony.c                |  2 +-
 drivers/hid/hid-wiimote-modules.c     |  2 +-
 drivers/hid/wacom_sys.c               |  5 +++--
 drivers/platform/x86/compal-laptop.c  |  2 +-
 drivers/power/88pm860x_battery.c      |  2 +-
 drivers/power/88pm860x_charger.c      |  7 ++++---
 drivers/power/ab8500_btemp.c          |  7 ++++---
 drivers/power/ab8500_charger.c        | 15 +++++++++------
 drivers/power/ab8500_fg.c             |  8 +++++---
 drivers/power/abx500_chargalg.c       |  8 +++++---
 drivers/power/bq2415x_charger.c       |  2 +-
 drivers/power/bq24190_charger.c       |  4 ++--
 drivers/power/bq24735-charger.c       | 10 ++++++----
 drivers/power/bq27x00_battery.c       |  2 +-
 drivers/power/charger-manager.c       |  2 +-
 drivers/power/collie_battery.c        |  4 ++--
 drivers/power/da9030_battery.c        |  2 +-
 drivers/power/da9052-battery.c        |  2 +-
 drivers/power/ds2760_battery.c        |  2 +-
 drivers/power/ds2780_battery.c        |  2 +-
 drivers/power/ds2781_battery.c        |  2 +-
 drivers/power/ds2782_battery.c        |  2 +-
 drivers/power/generic-adc-battery.c   |  2 +-
 drivers/power/goldfish_battery.c      |  4 ++--
 drivers/power/gpio-charger.c          | 10 ++++++----
 drivers/power/intel_mid_battery.c     |  4 ++--
 drivers/power/ipaq_micro_battery.c    |  4 ++--
 drivers/power/isp1704_charger.c       |  2 +-
 drivers/power/jz4740-battery.c        |  2 +-
 drivers/power/lp8727_charger.c        | 14 +++++++-------
 drivers/power/lp8788-charger.c        | 11 +++++++----
 drivers/power/ltc2941-battery-gauge.c |  2 +-
 drivers/power/max14577_charger.c      |  2 +-
 drivers/power/max17040_battery.c      |  2 +-
 drivers/power/max17042_battery.c      |  2 +-
 drivers/power/max77693_charger.c      |  2 +-
 drivers/power/max8903_charger.c       |  2 +-
 drivers/power/max8925_power.c         | 14 +++++++-------
 drivers/power/max8997_charger.c       |  2 +-
 drivers/power/max8998_charger.c       |  2 +-
 drivers/power/olpc_battery.c          |  4 ++--
 drivers/power/pcf50633-charger.c      | 16 +++++++---------
 drivers/power/pda_power.c             | 18 ++++++++----------
 drivers/power/pm2301_charger.c        |  8 +++++---
 drivers/power/pmu_battery.c           |  4 ++--
 drivers/power/power_supply_core.c     | 20 +++++++++++++++-----
 drivers/power/rt5033_battery.c        |  2 +-
 drivers/power/rx51_battery.c          |  2 +-
 drivers/power/s3c_adc_battery.c       |  4 ++--
 drivers/power/sbs-battery.c           |  6 ++++--
 drivers/power/smb347-charger.c        | 13 ++++++-------
 drivers/power/test_power.c            | 21 ++++++++++++++++-----
 drivers/power/tosa_battery.c          |  6 +++---
 drivers/power/tps65090-charger.c      | 10 ++++++----
 drivers/power/twl4030_charger.c       |  4 ++--
 drivers/power/twl4030_madc_battery.c  |  2 +-
 drivers/power/wm831x_backup.c         |  2 +-
 drivers/power/wm831x_power.c          |  6 +++---
 drivers/power/wm8350_power.c          |  6 +++---
 drivers/power/wm97xx_battery.c        |  2 +-
 drivers/power/z2_battery.c            |  2 +-
 drivers/staging/nvec/nvec_power.c     |  7 ++++---
 include/linux/power_supply.h          | 16 ++++++++++++++--
 67 files changed, 211 insertions(+), 158 deletions(-)

diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 36b0e61f9c09..8bf516885ede 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -351,7 +351,7 @@ static int acpi_ac_add(struct acpi_device *device)
 	ac->charger.properties = ac_props;
 	ac->charger.num_properties = ARRAY_SIZE(ac_props);
 	ac->charger.get_property = get_ac_property;
-	result = power_supply_register(&ac->device->dev, &ac->charger);
+	result = power_supply_register(&ac->device->dev, &ac->charger, NULL);
 	if (result)
 		goto end;
 
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/acpi/sbs.c b/drivers/acpi/sbs.c
index a7a3edd28beb..2038ec1d021d 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -540,7 +540,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
 		    ARRAY_SIZE(sbs_energy_battery_props);
 	}
 	battery->bat.get_property = acpi_sbs_battery_get_property;
-	result = power_supply_register(&sbs->device->dev, &battery->bat);
+	result = power_supply_register(&sbs->device->dev, &battery->bat, NULL);
 	if (result)
 		goto end;
 
@@ -580,7 +580,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
 	sbs->charger.properties = sbs_ac_props;
 	sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
 	sbs->charger.get_property = sbs_get_ac_property;
-	power_supply_register(&sbs->device->dev, &sbs->charger);
+	power_supply_register(&sbs->device->dev, &sbs->charger, NULL);
 	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
 	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
 	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 052869d0ab78..6182265a6571 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -439,7 +439,7 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
 	dev->battery_report_type = report_type;
 	dev->battery_report_id = field->report->id;
 
-	ret = power_supply_register(&dev->dev, battery);
+	ret = power_supply_register(&dev->dev, battery, NULL);
 	if (ret != 0) {
 		hid_warn(dev, "can't register power supply: %d\n", ret);
 		kfree(battery->name);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 31e9d2561106..16fc6a17ac63 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1718,7 +1718,7 @@ static int sony_battery_probe(struct sony_sc *sc)
 	if (!sc->battery.name)
 		return -ENOMEM;
 
-	ret = power_supply_register(&hdev->dev, &sc->battery);
+	ret = power_supply_register(&hdev->dev, &sc->battery, NULL);
 	if (ret) {
 		hid_err(hdev, "Unable to register battery device\n");
 		goto err_free;
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 6b61f01e01e7..91cb00abcb8e 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -250,7 +250,7 @@ static int wiimod_battery_probe(const struct wiimod_ops *ops,
 	if (!wdata->battery.name)
 		return -ENOMEM;
 
-	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
+	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery, NULL);
 	if (ret) {
 		hid_err(wdata->hdev, "cannot register battery device\n");
 		goto err_free;
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index f01ab3a0c5f5..d33ab600c65a 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1018,13 +1018,14 @@ static int wacom_initialize_battery(struct wacom *wacom)
 		wacom->ac.use_for_apm = 0;
 
 		error = power_supply_register(&wacom->hdev->dev,
-					      &wacom->battery);
+					      &wacom->battery, NULL);
 		if (error)
 			return error;
 
 		power_supply_powers(&wacom->battery, &wacom->hdev->dev);
 
-		error = power_supply_register(&wacom->hdev->dev, &wacom->ac);
+		error = power_supply_register(&wacom->hdev->dev, &wacom->ac,
+					      NULL);
 		if (error) {
 			power_supply_unregister(&wacom->battery);
 			return error;
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index cf55a9246f12..0f2d9e710eac 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -1036,7 +1036,7 @@ static int compal_probe(struct platform_device *pdev)
 
 	/* Power supply */
 	initialize_power_supply_data(data);
-	err = power_supply_register(&compal_device->dev, &data->psy);
+	err = power_supply_register(&compal_device->dev, &data->psy, NULL);
 	if (err < 0)
 		goto psy_err;
 
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
index bd3c997f4fee..a99d7f2829a7 100644
--- a/drivers/power/88pm860x_battery.c
+++ b/drivers/power/88pm860x_battery.c
@@ -953,7 +953,7 @@ static int pm860x_battery_probe(struct platform_device *pdev)
 	else
 		info->resistor = 300;	/* set default internal resistor */
 
-	ret = power_supply_register(&pdev->dev, &info->battery);
+	ret = power_supply_register(&pdev->dev, &info->battery, NULL);
 	if (ret)
 		return ret;
 	info->battery.dev->parent = &pdev->dev;
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index 734ec4afa14d..ac352a6c03ea 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -648,6 +648,7 @@ static struct pm860x_irq_desc {
 static int pm860x_charger_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct power_supply_config psy_cfg = {};
 	struct pm860x_charger_info *info;
 	int ret;
 	int count;
@@ -687,12 +688,12 @@ static int pm860x_charger_probe(struct platform_device *pdev)
 
 	info->usb.name = "usb";
 	info->usb.type = POWER_SUPPLY_TYPE_USB;
-	info->usb.supplied_to = pm860x_supplied_to;
-	info->usb.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
 	info->usb.properties = pm860x_usb_props;
 	info->usb.num_properties = ARRAY_SIZE(pm860x_usb_props);
 	info->usb.get_property = pm860x_usb_get_prop;
-	ret = power_supply_register(&pdev->dev, &info->usb);
+	psy_cfg.supplied_to = pm860x_supplied_to;
+	psy_cfg.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
+	ret = power_supply_register(&pdev->dev, &info->usb, &psy_cfg);
 	if (ret)
 		goto out;
 
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 4ebf7b0819f7..d5683f503a4e 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -1058,6 +1058,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct abx500_bm_data *plat = pdev->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct ab8500_btemp *di;
 	int irq, i, ret = 0;
 	u8 val;
@@ -1095,11 +1096,11 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
 	di->btemp_psy.properties = ab8500_btemp_props;
 	di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
 	di->btemp_psy.get_property = ab8500_btemp_get_property;
-	di->btemp_psy.supplied_to = supply_interface;
-	di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
 	di->btemp_psy.external_power_changed =
 		ab8500_btemp_external_power_changed;
 
+	psy_cfg.supplied_to = supply_interface;
+	psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
 
 	/* Create a work queue for the btemp */
 	di->btemp_wq =
@@ -1140,7 +1141,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
 	}
 
 	/* Register BTEMP power supply class */
-	ret = power_supply_register(di->dev, &di->btemp_psy);
+	ret = power_supply_register(di->dev, &di->btemp_psy, &psy_cfg);
 	if (ret) {
 		dev_err(di->dev, "failed to register BTEMP psy\n");
 		goto free_btemp_wq;
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 8c8d170ff0f8..cee9b9e46825 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -3446,6 +3446,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct abx500_bm_data *plat = pdev->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct ab8500_charger *di;
 	int irq, i, charger_status, ret = 0, ch_stat;
 
@@ -3483,6 +3484,10 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	di->autopower = false;
 	di->invalid_charger_detect_state = 0;
 
+	/* AC and USB supply config */
+	psy_cfg.supplied_to = supply_interface;
+	psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+
 	/* AC supply */
 	/* power_supply base class */
 	di->ac_chg.psy.name = "ab8500_ac";
@@ -3490,8 +3495,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	di->ac_chg.psy.properties = ab8500_charger_ac_props;
 	di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
 	di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
-	di->ac_chg.psy.supplied_to = supply_interface;
-	di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
 	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
@@ -3517,8 +3520,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 	di->usb_chg.psy.properties = ab8500_charger_usb_props;
 	di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
 	di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
-	di->usb_chg.psy.supplied_to = supply_interface;
-	di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
 	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
@@ -3616,7 +3617,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 
 	/* Register AC charger class */
 	if (di->ac_chg.enabled) {
-		ret = power_supply_register(di->dev, &di->ac_chg.psy);
+		ret = power_supply_register(di->dev, &di->ac_chg.psy,
+						&psy_cfg);
 		if (ret) {
 			dev_err(di->dev, "failed to register AC charger\n");
 			goto free_charger_wq;
@@ -3625,7 +3627,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 
 	/* Register USB charger class */
 	if (di->usb_chg.enabled) {
-		ret = power_supply_register(di->dev, &di->usb_chg.psy);
+		ret = power_supply_register(di->dev, &di->usb_chg.psy,
+						&psy_cfg);
 		if (ret) {
 			dev_err(di->dev, "failed to register USB charger\n");
 			goto free_ac;
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 94d3b10a21ff..0e2c9d592a53 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -3072,6 +3072,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct abx500_bm_data *plat = pdev->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct ab8500_fg *di;
 	int i, irq;
 	int ret = 0;
@@ -3108,10 +3109,11 @@ static int ab8500_fg_probe(struct platform_device *pdev)
 	di->fg_psy.properties = ab8500_fg_props;
 	di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
 	di->fg_psy.get_property = ab8500_fg_get_property;
-	di->fg_psy.supplied_to = supply_interface;
-	di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
 
+	psy_cfg.supplied_to = supply_interface;
+	psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+
 	di->bat_cap.max_mah_design = MILLI_TO_MICRO *
 		di->bm->bat_type[di->bm->batt_id].charge_full_design;
 
@@ -3171,7 +3173,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
 	di->flags.batt_id_received = false;
 
 	/* Register FG power supply class */
-	ret = power_supply_register(di->dev, &di->fg_psy);
+	ret = power_supply_register(di->dev, &di->fg_psy, &psy_cfg);
 	if (ret) {
 		dev_err(di->dev, "failed to register FG psy\n");
 		goto free_inst_curr_wq;
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index ab54b8dea670..0da4415cbc10 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -2047,6 +2047,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct abx500_bm_data *plat = pdev->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct abx500_chargalg *di;
 	int ret = 0;
 
@@ -2080,11 +2081,12 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 	di->chargalg_psy.properties = abx500_chargalg_props;
 	di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
 	di->chargalg_psy.get_property = abx500_chargalg_get_property;
-	di->chargalg_psy.supplied_to = supply_interface;
-	di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	di->chargalg_psy.external_power_changed =
 		abx500_chargalg_external_power_changed;
 
+	psy_cfg.supplied_to = supply_interface;
+	psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+
 	/* Initilialize safety timer */
 	hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	di->safety_timer.function = abx500_chargalg_safety_timer_expired;
@@ -2115,7 +2117,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
 	di->chg_info.prev_conn_chg = -1;
 
 	/* Register chargalg power supply class */
-	ret = power_supply_register(di->dev, &di->chargalg_psy);
+	ret = power_supply_register(di->dev, &di->chargalg_psy, &psy_cfg);
 	if (ret) {
 		dev_err(di->dev, "failed to register chargalg psy\n");
 		goto free_chargalg_wq;
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 1f49986fc605..73b0a8521803 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1058,7 +1058,7 @@ static int bq2415x_power_supply_init(struct bq2415x_device *bq)
 		return -ENOMEM;
 	}
 
-	ret = power_supply_register(bq->dev, &bq->charger);
+	ret = power_supply_register(bq->dev, &bq->charger, NULL);
 	if (ret) {
 		kfree(bq->model);
 		return ret;
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c
index d0e8236a6404..54eb58485d55 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/bq24735-charger.c b/drivers/power/bq24735-charger.c
index d022b823305b..242e79bfe217 100644
--- a/drivers/power/bq24735-charger.c
+++ b/drivers/power/bq24735-charger.c
@@ -249,6 +249,7 @@ static int bq24735_charger_probe(struct i2c_client *client,
 	int ret;
 	struct bq24735 *charger;
 	struct power_supply *supply;
+	struct power_supply_config psy_cfg = {};
 	char *name;
 
 	charger = devm_kzalloc(&client->dev, sizeof(*charger), GFP_KERNEL);
@@ -284,9 +285,10 @@ static int bq24735_charger_probe(struct i2c_client *client,
 	supply->properties = bq24735_charger_properties;
 	supply->num_properties = ARRAY_SIZE(bq24735_charger_properties);
 	supply->get_property = bq24735_charger_get_property;
-	supply->supplied_to = charger->pdata->supplied_to;
-	supply->num_supplicants = charger->pdata->num_supplicants;
-	supply->of_node = client->dev.of_node;
+
+	psy_cfg.supplied_to = charger->pdata->supplied_to;
+	psy_cfg.num_supplicants = charger->pdata->num_supplicants;
+	psy_cfg.of_node = client->dev.of_node;
 
 	i2c_set_clientdata(client, charger);
 
@@ -341,7 +343,7 @@ static int bq24735_charger_probe(struct i2c_client *client,
 		}
 	}
 
-	ret = power_supply_register(&client->dev, supply);
+	ret = power_supply_register(&client->dev, supply, &psy_cfg);
 	if (ret < 0) {
 		dev_err(&client->dev, "Failed to register power supply: %d\n",
 			ret);
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index b72ba7c1bd69..5b8bdd0d3cb0 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -755,7 +755,7 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
 	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
 	mutex_init(&di->lock);
 
-	ret = power_supply_register(di->dev, &di->bat);
+	ret = power_supply_register(di->dev, &di->bat, NULL);
 	if (ret) {
 		dev_err(di->dev, "failed to register battery: %d\n", ret);
 		return ret;
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index f1d6279bdc8e..1acb04629fa0 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1745,7 +1745,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/collie_battery.c b/drivers/power/collie_battery.c
index 594e4dbc2d51..e7a808d1758a 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -334,10 +334,10 @@ static int collie_bat_probe(struct ucb1x00_dev *dev)
 
 	INIT_WORK(&bat_work, collie_bat_work);
 
-	ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy);
+	ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy, NULL);
 	if (ret)
 		goto err_psy_reg_main;
-	ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy);
+	ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy, NULL);
 	if (ret)
 		goto err_psy_reg_bu;
 
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index 78cd5d66144b..a87406ef18ee 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -541,7 +541,7 @@ static int da9030_battery_probe(struct platform_device *pdev)
 		goto err_notifier;
 
 	da9030_battery_setup_psy(charger);
-	ret = power_supply_register(&pdev->dev, &charger->psy);
+	ret = power_supply_register(&pdev->dev, &charger->psy, NULL);
 	if (ret)
 		goto err_ps_register;
 
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
index d17250f745c2..54ba9ddb6d4f 100644
--- a/drivers/power/da9052-battery.c
+++ b/drivers/power/da9052-battery.c
@@ -625,7 +625,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = power_supply_register(&pdev->dev, &bat->psy);
+	ret = power_supply_register(&pdev->dev, &bat->psy, NULL);
 	 if (ret)
 		goto err;
 
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 85b4e6eca0b1..e82dff0bbb20 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -555,7 +555,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
 	if (current_accum)
 		ds2760_battery_set_current_accum(di, current_accum);
 
-	retval = power_supply_register(&pdev->dev, &di->bat);
+	retval = power_supply_register(&pdev->dev, &di->bat, NULL);
 	if (retval) {
 		dev_err(di->dev, "failed to register battery\n");
 		goto batt_failed;
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 9f418fa879e5..b1d3570ea730 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -776,7 +776,7 @@ static int ds2780_battery_probe(struct platform_device *pdev)
 	dev_info->bat.num_properties	= ARRAY_SIZE(ds2780_battery_props);
 	dev_info->bat.get_property	= ds2780_battery_get_property;
 
-	ret = power_supply_register(&pdev->dev, &dev_info->bat);
+	ret = power_supply_register(&pdev->dev, &dev_info->bat, NULL);
 	if (ret) {
 		dev_err(dev_info->dev, "failed to register battery\n");
 		goto fail;
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
index 0a5acc6fc6f0..50686dc59711 100644
--- a/drivers/power/ds2781_battery.c
+++ b/drivers/power/ds2781_battery.c
@@ -769,7 +769,7 @@ static int ds2781_battery_probe(struct platform_device *pdev)
 	dev_info->bat.num_properties	= ARRAY_SIZE(ds2781_battery_props);
 	dev_info->bat.get_property	= ds2781_battery_get_property;
 
-	ret = power_supply_register(&pdev->dev, &dev_info->bat);
+	ret = power_supply_register(&pdev->dev, &dev_info->bat, NULL);
 	if (ret) {
 		dev_err(dev_info->dev, "failed to register battery\n");
 		goto fail;
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index 39694883d3bf..2dcb96a83cee 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -424,7 +424,7 @@ static int ds278x_battery_probe(struct i2c_client *client,
 
 	INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work);
 
-	ret = power_supply_register(&client->dev, &info->battery);
+	ret = power_supply_register(&client->dev, &info->battery, NULL);
 	if (ret) {
 		dev_err(&client->dev, "failed to register battery\n");
 		goto fail_register;
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
index d72733e4f93a..8ddbcffdb7f6 100644
--- a/drivers/power/generic-adc-battery.c
+++ b/drivers/power/generic-adc-battery.c
@@ -312,7 +312,7 @@ static int gab_probe(struct platform_device *pdev)
 	 */
 	psy->num_properties = ARRAY_SIZE(gab_props) + index;
 
-	ret = power_supply_register(&pdev->dev, psy);
+	ret = power_supply_register(&pdev->dev, psy, NULL);
 	if (ret)
 		goto err_reg_fail;
 
diff --git a/drivers/power/goldfish_battery.c b/drivers/power/goldfish_battery.c
index 29eba88a2963..61d437f8cf76 100644
--- a/drivers/power/goldfish_battery.c
+++ b/drivers/power/goldfish_battery.c
@@ -195,11 +195,11 @@ static int goldfish_battery_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = power_supply_register(&pdev->dev, &data->ac);
+	ret = power_supply_register(&pdev->dev, &data->ac, NULL);
 	if (ret)
 		return ret;
 
-	ret = power_supply_register(&pdev->dev, &data->battery);
+	ret = power_supply_register(&pdev->dev, &data->battery, NULL);
 	if (ret) {
 		power_supply_unregister(&data->ac);
 		return ret;
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index b7424c8501f1..47a9e2bd94d9 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -127,6 +127,7 @@ struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev)
 static int gpio_charger_probe(struct platform_device *pdev)
 {
 	const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct gpio_charger *gpio_charger;
 	struct power_supply *charger;
 	int ret;
@@ -161,9 +162,10 @@ static int gpio_charger_probe(struct platform_device *pdev)
 	charger->properties = gpio_charger_properties;
 	charger->num_properties = ARRAY_SIZE(gpio_charger_properties);
 	charger->get_property = gpio_charger_get_property;
-	charger->supplied_to = pdata->supplied_to;
-	charger->num_supplicants = pdata->num_supplicants;
-	charger->of_node = pdev->dev.of_node;
+
+	psy_cfg.supplied_to = pdata->supplied_to;
+	psy_cfg.num_supplicants = pdata->num_supplicants;
+	psy_cfg.of_node = pdev->dev.of_node;
 
 	ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
 	if (ret) {
@@ -178,7 +180,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
 
 	gpio_charger->pdata = pdata;
 
-	ret = power_supply_register(&pdev->dev, charger);
+	ret = power_supply_register(&pdev->dev, charger, &psy_cfg);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register power supply: %d\n",
 			ret);
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index de3f39e6fa8e..8a149657cd71 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -692,7 +692,7 @@ static int probe(int irq, struct device *dev)
 	pbi->batt.properties = pmic_battery_props;
 	pbi->batt.num_properties = ARRAY_SIZE(pmic_battery_props);
 	pbi->batt.get_property = pmic_battery_get_property;
-	retval = power_supply_register(dev, &pbi->batt);
+	retval = power_supply_register(dev, &pbi->batt, NULL);
 	if (retval) {
 		dev_err(dev,
 			"%s(): failed to register pmic battery device with power supply subsystem\n",
@@ -712,7 +712,7 @@ static int probe(int irq, struct device *dev)
 	pbi->usb.properties = pmic_usb_props;
 	pbi->usb.num_properties = ARRAY_SIZE(pmic_usb_props);
 	pbi->usb.get_property = pmic_usb_get_property;
-	retval = power_supply_register(dev, &pbi->usb);
+	retval = power_supply_register(dev, &pbi->usb, NULL);
 	if (retval) {
 		dev_err(dev,
 			"%s(): failed to register pmic usb device with power supply subsystem\n",
diff --git a/drivers/power/ipaq_micro_battery.c b/drivers/power/ipaq_micro_battery.c
index 96b15e003f3f..842e7e2e1cb5 100644
--- a/drivers/power/ipaq_micro_battery.c
+++ b/drivers/power/ipaq_micro_battery.c
@@ -241,11 +241,11 @@ static int micro_batt_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, mb);
 	queue_delayed_work(mb->wq, &mb->update, 1);
 
-	ret = power_supply_register(&pdev->dev, &micro_batt_power);
+	ret = power_supply_register(&pdev->dev, &micro_batt_power, NULL);
 	if (ret < 0)
 		goto batt_err;
 
-	ret = power_supply_register(&pdev->dev, &micro_ac_power);
+	ret = power_supply_register(&pdev->dev, &micro_ac_power, NULL);
 	if (ret < 0)
 		goto ac_err;
 
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 0b4cf9d63291..5521178bdc08 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -460,7 +460,7 @@ static int isp1704_charger_probe(struct platform_device *pdev)
 	isp->psy.num_properties	= ARRAY_SIZE(power_props);
 	isp->psy.get_property	= isp1704_charger_get_property;
 
-	ret = power_supply_register(isp->dev, &isp->psy);
+	ret = power_supply_register(isp->dev, &isp->psy, NULL);
 	if (ret)
 		goto fail1;
 
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 9cd391d61819..0444434e1927 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -330,7 +330,7 @@ static int jz_battery_probe(struct platform_device *pdev)
 	else
 		jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, 0);
 
-	ret = power_supply_register(&pdev->dev, &jz_battery->battery);
+	ret = power_supply_register(&pdev->dev, &jz_battery->battery, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "power supply battery register failed.\n");
 		goto err_free_charge_irq;
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index 32de636dcd73..1f71af7a3811 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -420,6 +420,7 @@ static void lp8727_charger_changed(struct power_supply *psy)
 
 static int lp8727_register_psy(struct lp8727_chg *pchg)
 {
+	struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
 	struct lp8727_psy *psy;
 
 	psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
@@ -428,15 +429,16 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
 
 	pchg->psy = psy;
 
+	psy_cfg.supplied_to = battery_supplied_to;
+	psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
 	psy->ac.name = "ac";
 	psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
 	psy->ac.properties = lp8727_charger_prop;
 	psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
 	psy->ac.get_property = lp8727_charger_get_property;
-	psy->ac.supplied_to = battery_supplied_to;
-	psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
-	if (power_supply_register(pchg->dev, &psy->ac))
+	if (power_supply_register(pchg->dev, &psy->ac, &psy_cfg))
 		goto err_psy_ac;
 
 	psy->usb.name = "usb";
@@ -444,10 +446,8 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
 	psy->usb.properties = lp8727_charger_prop;
 	psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
 	psy->usb.get_property = lp8727_charger_get_property;
-	psy->usb.supplied_to = battery_supplied_to;
-	psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
-	if (power_supply_register(pchg->dev, &psy->usb))
+	if (power_supply_register(pchg->dev, &psy->usb, &psy_cfg))
 		goto err_psy_usb;
 
 	psy->batt.name = "main_batt";
@@ -457,7 +457,7 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
 	psy->batt.get_property = lp8727_battery_get_property;
 	psy->batt.external_power_changed = lp8727_charger_changed;
 
-	if (power_supply_register(pchg->dev, &psy->batt))
+	if (power_supply_register(pchg->dev, &psy->batt, NULL))
 		goto err_psy_batt;
 
 	return 0;
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
index 176dab2e4c16..8e4d228519c1 100644
--- a/drivers/power/lp8788-charger.c
+++ b/drivers/power/lp8788-charger.c
@@ -400,15 +400,18 @@ static int lp8788_update_charger_params(struct platform_device *pdev,
 static int lp8788_psy_register(struct platform_device *pdev,
 				struct lp8788_charger *pchg)
 {
+	struct power_supply_config charger_cfg = {};
+
 	pchg->charger.name = LP8788_CHARGER_NAME;
 	pchg->charger.type = POWER_SUPPLY_TYPE_MAINS;
 	pchg->charger.properties = lp8788_charger_prop;
 	pchg->charger.num_properties = ARRAY_SIZE(lp8788_charger_prop);
 	pchg->charger.get_property = lp8788_charger_get_property;
-	pchg->charger.supplied_to = battery_supplied_to;
-	pchg->charger.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
-	if (power_supply_register(&pdev->dev, &pchg->charger))
+	charger_cfg.supplied_to = battery_supplied_to;
+	charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+	if (power_supply_register(&pdev->dev, &pchg->charger, &charger_cfg))
 		return -EPERM;
 
 	pchg->battery.name = LP8788_BATTERY_NAME;
@@ -417,7 +420,7 @@ static int lp8788_psy_register(struct platform_device *pdev,
 	pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
 	pchg->battery.get_property = lp8788_battery_get_property;
 
-	if (power_supply_register(&pdev->dev, &pchg->battery)) {
+	if (power_supply_register(&pdev->dev, &pchg->battery, NULL)) {
 		power_supply_unregister(&pchg->charger);
 		return -EPERM;
 	}
diff --git a/drivers/power/ltc2941-battery-gauge.c b/drivers/power/ltc2941-battery-gauge.c
index e31c927a6d16..f9fab730bb24 100644
--- a/drivers/power/ltc2941-battery-gauge.c
+++ b/drivers/power/ltc2941-battery-gauge.c
@@ -473,7 +473,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
 		goto fail_comm;
 	}
 
-	ret = power_supply_register(&client->dev, &info->supply);
+	ret = power_supply_register(&client->dev, &info->supply, NULL);
 	if (ret) {
 		dev_err(&client->dev, "failed to register ltc2941\n");
 		goto fail_register;
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/max77693_charger.c b/drivers/power/max77693_charger.c
index b042970fdeaf..884ec851e993 100644
--- a/drivers/power/max77693_charger.c
+++ b/drivers/power/max77693_charger.c
@@ -703,7 +703,7 @@ static int max77693_charger_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	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/max8903_charger.c b/drivers/power/max8903_charger.c
index 99e3cdcd3e11..2f769faa85f6 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -288,7 +288,7 @@ static int max8903_probe(struct platform_device *pdev)
 	data->psy.properties = max8903_charger_props;
 	data->psy.num_properties = ARRAY_SIZE(max8903_charger_props);
 
-	ret = power_supply_register(dev, &data->psy);
+	ret = power_supply_register(dev, &data->psy, NULL);
 	if (ret) {
 		dev_err(dev, "failed: power supply register.\n");
 		goto err;
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index a6d45eef64dd..71c087e3feaf 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -482,6 +482,7 @@ max8925_power_dt_init(struct platform_device *pdev)
 static int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
 	int ret;
@@ -502,14 +503,15 @@ static int max8925_power_probe(struct platform_device *pdev)
 	info->adc = chip->adc;
 	platform_set_drvdata(pdev, info);
 
+	psy_cfg.supplied_to = pdata->supplied_to;
+	psy_cfg.num_supplicants = pdata->num_supplicants;
+
 	info->ac.name = "max8925-ac";
 	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
 	info->ac.properties = max8925_ac_props;
 	info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
 	info->ac.get_property = max8925_ac_get_prop;
-	info->ac.supplied_to = pdata->supplied_to;
-	info->ac.num_supplicants = pdata->num_supplicants;
-	ret = power_supply_register(&pdev->dev, &info->ac);
+	ret = power_supply_register(&pdev->dev, &info->ac, &psy_cfg);
 	if (ret)
 		goto out;
 	info->ac.dev->parent = &pdev->dev;
@@ -519,10 +521,8 @@ static int max8925_power_probe(struct platform_device *pdev)
 	info->usb.properties = max8925_usb_props;
 	info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
 	info->usb.get_property = max8925_usb_get_prop;
-	info->usb.supplied_to = pdata->supplied_to;
-	info->usb.num_supplicants = pdata->num_supplicants;
 
-	ret = power_supply_register(&pdev->dev, &info->usb);
+	ret = power_supply_register(&pdev->dev, &info->usb, &psy_cfg);
 	if (ret)
 		goto out_usb;
 	info->usb.dev->parent = &pdev->dev;
@@ -532,7 +532,7 @@ static int max8925_power_probe(struct platform_device *pdev)
 	info->battery.properties = max8925_battery_props;
 	info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
 	info->battery.get_property = max8925_bat_get_prop;
-	ret = power_supply_register(&pdev->dev, &info->battery);
+	ret = power_supply_register(&pdev->dev, &info->battery, NULL);
 	if (ret)
 		goto out_battery;
 	info->battery.dev->parent = &pdev->dev;
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index aefa0c9a3007..a9f4d506eb44 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -156,7 +156,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
 	charger->dev = &pdev->dev;
 	charger->iodev = iodev;
 
-	ret = power_supply_register(&pdev->dev, &charger->battery);
+	ret = power_supply_register(&pdev->dev, &charger->battery, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed: power supply register\n");
 		return ret;
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 08694c7a9f38..9ee72314b3d0 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -167,7 +167,7 @@ static int max8998_battery_probe(struct platform_device *pdev)
 	max8998->battery.properties = max8998_battery_props;
 	max8998->battery.num_properties = ARRAY_SIZE(max8998_battery_props);
 
-	ret = power_supply_register(max8998->dev, &max8998->battery);
+	ret = power_supply_register(max8998->dev, &max8998->battery, NULL);
 	if (ret) {
 		dev_err(max8998->dev, "failed: power supply register\n");
 		goto err;
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index ad9cde705de1..1340a1a75325 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -619,7 +619,7 @@ static int olpc_battery_probe(struct platform_device *pdev)
 
 	/* Ignore the status. It doesn't actually matter */
 
-	ret = power_supply_register(&pdev->dev, &olpc_ac);
+	ret = power_supply_register(&pdev->dev, &olpc_ac, NULL);
 	if (ret)
 		return ret;
 
@@ -631,7 +631,7 @@ static int olpc_battery_probe(struct platform_device *pdev)
 		olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
 	}
 
-	ret = power_supply_register(&pdev->dev, &olpc_bat);
+	ret = power_supply_register(&pdev->dev, &olpc_bat, NULL);
 	if (ret)
 		goto battery_failed;
 
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 771c4f0fb8ac..88fe7db2afcf 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -368,6 +368,7 @@ static const u8 mbc_irq_handlers[] = {
 
 static int pcf50633_mbc_probe(struct platform_device *pdev)
 {
+	struct power_supply_config psy_cfg = {};
 	struct pcf50633_mbc *mbc;
 	int ret;
 	int i;
@@ -385,45 +386,42 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
 		pcf50633_register_irq(mbc->pcf, mbc_irq_handlers[i],
 					pcf50633_mbc_irq_handler, mbc);
 
+	psy_cfg.supplied_to		= mbc->pcf->pdata->batteries;
+	psy_cfg.num_supplicants		= mbc->pcf->pdata->num_batteries;
+
 	/* Create power supplies */
 	mbc->adapter.name		= "adapter";
 	mbc->adapter.type		= POWER_SUPPLY_TYPE_MAINS;
 	mbc->adapter.properties		= power_props;
 	mbc->adapter.num_properties	= ARRAY_SIZE(power_props);
 	mbc->adapter.get_property	= &adapter_get_property;
-	mbc->adapter.supplied_to	= mbc->pcf->pdata->batteries;
-	mbc->adapter.num_supplicants	= mbc->pcf->pdata->num_batteries;
 
 	mbc->usb.name			= "usb";
 	mbc->usb.type			= POWER_SUPPLY_TYPE_USB;
 	mbc->usb.properties		= power_props;
 	mbc->usb.num_properties		= ARRAY_SIZE(power_props);
 	mbc->usb.get_property		= usb_get_property;
-	mbc->usb.supplied_to		= mbc->pcf->pdata->batteries;
-	mbc->usb.num_supplicants	= mbc->pcf->pdata->num_batteries;
 
 	mbc->ac.name			= "ac";
 	mbc->ac.type			= POWER_SUPPLY_TYPE_MAINS;
 	mbc->ac.properties		= power_props;
 	mbc->ac.num_properties		= ARRAY_SIZE(power_props);
 	mbc->ac.get_property		= ac_get_property;
-	mbc->ac.supplied_to		= mbc->pcf->pdata->batteries;
-	mbc->ac.num_supplicants		= mbc->pcf->pdata->num_batteries;
 
-	ret = power_supply_register(&pdev->dev, &mbc->adapter);
+	ret = power_supply_register(&pdev->dev, &mbc->adapter, &psy_cfg);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register adapter\n");
 		return ret;
 	}
 
-	ret = power_supply_register(&pdev->dev, &mbc->usb);
+	ret = power_supply_register(&pdev->dev, &mbc->usb, &psy_cfg);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register usb\n");
 		power_supply_unregister(&mbc->adapter);
 		return ret;
 	}
 
-	ret = power_supply_register(&pdev->dev, &mbc->ac);
+	ret = power_supply_register(&pdev->dev, &mbc->ac, &psy_cfg);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register ac\n");
 		power_supply_unregister(&mbc->adapter);
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 0c52e2a0d90c..fd55fad1d0db 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -83,8 +83,6 @@ static char *pda_power_supplied_to[] = {
 static struct power_supply pda_psy_ac = {
 	.name = "ac",
 	.type = POWER_SUPPLY_TYPE_MAINS,
-	.supplied_to = pda_power_supplied_to,
-	.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
 	.properties = pda_power_props,
 	.num_properties = ARRAY_SIZE(pda_power_props),
 	.get_property = pda_power_get_property,
@@ -93,8 +91,6 @@ static struct power_supply pda_psy_ac = {
 static struct power_supply pda_psy_usb = {
 	.name = "usb",
 	.type = POWER_SUPPLY_TYPE_USB,
-	.supplied_to = pda_power_supplied_to,
-	.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
 	.properties = pda_power_props,
 	.num_properties = ARRAY_SIZE(pda_power_props),
 	.get_property = pda_power_get_property,
@@ -262,6 +258,7 @@ static int otg_handle_notification(struct notifier_block *nb,
 
 static int pda_power_probe(struct platform_device *pdev)
 {
+	struct power_supply_config psy_cfg = {};
 	int ret = 0;
 
 	dev = &pdev->dev;
@@ -309,10 +306,11 @@ static int pda_power_probe(struct platform_device *pdev)
 	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
 
 	if (pdata->supplied_to) {
-		pda_psy_ac.supplied_to = pdata->supplied_to;
-		pda_psy_ac.num_supplicants = pdata->num_supplicants;
-		pda_psy_usb.supplied_to = pdata->supplied_to;
-		pda_psy_usb.num_supplicants = pdata->num_supplicants;
+		psy_cfg.supplied_to = pdata->supplied_to;
+		psy_cfg.num_supplicants = pdata->num_supplicants;
+	} else {
+		psy_cfg.supplied_to = pda_power_supplied_to;
+		psy_cfg.num_supplicants = ARRAY_SIZE(pda_power_supplied_to);
 	}
 
 #if IS_ENABLED(CONFIG_USB_PHY)
@@ -326,7 +324,7 @@ static int pda_power_probe(struct platform_device *pdev)
 #endif
 
 	if (pdata->is_ac_online) {
-		ret = power_supply_register(&pdev->dev, &pda_psy_ac);
+		ret = power_supply_register(&pdev->dev, &pda_psy_ac, &psy_cfg);
 		if (ret) {
 			dev_err(dev, "failed to register %s power supply\n",
 				pda_psy_ac.name);
@@ -347,7 +345,7 @@ static int pda_power_probe(struct platform_device *pdev)
 	}
 
 	if (pdata->is_usb_online) {
-		ret = power_supply_register(&pdev->dev, &pda_psy_usb);
+		ret = power_supply_register(&pdev->dev, &pda_psy_usb, &psy_cfg);
 		if (ret) {
 			dev_err(dev, "failed to register %s power supply\n",
 				pda_psy_usb.name);
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c
index 777324992c59..d2e88e473238 100644
--- a/drivers/power/pm2301_charger.c
+++ b/drivers/power/pm2301_charger.c
@@ -989,6 +989,7 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 		const struct i2c_device_id *id)
 {
 	struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data;
+	struct power_supply_config psy_cfg = {};
 	struct pm2xxx_charger *pm2;
 	int ret = 0;
 	u8 val;
@@ -1047,8 +1048,9 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 	pm2->ac_chg.psy.properties = pm2xxx_charger_ac_props;
 	pm2->ac_chg.psy.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props);
 	pm2->ac_chg.psy.get_property = pm2xxx_charger_ac_get_property;
-	pm2->ac_chg.psy.supplied_to = pm2->pdata->supplied_to;
-	pm2->ac_chg.psy.num_supplicants = pm2->pdata->num_supplicants;
+
+	psy_cfg.supplied_to = pm2->pdata->supplied_to;
+	psy_cfg.num_supplicants = pm2->pdata->num_supplicants;
 	/* pm2xxx_charger sub-class */
 	pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en;
 	pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick;
@@ -1093,7 +1095,7 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 	}
 
 	/* Register AC charger class */
-	ret = power_supply_register(pm2->dev, &pm2->ac_chg.psy);
+	ret = power_supply_register(pm2->dev, &pm2->ac_chg.psy, &psy_cfg);
 	if (ret) {
 		dev_err(pm2->dev, "failed to register AC charger\n");
 		goto free_regulator;
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
index 023d24993b87..fb026f19aa4a 100644
--- a/drivers/power/pmu_battery.c
+++ b/drivers/power/pmu_battery.c
@@ -152,7 +152,7 @@ static int __init pmu_bat_init(void)
 		goto pdev_register_failed;
 	}
 
-	ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+	ret = power_supply_register(&bat_pdev->dev, &pmu_ac, NULL);
 	if (ret)
 		goto ac_register_failed;
 
@@ -169,7 +169,7 @@ static int __init pmu_bat_init(void)
 		pbat->bat.get_property = pmu_bat_get_property;
 		pbat->pbi = &pmu_batteries[i];
 
-		ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+		ret = power_supply_register(&bat_pdev->dev, &pbat->bat, NULL);
 		if (ret) {
 			kfree(pbat);
 			goto battery_register_failed;
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/rt5033_battery.c b/drivers/power/rt5033_battery.c
index 7b898f41c595..fa0da8fd289c 100644
--- a/drivers/power/rt5033_battery.c
+++ b/drivers/power/rt5033_battery.c
@@ -138,7 +138,7 @@ static int rt5033_battery_probe(struct i2c_client *client,
 	battery->psy.properties		= rt5033_battery_props;
 	battery->psy.num_properties	= ARRAY_SIZE(rt5033_battery_props);
 
-	ret = power_supply_register(&client->dev, &battery->psy);
+	ret = power_supply_register(&client->dev, &battery->psy, NULL);
 	if (ret) {
 		dev_err(&client->dev, "Failed to register power supply\n");
 		return ret;
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
index a01aacb32f59..804f60c7b715 100644
--- a/drivers/power/rx51_battery.c
+++ b/drivers/power/rx51_battery.c
@@ -238,7 +238,7 @@ static int rx51_battery_probe(struct platform_device *pdev)
 		goto error_channel_bsi;
 	}
 
-	ret = power_supply_register(di->dev, &di->bat);
+	ret = power_supply_register(di->dev, &di->bat, NULL);
 	if (ret)
 		goto error_channel_vbat;
 
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index 5948ce058bdd..b6ff213373dd 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -310,14 +310,14 @@ static int s3c_adc_bat_probe(struct platform_device *pdev)
 	main_bat.cable_plugged = 0;
 	main_bat.status = POWER_SUPPLY_STATUS_DISCHARGING;
 
-	ret = power_supply_register(&pdev->dev, &main_bat.psy);
+	ret = power_supply_register(&pdev->dev, &main_bat.psy, NULL);
 	if (ret)
 		goto err_reg_main;
 	if (pdata->backup_volt_mult) {
 		backup_bat.client = client;
 		backup_bat.pdata = pdev->dev.platform_data;
 		backup_bat.volt_value = -1;
-		ret = power_supply_register(&pdev->dev, &backup_bat.psy);
+		ret = power_supply_register(&pdev->dev, &backup_bat.psy, NULL);
 		if (ret)
 			goto err_reg_backup;
 	}
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/smb347-charger.c b/drivers/power/smb347-charger.c
index acf84e80fe98..5999e1b85983 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -1193,6 +1193,7 @@ static int smb347_probe(struct i2c_client *client,
 {
 	static char *battery[] = { "smb347-battery" };
 	const struct smb347_charger_platform_data *pdata;
+	struct power_supply_config psy_cfg = {}; /* Only for mains and usb */
 	struct device *dev = &client->dev;
 	struct smb347_charger *smb;
 	int ret;
@@ -1222,15 +1223,15 @@ static int smb347_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
+	psy_cfg.supplied_to = battery;
+	psy_cfg.num_supplicants = ARRAY_SIZE(battery);
 	if (smb->pdata->use_mains) {
 		smb->mains.name = "smb347-mains";
 		smb->mains.type = POWER_SUPPLY_TYPE_MAINS;
 		smb->mains.get_property = smb347_mains_get_property;
 		smb->mains.properties = smb347_mains_properties;
 		smb->mains.num_properties = ARRAY_SIZE(smb347_mains_properties);
-		smb->mains.supplied_to = battery;
-		smb->mains.num_supplicants = ARRAY_SIZE(battery);
-		ret = power_supply_register(dev, &smb->mains);
+		ret = power_supply_register(dev, &smb->mains, &psy_cfg);
 		if (ret < 0)
 			return ret;
 	}
@@ -1241,9 +1242,7 @@ static int smb347_probe(struct i2c_client *client,
 		smb->usb.get_property = smb347_usb_get_property;
 		smb->usb.properties = smb347_usb_properties;
 		smb->usb.num_properties = ARRAY_SIZE(smb347_usb_properties);
-		smb->usb.supplied_to = battery;
-		smb->usb.num_supplicants = ARRAY_SIZE(battery);
-		ret = power_supply_register(dev, &smb->usb);
+		ret = power_supply_register(dev, &smb->usb, &psy_cfg);
 		if (ret < 0) {
 			if (smb->pdata->use_mains)
 				power_supply_unregister(&smb->mains);
@@ -1258,7 +1257,7 @@ static int smb347_probe(struct i2c_client *client,
 	smb->battery.num_properties = ARRAY_SIZE(smb347_battery_properties);
 
 
-	ret = power_supply_register(dev, &smb->battery);
+	ret = power_supply_register(dev, &smb->battery, NULL);
 	if (ret < 0) {
 		if (smb->pdata->use_usb)
 			power_supply_unregister(&smb->usb);
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c
index f26b1fa00fe1..f6c92d1d7811 100644
--- a/drivers/power/test_power.c
+++ b/drivers/power/test_power.c
@@ -157,8 +157,6 @@ static struct power_supply test_power_supplies[] = {
 	[TEST_AC] = {
 		.name = "test_ac",
 		.type = POWER_SUPPLY_TYPE_MAINS,
-		.supplied_to = test_power_ac_supplied_to,
-		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
 		.properties = test_power_ac_props,
 		.num_properties = ARRAY_SIZE(test_power_ac_props),
 		.get_property = test_power_get_ac_property,
@@ -173,14 +171,25 @@ static struct power_supply test_power_supplies[] = {
 	[TEST_USB] = {
 		.name = "test_usb",
 		.type = POWER_SUPPLY_TYPE_USB,
-		.supplied_to = test_power_ac_supplied_to,
-		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
 		.properties = test_power_ac_props,
 		.num_properties = ARRAY_SIZE(test_power_ac_props),
 		.get_property = test_power_get_usb_property,
 	},
 };
 
+static const struct power_supply_config test_power_configs[] = {
+	{
+		/* test_ac */
+		.supplied_to = test_power_ac_supplied_to,
+		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
+	}, {
+		/* test_battery */
+	}, {
+		/* test_usb */
+		.supplied_to = test_power_ac_supplied_to,
+		.num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
+	},
+};
 
 static int __init test_power_init(void)
 {
@@ -188,9 +197,11 @@ static int __init test_power_init(void)
 	int ret;
 
 	BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_supplies));
+	BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_configs));
 
 	for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) {
-		ret = power_supply_register(NULL, &test_power_supplies[i]);
+		ret = power_supply_register(NULL, &test_power_supplies[i],
+						&test_power_configs[i]);
 		if (ret) {
 			pr_err("%s: failed to register %s\n", __func__,
 				test_power_supplies[i].name);
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index f4d80df627c7..895e4b4dfcf6 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -358,13 +358,13 @@ static int tosa_bat_probe(struct platform_device *dev)
 
 	INIT_WORK(&bat_work, tosa_bat_work);
 
-	ret = power_supply_register(&dev->dev, &tosa_bat_main.psy);
+	ret = power_supply_register(&dev->dev, &tosa_bat_main.psy, NULL);
 	if (ret)
 		goto err_psy_reg_main;
-	ret = power_supply_register(&dev->dev, &tosa_bat_jacket.psy);
+	ret = power_supply_register(&dev->dev, &tosa_bat_jacket.psy, NULL);
 	if (ret)
 		goto err_psy_reg_jacket;
-	ret = power_supply_register(&dev->dev, &tosa_bat_bu.psy);
+	ret = power_supply_register(&dev->dev, &tosa_bat_bu.psy, NULL);
 	if (ret)
 		goto err_psy_reg_bu;
 
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 0f4e5971dff5..9872c901bd70 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -233,6 +233,7 @@ 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;
@@ -264,11 +265,12 @@ static int tps65090_charger_probe(struct platform_device *pdev)
 	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);
+	psy_cfg.supplied_to		= pdata->supplied_to;
+	psy_cfg.num_supplicants		= pdata->num_supplicants;
+	psy_cfg.of_node			= pdev->dev.of_node;
+
+	ret = power_supply_register(&pdev->dev, &cdata->ac, &psy_cfg);
 	if (ret) {
 		dev_err(&pdev->dev, "failed: power supply register\n");
 		return ret;
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index d35b83e635b5..156f30e64a75 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -590,7 +590,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
 	bci->ac.get_property = twl4030_bci_get_property;
 
-	ret = power_supply_register(&pdev->dev, &bci->ac);
+	ret = power_supply_register(&pdev->dev, &bci->ac, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
 		goto fail_register_ac;
@@ -604,7 +604,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
 	bci->usb_reg = regulator_get(bci->dev, "bci3v1");
 
-	ret = power_supply_register(&pdev->dev, &bci->usb);
+	ret = power_supply_register(&pdev->dev, &bci->usb, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
 		goto fail_register_usb;
diff --git a/drivers/power/twl4030_madc_battery.c b/drivers/power/twl4030_madc_battery.c
index cf907609ec49..d065460c1cb3 100644
--- a/drivers/power/twl4030_madc_battery.c
+++ b/drivers/power/twl4030_madc_battery.c
@@ -217,7 +217,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
 
 	twl4030_madc_bat->pdata = pdata;
 	platform_set_drvdata(pdev, twl4030_madc_bat);
-	ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+	ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy, NULL);
 	if (ret < 0)
 		kfree(twl4030_madc_bat);
 
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index 56fb509f4be0..60ae871148b0 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -197,7 +197,7 @@ static int wm831x_backup_probe(struct platform_device *pdev)
 	backup->properties = wm831x_backup_props;
 	backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
 	backup->get_property = wm831x_backup_get_prop;
-	ret = power_supply_register(&pdev->dev, backup);
+	ret = power_supply_register(&pdev->dev, backup, NULL);
 
 	return ret;
 }
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 3bed2f55cf7d..a132aae6225d 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -536,7 +536,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
 	wall->properties = wm831x_wall_props;
 	wall->num_properties = ARRAY_SIZE(wm831x_wall_props);
 	wall->get_property = wm831x_wall_get_prop;
-	ret = power_supply_register(&pdev->dev, wall);
+	ret = power_supply_register(&pdev->dev, wall, NULL);
 	if (ret)
 		goto err_kmalloc;
 
@@ -545,7 +545,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
 	usb->properties = wm831x_usb_props;
 	usb->num_properties = ARRAY_SIZE(wm831x_usb_props);
 	usb->get_property = wm831x_usb_get_prop;
-	ret = power_supply_register(&pdev->dev, usb);
+	ret = power_supply_register(&pdev->dev, usb, NULL);
 	if (ret)
 		goto err_wall;
 
@@ -560,7 +560,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
 		    battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
 		    battery->get_property = wm831x_bat_get_prop;
 		    battery->use_for_apm = 1;
-		    ret = power_supply_register(&pdev->dev, battery);
+		    ret = power_supply_register(&pdev->dev, battery, NULL);
 		    if (ret)
 			    goto err_usb;
 	}
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index b3607e2906d2..261ceca561d5 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -457,7 +457,7 @@ static int wm8350_power_probe(struct platform_device *pdev)
 	ac->properties = wm8350_ac_props;
 	ac->num_properties = ARRAY_SIZE(wm8350_ac_props);
 	ac->get_property = wm8350_ac_get_prop;
-	ret = power_supply_register(&pdev->dev, ac);
+	ret = power_supply_register(&pdev->dev, ac, NULL);
 	if (ret)
 		return ret;
 
@@ -466,7 +466,7 @@ static int wm8350_power_probe(struct platform_device *pdev)
 	battery->num_properties = ARRAY_SIZE(wm8350_bat_props);
 	battery->get_property = wm8350_bat_get_property;
 	battery->use_for_apm = 1;
-	ret = power_supply_register(&pdev->dev, battery);
+	ret = power_supply_register(&pdev->dev, battery, NULL);
 	if (ret)
 		goto battery_failed;
 
@@ -475,7 +475,7 @@ static int wm8350_power_probe(struct platform_device *pdev)
 	usb->properties = wm8350_usb_props;
 	usb->num_properties = ARRAY_SIZE(wm8350_usb_props);
 	usb->get_property = wm8350_usb_get_prop;
-	ret = power_supply_register(&pdev->dev, usb);
+	ret = power_supply_register(&pdev->dev, usb, NULL);
 	if (ret)
 		goto usb_failed;
 
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index a8e6203673ad..e81e917bd9d0 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -244,7 +244,7 @@ static int wm97xx_bat_probe(struct platform_device *dev)
 	bat_ps.properties = prop;
 	bat_ps.num_properties = props;
 
-	ret = power_supply_register(&dev->dev, &bat_ps);
+	ret = power_supply_register(&dev->dev, &bat_ps, NULL);
 	if (!ret)
 		schedule_work(&bat_work);
 	else
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index 814d2e31f0c9..df22364212dd 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -230,7 +230,7 @@ static int z2_batt_probe(struct i2c_client *client,
 
 	INIT_WORK(&charger->bat_work, z2_batt_work);
 
-	ret = power_supply_register(&client->dev, &charger->batt_ps);
+	ret = power_supply_register(&client->dev, &charger->batt_ps, NULL);
 	if (ret)
 		goto err4;
 
diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
index 6a1459d4f8fb..4bfa84672818 100644
--- a/drivers/staging/nvec/nvec_power.c
+++ b/drivers/staging/nvec/nvec_power.c
@@ -334,8 +334,6 @@ static struct power_supply nvec_bat_psy = {
 static struct power_supply nvec_psy = {
 	.name = "ac",
 	.type = POWER_SUPPLY_TYPE_MAINS,
-	.supplied_to = nvec_power_supplied_to,
-	.num_supplicants = ARRAY_SIZE(nvec_power_supplied_to),
 	.properties = nvec_power_props,
 	.num_properties = ARRAY_SIZE(nvec_power_props),
 	.get_property = nvec_power_get_property,
@@ -376,6 +374,7 @@ static int nvec_power_probe(struct platform_device *pdev)
 	struct power_supply *psy;
 	struct nvec_power *power;
 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+	struct power_supply_config psy_cfg = {};
 
 	power = devm_kzalloc(&pdev->dev, sizeof(struct nvec_power), GFP_NOWAIT);
 	if (power == NULL)
@@ -387,6 +386,8 @@ static int nvec_power_probe(struct platform_device *pdev)
 	switch (pdev->id) {
 	case AC:
 		psy = &nvec_psy;
+		psy_cfg.supplied_to = nvec_power_supplied_to;
+		psy_cfg.num_supplicants = ARRAY_SIZE(nvec_power_supplied_to);
 
 		power->notifier.notifier_call = nvec_power_notifier;
 
@@ -407,7 +408,7 @@ static int nvec_power_probe(struct platform_device *pdev)
 	if (pdev->id == BAT)
 		get_bat_mfg_data(power);
 
-	return power_supply_register(&pdev->dev, psy);
+	return power_supply_register(&pdev->dev, psy, &psy_cfg);
 }
 
 static int nvec_power_remove(struct platform_device *pdev)
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] 31+ messages in thread

* [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 01/20] power_supply: Add driver private data Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-02-04 13:44   ` Pavel Machek
  2015-01-30 14:47 ` [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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 atomic 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.

Next patch changing the ownership of power supply class is still needed
to fully fix race conditions in accessing freed power supply.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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..0521681b3674 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -314,7 +314,9 @@ 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 (atomic_read(&psy->use_cnt) >= 0 &&
+			psy->type == POWER_SUPPLY_TYPE_BATTERY &&
+			psy->set_charged) {
 		psy->set_charged(psy);
 		return 0;
 	}
@@ -366,6 +368,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 (atomic_read(&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 (atomic_read(&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 (atomic_read(&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 (atomic_read(&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 +598,7 @@ static int __power_supply_register(struct device *parent,
 	dev->release = power_supply_dev_release;
 	dev_set_drvdata(dev, psy);
 	psy->dev = dev;
+	atomic_inc(&psy->use_cnt);
 	if (cfg) {
 		psy->drv_data = cfg->drv_data;
 		psy->of_node = cfg->of_node;
@@ -629,6 +673,7 @@ EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
 
 void power_supply_unregister(struct power_supply *psy)
 {
+	WARN_ON(atomic_dec_return(&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..5d460995f38d 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;
+	atomic_t 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] 31+ messages in thread

* [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (2 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-02-09 19:02   ` Stefan Wahren
  2015-01-30 14:47 ` [PATCH v3 05/20] power_supply: 88pm860x_charger: " Krzysztof Kozlowski
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 05/20] power_supply: 88pm860x_charger: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (3 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 06/20] power_supply: ab8500: " Krzysztof Kozlowski
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 ac352a6c03ea..98e31419d9cf 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] 31+ messages in thread

* [PATCH v3 06/20] power_supply: ab8500: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (4 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 05/20] power_supply: 88pm860x_charger: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 07/20] mfd: " Krzysztof Kozlowski
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.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 d5683f503a4e..4d18464d6400 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 cee9b9e46825..f9eb7fff1d65 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 0e2c9d592a53..c957e8a41847 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 0da4415cbc10..ac6f4a22f846 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] 31+ messages in thread

* [PATCH v3 07/20] mfd: ab8500: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (5 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 06/20] power_supply: ab8500: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 08/20] power_supply: apm_power: " Krzysztof Kozlowski
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.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] 31+ messages in thread

* [PATCH v3 08/20] power_supply: apm_power: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (6 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 07/20] mfd: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 09/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 09/20] power_supply: bq2415x_charger: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (7 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 08/20] power_supply: apm_power: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 10/20] power_supply: charger-manager: " Krzysztof Kozlowski
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 73b0a8521803..bc47a265b304 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] 31+ messages in thread

* [PATCH v3 10/20] power_supply: charger-manager: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (8 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 09/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 12/20] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 1acb04629fa0..3a8ceacb1bee 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -103,8 +103,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;
@@ -118,8 +118,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;
@@ -155,7 +155,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;
@@ -183,7 +184,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;
@@ -223,7 +224,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]);
@@ -236,7 +238,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]);
@@ -279,7 +282,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;
@@ -296,7 +299,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;
@@ -580,7 +583,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);
 }
@@ -901,7 +904,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:
@@ -924,7 +927,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;
@@ -980,7 +983,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) {
@@ -1429,7 +1432,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) {
@@ -1723,13 +1726,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] 31+ messages in thread

* [PATCH v3 12/20] power_supply: Add power_supply_put for decrementing device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (9 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 10/20] power_supply: charger-manager: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 13/20] power_supply: Increment power supply use counter when obtaining references Krzysztof Kozlowski
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 0dcf5ca0092e..95aeae44c34a 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -336,6 +336,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,
@@ -345,12 +356,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 54ebac5e3fe3..7000a4927ac8 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] 31+ messages in thread

* [PATCH v3 13/20] power_supply: Increment power supply use counter when obtaining references
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (10 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 12/20] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 14/20] power_supply: charger-manager: Decrement the power supply's device reference counter Krzysztof Kozlowski
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Increment the power_supply.use_cnt usage counter on:
 - power_supply_get_by_phandle()
 - power_supply_get_by_name()
and decrement it on power_supply_put() call.

This helps tracking of valid usage of power supply instance by
consumers. The usage counter itself also allows safe calling of
power_supply_get_property-like functions even when driver unregisters
this power supply.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/power/power_supply_core.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 95aeae44c34a..acad7e87f754 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -349,10 +349,16 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
  */
 struct power_supply *power_supply_get_by_name(const char *name)
 {
+	struct power_supply *psy = NULL;
 	struct device *dev = class_find_device(power_supply_class, NULL, name,
 					power_supply_match_device_by_name);
 
-	return dev ? dev_get_drvdata(dev) : NULL;
+	if (dev) {
+		psy = dev_get_drvdata(dev);
+		atomic_inc(&psy->use_cnt);
+	}
+
+	return psy;
 }
 EXPORT_SYMBOL_GPL(power_supply_get_by_name);
 
@@ -367,6 +373,7 @@ void power_supply_put(struct power_supply *psy)
 {
 	might_sleep();
 
+	atomic_dec(&psy->use_cnt);
 	put_device(&psy->dev);
 }
 EXPORT_SYMBOL_GPL(power_supply_put);
@@ -393,6 +400,7 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
 							const char *property)
 {
 	struct device_node *power_supply_np;
+	struct power_supply *psy = NULL;
 	struct device *dev;
 
 	power_supply_np = of_parse_phandle(np, property, 0);
@@ -404,7 +412,12 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
 
 	of_node_put(power_supply_np);
 
-	return dev ? dev_get_drvdata(dev) : NULL;
+	if (dev) {
+		psy = dev_get_drvdata(dev);
+		atomic_inc(&psy->use_cnt);
+	}
+
+	return psy;
 }
 EXPORT_SYMBOL_GPL(power_supply_get_by_phandle);
 #endif /* CONFIG_OF */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 14/20] power_supply: charger-manager: Decrement the power supply's device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (11 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 13/20] power_supply: Increment power supply use counter when obtaining references Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 15/20] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 8aa780125dfa..c2aef7a5582b 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -107,6 +107,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++) {
@@ -120,6 +121,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;
@@ -157,6 +159,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;
@@ -186,6 +189,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;
 
@@ -229,10 +233,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,
@@ -240,6 +247,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]);
@@ -267,6 +275,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;
 
@@ -284,15 +293,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 */
@@ -301,11 +314,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;
 }
 
 /**
@@ -578,14 +595,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,
@@ -867,7 +888,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;
 
@@ -910,12 +931,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;
@@ -926,6 +941,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)
@@ -1000,6 +1021,8 @@ static int charger_get_property(struct power_supply *psy,
 	default:
 		return -EINVAL;
 	}
+	if (fuel_gauge)
+		power_supply_put(fuel_gauge);
 	return ret;
 }
 
@@ -1681,13 +1704,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 ||
@@ -1727,6 +1744,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] =
@@ -1746,6 +1769,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] 31+ messages in thread

* [PATCH v3 15/20] x86/olpc/xo1/sci: Use newly added power_supply_put API
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (12 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 14/20] power_supply: charger-manager: Decrement the power supply's device reference counter Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 16/20] x86/olpc/xo15/sci: " Krzysztof Kozlowski
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 16/20] x86/olpc/xo15/sci: Use newly added power_supply_put API
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (13 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 15/20] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 17/20] power_supply: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 17/20] power_supply: 88pm860x_charger: Decrement the power supply's device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (14 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 16/20] x86/olpc/xo15/sci: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 18/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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 a7f32a5b2299..bf822aa00c14 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] 31+ messages in thread

* [PATCH v3 18/20] power_supply: bq2415x_charger: Decrement the power supply's device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (15 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 17/20] power_supply: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 19/20] mfd: ab8500: " Krzysztof Kozlowski
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14:47 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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 drivers/power/bq2415x_charger.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index cb92022df8eb..4adcd65bef5b 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1601,27 +1601,27 @@ static int bq2415x_probe(struct i2c_client *client,
 		ret = of_property_read_u32(np, "ti,current-limit",
 				&bq->init_data.current_limit);
 		if (ret)
-			goto error_2;
+			goto error_3;
 		ret = of_property_read_u32(np, "ti,weak-battery-voltage",
 				&bq->init_data.weak_battery_voltage);
 		if (ret)
-			goto error_2;
+			goto error_3;
 		ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
 				&bq->init_data.battery_regulation_voltage);
 		if (ret)
-			goto error_2;
+			goto error_3;
 		ret = of_property_read_u32(np, "ti,charge-current",
 				&bq->init_data.charge_current);
 		if (ret)
-			goto error_2;
+			goto error_3;
 		ret = of_property_read_u32(np, "ti,termination-current",
 				&bq->init_data.termination_current);
 		if (ret)
-			goto error_2;
+			goto error_3;
 		ret = of_property_read_u32(np, "ti,resistor-sense",
 				&bq->init_data.resistor_sense);
 		if (ret)
-			goto error_2;
+			goto error_3;
 	} else {
 		memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
 	}
@@ -1631,19 +1631,19 @@ static int bq2415x_probe(struct i2c_client *client,
 	ret = bq2415x_power_supply_init(bq);
 	if (ret) {
 		dev_err(bq->dev, "failed to register power supply: %d\n", ret);
-		goto error_2;
+		goto error_3;
 	}
 
 	ret = bq2415x_sysfs_init(bq);
 	if (ret) {
 		dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
-		goto error_3;
+		goto error_4;
 	}
 
 	ret = bq2415x_set_defaults(bq);
 	if (ret) {
 		dev_err(bq->dev, "failed to set default values: %d\n", ret);
-		goto error_4;
+		goto error_5;
 	}
 
 	if (bq->notify_psy) {
@@ -1651,7 +1651,7 @@ static int bq2415x_probe(struct i2c_client *client,
 		ret = power_supply_reg_notifier(&bq->nb);
 		if (ret) {
 			dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
-			goto error_5;
+			goto error_6;
 		}
 
 		/* Query for initial reported_mode and set it */
@@ -1671,11 +1671,14 @@ static int bq2415x_probe(struct i2c_client *client,
 	dev_info(bq->dev, "driver registered\n");
 	return 0;
 
+error_6:
 error_5:
-error_4:
 	bq2415x_sysfs_exit(bq);
-error_3:
+error_4:
 	bq2415x_power_supply_exit(bq);
+error_3:
+	if (!IS_ERR(bq->notify_psy))
+		power_supply_put(bq->notify_psy);
 error_2:
 	kfree(name);
 error_1:
@@ -1692,8 +1695,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] 31+ messages in thread

* [PATCH v3 19/20] mfd: ab8500: Decrement the power supply's device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (16 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 18/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-01-30 14:47 ` [PATCH v3 20/20] arm: mach-pxa: " Krzysztof Kozlowski
  2015-02-02  8:58 ` [PATCH v3 00/20] power_supply: Allow safe usage of power supply Marc Dietrich
  19 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.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] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (17 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 19/20] mfd: ab8500: " Krzysztof Kozlowski
@ 2015-01-30 14:47 ` Krzysztof Kozlowski
  2015-02-06 13:49   ` Pavel Machek
  2015-02-07 12:54   ` Robert Jarzmik
  2015-02-02  8:58 ` [PATCH v3 00/20] power_supply: Allow safe usage of power supply Marc Dietrich
  19 siblings, 2 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-01-30 14: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>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
---
 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] 31+ messages in thread

* [PATCH v3 00/20] power_supply: Allow safe usage of power supply
  2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
                   ` (18 preceding siblings ...)
  2015-01-30 14:47 ` [PATCH v3 20/20] arm: mach-pxa: " Krzysztof Kozlowski
@ 2015-02-02  8:58 ` Marc Dietrich
  19 siblings, 0 replies; 31+ messages in thread
From: Marc Dietrich @ 2015-02-02  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

Am Freitag, 30. Januar 2015, 15:47:38 schrieb Krzysztof Kozlowski:
> Hi,
> 
> The patchset changes power supply API and drivers implementing
> power supply class.
> 
> 
> TLDR for driver and subsystem maintainers
> =========================================
> Two patches of patchset change power_supply_register() function so in
> the same time they touch all drivers. I am kindly asking for acks,
> review and help in testing.
> 
> Please look at:
>  - patch 2: power_supply: Move run-time configuration to separate structure
>  - patch 11: power_supply: Change ownership from driver to core
> 
> These are huge.

Patches 2 and 11 are Reviewed-By: Marc Dietrich <marvin24@gmx.de> # for the 
nvec part.

Thanks!

Marc
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150202/d038734b/attachment.sig>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs
  2015-01-30 14:47 ` [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
@ 2015-02-04 13:44   ` Pavel Machek
  0 siblings, 0 replies; 31+ messages in thread
From: Pavel Machek @ 2015-02-04 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri 2015-01-30 15:47:41, Krzysztof Kozlowski wrote:
> Add simple wrappers for accessing power supply's function attributes:
>  - get_property -> power_supply_get_property
>  - set_property -> power_supply_set_property
>  - property_is_writeable -> power_supply_property_is_writeable
>  - external_power_changed -> power_supply_external_power_changed
> 
> This API along with atomic 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.
> 
> Next patch changing the ownership of power supply class is still needed
> to fully fix race conditions in accessing freed power supply.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Reviewed-by: Sebastian Reichel <sre@kernel.org>

For 1-3: Acked-by: Pavel Machek <pavel@ucw.cz>

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-01-30 14:47 ` [PATCH v3 20/20] arm: mach-pxa: " Krzysztof Kozlowski
@ 2015-02-06 13:49   ` Pavel Machek
  2015-02-06 14:43     ` Krzysztof Kozlowski
  2015-02-07 12:54   ` Robert Jarzmik
  1 sibling, 1 reply; 31+ messages in thread
From: Pavel Machek @ 2015-02-06 13:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri 2015-01-30 15:47:58, 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>
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Reviewed-by: Sebastian Reichel <sre@kernel.org>

11,13,20 nothing obviously wrong. But I'm not sure if I studied them
closely enough to warrant an ACK.

It would be good to get this into kernel -- I seen no bad comments,
and it is not going to improve without merge into mainline.

									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] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-02-06 13:49   ` Pavel Machek
@ 2015-02-06 14:43     ` Krzysztof Kozlowski
  2015-02-06 14:59       ` Pavel Machek
  0 siblings, 1 reply; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-02-06 14:43 UTC (permalink / raw)
  To: linux-arm-kernel

On pi?, 2015-02-06 at 14:49 +0100, Pavel Machek wrote:
> On Fri 2015-01-30 15:47:58, 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>
> > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > Reviewed-by: Sebastian Reichel <sre@kernel.org>
> 
> 11,13,20 nothing obviously wrong. But I'm not sure if I studied them
> closely enough to warrant an ACK.
> 
> It would be good to get this into kernel -- I seen no bad comments,
> and it is not going to improve without merge into mainline.

Thanks for looking at patchset. It would be really nice if this could be
tested for some time in linux-next. Such testing would help a lot. But I
need acks from various maintainers for that.

Of course the patchset to big enough to go into 3.20. If needed this
could be taken gradually in following steps:
1. Patches 1-2 (patch 2 touches *all drivers*),
2. Patches 3-10 (touch only individual drivers),
3. Patch 11 (again *everything* changed),
4. Patches 12-20 (individual changes).

In such case I will refresh everything after each step so new drivers
would be also updated.

Thanks again Pavel for prompt replies.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-02-06 14:43     ` Krzysztof Kozlowski
@ 2015-02-06 14:59       ` Pavel Machek
  2015-02-09 10:07         ` Krzysztof Kozlowski
  0 siblings, 1 reply; 31+ messages in thread
From: Pavel Machek @ 2015-02-06 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri 2015-02-06 15:43:08, Krzysztof Kozlowski wrote:
> On pi?, 2015-02-06 at 14:49 +0100, Pavel Machek wrote:
> > On Fri 2015-01-30 15:47:58, 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>
> > > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > Reviewed-by: Sebastian Reichel <sre@kernel.org>
> > 
> > 11,13,20 nothing obviously wrong. But I'm not sure if I studied them
> > closely enough to warrant an ACK.
> > 
> > It would be good to get this into kernel -- I seen no bad comments,
> > and it is not going to improve without merge into mainline.
> 
> Thanks for looking at patchset. It would be really nice if this could be
> tested for some time in linux-next. Such testing would help a lot. But I
> need acks from various maintainers for that.

Actually, you don't. The various maintainers clearly don't care at
this point. They had enough time. So you select one maintainer you
want to push this through, and you push it.

Someone may complain, so you'll solve the feedback...

Good luck,
									Pavel

> Of course the patchset to big enough to go into 3.20. If needed this
> could be taken gradually in following steps:
> 1. Patches 1-2 (patch 2 touches *all drivers*),
> 2. Patches 3-10 (touch only individual drivers),
> 3. Patch 11 (again *everything* changed),
> 4. Patches 12-20 (individual changes).
> 
> In such case I will refresh everything after each step so new drivers
> would be also updated.
> 
> Thanks again Pavel for prompt replies.

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

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure
  2015-01-30 14:47 ` [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
@ 2015-02-07  2:19   ` Darren Hart
  0 siblings, 0 replies; 31+ messages in thread
From: Darren Hart @ 2015-02-07  2:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 30, 2015 at 03:47:40PM +0100, Krzysztof Kozlowski wrote:
> Add new structure 'power_supply_config' for holding run-time
> initialization data like of_node, supplies and private driver data.
> 
> The power_supply_register() function is changed so all power supply
> drivers need updating.
> 
> When registering the power supply this new 'power_supply_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.
> 
> When a driver does not use of_node or supplies then it should use NULL
> as config. If driver uses of_node or supplies then it should allocate
> config on stack and initialize it with proper values.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

For drivers/platform/x86/compal-laptop.c

Reviewed-by: Darren Hart <dvhart@linux.intel.com>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-01-30 14:47 ` [PATCH v3 20/20] arm: mach-pxa: " Krzysztof Kozlowski
  2015-02-06 13:49   ` Pavel Machek
@ 2015-02-07 12:54   ` Robert Jarzmik
  1 sibling, 0 replies; 31+ messages in thread
From: Robert Jarzmik @ 2015-02-07 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

Krzysztof Kozlowski <k.kozlowski@samsung.com> writes:

> Use power_supply_put() to decrement the power supply's device reference
> counter.
>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Reviewed-by: Sebastian Reichel <sre@kernel.org>

Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>

--
Robert

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-02-06 14:59       ` Pavel Machek
@ 2015-02-09 10:07         ` Krzysztof Kozlowski
  2015-02-11 22:12           ` Pavel Machek
  0 siblings, 1 reply; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-02-09 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On pi?, 2015-02-06 at 15:59 +0100, Pavel Machek wrote:
> On Fri 2015-02-06 15:43:08, Krzysztof Kozlowski wrote:
> > On pi?, 2015-02-06 at 14:49 +0100, Pavel Machek wrote:
> > > On Fri 2015-01-30 15:47:58, 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>
> > > > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > > Reviewed-by: Sebastian Reichel <sre@kernel.org>
> > > 
> > > 11,13,20 nothing obviously wrong. But I'm not sure if I studied them
> > > closely enough to warrant an ACK.
> > > 
> > > It would be good to get this into kernel -- I seen no bad comments,
> > > and it is not going to improve without merge into mainline.
> > 
> > Thanks for looking at patchset. It would be really nice if this could be
> > tested for some time in linux-next. Such testing would help a lot. But I
> > need acks from various maintainers for that.
> 
> Actually, you don't. The various maintainers clearly don't care at
> this point. They had enough time. So you select one maintainer you
> want to push this through, and you push it.
> 
> Someone may complain, so you'll solve the feedback...

I am thinking also on another way of solving this huge-patch problem:
1. Mark all drivers broken (CONFIG_BROKEN).
2. Introduce change in power_supply_register() API. Broken drivers
   will fail to build.
3. Convert broken drivers to new API incrementally (one driver
   per patch) marking them also non-broken.

This would be much easier to review but also this would break
build-bisectability for drivers and some platforms using them (like
OLPC, compal-laptop, ACPI).

In case of important platforms (like ACPI) I could do the old-way:
change the driver along with API change.

What do you think about this?


I pushed the patchset here:
https://git.linaro.org/people/marek.szyprowski/linux-srpol.git/shortlog/refs/heads/v3.19-next-power-supply-core-ownership
(actually this is v4: added acks/reviews and minor issue fixed; merge
window has opened so I'll wait with sending this to LKML).


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing function attrs
  2015-01-30 14:47 ` [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
@ 2015-02-09 19:02   ` Stefan Wahren
  2015-02-10  7:39     ` Krzysztof Kozlowski
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan Wahren @ 2015-02-09 19:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Krzysztof,

> Krzysztof Kozlowski <k.kozlowski@samsung.com> hat am 30. Januar 2015 um 15:47
> geschrieben:
>
>
> 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>

just a nit. It looks like a typo in the mail address which is also in patch 5 -
10.

I applied patch 1 - 14 to my repo with a upcoming power driver (mxs_power) and
didn't see any problems with your patches.

Stefan

> Acked-by: Pavel Machek <pavel@ucw.cz>
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Reviewed-by: Sebastian Reichel <sre@kernel.org>
> ---

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing function attrs
  2015-02-09 19:02   ` Stefan Wahren
@ 2015-02-10  7:39     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 31+ messages in thread
From: Krzysztof Kozlowski @ 2015-02-10  7:39 UTC (permalink / raw)
  To: linux-arm-kernel

On pon, 2015-02-09 at 20:02 +0100, Stefan Wahren wrote:
> Hi Krzysztof,
> 
> > Krzysztof Kozlowski <k.kozlowski@samsung.com> hat am 30. Januar 2015 um 15:47
> > geschrieben:
> >
> >
> > 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>
> 
> just a nit. It looks like a typo in the mail address which is also in patch 5 -
> 10.

Right, I copied it directly from Jonghwa's response. Thank you for
noticing it.

> 
> I applied patch 1 - 14 to my repo with a upcoming power driver (mxs_power) and
> didn't see any problems with your patches.

Great, thanks!

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 20/20] arm: mach-pxa: Decrement the power supply's device reference counter
  2015-02-09 10:07         ` Krzysztof Kozlowski
@ 2015-02-11 22:12           ` Pavel Machek
  0 siblings, 0 replies; 31+ messages in thread
From: Pavel Machek @ 2015-02-11 22:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 2015-02-09 11:07:12, Krzysztof Kozlowski wrote:
> On pi?, 2015-02-06 at 15:59 +0100, Pavel Machek wrote:
> > On Fri 2015-02-06 15:43:08, Krzysztof Kozlowski wrote:
> > > On pi?, 2015-02-06 at 14:49 +0100, Pavel Machek wrote:
> > > > On Fri 2015-01-30 15:47:58, 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>
> > > > > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > > > Reviewed-by: Sebastian Reichel <sre@kernel.org>
> > > > 
> > > > 11,13,20 nothing obviously wrong. But I'm not sure if I studied them
> > > > closely enough to warrant an ACK.
> > > > 
> > > > It would be good to get this into kernel -- I seen no bad comments,
> > > > and it is not going to improve without merge into mainline.
> > > 
> > > Thanks for looking at patchset. It would be really nice if this could be
> > > tested for some time in linux-next. Such testing would help a lot. But I
> > > need acks from various maintainers for that.
> > 
> > Actually, you don't. The various maintainers clearly don't care at
> > this point. They had enough time. So you select one maintainer you
> > want to push this through, and you push it.
> > 
> > Someone may complain, so you'll solve the feedback...
> 
> I am thinking also on another way of solving this huge-patch problem:
> 1. Mark all drivers broken (CONFIG_BROKEN).
> 2. Introduce change in power_supply_register() API. Broken drivers
>    will fail to build.
> 3. Convert broken drivers to new API incrementally (one driver
>    per patch) marking them also non-broken.
> 
> This would be much easier to review but also this would break
> build-bisectability for drivers and some platforms using them (like
> OLPC, compal-laptop, ACPI).

It is easy enough to review as it is, playing with CONFIG_BROKEN will
not improve it. Just push the patch...

> I pushed the patchset here:
> https://git.linaro.org/people/marek.szyprowski/linux-srpol.git/shortlog/refs/heads/v3.19-next-power-supply-core-ownership
> (actually this is v4: added acks/reviews and minor issue fixed; merge
> window has opened so I'll wait with sending this to LKML).

Great... now you just need one of maintainers to merge it...

POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
M:      Sebastian Reichel <sre@kernel.org>
M:      Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
M:      David Woodhouse <dwmw2@infradead.org>
									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] 31+ messages in thread

end of thread, other threads:[~2015-02-11 22:12 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-30 14:47 [PATCH v3 00/20] power_supply: Allow safe usage of power supply Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 01/20] power_supply: Add driver private data Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 02/20] power_supply: Move run-time configuration to separate structure Krzysztof Kozlowski
2015-02-07  2:19   ` Darren Hart
2015-01-30 14:47 ` [PATCH v3 03/20] power_supply: Add API for safe access of power supply function attrs Krzysztof Kozlowski
2015-02-04 13:44   ` Pavel Machek
2015-01-30 14:47 ` [PATCH v3 04/20] power_supply: sysfs: Use power_supply_*() API for accessing " Krzysztof Kozlowski
2015-02-09 19:02   ` Stefan Wahren
2015-02-10  7:39     ` Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 05/20] power_supply: 88pm860x_charger: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 06/20] power_supply: ab8500: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 07/20] mfd: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 08/20] power_supply: apm_power: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 09/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 10/20] power_supply: charger-manager: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 12/20] power_supply: Add power_supply_put for decrementing device reference counter Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 13/20] power_supply: Increment power supply use counter when obtaining references Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 14/20] power_supply: charger-manager: Decrement the power supply's device reference counter Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 15/20] x86/olpc/xo1/sci: Use newly added power_supply_put API Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 16/20] x86/olpc/xo15/sci: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 17/20] power_supply: 88pm860x_charger: Decrement the power supply's device reference counter Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 18/20] power_supply: bq2415x_charger: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 19/20] mfd: ab8500: " Krzysztof Kozlowski
2015-01-30 14:47 ` [PATCH v3 20/20] arm: mach-pxa: " Krzysztof Kozlowski
2015-02-06 13:49   ` Pavel Machek
2015-02-06 14:43     ` Krzysztof Kozlowski
2015-02-06 14:59       ` Pavel Machek
2015-02-09 10:07         ` Krzysztof Kozlowski
2015-02-11 22:12           ` Pavel Machek
2015-02-07 12:54   ` Robert Jarzmik
2015-02-02  8:58 ` [PATCH v3 00/20] power_supply: Allow safe usage of power supply Marc Dietrich

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).