summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-04-13 21:53:09 -0400
committerAndy Walls <awalls@radix.net>2009-04-13 21:53:09 -0400
commitb475f6c79d531e93935cba748b4dd3a0c572597b (patch)
tree34863d1908181ce860dab98021f72ad8c596bfff /linux/drivers/media/video
parent30acb038b4822df9ff73cd379a9144314a194d94 (diff)
downloadmediapointer-dvb-s2-b475f6c79d531e93935cba748b4dd3a0c572597b.tar.gz
mediapointer-dvb-s2-b475f6c79d531e93935cba748b4dd3a0c572597b.tar.bz2
cx18: Set up to wait for a one-shot response before sending a firmware cmd
From: Andy Walls <awalls@radix.net> When sending an outgoing firmware command, prepare to wait before we raise the interrupt, so we don't miss the wake_up() on the acknowledgment. When waiting for the acknowledgement, there is no need to loop around schedule(), as there will only be one interrupt, and hence one wake_up(), issued. Priority: normal Signed-off-by: Andy Walls <awalls@radix.net>
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c
index 1f643b9e6..58b5d0229 100644
--- a/linux/drivers/media/video/cx18/cx18-mailbox.c
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.c
@@ -484,9 +484,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
u32 __iomem *xpu_state;
wait_queue_head_t *waitq;
struct mutex *mb_lock;
- long int timeout, ret;
+ unsigned long int t0, timeout, ret;
int i;
char argstr[MAX_MB_ARGUMENTS*11+1];
+ DEFINE_WAIT(w);
if (info == NULL) {
CX18_WARN("unknown cmd %x\n", cmd);
@@ -568,25 +569,49 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
irq, info->name);
+
+ /* So we don't miss the wakeup, prepare to wait before notifying fw */
+ prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
- ret = wait_event_timeout(
- *waitq,
- cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
- timeout);
+ t0 = jiffies;
+ ack = cx18_readl(cx, &mb->ack);
+ if (ack != req) {
+ schedule_timeout(timeout);
+ ret = jiffies - t0;
+ ack = cx18_readl(cx, &mb->ack);
+ } else {
+ ret = jiffies - t0;
+ }
+
+ finish_wait(waitq, &w);
- if (ret == 0) {
- /* Timed out */
+ if (req != ack) {
mutex_unlock(mb_lock);
- CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU "
- "acknowledgement\n",
- info->name, jiffies_to_msecs(timeout));
+ if (ret >= timeout) {
+ /* Timed out */
+ CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
+ "for RPU acknowledgement\n",
+ info->name, jiffies_to_msecs(ret));
+ } else {
+ CX18_DEBUG_WARN("woken up before mailbox ack was ready "
+ "after submitting %s to RPU. only "
+ "waited %d msecs on req %u but awakened"
+ " with unmatched ack %u\n",
+ info->name,
+ jiffies_to_msecs(ret),
+ req, ack);
+ }
return -EINVAL;
}
- if (ret != timeout)
+ if (ret >= timeout)
+ CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
+ "sending %s; timed out waiting %d msecs\n",
+ info->name, jiffies_to_msecs(ret));
+ else
CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
- jiffies_to_msecs(timeout-ret), info->name);
+ jiffies_to_msecs(ret), info->name);
/* Collect data returned by the XPU */
for (i = 0; i < MAX_MB_ARGUMENTS; i++)