summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnshul Jain <anshulj@nvidia.com>2013-10-15 22:01:40 -0700
committerMandar Padmawar <mpadmawar@nvidia.com>2013-10-17 00:52:02 -0700
commit4de3651f005b9102cdbcc316f4301daa88cb1b9c (patch)
treeed6d5e022562a7746d90e8155a68cf07847da520
parent393b442196ed680a43b7ae2b8ac5f828690eb454 (diff)
misc: nct1008: Suspend Lock
Suspend lock is required to serialize suspend/resume, get_temp from thermal framework and work queue. Bug 1388303 Change-Id: Ib3e8873e3d2560aacd74ba02c726ec9fdc73e660 Signed-off-by: Anshul Jain <anshulj@nvidia.com> Reviewed-on: http://git-master/r/299754 Reviewed-by: Sang-Hun Lee <sanlee@nvidia.com>
-rw-r--r--drivers/misc/nct1008.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
index e6aa33d9a9ff..8bebf2f7c4d0 100644
--- a/drivers/misc/nct1008.c
+++ b/drivers/misc/nct1008.c
@@ -87,6 +87,7 @@ struct nct1008_data {
struct i2c_client *client;
struct nct1008_platform_data plat_data;
struct mutex mutex;
+ struct mutex suspend_mutex;
struct dentry *dent;
u8 config;
enum nct1008_chip chip;
@@ -530,15 +531,16 @@ static int nct1008_ext_get_temp(struct thermal_zone_device *thz,
long temp_ext_milli;
u8 value;
+ mutex_lock(&data->suspend_mutex);
/* Read External Temp */
value = nct1008_read_reg(client, EXT_TEMP_RD_LO);
if (value < 0)
- return -1;
+ goto read_error;
temp_ext_lo = (value >> 6);
value = nct1008_read_reg(client, EXT_TEMP_RD_HI);
if (value < 0)
- return -1;
+ goto read_error;
temp_ext_hi = value_to_temperature(pdata->ext_range, value);
temp_ext_milli = CELSIUS_TO_MILLICELSIUS(temp_ext_hi) +
@@ -546,7 +548,13 @@ static int nct1008_ext_get_temp(struct thermal_zone_device *thz,
*temp = temp_ext_milli;
data->etemp = temp_ext_milli;
+ mutex_unlock(&data->suspend_mutex);
return 0;
+
+read_error:
+ mutex_unlock(&data->suspend_mutex);
+ *temp = 0;
+ return -1;
}
static int nct1008_ext_bind(struct thermal_zone_device *thz,
@@ -665,16 +673,23 @@ static int nct1008_int_get_temp(struct thermal_zone_device *thz,
long temp_local_milli;
u8 value;
+ mutex_lock(&data->suspend_mutex);
/* Read Local Temp */
value = nct1008_read_reg(client, LOCAL_TEMP_RD);
if (value < 0)
- return -1;
+ goto read_error;
+
temp_local = value_to_temperature(pdata->ext_range, value);
temp_local_milli = CELSIUS_TO_MILLICELSIUS(temp_local);
*temp = temp_local_milli;
+ mutex_unlock(&data->suspend_mutex);
return 0;
+read_error:
+ *temp = 0;
+ mutex_unlock(&data->suspend_mutex);
+ return -1;
}
static int nct1008_int_bind(struct thermal_zone_device *thz,
@@ -1109,6 +1124,7 @@ static int __devinit nct1008_probe(struct i2c_client *client,
sizeof(struct nct1008_platform_data));
i2c_set_clientdata(client, data);
mutex_init(&data->mutex);
+ mutex_init(&data->suspend_mutex);
nct1008_power_control(data, true);
/* extended range recommended steps 1 through 4 taken care
@@ -1250,11 +1266,17 @@ static int nct1008_suspend(struct device *dev)
mutex_lock(&data->mutex);
data->stop_workqueue = 1;
mutex_unlock(&data->mutex);
+
cancel_work_sync(&data->work);
- disable_irq(client->irq);
+ /* Unlikely race: Interrupt could revive the
+ * work that could start
+ */
+ mutex_lock(&data->suspend_mutex);
+ disable_irq(client->irq);
err = nct1008_disable(client);
nct1008_power_control(data, false);
+ mutex_unlock(&data->suspend_mutex);
return err;
}
@@ -1264,20 +1286,22 @@ static int nct1008_resume(struct device *dev)
int err;
struct nct1008_data *data = i2c_get_clientdata(client);
+ mutex_lock(&data->suspend_mutex);
nct1008_power_control(data, true);
nct1008_configure_sensor(data);
err = nct1008_enable(client);
if (err < 0) {
+ mutex_unlock(&data->suspend_mutex);
dev_err(&client->dev, "Error: %s, error=%d\n",
__func__, err);
return err;
}
+ mutex_unlock(&data->suspend_mutex);
nct1008_update(data);
mutex_lock(&data->mutex);
data->stop_workqueue = 0;
mutex_unlock(&data->mutex);
enable_irq(client->irq);
-
return 0;
}