summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaohui Tao <xtao@nvidia.com>2013-06-17 15:25:52 -0700
committerAnshul Jain (SW) <anshulj@nvidia.com>2013-06-20 14:43:02 -0700
commit146cfe48b97eb51e21a09dda006726c1e2fcfdf1 (patch)
tree1b300a7ccb72a4fe3406920badcfbb160407bae9
parentff0c1a62c460384427d7b12ec121044200c2317b (diff)
input: misc: inv: Add critical section protection for power on/off
Unbalanced irq_enable/disable will cause potential risk of the sensor data not being sent out. Add critical section and flag to prevent this situation. Change-Id: I4a8b3ebfd07b3e4901ad807c8052c38e3f23315e Signed-off-by: Xiaohui Tao <xtao@nvidia.com> Reviewed-on: http://git-master/r/239385 Reviewed-by: Sang-Hun Lee <sanlee@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Robert Collins <rcollins@nvidia.com> Reviewed-by: Anshul Jain (SW) <anshulj@nvidia.com>
-rw-r--r--drivers/input/misc/mpu/inv_gyro.c16
-rw-r--r--drivers/input/misc/mpu/inv_gyro.h4
2 files changed, 15 insertions, 5 deletions
diff --git a/drivers/input/misc/mpu/inv_gyro.c b/drivers/input/misc/mpu/inv_gyro.c
index d7cd0ea87ca4..c7fa3b65b214 100644
--- a/drivers/input/misc/mpu/inv_gyro.c
+++ b/drivers/input/misc/mpu/inv_gyro.c
@@ -229,16 +229,21 @@ static int set_power_itg(struct inv_gyro_state_s *st, unsigned char power_on)
int inv_set_power_state(struct inv_gyro_state_s *st, unsigned char power_on)
{
int ret;
- if (!power_on)
+ mutex_lock(&st->power_lock);
+ if (!power_on && st->trigger.irq && !st->irq_disabled) {
disable_irq(st->trigger.irq);
-
+ st->irq_disabled = true;
+ }
if (INV_MPU3050 == st->chip_type)
ret = set_power_mpu3050(st, power_on);
else
ret = set_power_itg(st, power_on);
- if (power_on)
+ if (power_on && st->trigger.irq && st->irq_disabled) {
enable_irq(st->trigger.irq);
+ st->irq_disabled = false;
+ }
+ mutex_unlock(&st->power_lock);
return ret;
}
@@ -2761,6 +2766,7 @@ static int inv_mod_probe(struct i2c_client *client,
goto out_no_free;
}
+ mutex_init(&st->power_lock);
inv_init_regulator(st, client);
/* Make state variables available to all _show and _store functions. */
@@ -2853,6 +2859,7 @@ out_free:
regulator_disable(st->inv_regulator.regulator_vlogic);
regulator_disable(st->inv_regulator.regulator_vdd);
}
+ mutex_destroy(&st->power_lock);
kfree(st);
out_no_free:
dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
@@ -2883,6 +2890,7 @@ static int inv_mod_remove(struct i2c_client *client)
regulator_disable(st->inv_regulator.regulator_vlogic);
regulator_disable(st->inv_regulator.regulator_vdd);
}
+ mutex_destroy(&st->power_lock);
kfree(st);
dev_info(&client->adapter->dev, "Gyro module removed.\n");
return 0;
@@ -2892,8 +2900,6 @@ static void inv_i2c_shutdown(struct i2c_client *client)
{
struct inv_gyro_state_s *st = i2c_get_clientdata(client);
- if (client->irq)
- disable_irq(client->irq);
set_inv_enable(st, 0);
inv_set_power_state(st, 0);
st->i2c_shutdown = true;
diff --git a/drivers/input/misc/mpu/inv_gyro.h b/drivers/input/misc/mpu/inv_gyro.h
index 8fca85f50dac..15c20dbd1eea 100644
--- a/drivers/input/misc/mpu/inv_gyro.h
+++ b/drivers/input/misc/mpu/inv_gyro.h
@@ -262,6 +262,8 @@ struct inv_mpu_slave;
* @early_suspend: struct for early suspend.
* @early_suspend_enable: sysfs interface to store current early_suspend.
* @inv_regulator_s: Regulator sturcture to store regulator.
+ * @power_lock: Mutex lock to secure critical section for power on/off
+ * @irq_disabled: Variable to check whether irq is disabled or not
*/
struct inv_gyro_state_s {
struct inv_chip_config_s chip_config;
@@ -296,6 +298,8 @@ struct inv_gyro_state_s {
long long last_isr_time;
struct inv_regulator_s inv_regulator;
bool i2c_shutdown;
+ struct mutex power_lock;
+ bool irq_disabled;
};
/* produces an unique identifier for each device based on the