diff options
author | Clifford Wolf <clifford@clifford.at> | 2009-06-15 12:01:46 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-06-15 12:01:46 -0400 |
commit | 66b650f04576a6737579ec404446450026ff2e0b (patch) | |
tree | 9653a442bfd01a97dd2a8c2e7930473d12623094 /drivers/i2c/i2c-core.c | |
parent | 1cf92b453a405f6e452737962933a19ec1582029 (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/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 30 |
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 | */ |
1023 | int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | 1023 | int 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, |