Re: saa7146_i2c_writeout: timed out waiting for end of xfer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



e9hack wrote:
> Manfred Petz wrote:
> > actually, both patches help. no more timeouts, and the frontend drivers
> > get loaded correctly (tried each patch separately). tried with latest hg
> > & 2.6.22.
> 
> I don't understand why both patches do solve the timeout problem. The message 'timed out waiting for
> end of xfer' means, that no i2c-interrupt was delivered. In this case, the return value of
> saa7146_i2c_writeout() is -EIO. The first patch has only an effect, if the return value is
> -EREMOTEIO. The second patch reduces the i2c bit-rate. Usually, it has nothing to do with the
> interrupts.

A lower i2c bit rate might have changed the timing.

> Independently of this, I've found some strange things. The drivers for the TT-C2300 and the Cinergy
> DVB-C cards probe some i2c devices which don't exist. This results in an address error (missing ACK
> after the device address). I see three interrupts for this error. The first sets I2C_BUSY and
> I2C_APERR within I2C_STATUS. It does not wake-up the waiting thread and may print the message
> 'unhandled irq: i2c'. The second interrupt is the normal error interrupt which does wake-up the
> thread. I2C_BUSSY, I2C_ERR and I2C_APERR are set. The third interrupt has set the same three status
> bits. It may print the message 'unexpected irq: i2c', because the thread was already wake-up. If the
> chip-set is only able to deliver the first interrupt, the error interrupt will be never delivered
> and the timeout occurs.

Imho the interrupt processing was broken:
- The first I2C interrupt should be used to wake-up the task.
  It does not matter that it takes some time until ERR in IIC_STA
  will be updated. We don't need it.
- Interrupts must be acknowledged at the end of the ISR.

@all
Please test the attached patch.
There shouldn't be any unexpected I2C interrupts anymore.

CU
Oliver

-- 
----------------------------------------------------------------
VDR Remote Plugin 0.3.9: http://www.escape-edv.de/endriss/vdr/
----------------------------------------------------------------
diff -r 0f9dfb292f40 linux/drivers/media/common/saa7146_core.c
--- a/linux/drivers/media/common/saa7146_core.c	Tue Jul 17 02:27:12 2007 +0200
+++ b/linux/drivers/media/common/saa7146_core.c	Tue Jul 17 04:17:36 2007 +0200
@@ -252,18 +252,17 @@ static irqreturn_t interrupt_hw(int irq,
 #endif
 {
 	struct saa7146_dev *dev = dev_id;
-	u32 isr = 0;
+	u32 isr;
+	u32 ack_isr;
 
 	/* read out the interrupt status register */
-	isr = saa7146_read(dev, ISR);
+	ack_isr = isr = saa7146_read(dev, ISR);
 
 	/* is this our interrupt? */
 	if ( 0 == isr ) {
 		/* nope, some other device */
 		return IRQ_NONE;
 	}
-
-	saa7146_write(dev, ISR, isr);
 
 	if( 0 != (dev->ext)) {
 		if( 0 != (dev->ext->irq_mask & isr )) {
@@ -287,21 +286,16 @@ static irqreturn_t interrupt_hw(int irq,
 		isr &= ~MASK_28;
 	}
 	if (0 != (isr & (MASK_16|MASK_17))) {
-		u32 status = saa7146_read(dev, I2C_STATUS);
-		if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
-			SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
-			/* only wake up if we expect something */
-			if( 0 != dev->i2c_op ) {
-				u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2;
-				u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f;
-				DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr));
-				dev->i2c_op = 0;
-				wake_up(&dev->i2c_wq);
-			} else {
-				DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
-			}
+		SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+		/* only wake up if we expect something */
+		if( 0 != dev->i2c_op ) {
+			dev->i2c_op = 0;
+			wake_up(&dev->i2c_wq);
 		} else {
-			DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
+			u32 psr = saa7146_read(dev, PSR);
+			u32 ssr = saa7146_read(dev, SSR);
+			printk(KERN_WARNING "saa7146: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+			       isr, psr, ssr);
 		}
 		isr &= ~(MASK_16|MASK_17);
 	}
@@ -310,6 +304,7 @@ static irqreturn_t interrupt_hw(int irq,
 		ERR(("disabling interrupt source(s)!\n"));
 		SAA7146_IER_DISABLE(dev,isr);
 	}
+	saa7146_write(dev, ISR, ack_isr);
 	return IRQ_HANDLED;
 }
 
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux