diff options
author | Oliver Endriss <o.endriss@gmx.de> | 2005-07-07 20:58:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-07 21:24:02 -0400 |
commit | 25de192660627e1e8dc8ee6a120ff8b54d108593 (patch) | |
tree | 45e15b799e09f6b5fe478082303a8c276529edc1 | |
parent | e161f817bebecc1c1cc461dc83cce2eafbed9ee9 (diff) |
[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>
-rw-r--r-- | drivers/media/common/saa7146_core.c | 11 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/av7110_hw.c | 72 |
2 files changed, 56 insertions, 27 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 77ff22911566..cd5828b5e9e3 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
@@ -62,13 +62,15 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) | |||
62 | int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) | 62 | int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) |
63 | { | 63 | { |
64 | unsigned long start; | 64 | unsigned long start; |
65 | int err; | ||
65 | 66 | ||
66 | /* wait for registers to be programmed */ | 67 | /* wait for registers to be programmed */ |
67 | start = jiffies; | 68 | start = jiffies; |
68 | while (1) { | 69 | while (1) { |
69 | if (saa7146_read(dev, MC2) & 2) | 70 | err = time_after(jiffies, start + HZ/20); |
70 | break; | 71 | if (saa7146_read(dev, MC2) & 2) |
71 | if (time_after(jiffies, start + HZ/20)) { | 72 | break; |
73 | if (err) { | ||
72 | DEB_S(("timed out while waiting for registers getting programmed\n")); | 74 | DEB_S(("timed out while waiting for registers getting programmed\n")); |
73 | return -ETIMEDOUT; | 75 | return -ETIMEDOUT; |
74 | } | 76 | } |
@@ -79,10 +81,11 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) | |||
79 | /* wait for transfer to complete */ | 81 | /* wait for transfer to complete */ |
80 | start = jiffies; | 82 | start = jiffies; |
81 | while (1) { | 83 | while (1) { |
84 | err = time_after(jiffies, start + HZ/4); | ||
82 | if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) | 85 | if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) |
83 | break; | 86 | break; |
84 | saa7146_read(dev, MC2); | 87 | saa7146_read(dev, MC2); |
85 | if (time_after(jiffies, start + HZ/4)) { | 88 | if (err) { |
86 | DEB_S(("timed out while waiting for transfer completion\n")); | 89 | DEB_S(("timed out while waiting for transfer completion\n")); |
87 | return -ETIMEDOUT; | 90 | return -ETIMEDOUT; |
88 | } | 91 | } |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index aa1efce6cb31..1220826696c5 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
@@ -308,6 +308,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) | |||
308 | { | 308 | { |
309 | unsigned long start; | 309 | unsigned long start; |
310 | u32 stat; | 310 | u32 stat; |
311 | int err; | ||
311 | 312 | ||
312 | if (FW_VERSION(av7110->arm_app) <= 0x261c) { | 313 | if (FW_VERSION(av7110->arm_app) <= 0x261c) { |
313 | /* not supported by old firmware */ | 314 | /* not supported by old firmware */ |
@@ -318,14 +319,14 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) | |||
318 | /* new firmware */ | 319 | /* new firmware */ |
319 | start = jiffies; | 320 | start = jiffies; |
320 | for (;;) { | 321 | for (;;) { |
322 | err = time_after(jiffies, start + ARM_WAIT_FREE); | ||
321 | if (down_interruptible(&av7110->dcomlock)) | 323 | if (down_interruptible(&av7110->dcomlock)) |
322 | return -ERESTARTSYS; | 324 | return -ERESTARTSYS; |
323 | stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); | 325 | stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); |
324 | up(&av7110->dcomlock); | 326 | up(&av7110->dcomlock); |
325 | if ((stat & flags) == 0) { | 327 | if ((stat & flags) == 0) |
326 | break; | 328 | break; |
327 | } | 329 | if (err) { |
328 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | ||
329 | printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", | 330 | printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", |
330 | __FUNCTION__, stat & flags); | 331 | __FUNCTION__, stat & flags); |
331 | return -ETIMEDOUT; | 332 | return -ETIMEDOUT; |
@@ -342,6 +343,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
342 | char *type = NULL; | 343 | char *type = NULL; |
343 | u16 flags[2] = {0, 0}; | 344 | u16 flags[2] = {0, 0}; |
344 | u32 stat; | 345 | u32 stat; |
346 | int err; | ||
345 | 347 | ||
346 | // dprintk(4, "%p\n", av7110); | 348 | // dprintk(4, "%p\n", av7110); |
347 | 349 | ||
@@ -351,8 +353,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
351 | } | 353 | } |
352 | 354 | ||
353 | start = jiffies; | 355 | start = jiffies; |
354 | while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { | 356 | while (1) { |
355 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 357 | err = time_after(jiffies, start + ARM_WAIT_FREE); |
358 | if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) | ||
359 | break; | ||
360 | if (err) { | ||
356 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); | 361 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); |
357 | return -ETIMEDOUT; | 362 | return -ETIMEDOUT; |
358 | } | 363 | } |
@@ -363,8 +368,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
363 | 368 | ||
364 | #ifndef _NOHANDSHAKE | 369 | #ifndef _NOHANDSHAKE |
365 | start = jiffies; | 370 | start = jiffies; |
366 | while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { | 371 | while (1) { |
367 | if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { | 372 | err = time_after(jiffies, start + ARM_WAIT_SHAKE); |
373 | if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) | ||
374 | break; | ||
375 | if (err) { | ||
368 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); | 376 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); |
369 | return -ETIMEDOUT; | 377 | return -ETIMEDOUT; |
370 | } | 378 | } |
@@ -401,6 +409,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
401 | /* non-immediate COMMAND type */ | 409 | /* non-immediate COMMAND type */ |
402 | start = jiffies; | 410 | start = jiffies; |
403 | for (;;) { | 411 | for (;;) { |
412 | err = time_after(jiffies, start + ARM_WAIT_FREE); | ||
404 | stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); | 413 | stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); |
405 | if (stat & flags[0]) { | 414 | if (stat & flags[0]) { |
406 | printk(KERN_ERR "%s: %s QUEUE overflow\n", | 415 | 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) | |||
409 | } | 418 | } |
410 | if ((stat & flags[1]) == 0) | 419 | if ((stat & flags[1]) == 0) |
411 | break; | 420 | break; |
412 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 421 | if (err) { |
413 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", | 422 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", |
414 | __FUNCTION__, type); | 423 | __FUNCTION__, type); |
415 | return -ETIMEDOUT; | 424 | return -ETIMEDOUT; |
@@ -432,12 +441,13 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
432 | 441 | ||
433 | #ifdef COM_DEBUG | 442 | #ifdef COM_DEBUG |
434 | start = jiffies; | 443 | start = jiffies; |
435 | while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { | 444 | while (1) { |
436 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 445 | err = time_after(jiffies, start + ARM_WAIT_FREE); |
446 | if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) | ||
447 | break; | ||
448 | if (err) { | ||
437 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", | 449 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", |
438 | __FUNCTION__, | 450 | __FUNCTION__, (buf[0] >> 8) & 0xff); |
439 | (buf[0] >> 8) & 0xff | ||
440 | ); | ||
441 | return -ETIMEDOUT; | 451 | return -ETIMEDOUT; |
442 | } | 452 | } |
443 | msleep(1); | 453 | msleep(1); |
@@ -553,8 +563,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, | |||
553 | } | 563 | } |
554 | 564 | ||
555 | start = jiffies; | 565 | start = jiffies; |
556 | while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) { | 566 | while (1) { |
557 | if (time_after(jiffies, start + ARM_WAIT_FREE)) { | 567 | err = time_after(jiffies, start + ARM_WAIT_FREE); |
568 | if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) | ||
569 | break; | ||
570 | if (err) { | ||
558 | printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); | 571 | printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); |
559 | up(&av7110->dcomlock); | 572 | up(&av7110->dcomlock); |
560 | return -ETIMEDOUT; | 573 | return -ETIMEDOUT; |
@@ -566,8 +579,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, | |||
566 | 579 | ||
567 | #ifndef _NOHANDSHAKE | 580 | #ifndef _NOHANDSHAKE |
568 | start = jiffies; | 581 | start = jiffies; |
569 | while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { | 582 | while (1) { |
570 | if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { | 583 | err = time_after(jiffies, start + ARM_WAIT_SHAKE); |
584 | if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) | ||
585 | break; | ||
586 | if (err) { | ||
571 | printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); | 587 | printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); |
572 | up(&av7110->dcomlock); | 588 | up(&av7110->dcomlock); |
573 | return -ETIMEDOUT; | 589 | return -ETIMEDOUT; |
@@ -707,12 +723,16 @@ static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize, | |||
707 | static int FlushText(struct av7110 *av7110) | 723 | static int FlushText(struct av7110 *av7110) |
708 | { | 724 | { |
709 | unsigned long start; | 725 | unsigned long start; |
726 | int err; | ||
710 | 727 | ||
711 | if (down_interruptible(&av7110->dcomlock)) | 728 | if (down_interruptible(&av7110->dcomlock)) |
712 | return -ERESTARTSYS; | 729 | return -ERESTARTSYS; |
713 | start = jiffies; | 730 | start = jiffies; |
714 | while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { | 731 | while (1) { |
715 | if (time_after(jiffies, start + ARM_WAIT_OSD)) { | 732 | err = time_after(jiffies, start + ARM_WAIT_OSD); |
733 | if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0) | ||
734 | break; | ||
735 | if (err) { | ||
716 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", | 736 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", |
717 | __FUNCTION__); | 737 | __FUNCTION__); |
718 | up(&av7110->dcomlock); | 738 | up(&av7110->dcomlock); |
@@ -735,8 +755,11 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) | |||
735 | return -ERESTARTSYS; | 755 | return -ERESTARTSYS; |
736 | 756 | ||
737 | start = jiffies; | 757 | start = jiffies; |
738 | while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { | 758 | while (1) { |
739 | if (time_after(jiffies, start + ARM_WAIT_OSD)) { | 759 | ret = time_after(jiffies, start + ARM_WAIT_OSD); |
760 | if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0) | ||
761 | break; | ||
762 | if (ret) { | ||
740 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", | 763 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", |
741 | __FUNCTION__); | 764 | __FUNCTION__); |
742 | up(&av7110->dcomlock); | 765 | up(&av7110->dcomlock); |
@@ -746,8 +769,11 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) | |||
746 | } | 769 | } |
747 | #ifndef _NOHANDSHAKE | 770 | #ifndef _NOHANDSHAKE |
748 | start = jiffies; | 771 | start = jiffies; |
749 | while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) { | 772 | while (1) { |
750 | if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { | 773 | ret = time_after(jiffies, start + ARM_WAIT_SHAKE); |
774 | if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) | ||
775 | break; | ||
776 | if (ret) { | ||
751 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", | 777 | printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", |
752 | __FUNCTION__); | 778 | __FUNCTION__); |
753 | up(&av7110->dcomlock); | 779 | up(&av7110->dcomlock); |