Skip to content

Commit 8379578

Browse files
committed
Merge tag 'for-v6.13-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply fixes from Sebastian Reichel: - fix potential array out of bounds access in gpio-charger - cros_charge-control: - fix concurrent sysfs access - allow start_threshold == end_threshold - workaround limited v2 charge threshold API - bq24296: fix vbus regulator handling * tag 'for-v6.13-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: power: supply: bq24190: Fix BQ24296 Vbus regulator support power: supply: cros_charge-control: hide start threshold on v2 cmd power: supply: cros_charge-control: allow start_threshold == end_threshold power: supply: cros_charge-control: add mutex for driver data power: supply: gpio-charger: Fix set charge current limits
2 parents eff4f67 + b3ded60 commit 8379578

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

drivers/power/supply/bq24190_charger.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
567567

568568
static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
569569
{
570+
union power_supply_propval val = { .intval = bdi->charge_type };
570571
int ret;
571572

572573
ret = pm_runtime_resume_and_get(bdi->dev);
@@ -587,13 +588,18 @@ static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
587588

588589
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
589590
BQ24296_REG_POC_OTG_CONFIG_MASK,
590-
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
591+
BQ24296_REG_POC_OTG_CONFIG_SHIFT,
591592
BQ24296_REG_POC_OTG_CONFIG_OTG);
592-
} else
593+
} else {
593594
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
594595
BQ24296_REG_POC_OTG_CONFIG_MASK,
595-
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
596+
BQ24296_REG_POC_OTG_CONFIG_SHIFT,
596597
BQ24296_REG_POC_OTG_CONFIG_DISABLE);
598+
if (ret < 0)
599+
goto out;
600+
601+
ret = bq24190_charger_set_charge_type(bdi, &val);
602+
}
597603

598604
out:
599605
pm_runtime_mark_last_busy(bdi->dev);

drivers/power/supply/cros_charge-control.c

Lines changed: 27 additions & 9 deletions
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) {
@@ -134,11 +139,15 @@ static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_
134139
return -EINVAL;
135140

136141
if (is_end_threshold) {
137-
if (val <= priv->current_start_threshold)
142+
/* Start threshold is not exposed, use fixed value */
143+
if (priv->cmd_version == 2)
144+
priv->current_start_threshold = val == 100 ? 0 : val;
145+
146+
if (val < priv->current_start_threshold)
138147
return -EINVAL;
139148
priv->current_end_threshold = val;
140149
} else {
141-
if (val >= priv->current_end_threshold)
150+
if (val > priv->current_end_threshold)
142151
return -EINVAL;
143152
priv->current_start_threshold = val;
144153
}
@@ -159,6 +168,7 @@ static ssize_t charge_control_start_threshold_show(struct device *dev,
159168
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
160169
CROS_CHCTL_ATTR_START_THRESHOLD);
161170

171+
guard(mutex)(&priv->lock);
162172
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold);
163173
}
164174

@@ -169,6 +179,7 @@ static ssize_t charge_control_start_threshold_store(struct device *dev,
169179
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
170180
CROS_CHCTL_ATTR_START_THRESHOLD);
171181

182+
guard(mutex)(&priv->lock);
172183
return cros_chctl_store_threshold(dev, priv, 0, buf, count);
173184
}
174185

@@ -178,6 +189,7 @@ static ssize_t charge_control_end_threshold_show(struct device *dev, struct devi
178189
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
179190
CROS_CHCTL_ATTR_END_THRESHOLD);
180191

192+
guard(mutex)(&priv->lock);
181193
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold);
182194
}
183195

@@ -187,6 +199,7 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, struct dev
187199
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
188200
CROS_CHCTL_ATTR_END_THRESHOLD);
189201

202+
guard(mutex)(&priv->lock);
190203
return cros_chctl_store_threshold(dev, priv, 1, buf, count);
191204
}
192205

@@ -195,6 +208,7 @@ static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute
195208
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
196209
CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);
197210

211+
guard(mutex)(&priv->lock);
198212
return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS,
199213
priv->current_behaviour, buf);
200214
}
@@ -210,6 +224,7 @@ static ssize_t charge_behaviour_store(struct device *dev, struct device_attribut
210224
if (ret < 0)
211225
return ret;
212226

227+
guard(mutex)(&priv->lock);
213228
priv->current_behaviour = ret;
214229

215230
ret = cros_chctl_configure_ec(priv);
@@ -223,12 +238,10 @@ static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute
223238
{
224239
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n);
225240

226-
if (priv->cmd_version < 2) {
227-
if (n == CROS_CHCTL_ATTR_START_THRESHOLD)
228-
return 0;
229-
if (n == CROS_CHCTL_ATTR_END_THRESHOLD)
230-
return 0;
231-
}
241+
if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3)
242+
return 0;
243+
else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2)
244+
return 0;
232245

233246
return attr->mode;
234247
}
@@ -290,6 +303,10 @@ static int cros_chctl_probe(struct platform_device *pdev)
290303
if (!priv)
291304
return -ENOMEM;
292305

306+
ret = devm_mutex_init(dev, &priv->lock);
307+
if (ret)
308+
return ret;
309+
293310
ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL);
294311
if (ret < 0)
295312
return ret;
@@ -327,7 +344,8 @@ static int cros_chctl_probe(struct platform_device *pdev)
327344
priv->current_end_threshold = 100;
328345

329346
/* Bring EC into well-known state */
330-
ret = cros_chctl_configure_ec(priv);
347+
scoped_guard(mutex, &priv->lock)
348+
ret = cros_chctl_configure_ec(priv);
331349
if (ret < 0)
332350
return ret;
333351

drivers/power/supply/gpio-charger.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ static int set_charge_current_limit(struct gpio_charger *gpio_charger, int val)
6767
if (gpio_charger->current_limit_map[i].limit_ua <= val)
6868
break;
6969
}
70+
71+
/*
72+
* If a valid charge current limit isn't found, default to smallest
73+
* current limitation for safety reasons.
74+
*/
75+
if (i >= gpio_charger->current_limit_map_size)
76+
i = gpio_charger->current_limit_map_size - 1;
77+
7078
mapping = gpio_charger->current_limit_map[i];
7179

7280
for (i = 0; i < ndescs; i++) {

0 commit comments

Comments
 (0)