summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@ideasonboard.com>2018-11-09 09:26:10 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-13 08:52:27 +0100
commit5146add60adf31ae4d02cfac0150eb8f8d3aa9b7 (patch)
tree4dc41d0141515ea432e2ad6098aeeef3fad6d16c
parent1ff89e6d4b2332801bfaf5ab3cfd6660b7096bd0 (diff)
downloadlinux-stable-5146add60adf31ae4d02cfac0150eb8f8d3aa9b7.tar.gz
linux-stable-5146add60adf31ae4d02cfac0150eb8f8d3aa9b7.tar.bz2
linux-stable-5146add60adf31ae4d02cfac0150eb8f8d3aa9b7.zip
media: uvcvideo: Abstract streaming object lifetime
[ Upstream commit ece41454c6a5ed8f301ef1c37710ab222e577823 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c54
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index cf4feff2a48c..063e229ead5e 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -391,6 +391,39 @@ static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
}
/* ------------------------------------------------------------------------
+ * 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
*/
@@ -682,17 +715,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.
*/
@@ -899,10 +927,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;
}
@@ -1818,7 +1843,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)
@@ -1856,10 +1881,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);