summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/media/v4l2-core/v4l2-mem2mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/media/v4l2-core/v4l2-mem2mem.c')
-rw-r--r--kernel/drivers/media/v4l2-core/v4l2-mem2mem.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/kernel/drivers/media/v4l2-core/v4l2-mem2mem.c b/kernel/drivers/media/v4l2-core/v4l2-mem2mem.c
index 73824a5ad..61d56c940 100644
--- a/kernel/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/kernel/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -17,7 +17,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
@@ -357,9 +357,16 @@ int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
struct v4l2_requestbuffers *reqbufs)
{
struct vb2_queue *vq;
+ int ret;
vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type);
- return vb2_reqbufs(vq, reqbufs);
+ ret = vb2_reqbufs(vq, reqbufs);
+ /* If count == 0, then the owner has released all buffers and he
+ is no longer owner of the queue. Otherwise we have an owner. */
+ if (ret == 0)
+ vq->owner = reqbufs->count ? file->private_data : NULL;
+
+ return ret;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
@@ -427,6 +434,25 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
/**
+ * v4l2_m2m_prepare_buf() - prepare a source or destination buffer, depending on
+ * the type
+ */
+int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+ struct v4l2_buffer *buf)
+{
+ struct vb2_queue *vq;
+ int ret;
+
+ vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+ ret = vb2_prepare_buf(vq, buf);
+ if (!ret)
+ v4l2_m2m_try_schedule(m2m_ctx);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
+
+/**
* v4l2_m2m_create_bufs() - create a source or destination buffer, depending
* on the type
*/
@@ -557,24 +583,25 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
goto end;
}
- if (m2m_ctx->m2m_dev->m2m_ops->unlock)
- m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock)
- mutex_unlock(m2m_ctx->q_lock);
-
+ spin_lock_irqsave(&src_q->done_lock, flags);
if (list_empty(&src_q->done_list))
poll_wait(file, &src_q->done_wq, wait);
- if (list_empty(&dst_q->done_list))
- poll_wait(file, &dst_q->done_wq, wait);
+ spin_unlock_irqrestore(&src_q->done_lock, flags);
- if (m2m_ctx->m2m_dev->m2m_ops->lock)
- m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock) {
- if (mutex_lock_interruptible(m2m_ctx->q_lock)) {
- rc |= POLLERR;
- goto end;
+ spin_lock_irqsave(&dst_q->done_lock, flags);
+ if (list_empty(&dst_q->done_list)) {
+ /*
+ * If the last buffer was dequeued from the capture queue,
+ * return immediately. DQBUF will return -EPIPE.
+ */
+ if (dst_q->last_buffer_dequeued) {
+ spin_unlock_irqrestore(&dst_q->done_lock, flags);
+ return rc | POLLIN | POLLRDNORM;
}
+
+ poll_wait(file, &dst_q->done_wq, wait);
}
+ spin_unlock_irqrestore(&dst_q->done_lock, flags);
spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list))
@@ -739,13 +766,15 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release);
*
* Call from buf_queue(), videobuf_queue_ops callback.
*/
-void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
+void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
+ struct vb2_v4l2_buffer *vbuf)
{
- struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
+ struct v4l2_m2m_buffer *b = container_of(vbuf,
+ struct v4l2_m2m_buffer, vb);
struct v4l2_m2m_queue_ctx *q_ctx;
unsigned long flags;
- q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type);
+ q_ctx = get_queue_ctx(m2m_ctx, vbuf->vb2_buf.vb2_queue->type);
if (!q_ctx)
return;
@@ -803,6 +832,15 @@ int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv,
}
EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf);
+int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct v4l2_fh *fh = file->private_data;
+
+ return v4l2_m2m_prepare_buf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_prepare_buf);
+
int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv,
struct v4l2_exportbuffer *eb)
{
@@ -838,18 +876,8 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff);
int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma)
{
struct v4l2_fh *fh = file->private_data;
- struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
- int ret;
-
- if (m2m_ctx->q_lock && mutex_lock_interruptible(m2m_ctx->q_lock))
- return -ERESTARTSYS;
-
- ret = v4l2_m2m_mmap(file, m2m_ctx, vma);
- if (m2m_ctx->q_lock)
- mutex_unlock(m2m_ctx->q_lock);
-
- return ret;
+ return v4l2_m2m_mmap(file, fh->m2m_ctx, vma);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap);