diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-12-13 11:13:38 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-01-07 04:00:04 -0500 |
commit | b18a8ff29d80b132018d33479e86ab8ecaee6b46 (patch) | |
tree | f8bc0cec256e75717d36952b278181f887252041 /drivers/media/v4l2-core | |
parent | b4fcdaf7654f9506f80d4e3f2b045a78333d62dc (diff) |
[media] vb2: push the mmap semaphore down to __buf_prepare()
Rather than taking the mmap semaphore at a relatively high-level function,
push it down to the place where it is really needed.
It was placed in vb2_queue_or_prepare_buf() to prevent racing with other
vb2 calls. The only way I can see that a race can happen is when two
threads queue the same buffer. The solution for that it to introduce
a PREPARING state.
Moving it down offers opportunities to simplify the code.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c | 82 |
1 files changed, 36 insertions, 46 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 12df9fda2924..d3f7e8abe212 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -481,6 +481,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
481 | case VB2_BUF_STATE_PREPARED: | 481 | case VB2_BUF_STATE_PREPARED: |
482 | b->flags |= V4L2_BUF_FLAG_PREPARED; | 482 | b->flags |= V4L2_BUF_FLAG_PREPARED; |
483 | break; | 483 | break; |
484 | case VB2_BUF_STATE_PREPARING: | ||
484 | case VB2_BUF_STATE_DEQUEUED: | 485 | case VB2_BUF_STATE_DEQUEUED: |
485 | /* nothing */ | 486 | /* nothing */ |
486 | break; | 487 | break; |
@@ -1228,6 +1229,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb) | |||
1228 | static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | 1229 | static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) |
1229 | { | 1230 | { |
1230 | struct vb2_queue *q = vb->vb2_queue; | 1231 | struct vb2_queue *q = vb->vb2_queue; |
1232 | struct rw_semaphore *mmap_sem; | ||
1231 | int ret; | 1233 | int ret; |
1232 | 1234 | ||
1233 | ret = __verify_length(vb, b); | 1235 | ret = __verify_length(vb, b); |
@@ -1237,12 +1239,31 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1237 | return ret; | 1239 | return ret; |
1238 | } | 1240 | } |
1239 | 1241 | ||
1242 | vb->state = VB2_BUF_STATE_PREPARING; | ||
1240 | switch (q->memory) { | 1243 | switch (q->memory) { |
1241 | case V4L2_MEMORY_MMAP: | 1244 | case V4L2_MEMORY_MMAP: |
1242 | ret = __qbuf_mmap(vb, b); | 1245 | ret = __qbuf_mmap(vb, b); |
1243 | break; | 1246 | break; |
1244 | case V4L2_MEMORY_USERPTR: | 1247 | case V4L2_MEMORY_USERPTR: |
1248 | /* | ||
1249 | * In case of user pointer buffers vb2 allocators need to get direct | ||
1250 | * access to userspace pages. This requires getting the mmap semaphore | ||
1251 | * for read access in the current process structure. The same semaphore | ||
1252 | * is taken before calling mmap operation, while both qbuf/prepare_buf | ||
1253 | * and mmap are called by the driver or v4l2 core with the driver's lock | ||
1254 | * held. To avoid an AB-BA deadlock (mmap_sem then driver's lock in mmap | ||
1255 | * and driver's lock then mmap_sem in qbuf/prepare_buf) the videobuf2 | ||
1256 | * core releases the driver's lock, takes mmap_sem and then takes the | ||
1257 | * driver's lock again. | ||
1258 | */ | ||
1259 | mmap_sem = ¤t->mm->mmap_sem; | ||
1260 | call_qop(q, wait_prepare, q); | ||
1261 | down_read(mmap_sem); | ||
1262 | call_qop(q, wait_finish, q); | ||
1263 | |||
1245 | ret = __qbuf_userptr(vb, b); | 1264 | ret = __qbuf_userptr(vb, b); |
1265 | |||
1266 | up_read(mmap_sem); | ||
1246 | break; | 1267 | break; |
1247 | case V4L2_MEMORY_DMABUF: | 1268 | case V4L2_MEMORY_DMABUF: |
1248 | ret = __qbuf_dmabuf(vb, b); | 1269 | ret = __qbuf_dmabuf(vb, b); |
@@ -1256,8 +1277,7 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
1256 | ret = call_qop(q, buf_prepare, vb); | 1277 | ret = call_qop(q, buf_prepare, vb); |
1257 | if (ret) | 1278 | if (ret) |
1258 | dprintk(1, "qbuf: buffer preparation failed: %d\n", ret); | 1279 | dprintk(1, "qbuf: buffer preparation failed: %d\n", ret); |
1259 | else | 1280 | vb->state = ret ? VB2_BUF_STATE_DEQUEUED : VB2_BUF_STATE_PREPARED; |
1260 | vb->state = VB2_BUF_STATE_PREPARED; | ||
1261 | 1281 | ||
1262 | return ret; | 1282 | return ret; |
1263 | } | 1283 | } |
@@ -1268,80 +1288,47 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, | |||
1268 | struct v4l2_buffer *, | 1288 | struct v4l2_buffer *, |
1269 | struct vb2_buffer *)) | 1289 | struct vb2_buffer *)) |
1270 | { | 1290 | { |
1271 | struct rw_semaphore *mmap_sem = NULL; | ||
1272 | struct vb2_buffer *vb; | 1291 | struct vb2_buffer *vb; |
1273 | int ret; | 1292 | int ret; |
1274 | 1293 | ||
1275 | /* | ||
1276 | * In case of user pointer buffers vb2 allocators need to get direct | ||
1277 | * access to userspace pages. This requires getting the mmap semaphore | ||
1278 | * for read access in the current process structure. The same semaphore | ||
1279 | * is taken before calling mmap operation, while both qbuf/prepare_buf | ||
1280 | * and mmap are called by the driver or v4l2 core with the driver's lock | ||
1281 | * held. To avoid an AB-BA deadlock (mmap_sem then driver's lock in mmap | ||
1282 | * and driver's lock then mmap_sem in qbuf/prepare_buf) the videobuf2 | ||
1283 | * core releases the driver's lock, takes mmap_sem and then takes the | ||
1284 | * driver's lock again. | ||
1285 | * | ||
1286 | * To avoid racing with other vb2 calls, which might be called after | ||
1287 | * releasing the driver's lock, this operation is performed at the | ||
1288 | * beginning of qbuf/prepare_buf processing. This way the queue status | ||
1289 | * is consistent after getting the driver's lock back. | ||
1290 | */ | ||
1291 | if (q->memory == V4L2_MEMORY_USERPTR) { | ||
1292 | mmap_sem = ¤t->mm->mmap_sem; | ||
1293 | call_qop(q, wait_prepare, q); | ||
1294 | down_read(mmap_sem); | ||
1295 | call_qop(q, wait_finish, q); | ||
1296 | } | ||
1297 | |||
1298 | if (q->fileio) { | 1294 | if (q->fileio) { |
1299 | dprintk(1, "%s(): file io in progress\n", opname); | 1295 | dprintk(1, "%s(): file io in progress\n", opname); |
1300 | ret = -EBUSY; | 1296 | return -EBUSY; |
1301 | goto unlock; | ||
1302 | } | 1297 | } |
1303 | 1298 | ||
1304 | if (b->type != q->type) { | 1299 | if (b->type != q->type) { |
1305 | dprintk(1, "%s(): invalid buffer type\n", opname); | 1300 | dprintk(1, "%s(): invalid buffer type\n", opname); |
1306 | ret = -EINVAL; | 1301 | return -EINVAL; |
1307 | goto unlock; | ||
1308 | } | 1302 | } |
1309 | 1303 | ||
1310 | if (b->index >= q->num_buffers) { | 1304 | if (b->index >= q->num_buffers) { |
1311 | dprintk(1, "%s(): buffer index out of range\n", opname); | 1305 | dprintk(1, "%s(): buffer index out of range\n", opname); |
1312 | ret = -EINVAL; | 1306 | return -EINVAL; |
1313 | goto unlock; | ||
1314 | } | 1307 | } |
1315 | 1308 | ||
1316 | vb = q->bufs[b->index]; | 1309 | vb = q->bufs[b->index]; |
1317 | if (NULL == vb) { | 1310 | if (NULL == vb) { |
1318 | /* Should never happen */ | 1311 | /* Should never happen */ |
1319 | dprintk(1, "%s(): buffer is NULL\n", opname); | 1312 | dprintk(1, "%s(): buffer is NULL\n", opname); |
1320 | ret = -EINVAL; | 1313 | return -EINVAL; |
1321 | goto unlock; | ||
1322 | } | 1314 | } |
1323 | 1315 | ||
1324 | if (b->memory != q->memory) { | 1316 | if (b->memory != q->memory) { |
1325 | dprintk(1, "%s(): invalid memory type\n", opname); | 1317 | dprintk(1, "%s(): invalid memory type\n", opname); |
1326 | ret = -EINVAL; | 1318 | return -EINVAL; |
1327 | goto unlock; | ||
1328 | } | 1319 | } |
1329 | 1320 | ||
1330 | ret = __verify_planes_array(vb, b); | 1321 | ret = __verify_planes_array(vb, b); |
1331 | if (ret) | 1322 | if (ret) |
1332 | goto unlock; | 1323 | return ret; |
1333 | 1324 | ||
1334 | ret = handler(q, b, vb); | 1325 | ret = handler(q, b, vb); |
1335 | if (ret) | 1326 | if (!ret) { |
1336 | goto unlock; | 1327 | /* Fill buffer information for the userspace */ |
1337 | 1328 | __fill_v4l2_buffer(vb, b); | |
1338 | /* Fill buffer information for the userspace */ | ||
1339 | __fill_v4l2_buffer(vb, b); | ||
1340 | 1329 | ||
1341 | dprintk(1, "%s() of buffer %d succeeded\n", opname, vb->v4l2_buf.index); | 1330 | dprintk(1, "%s() of buffer %d succeeded\n", opname, vb->v4l2_buf.index); |
1342 | unlock: | 1331 | } |
1343 | if (mmap_sem) | ||
1344 | up_read(mmap_sem); | ||
1345 | return ret; | 1332 | return ret; |
1346 | } | 1333 | } |
1347 | 1334 | ||
@@ -1390,6 +1377,9 @@ static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, | |||
1390 | return ret; | 1377 | return ret; |
1391 | case VB2_BUF_STATE_PREPARED: | 1378 | case VB2_BUF_STATE_PREPARED: |
1392 | break; | 1379 | break; |
1380 | case VB2_BUF_STATE_PREPARING: | ||
1381 | dprintk(1, "qbuf: buffer still being prepared\n"); | ||
1382 | return -EINVAL; | ||
1393 | default: | 1383 | default: |
1394 | dprintk(1, "qbuf: buffer already in use\n"); | 1384 | dprintk(1, "qbuf: buffer already in use\n"); |
1395 | return -EINVAL; | 1385 | return -EINVAL; |