Oliver Endriss wrote: > e9hack wrote: > > >> 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; >> + } >> > > Please remove '{' and '}' - kernel coding style ;-) > The original code contains also this brackets. I removed it. > >> + /* this is normal when probing the bus >> + * (no answer from nonexisistant device...) >> + */ >> + DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); >> + return -EIO; >> > > Are you able to trigger this timeout? Is yes, how? > > Imho it cannot happen anymore (because of [1]) unless the hardware is > broken. Even with nonexistent devices there should be an I2C irq. > > Anyway, it is a good idea to add this timeout protection. > I didn't see such a timeout. > If it cannot happen under normal circumstances you should replace > DEB_I2C by printk. > I changed it. - Hartmut
Signed-off-by: Hartmut Birr <e9hack@xxxxxxxxxxxxxx> Add a timeout to the wait for the i2c-interrupt. The interrupt may never hit. The timeout prevents from endless waiting. diff -r 7b945ba585c3 linux/drivers/media/common/saa7146_i2c.c --- a/linux/drivers/media/common/saa7146_i2c.c Tue Oct 31 15:33:29 2006 -0300 +++ b/linux/drivers/media/common/saa7146_i2c.c Wed Nov 01 07:57:14 2006 +0100 @@ -190,13 +190,21 @@ static int saa7146_i2c_writeout(struct s 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 {
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb