aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2014-07-17 05:53:08 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-21 23:04:58 -0400
commit8a75ffb81b1c1b6949d191fbef3eaa03fd648852 (patch)
treed490a450f9f24662f8c345b2c0746d1dbaa0542a
parenta54e0fee61a585956b4e9a97ae2605600e5c1c82 (diff)
[media] vb2: fix bytesused == 0 handling
The original report from Nikhil was that if data_offset > 0 and bytesused == 0, then the check in __verify_length() would fail, even though the spec says that if bytes_used == 0, then it will be replaced by the actual length of the buffer. After digging into it a bit more I realized that there were several other things wrong: - in __verify_length() it would use the application-provided length value for USERPTR and the vb2 core length for other memory models, but it should have used the application-provided length as well for DMABUF. - in __fill_vb2_buffer() on the other hand it would replace bytesused == 0 by the application-provided length, even for MMAP buffers where the length is determined by the vb2 core. - in __fill_vb2_buffer() it tries to figure out if all the planes have bytesused == 0 before it will decide to replace bytesused by length. However, the spec makes no such provision, and it makes for convoluted code. So just replace any bytesused == 0 by the proper length. The idea behind this was that you could use bytesused to signal empty planes, something that is currently not supported. But that is better done in the future by using one of the reserved fields in strucy v4l2_plane. This patch fixes all these issues. Regards, Hans Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Reported-by: Nikhil Devshatwar <nikhil.nd@ti.com> Cc: Nikhil Devshatwar <nikhil.nd@ti.com> Acked-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c78
1 files changed, 38 insertions, 40 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index a5c41cc65d1c..f33508f854a4 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -576,6 +576,7 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer
576static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) 576static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
577{ 577{
578 unsigned int length; 578 unsigned int length;
579 unsigned int bytesused;
579 unsigned int plane; 580 unsigned int plane;
580 581
581 if (!V4L2_TYPE_IS_OUTPUT(b->type)) 582 if (!V4L2_TYPE_IS_OUTPUT(b->type))
@@ -583,21 +584,24 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
583 584
584 if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { 585 if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
585 for (plane = 0; plane < vb->num_planes; ++plane) { 586 for (plane = 0; plane < vb->num_planes; ++plane) {
586 length = (b->memory == V4L2_MEMORY_USERPTR) 587 length = (b->memory == V4L2_MEMORY_USERPTR ||
588 b->memory == V4L2_MEMORY_DMABUF)
587 ? b->m.planes[plane].length 589 ? b->m.planes[plane].length
588 : vb->v4l2_planes[plane].length; 590 : vb->v4l2_planes[plane].length;
591 bytesused = b->m.planes[plane].bytesused
592 ? b->m.planes[plane].bytesused : length;
589 593
590 if (b->m.planes[plane].bytesused > length) 594 if (b->m.planes[plane].bytesused > length)
591 return -EINVAL; 595 return -EINVAL;
592 596
593 if (b->m.planes[plane].data_offset > 0 && 597 if (b->m.planes[plane].data_offset > 0 &&
594 b->m.planes[plane].data_offset >= 598 b->m.planes[plane].data_offset >= bytesused)
595 b->m.planes[plane].bytesused)
596 return -EINVAL; 599 return -EINVAL;
597 } 600 }
598 } else { 601 } else {
599 length = (b->memory == V4L2_MEMORY_USERPTR) 602 length = (b->memory == V4L2_MEMORY_USERPTR)
600 ? b->length : vb->v4l2_planes[0].length; 603 ? b->length : vb->v4l2_planes[0].length;
604 bytesused = b->bytesused ? b->bytesused : length;
601 605
602 if (b->bytesused > length) 606 if (b->bytesused > length)
603 return -EINVAL; 607 return -EINVAL;
@@ -1234,35 +1238,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
1234 unsigned int plane; 1238 unsigned int plane;
1235 1239
1236 if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { 1240 if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
1237 /* Fill in driver-provided information for OUTPUT types */
1238 if (V4L2_TYPE_IS_OUTPUT(b->type)) {
1239 bool bytesused_is_used;
1240
1241 /* Check if bytesused == 0 for all planes */
1242 for (plane = 0; plane < vb->num_planes; ++plane)
1243 if (b->m.planes[plane].bytesused)
1244 break;
1245 bytesused_is_used = plane < vb->num_planes;
1246
1247 /*
1248 * Will have to go up to b->length when API starts
1249 * accepting variable number of planes.
1250 *
1251 * If bytesused_is_used is false, then fall back to the
1252 * full buffer size. In that case userspace clearly
1253 * never bothered to set it and it's a safe assumption
1254 * that they really meant to use the full plane sizes.
1255 */
1256 for (plane = 0; plane < vb->num_planes; ++plane) {
1257 struct v4l2_plane *pdst = &v4l2_planes[plane];
1258 struct v4l2_plane *psrc = &b->m.planes[plane];
1259
1260 pdst->bytesused = bytesused_is_used ?
1261 psrc->bytesused : psrc->length;
1262 pdst->data_offset = psrc->data_offset;
1263 }
1264 }
1265
1266 if (b->memory == V4L2_MEMORY_USERPTR) { 1241 if (b->memory == V4L2_MEMORY_USERPTR) {
1267 for (plane = 0; plane < vb->num_planes; ++plane) { 1242 for (plane = 0; plane < vb->num_planes; ++plane) {
1268 v4l2_planes[plane].m.userptr = 1243 v4l2_planes[plane].m.userptr =
@@ -1279,6 +1254,28 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
1279 b->m.planes[plane].length; 1254 b->m.planes[plane].length;
1280 } 1255 }
1281 } 1256 }
1257
1258 /* Fill in driver-provided information for OUTPUT types */
1259 if (V4L2_TYPE_IS_OUTPUT(b->type)) {
1260 /*
1261 * Will have to go up to b->length when API starts
1262 * accepting variable number of planes.
1263 *
1264 * If bytesused == 0 for the output buffer, then fall
1265 * back to the full buffer size. In that case
1266 * userspace clearly never bothered to set it and
1267 * it's a safe assumption that they really meant to
1268 * use the full plane sizes.
1269 */
1270 for (plane = 0; plane < vb->num_planes; ++plane) {
1271 struct v4l2_plane *pdst = &v4l2_planes[plane];
1272 struct v4l2_plane *psrc = &b->m.planes[plane];
1273
1274 pdst->bytesused = psrc->bytesused ?
1275 psrc->bytesused : pdst->length;
1276 pdst->data_offset = psrc->data_offset;
1277 }
1278 }
1282 } else { 1279 } else {
1283 /* 1280 /*
1284 * Single-planar buffers do not use planes array, 1281 * Single-planar buffers do not use planes array,
@@ -1286,15 +1283,9 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
1286 * In videobuf we use our internal V4l2_planes struct for 1283 * In videobuf we use our internal V4l2_planes struct for
1287 * single-planar buffers as well, for simplicity. 1284 * single-planar buffers as well, for simplicity.
1288 * 1285 *
1289 * If bytesused == 0, then fall back to the full buffer size 1286 * If bytesused == 0 for the output buffer, then fall back
1290 * as that's a sensible default. 1287 * to the full buffer size as that's a sensible default.
1291 */ 1288 */
1292 if (V4L2_TYPE_IS_OUTPUT(b->type))
1293 v4l2_planes[0].bytesused =
1294 b->bytesused ? b->bytesused : b->length;
1295 else
1296 v4l2_planes[0].bytesused = 0;
1297
1298 if (b->memory == V4L2_MEMORY_USERPTR) { 1289 if (b->memory == V4L2_MEMORY_USERPTR) {
1299 v4l2_planes[0].m.userptr = b->m.userptr; 1290 v4l2_planes[0].m.userptr = b->m.userptr;
1300 v4l2_planes[0].length = b->length; 1291 v4l2_planes[0].length = b->length;
@@ -1304,6 +1295,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
1304 v4l2_planes[0].m.fd = b->m.fd; 1295 v4l2_planes[0].m.fd = b->m.fd;
1305 v4l2_planes[0].length = b->length; 1296 v4l2_planes[0].length = b->length;
1306 } 1297 }
1298
1299 if (V4L2_TYPE_IS_OUTPUT(b->type))
1300 v4l2_planes[0].bytesused = b->bytesused ?
1301 b->bytesused : v4l2_planes[0].length;
1302 else
1303 v4l2_planes[0].bytesused = 0;
1304
1307 } 1305 }
1308 1306
1309 /* Zero flags that the vb2 core handles */ 1307 /* Zero flags that the vb2 core handles */