i2c: octeon: thunderx: Recovery fixes and improvements
Subsystems (2)
v2 cover i2c: octeon: thunderx: Recovery fixes and improvements
Hi Wolfram,
here are the remaining two patches with iopoll.h usage and a timed wait before entering the recovery on a failed bus check.
thanks,
Jan
---------------------
Jan Glauber (2):
i2c: octeon: thunderx: Check bus state before starting a transaction
i2c: octeon: thunderx: Limit register access retries
drivers/i2c/busses/i2c-octeon-core.c | 33 ++++++++++++++++++++++++++++++++- drivers/i2c/busses/i2c-octeon-core.h | 27 ++++++++++++++++----------- 2 files changed, 48 insertions(+), 12 deletions(-)
Signature · 1 line
1.9.1
PATCH v2 1/2 i2c: octeon: thunderx: Check bus state before starting a transaction
Add an additional status check before starting a transaction. If the check fails wait for some time to tolerate multi-master mode. After the timeout expires trigger the recovery.
--- drivers/i2c/busses/i2c-octeon-core.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
drivers/i2c/busses/i2c-octeon-core.c +29 -0
@@ -630,6 +630,31 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgreturn ret; } +static int octeon_i2c_check_bus (struct octeon_i2c *i2c) +{ +u64 end =get_jiffies_64 () + i2c->adap.timeout; +int stat, lines; + +while (time_before64 (get_jiffies_64 (), end)) { + stat =octeon_i2c_stat_read (i2c); + +/* get I2C line state */ + lines =octeon_i2c_read_int (i2c) & (TWSI_INT_SCL |TWSI_INT_SDA ); + +if (stat ==STAT_IDLE && lines == (TWSI_INT_SCL |TWSI_INT_SDA )) +return 0 ; + +if (stat ==STAT_LOST_ARB_38 || stat ==STAT_LOST_ARB_68 || + stat ==STAT_LOST_ARB_78 || stat ==STAT_LOST_ARB_B0 ) +break ; + +usleep_range (I2C_OCTEON_EVENT_WAIT /2 ,I2C_OCTEON_EVENT_WAIT ); + } + +/* bus check failed, try to recover */ +return octeon_i2c_recovery (i2c); +} +/** * octeon_i2c_xfer - The driver's master_xfer function * @adap: Pointer to the i2c_adapter structure
@@ -643,6 +668,10 @@ int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)struct octeon_i2c *i2c =i2c_get_adapdata (adap);int i, ret =0 ; + ret =octeon_i2c_check_bus (i2c); +if (ret) + goto out; +if (num ==1 ) {if (msgs[0 ].len >0 && msgs[0 ].len <=8 ) {if (msgs[0 ].flags &I2C_M_RD )
Signature · 1 line
1.9.1
Re: [PATCH v2 1/2] i2c: octeon: thunderx: Check bus state before starting a transaction
Quoted 5 lines · Jan Glauber
Add an additional status check before starting a transaction. If the check fails wait for some time to tolerate multi-master mode. After the timeout expires trigger the recovery.
Signed-off-by Jan Glauber <[email protected]>
Need to think more about it, needs to wait for next cycle.
Re: [PATCH v2 1/2] i2c: octeon: thunderx: Check bus state before starting a transaction
Quoted 9 lines · Wolfram Sang
Quoted 5 lines · Jan Glauber
Add an additional status check before starting a transaction. If the check fails wait for some time to tolerate multi-master mode. After the timeout expires trigger the recovery.
Signed-off-by Jan Glauber <[email protected]>Need to think more about it, needs to wait for next cycle.
OK, please share your thoughts when you get to it.
--Jan
PATCH v2 2/2 i2c: octeon: thunderx: Limit register access retries
In reply to Jan GlauberDo not infinitely retry register readq and writeq operations in order to not lock up the CPU in case the TWSI gets stuck.
Return -ETIMEDOUT in case of a failed data read. For all other cases just return so subsequent operations will fail and trigger the recovery.
--- drivers/i2c/busses/i2c-octeon-core.c | 4 +++- drivers/i2c/busses/i2c-octeon-core.h | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-)
drivers/i2c/busses/i2c-octeon-core.c +3 -1
@@ -381,7 +381,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,if (result)return result; - data[i] =octeon_i2c_data_read (i2c); + data[i] =octeon_i2c_data_read (i2c, &result); +if (result) +return result;if (recv_len && i ==0 ) {if (data[i] >I2C_SMBUS_BLOCK_MAX +1 )return -EPROTO ;
drivers/i2c/busses/i2c-octeon-core.h +16 -11
@@ -5,6 +5,7 @@#include <linux/i2c.h> #include <linux/i2c-smbus.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/pci.h>
@@ -144,9 +145,9 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8u64 tmp;__raw_writeq (SW_TWSI_V | eop_reg | data, i2c->twsi_base +SW_TWSI (i2c)); -do { - tmp =__raw_readq (i2c->twsi_base +SW_TWSI (i2c)); - }while ((tmp &SW_TWSI_V ) !=0 ); + +readq_poll_timeout (i2c->twsi_base +SW_TWSI (i2c), tmp, tmp &SW_TWSI_V , +I2C_OCTEON_EVENT_WAIT , i2c->adap.timeout); }#define octeon_i2c_ctl_write (i2c, val) \
@@ -163,24 +164,28 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8* * The I2C core registers are accessed indirectly via the SW_TWSI CSR. */ -static inline u8 octeon_i2c_reg_read (struct octeon_i2c *i2c,u64 eop_reg) +static inline int octeon_i2c_reg_read (struct octeon_i2c *i2c,u64 eop_reg, +int *error) {u64 tmp; +int ret;__raw_writeq (SW_TWSI_V | eop_reg |SW_TWSI_R , i2c->twsi_base +SW_TWSI (i2c)); -do { - tmp =__raw_readq (i2c->twsi_base +SW_TWSI (i2c)); - }while ((tmp &SW_TWSI_V ) !=0 ); + ret =readq_poll_timeout (i2c->twsi_base +SW_TWSI (i2c), tmp, + tmp &SW_TWSI_V ,I2C_OCTEON_EVENT_WAIT , + i2c->adap.timeout); +if (error) + *error = ret;return tmp &0xFF ; }#define octeon_i2c_ctl_read (i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) -#define octeon_i2c_data_read (i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL) +#define octeon_i2c_data_read (i2c, error) \ + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)#define octeon_i2c_stat_read (i2c) \ - octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT) + octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)/** * octeon_i2c_read_int - read the TWSI_INT register
Signature · 1 line
1.9.1
Re: [PATCH v2 2/2] i2c: octeon: thunderx: Limit register access retries
Quoted 8 lines · Jan Glauber
Do not infinitely retry register readq and writeq operations in order to not lock up the CPU in case the TWSI gets stuck.
Return
-ETIMEDOUTin case of a failed data read. For all other cases just return so subsequent operations will fail and trigger the recovery.Signed-off-by Jan Glauber <[email protected]>
Deleted the last 4 words from commit message (previous recovery patch needs more discussion) and applied to for-next, thanks!