aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2009-06-15 12:01:46 -0400
committerJean Delvare <khali@linux-fr.org>2009-06-15 12:01:46 -0400
commit66b650f04576a6737579ec404446450026ff2e0b (patch)
tree9653a442bfd01a97dd2a8c2e7930473d12623094 /drivers/i2c
parent1cf92b453a405f6e452737962933a19ec1582029 (diff)
i2c: Retry automatically on arbitration loss
Some small changes in i2c core to retry i2c xfers until either the maximum number of retries or the timeout is hit. Signed-off-by: Clifford Wolf <clifford@clifford.at> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/i2c-core.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index dfd7bc8094bf..635c488262c0 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1022,7 +1022,8 @@ module_exit(i2c_exit);
1022 */ 1022 */
1023int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 1023int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
1024{ 1024{
1025 int ret; 1025 unsigned long orig_jiffies;
1026 int ret, try;
1026 1027
1027 /* REVISIT the fault reporting model here is weak: 1028 /* REVISIT the fault reporting model here is weak:
1028 * 1029 *
@@ -1060,7 +1061,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
1060 mutex_lock_nested(&adap->bus_lock, adap->level); 1061 mutex_lock_nested(&adap->bus_lock, adap->level);
1061 } 1062 }
1062 1063
1063 ret = adap->algo->master_xfer(adap,msgs,num); 1064 /* Retry automatically on arbitration loss */
1065 orig_jiffies = jiffies;
1066 for (ret = 0, try = 0; try <= adap->retries; try++) {
1067 ret = adap->algo->master_xfer(adap, msgs, num);
1068 if (ret != -EAGAIN)
1069 break;
1070 if (time_after(jiffies, orig_jiffies + adap->timeout))
1071 break;
1072 }
1064 mutex_unlock(&adap->bus_lock); 1073 mutex_unlock(&adap->bus_lock);
1065 1074
1066 return ret; 1075 return ret;
@@ -1995,14 +2004,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
1995 char read_write, u8 command, int protocol, 2004 char read_write, u8 command, int protocol,
1996 union i2c_smbus_data *data) 2005 union i2c_smbus_data *data)
1997{ 2006{
2007 unsigned long orig_jiffies;
2008 int try;
1998 s32 res; 2009 s32 res;
1999 2010
2000 flags &= I2C_M_TEN | I2C_CLIENT_PEC; 2011 flags &= I2C_M_TEN | I2C_CLIENT_PEC;
2001 2012
2002 if (adapter->algo->smbus_xfer) { 2013 if (adapter->algo->smbus_xfer) {
2003 mutex_lock(&adapter->bus_lock); 2014 mutex_lock(&adapter->bus_lock);
2004 res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, 2015
2005 command, protocol, data); 2016 /* Retry automatically on arbitration loss */
2017 orig_jiffies = jiffies;
2018 for (res = 0, try = 0; try <= adapter->retries; try++) {
2019 res = adapter->algo->smbus_xfer(adapter, addr, flags,
2020 read_write, command,
2021 protocol, data);
2022 if (res != -EAGAIN)
2023 break;
2024 if (time_after(jiffies,
2025 orig_jiffies + adapter->timeout))
2026 break;
2027 }
2006 mutex_unlock(&adapter->bus_lock); 2028 mutex_unlock(&adapter->bus_lock);
2007 } else 2029 } else
2008 res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, 2030 res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,