@all users of saa7146-based cards (drivers: dvb-ttpci, budget, budget-ci, budget-av) Please test whether the attached patch has any negative effects. Two fixes for the 'saa7146_wait_for_debi_done' code: (a) Timeout did not work when the routine was called with interrupts disabled. (b) Reduce PCI I/O load caused by saa7146_wait_for_debi_done. Seems to be very important on fast machines! Based on a patch posted by e9hack@vdr-portal. If nobody complains I will commit this patch next week. CU Oliver -- ---------------------------------------------------------------- VDR Remote Plugin 0.4.0: http://www.escape-edv.de/endriss/vdr/ ----------------------------------------------------------------
diff -r 54b01562b12d linux/drivers/media/common/saa7146_core.c --- a/linux/drivers/media/common/saa7146_core.c Tue Oct 09 22:58:39 2007 +0200 +++ b/linux/drivers/media/common/saa7146_core.c Tue Oct 09 23:54:20 2007 +0200 @@ -59,41 +59,85 @@ void saa7146_setgpio(struct saa7146_dev } /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ -int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) -{ - unsigned long start; +static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, + unsigned long us1, unsigned long us2) +{ + unsigned long timeout; int err; /* wait for registers to be programmed */ - start = jiffies; + timeout = jiffies + usecs_to_jiffies(us1); while (1) { - err = time_after(jiffies, start + HZ/20); + err = time_after(jiffies, timeout); if (saa7146_read(dev, MC2) & 2) break; if (err) { - DEB_S(("timed out while waiting for registers getting programmed\n")); + printk(KERN_ERR "%s: %s timed out while waiting for registers getting programmed\n", + dev->name, __FUNCTION__); return -ETIMEDOUT; } - if (nobusyloop) - msleep(1); + msleep(1); } /* wait for transfer to complete */ - start = jiffies; + timeout = jiffies + usecs_to_jiffies(us2); while (1) { - err = time_after(jiffies, start + HZ/4); + err = time_after(jiffies, timeout); if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) break; saa7146_read(dev, MC2); if (err) { - DEB_S(("timed out while waiting for transfer completion\n")); + printk(KERN_ERR "%s: %s timed out while waiting for transfer completion\n", + dev->name, __FUNCTION__); return -ETIMEDOUT; } - if (nobusyloop) - msleep(1); + msleep(1); } return 0; +} + +static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev, + unsigned long us1, unsigned long us2) +{ + unsigned long loops; + + /* wait for registers to be programmed */ + loops = us1; + while (1) { + if (saa7146_read(dev, MC2) & 2) + break; + if (!loops--) { + printk(KERN_ERR "%s: %s timed out while waiting for registers getting programmed\n", + dev->name, __FUNCTION__); + return -ETIMEDOUT; + } + udelay(1); + } + + /* wait for transfer to complete */ + loops = us2 / 5; + while (1) { + if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) + break; + saa7146_read(dev, MC2); + if (!loops--) { + printk(KERN_ERR "%s: %s timed out while waiting for transfer completion\n", + dev->name, __FUNCTION__); + return -ETIMEDOUT; + } + udelay(5); + } + + return 0; +} + +int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) +{ + if (nobusyloop) + return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000); + else + return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000); } /****************************************************************************
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb