diff options
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.h | 7 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-io.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 47 |
4 files changed, 42 insertions, 18 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3079e466e6e..8ef11d578b8 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -187,7 +187,7 @@ MODULE_VERSION(CX18_VERSION); /* Generic utility functions */ int cx18_msleep_timeout(unsigned int msecs, int intr) { - int timeout = msecs_to_jiffies(msecs); + long int timeout = msecs_to_jiffies(msecs); int sig; do { diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e2ec1554978..ce76806759e 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -360,6 +360,12 @@ struct cx18_mmio_stats { atomic_t retried_read[CX18_MAX_MMIO_RD_RETRIES+1]; }; +#define CX18_MAX_MB_ACK_DELAY 100 + +struct cx18_mbox_stats { + atomic_t mb_ack_delay[CX18_MAX_MB_ACK_DELAY+1]; +}; + /* Struct to hold info about cx18 cards */ struct cx18 { int num; /* board number, -1 during init! */ @@ -452,6 +458,7 @@ struct cx18 { /* Statistics */ struct cx18_mmio_stats mmio_stats; + struct cx18_mbox_stats mbox_stats; /* v4l2 and User settings */ diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 0ad8dea3e60..48a8adc83c2 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -37,6 +37,10 @@ void cx18_log_statistics(struct cx18 *cx) for (i = 0; i <= CX18_MAX_MMIO_RD_RETRIES; i++) CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, atomic_read(&cx->mmio_stats.retried_read[i])); + for (i = 0; i <= CX18_MAX_MB_ACK_DELAY; i++) + if (atomic_read(&cx->mbox_stats.mb_ack_delay[i])) + CX18_DEBUG_INFO("mb_ack_delay[%d] = %d\n", i, + atomic_read(&cx->mbox_stats.mb_ack_delay[i])); return; } diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 0de4b9a7bbc..35f7188d4d3 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -118,6 +118,12 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb, int rpu) return 0; } +static void cx18_api_log_ack_delay(struct cx18 *cx, int msecs) +{ + if (msecs > CX18_MAX_MB_ACK_DELAY) + msecs = CX18_MAX_MB_ACK_DELAY; + atomic_inc(&cx->mbox_stats.mb_ack_delay[msecs]); +} static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) { @@ -127,8 +133,7 @@ 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; - int timeout = 100; - long unsigned int j, ret; + long int timeout, ret; int i; if (info == NULL) { @@ -176,18 +181,18 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) */ state = cx18_readl(cx, xpu_state); req = cx18_readl(cx, &mb->request); - j = msecs_to_jiffies(timeout); + timeout = msecs_to_jiffies(20); /* 1 field at 50 Hz vertical refresh */ ret = wait_event_timeout(*waitq, (ack = cx18_readl(cx, &mb->ack)) == req, - j); + timeout); if (req != ack) { /* waited long enough, make the mbox "not busy" from our end */ cx18_writel(cx, req, &mb->ack); CX18_ERR("mbox was found stuck busy when setting up for %s; " "clearing busy and trying to proceed\n", info->name); - } else if (ret != j) + } else if (ret != timeout) CX18_DEBUG_API("waited %u usecs for busy mbox to be acked\n", - jiffies_to_usecs(j-ret)); + jiffies_to_usecs(timeout-ret)); /* Build the outgoing mailbox */ req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1; @@ -199,24 +204,28 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) cx18_writel(cx, req, &mb->request); cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */ - /* Notify the XPU and wait for it to send an Ack back */ - if (info->flags & API_FAST) - timeout /= 2; - j = msecs_to_jiffies(timeout); + /* + * Notify the XPU and wait for it to send an Ack back + * 21 ms = ~ 0.5 frames at a frame rate of 24 fps + * 42 ms = ~ 1 frame at a frame rate of 24 fps + */ + timeout = msecs_to_jiffies((info->flags & API_FAST) ? 21 : 42); CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", irq, info->name); cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); - ret = wait_event_interruptible_timeout( + ret = wait_event_timeout( *waitq, cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), - j); + timeout); if (ret == 0) { /* Timed out */ mutex_unlock(mb_lock); - CX18_ERR("sending %s timed out waiting for RPU " - "acknowledgement\n", info->name); + i = jiffies_to_msecs(timeout); + cx18_api_log_ack_delay(cx, i); + CX18_WARN("sending %s timed out waiting %d msecs for RPU " + "acknowledgement\n", info->name, i); return -EINVAL; } else if (ret < 0) { /* Interrupted */ @@ -224,9 +233,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) CX18_WARN("sending %s was interrupted waiting for RPU" "acknowledgement\n", info->name); return -EINTR; - } else if (ret != j) - CX18_DEBUG_HI_API("waited %u usecs for %s to be acked\n", - jiffies_to_usecs(j-ret), info->name); + } + + i = jiffies_to_msecs(timeout-ret); + cx18_api_log_ack_delay(cx, i); + if (ret != timeout) + CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", + i, info->name); /* Collect data returned by the XPU */ for (i = 0; i < MAX_MB_ARGUMENTS; i++) |