diff options
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c | 100 |
1 files changed, 67 insertions, 33 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 16ae66f5584f..6c33b788ecd7 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -377,8 +377,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) | |||
377 | /* Call driver-provided cleanup function for each buffer, if provided */ | 377 | /* Call driver-provided cleanup function for each buffer, if provided */ |
378 | for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; | 378 | for (buffer = q->num_buffers - buffers; buffer < q->num_buffers; |
379 | ++buffer) { | 379 | ++buffer) { |
380 | if (q->bufs[buffer]) | 380 | struct vb2_buffer *vb = q->bufs[buffer]; |
381 | call_vb_qop(q->bufs[buffer], buf_cleanup, q->bufs[buffer]); | 381 | |
382 | if (vb && vb->planes[0].mem_priv) | ||
383 | call_vb_qop(vb, buf_cleanup, vb); | ||
382 | } | 384 | } |
383 | 385 | ||
384 | /* Release video buffer memory */ | 386 | /* Release video buffer memory */ |
@@ -1196,6 +1198,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1196 | unsigned int plane; | 1198 | unsigned int plane; |
1197 | int ret; | 1199 | int ret; |
1198 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); | 1200 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); |
1201 | bool reacquired = vb->planes[0].mem_priv == NULL; | ||
1199 | 1202 | ||
1200 | /* Copy relevant information provided by the userspace */ | 1203 | /* Copy relevant information provided by the userspace */ |
1201 | __fill_vb2_buffer(vb, b, planes); | 1204 | __fill_vb2_buffer(vb, b, planes); |
@@ -1221,12 +1224,16 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1221 | } | 1224 | } |
1222 | 1225 | ||
1223 | /* Release previously acquired memory if present */ | 1226 | /* Release previously acquired memory if present */ |
1224 | if (vb->planes[plane].mem_priv) | 1227 | if (vb->planes[plane].mem_priv) { |
1228 | if (!reacquired) { | ||
1229 | reacquired = true; | ||
1230 | call_vb_qop(vb, buf_cleanup, vb); | ||
1231 | } | ||
1225 | call_memop(vb, put_userptr, vb->planes[plane].mem_priv); | 1232 | call_memop(vb, put_userptr, vb->planes[plane].mem_priv); |
1233 | } | ||
1226 | 1234 | ||
1227 | vb->planes[plane].mem_priv = NULL; | 1235 | vb->planes[plane].mem_priv = NULL; |
1228 | vb->v4l2_planes[plane].m.userptr = 0; | 1236 | memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); |
1229 | vb->v4l2_planes[plane].length = 0; | ||
1230 | 1237 | ||
1231 | /* Acquire each plane's memory */ | 1238 | /* Acquire each plane's memory */ |
1232 | mem_priv = call_memop(vb, get_userptr, q->alloc_ctx[plane], | 1239 | mem_priv = call_memop(vb, get_userptr, q->alloc_ctx[plane], |
@@ -1243,23 +1250,34 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1243 | } | 1250 | } |
1244 | 1251 | ||
1245 | /* | 1252 | /* |
1246 | * Call driver-specific initialization on the newly acquired buffer, | ||
1247 | * if provided. | ||
1248 | */ | ||
1249 | ret = call_vb_qop(vb, buf_init, vb); | ||
1250 | if (ret) { | ||
1251 | dprintk(1, "qbuf: buffer initialization failed\n"); | ||
1252 | fail_vb_qop(vb, buf_init); | ||
1253 | goto err; | ||
1254 | } | ||
1255 | |||
1256 | /* | ||
1257 | * Now that everything is in order, copy relevant information | 1253 | * Now that everything is in order, copy relevant information |
1258 | * provided by userspace. | 1254 | * provided by userspace. |
1259 | */ | 1255 | */ |
1260 | for (plane = 0; plane < vb->num_planes; ++plane) | 1256 | for (plane = 0; plane < vb->num_planes; ++plane) |
1261 | vb->v4l2_planes[plane] = planes[plane]; | 1257 | vb->v4l2_planes[plane] = planes[plane]; |
1262 | 1258 | ||
1259 | if (reacquired) { | ||
1260 | /* | ||
1261 | * One or more planes changed, so we must call buf_init to do | ||
1262 | * the driver-specific initialization on the newly acquired | ||
1263 | * buffer, if provided. | ||
1264 | */ | ||
1265 | ret = call_vb_qop(vb, buf_init, vb); | ||
1266 | if (ret) { | ||
1267 | dprintk(1, "qbuf: buffer initialization failed\n"); | ||
1268 | fail_vb_qop(vb, buf_init); | ||
1269 | goto err; | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | ret = call_vb_qop(vb, buf_prepare, vb); | ||
1274 | if (ret) { | ||
1275 | dprintk(1, "qbuf: buffer preparation failed\n"); | ||
1276 | fail_vb_qop(vb, buf_prepare); | ||
1277 | call_vb_qop(vb, buf_cleanup, vb); | ||
1278 | goto err; | ||
1279 | } | ||
1280 | |||
1263 | return 0; | 1281 | return 0; |
1264 | err: | 1282 | err: |
1265 | /* In case of errors, release planes that were already acquired */ | 1283 | /* In case of errors, release planes that were already acquired */ |
@@ -1279,8 +1297,13 @@ err: | |||
1279 | */ | 1297 | */ |
1280 | static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) | 1298 | static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b) |
1281 | { | 1299 | { |
1300 | int ret; | ||
1301 | |||
1282 | __fill_vb2_buffer(vb, b, vb->v4l2_planes); | 1302 | __fill_vb2_buffer(vb, b, vb->v4l2_planes); |
1283 | return 0; | 1303 | ret = call_vb_qop(vb, buf_prepare, vb); |
1304 | if (ret) | ||
1305 | fail_vb_qop(vb, buf_prepare); | ||
1306 | return ret; | ||
1284 | } | 1307 | } |
1285 | 1308 | ||
1286 | /** | 1309 | /** |
@@ -1294,6 +1317,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1294 | unsigned int plane; | 1317 | unsigned int plane; |
1295 | int ret; | 1318 | int ret; |
1296 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); | 1319 | int write = !V4L2_TYPE_IS_OUTPUT(q->type); |
1320 | bool reacquired = vb->planes[0].mem_priv == NULL; | ||
1297 | 1321 | ||
1298 | /* Copy relevant information provided by the userspace */ | 1322 | /* Copy relevant information provided by the userspace */ |
1299 | __fill_vb2_buffer(vb, b, planes); | 1323 | __fill_vb2_buffer(vb, b, planes); |
@@ -1329,6 +1353,11 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1329 | 1353 | ||
1330 | dprintk(1, "qbuf: buffer for plane %d changed\n", plane); | 1354 | dprintk(1, "qbuf: buffer for plane %d changed\n", plane); |
1331 | 1355 | ||
1356 | if (!reacquired) { | ||
1357 | reacquired = true; | ||
1358 | call_vb_qop(vb, buf_cleanup, vb); | ||
1359 | } | ||
1360 | |||
1332 | /* Release previously acquired memory if present */ | 1361 | /* Release previously acquired memory if present */ |
1333 | __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); | 1362 | __vb2_plane_dmabuf_put(vb, &vb->planes[plane]); |
1334 | memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); | 1363 | memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane)); |
@@ -1364,23 +1393,33 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1364 | } | 1393 | } |
1365 | 1394 | ||
1366 | /* | 1395 | /* |
1367 | * Call driver-specific initialization on the newly acquired buffer, | ||
1368 | * if provided. | ||
1369 | */ | ||
1370 | ret = call_vb_qop(vb, buf_init, vb); | ||
1371 | if (ret) { | ||
1372 | dprintk(1, "qbuf: buffer initialization failed\n"); | ||
1373 | fail_vb_qop(vb, buf_init); | ||
1374 | goto err; | ||
1375 | } | ||
1376 | |||
1377 | /* | ||
1378 | * Now that everything is in order, copy relevant information | 1396 | * Now that everything is in order, copy relevant information |
1379 | * provided by userspace. | 1397 | * provided by userspace. |
1380 | */ | 1398 | */ |
1381 | for (plane = 0; plane < vb->num_planes; ++plane) | 1399 | for (plane = 0; plane < vb->num_planes; ++plane) |
1382 | vb->v4l2_planes[plane] = planes[plane]; | 1400 | vb->v4l2_planes[plane] = planes[plane]; |
1383 | 1401 | ||
1402 | if (reacquired) { | ||
1403 | /* | ||
1404 | * Call driver-specific initialization on the newly acquired buffer, | ||
1405 | * if provided. | ||
1406 | */ | ||
1407 | ret = call_vb_qop(vb, buf_init, vb); | ||
1408 | if (ret) { | ||
1409 | dprintk(1, "qbuf: buffer initialization failed\n"); | ||
1410 | fail_vb_qop(vb, buf_init); | ||
1411 | goto err; | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | ret = call_vb_qop(vb, buf_prepare, vb); | ||
1416 | if (ret) { | ||
1417 | dprintk(1, "qbuf: buffer preparation failed\n"); | ||
1418 | fail_vb_qop(vb, buf_prepare); | ||
1419 | call_vb_qop(vb, buf_cleanup, vb); | ||
1420 | goto err; | ||
1421 | } | ||
1422 | |||
1384 | return 0; | 1423 | return 0; |
1385 | err: | 1424 | err: |
1386 | /* In case of errors, release planes that were already acquired */ | 1425 | /* 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) | |||
1459 | ret = -EINVAL; | 1498 | ret = -EINVAL; |
1460 | } | 1499 | } |
1461 | 1500 | ||
1462 | if (!ret) { | ||
1463 | ret = call_vb_qop(vb, buf_prepare, vb); | ||
1464 | if (ret) | ||
1465 | fail_vb_qop(vb, buf_prepare); | ||
1466 | } | ||
1467 | if (ret) | 1501 | if (ret) |
1468 | dprintk(1, "qbuf: buffer preparation failed: %d\n", ret); | 1502 | dprintk(1, "qbuf: buffer preparation failed: %d\n", ret); |
1469 | vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED; | 1503 | vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED; |