Commit 5146add6 authored by Kieran Bingham's avatar Kieran Bingham Committed by Greg Kroah-Hartman

media: uvcvideo: Abstract streaming object lifetime

[ Upstream commit ece41454 ]

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: default avatarKieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 1ff89e6d
......@@ -390,6 +390,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
*/
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment