Re: [PATCH] i2c: imx: double check IIF in case interrupt lost

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

 



Hello,

On Thu, Aug 14, 2014 at 10:09:42AM +0000, fugang.duan@xxxxxxxxxxxxx wrote:
> From: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> Sent: Thursday, August 14, 2014 5:42 PM
> >On Thu, Aug 14, 2014 at 04:29:14PM +0800, Fugang Duan wrote:
> >> diff --git a/drivers/i2c/busses/i2c-imx.c
> >> b/drivers/i2c/busses/i2c-imx.c index aa8bc14..4b63771 100644
> >> --- a/drivers/i2c/busses/i2c-imx.c
> >> +++ b/drivers/i2c/busses/i2c-imx.c
> >> @@ -285,11 +285,17 @@ static int i2c_imx_bus_busy(struct
> >> imx_i2c_struct *i2c_imx, int for_busy)
> >>
> >>  static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)  {
> >> +	unsigned int temp;
> >> +
> >>  	wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ /
> >> 10);
> >>
> >>  	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
> >> -		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
> >> -		return -ETIMEDOUT;
> >> +		/* Double check IIF to avoid interrupt lost */
> >> +		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
> >> +		if (!(temp & I2SR_IIF)) {
> >> +			dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n",
> >__func__);
> >> +			return -ETIMEDOUT;
> >> +		}
> >This smells fishy. If possible the fix should be not to loose an interrupt.
> >Can you
> >
> >If I2SR_IIF is unset in i2c_imx->i2csr this means that
> >i2c_imx_trx_complete was already run before since the last irq triggered.
> >But if then imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) returns the IIF flag
> >set why doesn't the irq trigger? That would mean there is a hardware bug,
> >doesn't it? Is there a related Errata? Does it apply to all SoCs using
> >this driver? Did you check that the irq handling in the driver isn't racy?
> After we debug, it seems that irq lost in the stress case.
> Because we increase the timeout value to one "HZ" in wait_event_timeout(), and it 
> Return "0" means no interrupt. But when we read I2SR, IIF bit is set.
> There have no racy in the driver code, so we judge there have interrupt lost. 
> 
> After apply the patch, it really solve the issue.
I'm still not convinced. Either there is a hardware problem (then
Freescale should emit a proper errata for it when it's completely
understood) or there is a software problem and then your fix looks
wrong. Can you do the following please:

Make the code read:

	static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
	{
		wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);

		if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
			unsigned int temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
			if (!(temp & I2SR_IFF)) {
				dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
				return -ETIMEDOUT;
			} else {
				dev_info(&i2c_imx->adapter.dev, "<%s> Disable tracing\n", __func__);
				tracing_off();
			}
		}

		dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
		i2c_imx->i2csr = 0;
		return 0;
	}

Then compile a kernel with CONFIG_FUNCTION_TRACER=y and before repeating
your tests do:

	cd /sys/kernel/debug/tracing # assuming you have debugfs mounted accordingly
	echo function > current_tracer
	echo 1 > tracing_on

And once the "Disable tracing" message appears extract

	/sys/kernel/debug/tracing/trace

and send it to me.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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