aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-11-21 11:36:34 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-01 17:10:24 -0500
commit6947756dfcecc493062a46e77f6bf51dddb5be75 (patch)
tree9ef949c2b95d43ce0389ea6d54b5b469322aaf0b /drivers/media/video
parent4aa275975beee41fd542a0f6df8cd0fee06089bf (diff)
[media] uvcvideo: Lock stream mutex when accessing format-related information
The stream mutex protects access to the struct uvc_streaming ctrl, cur_format and cur_frame fields as well as to the hardware probe control. Lock it appropriately. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c78
-rw-r--r--drivers/media/video/uvc/uvc_video.c3
-rw-r--r--drivers/media/video/uvc/uvcvideo.h4
3 files changed, 58 insertions, 27 deletions
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 07dd2357fbb9..2f6dc6b97348 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -226,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
226 * developers test their webcams with the Linux driver as well as with 226 * developers test their webcams with the Linux driver as well as with
227 * the Windows driver). 227 * the Windows driver).
228 */ 228 */
229 mutex_lock(&stream->mutex);
229 if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) 230 if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
230 probe->dwMaxVideoFrameSize = 231 probe->dwMaxVideoFrameSize =
231 stream->ctrl.dwMaxVideoFrameSize; 232 stream->ctrl.dwMaxVideoFrameSize;
232 233
233 /* Probe the device. */ 234 /* Probe the device. */
234 ret = uvc_probe_video(stream, probe); 235 ret = uvc_probe_video(stream, probe);
236 mutex_unlock(&stream->mutex);
235 if (ret < 0) 237 if (ret < 0)
236 goto done; 238 goto done;
237 239
@@ -255,14 +257,21 @@ done:
255static int uvc_v4l2_get_format(struct uvc_streaming *stream, 257static int uvc_v4l2_get_format(struct uvc_streaming *stream,
256 struct v4l2_format *fmt) 258 struct v4l2_format *fmt)
257{ 259{
258 struct uvc_format *format = stream->cur_format; 260 struct uvc_format *format;
259 struct uvc_frame *frame = stream->cur_frame; 261 struct uvc_frame *frame;
262 int ret = 0;
260 263
261 if (fmt->type != stream->type) 264 if (fmt->type != stream->type)
262 return -EINVAL; 265 return -EINVAL;
263 266
264 if (format == NULL || frame == NULL) 267 mutex_lock(&stream->mutex);
265 return -EINVAL; 268 format = stream->cur_format;
269 frame = stream->cur_frame;
270
271 if (format == NULL || frame == NULL) {
272 ret = -EINVAL;
273 goto done;
274 }
266 275
267 fmt->fmt.pix.pixelformat = format->fcc; 276 fmt->fmt.pix.pixelformat = format->fcc;
268 fmt->fmt.pix.width = frame->wWidth; 277 fmt->fmt.pix.width = frame->wWidth;
@@ -273,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
273 fmt->fmt.pix.colorspace = format->colorspace; 282 fmt->fmt.pix.colorspace = format->colorspace;
274 fmt->fmt.pix.priv = 0; 283 fmt->fmt.pix.priv = 0;
275 284
276 return 0; 285done:
286 mutex_unlock(&stream->mutex);
287 return ret;
277} 288}
278 289
279static int uvc_v4l2_set_format(struct uvc_streaming *stream, 290static int uvc_v4l2_set_format(struct uvc_streaming *stream,
@@ -287,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
287 if (fmt->type != stream->type) 298 if (fmt->type != stream->type)
288 return -EINVAL; 299 return -EINVAL;
289 300
290 if (uvc_queue_allocated(&stream->queue))
291 return -EBUSY;
292
293 ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); 301 ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
294 if (ret < 0) 302 if (ret < 0)
295 return ret; 303 return ret;
296 304
305 mutex_lock(&stream->mutex);
306
307 if (uvc_queue_allocated(&stream->queue)) {
308 ret = -EBUSY;
309 goto done;
310 }
311
297 memcpy(&stream->ctrl, &probe, sizeof probe); 312 memcpy(&stream->ctrl, &probe, sizeof probe);
298 stream->cur_format = format; 313 stream->cur_format = format;
299 stream->cur_frame = frame; 314 stream->cur_frame = frame;
300 315
301 return 0; 316done:
317 mutex_unlock(&stream->mutex);
318 return ret;
302} 319}
303 320
304static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, 321static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
@@ -309,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
309 if (parm->type != stream->type) 326 if (parm->type != stream->type)
310 return -EINVAL; 327 return -EINVAL;
311 328
329 mutex_lock(&stream->mutex);
312 numerator = stream->ctrl.dwFrameInterval; 330 numerator = stream->ctrl.dwFrameInterval;
331 mutex_unlock(&stream->mutex);
332
313 denominator = 10000000; 333 denominator = 10000000;
314 uvc_simplify_fraction(&numerator, &denominator, 8, 333); 334 uvc_simplify_fraction(&numerator, &denominator, 8, 333);
315 335
@@ -336,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
336static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, 356static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
337 struct v4l2_streamparm *parm) 357 struct v4l2_streamparm *parm)
338{ 358{
339 struct uvc_frame *frame = stream->cur_frame;
340 struct uvc_streaming_control probe; 359 struct uvc_streaming_control probe;
341 struct v4l2_fract timeperframe; 360 struct v4l2_fract timeperframe;
342 uint32_t interval; 361 uint32_t interval;
@@ -345,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
345 if (parm->type != stream->type) 364 if (parm->type != stream->type)
346 return -EINVAL; 365 return -EINVAL;
347 366
348 if (uvc_queue_streaming(&stream->queue))
349 return -EBUSY;
350
351 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 367 if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
352 timeperframe = parm->parm.capture.timeperframe; 368 timeperframe = parm->parm.capture.timeperframe;
353 else 369 else
354 timeperframe = parm->parm.output.timeperframe; 370 timeperframe = parm->parm.output.timeperframe;
355 371
356 memcpy(&probe, &stream->ctrl, sizeof probe);
357 interval = uvc_fraction_to_interval(timeperframe.numerator, 372 interval = uvc_fraction_to_interval(timeperframe.numerator,
358 timeperframe.denominator); 373 timeperframe.denominator);
359
360 uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", 374 uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
361 timeperframe.numerator, timeperframe.denominator, interval); 375 timeperframe.numerator, timeperframe.denominator, interval);
362 probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); 376
377 mutex_lock(&stream->mutex);
378
379 if (uvc_queue_streaming(&stream->queue)) {
380 mutex_unlock(&stream->mutex);
381 return -EBUSY;
382 }
383
384 memcpy(&probe, &stream->ctrl, sizeof probe);
385 probe.dwFrameInterval =
386 uvc_try_frame_interval(stream->cur_frame, interval);
363 387
364 /* Probe the device with the new settings. */ 388 /* Probe the device with the new settings. */
365 ret = uvc_probe_video(stream, &probe); 389 ret = uvc_probe_video(stream, &probe);
366 if (ret < 0) 390 if (ret < 0) {
391 mutex_unlock(&stream->mutex);
367 return ret; 392 return ret;
393 }
368 394
369 memcpy(&stream->ctrl, &probe, sizeof probe); 395 memcpy(&stream->ctrl, &probe, sizeof probe);
396 mutex_unlock(&stream->mutex);
370 397
371 /* Return the actual frame period. */ 398 /* Return the actual frame period. */
372 timeperframe.numerator = probe.dwFrameInterval; 399 timeperframe.numerator = probe.dwFrameInterval;
@@ -869,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
869 case VIDIOC_CROPCAP: 896 case VIDIOC_CROPCAP:
870 { 897 {
871 struct v4l2_cropcap *ccap = arg; 898 struct v4l2_cropcap *ccap = arg;
872 struct uvc_frame *frame = stream->cur_frame;
873 899
874 if (ccap->type != stream->type) 900 if (ccap->type != stream->type)
875 return -EINVAL; 901 return -EINVAL;
876 902
877 ccap->bounds.left = 0; 903 ccap->bounds.left = 0;
878 ccap->bounds.top = 0; 904 ccap->bounds.top = 0;
879 ccap->bounds.width = frame->wWidth; 905
880 ccap->bounds.height = frame->wHeight; 906 mutex_lock(&stream->mutex);
907 ccap->bounds.width = stream->cur_frame->wWidth;
908 ccap->bounds.height = stream->cur_frame->wHeight;
909 mutex_unlock(&stream->mutex);
881 910
882 ccap->defrect = ccap->bounds; 911 ccap->defrect = ccap->bounds;
883 912
@@ -894,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
894 case VIDIOC_REQBUFS: 923 case VIDIOC_REQBUFS:
895 { 924 {
896 struct v4l2_requestbuffers *rb = arg; 925 struct v4l2_requestbuffers *rb = arg;
897 unsigned int bufsize =
898 stream->ctrl.dwMaxVideoFrameSize;
899 926
900 if (rb->type != stream->type || 927 if (rb->type != stream->type ||
901 rb->memory != V4L2_MEMORY_MMAP) 928 rb->memory != V4L2_MEMORY_MMAP)
@@ -904,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
904 if ((ret = uvc_acquire_privileges(handle)) < 0) 931 if ((ret = uvc_acquire_privileges(handle)) < 0)
905 return ret; 932 return ret;
906 933
907 ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); 934 mutex_lock(&stream->mutex);
935 ret = uvc_alloc_buffers(&stream->queue, rb->count,
936 stream->ctrl.dwMaxVideoFrameSize);
937 mutex_unlock(&stream->mutex);
908 if (ret < 0) 938 if (ret < 0)
909 return ret; 939 return ret;
910 940
@@ -952,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
952 if (!uvc_has_privileges(handle)) 982 if (!uvc_has_privileges(handle))
953 return -EBUSY; 983 return -EBUSY;
954 984
985 mutex_lock(&stream->mutex);
955 ret = uvc_video_enable(stream, 1); 986 ret = uvc_video_enable(stream, 1);
987 mutex_unlock(&stream->mutex);
956 if (ret < 0) 988 if (ret < 0)
957 return ret; 989 return ret;
958 break; 990 break;
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 5555f0102838..5673d673504b 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
293 unsigned int i; 293 unsigned int i;
294 int ret; 294 int ret;
295 295
296 mutex_lock(&stream->mutex);
297
298 /* Perform probing. The device should adjust the requested values 296 /* Perform probing. The device should adjust the requested values
299 * according to its capabilities. However, some devices, namely the 297 * according to its capabilities. However, some devices, namely the
300 * first generation UVC Logitech webcams, don't implement the Video 298 * first generation UVC Logitech webcams, don't implement the Video
@@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
346 } 344 }
347 345
348done: 346done:
349 mutex_unlock(&stream->mutex);
350 return ret; 347 return ret;
351} 348}
352 349
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index ea893bc0df07..45f01e7e13d2 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -436,7 +436,9 @@ struct uvc_streaming {
436 struct uvc_streaming_control ctrl; 436 struct uvc_streaming_control ctrl;
437 struct uvc_format *cur_format; 437 struct uvc_format *cur_format;
438 struct uvc_frame *cur_frame; 438 struct uvc_frame *cur_frame;
439 439 /* Protect access to ctrl, cur_format, cur_frame and hardware video
440 * probe control.
441 */
440 struct mutex mutex; 442 struct mutex mutex;
441 443
442 unsigned int frozen : 1; 444 unsigned int frozen : 1;