diff options
author | Oliver Endriss <o.endriss@gmx.de> | 2007-10-31 04:39:48 +0100 |
---|---|---|
committer | Oliver Endriss <o.endriss@gmx.de> | 2007-10-31 04:39:48 +0100 |
commit | 287c6f597fa1eb5bb9ecbcd47c5c6bae7b004a3d (patch) | |
tree | 105dcbd9abe0f7d26b6dc86a4fbb0ace15ab3986 /linux/drivers/media | |
parent | 47c9bdaf6e07f0a4b5ccaec663d41aec4bf62e63 (diff) | |
download | mediapointer-dvb-s2-287c6f597fa1eb5bb9ecbcd47c5c6bae7b004a3d.tar.gz mediapointer-dvb-s2-287c6f597fa1eb5bb9ecbcd47c5c6bae7b004a3d.tar.bz2 |
saa7146: saa7146_wait_for_debi_done fixes
From: Oliver Endriss <o.endriss@gmx.de>
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 code posted by Hartmut Birr @vdr-portal.
Thanks-to: Hartmut Birr <e9hack@googlemail.com>
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index b986e9ef6..e4063a1e0 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -59,43 +59,89 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) } /* 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) +static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, + unsigned long us1, unsigned long us2) { - unsigned long start; + 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")); + DEB_S(("%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--) { + DEB_S(("%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); +} + /**************************************************************************** * general helper functions ****************************************************************************/ |