summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2012-03-20 13:53:58 +0800
committerAndy Green <andy.green@linaro.org>2012-03-20 16:20:15 +0800
commit25566bc79e56cb70b47058f8d8f5a1a75fd7dd2e (patch)
tree0e8eeeb2bd312beaa5e4066071d73e12e191ae2d
parentbec19ca37dd6f42fd9a44a5f64f442864fc44095 (diff)
regulator palmas use the missing io_mutex stuff to protect nonatomic iotilt-3.3-omap5-eng-12
Palmas communications can get confused if multiple threads are wanting to do IO to it at the moment. Normally i2c layer would serialize it OK but in case of palmas_i2c_read_block(), the io is not atomic, it first sends dat and then performs a second transaction. This was seen to be occurring at boot when one thread is doing regulator_init_complete() which iterates all the regulator statuses calling palmas_i2c_read_block, and other things like mmc might want to set their regulator. Without any locking, the two actions can interrupt each other. This patch uses the already defined and inited but not used io_mutex member of palmas struct to protect palmas IO from itself. Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r--drivers/mfd/palmas.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 7263e1c931a..5ee15de9271 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -125,6 +125,8 @@ static int palmas_i2c_read_block(struct palmas *palmas, int ipblock, u8 reg,
u8 addr;
int ret;
+ mutex_lock(&palmas->io_mutex);
+
i2c = palmas->palmas_clients[(ipblock >> 8) - 1].client;
addr = (ipblock & 0xFF) + reg;
@@ -138,6 +140,8 @@ static int palmas_i2c_read_block(struct palmas *palmas, int ipblock, u8 reg,
/* Read the result */
ret = i2c_master_recv(i2c, dest, length);
+ mutex_unlock(&palmas->io_mutex);
+
if (ret < 0)
return ret;
else if (ret != length)
@@ -165,6 +169,8 @@ static int palmas_i2c_write_block(struct palmas *palmas, int ipblock, u8 reg,
return -EINVAL;
}
+ mutex_lock(&palmas->io_mutex);
+
i2c = palmas->palmas_clients[(ipblock >> 8) - 1].client;
addr = (ipblock & 0xFF) + reg;
@@ -173,6 +179,9 @@ static int palmas_i2c_write_block(struct palmas *palmas, int ipblock, u8 reg,
/* Write the Address */
ret = i2c_master_send(i2c, buffer, length + 1);
+
+ mutex_unlock(&palmas->io_mutex);
+
if (ret < 0)
return ret;
if (ret != (length + 1))