Re: [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval

From: Alan Stern

Date: Thu Apr 23 2026 - 10:06:12 EST


On Thu, Apr 23, 2026 at 11:09:59AM +0200, Michal Pecio wrote:
> Tao Xue found that some common devices violate USB3 section 9.6.7
> by reporting wBytesPerInterval lower than the size of packets they
> actually send. I confirmed that AX88179 may set it to 0 and RTL8153
> CDC configuration sets it to 8 but sends both 8 and 16 byte packets:
>
> S Ii:11:007:3 -115:128 16 <
> C Ii:11:007:3 0:128 8 = a1000000 01000000
> S Ii:11:007:3 -115:128 16 <
> C Ii:11:007:3 0:128 16 = a12a0000 01000800 00000000 00000000
>
> Most xHCI host controllers neglect interrupt bandwidth reservations
> and let such devices exceed theirs, some fail the URB with EOVERFLOW.
>
> Assume that wBytesPerInterval lower than wMaxPacketSize is bogus and
> increase it to the worst case maximum on interrupt IN endpoints. This
> solves xHCI problems and appears to have no other effect. Interrupt
> transfers are not limited to one interval and drivers submit URBs of
> class defined size without looking at wBytesPerInterval. Any multi-
> interval transfer is considered terminated by a packet shorter than
> wMaxPacketSize regardless of wBytesPerInterval - see USB3 8.10.3.
>
> Stay in spec on OUT endpoints and isochronous. No buggy devices are
> known and we don't want to risk sending more data than the device
> is prepared to handle or confusing isoc drivers regarding altsetting
> capacities guaranteed by the device itself. And don't complain when
> wMaxPacketSize <= wBytesPerInterval < wMaxPacketSize * (bMaxBurst+1)
> because enabling this seems to be the exact goal of the spec.
>
> Reported-by: Tao Xue <xuetao09@xxxxxxxxxx>
> Closes: https://lore.kernel.org/linux-usb/20260402021400.28853-1-xuetao09@xxxxxxxxxx/
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Michal Pecio <michal.pecio@xxxxxxxxx>
> ---
>
> Note:
> Compared to original suggestion, this is a conservative patch which
> only addresses known broken devices and tries to minimize disruption
> for spec compliant ones.
>
> drivers/usb/core/config.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
> index 6a1fd967e0a6..bdd912627bac 100644
> --- a/drivers/usb/core/config.c
> +++ b/drivers/usb/core/config.c
> @@ -191,7 +191,14 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
> (desc->bMaxBurst + 1);
> else
> max_tx = 999999;
> - if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
> + /*
> + * wBytesPerInterval > max_tx is bogus, but USB3 spec doesn't forbid the opposite.
> + * Experience shows that wBytesPerInterval < wMaxPacketSize on common interrupt IN
> + * endpoints is usually bogus too, and recent HCs enforce interrupt BW limits.
> + */
> + if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
> + (le16_to_cpu(desc->wBytesPerInterval) < usb_endpoint_maxp(&ep->desc) &&
> + usb_endpoint_xfer_int(&ep->desc) && usb_endpoint_dir_in(&ep->desc))
You can use usb_endpoint_is_int_in() here.

Alan Stern

) {
> dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
> "config %d interface %d altsetting %d ep %d: "
> "setting to %d\n",
> --
> 2.48.1