Commit 276e49a0 authored by Oliver Endriss's avatar Oliver Endriss Committed by Mauro Carvalho Chehab

V4L/DVB (5987): saa7146: clean-up irq processing

Interrupt processing fixed: First handle interrupt, then acknowledge it.
Otherwise the same interrupt might occur twice.
Cleaned-up i2c interrupt handler and i2c error messages.
Signed-off-by: default avatarOliver Endriss <o.endriss@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent c471b331
...@@ -248,10 +248,11 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt ...@@ -248,10 +248,11 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
static irqreturn_t interrupt_hw(int irq, void *dev_id) static irqreturn_t interrupt_hw(int irq, void *dev_id)
{ {
struct saa7146_dev *dev = dev_id; struct saa7146_dev *dev = dev_id;
u32 isr = 0; u32 isr;
u32 ack_isr;
/* read out the interrupt status register */ /* read out the interrupt status register */
isr = saa7146_read(dev, ISR); ack_isr = isr = saa7146_read(dev, ISR);
/* is this our interrupt? */ /* is this our interrupt? */
if ( 0 == isr ) { if ( 0 == isr ) {
...@@ -259,8 +260,6 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) ...@@ -259,8 +260,6 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
} }
saa7146_write(dev, ISR, isr);
if( 0 != (dev->ext)) { if( 0 != (dev->ext)) {
if( 0 != (dev->ext->irq_mask & isr )) { if( 0 != (dev->ext->irq_mask & isr )) {
if( 0 != dev->ext->irq_func ) { if( 0 != dev->ext->irq_func ) {
...@@ -283,21 +282,16 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) ...@@ -283,21 +282,16 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
isr &= ~MASK_28; isr &= ~MASK_28;
} }
if (0 != (isr & (MASK_16|MASK_17))) { 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); SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
/* only wake up if we expect something */ /* only wake up if we expect something */
if( 0 != dev->i2c_op ) { 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; dev->i2c_op = 0;
wake_up(&dev->i2c_wq); wake_up(&dev->i2c_wq);
} else { } else {
DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); u32 psr = saa7146_read(dev, PSR);
} u32 ssr = saa7146_read(dev, SSR);
} else { printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); dev->name, isr, psr, ssr);
} }
isr &= ~(MASK_16|MASK_17); isr &= ~(MASK_16|MASK_17);
} }
...@@ -306,6 +300,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id) ...@@ -306,6 +300,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
ERR(("disabling interrupt source(s)!\n")); ERR(("disabling interrupt source(s)!\n"));
SAA7146_IER_DISABLE(dev,isr); SAA7146_IER_DISABLE(dev,isr);
} }
saa7146_write(dev, ISR, ack_isr);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -202,7 +202,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d ...@@ -202,7 +202,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
/* a signal arrived */ /* a signal arrived */
return -ERESTARTSYS; return -ERESTARTSYS;
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
dev->name, __FUNCTION__);
return -EIO; return -EIO;
} }
status = saa7146_read(dev, I2C_STATUS); status = saa7146_read(dev, I2C_STATUS);
...@@ -219,7 +220,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d ...@@ -219,7 +220,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
break; break;
} }
if (time_after(jiffies,timeout)) { if (time_after(jiffies,timeout)) {
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n"); printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
dev->name, __FUNCTION__);
return -EIO; return -EIO;
} }
} }
...@@ -235,7 +237,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d ...@@ -235,7 +237,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
/* this is normal when probing the bus /* this is normal when probing the bus
* (no answer from nonexisistant device...) * (no answer from nonexisistant device...)
*/ */
DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
dev->name, __FUNCTION__);
return -EIO; return -EIO;
} }
if (++trial < 50 && short_delay) if (++trial < 50 && short_delay)
...@@ -246,8 +249,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d ...@@ -246,8 +249,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
} }
/* give a detailed status report */ /* 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) ) {
/* it may take some time until ERR goes high - ignore */
DEB_I2C(("unexpected i2c status %04x\n", status));
}
if( 0 != (status & SAA7146_I2C_SPERR) ) { if( 0 != (status & SAA7146_I2C_SPERR) ) {
DEB_I2C(("error due to invalid start/stop condition.\n")); DEB_I2C(("error due to invalid start/stop condition.\n"));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment