Commit 97397687 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB: videobuf: prepare to make locking optional in videobuf

Currently videobuf uses the vb_lock mutex to lock its data structures.
But this locking will (optionally) move into the v4l2 core, which means
that in that case vb_lock shouldn't be used since the external lock is already
held.

Prepare for this by adding a pointer to such an external mutex and
don't lock if that pointer is set.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ee6869af
...@@ -421,8 +421,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, ...@@ -421,8 +421,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
src_q = v4l2_m2m_get_src_vq(m2m_ctx); src_q = v4l2_m2m_get_src_vq(m2m_ctx);
dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
mutex_lock(&src_q->vb_lock); videobuf_queue_lock(src_q);
mutex_lock(&dst_q->vb_lock); videobuf_queue_lock(dst_q);
if (src_q->streaming && !list_empty(&src_q->stream)) if (src_q->streaming && !list_empty(&src_q->stream))
src_vb = list_first_entry(&src_q->stream, src_vb = list_first_entry(&src_q->stream,
...@@ -450,8 +450,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, ...@@ -450,8 +450,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
} }
end: end:
mutex_unlock(&dst_q->vb_lock); videobuf_queue_unlock(dst_q);
mutex_unlock(&src_q->vb_lock); videobuf_queue_unlock(src_q);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(v4l2_m2m_poll); EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
......
...@@ -350,9 +350,9 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, ...@@ -350,9 +350,9 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
int videobuf_mmap_free(struct videobuf_queue *q) int videobuf_mmap_free(struct videobuf_queue *q)
{ {
int ret; int ret;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
ret = __videobuf_free(q); ret = __videobuf_free(q);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(videobuf_mmap_free); EXPORT_SYMBOL_GPL(videobuf_mmap_free);
...@@ -407,9 +407,9 @@ int videobuf_mmap_setup(struct videobuf_queue *q, ...@@ -407,9 +407,9 @@ int videobuf_mmap_setup(struct videobuf_queue *q,
enum v4l2_memory memory) enum v4l2_memory memory)
{ {
int ret; int ret;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
ret = __videobuf_mmap_setup(q, bcount, bsize, memory); ret = __videobuf_mmap_setup(q, bcount, bsize, memory);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(videobuf_mmap_setup); EXPORT_SYMBOL_GPL(videobuf_mmap_setup);
...@@ -432,7 +432,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, ...@@ -432,7 +432,7 @@ int videobuf_reqbufs(struct videobuf_queue *q,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
if (req->type != q->type) { if (req->type != q->type) {
dprintk(1, "reqbufs: queue type invalid\n"); dprintk(1, "reqbufs: queue type invalid\n");
retval = -EINVAL; retval = -EINVAL;
...@@ -469,7 +469,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, ...@@ -469,7 +469,7 @@ int videobuf_reqbufs(struct videobuf_queue *q,
retval = 0; retval = 0;
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(videobuf_reqbufs); EXPORT_SYMBOL_GPL(videobuf_reqbufs);
...@@ -478,7 +478,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) ...@@ -478,7 +478,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{ {
int ret = -EINVAL; int ret = -EINVAL;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
if (unlikely(b->type != q->type)) { if (unlikely(b->type != q->type)) {
dprintk(1, "querybuf: Wrong type.\n"); dprintk(1, "querybuf: Wrong type.\n");
goto done; goto done;
...@@ -496,7 +496,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) ...@@ -496,7 +496,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
ret = 0; ret = 0;
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(videobuf_querybuf); EXPORT_SYMBOL_GPL(videobuf_querybuf);
...@@ -513,7 +513,7 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) ...@@ -513,7 +513,7 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
if (b->memory == V4L2_MEMORY_MMAP) if (b->memory == V4L2_MEMORY_MMAP)
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
retval = -EBUSY; retval = -EBUSY;
if (q->reading) { if (q->reading) {
dprintk(1, "qbuf: Reading running...\n"); dprintk(1, "qbuf: Reading running...\n");
...@@ -605,7 +605,7 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) ...@@ -605,7 +605,7 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
wake_up_interruptible_sync(&q->wait); wake_up_interruptible_sync(&q->wait);
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
if (b->memory == V4L2_MEMORY_MMAP) if (b->memory == V4L2_MEMORY_MMAP)
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
...@@ -635,14 +635,14 @@ static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) ...@@ -635,14 +635,14 @@ static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
dprintk(2, "next_buffer: waiting on buffer\n"); dprintk(2, "next_buffer: waiting on buffer\n");
/* Drop lock to avoid deadlock with qbuf */ /* Drop lock to avoid deadlock with qbuf */
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
/* Checking list_empty and streaming is safe without /* Checking list_empty and streaming is safe without
* locks because we goto checks to validate while * locks because we goto checks to validate while
* holding locks before proceeding */ * holding locks before proceeding */
retval = wait_event_interruptible(q->wait, retval = wait_event_interruptible(q->wait,
!list_empty(&q->stream) || !q->streaming); !list_empty(&q->stream) || !q->streaming);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
if (retval) if (retval)
goto done; goto done;
...@@ -687,7 +687,7 @@ int videobuf_dqbuf(struct videobuf_queue *q, ...@@ -687,7 +687,7 @@ int videobuf_dqbuf(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
memset(b, 0, sizeof(*b)); memset(b, 0, sizeof(*b));
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
retval = stream_next_buffer(q, &buf, nonblocking); retval = stream_next_buffer(q, &buf, nonblocking);
if (retval < 0) { if (retval < 0) {
...@@ -713,7 +713,7 @@ int videobuf_dqbuf(struct videobuf_queue *q, ...@@ -713,7 +713,7 @@ int videobuf_dqbuf(struct videobuf_queue *q,
buf->state = VIDEOBUF_IDLE; buf->state = VIDEOBUF_IDLE;
b->flags &= ~V4L2_BUF_FLAG_DONE; b->flags &= ~V4L2_BUF_FLAG_DONE;
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(videobuf_dqbuf); EXPORT_SYMBOL_GPL(videobuf_dqbuf);
...@@ -724,7 +724,7 @@ int videobuf_streamon(struct videobuf_queue *q) ...@@ -724,7 +724,7 @@ int videobuf_streamon(struct videobuf_queue *q)
unsigned long flags = 0; unsigned long flags = 0;
int retval; int retval;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
retval = -EBUSY; retval = -EBUSY;
if (q->reading) if (q->reading)
goto done; goto done;
...@@ -740,7 +740,7 @@ int videobuf_streamon(struct videobuf_queue *q) ...@@ -740,7 +740,7 @@ int videobuf_streamon(struct videobuf_queue *q)
wake_up_interruptible_sync(&q->wait); wake_up_interruptible_sync(&q->wait);
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(videobuf_streamon); EXPORT_SYMBOL_GPL(videobuf_streamon);
...@@ -760,9 +760,9 @@ int videobuf_streamoff(struct videobuf_queue *q) ...@@ -760,9 +760,9 @@ int videobuf_streamoff(struct videobuf_queue *q)
{ {
int retval; int retval;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
retval = __videobuf_streamoff(q); retval = __videobuf_streamoff(q);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
...@@ -868,7 +868,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, ...@@ -868,7 +868,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
q->ops->buf_setup(q, &nbufs, &size); q->ops->buf_setup(q, &nbufs, &size);
...@@ -938,7 +938,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, ...@@ -938,7 +938,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
} }
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(videobuf_read_one); EXPORT_SYMBOL_GPL(videobuf_read_one);
...@@ -999,9 +999,9 @@ int videobuf_read_start(struct videobuf_queue *q) ...@@ -999,9 +999,9 @@ int videobuf_read_start(struct videobuf_queue *q)
{ {
int rc; int rc;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
rc = __videobuf_read_start(q); rc = __videobuf_read_start(q);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return rc; return rc;
} }
...@@ -1009,15 +1009,15 @@ EXPORT_SYMBOL_GPL(videobuf_read_start); ...@@ -1009,15 +1009,15 @@ EXPORT_SYMBOL_GPL(videobuf_read_start);
void videobuf_read_stop(struct videobuf_queue *q) void videobuf_read_stop(struct videobuf_queue *q)
{ {
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
__videobuf_read_stop(q); __videobuf_read_stop(q);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
} }
EXPORT_SYMBOL_GPL(videobuf_read_stop); EXPORT_SYMBOL_GPL(videobuf_read_stop);
void videobuf_stop(struct videobuf_queue *q) void videobuf_stop(struct videobuf_queue *q)
{ {
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
if (q->streaming) if (q->streaming)
__videobuf_streamoff(q); __videobuf_streamoff(q);
...@@ -1025,7 +1025,7 @@ void videobuf_stop(struct videobuf_queue *q) ...@@ -1025,7 +1025,7 @@ void videobuf_stop(struct videobuf_queue *q)
if (q->reading) if (q->reading)
__videobuf_read_stop(q); __videobuf_read_stop(q);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
} }
EXPORT_SYMBOL_GPL(videobuf_stop); EXPORT_SYMBOL_GPL(videobuf_stop);
...@@ -1039,7 +1039,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, ...@@ -1039,7 +1039,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
dprintk(2, "%s\n", __func__); dprintk(2, "%s\n", __func__);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
retval = -EBUSY; retval = -EBUSY;
if (q->streaming) if (q->streaming)
goto done; goto done;
...@@ -1097,7 +1097,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, ...@@ -1097,7 +1097,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
} }
done: done:
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(videobuf_read_stream); EXPORT_SYMBOL_GPL(videobuf_read_stream);
...@@ -1109,7 +1109,7 @@ unsigned int videobuf_poll_stream(struct file *file, ...@@ -1109,7 +1109,7 @@ unsigned int videobuf_poll_stream(struct file *file,
struct videobuf_buffer *buf = NULL; struct videobuf_buffer *buf = NULL;
unsigned int rc = 0; unsigned int rc = 0;
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
if (q->streaming) { if (q->streaming) {
if (!list_empty(&q->stream)) if (!list_empty(&q->stream))
buf = list_entry(q->stream.next, buf = list_entry(q->stream.next,
...@@ -1147,7 +1147,7 @@ unsigned int videobuf_poll_stream(struct file *file, ...@@ -1147,7 +1147,7 @@ unsigned int videobuf_poll_stream(struct file *file,
} }
} }
} }
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(videobuf_poll_stream); EXPORT_SYMBOL_GPL(videobuf_poll_stream);
...@@ -1164,7 +1164,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) ...@@ -1164,7 +1164,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma)
return -EINVAL; return -EINVAL;
} }
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
for (i = 0; i < VIDEO_MAX_FRAME; i++) { for (i = 0; i < VIDEO_MAX_FRAME; i++) {
struct videobuf_buffer *buf = q->bufs[i]; struct videobuf_buffer *buf = q->bufs[i];
...@@ -1174,7 +1174,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) ...@@ -1174,7 +1174,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma)
break; break;
} }
} }
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
return rc; return rc;
} }
......
...@@ -63,7 +63,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -63,7 +63,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
struct videobuf_dma_contig_memory *mem; struct videobuf_dma_contig_memory *mem;
dev_dbg(q->dev, "munmap %p q=%p\n", map, q); dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
/* We need first to cancel streams, before unmapping */ /* We need first to cancel streams, before unmapping */
if (q->streaming) if (q->streaming)
...@@ -103,7 +103,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -103,7 +103,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
kfree(map); kfree(map);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
} }
} }
......
...@@ -358,7 +358,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -358,7 +358,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
map->count--; map->count--;
if (0 == map->count) { if (0 == map->count) {
dprintk(1, "munmap %p q=%p\n", map, q); dprintk(1, "munmap %p q=%p\n", map, q);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
for (i = 0; i < VIDEO_MAX_FRAME; i++) { for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i]) if (NULL == q->bufs[i])
continue; continue;
...@@ -374,7 +374,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -374,7 +374,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
q->bufs[i]->baddr = 0; q->bufs[i]->baddr = 0;
q->ops->buf_release(q, q->bufs[i]); q->ops->buf_release(q, q->bufs[i]);
} }
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
kfree(map); kfree(map);
} }
return; return;
......
...@@ -75,7 +75,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -75,7 +75,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
struct videobuf_vmalloc_memory *mem; struct videobuf_vmalloc_memory *mem;
dprintk(1, "munmap %p q=%p\n", map, q); dprintk(1, "munmap %p q=%p\n", map, q);
mutex_lock(&q->vb_lock); videobuf_queue_lock(q);
/* We need first to cancel streams, before unmapping */ /* We need first to cancel streams, before unmapping */
if (q->streaming) if (q->streaming)
...@@ -114,7 +114,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) ...@@ -114,7 +114,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
kfree(map); kfree(map);
mutex_unlock(&q->vb_lock); videobuf_queue_unlock(q);
} }
return; return;
......
...@@ -139,6 +139,7 @@ struct videobuf_qtype_ops { ...@@ -139,6 +139,7 @@ struct videobuf_qtype_ops {
struct videobuf_queue { struct videobuf_queue {
struct mutex vb_lock; struct mutex vb_lock;
struct mutex *ext_lock;
spinlock_t *irqlock; spinlock_t *irqlock;
struct device *dev; struct device *dev;
...@@ -167,6 +168,18 @@ struct videobuf_queue { ...@@ -167,6 +168,18 @@ struct videobuf_queue {
void *priv_data; void *priv_data;
}; };
static inline void videobuf_queue_lock(struct videobuf_queue *q)
{
if (!q->ext_lock)
mutex_lock(&q->vb_lock);
}
static inline void videobuf_queue_unlock(struct videobuf_queue *q)
{
if (!q->ext_lock)
mutex_unlock(&q->vb_lock);
}
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf); struct v4l2_framebuffer *fbuf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment