diff options
Diffstat (limited to 'drivers/media/video')
-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 3079e466e6e7..8ef11d578b8d 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); | |||
187 | /* Generic utility functions */ | 187 | /* Generic utility functions */ |
188 | int cx18_msleep_timeout(unsigned int msecs, int intr) | 188 | int cx18_msleep_timeout(unsigned int msecs, int intr) |
189 | { | 189 | { |
190 | int timeout = msecs_to_jiffies(msecs); | 190 | long int timeout = msecs_to_jiffies(msecs); |
191 | int sig; | 191 | int sig; |
192 | 192 | ||
193 | do { | 193 | do { |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e2ec15549783..ce76806759ec 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 { | |||
360 | atomic_t retried_read[CX18_MAX_MMIO_RD_RETRIES+1]; | 360 | atomic_t retried_read[CX18_MAX_MMIO_RD_RETRIES+1]; |
361 | }; | 361 | }; |
362 | 362 | ||
363 | #define CX18_MAX_MB_ACK_DELAY 100 | ||
364 | |||
365 | struct cx18_mbox_stats { | ||
366 | atomic_t mb_ack_delay[CX18_MAX_MB_ACK_DELAY+1]; | ||
367 | }; | ||
368 | |||
363 | /* Struct to hold info about cx18 cards */ | 369 | /* Struct to hold info about cx18 cards */ |
364 | struct cx18 { | 370 | struct cx18 { |
365 | int num; /* board number, -1 during init! */ | 371 | int num; /* board number, -1 during init! */ |
@@ -452,6 +458,7 @@ struct cx18 { | |||
452 | 458 | ||
453 | /* Statistics */ | 459 | /* Statistics */ |
454 | struct cx18_mmio_stats mmio_stats; | 460 | struct cx18_mmio_stats mmio_stats; |
461 | struct cx18_mbox_stats mbox_stats; | ||
455 | 462 | ||
456 | /* v4l2 and User settings */ | 463 | /* v4l2 and User settings */ |
457 | 464 | ||
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 0ad8dea3e600..48a8adc83c2f 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) | |||
37 | for (i = 0; i <= CX18_MAX_MMIO_RD_RETRIES; i++) | 37 | for (i = 0; i <= CX18_MAX_MMIO_RD_RETRIES; i++) |
38 | CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, | 38 | CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, |
39 | atomic_read(&cx->mmio_stats.retried_read[i])); | 39 | atomic_read(&cx->mmio_stats.retried_read[i])); |
40 | for (i = 0; i <= CX18_MAX_MB_ACK_DELAY; i++) | ||
41 | if (atomic_read(&cx->mbox_stats.mb_ack_delay[i])) | ||
42 | CX18_DEBUG_INFO("mb_ack_delay[%d] = %d\n", i, | ||
43 | atomic_read(&cx->mbox_stats.mb_ack_delay[i])); | ||
40 | return; | 44 | return; |
41 | } | 45 | } |
42 | 46 | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 0de4b9a7bbca..35f7188d4d3b 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) | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | static void cx18_api_log_ack_delay(struct cx18 *cx, int msecs) | ||
122 | { | ||
123 | if (msecs > CX18_MAX_MB_ACK_DELAY) | ||
124 | msecs = CX18_MAX_MB_ACK_DELAY; | ||
125 | atomic_inc(&cx->mbox_stats.mb_ack_delay[msecs]); | ||
126 | } | ||
121 | 127 | ||
122 | static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | 128 | static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) |
123 | { | 129 | { |
@@ -127,8 +133,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
127 | u32 __iomem *xpu_state; | 133 | u32 __iomem *xpu_state; |
128 | wait_queue_head_t *waitq; | 134 | wait_queue_head_t *waitq; |
129 | struct mutex *mb_lock; | 135 | struct mutex *mb_lock; |
130 | int timeout = 100; | 136 | long int timeout, ret; |
131 | long unsigned int j, ret; | ||
132 | int i; | 137 | int i; |
133 | 138 | ||
134 | if (info == NULL) { | 139 | if (info == NULL) { |
@@ -176,18 +181,18 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
176 | */ | 181 | */ |
177 | state = cx18_readl(cx, xpu_state); | 182 | state = cx18_readl(cx, xpu_state); |
178 | req = cx18_readl(cx, &mb->request); | 183 | req = cx18_readl(cx, &mb->request); |
179 | j = msecs_to_jiffies(timeout); | 184 | timeout = msecs_to_jiffies(20); /* 1 field at 50 Hz vertical refresh */ |
180 | ret = wait_event_timeout(*waitq, | 185 | ret = wait_event_timeout(*waitq, |
181 | (ack = cx18_readl(cx, &mb->ack)) == req, | 186 | (ack = cx18_readl(cx, &mb->ack)) == req, |
182 | j); | 187 | timeout); |
183 | if (req != ack) { | 188 | if (req != ack) { |
184 | /* waited long enough, make the mbox "not busy" from our end */ | 189 | /* waited long enough, make the mbox "not busy" from our end */ |
185 | cx18_writel(cx, req, &mb->ack); | 190 | cx18_writel(cx, req, &mb->ack); |
186 | CX18_ERR("mbox was found stuck busy when setting up for %s; " | 191 | CX18_ERR("mbox was found stuck busy when setting up for %s; " |
187 | "clearing busy and trying to proceed\n", info->name); | 192 | "clearing busy and trying to proceed\n", info->name); |
188 | } else if (ret != j) | 193 | } else if (ret != timeout) |
189 | CX18_DEBUG_API("waited %u usecs for busy mbox to be acked\n", | 194 | CX18_DEBUG_API("waited %u usecs for busy mbox to be acked\n", |
190 | jiffies_to_usecs(j-ret)); | 195 | jiffies_to_usecs(timeout-ret)); |
191 | 196 | ||
192 | /* Build the outgoing mailbox */ | 197 | /* Build the outgoing mailbox */ |
193 | req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1; | 198 | 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[]) | |||
199 | cx18_writel(cx, req, &mb->request); | 204 | cx18_writel(cx, req, &mb->request); |
200 | cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */ | 205 | cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */ |
201 | 206 | ||
202 | /* Notify the XPU and wait for it to send an Ack back */ | 207 | /* |
203 | if (info->flags & API_FAST) | 208 | * Notify the XPU and wait for it to send an Ack back |
204 | timeout /= 2; | 209 | * 21 ms = ~ 0.5 frames at a frame rate of 24 fps |
205 | j = msecs_to_jiffies(timeout); | 210 | * 42 ms = ~ 1 frame at a frame rate of 24 fps |
211 | */ | ||
212 | timeout = msecs_to_jiffies((info->flags & API_FAST) ? 21 : 42); | ||
206 | 213 | ||
207 | CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", | 214 | CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", |
208 | irq, info->name); | 215 | irq, info->name); |
209 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); | 216 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); |
210 | 217 | ||
211 | ret = wait_event_interruptible_timeout( | 218 | ret = wait_event_timeout( |
212 | *waitq, | 219 | *waitq, |
213 | cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), | 220 | cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), |
214 | j); | 221 | timeout); |
215 | if (ret == 0) { | 222 | if (ret == 0) { |
216 | /* Timed out */ | 223 | /* Timed out */ |
217 | mutex_unlock(mb_lock); | 224 | mutex_unlock(mb_lock); |
218 | CX18_ERR("sending %s timed out waiting for RPU " | 225 | i = jiffies_to_msecs(timeout); |
219 | "acknowledgement\n", info->name); | 226 | cx18_api_log_ack_delay(cx, i); |
227 | CX18_WARN("sending %s timed out waiting %d msecs for RPU " | ||
228 | "acknowledgement\n", info->name, i); | ||
220 | return -EINVAL; | 229 | return -EINVAL; |
221 | } else if (ret < 0) { | 230 | } else if (ret < 0) { |
222 | /* Interrupted */ | 231 | /* Interrupted */ |
@@ -224,9 +233,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
224 | CX18_WARN("sending %s was interrupted waiting for RPU" | 233 | CX18_WARN("sending %s was interrupted waiting for RPU" |
225 | "acknowledgement\n", info->name); | 234 | "acknowledgement\n", info->name); |
226 | return -EINTR; | 235 | return -EINTR; |
227 | } else if (ret != j) | 236 | } |
228 | CX18_DEBUG_HI_API("waited %u usecs for %s to be acked\n", | 237 | |
229 | jiffies_to_usecs(j-ret), info->name); | 238 | i = jiffies_to_msecs(timeout-ret); |
239 | cx18_api_log_ack_delay(cx, i); | ||
240 | if (ret != timeout) | ||
241 | CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", | ||
242 | i, info->name); | ||
230 | 243 | ||
231 | /* Collect data returned by the XPU */ | 244 | /* Collect data returned by the XPU */ |
232 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) | 245 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) |