aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-streams.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-12-12 13:50:27 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:32 -0500
commitabb096de82f6f920a06ca935f76925261e66b556 (patch)
tree51f71ecb1d420083e54162b32733cf237b5b2393 /drivers/media/video/cx18/cx18-streams.c
parent765f6f612ef69ada79f7ec2627dcbc49276bf7b5 (diff)
V4L/DVB (9804): cx18: Avoid making firmware API calls with the queue lock held
cx18: Avoid making firmware API calls with the queue lock held. The source of MPEG strem corruption when not holding the queue lock was found to be that the MPEG buffer could be retrieved by the user app before it was sync'ed for the host cpu. Incoming buffers are now sync'ed before being put on q_full and releasing the queue lock. We can thus avoid the sometimes lengthy call to the firmware for CPU_DE_SET_MDL while holding the queue lock, so we can get better performance. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r--drivers/media/video/cx18/cx18-streams.c37
1 files changed, 14 insertions, 23 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index d2690ccdf327..9ead4591b1d2 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -419,31 +419,22 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
419 return q; 419 return q;
420} 420}
421 421
422/* Must hold s->qlock when calling */ 422void cx18_stream_load_fw_queue(struct cx18_stream *s)
423void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s)
424{ 423{
424 struct cx18_queue *q;
425 struct cx18_buffer *buf; 425 struct cx18_buffer *buf;
426 struct cx18 *cx = s->cx;
427 426
428 /* Move from q_free to q_busy notifying the firmware: 63 buf limit */ 427 if (atomic_read(&s->q_free.buffers) == 0 ||
429 while (s->handle != CX18_INVALID_TASK_HANDLE && 428 atomic_read(&s->q_busy.buffers) >= 63)
430 test_bit(CX18_F_S_STREAMING, &s->s_flags) && 429 return;
431 atomic_read(&s->q_busy.buffers) < 63 && 430
432 !list_empty(&s->q_free.list)) { 431 /* Move from q_free to q_busy notifying the firmware, until the limit */
433 432 do {
434 /* Move from q_free to q_busy */ 433 buf = cx18_dequeue(s, &s->q_free);
435 buf = list_entry(s->q_free.list.next, struct cx18_buffer, list); 434 if (buf == NULL)
436 list_move_tail(&buf->list, &s->q_busy.list); 435 break;
437 buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; 436 q = cx18_stream_put_buf_fw(s, buf);
438 atomic_dec(&s->q_free.buffers); 437 } while (atomic_read(&s->q_busy.buffers) < 63 && q == &s->q_busy);
439 atomic_inc(&s->q_busy.buffers);
440
441 /* Notify firmware */
442 cx18_buf_sync_for_device(s, buf);
443 cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
444 (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
445 1, buf->id, s->buf_size);
446 }
447} 438}
448 439
449int cx18_start_v4l2_encode_stream(struct cx18_stream *s) 440int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
@@ -543,8 +534,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
543 &cx->scb->cpu_mdl[buf->id].paddr); 534 &cx->scb->cpu_mdl[buf->id].paddr);
544 cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); 535 cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
545 } 536 }
546 cx18_stream_load_fw_queue_nolock(s);
547 mutex_unlock(&s->qlock); 537 mutex_unlock(&s->qlock);
538 cx18_stream_load_fw_queue(s);
548 539
549 /* begin_capture */ 540 /* begin_capture */
550 if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { 541 if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {