Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Oliver Endriss and committed by
Mauro Carvalho Chehab
276e49a0 c471b331

+28 -22
+13 -18
drivers/media/common/saa7146_core.c
··· 248 248 static irqreturn_t interrupt_hw(int irq, void *dev_id) 249 249 { 250 250 struct saa7146_dev *dev = dev_id; 251 - u32 isr = 0; 251 + u32 isr; 252 + u32 ack_isr; 252 253 253 254 /* read out the interrupt status register */ 254 - isr = saa7146_read(dev, ISR); 255 + ack_isr = isr = saa7146_read(dev, ISR); 255 256 256 257 /* is this our interrupt? */ 257 258 if ( 0 == isr ) { 258 259 /* nope, some other device */ 259 260 return IRQ_NONE; 260 261 } 261 - 262 - saa7146_write(dev, ISR, isr); 263 262 264 263 if( 0 != (dev->ext)) { 265 264 if( 0 != (dev->ext->irq_mask & isr )) { ··· 282 283 isr &= ~MASK_28; 283 284 } 284 285 if (0 != (isr & (MASK_16|MASK_17))) { 285 - u32 status = saa7146_read(dev, I2C_STATUS); 286 - if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { 287 - SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); 288 - /* only wake up if we expect something */ 289 - if( 0 != dev->i2c_op ) { 290 - u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; 291 - u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f; 292 - DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr)); 293 - dev->i2c_op = 0; 294 - wake_up(&dev->i2c_wq); 295 - } else { 296 - DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); 297 - } 286 + SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); 287 + /* only wake up if we expect something */ 288 + if (0 != dev->i2c_op) { 289 + dev->i2c_op = 0; 290 + wake_up(&dev->i2c_wq); 298 291 } else { 299 - DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); 292 + u32 psr = saa7146_read(dev, PSR); 293 + u32 ssr = saa7146_read(dev, SSR); 294 + printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n", 295 + dev->name, isr, psr, ssr); 300 296 } 301 297 isr &= ~(MASK_16|MASK_17); 302 298 } ··· 300 306 ERR(("disabling interrupt source(s)!\n")); 301 307 SAA7146_IER_DISABLE(dev,isr); 302 308 } 309 + saa7146_write(dev, ISR, ack_isr); 303 310 return IRQ_HANDLED; 304 311 } 305 312
+15 -4
drivers/media/common/saa7146_i2c.c
··· 202 202 /* a signal arrived */ 203 203 return -ERESTARTSYS; 204 204 205 - printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); 205 + printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n", 206 + dev->name, __FUNCTION__); 206 207 return -EIO; 207 208 } 208 209 status = saa7146_read(dev, I2C_STATUS); ··· 220 219 break; 221 220 } 222 221 if (time_after(jiffies,timeout)) { 223 - printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n"); 222 + printk(KERN_WARNING "%s %s: timed out waiting for MC2\n", 223 + dev->name, __FUNCTION__); 224 224 return -EIO; 225 225 } 226 226 } ··· 237 235 /* this is normal when probing the bus 238 236 * (no answer from nonexisistant device...) 239 237 */ 240 - DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); 238 + printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n", 239 + dev->name, __FUNCTION__); 241 240 return -EIO; 242 241 } 243 242 if (++trial < 50 && short_delay) ··· 249 246 } 250 247 251 248 /* give a detailed status report */ 252 - if ( 0 != (status & SAA7146_I2C_ERR)) { 249 + if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR | 250 + SAA7146_I2C_DTERR | SAA7146_I2C_DRERR | 251 + SAA7146_I2C_AL | SAA7146_I2C_ERR | 252 + SAA7146_I2C_BUSY)) ) { 253 253 254 + if ( 0 == (status & SAA7146_I2C_ERR) || 255 + 0 == (status & SAA7146_I2C_BUSY) ) { 256 + /* it may take some time until ERR goes high - ignore */ 257 + DEB_I2C(("unexpected i2c status %04x\n", status)); 258 + } 254 259 if( 0 != (status & SAA7146_I2C_SPERR) ) { 255 260 DEB_I2C(("error due to invalid start/stop condition.\n")); 256 261 }