summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2014-03-26 15:29:12 +0530
committerRiham Haidar <rhaidar@nvidia.com>2014-05-06 10:50:24 -0700
commiteea661d31a429a88f0f1f259e8a2ed49bfb57146 (patch)
tree546cf64eb43021a0203d5db3e443c039d596ea14 /drivers/power
parent7195780d0b7150725084926a7febada7dcd77476 (diff)
power: lc709203: synchronize different context with locking
Synchronize the battery work queue, charger update and power supply get_status() context with mutex. Avoid register access after shutdown. Change-Id: Id18ef28eac512cb08eafec5cfed6f8d575de0bb5 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/387022 Reviewed-on: http://git-master/r/405642 GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/lc709203f_battery.c65
1 files changed, 38 insertions, 27 deletions
diff --git a/drivers/power/lc709203f_battery.c b/drivers/power/lc709203f_battery.c
index c7b43639e6e4..6149f99f2a37 100644
--- a/drivers/power/lc709203f_battery.c
+++ b/drivers/power/lc709203f_battery.c
@@ -84,6 +84,8 @@ struct lc709203f_chip {
/* battery capacity */
int capacity_level;
+ int temperature;
+
int lasttime_soc;
int lasttime_status;
int shutdown_complete;
@@ -95,38 +97,20 @@ static int lc709203f_read_word(struct i2c_client *client, u8 reg)
{
int ret;
- struct lc709203f_chip *chip = i2c_get_clientdata(client);
-
- mutex_lock(&chip->mutex);
- if (chip && chip->shutdown_complete) {
- mutex_unlock(&chip->mutex);
- return -ENODEV;
- }
-
ret = i2c_smbus_read_word_data(client, reg);
if (ret < 0)
dev_err(&client->dev, "err reading reg: 0x%x, %d\n", reg, ret);
-
- mutex_unlock(&chip->mutex);
return ret;
}
static int lc709203f_write_word(struct i2c_client *client, u8 reg, u16 value)
{
- struct lc709203f_chip *chip = i2c_get_clientdata(client);
int ret;
- mutex_lock(&chip->mutex);
- if (chip && chip->shutdown_complete) {
- mutex_unlock(&chip->mutex);
- return -ENODEV;
- }
-
ret = i2c_smbus_write_word_data(client, reg, value);
if (ret < 0)
dev_err(&client->dev, "err writing 0x%0x, %d\n" , reg, ret);
- mutex_unlock(&chip->mutex);
return ret;
}
@@ -166,6 +150,7 @@ static int lc709203f_update_soc_voltage(struct lc709203f_chip *chip)
}
return 0;
}
+
static void lc709203f_work(struct work_struct *work)
{
struct lc709203f_chip *chip;
@@ -174,6 +159,12 @@ static void lc709203f_work(struct work_struct *work)
chip = container_of(work, struct lc709203f_chip, work.work);
+ mutex_lock(&chip->mutex);
+ if (chip->shutdown_complete) {
+ mutex_unlock(&chip->mutex);
+ return;
+ }
+
lc709203f_update_soc_voltage(chip);
if (chip->soc != chip->lasttime_soc ||
@@ -185,13 +176,16 @@ static void lc709203f_work(struct work_struct *work)
if (chip->pdata->tz_name) {
val = battery_gauge_get_battery_temperature(chip->bg_dev,
&temperature);
- if (val < 0)
+ if (val < 0) {
dev_err(&chip->client->dev, "temp invalid\n");
- else
+ } else {
lc709203f_write_word(chip->client, LC709203F_TEMPERATURE
, temperature * 10 + 2732);
+ chip->temperature = temperature;
+ }
}
+ mutex_unlock(&chip->mutex);
schedule_delayed_work(&chip->work, LC709203F_DELAY);
}
@@ -199,11 +193,15 @@ static int lc709203f_get_temperature(struct lc709203f_chip *chip)
{
int val;
+ if (chip->shutdown_complete)
+ return chip->temperature;
+
val = lc709203f_read_word(chip->client, LC709203F_TEMPERATURE);
if (val < 0) {
dev_err(&chip->client->dev, "%s: err %d\n", __func__, val);
- return -EINVAL;
+ return val;
}
+ chip->temperature = val;
return val;
}
@@ -227,7 +225,9 @@ static int lc709203f_get_property(struct power_supply *psy,
struct lc709203f_chip, battery);
int temperature;
int curr_ma;
- int ret;
+ int ret = 0;
+
+ mutex_lock(&chip->mutex);
switch (psp) {
case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -276,9 +276,12 @@ static int lc709203f_get_property(struct power_supply *psy,
val->intval = curr_ma;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
}
- return 0;
+
+ mutex_unlock(&chip->mutex);
+ return ret;
}
static int lc709203f_update_battery_status(struct battery_gauge_dev *bg_dev,
@@ -286,6 +289,12 @@ static int lc709203f_update_battery_status(struct battery_gauge_dev *bg_dev,
{
struct lc709203f_chip *chip = battery_gauge_get_drvdata(bg_dev);
+ mutex_lock(&chip->mutex);
+ if (chip->shutdown_complete) {
+ mutex_unlock(&chip->mutex);
+ return 0;
+ }
+
if (status == BATTERY_CHARGING) {
chip->charge_complete = 0;
chip->status = POWER_SUPPLY_STATUS_CHARGING;
@@ -293,13 +302,15 @@ static int lc709203f_update_battery_status(struct battery_gauge_dev *bg_dev,
chip->charge_complete = 1;
chip->soc = LC709203F_BATTERY_FULL;
chip->status = POWER_SUPPLY_STATUS_FULL;
- power_supply_changed(&chip->battery);
- return 0;
+ goto done;
} else {
chip->status = POWER_SUPPLY_STATUS_DISCHARGING;
chip->charge_complete = 0;
}
chip->lasttime_status = chip->status;
+
+done:
+ mutex_unlock(&chip->mutex);
power_supply_changed(&chip->battery);
return 0;
}
@@ -625,11 +636,11 @@ static void lc709203f_shutdown(struct i2c_client *client)
{
struct lc709203f_chip *chip = i2c_get_clientdata(client);
- cancel_delayed_work_sync(&chip->work);
mutex_lock(&chip->mutex);
chip->shutdown_complete = 1;
mutex_unlock(&chip->mutex);
+ cancel_delayed_work_sync(&chip->work);
}
#ifdef CONFIG_PM_SLEEP