Skip to content

Commit e5f84d1

Browse files
t-8chsre
authored andcommitted
power: supply: cros_charge-control: add mutex for driver data
Concurrent accesses through sysfs may lead to inconsistent state in the priv data. Introduce a mutex to avoid this. Fixes: c6ed48e ("power: supply: add ChromeOS EC based charge control driver") Cc: [email protected] Signed-off-by: Thomas Weißschuh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sebastian Reichel <[email protected]>
1 parent afc6e39 commit e5f84d1

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

drivers/power/supply/cros_charge-control.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
#include <acpi/battery.h>
88
#include <linux/container_of.h>
99
#include <linux/dmi.h>
10+
#include <linux/lockdep.h>
1011
#include <linux/mod_devicetable.h>
1112
#include <linux/module.h>
13+
#include <linux/mutex.h>
1214
#include <linux/platform_data/cros_ec_commands.h>
1315
#include <linux/platform_data/cros_ec_proto.h>
1416
#include <linux/platform_device.h>
@@ -49,6 +51,7 @@ struct cros_chctl_priv {
4951
struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT];
5052
struct attribute_group group;
5153

54+
struct mutex lock; /* protects fields below and cros_ec */
5255
enum power_supply_charge_behaviour current_behaviour;
5356
u8 current_start_threshold, current_end_threshold;
5457
};
@@ -85,6 +88,8 @@ static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
8588
{
8689
struct ec_params_charge_control req = {};
8790

91+
lockdep_assert_held(&priv->lock);
92+
8893
req.cmd = EC_CHARGE_CONTROL_CMD_SET;
8994

9095
switch (priv->current_behaviour) {
@@ -159,6 +164,7 @@ static ssize_t charge_control_start_threshold_show(struct device *dev,
159164
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
160165
CROS_CHCTL_ATTR_START_THRESHOLD);
161166

167+
guard(mutex)(&priv->lock);
162168
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold);
163169
}
164170

@@ -169,6 +175,7 @@ static ssize_t charge_control_start_threshold_store(struct device *dev,
169175
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
170176
CROS_CHCTL_ATTR_START_THRESHOLD);
171177

178+
guard(mutex)(&priv->lock);
172179
return cros_chctl_store_threshold(dev, priv, 0, buf, count);
173180
}
174181

@@ -178,6 +185,7 @@ static ssize_t charge_control_end_threshold_show(struct device *dev, struct devi
178185
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
179186
CROS_CHCTL_ATTR_END_THRESHOLD);
180187

188+
guard(mutex)(&priv->lock);
181189
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold);
182190
}
183191

@@ -187,6 +195,7 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, struct dev
187195
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
188196
CROS_CHCTL_ATTR_END_THRESHOLD);
189197

198+
guard(mutex)(&priv->lock);
190199
return cros_chctl_store_threshold(dev, priv, 1, buf, count);
191200
}
192201

@@ -195,6 +204,7 @@ static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute
195204
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
196205
CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);
197206

207+
guard(mutex)(&priv->lock);
198208
return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS,
199209
priv->current_behaviour, buf);
200210
}
@@ -210,6 +220,7 @@ static ssize_t charge_behaviour_store(struct device *dev, struct device_attribut
210220
if (ret < 0)
211221
return ret;
212222

223+
guard(mutex)(&priv->lock);
213224
priv->current_behaviour = ret;
214225

215226
ret = cros_chctl_configure_ec(priv);
@@ -290,6 +301,10 @@ static int cros_chctl_probe(struct platform_device *pdev)
290301
if (!priv)
291302
return -ENOMEM;
292303

304+
ret = devm_mutex_init(dev, &priv->lock);
305+
if (ret)
306+
return ret;
307+
293308
ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL);
294309
if (ret < 0)
295310
return ret;
@@ -327,7 +342,8 @@ static int cros_chctl_probe(struct platform_device *pdev)
327342
priv->current_end_threshold = 100;
328343

329344
/* Bring EC into well-known state */
330-
ret = cros_chctl_configure_ec(priv);
345+
scoped_guard(mutex, &priv->lock)
346+
ret = cros_chctl_configure_ec(priv);
331347
if (ret < 0)
332348
return ret;
333349

0 commit comments

Comments
 (0)