aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorMika Kuoppala <mika.kuoppala@nokia.com>2009-12-06 11:06:22 -0500
committerJean Delvare <khali@linux-fr.org>2009-12-06 11:06:22 -0500
commit194684e596af4bdaebb424166d94a8aa528edfda (patch)
tree1a6b0ede432e8c9fb4f7a1652deb71044ff9aa50 /drivers/i2c
parenta0c11cdd6a1975fd8d6d186f2e2865a82f3e9bbf (diff)
i2c: Prevent priority inversion on top of bus lock
Low priority thread holding the i2c bus mutex could block higher priority threads to access the bus resulting in unacceptable latencies. Change the mutex type to rt_mutex preventing priority inversion. Tested-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Mika Kuoppala <mika.kuoppala@nokia.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/Kconfig1
-rw-r--r--drivers/i2c/i2c-core.c12
2 files changed, 7 insertions, 6 deletions
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index d7ece131b4f4..8d8a00e5a30e 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -5,6 +5,7 @@
5menuconfig I2C 5menuconfig I2C
6 tristate "I2C support" 6 tristate "I2C support"
7 depends on HAS_IOMEM 7 depends on HAS_IOMEM
8 select RT_MUTEXES
8 ---help--- 9 ---help---
9 I2C (pronounce: I-square-C) is a slow serial bus protocol used in 10 I2C (pronounce: I-square-C) is a slow serial bus protocol used in
10 many micro controller applications and developed by Philips. SMBus, 11 many micro controller applications and developed by Philips. SMBus,
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 296504355142..d664b4a97a31 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -584,7 +584,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
584 goto out_list; 584 goto out_list;
585 } 585 }
586 586
587 mutex_init(&adap->bus_lock); 587 rt_mutex_init(&adap->bus_lock);
588 588
589 /* Set default timeout to 1 second if not already set */ 589 /* Set default timeout to 1 second if not already set */
590 if (adap->timeout == 0) 590 if (adap->timeout == 0)
@@ -1092,12 +1092,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
1092#endif 1092#endif
1093 1093
1094 if (in_atomic() || irqs_disabled()) { 1094 if (in_atomic() || irqs_disabled()) {
1095 ret = mutex_trylock(&adap->bus_lock); 1095 ret = rt_mutex_trylock(&adap->bus_lock);
1096 if (!ret) 1096 if (!ret)
1097 /* I2C activity is ongoing. */ 1097 /* I2C activity is ongoing. */
1098 return -EAGAIN; 1098 return -EAGAIN;
1099 } else { 1099 } else {
1100 mutex_lock_nested(&adap->bus_lock, adap->level); 1100 rt_mutex_lock(&adap->bus_lock);
1101 } 1101 }
1102 1102
1103 /* Retry automatically on arbitration loss */ 1103 /* Retry automatically on arbitration loss */
@@ -1109,7 +1109,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
1109 if (time_after(jiffies, orig_jiffies + adap->timeout)) 1109 if (time_after(jiffies, orig_jiffies + adap->timeout))
1110 break; 1110 break;
1111 } 1111 }
1112 mutex_unlock(&adap->bus_lock); 1112 rt_mutex_unlock(&adap->bus_lock);
1113 1113
1114 return ret; 1114 return ret;
1115 } else { 1115 } else {
@@ -1913,7 +1913,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
1913 flags &= I2C_M_TEN | I2C_CLIENT_PEC; 1913 flags &= I2C_M_TEN | I2C_CLIENT_PEC;
1914 1914
1915 if (adapter->algo->smbus_xfer) { 1915 if (adapter->algo->smbus_xfer) {
1916 mutex_lock(&adapter->bus_lock); 1916 rt_mutex_lock(&adapter->bus_lock);
1917 1917
1918 /* Retry automatically on arbitration loss */ 1918 /* Retry automatically on arbitration loss */
1919 orig_jiffies = jiffies; 1919 orig_jiffies = jiffies;
@@ -1927,7 +1927,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
1927 orig_jiffies + adapter->timeout)) 1927 orig_jiffies + adapter->timeout))
1928 break; 1928 break;
1929 } 1929 }
1930 mutex_unlock(&adapter->bus_lock); 1930 rt_mutex_unlock(&adapter->bus_lock);
1931 } else 1931 } else
1932 res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, 1932 res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
1933 command, protocol, data); 1933 command, protocol, data);