media: uvcvideo: Abstract streaming object lifetime

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>
This commit is contained in:
Kieran Bingham 2018-11-09 09:26:10 -05:00 committed by Mauro Carvalho Chehab
parent 01e90464e4
commit ece41454c6

View 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);