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