[PATCH] dvb: ttpci: fix timeout handling to be save with PREEMPT

Timeout handling fixed, especially for preemtible kernels and/or high system
load.

Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Oliver Endriss 2005-07-07 17:58:28 -07:00 committed by Linus Torvalds
parent e161f817be
commit 25de192660
2 changed files with 56 additions and 27 deletions

View File

@ -62,13 +62,15 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
{ {
unsigned long start; unsigned long start;
int err;
/* wait for registers to be programmed */ /* wait for registers to be programmed */
start = jiffies; start = jiffies;
while (1) { while (1) {
if (saa7146_read(dev, MC2) & 2) err = time_after(jiffies, start + HZ/20);
break; if (saa7146_read(dev, MC2) & 2)
if (time_after(jiffies, start + HZ/20)) { break;
if (err) {
DEB_S(("timed out while waiting for registers getting programmed\n")); DEB_S(("timed out while waiting for registers getting programmed\n"));
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -79,10 +81,11 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
/* wait for transfer to complete */ /* wait for transfer to complete */
start = jiffies; start = jiffies;
while (1) { while (1) {
err = time_after(jiffies, start + HZ/4);
if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
break; break;
saa7146_read(dev, MC2); saa7146_read(dev, MC2);
if (time_after(jiffies, start + HZ/4)) { if (err) {
DEB_S(("timed out while waiting for transfer completion\n")); DEB_S(("timed out while waiting for transfer completion\n"));
return -ETIMEDOUT; return -ETIMEDOUT;
} }

View File

@ -308,6 +308,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
{ {
unsigned long start; unsigned long start;
u32 stat; u32 stat;
int err;
if (FW_VERSION(av7110->arm_app) <= 0x261c) { if (FW_VERSION(av7110->arm_app) <= 0x261c) {
/* not supported by old firmware */ /* not supported by old firmware */
@ -318,14 +319,14 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
/* new firmware */ /* new firmware */
start = jiffies; start = jiffies;
for (;;) { for (;;) {
err = time_after(jiffies, start + ARM_WAIT_FREE);
if (down_interruptible(&av7110->dcomlock)) if (down_interruptible(&av7110->dcomlock))
return -ERESTARTSYS; return -ERESTARTSYS;
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
up(&av7110->dcomlock); up(&av7110->dcomlock);
if ((stat & flags) == 0) { if ((stat & flags) == 0)
break; break;
} if (err) {
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
__FUNCTION__, stat & flags); __FUNCTION__, stat & flags);
return -ETIMEDOUT; return -ETIMEDOUT;
@ -342,6 +343,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
char *type = NULL; char *type = NULL;
u16 flags[2] = {0, 0}; u16 flags[2] = {0, 0};
u32 stat; u32 stat;
int err;
// dprintk(4, "%p\n", av7110); // dprintk(4, "%p\n", av7110);
@ -351,8 +353,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
} }
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_FREE)) { err = time_after(jiffies, start + ARM_WAIT_FREE);
if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -363,8 +368,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
#ifndef _NOHANDSHAKE #ifndef _NOHANDSHAKE
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { err = time_after(jiffies, start + ARM_WAIT_SHAKE);
if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -401,6 +409,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
/* non-immediate COMMAND type */ /* non-immediate COMMAND type */
start = jiffies; start = jiffies;
for (;;) { for (;;) {
err = time_after(jiffies, start + ARM_WAIT_FREE);
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & flags[0]) { if (stat & flags[0]) {
printk(KERN_ERR "%s: %s QUEUE overflow\n", printk(KERN_ERR "%s: %s QUEUE overflow\n",
@ -409,7 +418,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
} }
if ((stat & flags[1]) == 0) if ((stat & flags[1]) == 0)
break; break;
if (time_after(jiffies, start + ARM_WAIT_FREE)) { if (err) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
__FUNCTION__, type); __FUNCTION__, type);
return -ETIMEDOUT; return -ETIMEDOUT;
@ -432,12 +441,13 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
#ifdef COM_DEBUG #ifdef COM_DEBUG
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_FREE)) { err = time_after(jiffies, start + ARM_WAIT_FREE);
if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
__FUNCTION__, __FUNCTION__, (buf[0] >> 8) & 0xff);
(buf[0] >> 8) & 0xff
);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
msleep(1); msleep(1);
@ -553,8 +563,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
} }
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_FREE)) { err = time_after(jiffies, start + ARM_WAIT_FREE);
if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
up(&av7110->dcomlock); up(&av7110->dcomlock);
return -ETIMEDOUT; return -ETIMEDOUT;
@ -566,8 +579,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
#ifndef _NOHANDSHAKE #ifndef _NOHANDSHAKE
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { err = time_after(jiffies, start + ARM_WAIT_SHAKE);
if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
up(&av7110->dcomlock); up(&av7110->dcomlock);
return -ETIMEDOUT; return -ETIMEDOUT;
@ -707,12 +723,16 @@ static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
static int FlushText(struct av7110 *av7110) static int FlushText(struct av7110 *av7110)
{ {
unsigned long start; unsigned long start;
int err;
if (down_interruptible(&av7110->dcomlock)) if (down_interruptible(&av7110->dcomlock))
return -ERESTARTSYS; return -ERESTARTSYS;
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_OSD)) { err = time_after(jiffies, start + ARM_WAIT_OSD);
if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
__FUNCTION__); __FUNCTION__);
up(&av7110->dcomlock); up(&av7110->dcomlock);
@ -735,8 +755,11 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
return -ERESTARTSYS; return -ERESTARTSYS;
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_OSD)) { ret = time_after(jiffies, start + ARM_WAIT_OSD);
if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
break;
if (ret) {
printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
__FUNCTION__); __FUNCTION__);
up(&av7110->dcomlock); up(&av7110->dcomlock);
@ -746,8 +769,11 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
} }
#ifndef _NOHANDSHAKE #ifndef _NOHANDSHAKE
start = jiffies; start = jiffies;
while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) { while (1) {
if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
break;
if (ret) {
printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
__FUNCTION__); __FUNCTION__);
up(&av7110->dcomlock); up(&av7110->dcomlock);