Message ID | 20170423045349.10292-1-dja@axtens.net (mailing list archive) |
---|---|
State | Accepted, archived |
Delegated to: | Laurent Pinchart |
Headers |
Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from <linux-media-owner@vger.kernel.org>) id 1d29Yu-0006h1-8Z; Sun, 23 Apr 2017 04:55:52 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.84_2/mailfrontend-7) with esmtp id 1d29Yr-000296-2d; Sun, 23 Apr 2017 06:55:52 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755482AbdDWEyj (ORCPT <rfc822;mkrufky@linuxtv.org> + 1 other); Sun, 23 Apr 2017 00:54:39 -0400 Received: from mail-it0-f67.google.com ([209.85.214.67]:34666 "EHLO mail-it0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755368AbdDWEyh (ORCPT <rfc822;linux-media@vger.kernel.org>); Sun, 23 Apr 2017 00:54:37 -0400 Received: by mail-it0-f67.google.com with SMTP id c26so55338itd.1 for <linux-media@vger.kernel.org>; Sat, 22 Apr 2017 21:54:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id; bh=5a4bc4+YF7BR3uRLc4mweB/arHfhIu2M032HvqTTjpU=; b=O4hjeLehfkjqWOMJ/K0HzF7pLzEhu5sJckrcxS44Es4obD7oWqdu46NTqGhULeMMVA 6y5Gh+iRh6sX0ZF0EOypDJmucuqUIlb+3JYmo5ToLlfPWEDvVNi54CjXFcPS376VAyZN 1t4z7gFll4PP6bwOv8RTLEnvV7+vMUBwl7vSU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=5a4bc4+YF7BR3uRLc4mweB/arHfhIu2M032HvqTTjpU=; b=jWuOYFFDo7bxy+6bx1pQiPZdZpWdyuziS0v1HW+V9fok2/gXDurq7ugBJTjkqnNGDb jdU9TP3x7v2C23u9xFGJGMoJu9Kikg3Wr7MuStKWVYNh1y/eAtqfPU+Pay68vetgvs/v lPi0epbVReok27I43cVteJp36DGVy1ka8aK9cjVgAhrfsGxM4qJLoiSP5IVsPe9wYowK 3q/rk41noh8E3sYKs4tY5yp1Wy6qJ2EeI8gQHqKtJmO5L8zX81hJY5IqlMM+fBjeJr68 cxsrjdxT77YVios5feE2Mry2UwJqfReZo6iuZsjfp41lHIC6aVw5B0X5vzyh4LsjKuDc o5RA== X-Gm-Message-State: AN3rC/5l3OnjASZCaq8wV9EHPUHO1tdiLFph2MeB2VYao8RC6L5o6vJ5 kja4qbRu1HVGCg== X-Received: by 10.84.197.3 with SMTP id m3mr24809187pld.3.1492923276228; Sat, 22 Apr 2017 21:54:36 -0700 (PDT) Received: from localhost.localdomain (124-171-164-116.dyn.iinet.net.au. [124.171.164.116]) by smtp.gmail.com with ESMTPSA id e71sm9700739pgc.17.2017.04.22.21.54.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 22 Apr 2017 21:54:35 -0700 (PDT) From: Daniel Axtens <dja@axtens.net> To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Daniel Axtens <dja@axtens.net>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Dave Stevenson <linux-media@destevenson.freeserve.co.uk>, Greg KH <greg@kroah.com> Subject: [PATCH v2] [media] uvcvideo: Refactor teardown of uvc on USB disconnect Date: Sun, 23 Apr 2017 14:53:49 +1000 Message-Id: <20170423045349.10292-1-dja@axtens.net> X-Mailer: git-send-email 2.11.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: <linux-media.vger.kernel.org> X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2017.4.23.44516 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_5000_5999 0, BODY_SIZE_7000_LESS 0, CHILD_EX_X3 0, DKIM_SIGNATURE 0, LEGITIMATE_SIGNS 0, MULTIPLE_REAL_RCPTS 0, SINGLE_URI_IN_BODY 0, URI_WITH_PATH_ONLY 0, __ANY_URI 0, __CC_NAME 0, __CC_NAME_DIFF_FROM_ACC 0, __CC_REAL_NAMES 0, __CP_MEDIA_BODY 0, __CP_NAME_BODY 0, __CP_URI_IN_BODY 0, __FROM_DOMAIN_IN_ANY_CC2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_LIST_ID 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __HTTPS_URI 0, __MIME_TEXT_ONLY 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MULTIPLE_RCPTS_CC_X2 0, __NO_HTML_TAG_RAW 0, __SANE_MSGID 0, __SINGLE_URI_TEXT 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_IN_BODY 0, __URI_NOT_IMG 0, __URI_NO_WWW 0, __URI_NS , __URI_WITH_PATH 0, __YOUTUBE_RCVD 0' |
Commit Message
Daniel Axtens
April 23, 2017, 4:53 a.m. UTC
Currently, disconnecting a USB webcam while it is in use prints out a
number of warnings, such as:
WARNING: CPU: 2 PID: 3118 at /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 sysfs_remove_group+0x8b/0x90
sysfs group ffffffffa7cd0780 not found for kobject 'event13'
This has been noticed before. [0]
This is because of the order in which things are torn down.
If there are no streams active during a USB disconnect:
- uvc_disconnect() is invoked via device_del() through the bus
notifier mechanism.
- this calls uvc_unregister_video().
- uvc_unregister_video() unregisters the video device for each
stream,
- because there are no streams open, it calls uvc_delete()
- uvc_delete() calls uvc_status_cleanup(), which cleans up the status
input device.
- uvc_delete() calls media_device_unregister(), which cleans up the
media device
- uvc_delete(), uvc_unregister_video() and uvc_disconnect() all
return, and we end up back in device_del().
- device_del() then cleans up the sysfs folder for the camera with
dpm_sysfs_remove(). Because uvc_status_cleanup() and
media_device_unregister() have already been called, this all works
nicely.
If, on the other hand, there *are* streams active during a USB disconnect:
- uvc_disconnect() is invoked
- this calls uvc_unregister_video()
- uvc_unregister_video() unregisters the video device for each
stream,
- uvc_unregister_video() and uvc_disconnect() return, and we end up
back in device_del().
- device_del() then cleans up the sysfs folder for the camera with
dpm_sysfs_remove(). Because the status input device and the media
device are children of the USB device, this also deletes their
sysfs folders.
- Sometime later, the final stream is closed, invoking uvc_release().
- uvc_release() calls uvc_delete()
- uvc_delete() calls uvc_status_cleanup(), which cleans up the status
input device. Because the sysfs directory has already been removed,
this causes a WARNing.
- uvc_delete() calls media_device_unregister(), which cleans up the
media device. Because the sysfs directory has already been removed,
this causes another WARNing.
To fix this, we need to make sure the devices are always unregistered
before the end of uvc_disconnect(). To this, move the unregistration
into the disconnect path:
- split uvc_status_cleanup() into two parts, one on disconnect that
unregisters and one on delete that frees.
- move v4l2_device_unregister() and media_device_unregister() into
the disconnect path.
[0]: https://lkml.org/lkml/2016/12/8/657
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Dave Stevenson <linux-media@destevenson.freeserve.co.uk>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
v2: Move v4l2_device_unregister() as well as media_device_unregister(),
thanks Laurent.
Tested with cheese and yavta.
Laurent, I know you were concerned about race conditions so I plugged
and unplugged the camera over a dozen times, with lots of debugging
turned on.
In particular:
- KASan was enabled and didn't trigger
- If I unplugged while yavta was running, and replugged *while yatva
was still running*, the video camera came up as video2, not video1.
This indicates that yatva was successfully holding a reference to
video1 - as it should.
- No other debugging triggered any warning.
---
drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++----
drivers/media/usb/uvc/uvc_status.c | 8 ++++++--
drivers/media/usb/uvc/uvcvideo.h | 1 +
3 files changed, 15 insertions(+), 6 deletions(-)
Comments
On Sun, Apr 23, 2017 at 02:53:49PM +1000, Daniel Axtens wrote: > Currently, disconnecting a USB webcam while it is in use prints out a > number of warnings, such as: > > WARNING: CPU: 2 PID: 3118 at /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 sysfs_remove_group+0x8b/0x90 > sysfs group ffffffffa7cd0780 not found for kobject 'event13' > > This has been noticed before. [0] > > This is because of the order in which things are torn down. > > If there are no streams active during a USB disconnect: > > - uvc_disconnect() is invoked via device_del() through the bus > notifier mechanism. > > - this calls uvc_unregister_video(). > > - uvc_unregister_video() unregisters the video device for each > stream, > > - because there are no streams open, it calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device > > - uvc_delete(), uvc_unregister_video() and uvc_disconnect() all > return, and we end up back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because uvc_status_cleanup() and > media_device_unregister() have already been called, this all works > nicely. > > If, on the other hand, there *are* streams active during a USB disconnect: > > - uvc_disconnect() is invoked > > - this calls uvc_unregister_video() > > - uvc_unregister_video() unregisters the video device for each > stream, > > - uvc_unregister_video() and uvc_disconnect() return, and we end up > back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because the status input device and the media > device are children of the USB device, this also deletes their > sysfs folders. > > - Sometime later, the final stream is closed, invoking uvc_release(). > > - uvc_release() calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. Because the sysfs directory has already been removed, > this causes a WARNing. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device. Because the sysfs directory has already been removed, > this causes another WARNing. > > To fix this, we need to make sure the devices are always unregistered > before the end of uvc_disconnect(). To this, move the unregistration > into the disconnect path: > > - split uvc_status_cleanup() into two parts, one on disconnect that > unregisters and one on delete that frees. > > - move v4l2_device_unregister() and media_device_unregister() into > the disconnect path. > > [0]: https://lkml.org/lkml/2016/12/8/657 > > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Cc: Dave Stevenson <linux-media@destevenson.freeserve.co.uk> > Cc: Greg KH <greg@kroah.com> > Signed-off-by: Daniel Axtens <dja@axtens.net> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Very nice work, what a tangled web this is... greg k-h
Hi Laurent, Just checking if this was OK with you - I hadn't heard anything and I noticed it's not in -next so I just wanted to check to see if there were any changes you wanted. Regards, Daniel Daniel Axtens <dja@axtens.net> writes: > Currently, disconnecting a USB webcam while it is in use prints out a > number of warnings, such as: > > WARNING: CPU: 2 PID: 3118 at /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 sysfs_remove_group+0x8b/0x90 > sysfs group ffffffffa7cd0780 not found for kobject 'event13' > > This has been noticed before. [0] > > This is because of the order in which things are torn down. > > If there are no streams active during a USB disconnect: > > - uvc_disconnect() is invoked via device_del() through the bus > notifier mechanism. > > - this calls uvc_unregister_video(). > > - uvc_unregister_video() unregisters the video device for each > stream, > > - because there are no streams open, it calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device > > - uvc_delete(), uvc_unregister_video() and uvc_disconnect() all > return, and we end up back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because uvc_status_cleanup() and > media_device_unregister() have already been called, this all works > nicely. > > If, on the other hand, there *are* streams active during a USB disconnect: > > - uvc_disconnect() is invoked > > - this calls uvc_unregister_video() > > - uvc_unregister_video() unregisters the video device for each > stream, > > - uvc_unregister_video() and uvc_disconnect() return, and we end up > back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because the status input device and the media > device are children of the USB device, this also deletes their > sysfs folders. > > - Sometime later, the final stream is closed, invoking uvc_release(). > > - uvc_release() calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. Because the sysfs directory has already been removed, > this causes a WARNing. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device. Because the sysfs directory has already been removed, > this causes another WARNing. > > To fix this, we need to make sure the devices are always unregistered > before the end of uvc_disconnect(). To this, move the unregistration > into the disconnect path: > > - split uvc_status_cleanup() into two parts, one on disconnect that > unregisters and one on delete that frees. > > - move v4l2_device_unregister() and media_device_unregister() into > the disconnect path. > > [0]: https://lkml.org/lkml/2016/12/8/657 > > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Cc: Dave Stevenson <linux-media@destevenson.freeserve.co.uk> > Cc: Greg KH <greg@kroah.com> > Signed-off-by: Daniel Axtens <dja@axtens.net> > > --- > > v2: Move v4l2_device_unregister() as well as media_device_unregister(), > thanks Laurent. > > Tested with cheese and yavta. > > Laurent, I know you were concerned about race conditions so I plugged > and unplugged the camera over a dozen times, with lots of debugging > turned on. > > In particular: > - KASan was enabled and didn't trigger > - If I unplugged while yavta was running, and replugged *while yatva > was still running*, the video camera came up as video2, not video1. > This indicates that yatva was successfully holding a reference to > video1 - as it should. > - No other debugging triggered any warning. > --- > drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++---- > drivers/media/usb/uvc/uvc_status.c | 8 ++++++-- > drivers/media/usb/uvc/uvcvideo.h | 1 + > 3 files changed, 15 insertions(+), 6 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > index 46d6be0bb316..0d0541054ce2 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -1812,11 +1812,7 @@ static void uvc_delete(struct uvc_device *dev) > usb_put_intf(dev->intf); > usb_put_dev(dev->udev); > > - if (dev->vdev.dev) > - v4l2_device_unregister(&dev->vdev); > #ifdef CONFIG_MEDIA_CONTROLLER > - if (media_devnode_is_registered(dev->mdev.devnode)) > - media_device_unregister(&dev->mdev); > media_device_cleanup(&dev->mdev); > #endif > > @@ -1884,6 +1880,14 @@ static void uvc_unregister_video(struct uvc_device *dev) > uvc_debugfs_cleanup_stream(stream); > } > > + uvc_status_unregister(dev); > + if (dev->vdev.dev) > + v4l2_device_unregister(&dev->vdev); > +#ifdef CONFIG_MEDIA_CONTROLLER > + if (media_devnode_is_registered(dev->mdev.devnode)) > + media_device_unregister(&dev->mdev); > +#endif > + > /* Decrement the stream count and call uvc_delete explicitly if there > * are no stream left. > */ > diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c > index f552ab997956..95709b23d3b4 100644 > --- a/drivers/media/usb/uvc/uvc_status.c > +++ b/drivers/media/usb/uvc/uvc_status.c > @@ -198,12 +198,16 @@ int uvc_status_init(struct uvc_device *dev) > return 0; > } > > -void uvc_status_cleanup(struct uvc_device *dev) > +void uvc_status_unregister(struct uvc_device *dev) > { > usb_kill_urb(dev->int_urb); > + uvc_input_cleanup(dev); > +} > + > +void uvc_status_cleanup(struct uvc_device *dev) > +{ > usb_free_urb(dev->int_urb); > kfree(dev->status); > - uvc_input_cleanup(dev); > } > > int uvc_status_start(struct uvc_device *dev, gfp_t flags) > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index 15e415e32c7f..4b4814df35cd 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -712,6 +712,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream, > > /* Status */ > extern int uvc_status_init(struct uvc_device *dev); > +extern void uvc_status_unregister(struct uvc_device *dev); > extern void uvc_status_cleanup(struct uvc_device *dev); > extern int uvc_status_start(struct uvc_device *dev, gfp_t flags); > extern void uvc_status_stop(struct uvc_device *dev); > -- > 2.11.0
Hi Daniel, Thank you for the patch. On Sunday, 23 April 2017 07:53:49 EET Daniel Axtens wrote: > Currently, disconnecting a USB webcam while it is in use prints out a > number of warnings, such as: > > WARNING: CPU: 2 PID: 3118 at > /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 > sysfs_remove_group+0x8b/0x90 sysfs group ffffffffa7cd0780 not found for > kobject 'event13' > > This has been noticed before. [0] > > This is because of the order in which things are torn down. > > If there are no streams active during a USB disconnect: > > - uvc_disconnect() is invoked via device_del() through the bus > notifier mechanism. > > - this calls uvc_unregister_video(). > > - uvc_unregister_video() unregisters the video device for each > stream, > > - because there are no streams open, it calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device > > - uvc_delete(), uvc_unregister_video() and uvc_disconnect() all > return, and we end up back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because uvc_status_cleanup() and > media_device_unregister() have already been called, this all works > nicely. > > If, on the other hand, there *are* streams active during a USB disconnect: > > - uvc_disconnect() is invoked > > - this calls uvc_unregister_video() > > - uvc_unregister_video() unregisters the video device for each > stream, > > - uvc_unregister_video() and uvc_disconnect() return, and we end up > back in device_del(). > > - device_del() then cleans up the sysfs folder for the camera with > dpm_sysfs_remove(). Because the status input device and the media > device are children of the USB device, this also deletes their > sysfs folders. > > - Sometime later, the final stream is closed, invoking uvc_release(). > > - uvc_release() calls uvc_delete() > > - uvc_delete() calls uvc_status_cleanup(), which cleans up the status > input device. Because the sysfs directory has already been removed, > this causes a WARNing. > > - uvc_delete() calls media_device_unregister(), which cleans up the > media device. Because the sysfs directory has already been removed, > this causes another WARNing. > > To fix this, we need to make sure the devices are always unregistered > before the end of uvc_disconnect(). To this, move the unregistration > into the disconnect path: > > - split uvc_status_cleanup() into two parts, one on disconnect that > unregisters and one on delete that frees. > > - move v4l2_device_unregister() and media_device_unregister() into > the disconnect path. > > [0]: https://lkml.org/lkml/2016/12/8/657 > > Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Cc: Dave Stevenson <linux-media@destevenson.freeserve.co.uk> > Cc: Greg KH <greg@kroah.com> > Signed-off-by: Daniel Axtens <dja@axtens.net> > > --- > > v2: Move v4l2_device_unregister() as well as media_device_unregister(), > thanks Laurent. > > Tested with cheese and yavta. > > Laurent, I know you were concerned about race conditions so I plugged > and unplugged the camera over a dozen times, with lots of debugging > turned on. > > In particular: > - KASan was enabled and didn't trigger > - If I unplugged while yavta was running, and replugged *while yatva > was still running*, the video camera came up as video2, not video1. > This indicates that yatva was successfully holding a reference to > video1 - as it should. > - No other debugging triggered any warning. Thank you for running those tests. I'm still a bit concerned but I'll live with it. The issues are in the MC and V4L2 core anyway, there isn't much we could do here to fix them. > --- > drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++---- > drivers/media/usb/uvc/uvc_status.c | 8 ++++++-- > drivers/media/usb/uvc/uvcvideo.h | 1 + > 3 files changed, 15 insertions(+), 6 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_driver.c > b/drivers/media/usb/uvc/uvc_driver.c index 46d6be0bb316..0d0541054ce2 > 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -1812,11 +1812,7 @@ static void uvc_delete(struct uvc_device *dev) > usb_put_intf(dev->intf); > usb_put_dev(dev->udev); > > - if (dev->vdev.dev) > - v4l2_device_unregister(&dev->vdev); > #ifdef CONFIG_MEDIA_CONTROLLER > - if (media_devnode_is_registered(dev->mdev.devnode)) > - media_device_unregister(&dev->mdev); > media_device_cleanup(&dev->mdev); > #endif > > @@ -1884,6 +1880,14 @@ static void uvc_unregister_video(struct uvc_device > *dev) uvc_debugfs_cleanup_stream(stream); > } > > + uvc_status_unregister(dev); > + if (dev->vdev.dev) > + v4l2_device_unregister(&dev->vdev); > +#ifdef CONFIG_MEDIA_CONTROLLER > + if (media_devnode_is_registered(dev->mdev.devnode)) > + media_device_unregister(&dev->mdev); > +#endif > + > /* Decrement the stream count and call uvc_delete explicitly if there > * are no stream left. > */ > diff --git a/drivers/media/usb/uvc/uvc_status.c > b/drivers/media/usb/uvc/uvc_status.c index f552ab997956..95709b23d3b4 > 100644 > --- a/drivers/media/usb/uvc/uvc_status.c > +++ b/drivers/media/usb/uvc/uvc_status.c > @@ -198,12 +198,16 @@ int uvc_status_init(struct uvc_device *dev) > return 0; > } > > -void uvc_status_cleanup(struct uvc_device *dev) > +void uvc_status_unregister(struct uvc_device *dev) > { > usb_kill_urb(dev->int_urb); > + uvc_input_cleanup(dev); I think it would make sense to rename uvc_input_cleanup() to uvc_input_unregister(). I'll make the change locally so there's no need to resubmit this patch. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> and applied to my tree. > +} > + > +void uvc_status_cleanup(struct uvc_device *dev) > +{ > usb_free_urb(dev->int_urb); > kfree(dev->status); > - uvc_input_cleanup(dev); > } > > int uvc_status_start(struct uvc_device *dev, gfp_t flags) [snip]
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 46d6be0bb316..0d0541054ce2 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1812,11 +1812,7 @@ static void uvc_delete(struct uvc_device *dev) usb_put_intf(dev->intf); usb_put_dev(dev->udev); - if (dev->vdev.dev) - v4l2_device_unregister(&dev->vdev); #ifdef CONFIG_MEDIA_CONTROLLER - if (media_devnode_is_registered(dev->mdev.devnode)) - media_device_unregister(&dev->mdev); media_device_cleanup(&dev->mdev); #endif @@ -1884,6 +1880,14 @@ static void uvc_unregister_video(struct uvc_device *dev) uvc_debugfs_cleanup_stream(stream); } + uvc_status_unregister(dev); + if (dev->vdev.dev) + v4l2_device_unregister(&dev->vdev); +#ifdef CONFIG_MEDIA_CONTROLLER + if (media_devnode_is_registered(dev->mdev.devnode)) + media_device_unregister(&dev->mdev); +#endif + /* Decrement the stream count and call uvc_delete explicitly if there * are no stream left. */ diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index f552ab997956..95709b23d3b4 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -198,12 +198,16 @@ int uvc_status_init(struct uvc_device *dev) return 0; } -void uvc_status_cleanup(struct uvc_device *dev) +void uvc_status_unregister(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); + uvc_input_cleanup(dev); +} + +void uvc_status_cleanup(struct uvc_device *dev) +{ usb_free_urb(dev->int_urb); kfree(dev->status); - uvc_input_cleanup(dev); } int uvc_status_start(struct uvc_device *dev, gfp_t flags) diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 15e415e32c7f..4b4814df35cd 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -712,6 +712,7 @@ void uvc_video_clock_update(struct uvc_streaming *stream, /* Status */ extern int uvc_status_init(struct uvc_device *dev); +extern void uvc_status_unregister(struct uvc_device *dev); extern void uvc_status_cleanup(struct uvc_device *dev); extern int uvc_status_start(struct uvc_device *dev, gfp_t flags); extern void uvc_status_stop(struct uvc_device *dev);