Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+44 -12
+9 -3
drivers/power/supply/bq24190_charger.c
··· 567 567 568 568 static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable) 569 569 { 570 + union power_supply_propval val = { .intval = bdi->charge_type }; 570 571 int ret; 571 572 572 573 ret = pm_runtime_resume_and_get(bdi->dev); ··· 588 587 589 588 ret = bq24190_write_mask(bdi, BQ24190_REG_POC, 590 589 BQ24296_REG_POC_OTG_CONFIG_MASK, 591 - BQ24296_REG_POC_CHG_CONFIG_SHIFT, 590 + BQ24296_REG_POC_OTG_CONFIG_SHIFT, 592 591 BQ24296_REG_POC_OTG_CONFIG_OTG); 593 - } else 592 + } else { 594 593 ret = bq24190_write_mask(bdi, BQ24190_REG_POC, 595 594 BQ24296_REG_POC_OTG_CONFIG_MASK, 596 - BQ24296_REG_POC_CHG_CONFIG_SHIFT, 595 + BQ24296_REG_POC_OTG_CONFIG_SHIFT, 597 596 BQ24296_REG_POC_OTG_CONFIG_DISABLE); 597 + if (ret < 0) 598 + goto out; 599 + 600 + ret = bq24190_charger_set_charge_type(bdi, &val); 601 + } 598 602 599 603 out: 600 604 pm_runtime_mark_last_busy(bdi->dev);
+27 -9
drivers/power/supply/cros_charge-control.c
··· 7 7 #include <acpi/battery.h> 8 8 #include <linux/container_of.h> 9 9 #include <linux/dmi.h> 10 + #include <linux/lockdep.h> 10 11 #include <linux/mod_devicetable.h> 11 12 #include <linux/module.h> 13 + #include <linux/mutex.h> 12 14 #include <linux/platform_data/cros_ec_commands.h> 13 15 #include <linux/platform_data/cros_ec_proto.h> 14 16 #include <linux/platform_device.h> ··· 51 49 struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT]; 52 50 struct attribute_group group; 53 51 52 + struct mutex lock; /* protects fields below and cros_ec */ 54 53 enum power_supply_charge_behaviour current_behaviour; 55 54 u8 current_start_threshold, current_end_threshold; 56 55 }; ··· 87 84 static int cros_chctl_configure_ec(struct cros_chctl_priv *priv) 88 85 { 89 86 struct ec_params_charge_control req = {}; 87 + 88 + lockdep_assert_held(&priv->lock); 90 89 91 90 req.cmd = EC_CHARGE_CONTROL_CMD_SET; 92 91 ··· 139 134 return -EINVAL; 140 135 141 136 if (is_end_threshold) { 142 - if (val <= priv->current_start_threshold) 137 + /* Start threshold is not exposed, use fixed value */ 138 + if (priv->cmd_version == 2) 139 + priv->current_start_threshold = val == 100 ? 0 : val; 140 + 141 + if (val < priv->current_start_threshold) 143 142 return -EINVAL; 144 143 priv->current_end_threshold = val; 145 144 } else { 146 - if (val >= priv->current_end_threshold) 145 + if (val > priv->current_end_threshold) 147 146 return -EINVAL; 148 147 priv->current_start_threshold = val; 149 148 } ··· 168 159 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 169 160 CROS_CHCTL_ATTR_START_THRESHOLD); 170 161 162 + guard(mutex)(&priv->lock); 171 163 return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold); 172 164 } 173 165 ··· 179 169 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 180 170 CROS_CHCTL_ATTR_START_THRESHOLD); 181 171 172 + guard(mutex)(&priv->lock); 182 173 return cros_chctl_store_threshold(dev, priv, 0, buf, count); 183 174 } 184 175 ··· 189 178 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 190 179 CROS_CHCTL_ATTR_END_THRESHOLD); 191 180 181 + guard(mutex)(&priv->lock); 192 182 return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold); 193 183 } 194 184 ··· 199 187 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 200 188 CROS_CHCTL_ATTR_END_THRESHOLD); 201 189 190 + guard(mutex)(&priv->lock); 202 191 return cros_chctl_store_threshold(dev, priv, 1, buf, count); 203 192 } 204 193 ··· 208 195 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr, 209 196 CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR); 210 197 198 + guard(mutex)(&priv->lock); 211 199 return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS, 212 200 priv->current_behaviour, buf); 213 201 } ··· 224 210 if (ret < 0) 225 211 return ret; 226 212 213 + guard(mutex)(&priv->lock); 227 214 priv->current_behaviour = ret; 228 215 229 216 ret = cros_chctl_configure_ec(priv); ··· 238 223 { 239 224 struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n); 240 225 241 - if (priv->cmd_version < 2) { 242 - if (n == CROS_CHCTL_ATTR_START_THRESHOLD) 243 - return 0; 244 - if (n == CROS_CHCTL_ATTR_END_THRESHOLD) 245 - return 0; 246 - } 226 + if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3) 227 + return 0; 228 + else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2) 229 + return 0; 247 230 248 231 return attr->mode; 249 232 } ··· 303 290 if (!priv) 304 291 return -ENOMEM; 305 292 293 + ret = devm_mutex_init(dev, &priv->lock); 294 + if (ret) 295 + return ret; 296 + 306 297 ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL); 307 298 if (ret < 0) 308 299 return ret; ··· 344 327 priv->current_end_threshold = 100; 345 328 346 329 /* Bring EC into well-known state */ 347 - ret = cros_chctl_configure_ec(priv); 330 + scoped_guard(mutex, &priv->lock) 331 + ret = cros_chctl_configure_ec(priv); 348 332 if (ret < 0) 349 333 return ret; 350 334
+8
drivers/power/supply/gpio-charger.c
··· 67 67 if (gpio_charger->current_limit_map[i].limit_ua <= val) 68 68 break; 69 69 } 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 + 70 78 mapping = gpio_charger->current_limit_map[i]; 71 79 72 80 for (i = 0; i < ndescs; i++) {