mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 03:06:10 +00:00
da9030_battery: Fix race between event handler and monitor
There are cases when charging monitor and the event handler try to change the charger state simultaneously. For instance, a charger is connected to the system, there's the detection event and the event handler tries to enable charging. It is possible that the periodic charging monitor runs at the same time and it still thinks there's no external charger. So it tries to disable the charging. As the result, even if the conditions necessary to charge the battery hold, there will be no actual charging. The patch changes the event handler so that instead of enabling/ disabling the charger immediately it would rather make the monitor run. The monitor code then decides what should be the charger state. Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
This commit is contained in:
parent
c6f4a42de6
commit
a35d01a5d2
1 changed files with 12 additions and 7 deletions
|
@ -22,8 +22,6 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#define DA9030_STATUS_CHDET (1 << 3)
|
||||
|
||||
#define DA9030_FAULT_LOG 0x0a
|
||||
#define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
|
||||
#define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
|
||||
|
@ -244,6 +242,8 @@ static void da9030_set_charge(struct da9030_charger *charger, int on)
|
|||
}
|
||||
|
||||
da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
|
||||
|
||||
power_supply_changed(&charger->psy);
|
||||
}
|
||||
|
||||
static void da9030_charger_check_state(struct da9030_charger *charger)
|
||||
|
@ -258,6 +258,12 @@ static void da9030_charger_check_state(struct da9030_charger *charger)
|
|||
da9030_set_charge(charger, 1);
|
||||
}
|
||||
} else {
|
||||
/* Charger has been pulled out */
|
||||
if (!charger->chdet) {
|
||||
da9030_set_charge(charger, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (charger->adc.vbat_res >=
|
||||
charger->thresholds.vbat_charge_stop) {
|
||||
da9030_set_charge(charger, 0);
|
||||
|
@ -395,13 +401,11 @@ static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
|
|||
{
|
||||
struct da9030_charger *charger =
|
||||
container_of(nb, struct da9030_charger, nb);
|
||||
int status;
|
||||
|
||||
switch (event) {
|
||||
case DA9030_EVENT_CHDET:
|
||||
status = da903x_query_status(charger->master,
|
||||
DA9030_STATUS_CHDET);
|
||||
da9030_set_charge(charger, status);
|
||||
cancel_delayed_work_sync(&charger->work);
|
||||
schedule_work(&charger->work.work);
|
||||
break;
|
||||
case DA9030_EVENT_VBATMON:
|
||||
da9030_battery_vbat_event(charger);
|
||||
|
@ -565,7 +569,8 @@ static int da9030_battery_remove(struct platform_device *dev)
|
|||
da903x_unregister_notifier(charger->master, &charger->nb,
|
||||
DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
|
||||
DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
|
||||
cancel_delayed_work(&charger->work);
|
||||
cancel_delayed_work_sync(&charger->work);
|
||||
da9030_set_charge(charger, 0);
|
||||
power_supply_unregister(&charger->psy);
|
||||
|
||||
kfree(charger);
|
||||
|
|
Loading…
Reference in a new issue