summaryrefslogtreecommitdiffstats
path: root/drivers/power/supply
diff options
context:
space:
mode:
authorSebastian Reichel <sebastian.reichel@collabora.com>2018-09-28 17:35:37 +0200
committerSebastian Reichel <sre@kernel.org>2018-12-13 00:16:20 +0100
commit157ba1bb5fcb91366df3be5e63a04b799ff9cf64 (patch)
treeefbb8664aa84ad60a9520966df63e0574bd44ca1 /drivers/power/supply
parentefcca6bdfba1d579d86bd3f5ea65e5bf8e7deebe (diff)
downloadlinux-157ba1bb5fcb91366df3be5e63a04b799ff9cf64.tar.bz2
power: supply: charger-manager: fix race-condition in sysfs registration
This registers custom sysfs properties using the native functionality of the power-supply framework, which cleans up the code a bit and fixes a race-condition. Before this patch the sysfs attributes were not properly registered to udev. Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Diffstat (limited to 'drivers/power/supply')
-rw-r--r--drivers/power/supply/charger-manager.c51
1 files changed, 22 insertions, 29 deletions
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index 2e579da5c0b9..38be91f21cc4 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -1351,7 +1351,7 @@ static ssize_t charger_externally_control_store(struct device *dev,
}
/**
- * charger_manager_register_sysfs - Register sysfs entry for each charger
+ * charger_manager_prepare_sysfs - Prepare sysfs entry for each charger
* @cm: the Charger Manager representing the battery.
*
* This function add sysfs entry for charger(regulator) to control charger from
@@ -1363,13 +1363,12 @@ static ssize_t charger_externally_control_store(struct device *dev,
* externally_control, this charger isn't controlled from charger-manager and
* always stay off state of regulator.
*/
-static int charger_manager_register_sysfs(struct charger_manager *cm)
+static int charger_manager_prepare_sysfs(struct charger_manager *cm)
{
struct charger_desc *desc = cm->desc;
struct charger_regulator *charger;
int chargers_externally_control = 1;
char *name;
- int ret;
int i;
/* Create sysfs entry to control charger(regulator) */
@@ -1384,8 +1383,10 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
charger->attrs[1] = &charger->attr_state.attr;
charger->attrs[2] = &charger->attr_externally_control.attr;
charger->attrs[3] = NULL;
- charger->attr_g.name = name;
- charger->attr_g.attrs = charger->attrs;
+
+ charger->attr_grp.name = name;
+ charger->attr_grp.attrs = charger->attrs;
+ desc->sysfs_groups[i] = &charger->attr_grp;
sysfs_attr_init(&charger->attr_name.attr);
charger->attr_name.attr.name = "name";
@@ -1412,14 +1413,6 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
dev_info(cm->dev, "'%s' regulator's externally_control is %d\n",
charger->regulator_name, charger->externally_control);
-
- ret = sysfs_create_group(&cm->charger_psy->dev.kobj,
- &charger->attr_g);
- if (ret < 0) {
- dev_err(cm->dev, "Cannot create sysfs entry of %s regulator\n",
- charger->regulator_name);
- return ret;
- }
}
if (chargers_externally_control) {
@@ -1560,6 +1553,13 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
desc->charger_regulators = chg_regs;
+ desc->sysfs_groups = devm_kcalloc(dev,
+ desc->num_charger_regulators + 1,
+ sizeof(*desc->sysfs_groups),
+ GFP_KERNEL);
+ if (!desc->sysfs_groups)
+ return ERR_PTR(-ENOMEM);
+
for_each_child_of_node(np, child) {
struct charger_cable *cables;
struct device_node *_child;
@@ -1762,6 +1762,15 @@ static int charger_manager_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
+ /* Register sysfs entry for charger(regulator) */
+ ret = charger_manager_prepare_sysfs(cm);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Cannot prepare sysfs entry of regulators\n");
+ return ret;
+ }
+ psy_cfg.attr_grp = desc->sysfs_groups;
+
cm->charger_psy = power_supply_register(&pdev->dev,
&cm->charger_psy_desc,
&psy_cfg);
@@ -1778,14 +1787,6 @@ static int charger_manager_probe(struct platform_device *pdev)
goto err_reg_extcon;
}
- /* Register sysfs entry for charger(regulator) */
- ret = charger_manager_register_sysfs(cm);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "Cannot initialize sysfs entry of regulator\n");
- goto err_reg_sysfs;
- }
-
/* Add to the list */
mutex_lock(&cm_list_mtx);
list_add(&cm->entry, &cm_list);
@@ -1809,14 +1810,6 @@ static int charger_manager_probe(struct platform_device *pdev)
return 0;
-err_reg_sysfs:
- for (i = 0; i < desc->num_charger_regulators; i++) {
- struct charger_regulator *charger;
-
- charger = &desc->charger_regulators[i];
- sysfs_remove_group(&cm->charger_psy->dev.kobj,
- &charger->attr_g);
- }
err_reg_extcon:
for (i = 0; i < desc->num_charger_regulators; i++) {
struct charger_regulator *charger;