diff options
author | John Sheu <sheu@chromium.org> | 2013-02-06 20:03:01 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-19 15:13:33 -0300 |
commit | 401f6a2729988c7229c3a78bba0d2f73851e3f51 (patch) | |
tree | 03f0331a3557b262fd508a769cf48673c3f39e1c /drivers/media/v4l2-core | |
parent | f1a0569be680a1bfb9d624cc4893cba0c6ad4172 (diff) |
[media] v4l2-mem2mem: drop rdy_queue on STREAMOFF
When a v4l2-mem2mem context gets a STREAMOFF call on either its CAPTURE
or OUTPUT queues, we should:
* Drop the corresponding rdy_queue, since a subsequent STREAMON expects
an empty queue.
* Deschedule the context, as it now has at least one empty queue and
cannot run.
Signed-off-by: John Sheu <sheu@google.com>
Acked-by: Pawel Osciak <pawel@osciak.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-mem2mem.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 27ddb3d1525..66f599fcb82 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -408,10 +408,35 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_streamon); int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) { - struct vb2_queue *vq; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_queue_ctx *q_ctx; + unsigned long flags_job, flags; + int ret; - vq = v4l2_m2m_get_vq(m2m_ctx, type); - return vb2_streamoff(vq, type); + q_ctx = get_queue_ctx(m2m_ctx, type); + ret = vb2_streamoff(&q_ctx->q, type); + if (ret) + return ret; + + m2m_dev = m2m_ctx->m2m_dev; + spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job); + /* We should not be scheduled anymore, since we're dropping a queue. */ + INIT_LIST_HEAD(&m2m_ctx->queue); + m2m_ctx->job_flags = 0; + + spin_lock_irqsave(&q_ctx->rdy_spinlock, flags); + /* Drop queue, since streamoff returns device to the same state as after + * calling reqbufs. */ + INIT_LIST_HEAD(&q_ctx->rdy_queue); + spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags); + + if (m2m_dev->curr_ctx == m2m_ctx) { + m2m_dev->curr_ctx = NULL; + wake_up(&m2m_ctx->finished); + } + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + + return 0; } EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); |