Commit f9ffcb0a authored by Philipp Zabel's avatar Philipp Zabel Committed by Mauro Carvalho Chehab

media: uvcvideo: Fix driver reference counting

kref_init initializes the reference count to 1, not 0. This additional
reference is never released since the conversion to reference counters.
As a result, uvc_delete is not called anymore when UVC cameras are
disconnected.
Fix this by adding an additional kref_put in uvc_disconnect and in the
probe error path. This also allows to remove the temporary additional
reference in uvc_unregister_video.

Fixes: 9d15cd95 ("media: uvcvideo: Convert from using an atomic variable to a reference count")
Signed-off-by: default avatarPhilipp Zabel <philipp.zabel@gmail.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 6c0e931c
...@@ -1871,13 +1871,6 @@ static void uvc_unregister_video(struct uvc_device *dev) ...@@ -1871,13 +1871,6 @@ static void uvc_unregister_video(struct uvc_device *dev)
{ {
struct uvc_streaming *stream; struct uvc_streaming *stream;
/* Unregistering all video devices might result in uvc_delete() being
* called from inside the loop if there's no open file handle. To avoid
* that, increment the refcount before iterating over the streams and
* decrement it when done.
*/
kref_get(&dev->ref);
list_for_each_entry(stream, &dev->streams, list) { list_for_each_entry(stream, &dev->streams, list) {
if (!video_is_registered(&stream->vdev)) if (!video_is_registered(&stream->vdev))
continue; continue;
...@@ -1887,8 +1880,6 @@ static void uvc_unregister_video(struct uvc_device *dev) ...@@ -1887,8 +1880,6 @@ static void uvc_unregister_video(struct uvc_device *dev)
uvc_debugfs_cleanup_stream(stream); uvc_debugfs_cleanup_stream(stream);
} }
kref_put(&dev->ref, uvc_delete);
} }
int uvc_register_video_device(struct uvc_device *dev, int uvc_register_video_device(struct uvc_device *dev,
...@@ -2184,6 +2175,7 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -2184,6 +2175,7 @@ static int uvc_probe(struct usb_interface *intf,
error: error:
uvc_unregister_video(dev); uvc_unregister_video(dev);
kref_put(&dev->ref, uvc_delete);
return -ENODEV; return -ENODEV;
} }
...@@ -2201,6 +2193,7 @@ static void uvc_disconnect(struct usb_interface *intf) ...@@ -2201,6 +2193,7 @@ static void uvc_disconnect(struct usb_interface *intf)
return; return;
uvc_unregister_video(dev); uvc_unregister_video(dev);
kref_put(&dev->ref, uvc_delete);
} }
static int uvc_suspend(struct usb_interface *intf, pm_message_t message) static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
......
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