Re: saa7146_i2c_writeout: timed out waiting for end of xfer

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

 



Oliver Endriss wrote:
> 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.

Attached is an updated patch which does extended status checking.

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 06:49:46 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;
 }
 
diff -r 0f9dfb292f40 linux/drivers/media/common/saa7146_i2c.c
--- a/linux/drivers/media/common/saa7146_i2c.c	Tue Jul 17 02:27:12 2007 +0200
+++ b/linux/drivers/media/common/saa7146_i2c.c	Tue Jul 17 06:49:46 2007 +0200
@@ -247,8 +247,16 @@ static int saa7146_i2c_writeout(struct s
 	}
 
 	/* give a detailed status report */
-	if ( 0 != (status & SAA7146_I2C_ERR)) {
-
+	if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
+			     SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
+			     SAA7146_I2C_AL    | SAA7146_I2C_ERR   |
+			     SAA7146_I2C_BUSY)) ) {
+
+		if ( 0 == (status & SAA7146_I2C_ERR) ||
+		     0 == (status & SAA7146_I2C_BUSY) ) {
+			printk(KERN_WARNING "%s: unexpected i2c status %04x\n",
+			       __FUNCTION__, status);
+		}
 		if( 0 != (status & SAA7146_I2C_SPERR) ) {
 			DEB_I2C(("error due to invalid start/stop condition.\n"));
 		}
_______________________________________________
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