Skip to content

Commit

Permalink
V4L/DVB (6495): saa7146: saa7146_wait_for_debi_done fixes
Browse files Browse the repository at this point in the history
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.


Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Oliver Endriss authored and Mauro Carvalho Chehab committed Nov 4, 2007
1 parent cb20630 commit 26ac14e
Showing 1 changed file with 58 additions and 12 deletions.
70 changes: 58 additions & 12 deletions drivers/media/common/saa7146_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
****************************************************************************/
Expand Down

0 comments on commit 26ac14e

Please sign in to comment.