Re: [PATCH] i2c: mv64xxx: Fix reading invalid status value in atomic mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, May 21, 2023 at 02:19:40PM +0200, Marek Behún wrote:
> There seems to be a bug within the mv64xxx I2C controller, wherein the
> status register may not necessarily contain valid value immediately
> after the IFLG flag is set in the control register.
> 
> My theory is that the controller:
> - first sets the IFLG in control register
> - then updates the status register
> - then raises an interrupt
> 
> This may sometime cause weird bugs when in atomic mode, since in this
> mode we do not wait for an interrupt, but instead we poll the control
> register for IFLG and read status register immediately after.
> 
> I encountered -ENXIO from mv64xxx_i2c_fsm() due to this issue when using
> this driver in atomic mode.
> 
> Note that I've only seen this issue on Armada 385, I don't know whether
> other SOCs with this controller are also affected. Also note that this
> fix has been in U-Boot for over 4 years [1] without anybody complaining,
> so it should not cause regressions.

I've never seen this bug before, but don't suspect it should cause any
issues for me. Thank you for finding/fixing this.

> 
> [1] https://source.denx.de/u-boot/u-boot/-/commit/d50e29662f78
> 
> Fixes: 544a8d75f3d6 ("i2c: mv64xxx: Add atomic_xfer method to driver")
> Signed-off-by: Marek Behún <kabel@xxxxxxxxxx>
> ---
>  drivers/i2c/busses/i2c-mv64xxx.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
> index 047dfef7a657..878c076ebdc6 100644
> --- a/drivers/i2c/busses/i2c-mv64xxx.c
> +++ b/drivers/i2c/busses/i2c-mv64xxx.c
> @@ -520,6 +520,17 @@ mv64xxx_i2c_intr(int irq, void *dev_id)
>  
>  	while (readl(drv_data->reg_base + drv_data->reg_offsets.control) &
>  						MV64XXX_I2C_REG_CONTROL_IFLG) {
> +		/*
> +		 * It seems that sometime the controller updates the status
> +		 * register only after it asserts IFLG in control register.
> +		 * This may result in weird bugs when in atomic mode. A delay
> +		 * of 100 ns before reading the status register solves this
> +		 * issue. This bug does not seem to appear when using
> +		 * interrupts.
> +		 */
> +		if (drv_data->atomic)
> +			ndelay(100);
> +
>  		status = readl(drv_data->reg_base + drv_data->reg_offsets.status);
>  		mv64xxx_i2c_fsm(drv_data, status);
>  		mv64xxx_i2c_do_action(drv_data);
> -- 
> 2.39.3
> 



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux