media: videobuf2-core: attach once if multiple planes share the same dbuf

When multiple planes use the same dma buf, each plane will have its own dma
buf attachment and mapping. It is a waste of IOVA space.

This patch adds a dbuf_duplicated boolean in vb2_plane. If a plane's dbuf
is the same as an existing plane, do not create another attachment and
mapping.

Signed-off-by: Yunke Cao <yunkec@chromium.org>
Acked-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
Yunke Cao 2024-08-14 11:06:43 +09:00 committed by Hans Verkuil
parent 1da4e16130
commit 03a979b74d
2 changed files with 29 additions and 4 deletions

View File

@ -303,10 +303,13 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
if (!p->mem_priv)
return;
if (p->dbuf_mapped)
call_void_memop(vb, unmap_dmabuf, p->mem_priv);
if (!p->dbuf_duplicated) {
if (p->dbuf_mapped)
call_void_memop(vb, unmap_dmabuf, p->mem_priv);
call_void_memop(vb, detach_dmabuf, p->mem_priv);
}
call_void_memop(vb, detach_dmabuf, p->mem_priv);
dma_buf_put(p->dbuf);
p->mem_priv = NULL;
p->dbuf = NULL;
@ -315,6 +318,7 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
p->length = 0;
p->m.fd = 0;
p->data_offset = 0;
p->dbuf_duplicated = false;
}
/*
@ -1379,7 +1383,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
void *mem_priv;
unsigned int plane;
unsigned int plane, i;
int ret = 0;
bool reacquired = vb->planes[0].mem_priv == NULL;
@ -1432,6 +1436,24 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
}
for (plane = 0; plane < vb->num_planes; ++plane) {
/*
* This is an optimization to reduce dma_buf attachment/mapping.
* When the same dma_buf is used for multiple planes, there is no need
* to create duplicated attachments.
*/
for (i = 0; i < plane; ++i) {
if (planes[plane].dbuf == vb->planes[i].dbuf &&
q->alloc_devs[plane] == q->alloc_devs[i]) {
vb->planes[plane].dbuf_duplicated = true;
vb->planes[plane].dbuf = vb->planes[i].dbuf;
vb->planes[plane].mem_priv = vb->planes[i].mem_priv;
break;
}
}
if (vb->planes[plane].dbuf_duplicated)
continue;
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(attach_dmabuf,
vb,

View File

@ -154,6 +154,8 @@ struct vb2_mem_ops {
* @mem_priv: private data with this plane.
* @dbuf: dma_buf - shared buffer object.
* @dbuf_mapped: flag to show whether dbuf is mapped or not
* @dbuf_duplicated: boolean to show whether dbuf is duplicated with a
* previous plane of the buffer.
* @bytesused: number of bytes occupied by data in the plane (payload).
* @length: size of this plane (NOT the payload) in bytes. The maximum
* valid size is MAX_UINT - PAGE_SIZE.
@ -179,6 +181,7 @@ struct vb2_plane {
void *mem_priv;
struct dma_buf *dbuf;
unsigned int dbuf_mapped;
bool dbuf_duplicated;
unsigned int bytesused;
unsigned int length;
unsigned int min_length;