summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Poynor <toddpoynor@google.com>2012-10-04 15:09:52 -0700
committerColin Cross <ccross@android.com>2014-03-19 13:09:29 -0700
commitac875ecbf3e136f66085d32c4f9e64342483da65 (patch)
treea61f23b9ccf5417cc257ff12e769692a787c893a
parent6ccb8c7c29a067c2b29adc73ad8eb6962e90da14 (diff)
power: android-battery: Add state locking
Change-Id: I83abd61f0ee2541f5406258b2c07f76af7d2acb5 Signed-off-by: Todd Poynor <toddpoynor@google.com>
-rw-r--r--drivers/power/android_battery.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/power/android_battery.c b/drivers/power/android_battery.c
index 16db8cff5095..d6ff01adcd08 100644
--- a/drivers/power/android_battery.c
+++ b/drivers/power/android_battery.c
@@ -33,6 +33,7 @@
#include <linux/workqueue.h>
#include <linux/alarmtimer.h>
#include <linux/timer.h>
+#include <linux/mutex.h>
#include <linux/debugfs.h>
#include <linux/platform_data/android_battery.h>
@@ -93,6 +94,8 @@ static enum power_supply_property android_power_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
+static DEFINE_MUTEX(android_bat_state_lock);
+
static void android_bat_update_data(struct android_bat_data *battery);
static int android_bat_enable_charging(struct android_bat_data *battery,
bool enable);
@@ -226,6 +229,13 @@ static void android_bat_get_temp(struct android_bat_data *battery)
battery->batt_temp = batt_temp;
}
+/*
+ * android_bat_state_lock not held, may call back into
+ * android_bat_charge_source_changed. Gathering data here can be
+ * non-atomic; updating our state based on the data may need to be
+ * atomic.
+ */
+
static void android_bat_update_data(struct android_bat_data *battery)
{
int ret;
@@ -344,15 +354,17 @@ static void android_bat_charging_timer(struct android_bat_data *battery)
static void android_bat_charge_source_changed(struct android_bat_callbacks *ptr,
int charge_source)
{
- struct android_bat_data *battery;
+ struct android_bat_data *battery =
+ container_of(ptr, struct android_bat_data, callbacks);
- battery = container_of(ptr, struct android_bat_data, callbacks);
wake_lock(&battery->charger_wake_lock);
+ mutex_lock(&android_bat_state_lock);
battery->charge_source = charge_source;
pr_info("battery: charge source type was changed: %s\n",
charge_source_str(battery->charge_source));
+ mutex_unlock(&android_bat_state_lock);
queue_work(battery->monitor_wqueue, &battery->charger_work);
}
@@ -361,10 +373,12 @@ static void android_bat_set_full_status(struct android_bat_callbacks *ptr)
struct android_bat_data *battery =
container_of(ptr, struct android_bat_data, callbacks);
+ mutex_lock(&android_bat_state_lock);
pr_info("battery: battery full\n");
battery->charging_status = POWER_SUPPLY_STATUS_FULL;
android_bat_enable_charging(battery, false);
battery->recharging = false;
+ mutex_unlock(&android_bat_state_lock);
power_supply_changed(&battery->psy_bat);
}
@@ -373,6 +387,8 @@ static void android_bat_charger_work(struct work_struct *work)
struct android_bat_data *battery =
container_of(work, struct android_bat_data, charger_work);
+ mutex_lock(&android_bat_state_lock);
+
switch (battery->charge_source) {
case CHARGE_SOURCE_NONE:
battery->charging_status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -391,10 +407,10 @@ static void android_bat_charger_work(struct work_struct *work)
break;
}
+ mutex_unlock(&android_bat_state_lock);
+ wake_lock_timeout(&battery->charger_wake_lock, HZ * 2);
power_supply_changed(&battery->psy_ac);
power_supply_changed(&battery->psy_usb);
-
- wake_lock_timeout(&battery->charger_wake_lock, HZ * 2);
}
@@ -413,6 +429,7 @@ static void android_bat_monitor_work(struct work_struct *work)
wake_lock(&battery->monitor_wake_lock);
android_bat_update_data(battery);
+ mutex_lock(&android_bat_state_lock);
switch (battery->charging_status) {
case POWER_SUPPLY_STATUS_FULL:
@@ -474,6 +491,7 @@ static void android_bat_monitor_work(struct work_struct *work)
battery->charging_start_time ?
cur_time.tv_sec - battery->charging_start_time : 0,
charge_source_str(battery->charge_source));
+ mutex_unlock(&android_bat_state_lock);
power_supply_changed(&battery->psy_bat);
battery->last_poll = ktime_get_boottime();
android_bat_monitor_set_alarm(battery, FAST_POLL);
@@ -499,6 +517,7 @@ static int android_power_debug_dump(struct seq_file *s, void *unused)
android_bat_update_data(battery);
get_monotonic_boottime(&cur_time);
+ mutex_lock(&android_bat_state_lock);
seq_printf(s, "l=%d v=%d c=%d temp=%s%ld.%ld h=%d st=%d%s ct=%lu type=%s\n",
battery->batt_soc, battery->batt_vcell/1000,
battery->batt_current, battery->batt_temp < 0 ? "-" : "",
@@ -508,7 +527,7 @@ static int android_power_debug_dump(struct seq_file *s, void *unused)
battery->charging_start_time ?
cur_time.tv_sec - battery->charging_start_time : 0,
charge_source_str(battery->charge_source));
-
+ mutex_unlock(&android_bat_state_lock);
return 0;
}