Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] uvc gadget: switch to v4l2 core locking

Switch this driver over to the V4L2 core locking mechanism in preparation
for switching to unlocked_ioctl. Suggested by Laurent Pinchart.

This patch introduces a new mutex at the struct uvc_video level and
drops the old mutex at the queue level. The new lock is now used for all
ioctl locking and in the release file operation (the driver always has
to take care of locking in file operations, the core only serializes
ioctls).

Note that the mmap and get_unmapped_area file operations no longer take
a lock. Commit f035eb4e976ef5a059e30bc91cfd310ff030a7d3 fixed a AB-BA
deadlock by moving all the locking down into vb2, so the mmap and
get_unmapped_area file operations should no longer do any locking before
calling into vb2.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
d8e96c4b 2e1328dd

+22 -70
+2
drivers/usb/gadget/function/f_uvc.c
··· 447 447 video->ioctl_ops = &uvc_v4l2_ioctl_ops; 448 448 video->release = video_device_release; 449 449 video->vfl_dir = VFL_DIR_TX; 450 + video->lock = &uvc->video.mutex; 450 451 strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); 451 452 452 453 uvc->vdev = video; ··· 919 918 if (uvc == NULL) 920 919 return ERR_PTR(-ENOMEM); 921 920 921 + mutex_init(&uvc->video.mutex); 922 922 uvc->state = UVC_STATE_DISCONNECTED; 923 923 opts = fi_to_f_uvc_opts(fi); 924 924
+1
drivers/usb/gadget/function/uvc.h
··· 115 115 unsigned int width; 116 116 unsigned int height; 117 117 unsigned int imagesize; 118 + struct mutex mutex; /* protects frame parameters */ 118 119 119 120 /* Requests */ 120 121 unsigned int req_size;
+13 -66
drivers/usb/gadget/function/uvc_queue.c
··· 104 104 spin_unlock_irqrestore(&queue->irqlock, flags); 105 105 } 106 106 107 - static void uvc_wait_prepare(struct vb2_queue *vq) 108 - { 109 - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); 110 - 111 - mutex_unlock(&queue->mutex); 112 - } 113 - 114 - static void uvc_wait_finish(struct vb2_queue *vq) 115 - { 116 - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); 117 - 118 - mutex_lock(&queue->mutex); 119 - } 120 - 121 107 static struct vb2_ops uvc_queue_qops = { 122 108 .queue_setup = uvc_queue_setup, 123 109 .buf_prepare = uvc_buffer_prepare, 124 110 .buf_queue = uvc_buffer_queue, 125 - .wait_prepare = uvc_wait_prepare, 126 - .wait_finish = uvc_wait_finish, 111 + .wait_prepare = vb2_ops_wait_prepare, 112 + .wait_finish = vb2_ops_wait_finish, 127 113 }; 128 114 129 - int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) 115 + int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, 116 + struct mutex *lock) 130 117 { 131 118 int ret; 132 119 ··· 122 135 queue->queue.drv_priv = queue; 123 136 queue->queue.buf_struct_size = sizeof(struct uvc_buffer); 124 137 queue->queue.ops = &uvc_queue_qops; 138 + queue->queue.lock = lock; 125 139 queue->queue.mem_ops = &vb2_vmalloc_memops; 126 140 queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC 127 141 | V4L2_BUF_FLAG_TSTAMP_SRC_EOF; ··· 130 142 if (ret) 131 143 return ret; 132 144 133 - mutex_init(&queue->mutex); 134 145 spin_lock_init(&queue->irqlock); 135 146 INIT_LIST_HEAD(&queue->irqqueue); 136 147 queue->flags = 0; ··· 142 155 */ 143 156 void uvcg_free_buffers(struct uvc_video_queue *queue) 144 157 { 145 - mutex_lock(&queue->mutex); 146 158 vb2_queue_release(&queue->queue); 147 - mutex_unlock(&queue->mutex); 148 159 } 149 160 150 161 /* ··· 153 168 { 154 169 int ret; 155 170 156 - mutex_lock(&queue->mutex); 157 171 ret = vb2_reqbufs(&queue->queue, rb); 158 - mutex_unlock(&queue->mutex); 159 172 160 173 return ret ? ret : rb->count; 161 174 } 162 175 163 176 int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) 164 177 { 165 - int ret; 166 - 167 - mutex_lock(&queue->mutex); 168 - ret = vb2_querybuf(&queue->queue, buf); 169 - mutex_unlock(&queue->mutex); 170 - 171 - return ret; 178 + return vb2_querybuf(&queue->queue, buf); 172 179 } 173 180 174 181 int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) ··· 168 191 unsigned long flags; 169 192 int ret; 170 193 171 - mutex_lock(&queue->mutex); 172 194 ret = vb2_qbuf(&queue->queue, buf); 173 195 if (ret < 0) 174 - goto done; 196 + return ret; 175 197 176 198 spin_lock_irqsave(&queue->irqlock, flags); 177 199 ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; 178 200 queue->flags &= ~UVC_QUEUE_PAUSED; 179 201 spin_unlock_irqrestore(&queue->irqlock, flags); 180 - 181 - done: 182 - mutex_unlock(&queue->mutex); 183 202 return ret; 184 203 } 185 204 ··· 186 213 int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, 187 214 int nonblocking) 188 215 { 189 - int ret; 190 - 191 - mutex_lock(&queue->mutex); 192 - ret = vb2_dqbuf(&queue->queue, buf, nonblocking); 193 - mutex_unlock(&queue->mutex); 194 - 195 - return ret; 216 + return vb2_dqbuf(&queue->queue, buf, nonblocking); 196 217 } 197 218 198 219 /* ··· 198 231 unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, 199 232 poll_table *wait) 200 233 { 201 - unsigned int ret; 202 - 203 - mutex_lock(&queue->mutex); 204 - ret = vb2_poll(&queue->queue, file, wait); 205 - mutex_unlock(&queue->mutex); 206 - 207 - return ret; 234 + return vb2_poll(&queue->queue, file, wait); 208 235 } 209 236 210 237 int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) 211 238 { 212 - int ret; 213 - 214 - mutex_lock(&queue->mutex); 215 - ret = vb2_mmap(&queue->queue, vma); 216 - mutex_unlock(&queue->mutex); 217 - 218 - return ret; 239 + return vb2_mmap(&queue->queue, vma); 219 240 } 220 241 221 242 #ifndef CONFIG_MMU ··· 215 260 unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue, 216 261 unsigned long pgoff) 217 262 { 218 - unsigned long ret; 219 - 220 - mutex_lock(&queue->mutex); 221 - ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); 222 - mutex_unlock(&queue->mutex); 223 - return ret; 263 + return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); 224 264 } 225 265 #endif 226 266 ··· 277 327 unsigned long flags; 278 328 int ret = 0; 279 329 280 - mutex_lock(&queue->mutex); 281 330 if (enable) { 282 331 ret = vb2_streamon(&queue->queue, queue->queue.type); 283 332 if (ret < 0) 284 - goto done; 333 + return ret; 285 334 286 335 queue->sequence = 0; 287 336 queue->buf_used = 0; 288 337 } else { 289 338 ret = vb2_streamoff(&queue->queue, queue->queue.type); 290 339 if (ret < 0) 291 - goto done; 340 + return ret; 292 341 293 342 spin_lock_irqsave(&queue->irqlock, flags); 294 343 INIT_LIST_HEAD(&queue->irqqueue); ··· 302 353 spin_unlock_irqrestore(&queue->irqlock, flags); 303 354 } 304 355 305 - done: 306 - mutex_unlock(&queue->mutex); 307 356 return ret; 308 357 } 309 358
+2 -2
drivers/usb/gadget/function/uvc_queue.h
··· 41 41 42 42 struct uvc_video_queue { 43 43 struct vb2_queue queue; 44 - struct mutex mutex; /* Protects queue */ 45 44 46 45 unsigned int flags; 47 46 __u32 sequence; ··· 56 57 return vb2_is_streaming(&queue->queue); 57 58 } 58 59 59 - int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type); 60 + int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, 61 + struct mutex *lock); 60 62 61 63 void uvcg_free_buffers(struct uvc_video_queue *queue); 62 64
+2 -1
drivers/usb/gadget/function/uvc_v4l2.c
··· 14 14 #include <linux/device.h> 15 15 #include <linux/errno.h> 16 16 #include <linux/list.h> 17 - #include <linux/mutex.h> 18 17 #include <linux/videodev2.h> 19 18 #include <linux/vmalloc.h> 20 19 #include <linux/wait.h> ··· 310 311 311 312 uvc_function_disconnect(uvc); 312 313 314 + mutex_lock(&video->mutex); 313 315 uvcg_video_enable(video, 0); 314 316 uvcg_free_buffers(&video->queue); 317 + mutex_unlock(&video->mutex); 315 318 316 319 file->private_data = NULL; 317 320 v4l2_fh_del(&handle->vfh);
+2 -1
drivers/usb/gadget/function/uvc_video.c
··· 390 390 video->imagesize = 320 * 240 * 2; 391 391 392 392 /* Initialize the video buffers queue. */ 393 - uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); 393 + uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT, 394 + &video->mutex); 394 395 return 0; 395 396 } 396 397