diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 82 |
1 files changed, 5 insertions, 77 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index e1934e9cfdc8..41a1b2618aac 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -124,6 +124,8 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
124 | cx18_queue_init(&s->q_busy); | 124 | cx18_queue_init(&s->q_busy); |
125 | spin_lock_init(&s->q_full.lock); | 125 | spin_lock_init(&s->q_full.lock); |
126 | cx18_queue_init(&s->q_full); | 126 | cx18_queue_init(&s->q_full); |
127 | |||
128 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); | ||
127 | } | 129 | } |
128 | 130 | ||
129 | static int cx18_prep_dev(struct cx18 *cx, int type) | 131 | static int cx18_prep_dev(struct cx18 *cx, int type) |
@@ -477,86 +479,12 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) | |||
477 | && q == &s->q_busy); | 479 | && q == &s->q_busy); |
478 | } | 480 | } |
479 | 481 | ||
480 | static inline | ||
481 | void free_out_work_order(struct cx18_out_work_order *order) | ||
482 | { | ||
483 | atomic_set(&order->pending, 0); | ||
484 | } | ||
485 | |||
486 | void cx18_out_work_handler(struct work_struct *work) | 482 | void cx18_out_work_handler(struct work_struct *work) |
487 | { | 483 | { |
488 | struct cx18_out_work_order *order = | 484 | struct cx18_stream *s = |
489 | container_of(work, struct cx18_out_work_order, work); | 485 | container_of(work, struct cx18_stream, out_work_order); |
490 | struct cx18_stream *s = order->s; | ||
491 | struct cx18_buffer *buf = order->buf; | ||
492 | |||
493 | free_out_work_order(order); | ||
494 | |||
495 | if (buf == NULL) | ||
496 | _cx18_stream_load_fw_queue(s); | ||
497 | else | ||
498 | _cx18_stream_put_buf_fw(s, buf); | ||
499 | } | ||
500 | |||
501 | static | ||
502 | struct cx18_out_work_order *alloc_out_work_order(struct cx18 *cx) | ||
503 | { | ||
504 | int i; | ||
505 | struct cx18_out_work_order *order = NULL; | ||
506 | |||
507 | for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) { | ||
508 | /* | ||
509 | * We need "pending" to be atomic to inspect & set its contents | ||
510 | * 1. "pending" is only set to 1 here, but needs multiple access | ||
511 | * protection | ||
512 | * 2. work handler threads only clear "pending" and only | ||
513 | * on one, particular work order at a time, per handler thread. | ||
514 | */ | ||
515 | if (atomic_add_unless(&cx->out_work_order[i].pending, 1, 1)) { | ||
516 | order = &cx->out_work_order[i]; | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | return order; | ||
521 | } | ||
522 | |||
523 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | ||
524 | struct cx18_buffer *buf) | ||
525 | { | ||
526 | struct cx18 *cx = s->cx; | ||
527 | struct cx18_out_work_order *order; | ||
528 | |||
529 | order = alloc_out_work_order(cx); | ||
530 | if (order == NULL) { | ||
531 | CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " | ||
532 | "order forms available; sending buffer %u back " | ||
533 | "to the firmware immediately for stream %s\n", | ||
534 | buf->id, s->name); | ||
535 | return _cx18_stream_put_buf_fw(s, buf); | ||
536 | } | ||
537 | order->s = s; | ||
538 | order->buf = buf; | ||
539 | queue_work(cx->out_work_queue, &order->work); | ||
540 | return NULL; | ||
541 | } | ||
542 | |||
543 | void cx18_stream_load_fw_queue(struct cx18_stream *s) | ||
544 | { | ||
545 | struct cx18 *cx = s->cx; | ||
546 | struct cx18_out_work_order *order; | ||
547 | 486 | ||
548 | order = alloc_out_work_order(cx); | 487 | _cx18_stream_load_fw_queue(s); |
549 | if (order == NULL) { | ||
550 | CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " | ||
551 | "order forms available; filling the firmware " | ||
552 | "buffer queue immediately for stream %s\n", | ||
553 | s->name); | ||
554 | _cx18_stream_load_fw_queue(s); | ||
555 | return; | ||
556 | } | ||
557 | order->s = s; | ||
558 | order->buf = NULL; /* Indicates to load the fw queue */ | ||
559 | queue_work(cx->out_work_queue, &order->work); | ||
560 | } | 488 | } |
561 | 489 | ||
562 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 490 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |