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) cx18_queue_init(&s->q_busy); spin_lock_init(&s->q_full.lock); cx18_queue_init(&s->q_full); + + INIT_WORK(&s->out_work_order, cx18_out_work_handler); } static int cx18_prep_dev(struct cx18 *cx, int type) @@ -477,86 +479,12 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) && q == &s->q_busy); } -static inline -void free_out_work_order(struct cx18_out_work_order *order) -{ - atomic_set(&order->pending, 0); -} - void cx18_out_work_handler(struct work_struct *work) { - struct cx18_out_work_order *order = - container_of(work, struct cx18_out_work_order, work); - struct cx18_stream *s = order->s; - struct cx18_buffer *buf = order->buf; - - free_out_work_order(order); - - if (buf == NULL) - _cx18_stream_load_fw_queue(s); - else - _cx18_stream_put_buf_fw(s, buf); -} - -static -struct cx18_out_work_order *alloc_out_work_order(struct cx18 *cx) -{ - int i; - struct cx18_out_work_order *order = NULL; - - for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) { - /* - * We need "pending" to be atomic to inspect & set its contents - * 1. "pending" is only set to 1 here, but needs multiple access - * protection - * 2. work handler threads only clear "pending" and only - * on one, particular work order at a time, per handler thread. - */ - if (atomic_add_unless(&cx->out_work_order[i].pending, 1, 1)) { - order = &cx->out_work_order[i]; - break; - } - } - return order; -} - -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) -{ - struct cx18 *cx = s->cx; - struct cx18_out_work_order *order; - - order = alloc_out_work_order(cx); - if (order == NULL) { - CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " - "order forms available; sending buffer %u back " - "to the firmware immediately for stream %s\n", - buf->id, s->name); - return _cx18_stream_put_buf_fw(s, buf); - } - order->s = s; - order->buf = buf; - queue_work(cx->out_work_queue, &order->work); - return NULL; -} - -void cx18_stream_load_fw_queue(struct cx18_stream *s) -{ - struct cx18 *cx = s->cx; - struct cx18_out_work_order *order; + struct cx18_stream *s = + container_of(work, struct cx18_stream, out_work_order); - order = alloc_out_work_order(cx); - if (order == NULL) { - CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " - "order forms available; filling the firmware " - "buffer queue immediately for stream %s\n", - s->name); - _cx18_stream_load_fw_queue(s); - return; - } - order->s = s; - order->buf = NULL; /* Indicates to load the fw queue */ - queue_work(cx->out_work_queue, &order->work); + _cx18_stream_load_fw_queue(s); } int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |