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: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
ee6869afc9
Коммит
9739768788
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
if (b->memory == V4L2_MEMORY_MMAP)
|
if (b->memory == V4L2_MEMORY_MMAP)
|
||||||
down_read(¤t->mm->mmap_sem);
|
down_read(¤t->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)
|
||||||
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(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
@ -635,14 +635,14 @@ checks:
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
kfree(map);
|
kfree(map);
|
||||||
|
|
||||||
mutex_unlock(&q->vb_lock);
|
videobuf_queue_unlock(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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 {
|
||||||
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче