diff options
Diffstat (limited to 'drivers/media/video/videobuf2-core.c')
-rw-r--r-- | drivers/media/video/videobuf2-core.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 3015e6000946..c3606276607e 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c | |||
@@ -43,8 +43,7 @@ module_param(debug, int, 0644); | |||
43 | /** | 43 | /** |
44 | * __vb2_buf_mem_alloc() - allocate video memory for the given buffer | 44 | * __vb2_buf_mem_alloc() - allocate video memory for the given buffer |
45 | */ | 45 | */ |
46 | static int __vb2_buf_mem_alloc(struct vb2_buffer *vb, | 46 | static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) |
47 | unsigned long *plane_sizes) | ||
48 | { | 47 | { |
49 | struct vb2_queue *q = vb->vb2_queue; | 48 | struct vb2_queue *q = vb->vb2_queue; |
50 | void *mem_priv; | 49 | void *mem_priv; |
@@ -53,13 +52,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb, | |||
53 | /* Allocate memory for all planes in this buffer */ | 52 | /* Allocate memory for all planes in this buffer */ |
54 | for (plane = 0; plane < vb->num_planes; ++plane) { | 53 | for (plane = 0; plane < vb->num_planes; ++plane) { |
55 | mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane], | 54 | mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane], |
56 | plane_sizes[plane]); | 55 | q->plane_sizes[plane]); |
57 | if (IS_ERR_OR_NULL(mem_priv)) | 56 | if (IS_ERR_OR_NULL(mem_priv)) |
58 | goto free; | 57 | goto free; |
59 | 58 | ||
60 | /* Associate allocator private data with this plane */ | 59 | /* Associate allocator private data with this plane */ |
61 | vb->planes[plane].mem_priv = mem_priv; | 60 | vb->planes[plane].mem_priv = mem_priv; |
62 | vb->v4l2_planes[plane].length = plane_sizes[plane]; | 61 | vb->v4l2_planes[plane].length = q->plane_sizes[plane]; |
63 | } | 62 | } |
64 | 63 | ||
65 | return 0; | 64 | return 0; |
@@ -141,8 +140,7 @@ static void __setup_offsets(struct vb2_queue *q) | |||
141 | * Returns the number of buffers successfully allocated. | 140 | * Returns the number of buffers successfully allocated. |
142 | */ | 141 | */ |
143 | static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, | 142 | static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, |
144 | unsigned int num_buffers, unsigned int num_planes, | 143 | unsigned int num_buffers, unsigned int num_planes) |
145 | unsigned long plane_sizes[]) | ||
146 | { | 144 | { |
147 | unsigned int buffer; | 145 | unsigned int buffer; |
148 | struct vb2_buffer *vb; | 146 | struct vb2_buffer *vb; |
@@ -169,7 +167,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, | |||
169 | 167 | ||
170 | /* Allocate video buffer memory for the MMAP type */ | 168 | /* Allocate video buffer memory for the MMAP type */ |
171 | if (memory == V4L2_MEMORY_MMAP) { | 169 | if (memory == V4L2_MEMORY_MMAP) { |
172 | ret = __vb2_buf_mem_alloc(vb, plane_sizes); | 170 | ret = __vb2_buf_mem_alloc(vb); |
173 | if (ret) { | 171 | if (ret) { |
174 | dprintk(1, "Failed allocating memory for " | 172 | dprintk(1, "Failed allocating memory for " |
175 | "buffer %d\n", buffer); | 173 | "buffer %d\n", buffer); |
@@ -454,7 +452,6 @@ static bool __buffers_in_use(struct vb2_queue *q) | |||
454 | int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) | 452 | int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) |
455 | { | 453 | { |
456 | unsigned int num_buffers, num_planes; | 454 | unsigned int num_buffers, num_planes; |
457 | unsigned long plane_sizes[VIDEO_MAX_PLANES]; | ||
458 | int ret = 0; | 455 | int ret = 0; |
459 | 456 | ||
460 | if (q->fileio) { | 457 | if (q->fileio) { |
@@ -516,7 +513,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) | |||
516 | * Make sure the requested values and current defaults are sane. | 513 | * Make sure the requested values and current defaults are sane. |
517 | */ | 514 | */ |
518 | num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME); | 515 | num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME); |
519 | memset(plane_sizes, 0, sizeof(plane_sizes)); | 516 | memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); |
520 | memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); | 517 | memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); |
521 | q->memory = req->memory; | 518 | q->memory = req->memory; |
522 | 519 | ||
@@ -525,13 +522,12 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) | |||
525 | * Driver also sets the size and allocator context for each plane. | 522 | * Driver also sets the size and allocator context for each plane. |
526 | */ | 523 | */ |
527 | ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, | 524 | ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, |
528 | plane_sizes, q->alloc_ctx); | 525 | q->plane_sizes, q->alloc_ctx); |
529 | if (ret) | 526 | if (ret) |
530 | return ret; | 527 | return ret; |
531 | 528 | ||
532 | /* Finally, allocate buffers and video memory */ | 529 | /* Finally, allocate buffers and video memory */ |
533 | ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes, | 530 | ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes); |
534 | plane_sizes); | ||
535 | if (ret == 0) { | 531 | if (ret == 0) { |
536 | dprintk(1, "Memory allocation failed\n"); | 532 | dprintk(1, "Memory allocation failed\n"); |
537 | return -ENOMEM; | 533 | return -ENOMEM; |
@@ -545,7 +541,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) | |||
545 | 541 | ||
546 | orig_num_buffers = num_buffers = ret; | 542 | orig_num_buffers = num_buffers = ret; |
547 | ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, | 543 | ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, |
548 | plane_sizes, q->alloc_ctx); | 544 | q->plane_sizes, q->alloc_ctx); |
549 | if (ret) | 545 | if (ret) |
550 | goto free_mem; | 546 | goto free_mem; |
551 | 547 | ||
@@ -745,12 +741,20 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
745 | dprintk(3, "qbuf: userspace address for plane %d changed, " | 741 | dprintk(3, "qbuf: userspace address for plane %d changed, " |
746 | "reacquiring memory\n", plane); | 742 | "reacquiring memory\n", plane); |
747 | 743 | ||
744 | /* Check if the provided plane buffer is large enough */ | ||
745 | if (planes[plane].length < q->plane_sizes[plane]) { | ||
746 | ret = EINVAL; | ||
747 | goto err; | ||
748 | } | ||
749 | |||
748 | /* Release previously acquired memory if present */ | 750 | /* Release previously acquired memory if present */ |
749 | if (vb->planes[plane].mem_priv) | 751 | if (vb->planes[plane].mem_priv) |
750 | call_memop(q, plane, put_userptr, | 752 | call_memop(q, plane, put_userptr, |
751 | vb->planes[plane].mem_priv); | 753 | vb->planes[plane].mem_priv); |
752 | 754 | ||
753 | vb->planes[plane].mem_priv = NULL; | 755 | vb->planes[plane].mem_priv = NULL; |
756 | vb->v4l2_planes[plane].m.userptr = 0; | ||
757 | vb->v4l2_planes[plane].length = 0; | ||
754 | 758 | ||
755 | /* Acquire each plane's memory */ | 759 | /* Acquire each plane's memory */ |
756 | if (q->mem_ops->get_userptr) { | 760 | if (q->mem_ops->get_userptr) { |
@@ -788,10 +792,13 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b) | |||
788 | return 0; | 792 | return 0; |
789 | err: | 793 | err: |
790 | /* In case of errors, release planes that were already acquired */ | 794 | /* In case of errors, release planes that were already acquired */ |
791 | for (; plane > 0; --plane) { | 795 | for (plane = 0; plane < vb->num_planes; ++plane) { |
792 | call_memop(q, plane, put_userptr, | 796 | if (vb->planes[plane].mem_priv) |
793 | vb->planes[plane - 1].mem_priv); | 797 | call_memop(q, plane, put_userptr, |
794 | vb->planes[plane - 1].mem_priv = NULL; | 798 | vb->planes[plane].mem_priv); |
799 | vb->planes[plane].mem_priv = NULL; | ||
800 | vb->v4l2_planes[plane].m.userptr = 0; | ||
801 | vb->v4l2_planes[plane].length = 0; | ||
795 | } | 802 | } |
796 | 803 | ||
797 | return ret; | 804 | return ret; |