[v4,03/10] media: videobuf2: Rework offset 'cookie' encoding pattern
Commit Message
Change how offset 'cookie' field value is computed to make possible
to use more buffers.
With this encoding pattern we know the maximum number that a queue
could store so we can check ing at queue init time.
It also make easier and faster to find buffer and plane from using
the offset field.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
.../media/common/videobuf2/videobuf2-core.c | 63 +++++++++----------
1 file changed, 29 insertions(+), 34 deletions(-)
@@ -31,6 +31,10 @@
#include <trace/events/vb2.h>
+#define PLANE_INDEX_SHIFT 3
+#define PLANE_INDEX_MASK 0x7
+#define MAX_BUFFERS 0xffff
+
static int debug;
module_param(debug, int, 0644);
@@ -358,29 +362,23 @@ static void __setup_offsets(struct vb2_buffer *vb)
unsigned int plane;
unsigned long off = 0;
- if (vb->index) {
- struct vb2_buffer *prev;
- struct vb2_plane *p;
-
- prev = vb2_get_buffer(q, vb->index - 1);
- if (!prev) {
- dprintk(q, 1, "can't find the requested buffer\n");
- return;
- }
-
- p = &prev->planes[prev->num_planes - 1];
-
- off = PAGE_ALIGN(p->m.offset + p->length);
- }
+ /*
+ * Offsets cookies value have the following constraints:
+ * - a buffer could have up to 8 planes.
+ * - v4l2 mem2mem use bit 30 to distinguish between source and destination buffers.
+ * - must be page aligned
+ * That led to this bit mapping:
+ * |30 |29 15|14 12|11 0|
+ * |DST_QUEUE_OFF_BASE|buffer index|plane index| 0 |
+ * where there is 16 bits to store buffer index.
+ */
+ off = vb->index << (PLANE_INDEX_SHIFT + PAGE_SHIFT);
for (plane = 0; plane < vb->num_planes; ++plane) {
- vb->planes[plane].m.offset = off;
+ vb->planes[plane].m.offset = off + (plane << PAGE_SHIFT);
dprintk(q, 3, "buffer %d, plane %d offset 0x%08lx\n",
vb->index, plane, off);
-
- off += vb->planes[plane].length;
- off = PAGE_ALIGN(off);
}
}
@@ -2294,24 +2292,18 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
return -EBUSY;
}
- /*
- * Go over all buffers and their planes, comparing the given offset
- * with an offset assigned to each plane. If a match is found,
- * return its buffer and plane numbers.
- */
- for (buffer = 0; buffer < q->num_buffers; ++buffer) {
- vb = vb2_get_buffer(q, buffer);
+ /* Get buffer and plane from the offset */
+ buffer = (off >> (PLANE_INDEX_SHIFT + PAGE_SHIFT)) & MAX_BUFFERS;
+ plane = (off >> PAGE_SHIFT) & PLANE_INDEX_MASK;
- if (!vb)
- continue;
+ vb = vb2_get_buffer(q, buffer);
+ if (!vb)
+ return -EINVAL;
- for (plane = 0; plane < vb->num_planes; ++plane) {
- if (vb->planes[plane].m.offset == off) {
- *_buffer = buffer;
- *_plane = plane;
- return 0;
- }
- }
+ if (vb->planes[plane].m.offset == off) {
+ *_buffer = buffer;
+ *_plane = plane;
+ return 0;
}
return -EINVAL;
@@ -2552,6 +2544,9 @@ int vb2_core_queue_init(struct vb2_queue *q)
if (!q->max_allowed_buffers)
q->max_allowed_buffers = VB2_MAX_FRAME;
+ /* The maximum is limited by offset cookie encoding pattern */
+ q->max_allowed_buffers = min_t(unsigned int, q->max_allowed_buffers, MAX_BUFFERS);
+
q->bufs = kcalloc(q->max_allowed_buffers, sizeof(*q->bufs), GFP_KERNEL);
if (q->buf_struct_size == 0)