diff options
author | Benjamin Gaignard <benjamin.gaignard@collabora.com> | 2024-03-14 16:32:22 +0100 |
---|---|---|
committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2024-03-25 12:00:44 +0100 |
commit | a286b0837e1390c558aabebc4f10b25b1f05bdce (patch) | |
tree | 59b319c91e67814ead79c1b78e6ce6a11769729d /drivers/media/common/videobuf2/videobuf2-core.c | |
parent | media: core: Rework how create_buf index returned value is computed (diff) | |
download | linux-a286b0837e1390c558aabebc4f10b25b1f05bdce.tar.xz linux-a286b0837e1390c558aabebc4f10b25b1f05bdce.zip |
media: core: Add bitmap manage bufs array entries
Add a bitmap field to know which of bufs array entries are
used or not.
Remove no more used num_buffers field from queue structure.
Use bitmap_find_next_zero_area() to find the first possible
range when creating new buffers to fill the gaps.
If no suitable range is found try to allocate less buffers
than requested.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Acked-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Diffstat (limited to 'drivers/media/common/videobuf2/videobuf2-core.c')
-rw-r--r-- | drivers/media/common/videobuf2/videobuf2-core.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 8e819d198c34..ec81426d4d79 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -421,11 +421,12 @@ static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb) */ static void vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, unsigned int index) { - WARN_ON(index >= q->max_num_buffers || q->bufs[index] || vb->vb2_queue); + WARN_ON(index >= q->max_num_buffers || test_bit(index, q->bufs_bitmap) || vb->vb2_queue); q->bufs[index] = vb; vb->index = index; vb->vb2_queue = q; + set_bit(index, q->bufs_bitmap); } /** @@ -434,6 +435,7 @@ static void vb2_queue_add_buffer(struct vb2_queue *q, struct vb2_buffer *vb, uns */ static void vb2_queue_remove_buffer(struct vb2_buffer *vb) { + clear_bit(vb->index, vb->vb2_queue->bufs_bitmap); vb->vb2_queue->bufs[vb->index] = NULL; vb->vb2_queue = NULL; } @@ -452,9 +454,9 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, const unsigned int plane_sizes[VB2_MAX_PLANES], unsigned int *first_index) { - unsigned int q_num_buffers = vb2_get_num_buffers(q); unsigned int buffer, plane; struct vb2_buffer *vb; + unsigned long index = q->max_num_buffers; int ret; /* @@ -462,9 +464,25 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, * in the queue is below q->max_num_buffers */ num_buffers = min_t(unsigned int, num_buffers, - q->max_num_buffers - q_num_buffers); + q->max_num_buffers - vb2_get_num_buffers(q)); + + while (num_buffers) { + index = bitmap_find_next_zero_area(q->bufs_bitmap, q->max_num_buffers, + 0, num_buffers, 0); + + if (index < q->max_num_buffers) + break; + /* Try to find free space for less buffers */ + num_buffers--; + } + + /* If there is no space left to allocate buffers return 0 to indicate the error */ + if (!num_buffers) { + *first_index = 0; + return 0; + } - *first_index = q_num_buffers; + *first_index = index; for (buffer = 0; buffer < num_buffers; ++buffer) { /* Allocate vb2 buffer structures */ @@ -484,7 +502,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory, vb->planes[plane].min_length = plane_sizes[plane]; } - vb2_queue_add_buffer(q, vb, q_num_buffers + buffer); + vb2_queue_add_buffer(q, vb, index++); call_void_bufop(q, init_buffer, vb); /* Allocate video buffer memory for the MMAP type */ @@ -664,7 +682,6 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) kfree(vb); } - q->num_buffers -= buffers; if (!vb2_get_num_buffers(q)) { q->memory = VB2_MEMORY_UNKNOWN; INIT_LIST_HEAD(&q->queued_list); @@ -818,6 +835,32 @@ static bool verify_coherency_flags(struct vb2_queue *q, bool non_coherent_mem) return true; } +static int vb2_core_allocated_buffers_storage(struct vb2_queue *q) +{ + if (!q->bufs) + q->bufs = kcalloc(q->max_num_buffers, sizeof(*q->bufs), GFP_KERNEL); + if (!q->bufs) + return -ENOMEM; + + if (!q->bufs_bitmap) + q->bufs_bitmap = bitmap_zalloc(q->max_num_buffers, GFP_KERNEL); + if (!q->bufs_bitmap) { + kfree(q->bufs); + q->bufs = NULL; + return -ENOMEM; + } + + return 0; +} + +static void vb2_core_free_buffers_storage(struct vb2_queue *q) +{ + kfree(q->bufs); + q->bufs = NULL; + bitmap_free(q->bufs_bitmap); + q->bufs_bitmap = NULL; +} + int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, unsigned int flags, unsigned int *count) { @@ -879,10 +922,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, * in the queue_setup op. */ mutex_lock(&q->mmap_lock); - if (!q->bufs) - q->bufs = kcalloc(q->max_num_buffers, sizeof(*q->bufs), GFP_KERNEL); - if (!q->bufs) - ret = -ENOMEM; + ret = vb2_core_allocated_buffers_storage(q); q->memory = memory; mutex_unlock(&q->mmap_lock); if (ret) @@ -954,7 +994,6 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, } mutex_lock(&q->mmap_lock); - q->num_buffers = allocated_buffers; if (ret < 0) { /* @@ -982,6 +1021,7 @@ error: mutex_lock(&q->mmap_lock); q->memory = VB2_MEMORY_UNKNOWN; mutex_unlock(&q->mmap_lock); + vb2_core_free_buffers_storage(q); return ret; } EXPORT_SYMBOL_GPL(vb2_core_reqbufs); @@ -1015,11 +1055,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, * value in the queue_setup op. */ mutex_lock(&q->mmap_lock); + ret = vb2_core_allocated_buffers_storage(q); q->memory = memory; - if (!q->bufs) - q->bufs = kcalloc(q->max_num_buffers, sizeof(*q->bufs), GFP_KERNEL); - if (!q->bufs) - ret = -ENOMEM; mutex_unlock(&q->mmap_lock); if (ret) return ret; @@ -1082,7 +1119,6 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, } mutex_lock(&q->mmap_lock); - q->num_buffers += allocated_buffers; if (ret < 0) { /* @@ -2583,8 +2619,7 @@ void vb2_core_queue_release(struct vb2_queue *q) __vb2_queue_cancel(q); mutex_lock(&q->mmap_lock); __vb2_queue_free(q, vb2_get_num_buffers(q)); - kfree(q->bufs); - q->bufs = NULL; + vb2_core_free_buffers_storage(q); q->is_busy = 0; mutex_unlock(&q->mmap_lock); } |