media: videobuf2-core: release all planes first in __prepare_dmabuf()

In the existing implementation, validating planes, checking if the planes
changed, releasing previous planes and reaquiring new planes all happens in
the same for loop.

Split the for loop into 3 parts
1. In the first for loop, validate planes and check if planes changed.
2. Call __vb2_buf_dmabuf_put() to release all planes.
3. In the second for loop, reaquire new planes.

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:41 +09:00 committed by Hans Verkuil
parent 6a9c97ab6b
commit 95af7c00f3

View File

@ -1387,11 +1387,13 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
for (plane = 0; plane < vb->num_planes; ++plane) { for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd); struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
planes[plane].dbuf = dbuf;
if (IS_ERR_OR_NULL(dbuf)) { if (IS_ERR_OR_NULL(dbuf)) {
dprintk(q, 1, "invalid dmabuf fd for plane %d\n", dprintk(q, 1, "invalid dmabuf fd for plane %d\n",
plane); plane);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_put_planes;
} }
/* use DMABUF size if length is not provided */ /* use DMABUF size if length is not provided */
@ -1402,60 +1404,53 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n", dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n",
planes[plane].length, plane, planes[plane].length, plane,
vb->planes[plane].min_length); vb->planes[plane].min_length);
dma_buf_put(dbuf);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err_put_planes;
} }
/* Skip the plane if already verified */ /* Skip the plane if already verified */
if (dbuf == vb->planes[plane].dbuf && if (dbuf == vb->planes[plane].dbuf &&
vb->planes[plane].length == planes[plane].length) { vb->planes[plane].length == planes[plane].length)
dma_buf_put(dbuf);
continue; continue;
}
dprintk(q, 3, "buffer for plane %d changed\n", plane); dprintk(q, 3, "buffer for plane %d changed\n", plane);
if (!reacquired) {
reacquired = true; reacquired = true;
vb->copied_timestamp = 0;
call_void_vb_qop(vb, buf_cleanup, vb);
} }
/* Release previously acquired memory if present */ if (reacquired) {
__vb2_plane_dmabuf_put(vb, &vb->planes[plane]); if (vb->planes[0].mem_priv) {
vb->copied_timestamp = 0;
call_void_vb_qop(vb, buf_cleanup, vb);
__vb2_buf_dmabuf_put(vb);
}
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Acquire each plane's memory */ /* Acquire each plane's memory */
mem_priv = call_ptr_memop(attach_dmabuf, mem_priv = call_ptr_memop(attach_dmabuf,
vb, vb,
q->alloc_devs[plane] ? : q->dev, q->alloc_devs[plane] ? : q->dev,
dbuf, planes[plane].dbuf,
planes[plane].length); planes[plane].length);
if (IS_ERR(mem_priv)) { if (IS_ERR(mem_priv)) {
dprintk(q, 1, "failed to attach dmabuf\n"); dprintk(q, 1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv); ret = PTR_ERR(mem_priv);
dma_buf_put(dbuf); goto err_put_vb2_buf;
goto err;
} }
vb->planes[plane].dbuf = dbuf; vb->planes[plane].dbuf = planes[plane].dbuf;
vb->planes[plane].mem_priv = mem_priv; vb->planes[plane].mem_priv = mem_priv;
}
/* /*
* This pins the buffer(s) with dma_buf_map_attachment()). It's done * This pins the buffer(s) with dma_buf_map_attachment()). It's done
* here instead just before the DMA, while queueing the buffer(s) so * here instead just before the DMA, while queueing the buffer(s) so
* userspace knows sooner rather than later if the dma-buf map fails. * userspace knows sooner rather than later if the dma-buf map fails.
*/ */
for (plane = 0; plane < vb->num_planes; ++plane) {
if (vb->planes[plane].dbuf_mapped)
continue;
ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv); ret = call_memop(vb, map_dmabuf, vb->planes[plane].mem_priv);
if (ret) { if (ret) {
dprintk(q, 1, "failed to map dmabuf for plane %d\n", dprintk(q, 1, "failed to map dmabuf for plane %d\n",
plane); plane);
goto err; goto err_put_vb2_buf;
} }
vb->planes[plane].dbuf_mapped = 1; vb->planes[plane].dbuf_mapped = 1;
} }
@ -1471,7 +1466,6 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
vb->planes[plane].data_offset = planes[plane].data_offset; vb->planes[plane].data_offset = planes[plane].data_offset;
} }
if (reacquired) {
/* /*
* Call driver-specific initialization on the newly acquired buffer, * Call driver-specific initialization on the newly acquired buffer,
* if provided. * if provided.
@ -1479,19 +1473,28 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
ret = call_vb_qop(vb, buf_init, vb); ret = call_vb_qop(vb, buf_init, vb);
if (ret) { if (ret) {
dprintk(q, 1, "buffer initialization failed\n"); dprintk(q, 1, "buffer initialization failed\n");
goto err; goto err_put_vb2_buf;
} }
} else {
for (plane = 0; plane < vb->num_planes; ++plane)
dma_buf_put(planes[plane].dbuf);
} }
ret = call_vb_qop(vb, buf_prepare, vb); ret = call_vb_qop(vb, buf_prepare, vb);
if (ret) { if (ret) {
dprintk(q, 1, "buffer preparation failed\n"); dprintk(q, 1, "buffer preparation failed\n");
call_void_vb_qop(vb, buf_cleanup, vb); call_void_vb_qop(vb, buf_cleanup, vb);
goto err; goto err_put_vb2_buf;
} }
return 0; return 0;
err:
err_put_planes:
for (plane = 0; plane < vb->num_planes; ++plane) {
if (!IS_ERR_OR_NULL(planes[plane].dbuf))
dma_buf_put(planes[plane].dbuf);
}
err_put_vb2_buf:
/* In case of errors, release planes that were already acquired */ /* In case of errors, release planes that were already acquired */
__vb2_buf_dmabuf_put(vb); __vb2_buf_dmabuf_put(vb);