Hello,

On Thu, Aug 14, 2014 at 10:09:42AM +0000, [email protected] wrote:
> From: Uwe Kleine-König <[email protected]> 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to