diff options
Diffstat (limited to 'drivers/media/video/videobuf2-core.c')
-rw-r--r-- | drivers/media/video/videobuf2-core.c | 118 |
1 files changed, 72 insertions, 46 deletions
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 95a3f5e82ae..2e8f1df775b 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c | |||
@@ -30,7 +30,7 @@ module_param(debug, int, 0644); | |||
30 | printk(KERN_DEBUG "vb2: " fmt, ## arg); \ | 30 | printk(KERN_DEBUG "vb2: " fmt, ## arg); \ |
31 | } while (0) | 31 | } while (0) |
32 | 32 | ||
33 | #define call_memop(q, plane, op, args...) \ | 33 | #define call_memop(q, op, args...) \ |
34 | (((q)->mem_ops->op) ? \ | 34 | (((q)->mem_ops->op) ? \ |
35 | ((q)->mem_ops->op(args)) : 0) | 35 | ((q)->mem_ops->op(args)) : 0) |
36 | 36 | ||
@@ -52,7 +52,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) | |||
52 | 52 | ||
53 | /* Allocate memory for all planes in this buffer */ | 53 | /* Allocate memory for all planes in this buffer */ |
54 | for (plane = 0; plane < vb->num_planes; ++plane) { | 54 | for (plane = 0; plane < vb->num_planes; ++plane) { |
55 | mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane], | 55 | mem_priv = call_memop(q, alloc, q->alloc_ctx[plane], |
56 | q->plane_sizes[plane]); | 56 | q->plane_sizes[plane]); |
57 | if (IS_ERR_OR_NULL(mem_priv)) | 57 | if (IS_ERR_OR_NULL(mem_priv)) |
58 | goto free; | 58 | goto free; |
@@ -65,8 +65,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) | |||
65 | return 0; | 65 | return 0; |
66 | free: | 66 | free: |
67 | /* Free already allocated memory if one of the allocations failed */ | 67 | /* Free already allocated memory if one of the allocations failed */ |
68 | for (; plane > 0; --plane) | 68 | for (; plane > 0; --plane) { |
69 | call_memop(q, plane, put, vb->planes[plane - 1].mem_priv); | 69 | call_memop(q, put, vb->planes[plane - 1].mem_priv); |
70 | vb->planes[plane - 1].mem_priv = NULL; | ||
71 | } | ||
70 | 72 | ||
71 | return -ENOMEM; | 73 | return -ENOMEM; |
72 | } | 74 | } |
@@ -80,10 +82,10 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb) | |||
80 | unsigned int plane; | 82 | unsigned int plane; |
81 | 83 | ||
82 | for (plane = 0; plane < vb->num_planes; ++plane) { | 84 | for (plane = 0; plane < vb->num_planes; ++plane) { |
83 | call_memop(q, plane, put, vb->planes[plane].mem_priv); | 85 | call_memop(q, put, vb->planes[plane].mem_priv); |
84 | vb->planes[plane].mem_priv = NULL; | 86 | vb->planes[plane].mem_priv = NULL; |
85 | dprintk(3, "Freed plane %d of buffer %d\n", | 87 | dprintk(3, "Freed plane %d of buffer %d\n", plane, |
86 | plane, vb->v4l2_buf.index); | 88 | vb->v4l2_buf.index); |
87 | } | 89 | } |
88 | } | 90 | } |
89 | 91 | ||
@@ -97,12 +99,9 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb) | |||
97 | unsigned int plane; | 99 | unsigned int plane; |
98 | 100 | ||
99 | for (plane = 0; plane < vb->num_planes; ++plane) { | 101 | for (plane = 0; plane < vb->num_planes; ++plane) { |
100 | void *mem_priv = vb->planes[plane].mem_priv; | 102 | if (vb->planes[plane].mem_priv) |
101 | 103 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); | |
102 | if (mem_priv) { | 104 | vb->planes[plane].mem_priv = NULL; |
103 | call_memop(q, plane, put_userptr, mem_priv); | ||
104 | vb->planes[plane].mem_priv = NULL; | ||
105 | } | ||
106 | } | 105 | } |
107 | } | 106 | } |
108 | 107 | ||
@@ -305,7 +304,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) | |||
305 | * case anyway. If num_users() returns more than 1, | 304 | * case anyway. If num_users() returns more than 1, |
306 | * we are not the only user of the plane's memory. | 305 | * we are not the only user of the plane's memory. |
307 | */ | 306 | */ |
308 | if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1) | 307 | if (mem_priv && call_memop(q, num_users, mem_priv) > 1) |
309 | return true; | 308 | return true; |
310 | } | 309 | } |
311 | return false; | 310 | return false; |
@@ -731,10 +730,10 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) | |||
731 | { | 730 | { |
732 | struct vb2_queue *q = vb->vb2_queue; | 731 | struct vb2_queue *q = vb->vb2_queue; |
733 | 732 | ||
734 | if (plane_no > vb->num_planes) | 733 | if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) |
735 | return NULL; | 734 | return NULL; |
736 | 735 | ||
737 | return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv); | 736 | return call_memop(q, vaddr, vb->planes[plane_no].mem_priv); |
738 | 737 | ||
739 | } | 738 | } |
740 | EXPORT_SYMBOL_GPL(vb2_plane_vaddr); | 739 | EXPORT_SYMBOL_GPL(vb2_plane_vaddr); |
@@ -754,10 +753,10 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) | |||
754 | { | 753 | { |
755 | struct vb2_queue *q = vb->vb2_queue; | 754 | struct vb2_queue *q = vb->vb2_queue; |
756 | 755 | ||
757 | if (plane_no > vb->num_planes) | 756 | if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) |
758 | return NULL; | 757 | return NULL; |
759 | 758 | ||
760 | return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv); | 759 | return call_memop(q, cookie, vb->planes[plane_no].mem_priv); |
761 | } | 760 | } |
762 | EXPORT_SYMBOL_GPL(vb2_plane_cookie); | 761 | EXPORT_SYMBOL_GPL(vb2_plane_cookie); |
763 | 762 | ||
@@ -883,7 +882,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
883 | 882 | ||
884 | for (plane = 0; plane < vb->num_planes; ++plane) { | 883 | for (plane = 0; plane < vb->num_planes; ++plane) { |
885 | /* Skip the plane if already verified */ | 884 | /* Skip the plane if already verified */ |
886 | if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr | 885 | if (vb->v4l2_planes[plane].m.userptr && |
886 | vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr | ||
887 | && vb->v4l2_planes[plane].length == planes[plane].length) | 887 | && vb->v4l2_planes[plane].length == planes[plane].length) |
888 | continue; | 888 | continue; |
889 | 889 | ||
@@ -898,27 +898,23 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
898 | 898 | ||
899 | /* Release previously acquired memory if present */ | 899 | /* Release previously acquired memory if present */ |
900 | if (vb->planes[plane].mem_priv) | 900 | if (vb->planes[plane].mem_priv) |
901 | call_memop(q, plane, put_userptr, | 901 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); |
902 | vb->planes[plane].mem_priv); | ||
903 | 902 | ||
904 | vb->planes[plane].mem_priv = NULL; | 903 | vb->planes[plane].mem_priv = NULL; |
905 | vb->v4l2_planes[plane].m.userptr = 0; | 904 | vb->v4l2_planes[plane].m.userptr = 0; |
906 | vb->v4l2_planes[plane].length = 0; | 905 | vb->v4l2_planes[plane].length = 0; |
907 | 906 | ||
908 | /* Acquire each plane's memory */ | 907 | /* Acquire each plane's memory */ |
909 | if (q->mem_ops->get_userptr) { | 908 | mem_priv = call_memop(q, get_userptr, q->alloc_ctx[plane], |
910 | mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane], | 909 | planes[plane].m.userptr, |
911 | planes[plane].m.userptr, | 910 | planes[plane].length, write); |
912 | planes[plane].length, | 911 | if (IS_ERR_OR_NULL(mem_priv)) { |
913 | write); | 912 | dprintk(1, "qbuf: failed acquiring userspace " |
914 | if (IS_ERR(mem_priv)) { | ||
915 | dprintk(1, "qbuf: failed acquiring userspace " | ||
916 | "memory for plane %d\n", plane); | 913 | "memory for plane %d\n", plane); |
917 | ret = PTR_ERR(mem_priv); | 914 | ret = mem_priv ? PTR_ERR(mem_priv) : -EINVAL; |
918 | goto err; | 915 | goto err; |
919 | } | ||
920 | vb->planes[plane].mem_priv = mem_priv; | ||
921 | } | 916 | } |
917 | vb->planes[plane].mem_priv = mem_priv; | ||
922 | } | 918 | } |
923 | 919 | ||
924 | /* | 920 | /* |
@@ -943,8 +939,7 @@ err: | |||
943 | /* In case of errors, release planes that were already acquired */ | 939 | /* In case of errors, release planes that were already acquired */ |
944 | for (plane = 0; plane < vb->num_planes; ++plane) { | 940 | for (plane = 0; plane < vb->num_planes; ++plane) { |
945 | if (vb->planes[plane].mem_priv) | 941 | if (vb->planes[plane].mem_priv) |
946 | call_memop(q, plane, put_userptr, | 942 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); |
947 | vb->planes[plane].mem_priv); | ||
948 | vb->planes[plane].mem_priv = NULL; | 943 | vb->planes[plane].mem_priv = NULL; |
949 | vb->v4l2_planes[plane].m.userptr = 0; | 944 | vb->v4l2_planes[plane].m.userptr = 0; |
950 | vb->v4l2_planes[plane].length = 0; | 945 | vb->v4l2_planes[plane].length = 0; |
@@ -1081,46 +1076,76 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf); | |||
1081 | */ | 1076 | */ |
1082 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | 1077 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) |
1083 | { | 1078 | { |
1079 | struct rw_semaphore *mmap_sem = NULL; | ||
1084 | struct vb2_buffer *vb; | 1080 | struct vb2_buffer *vb; |
1085 | int ret; | 1081 | int ret = 0; |
1082 | |||
1083 | /* | ||
1084 | * In case of user pointer buffers vb2 allocator needs to get direct | ||
1085 | * access to userspace pages. This requires getting read access on | ||
1086 | * mmap semaphore in the current process structure. The same | ||
1087 | * semaphore is taken before calling mmap operation, while both mmap | ||
1088 | * and qbuf are called by the driver or v4l2 core with driver's lock | ||
1089 | * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in | ||
1090 | * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core | ||
1091 | * release driver's lock, takes mmap_sem and then takes again driver's | ||
1092 | * lock. | ||
1093 | * | ||
1094 | * To avoid race with other vb2 calls, which might be called after | ||
1095 | * releasing driver's lock, this operation is performed at the | ||
1096 | * beggining of qbuf processing. This way the queue status is | ||
1097 | * consistent after getting driver's lock back. | ||
1098 | */ | ||
1099 | if (q->memory == V4L2_MEMORY_USERPTR) { | ||
1100 | mmap_sem = ¤t->mm->mmap_sem; | ||
1101 | call_qop(q, wait_prepare, q); | ||
1102 | down_read(mmap_sem); | ||
1103 | call_qop(q, wait_finish, q); | ||
1104 | } | ||
1086 | 1105 | ||
1087 | if (q->fileio) { | 1106 | if (q->fileio) { |
1088 | dprintk(1, "qbuf: file io in progress\n"); | 1107 | dprintk(1, "qbuf: file io in progress\n"); |
1089 | return -EBUSY; | 1108 | ret = -EBUSY; |
1109 | goto unlock; | ||
1090 | } | 1110 | } |
1091 | 1111 | ||
1092 | if (b->type != q->type) { | 1112 | if (b->type != q->type) { |
1093 | dprintk(1, "qbuf: invalid buffer type\n"); | 1113 | dprintk(1, "qbuf: invalid buffer type\n"); |
1094 | return -EINVAL; | 1114 | ret = -EINVAL; |
1115 | goto unlock; | ||
1095 | } | 1116 | } |
1096 | 1117 | ||
1097 | if (b->index >= q->num_buffers) { | 1118 | if (b->index >= q->num_buffers) { |
1098 | dprintk(1, "qbuf: buffer index out of range\n"); | 1119 | dprintk(1, "qbuf: buffer index out of range\n"); |
1099 | return -EINVAL; | 1120 | ret = -EINVAL; |
1121 | goto unlock; | ||
1100 | } | 1122 | } |
1101 | 1123 | ||
1102 | vb = q->bufs[b->index]; | 1124 | vb = q->bufs[b->index]; |
1103 | if (NULL == vb) { | 1125 | if (NULL == vb) { |
1104 | /* Should never happen */ | 1126 | /* Should never happen */ |
1105 | dprintk(1, "qbuf: buffer is NULL\n"); | 1127 | dprintk(1, "qbuf: buffer is NULL\n"); |
1106 | return -EINVAL; | 1128 | ret = -EINVAL; |
1129 | goto unlock; | ||
1107 | } | 1130 | } |
1108 | 1131 | ||
1109 | if (b->memory != q->memory) { | 1132 | if (b->memory != q->memory) { |
1110 | dprintk(1, "qbuf: invalid memory type\n"); | 1133 | dprintk(1, "qbuf: invalid memory type\n"); |
1111 | return -EINVAL; | 1134 | ret = -EINVAL; |
1135 | goto unlock; | ||
1112 | } | 1136 | } |
1113 | 1137 | ||
1114 | switch (vb->state) { | 1138 | switch (vb->state) { |
1115 | case VB2_BUF_STATE_DEQUEUED: | 1139 | case VB2_BUF_STATE_DEQUEUED: |
1116 | ret = __buf_prepare(vb, b); | 1140 | ret = __buf_prepare(vb, b); |
1117 | if (ret) | 1141 | if (ret) |
1118 | return ret; | 1142 | goto unlock; |
1119 | case VB2_BUF_STATE_PREPARED: | 1143 | case VB2_BUF_STATE_PREPARED: |
1120 | break; | 1144 | break; |
1121 | default: | 1145 | default: |
1122 | dprintk(1, "qbuf: buffer already in use\n"); | 1146 | dprintk(1, "qbuf: buffer already in use\n"); |
1123 | return -EINVAL; | 1147 | ret = -EINVAL; |
1148 | goto unlock; | ||
1124 | } | 1149 | } |
1125 | 1150 | ||
1126 | /* | 1151 | /* |
@@ -1141,7 +1166,10 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1141 | __fill_v4l2_buffer(vb, b); | 1166 | __fill_v4l2_buffer(vb, b); |
1142 | 1167 | ||
1143 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); | 1168 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); |
1144 | return 0; | 1169 | unlock: |
1170 | if (mmap_sem) | ||
1171 | up_read(mmap_sem); | ||
1172 | return ret; | ||
1145 | } | 1173 | } |
1146 | EXPORT_SYMBOL_GPL(vb2_qbuf); | 1174 | EXPORT_SYMBOL_GPL(vb2_qbuf); |
1147 | 1175 | ||
@@ -1521,7 +1549,6 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, | |||
1521 | int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) | 1549 | int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) |
1522 | { | 1550 | { |
1523 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | 1551 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; |
1524 | struct vb2_plane *vb_plane; | ||
1525 | struct vb2_buffer *vb; | 1552 | struct vb2_buffer *vb; |
1526 | unsigned int buffer, plane; | 1553 | unsigned int buffer, plane; |
1527 | int ret; | 1554 | int ret; |
@@ -1558,9 +1585,8 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) | |||
1558 | return ret; | 1585 | return ret; |
1559 | 1586 | ||
1560 | vb = q->bufs[buffer]; | 1587 | vb = q->bufs[buffer]; |
1561 | vb_plane = &vb->planes[plane]; | ||
1562 | 1588 | ||
1563 | ret = q->mem_ops->mmap(vb_plane->mem_priv, vma); | 1589 | ret = call_memop(q, mmap, vb->planes[plane].mem_priv, vma); |
1564 | if (ret) | 1590 | if (ret) |
1565 | return ret; | 1591 | return ret; |
1566 | 1592 | ||