From: Ricardo Ribalda <ribalda@chromium.org>
To: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Guenter Roeck <linux@roeck-us.net>,
Tomasz Figa <tfiga@chromium.org>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Alan Stern <stern@rowland.harvard.edu>,
Hans Verkuil <hverkuil-cisco@xs4all.nl>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
Sean Paul <seanpaul@chromium.org>,
Ricardo Ribalda <ribalda@chromium.org>,
Sakari Ailus <sakari.ailus@linux.intel.com>
Subject: [PATCH v5 3/3] media: uvcvideo: Do not use usb_* functions after .disconnect
Date: Wed, 22 Nov 2023 11:45:49 +0000 [thread overview]
Message-ID: <20231122-guenter-mini-v5-3-15d8cd8ed74f@chromium.org> (raw)
In-Reply-To: <20231122-guenter-mini-v5-0-15d8cd8ed74f@chromium.org>
usb drivers should not call to any I/O function after the
.disconnect() callback has been triggered.
https://www.kernel.org/doc/html/latest/driver-api/usb/callbacks.html#the-disconnect-callback
If an application is receiving frames form a camera and the device is
disconnected: the device will call close() after the usb .disconnect()
callback has been called. The streamoff path will call usb_set_interface
or usb_clear_halt, which is not allowed.
This patch only solves the calls to close() *after* .disconnect() is
being called.
Trace:
[ 1065.389723] drivers/media/usb/uvc/uvc_driver.c:2248 uvc_disconnect enter
[ 1065.390160] drivers/media/usb/uvc/uvc_driver.c:2264 uvc_disconnect exit
[ 1065.433956] drivers/media/usb/uvc/uvc_v4l2.c:659 uvc_v4l2_release enter
[ 1065.433973] drivers/media/usb/uvc/uvc_video.c:2274 uvc_video_stop_streaming enter
[ 1065.434560] drivers/media/usb/uvc/uvc_video.c:2285 uvc_video_stop_streaming exit
[ 1065.435154] drivers/media/usb/uvc/uvc_v4l2.c:680 uvc_v4l2_release exit
[ 1065.435188] drivers/media/usb/uvc/uvc_driver.c:2248 uvc_disconnect enter
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
---
drivers/media/usb/uvc/uvc_driver.c | 2 ++
drivers/media/usb/uvc/uvc_video.c | 45 ++++++++++++++++++++++++--------------
drivers/media/usb/uvc/uvcvideo.h | 2 ++
3 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d5dbf2644272..d78640d422f4 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2266,6 +2266,8 @@ static void uvc_disconnect(struct usb_interface *intf)
return;
uvc_unregister_video(dev);
+ /* Barrier needed to pair with uvc_video_stop_streaming(). */
+ smp_store_release(&dev->disconnected, true);
kref_put(&dev->ref, uvc_delete);
}
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 28dde08ec6c5..f5ef375088de 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -2243,28 +2243,39 @@ int uvc_video_start_streaming(struct uvc_streaming *stream)
return ret;
}
-void uvc_video_stop_streaming(struct uvc_streaming *stream)
+static void uvc_video_halt(struct uvc_streaming *stream)
{
- uvc_video_stop_transfer(stream, 1);
+ unsigned int epnum;
+ unsigned int pipe;
+ unsigned int dir;
if (stream->intf->num_altsetting > 1) {
usb_set_interface(stream->dev->udev, stream->intfnum, 0);
- } else {
- /*
- * UVC doesn't specify how to inform a bulk-based device
- * when the video stream is stopped. Windows sends a
- * CLEAR_FEATURE(HALT) request to the video streaming
- * bulk endpoint, mimic the same behaviour.
- */
- unsigned int epnum = stream->header.bEndpointAddress
- & USB_ENDPOINT_NUMBER_MASK;
- unsigned int dir = stream->header.bEndpointAddress
- & USB_ENDPOINT_DIR_MASK;
- unsigned int pipe;
-
- pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
- usb_clear_halt(stream->dev->udev, pipe);
+ return;
}
+ /*
+ * UVC doesn't specify how to inform a bulk-based device
+ * when the video stream is stopped. Windows sends a
+ * CLEAR_FEATURE(HALT) request to the video streaming
+ * bulk endpoint, mimic the same behaviour.
+ */
+ epnum = stream->header.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ dir = stream->header.bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+ pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
+ usb_clear_halt(stream->dev->udev, pipe);
+}
+
+void uvc_video_stop_streaming(struct uvc_streaming *stream)
+{
+ uvc_video_stop_transfer(stream, 1);
+
+ /*
+ * Barrier needed to pair with uvc_disconnect().
+ * We cannot call usb_* functions on a disconnected USB device.
+ */
+ if (!smp_load_acquire(&stream->dev->disconnected))
+ uvc_video_halt(stream);
+
uvc_video_clock_cleanup(stream);
}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index ba8f8c1f2c83..5b1a3643de05 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -559,6 +559,8 @@ struct uvc_device {
unsigned int users;
atomic_t nmappings;
+ bool disconnected;
+
/* Video control interface */
#ifdef CONFIG_MEDIA_CONTROLLER
struct media_device mdev;
--
2.43.0.rc1.413.gea7ed67945-goog
next prev parent reply other threads:[~2023-11-22 11:45 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-22 11:45 [PATCH v5 0/3] uvcvideo: Attempt N to land UVC race conditions fixes Ricardo Ribalda
2023-11-22 11:45 ` [PATCH v5 1/3] media: uvcvideo: Lock video streams and queues while unregistering Ricardo Ribalda
2024-03-21 15:47 ` Hans Verkuil
2024-03-25 16:37 ` Ricardo Ribalda
2023-11-22 11:45 ` [PATCH v5 2/3] media: uvcvideo: Always use uvc_status_stop() Ricardo Ribalda
2023-11-22 13:32 ` Laurent Pinchart
2023-11-22 11:45 ` Ricardo Ribalda [this message]
2023-11-22 13:33 ` [PATCH v5 3/3] media: uvcvideo: Do not use usb_* functions after .disconnect Laurent Pinchart
2023-11-22 14:59 ` Ricardo Ribalda
2024-03-22 14:19 ` Laurent Pinchart
2024-03-22 14:31 ` Ricardo Ribalda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231122-guenter-mini-v5-3-15d8cd8ed74f@chromium.org \
--to=ribalda@chromium.org \
--cc=hverkuil-cisco@xs4all.nl \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=mchehab@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=seanpaul@chromium.org \
--cc=stern@rowland.harvard.edu \
--cc=tfiga@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.