@@ -1837,7 +1837,8 @@ static void uvc_delete(struct kref *kref)
struct uvc_device *dev = container_of(kref, struct uvc_device, ref);
struct list_head *p, *n;
- uvc_status_cleanup(dev);
+ if (dev->int_ep)
+ uvc_status_cleanup(dev);
uvc_ctrl_cleanup_device(dev);
usb_put_intf(dev->intf);
@@ -1898,7 +1899,8 @@ static void uvc_unregister_video(struct uvc_device *dev)
uvc_debugfs_cleanup_stream(stream);
}
- uvc_status_unregister(dev);
+ if (dev->int_ep)
+ uvc_status_unregister(dev);
if (dev->vdev.dev)
v4l2_device_unregister(&dev->vdev);
@@ -2199,10 +2201,13 @@ static int uvc_probe(struct usb_interface *intf,
usb_set_intfdata(intf, dev);
/* Initialize the interrupt URB. */
- if ((ret = uvc_status_init(dev)) < 0) {
- dev_info(&dev->udev->dev,
- "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n",
- ret);
+ if (dev->int_ep) {
+ ret = uvc_status_init(dev);
+ if (ret < 0) {
+ dev_info(&dev->udev->dev,
+ "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n",
+ ret);
+ }
}
ret = uvc_gpio_init_irq(dev);
@@ -2251,6 +2256,8 @@ 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) {
+ if (!dev->int_ep)
+ return 0;
mutex_lock(&dev->lock);
if (dev->users)
uvc_status_stop(dev);
@@ -2285,6 +2292,9 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
return ret;
}
+ if (!dev->int_ep)
+ return ret;
+
mutex_lock(&dev->lock);
if (dev->users)
ret = uvc_status_start(dev, GFP_NOIO);
@@ -277,7 +277,7 @@ int uvc_status_init(struct uvc_device *dev)
unsigned int pipe;
int interval;
- if (ep == NULL)
+ if (WARN_ON(!ep))
return 0;
uvc_input_init(dev);
@@ -312,19 +312,23 @@ int uvc_status_init(struct uvc_device *dev)
void uvc_status_unregister(struct uvc_device *dev)
{
+ if (WARN_ON(!dev->int_ep))
+ return;
usb_kill_urb(dev->int_urb);
uvc_input_unregister(dev);
}
void uvc_status_cleanup(struct uvc_device *dev)
{
+ if (WARN_ON(!dev->int_ep))
+ return;
usb_free_urb(dev->int_urb);
kfree(dev->status);
}
int uvc_status_start(struct uvc_device *dev, gfp_t flags)
{
- if (dev->int_urb == NULL)
+ if (WARN_ON(!dev->int_ep) || !dev->int_urb)
return 0;
return usb_submit_urb(dev->int_urb, flags);
@@ -332,5 +336,8 @@ int uvc_status_start(struct uvc_device *dev, gfp_t flags)
void uvc_status_stop(struct uvc_device *dev)
{
+ if (WARN_ON(!dev->int_ep) || !dev->int_urb)
+ return;
+
usb_kill_urb(dev->int_urb);
}
@@ -37,6 +37,9 @@ static int uvc_pm_get(struct uvc_streaming *stream)
if (ret)
return ret;
+ if (!stream->dev->int_ep)
+ return 0;
+
mutex_lock(&stream->dev->lock);
if (!stream->dev->users)
ret = uvc_status_start(stream->dev, GFP_KERNEL);
@@ -52,6 +55,9 @@ static int uvc_pm_get(struct uvc_streaming *stream)
static void uvc_pm_put(struct uvc_streaming *stream)
{
+ if (!stream->dev->int_ep)
+ goto done;
+
mutex_lock(&stream->dev->lock);
if (WARN_ON(!stream->dev->users)) {
mutex_unlock(&stream->dev->lock);
@@ -62,6 +68,7 @@ static void uvc_pm_put(struct uvc_streaming *stream)
uvc_status_stop(stream->dev);
mutex_unlock(&stream->dev->lock);
+done:
usb_autopm_put_interface(stream->dev->intf);
}
Instead of calling uvc_status_* regardless if the hw supports it or not, make all the calls conditional. This simplifies the locking during suspend/resume. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>