Instead of a static array change bufs to a dynamically allocated array. This will allow to store more video buffer if needed. Protect the array with a spinlock. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@xxxxxxxxxxxxx> --- .../media/common/videobuf2/videobuf2-core.c | 8 +++ include/media/videobuf2-core.h | 49 ++++++++++++++++--- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 79e90e338846..ae9d72f4d181 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -2452,6 +2452,13 @@ int vb2_core_queue_init(struct vb2_queue *q) mutex_init(&q->mmap_lock); init_waitqueue_head(&q->done_wq); + q->max_num_bufs = 32; + q->bufs = kmalloc_array(q->max_num_bufs, sizeof(*q->bufs), GFP_KERNEL | __GFP_ZERO); + if (!q->bufs) + return -ENOMEM; + + spin_lock_init(&q->bufs_lock); + q->memory = VB2_MEMORY_UNKNOWN; if (q->buf_struct_size == 0) @@ -2479,6 +2486,7 @@ void vb2_core_queue_release(struct vb2_queue *q) mutex_lock(&q->mmap_lock); __vb2_queue_free(q, q->num_buffers); mutex_unlock(&q->mmap_lock); + kfree(q->bufs); } EXPORT_SYMBOL_GPL(vb2_core_queue_release); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 5b1e3d801546..397dbf6e61e1 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -558,6 +558,8 @@ struct vb2_buf_ops { * @dma_dir: DMA mapping direction. * @bufs: videobuf2 buffer structures * @num_buffers: number of allocated/used buffers + * @bufs_lock: lock to protect bufs access + * @max_num_bufs: max number of buffers storable in bufs * @queued_list: list of buffers currently queued from userspace * @queued_count: number of buffers queued and ready for streaming. * @owned_by_drv_count: number of buffers owned by the driver @@ -619,8 +621,10 @@ struct vb2_queue { struct mutex mmap_lock; unsigned int memory; enum dma_data_direction dma_dir; - struct vb2_buffer *bufs[VB2_MAX_FRAME]; + struct vb2_buffer **bufs; unsigned int num_buffers; + spinlock_t bufs_lock; + size_t max_num_bufs; struct list_head queued_list; unsigned int queued_count; @@ -1239,9 +1243,16 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q) static inline struct vb2_buffer *vb2_get_buffer(struct vb2_queue *q, unsigned int index) { - if (index < q->num_buffers) - return q->bufs[index]; - return NULL; + struct vb2_buffer *vb = NULL; + + spin_lock(&q->bufs_lock); + + if (index < q->max_num_bufs) + vb = q->bufs[index]; + + spin_unlock(&q->bufs_lock); + + return vb; } /** @@ -1251,12 +1262,30 @@ static inline struct vb2_buffer *vb2_get_buffer(struct vb2_queue *q, */ static inline bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb) { - if (vb->index < VB2_MAX_FRAME) { + bool ret = false; + + spin_lock(&q->bufs_lock); + + if (vb->index >= q->max_num_bufs) { + struct vb2_buffer **tmp; + + tmp = krealloc_array(q->bufs, q->max_num_bufs * 2, sizeof(*q->bufs), GFP_KERNEL); + if (!tmp) + goto realloc_failed; + + q->max_num_bufs *= 2; + q->bufs = tmp; + } + + if (vb->index < q->max_num_bufs) { q->bufs[vb->index] = vb; - return true; + ret = true; } - return false; +realloc_failed: + spin_unlock(&q->bufs_lock); + + return ret; } /** @@ -1266,8 +1295,12 @@ static inline bool vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer * */ static inline void vb2_queue_remove_buffer(struct vb2_queue *q, struct vb2_buffer *vb) { - if (vb->index < VB2_MAX_FRAME) + spin_lock(&q->bufs_lock); + + if (vb->index < q->max_num_bufs) q->bufs[vb->index] = NULL; + + spin_unlock(&q->bufs_lock); } /* -- 2.34.1