media: uvcvideo: Abstract streaming object lifetime
authorKieran Bingham <kieran.bingham@ideasonboard.com>
Fri, 9 Nov 2018 14:26:10 +0000 (09:26 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 5 Dec 2018 08:13:48 +0000 (03:13 -0500)
The streaming object is a key part of handling the UVC device. Although
not critical, we are currently missing a call to destroy the mutex on
clean up paths, and we are due to extend the objects complexity in the
near future.

Facilitate easy management of a stream object by creating a pair of
functions to handle creating and destroying the allocation. The new
uvc_stream_delete() function also performs the missing mutex_destroy()
operation.

Previously a failed streaming object allocation would cause
uvc_parse_streaming() to return -EINVAL, which is inappropriate. If the
constructor failes, we will instead return -ENOMEM.

While we're here, fix the trivial spelling error in the function banner
of uvc_delete().

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/usb/uvc/uvc_driver.c

index 67bd58c6f3977481423903944363f145c646b0a9..afb44d1c9d043870de499d71e4debcf98bf6c958 100644 (file)
@@ -395,6 +395,39 @@ static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
        return NULL;
 }
 
+/* ------------------------------------------------------------------------
+ * Streaming Object Management
+ */
+
+static void uvc_stream_delete(struct uvc_streaming *stream)
+{
+       mutex_destroy(&stream->mutex);
+
+       usb_put_intf(stream->intf);
+
+       kfree(stream->format);
+       kfree(stream->header.bmaControls);
+       kfree(stream);
+}
+
+static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev,
+                                           struct usb_interface *intf)
+{
+       struct uvc_streaming *stream;
+
+       stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+       if (stream == NULL)
+               return NULL;
+
+       mutex_init(&stream->mutex);
+
+       stream->dev = dev;
+       stream->intf = usb_get_intf(intf);
+       stream->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       return stream;
+}
+
 /* ------------------------------------------------------------------------
  * Descriptors parsing
  */
@@ -687,17 +720,12 @@ static int uvc_parse_streaming(struct uvc_device *dev,
                return -EINVAL;
        }
 
-       streaming = kzalloc(sizeof(*streaming), GFP_KERNEL);
+       streaming = uvc_stream_new(dev, intf);
        if (streaming == NULL) {
                usb_driver_release_interface(&uvc_driver.driver, intf);
-               return -EINVAL;
+               return -ENOMEM;
        }
 
-       mutex_init(&streaming->mutex);
-       streaming->dev = dev;
-       streaming->intf = usb_get_intf(intf);
-       streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
        /* The Pico iMage webcam has its class-specific interface descriptors
         * after the endpoint descriptors.
         */
@@ -904,10 +932,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 
 error:
        usb_driver_release_interface(&uvc_driver.driver, intf);
-       usb_put_intf(intf);
-       kfree(streaming->format);
-       kfree(streaming->header.bmaControls);
-       kfree(streaming);
+       uvc_stream_delete(streaming);
        return ret;
 }
 
@@ -1815,7 +1840,7 @@ static int uvc_scan_device(struct uvc_device *dev)
  * is released.
  *
  * As this function is called after or during disconnect(), all URBs have
- * already been canceled by the USB core. There is no need to kill the
+ * already been cancelled by the USB core. There is no need to kill the
  * interrupt URB manually.
  */
 static void uvc_delete(struct kref *kref)
@@ -1853,10 +1878,7 @@ static void uvc_delete(struct kref *kref)
                streaming = list_entry(p, struct uvc_streaming, list);
                usb_driver_release_interface(&uvc_driver.driver,
                        streaming->intf);
-               usb_put_intf(streaming->intf);
-               kfree(streaming->format);
-               kfree(streaming->header.bmaControls);
-               kfree(streaming);
+               uvc_stream_delete(streaming);
        }
 
        kfree(dev);