Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Clifford Wolf and committed by
Jean Delvare
66b650f0 1cf92b45

+26 -4
+26 -4
drivers/i2c/i2c-core.c
··· 1022 1022 */ 1023 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 1028 /* REVISIT the fault reporting model here is weak: 1028 1029 * ··· 1061 1060 mutex_lock_nested(&adap->bus_lock, adap->level); 1062 1061 } 1063 1062 1064 - ret = adap->algo->master_xfer(adap,msgs,num); 1063 + /* Retry automatically on arbitration loss */ 1064 + orig_jiffies = jiffies; 1065 + for (ret = 0, try = 0; try <= adap->retries; try++) { 1066 + ret = adap->algo->master_xfer(adap, msgs, num); 1067 + if (ret != -EAGAIN) 1068 + break; 1069 + if (time_after(jiffies, orig_jiffies + adap->timeout)) 1070 + break; 1071 + } 1065 1072 mutex_unlock(&adap->bus_lock); 1066 1073 1067 1074 return ret; ··· 2004 1995 char read_write, u8 command, int protocol, 2005 1996 union i2c_smbus_data *data) 2006 1997 { 1998 + unsigned long orig_jiffies; 1999 + int try; 2007 2000 s32 res; 2008 2001 2009 2002 flags &= I2C_M_TEN | I2C_CLIENT_PEC; 2010 2003 2011 2004 if (adapter->algo->smbus_xfer) { 2012 2005 mutex_lock(&adapter->bus_lock); 2013 - res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, 2014 - command, protocol, data); 2006 + 2007 + /* Retry automatically on arbitration loss */ 2008 + orig_jiffies = jiffies; 2009 + for (res = 0, try = 0; try <= adapter->retries; try++) { 2010 + res = adapter->algo->smbus_xfer(adapter, addr, flags, 2011 + read_write, command, 2012 + protocol, data); 2013 + if (res != -EAGAIN) 2014 + break; 2015 + if (time_after(jiffies, 2016 + orig_jiffies + adapter->timeout)) 2017 + break; 2018 + } 2015 2019 mutex_unlock(&adapter->bus_lock); 2016 2020 } else 2017 2021 res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,