Skip to content

Commit

Permalink
i2c: Retry automatically on arbitration loss
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Clifford Wolf authored and Jean Delvare committed Jun 15, 2009
1 parent 1cf92b4 commit 66b650f
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,8 @@ module_exit(i2c_exit);
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
int ret;
unsigned long orig_jiffies;
int ret, try;

/* REVISIT the fault reporting model here is weak:
*
Expand Down Expand Up @@ -1060,7 +1061,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
mutex_lock_nested(&adap->bus_lock, adap->level);
}

ret = adap->algo->master_xfer(adap,msgs,num);
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
mutex_unlock(&adap->bus_lock);

return ret;
Expand Down Expand Up @@ -1995,14 +2004,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int protocol,
union i2c_smbus_data *data)
{
unsigned long orig_jiffies;
int try;
s32 res;

flags &= I2C_M_TEN | I2C_CLIENT_PEC;

if (adapter->algo->smbus_xfer) {
mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command, protocol, data);

/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (res = 0, try = 0; try <= adapter->retries; try++) {
res = adapter->algo->smbus_xfer(adapter, addr, flags,
read_write, command,
protocol, data);
if (res != -EAGAIN)
break;
if (time_after(jiffies,
orig_jiffies + adapter->timeout))
break;
}
mutex_unlock(&adapter->bus_lock);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
Expand Down

0 comments on commit 66b650f

Please sign in to comment.