[RFC PATCH 0/1] media: uvcvideo: reset interface on bulk stream stop

Henry Lin posted 1 patch 2 weeks ago
[RFC PATCH 0/1] media: uvcvideo: reset interface on bulk stream stop
Posted by Henry Lin 2 weeks ago
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
Re: [RFC PATCH 0/1] media: uvcvideo: reset interface on bulk stream stop
Posted by Michal Pecio 1 week, 6 days ago
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
Re: [RFC PATCH 0/1] media: uvcvideo: reset interface on bulk stream stop
Posted by Alan Stern 2 weeks ago
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