diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-07-03 10:50:51 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:45 -0400 |
commit | c11271349ad5d4647e69e511fc481b2dd390efc4 (patch) | |
tree | bc9ecda60fb903856dae5e21271e449e203a14bc /drivers/media/video/pwc | |
parent | 6c9cac89c009c049a9ad29cdf0f51892410fe751 (diff) |
[media] pwc: Allow dqbuf / read to complete while waiting for controls
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 3 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-v4l.c | 36 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 3 |
3 files changed, 38 insertions, 4 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 1d5a6db915fa..fdf113fe51c3 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -1160,6 +1160,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1160 | pwc_construct(pdev); /* set min/max sizes correct */ | 1160 | pwc_construct(pdev); /* set min/max sizes correct */ |
1161 | 1161 | ||
1162 | mutex_init(&pdev->modlock); | 1162 | mutex_init(&pdev->modlock); |
1163 | mutex_init(&pdev->udevlock); | ||
1163 | spin_lock_init(&pdev->queued_bufs_lock); | 1164 | spin_lock_init(&pdev->queued_bufs_lock); |
1164 | INIT_LIST_HEAD(&pdev->queued_bufs); | 1165 | INIT_LIST_HEAD(&pdev->queued_bufs); |
1165 | 1166 | ||
@@ -1297,6 +1298,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1297 | { | 1298 | { |
1298 | struct pwc_device *pdev = usb_get_intfdata(intf); | 1299 | struct pwc_device *pdev = usb_get_intfdata(intf); |
1299 | 1300 | ||
1301 | mutex_lock(&pdev->udevlock); | ||
1300 | mutex_lock(&pdev->modlock); | 1302 | mutex_lock(&pdev->modlock); |
1301 | 1303 | ||
1302 | usb_set_intfdata(intf, NULL); | 1304 | usb_set_intfdata(intf, NULL); |
@@ -1306,6 +1308,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1306 | pdev->udev = NULL; | 1308 | pdev->udev = NULL; |
1307 | 1309 | ||
1308 | mutex_unlock(&pdev->modlock); | 1310 | mutex_unlock(&pdev->modlock); |
1311 | mutex_unlock(&pdev->udevlock); | ||
1309 | 1312 | ||
1310 | pwc_remove_sysfs_files(pdev); | 1313 | pwc_remove_sysfs_files(pdev); |
1311 | video_unregister_device(&pdev->vdev); | 1314 | video_unregister_device(&pdev->vdev); |
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 986dd5d6187a..537657283e79 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -526,8 +526,24 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
526 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 526 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
527 | int ret = 0; | 527 | int ret = 0; |
528 | 528 | ||
529 | if (!pdev->udev) | 529 | /* |
530 | return -ENODEV; | 530 | * Sometimes it can take quite long for the pwc to complete usb control |
531 | * transfers, so release the modlock to give streaming by another | ||
532 | * process / thread the chance to continue with a dqbuf. | ||
533 | */ | ||
534 | mutex_unlock(&pdev->modlock); | ||
535 | |||
536 | /* | ||
537 | * Take the udev-lock to protect against the disconnect handler | ||
538 | * completing and setting dev->udev to NULL underneath us. Other code | ||
539 | * does not need to do this since it is protected by the modlock. | ||
540 | */ | ||
541 | mutex_lock(&pdev->udevlock); | ||
542 | |||
543 | if (!pdev->udev) { | ||
544 | ret = -ENODEV; | ||
545 | goto leave; | ||
546 | } | ||
531 | 547 | ||
532 | switch (ctrl->id) { | 548 | switch (ctrl->id) { |
533 | case V4L2_CID_AUTO_WHITE_BALANCE: | 549 | case V4L2_CID_AUTO_WHITE_BALANCE: |
@@ -590,6 +606,9 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
590 | if (ret) | 606 | if (ret) |
591 | PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret); | 607 | PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret); |
592 | 608 | ||
609 | leave: | ||
610 | mutex_unlock(&pdev->udevlock); | ||
611 | mutex_lock(&pdev->modlock); | ||
593 | return ret; | 612 | return ret; |
594 | } | 613 | } |
595 | 614 | ||
@@ -751,8 +770,14 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
751 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 770 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
752 | int ret = 0; | 771 | int ret = 0; |
753 | 772 | ||
754 | if (!pdev->udev) | 773 | /* See the comments on locking in pwc_g_volatile_ctrl */ |
755 | return -ENODEV; | 774 | mutex_unlock(&pdev->modlock); |
775 | mutex_lock(&pdev->udevlock); | ||
776 | |||
777 | if (!pdev->udev) { | ||
778 | ret = -ENODEV; | ||
779 | goto leave; | ||
780 | } | ||
756 | 781 | ||
757 | switch (ctrl->id) { | 782 | switch (ctrl->id) { |
758 | case V4L2_CID_BRIGHTNESS: | 783 | case V4L2_CID_BRIGHTNESS: |
@@ -841,6 +866,9 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
841 | if (ret) | 866 | if (ret) |
842 | PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); | 867 | PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); |
843 | 868 | ||
869 | leave: | ||
870 | mutex_unlock(&pdev->udevlock); | ||
871 | mutex_lock(&pdev->modlock); | ||
844 | return ret; | 872 | return ret; |
845 | } | 873 | } |
846 | 874 | ||
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 601a549988b5..e02dbf745155 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -200,6 +200,9 @@ struct pwc_device | |||
200 | 200 | ||
201 | /* Pointer to our usb_device, may be NULL after unplug */ | 201 | /* Pointer to our usb_device, may be NULL after unplug */ |
202 | struct usb_device *udev; | 202 | struct usb_device *udev; |
203 | /* Protects the setting of udev to NULL by our disconnect handler */ | ||
204 | struct mutex udevlock; | ||
205 | |||
203 | /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ | 206 | /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ |
204 | int type; | 207 | int type; |
205 | int release; /* release number */ | 208 | int release; /* release number */ |