mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 15:32:04 +02:00
Power Supply Fixes for 7.3 cycle
* power-supply core - prevent unregistering a power supply while a callback runs * power-supply drivers - generic-adc-battery: Fix temperature IIO channel conversion - ds2780: Fix ds2780_get_capacity() returning raw value - max17042_battery: Fix vmin assigned instead of vmax in DT parsing - Fix maintenance charge table kernel-doc -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmrOwSkACgkQ2O7X88g7 +prAqw//d/NwWB6j/ZgAmi7Ww7BDnZrpHIaPrwc6t2qLG6Mu+WgWeGuKjIEd3dye +j+nSQBwEnE2yI1bJK/R2suV3c3MeMBga24W3QQ9smYvRsH+btR59TVb5Aak/l0B eo3UM8DC36k9+pzOpPFFqqf7tJNcatkC3jUdqp9nL1FA/dITc7OrVhsFkSAijjO+ U2BhXFvw9Oy1vkXPbEew9kmfi0DyYVsJJc0G7PNsJmlmS1q+VOZMTtGhXKy5/BG0 XR4BDOv7Sas7gETkTz3CKD+5IYRx7j2nah4slVYXmFImnpWfhsVCBPGdPR4jhGW6 5L5+TlK21DRvIEoaQZWdkvxvAqXIqHINUZzGNHiqdhBEYRT2Qr+KtyTVfYOeUmh7 IHLUJl+HpuZn5V/jfCkxfrSrNqmyK0/8O6hVVyvn7I6eEmTWvd6b8AcWr++TQTZa xgZl2js9F7DZ176cJaf/3rn9twShuQ2xhAtbVTr1V+HbD5IBGheQ/TfELLVUr/m1 JKBUjDRY060EROXhTkcXs3Lwt7hSFqj/fKggiWJZKqsMnSgJjyaTwpLx9k88Qqqn 5eyyjFZDEqcT8fzb5MwRvCLYVJbcJ0Up72e5xi4nXBfLcuC1jVeOG4hiwF55obrb XvFx8TQvOLVdy7H15ZX0fwOiNj68lUZi+1jebQWhoTb5z9GdkBg= =QLJn -----END PGP SIGNATURE----- Merge tag 'for-v7.3-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply Pull power supply fixes from Sebastian Reichel: "power-supply core: - prevent unregistering a power supply while a callback runs power-supply drivers: - generic-adc-battery: Fix temperature IIO channel conversion - ds2780: Fix ds2780_get_capacity() returning raw value - max17042_battery: Fix vmin assigned instead of vmax in DT parsing - Fix maintenance charge table kernel-doc" * tag 'for-v7.3-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: power: supply: core: prevent unregistering a power supply while a callback runs power: supply: generic-adc-battery: Fix temperature IIO channel conversion power: supply: ds2780: Fix ds2780_get_capacity() returning raw value power: supply: Fix maintenance charge table kernel-doc power: supply: max17042_battery: Fix vmin assigned instead of vmax in DT parsing
This commit is contained in:
commit
d77bd0d469
|
|
@ -304,7 +304,7 @@ static int ds2780_get_capacity(struct ds2780_device_info *dev_info,
|
|||
return ret;
|
||||
|
||||
*capacity = raw;
|
||||
return raw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ds2780_get_status(struct ds2780_device_info *dev_info, int *status)
|
||||
|
|
|
|||
|
|
@ -90,12 +90,17 @@ static int gab_read_channel(struct gab *adc_bat, enum gab_chan_type channel,
|
|||
int ret;
|
||||
|
||||
ret = iio_read_channel_processed(adc_bat->channel[channel], result);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(&adc_bat->psy->dev, "read channel error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (channel == GAB_TEMP)
|
||||
*result /= 100; /* Convert from milli- to deci-degree */
|
||||
else
|
||||
*result *= 1000;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gab_get_property(struct power_supply *psy,
|
||||
|
|
|
|||
|
|
@ -1233,7 +1233,7 @@ static int max17042_parse_dt(struct max17042_chip *chip)
|
|||
if (of_property_read_u32(np, "maxim,over-volt", &prop))
|
||||
chip->vmax = INT_MAX;
|
||||
else
|
||||
chip->vmin = prop;
|
||||
chip->vmax = prop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1530,6 +1530,19 @@ void power_supply_external_power_changed(struct power_supply *psy)
|
|||
!psy->desc->external_power_changed)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Keep power_supply_unregister() from returning, and thus from letting
|
||||
* the driver's data be freed, while the callback is running. The
|
||||
* ->removing check has to happen under the lock: on its own, just like
|
||||
* the use_cnt check above, it only tells us the supply was still there
|
||||
* when we looked, not that it still is by the time the callback
|
||||
* dereferences its driver data.
|
||||
*/
|
||||
guard(rwsem_read)(&psy->epc_sem);
|
||||
|
||||
if (psy->removing)
|
||||
return;
|
||||
|
||||
psy->desc->external_power_changed(psy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_external_power_changed);
|
||||
|
|
@ -1774,6 +1787,7 @@ __power_supply_register(struct device *parent,
|
|||
}
|
||||
|
||||
spin_lock_init(&psy->changed_lock);
|
||||
init_rwsem(&psy->epc_sem);
|
||||
init_rwsem(&psy->extensions_sem);
|
||||
INIT_LIST_HEAD(&psy->extensions);
|
||||
|
||||
|
|
@ -1914,7 +1928,17 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register);
|
|||
void power_supply_unregister(struct power_supply *psy)
|
||||
{
|
||||
WARN_ON(atomic_dec_return(&psy->use_cnt));
|
||||
psy->removing = true;
|
||||
|
||||
/*
|
||||
* Publish ->removing so that no new ->external_power_changed() call can
|
||||
* start, and wait via semaphore for one that is already running: it may
|
||||
* be a supplier's changed_work, which cancel_work_sync() below does not
|
||||
* cover, and it may still dereference driver data that the caller is
|
||||
* about to free.
|
||||
*/
|
||||
scoped_guard(rwsem_write, &psy->epc_sem)
|
||||
psy->removing = true;
|
||||
|
||||
cancel_work_sync(&psy->changed_work);
|
||||
cancel_delayed_work_sync(&psy->deferred_register_work);
|
||||
sysfs_remove_link(&psy->dev.kobj, "powers");
|
||||
|
|
|
|||
|
|
@ -351,6 +351,16 @@ struct power_supply {
|
|||
bool removing;
|
||||
atomic_t use_cnt;
|
||||
struct power_supply_battery_info *battery_info;
|
||||
/*
|
||||
* Held for read while ->external_power_changed() runs, and for write by
|
||||
* power_supply_unregister() when it publishes @removing, so that it
|
||||
* waits for an in-flight callback to finish. Without this a driver's
|
||||
* data, typically devm-allocated on its own device, can be freed while
|
||||
* the callback is still using it.
|
||||
* Must not be shared with extensions_sem: callbacks may read their own
|
||||
* properties, which takes that one for read.
|
||||
*/
|
||||
struct rw_semaphore epc_sem;
|
||||
struct rw_semaphore extensions_sem; /* protects "extensions" */
|
||||
struct list_head extensions;
|
||||
#ifdef CONFIG_THERMAL
|
||||
|
|
@ -414,9 +424,9 @@ struct power_supply_vbat_ri_table {
|
|||
* @charge_voltage_max_uv: maintenance charging voltage that is usually a bit
|
||||
* lower than the constant_charge_voltage_max_uv. We can apply this settings
|
||||
* charge_current_max_ua until we get back up to this voltage.
|
||||
* @safety_timer_minutes: maintenance charging safety timer, with an expiry
|
||||
* time in minutes. We will only use maintenance charging in this setting
|
||||
* for a certain amount of time, then we will first move to the next
|
||||
* @charge_safety_timer_minutes: maintenance charging safety timer, with an
|
||||
* expiry time in minutes. We will only use maintenance charging in this
|
||||
* setting for a certain amount of time, then we will first move to the next
|
||||
* maintenance charge current and voltage pair in respective array and wait
|
||||
* for the next safety timer timeout, or, if we reached the last maintencance
|
||||
* charging setting, disable charging until we reach
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user