Hi,
I would like to revive an old UVC bulk-streaming issue originally reported
by Hans Yang. I am sending this RFC on his behalf for discussion before
submitting a non-RFC patch.
Hans previously proposed making uvcvideo call usb_set_interface(..., 0)
when stopping a bulk-based stream, before clearing halt on the bulk endpoint.
The issue was discussed here:
https://www.spinics.net/lists/linux-usb/msg171584.html
The current upstream stop path calls usb_set_interface(..., 0) only when the
streaming interface has more than one alternate setting. For single-altsetting
bulk devices, uvcvideo only sends CLEAR_FEATURE(ENDPOINT_HALT) to the bulk
endpoint.
The patch in this RFC changes uvc_video_stop_streaming() to always call
usb_set_interface(..., 0) to reset the streaming interface first. For
bulk devices, the existing CLEAR_FEATURE(ENDPOINT_HALT) request is still
sent afterwards.
On the affected devices, current upstream stop/start sequence can leave
the next bulk stream failing immediately with transfer errors such as:
uvcvideo: Non-zero status (-71) in video completion handler.
USB bus traces show that, without usb_set_interface(..., 0), the host
continues the next bulk stream with the previous stream's sequence state,
while the device expects the new stream to start from the initial sequence
state. With usb_set_interface(..., 0), the host and device sequence states
match again and repeated stop/start cycles complete successfully.
The affected devices we have seen include:
- ID 8086:0b07 Intel Corp. RealSense D435
- ID 2560:c1d0 e-con Systems See3CAM_CU130
- ID 2b03:f582 STEREOLABS ZED camera
I understand that the earlier discussion raised two important concerns:
1. Whether this should be fixed in uvcvideo or lower in the USB/xHCI stack,
since CLEAR_FEATURE(ENDPOINT_HALT) should normally reset the endpoint
halt condition and data toggle/sequence state.
2. Whether calling usb_set_interface(..., 0) for single-altsetting bulk UVC
devices could regress existing devices.
For the first point, my understanding is that the kernel helper
usb_set_interface(..., 0) issues SET_INTERFACE and lets the USB core
reinitialize the endpoints for the selected alternate setting, including their
data toggle/sequence state. The traces suggest that, in this stop/start path,
CLEAR_FEATURE(ENDPOINT_HALT) alone is not enough to make the host and device
restart the next bulk stream from the same sequence state. The additional
usb_set_interface(..., 0) call makes repeated stop/start cycles reliable on
the affected hardware.
For the second point, I can provide before/after test results from the
affected hardware listed above. I can also test a quirk-based version if that
would be preferred over changing the generic bulk-stream stop path.
I would appreciate guidance on whether this one-patch RFC is the preferred
direction, or whether upstream would prefer a UVC quirk-based change for the
affected devices listed above.
Thanks,
Henry
On Mon, 25 May 2026 18:20:27 +0000, Henry Lin wrote: > I would like to revive an old UVC bulk-streaming issue originally > reported by Hans Yang. I am sending this RFC on his behalf for > discussion before submitting a non-RFC patch. > > Hans previously proposed making uvcvideo call usb_set_interface(..., > 0) when stopping a bulk-based stream, before clearing halt on the > bulk endpoint. The issue was discussed here: > > https://www.spinics.net/lists/linux-usb/msg171584.html > > The current upstream stop path calls usb_set_interface(..., 0) only > when the streaming interface has more than one alternate setting. For > single-altsetting bulk devices, uvcvideo only sends > CLEAR_FEATURE(ENDPOINT_HALT) to the bulk endpoint. You are referring to uvc_video_stop_streaming() here, right? This calls usb_clear_halt(), which is supposed to reset both ends of the pipe. > The patch in this RFC changes uvc_video_stop_streaming() to always > call usb_set_interface(..., 0) to reset the streaming interface > first. For bulk devices, the existing CLEAR_FEATURE(ENDPOINT_HALT) > request is still sent afterwards. > > On the affected devices, current upstream stop/start sequence can > leave the next bulk stream failing immediately with transfer errors > such as: > > uvcvideo: Non-zero status (-71) in video completion handler. > > USB bus traces show that, without usb_set_interface(..., 0), the host > continues the next bulk stream with the previous stream's sequence > state, while the device expects the new stream to start from the > initial sequence state. With usb_set_interface(..., 0), the host and > device sequence states match again and repeated stop/start cycles > complete successfully. I suppose you mean SuperSpeed and xHCI, so that's a little mysterious because xhci_hcd resets host sequence state on Transaction Error completions and hence it should recover from such mismatch after the first error. Of course, no mismatch should exist in the first place. But xhci_hcd was broken for years and failed to clear host sequence state when requested by usb_clear_halt() in some cases. This recent commit fixed the most blatant bug and was motivated precisely by this UVC issue, which I encountered myself. 25e531b422dc usb: xhci: Make usb_host_endpoint.hcpriv survive endpoint_disable() Please check if this works for you, it's included in 7.1 RCs and some latest stable kernels. If not, you might be affected by other bugs. > The affected devices we have seen include: > > - ID 8086:0b07 Intel Corp. RealSense D435 > - ID 2560:c1d0 e-con Systems See3CAM_CU130 > - ID 2b03:f582 STEREOLABS ZED camera I think all bulk devices were affected, and all SuperSpeed bulk devices were affected particularly badly. Regards, Michal
On Mon, May 25, 2026 at 06:20:27PM +0000, Henry Lin wrote:
> Hi,
>
> I would like to revive an old UVC bulk-streaming issue originally reported
> by Hans Yang. I am sending this RFC on his behalf for discussion before
> submitting a non-RFC patch.
>
> Hans previously proposed making uvcvideo call usb_set_interface(..., 0)
> when stopping a bulk-based stream, before clearing halt on the bulk endpoint.
> The issue was discussed here:
>
> https://www.spinics.net/lists/linux-usb/msg171584.html
>
> The current upstream stop path calls usb_set_interface(..., 0) only when the
> streaming interface has more than one alternate setting. For single-altsetting
> bulk devices, uvcvideo only sends CLEAR_FEATURE(ENDPOINT_HALT) to the bulk
> endpoint.
How does it send this request? By calling usb_clear_halt()? Or some
other way?
> The patch in this RFC changes uvc_video_stop_streaming() to always call
> usb_set_interface(..., 0) to reset the streaming interface first. For
> bulk devices, the existing CLEAR_FEATURE(ENDPOINT_HALT) request is still
> sent afterwards.
>
> On the affected devices, current upstream stop/start sequence can leave
> the next bulk stream failing immediately with transfer errors such as:
>
> uvcvideo: Non-zero status (-71) in video completion handler.
>
> USB bus traces show that, without usb_set_interface(..., 0), the host
> continues the next bulk stream with the previous stream's sequence state,
> while the device expects the new stream to start from the initial sequence
> state.
(I assume by "sequence state" you mean the USB-3 sequence number
associated with the endpoint.)
Are you certain about this? The usb_clear_halt() routine has reset
the endpoint state, including the sequence number, ever since commit
3444b26afa14 ("USB: add reset endpoint operations") was added in 2009.
If uvcvideo isn't using usb_clear_halt(), the simplest solution might be
to make it do so.
Alan Stern
© 2016 - 2026 Red Hat, Inc.