|
@@ -377,8 +377,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
|
|
/* Call driver-provided cleanup function for each buffer, if provided */
|
|
/* Call driver-provided cleanup function for each buffer, if provided */
|
|
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
|
|
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
|
|
++buffer) {
|
|
++buffer) {
|
|
- if (q->bufs[buffer])
|
|
|
|
- call_vb_qop(q->bufs[buffer], buf_cleanup, q->bufs[buffer]);
|
|
|
|
|
|
+ struct vb2_buffer *vb = q->bufs[buffer];
|
|
|
|
+
|
|
|
|
+ if (vb && vb->planes[0].mem_priv)
|
|
|
|
+ call_vb_qop(vb, buf_cleanup, vb);
|
|
}
|
|
}
|
|
|
|
|
|
/* Release video buffer memory */
|
|
/* Release video buffer memory */
|
|
@@ -1196,6 +1198,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
unsigned int plane;
|
|
unsigned int plane;
|
|
int ret;
|
|
int ret;
|
|
int write = !V4L2_TYPE_IS_OUTPUT(q->type);
|
|
int write = !V4L2_TYPE_IS_OUTPUT(q->type);
|
|
|
|
+ bool reacquired = vb->planes[0].mem_priv == NULL;
|
|
|
|
|
|
/* Copy relevant information provided by the userspace */
|
|
/* Copy relevant information provided by the userspace */
|
|
__fill_vb2_buffer(vb, b, planes);
|
|
__fill_vb2_buffer(vb, b, planes);
|
|
@@ -1221,12 +1224,16 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
}
|
|
}
|
|
|
|
|
|
/* Release previously acquired memory if present */
|
|
/* Release previously acquired memory if present */
|
|
- if (vb->planes[plane].mem_priv)
|
|
|
|
|
|
+ if (vb->planes[plane].mem_priv) {
|
|
|
|
+ if (!reacquired) {
|
|
|
|
+ reacquired = true;
|
|
|
|
+ call_vb_qop(vb, buf_cleanup, vb);
|
|
|
|
+ }
|
|
call_memop(vb, put_userptr, vb->planes[plane].mem_priv);
|
|
call_memop(vb, put_userptr, vb->planes[plane].mem_priv);
|
|
|
|
+ }
|
|
|
|
|
|
vb->planes[plane].mem_priv = NULL;
|
|
vb->planes[plane].mem_priv = NULL;
|
|
- vb->v4l2_planes[plane].m.userptr = 0;
|
|
|
|
- vb->v4l2_planes[plane].length = 0;
|
|
|
|
|
|
+ memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
|
|
|
|
|
|
/* Acquire each plane's memory */
|
|
/* Acquire each plane's memory */
|
|
mem_priv = call_memop(vb, get_userptr, q->alloc_ctx[plane],
|
|
mem_priv = call_memop(vb, get_userptr, q->alloc_ctx[plane],
|
|
@@ -1242,17 +1249,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
vb->planes[plane].mem_priv = mem_priv;
|
|
vb->planes[plane].mem_priv = mem_priv;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Call driver-specific initialization on the newly acquired buffer,
|
|
|
|
- * if provided.
|
|
|
|
- */
|
|
|
|
- ret = call_vb_qop(vb, buf_init, vb);
|
|
|
|
- if (ret) {
|
|
|
|
- dprintk(1, "qbuf: buffer initialization failed\n");
|
|
|
|
- fail_vb_qop(vb, buf_init);
|
|
|
|
- goto err;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Now that everything is in order, copy relevant information
|
|
* Now that everything is in order, copy relevant information
|
|
* provided by userspace.
|
|
* provided by userspace.
|
|
@@ -1260,6 +1256,28 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
for (plane = 0; plane < vb->num_planes; ++plane)
|
|
for (plane = 0; plane < vb->num_planes; ++plane)
|
|
vb->v4l2_planes[plane] = planes[plane];
|
|
vb->v4l2_planes[plane] = planes[plane];
|
|
|
|
|
|
|
|
+ if (reacquired) {
|
|
|
|
+ /*
|
|
|
|
+ * One or more planes changed, so we must call buf_init to do
|
|
|
|
+ * the driver-specific initialization on the newly acquired
|
|
|
|
+ * buffer, if provided.
|
|
|
|
+ */
|
|
|
|
+ ret = call_vb_qop(vb, buf_init, vb);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dprintk(1, "qbuf: buffer initialization failed\n");
|
|
|
|
+ fail_vb_qop(vb, buf_init);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = call_vb_qop(vb, buf_prepare, vb);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dprintk(1, "qbuf: buffer preparation failed\n");
|
|
|
|
+ fail_vb_qop(vb, buf_prepare);
|
|
|
|
+ call_vb_qop(vb, buf_cleanup, vb);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
err:
|
|
err:
|
|
/* In case of errors, release planes that were already acquired */
|
|
/* In case of errors, release planes that were already acquired */
|
|
@@ -1279,8 +1297,13 @@ err:
|
|
*/
|
|
*/
|
|
static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
{
|
|
{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
__fill_vb2_buffer(vb, b, vb->v4l2_planes);
|
|
__fill_vb2_buffer(vb, b, vb->v4l2_planes);
|
|
- return 0;
|
|
|
|
|
|
+ ret = call_vb_qop(vb, buf_prepare, vb);
|
|
|
|
+ if (ret)
|
|
|
|
+ fail_vb_qop(vb, buf_prepare);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1294,6 +1317,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
unsigned int plane;
|
|
unsigned int plane;
|
|
int ret;
|
|
int ret;
|
|
int write = !V4L2_TYPE_IS_OUTPUT(q->type);
|
|
int write = !V4L2_TYPE_IS_OUTPUT(q->type);
|
|
|
|
+ bool reacquired = vb->planes[0].mem_priv == NULL;
|
|
|
|
|
|
/* Copy relevant information provided by the userspace */
|
|
/* Copy relevant information provided by the userspace */
|
|
__fill_vb2_buffer(vb, b, planes);
|
|
__fill_vb2_buffer(vb, b, planes);
|
|
@@ -1329,6 +1353,11 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
|
|
|
|
dprintk(1, "qbuf: buffer for plane %d changed\n", plane);
|
|
dprintk(1, "qbuf: buffer for plane %d changed\n", plane);
|
|
|
|
|
|
|
|
+ if (!reacquired) {
|
|
|
|
+ reacquired = true;
|
|
|
|
+ call_vb_qop(vb, buf_cleanup, vb);
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Release previously acquired memory if present */
|
|
/* Release previously acquired memory if present */
|
|
__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
|
|
__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
|
|
memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
|
|
memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
|
|
@@ -1363,17 +1392,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
vb->planes[plane].dbuf_mapped = 1;
|
|
vb->planes[plane].dbuf_mapped = 1;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Call driver-specific initialization on the newly acquired buffer,
|
|
|
|
- * if provided.
|
|
|
|
- */
|
|
|
|
- ret = call_vb_qop(vb, buf_init, vb);
|
|
|
|
- if (ret) {
|
|
|
|
- dprintk(1, "qbuf: buffer initialization failed\n");
|
|
|
|
- fail_vb_qop(vb, buf_init);
|
|
|
|
- goto err;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Now that everything is in order, copy relevant information
|
|
* Now that everything is in order, copy relevant information
|
|
* provided by userspace.
|
|
* provided by userspace.
|
|
@@ -1381,6 +1399,27 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
for (plane = 0; plane < vb->num_planes; ++plane)
|
|
for (plane = 0; plane < vb->num_planes; ++plane)
|
|
vb->v4l2_planes[plane] = planes[plane];
|
|
vb->v4l2_planes[plane] = planes[plane];
|
|
|
|
|
|
|
|
+ if (reacquired) {
|
|
|
|
+ /*
|
|
|
|
+ * Call driver-specific initialization on the newly acquired buffer,
|
|
|
|
+ * if provided.
|
|
|
|
+ */
|
|
|
|
+ ret = call_vb_qop(vb, buf_init, vb);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dprintk(1, "qbuf: buffer initialization failed\n");
|
|
|
|
+ fail_vb_qop(vb, buf_init);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = call_vb_qop(vb, buf_prepare, vb);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dprintk(1, "qbuf: buffer preparation failed\n");
|
|
|
|
+ fail_vb_qop(vb, buf_prepare);
|
|
|
|
+ call_vb_qop(vb, buf_cleanup, vb);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
err:
|
|
err:
|
|
/* In case of errors, release planes that were already acquired */
|
|
/* In case of errors, release planes that were already acquired */
|
|
@@ -1459,11 +1498,6 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!ret) {
|
|
|
|
- ret = call_vb_qop(vb, buf_prepare, vb);
|
|
|
|
- if (ret)
|
|
|
|
- fail_vb_qop(vb, buf_prepare);
|
|
|
|
- }
|
|
|
|
if (ret)
|
|
if (ret)
|
|
dprintk(1, "qbuf: buffer preparation failed: %d\n", ret);
|
|
dprintk(1, "qbuf: buffer preparation failed: %d\n", ret);
|
|
vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED;
|
|
vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED;
|