|
@@ -1836,8 +1836,8 @@ static int uvc_probe(struct usb_interface *intf,
|
|
|
INIT_LIST_HEAD(&dev->chains);
|
|
|
INIT_LIST_HEAD(&dev->streams);
|
|
|
atomic_set(&dev->nstreams, 0);
|
|
|
- atomic_set(&dev->users, 0);
|
|
|
atomic_set(&dev->nmappings, 0);
|
|
|
+ mutex_init(&dev->lock);
|
|
|
|
|
|
dev->udev = usb_get_dev(udev);
|
|
|
dev->intf = usb_get_intf(intf);
|
|
@@ -1950,8 +1950,13 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
|
|
|
|
|
|
/* Controls are cached on the fly so they don't need to be saved. */
|
|
|
if (intf->cur_altsetting->desc.bInterfaceSubClass ==
|
|
|
- UVC_SC_VIDEOCONTROL)
|
|
|
- return uvc_status_suspend(dev);
|
|
|
+ UVC_SC_VIDEOCONTROL) {
|
|
|
+ mutex_lock(&dev->lock);
|
|
|
+ if (dev->users)
|
|
|
+ uvc_status_stop(dev);
|
|
|
+ mutex_unlock(&dev->lock);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
list_for_each_entry(stream, &dev->streams, list) {
|
|
|
if (stream->intf == intf)
|
|
@@ -1973,14 +1978,20 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
|
|
|
|
|
|
if (intf->cur_altsetting->desc.bInterfaceSubClass ==
|
|
|
UVC_SC_VIDEOCONTROL) {
|
|
|
- if (reset) {
|
|
|
- int ret = uvc_ctrl_resume_device(dev);
|
|
|
+ int ret = 0;
|
|
|
|
|
|
+ if (reset) {
|
|
|
+ ret = uvc_ctrl_resume_device(dev);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- return uvc_status_resume(dev);
|
|
|
+ mutex_lock(&dev->lock);
|
|
|
+ if (dev->users)
|
|
|
+ ret = uvc_status_start(dev, GFP_NOIO);
|
|
|
+ mutex_unlock(&dev->lock);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
list_for_each_entry(stream, &dev->streams, list) {
|