diff options
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 2a4d4356d1b..df7d61d0a13 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -478,9 +478,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
478 | u32 __iomem *xpu_state; | 478 | u32 __iomem *xpu_state; |
479 | wait_queue_head_t *waitq; | 479 | wait_queue_head_t *waitq; |
480 | struct mutex *mb_lock; | 480 | struct mutex *mb_lock; |
481 | long int timeout, ret; | 481 | unsigned long int t0, timeout, ret; |
482 | int i; | 482 | int i; |
483 | char argstr[MAX_MB_ARGUMENTS*11+1]; | 483 | char argstr[MAX_MB_ARGUMENTS*11+1]; |
484 | DEFINE_WAIT(w); | ||
484 | 485 | ||
485 | if (info == NULL) { | 486 | if (info == NULL) { |
486 | CX18_WARN("unknown cmd %x\n", cmd); | 487 | CX18_WARN("unknown cmd %x\n", cmd); |
@@ -562,25 +563,49 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
562 | 563 | ||
563 | CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", | 564 | CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", |
564 | irq, info->name); | 565 | irq, info->name); |
566 | |||
567 | /* So we don't miss the wakeup, prepare to wait before notifying fw */ | ||
568 | prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE); | ||
565 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); | 569 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); |
566 | 570 | ||
567 | ret = wait_event_timeout( | 571 | t0 = jiffies; |
568 | *waitq, | 572 | ack = cx18_readl(cx, &mb->ack); |
569 | cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), | 573 | if (ack != req) { |
570 | timeout); | 574 | schedule_timeout(timeout); |
575 | ret = jiffies - t0; | ||
576 | ack = cx18_readl(cx, &mb->ack); | ||
577 | } else { | ||
578 | ret = jiffies - t0; | ||
579 | } | ||
580 | |||
581 | finish_wait(waitq, &w); | ||
571 | 582 | ||
572 | if (ret == 0) { | 583 | if (req != ack) { |
573 | /* Timed out */ | ||
574 | mutex_unlock(mb_lock); | 584 | mutex_unlock(mb_lock); |
575 | CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU " | 585 | if (ret >= timeout) { |
576 | "acknowledgement\n", | 586 | /* Timed out */ |
577 | info->name, jiffies_to_msecs(timeout)); | 587 | CX18_DEBUG_WARN("sending %s timed out waiting %d msecs " |
588 | "for RPU acknowledgement\n", | ||
589 | info->name, jiffies_to_msecs(ret)); | ||
590 | } else { | ||
591 | CX18_DEBUG_WARN("woken up before mailbox ack was ready " | ||
592 | "after submitting %s to RPU. only " | ||
593 | "waited %d msecs on req %u but awakened" | ||
594 | " with unmatched ack %u\n", | ||
595 | info->name, | ||
596 | jiffies_to_msecs(ret), | ||
597 | req, ack); | ||
598 | } | ||
578 | return -EINVAL; | 599 | return -EINVAL; |
579 | } | 600 | } |
580 | 601 | ||
581 | if (ret != timeout) | 602 | if (ret >= timeout) |
603 | CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment " | ||
604 | "sending %s; timed out waiting %d msecs\n", | ||
605 | info->name, jiffies_to_msecs(ret)); | ||
606 | else | ||
582 | CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", | 607 | CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", |
583 | jiffies_to_msecs(timeout-ret), info->name); | 608 | jiffies_to_msecs(ret), info->name); |
584 | 609 | ||
585 | /* Collect data returned by the XPU */ | 610 | /* Collect data returned by the XPU */ |
586 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) | 611 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) |