Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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: 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
Loading
Loading
Loading
Loading
+38 −16
Original line number Diff line number Diff line
@@ -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);