V4L/DVB (4915): Saa7146: Add timeout protection for I2C interrupt
authorHartmut Birr <e9hack@googlemail.com>
Wed, 1 Nov 2006 16:01:42 +0000 (13:01 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 10 Dec 2006 11:05:34 +0000 (09:05 -0200)
Add a timeout to the wait for the i2c-interrupt.
The timeout prevents from endless waiting if the
interrupt gets lost.

Signed-off-by: Hartmut Birr <e9hack@googlemail.com>
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/common/saa7146_i2c.c

index 5297a365c928e2b8c8928c8f3edafc7324db1915..8c85efc26527fe9bf5bdd85473f014b568871876 100644 (file)
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                saa7146_write(dev, I2C_TRANSFER, *dword);
 
                dev->i2c_op = 1;
+               SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
                SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
 
-               wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
-               if (signal_pending (current)) {
-                       /* a signal arrived */
-                       return -ERESTARTSYS;
+               timeout = HZ/100 + 1; /* 10ms */
+               timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+               if (timeout == -ERESTARTSYS || dev->i2c_op) {
+                       SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+                       SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+                       if (timeout == -ERESTARTSYS)
+                               /* a signal arrived */
+                               return -ERESTARTSYS;
+
+                       printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
+                       return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
        } else {