From: JP Hein <jp@jphein.com>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hansg@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-media@vger.kernel.org, linux-usb@vger.kernel.org,
Ricardo Ribalda <ribalda@chromium.org>,
Michal Pecio <michal.pecio@gmail.com>, JP Hein <jp@jphein.com>
Subject: [PATCH v6 1/2] media: uvcvideo: add UVC_QUIRK_CTRL_THROTTLE for fragile USB firmware
Date: Thu, 9 Apr 2026 00:42:41 -0700 [thread overview]
Message-ID: <20260409074242.2115657-2-jp@jphein.com> (raw)
In-Reply-To: <20260409074242.2115657-1-jp@jphein.com>
Some UVC devices have firmware that locks up under sustained rapid
USB control transfers, crashing the xHCI host controller and taking
all USB devices on the bus with it.
The Razer Kiyo Pro (1532:0e05) is the first known example: approximately
25 rapid consecutive control transfers cause the firmware to stall an
endpoint. The kernel's standard UVC error recovery (GET_CUR on
UVC_VC_REQUEST_ERROR_CODE_CONTROL) then sends a second transfer to the
already-stalling device, amplifying the failure into complete firmware
lockup and xHCI controller death.
Add UVC_QUIRK_CTRL_THROTTLE which:
- Rate-limits all USB control transfers to 50ms intervals in
__uvc_query_ctrl(), the lowest-level UVC control transfer function,
ensuring all callers are throttled including uvc_set_video_ctrl()
which bypasses uvc_query_ctrl()
- Skips the error-code query after EPIPE to avoid amplifying stalls
The 50ms interval was determined experimentally: the device is stable
at this rate under sustained operation, while shorter intervals
eventually trigger the firmware bug.
Signed-off-by: JP Hein <jp@jphein.com>
---
drivers/media/usb/uvc/uvc_video.c | 30 ++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvcvideo.h | 3 +++
2 files changed, 33 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index a5013a7..cee93ac 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -36,6 +36,26 @@ static int __uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit,
u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int pipe;
+ /*
+ * Rate-limit control transfers for devices with fragile firmware.
+ * The Razer Kiyo Pro locks up under sustained rapid control
+ * transfers (hundreds without delay), crashing the xHCI controller.
+ * Throttle in this low-level function to cover all callers,
+ * including uvc_set_video_ctrl() which bypasses uvc_query_ctrl().
+ */
+ if (dev->quirks & UVC_QUIRK_CTRL_THROTTLE) {
+ unsigned long min_interval = msecs_to_jiffies(50);
+
+ if (dev->last_ctrl_jiffies &&
+ time_before(jiffies,
+ dev->last_ctrl_jiffies + min_interval)) {
+ unsigned long wait = dev->last_ctrl_jiffies +
+ min_interval - jiffies;
+ msleep(jiffies_to_msecs(wait));
+ }
+ dev->last_ctrl_jiffies = jiffies;
+ }
+
pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0)
: usb_sndctrlpipe(dev->udev, 0);
type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT;
@@ -108,6 +128,16 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit,
return ret < 0 ? ret : -EPIPE;
}
+ /*
+ * Skip the error code query for devices that crash under load.
+ * The standard error-code query (GET_CUR on
+ * UVC_VC_REQUEST_ERROR_CODE_CONTROL) sends a second USB transfer to
+ * a device that is already stalling, which can amplify the failure
+ * into a full firmware lockup and xHCI controller death.
+ */
+ if (dev->quirks & UVC_QUIRK_CTRL_THROTTLE)
+ return -EPIPE;
+
/* Reuse data[0] to request the error code. */
tmp = *(u8 *)data;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 757254f..31f2af5 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -78,6 +78,7 @@
#define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000
#define UVC_QUIRK_MJPEG_NO_EOF 0x00020000
#define UVC_QUIRK_MSXU_META 0x00040000
+#define UVC_QUIRK_CTRL_THROTTLE 0x00080000
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
@@ -583,6 +584,8 @@ struct uvc_device {
struct usb_interface *intf;
unsigned long warnings;
u32 quirks;
+ /* UVC control transfer throttling (UVC_QUIRK_CTRL_THROTTLE) */
+ unsigned long last_ctrl_jiffies;
int intfnum;
char name[32];
--
2.43.0
next prev parent reply other threads:[~2026-04-09 7:44 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-31 0:38 [PATCH v5 0/3] USB/UVC: Add quirks to prevent Razer Kiyo Pro xHCI cascade failure JP Hein
2026-03-31 0:38 ` [PATCH v5 1/3] USB: core: add NO_LPM quirk for Razer Kiyo Pro webcam JP Hein
2026-03-31 0:38 ` [PATCH v5 2/3] media: uvcvideo: add UVC_QUIRK_CTRL_THROTTLE for fragile firmware JP Hein
2026-04-09 6:45 ` Ricardo Ribalda
[not found] ` <CAD5VvzAu8+Qz7hEEBzuKvO11X=YD-wrtX3_Tk77g2Cq5rZZD0Q@mail.gmail.com>
2026-04-09 7:51 ` Jeffrey Hein
2026-04-09 8:02 ` Michal Pecio
2026-04-09 8:15 ` Jeffrey Hein
2026-04-09 20:17 ` Michal Pecio
2026-04-10 0:01 ` Jeffrey Hein
2026-04-10 0:24 ` Jeffrey Hein
2026-04-10 4:47 ` Michal Pecio
2026-04-10 21:48 ` Mathias Nyman
2026-04-10 23:06 ` Jeffrey Hein
2026-04-11 13:39 ` Michal Pecio
2026-03-31 0:38 ` [PATCH v5 3/3] media: uvcvideo: add quirks for Razer Kiyo Pro webcam JP Hein
2026-04-09 6:49 ` Ricardo Ribalda
2026-04-09 7:38 ` Jeffrey Hein
2026-04-09 7:42 ` [PATCH v6 0/2] media: uvcvideo: Add quirks to prevent Razer Kiyo Pro xHCI cascade failure JP Hein
2026-04-09 7:42 ` JP Hein [this message]
2026-04-09 7:57 ` [PATCH v6 1/2] media: uvcvideo: add UVC_QUIRK_CTRL_THROTTLE for fragile USB firmware Ricardo Ribalda
2026-04-09 8:12 ` Jeffrey Hein
2026-04-09 7:42 ` [PATCH v6 2/2] media: uvcvideo: add Razer Kiyo Pro to device info table JP Hein
2026-04-09 7:57 ` Ricardo Ribalda
2026-04-09 8:13 ` Jeffrey Hein
2026-04-10 0:28 ` [PATCH v7 0/2] media: uvcvideo: Add quirks to prevent Razer Kiyo Pro xHCI cascade failure JP Hein
2026-04-10 0:28 ` [PATCH v7 1/2] media: uvcvideo: add UVC_QUIRK_CTRL_THROTTLE for fragile USB firmware JP Hein
2026-04-10 0:28 ` [PATCH v7 2/2] media: uvcvideo: add Razer Kiyo Pro to device info table JP Hein
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=20260409074242.2115657-2-jp@jphein.com \
--to=jp@jphein.com \
--cc=gregkh@linuxfoundation.org \
--cc=hansg@kernel.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=michal.pecio@gmail.com \
--cc=ribalda@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox