omap: i2c: add a timeout to the busy waiting
authorAlexander Shishkin <virtuoso@slind.org>
Tue, 11 May 2010 18:35:17 +0000 (11:35 -0700)
committerBen Dooks <ben-linux@fluff.org>
Wed, 19 May 2010 23:18:59 +0000 (00:18 +0100)
The errata 1.153 workaround is busy waiting on XUDF bit in interrupt
context, which may lead to kernel hangs. The problem can be reproduced
by running the bus with wrong (too high) speed.

Signed-off-by: Alexander Shishkin <virtuoso@slind.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
drivers/i2c/busses/i2c-omap.c

index ef73483efb846d158509a2fe1a5b4fb7fd066d07..00fd02ec1b650068b798af880e85dd97de1e2851 100644 (file)
@@ -763,17 +763,25 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
  */
 static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err)
 {
-       while (!(*stat & OMAP_I2C_STAT_XUDF)) {
+       unsigned long timeout = 10000;
+
+       while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) {
                if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
                        omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
                                                        OMAP_I2C_STAT_XDR));
                        *err |= OMAP_I2C_STAT_XUDF;
                        return -ETIMEDOUT;
                }
+
                cpu_relax();
                *stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
        }
 
+       if (!timeout) {
+               dev_err(dev->dev, "timeout waiting on XUDF bit\n");
+               return 0;
+       }
+
        return 0;
 }