diff options
author | Mika Kuoppala <mika.kuoppala@nokia.com> | 2009-12-06 11:06:22 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-12-06 11:06:22 -0500 |
commit | 194684e596af4bdaebb424166d94a8aa528edfda (patch) | |
tree | 1a6b0ede432e8c9fb4f7a1652deb71044ff9aa50 /drivers/i2c | |
parent | a0c11cdd6a1975fd8d6d186f2e2865a82f3e9bbf (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 12 |
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 @@ | |||
5 | menuconfig I2C | 5 | menuconfig 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); |