public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
@ 2026-04-02  2:14 Tao Xue
  2026-04-02  2:45 ` Alan Stern
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Tao Xue @ 2026-04-02  2:14 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, linux-kernel, caiyadong, Tao Xue, stable

As specified in Section 4.14.2 of the xHCI Specification, the xHC
reserves bandwidth for periodic endpoints according to bInterval and
wBytesPerInterval (Max ESIT Payload).

Some peripherals report an invalid wBytesPerInterval in their device
descriptor, which is either 0 or smaller than the actual data length
transmitted. This issue is observed on ASIX AX88179 series USB 3.0
Ethernet adapters.

These errors may lead to unexpected behavior on certain USB host
controllers, causing USB peripherals to malfunction.

To address the issue, return max(wBytesPerInterval, max_payload) when
calculating bandwidth reservation.

Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
Cc: <stable@kernel.org>
Signed-off-by: Tao Xue <xuetao09@huawei.com>
---
 drivers/usb/core/usb.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e9a10a33534c..8f2e05a5a015 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
 u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
 				      const struct usb_host_endpoint *ep)
 {
+	u32 max_payload;
+
 	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
 	    !usb_endpoint_xfer_int(&ep->desc))
 		return 0;
@@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
 			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
 		fallthrough;
 	case USB_SPEED_SUPER:
-		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
+		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
+		if (usb_endpoint_xfer_isoc(&ep->desc))
+			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
+					ep->ss_ep_comp.wBytesPerInterval);
+		else
+			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);
 	default:
 		if (usb_endpoint_is_hs_isoc_double(udev, ep))
 			return le32_to_cpu(ep->eusb2_isoc_ep_comp.dwBytesPerInterval);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  2:14 [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Tao Xue
@ 2026-04-02  2:45 ` Alan Stern
  2026-04-02  3:51 ` Greg KH
  2026-04-02  9:44 ` Michal Pecio
  2 siblings, 0 replies; 21+ messages in thread
From: Alan Stern @ 2026-04-02  2:45 UTC (permalink / raw)
  To: Tao Xue; +Cc: gregkh, linux-usb, linux-kernel, caiyadong, stable

On Thu, Apr 02, 2026 at 10:14:00AM +0800, Tao Xue wrote:
> As specified in Section 4.14.2 of the xHCI Specification, the xHC
> reserves bandwidth for periodic endpoints according to bInterval and
> wBytesPerInterval (Max ESIT Payload).
> 
> Some peripherals report an invalid wBytesPerInterval in their device
> descriptor, which is either 0 or smaller than the actual data length
> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
> Ethernet adapters.

Do we log these invalid values when we parse the endpoint and their 
companion descriptors?  We should -- and we can fix up any errors then, 
just once.

Alan Stern

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  2:14 [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Tao Xue
  2026-04-02  2:45 ` Alan Stern
@ 2026-04-02  3:51 ` Greg KH
  2026-04-02  6:59   ` Xuetao (kirin)
  2026-04-02  9:44 ` Michal Pecio
  2 siblings, 1 reply; 21+ messages in thread
From: Greg KH @ 2026-04-02  3:51 UTC (permalink / raw)
  To: Tao Xue; +Cc: linux-usb, linux-kernel, caiyadong, stable

On Thu, Apr 02, 2026 at 10:14:00AM +0800, Tao Xue wrote:
> As specified in Section 4.14.2 of the xHCI Specification, the xHC
> reserves bandwidth for periodic endpoints according to bInterval and
> wBytesPerInterval (Max ESIT Payload).
> 
> Some peripherals report an invalid wBytesPerInterval in their device
> descriptor, which is either 0 or smaller than the actual data length
> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
> Ethernet adapters.
> 
> These errors may lead to unexpected behavior on certain USB host
> controllers, causing USB peripherals to malfunction.
> 
> To address the issue, return max(wBytesPerInterval, max_payload) when
> calculating bandwidth reservation.
> 
> Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
> Cc: <stable@kernel.org>
> Signed-off-by: Tao Xue <xuetao09@huawei.com>
> ---
>  drivers/usb/core/usb.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
> index e9a10a33534c..8f2e05a5a015 100644
> --- a/drivers/usb/core/usb.c
> +++ b/drivers/usb/core/usb.c
> @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
>  u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>  				      const struct usb_host_endpoint *ep)
>  {
> +	u32 max_payload;
> +
>  	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
>  	    !usb_endpoint_xfer_int(&ep->desc))
>  		return 0;
> @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>  			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
>  		fallthrough;
>  	case USB_SPEED_SUPER:
> -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
> +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
> +		if (usb_endpoint_xfer_isoc(&ep->desc))
> +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
> +					ep->ss_ep_comp.wBytesPerInterval);
> +		else
> +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);

You dropped the conversion from le16 to cpu?  Why?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  3:51 ` Greg KH
@ 2026-04-02  6:59   ` Xuetao (kirin)
  2026-04-02  7:10     ` Greg KH
  2026-04-02 13:56     ` Alan Stern
  0 siblings, 2 replies; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-02  6:59 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, linux-kernel, caiyadong, stable, stern



在 2026/4/2 11:51, Greg KH 写道:
> On Thu, Apr 02, 2026 at 10:14:00AM +0800, Tao Xue wrote:
>> As specified in Section 4.14.2 of the xHCI Specification, the xHC
>> reserves bandwidth for periodic endpoints according to bInterval and
>> wBytesPerInterval (Max ESIT Payload).
>>
>> Some peripherals report an invalid wBytesPerInterval in their device
>> descriptor, which is either 0 or smaller than the actual data length
>> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
>> Ethernet adapters.
>>
>> These errors may lead to unexpected behavior on certain USB host
>> controllers, causing USB peripherals to malfunction.
>>
>> To address the issue, return max(wBytesPerInterval, max_payload) when
>> calculating bandwidth reservation.
>>
>> Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
>> Cc: <stable@kernel.org>
>> Signed-off-by: Tao Xue <xuetao09@huawei.com>
>> ---
>>   drivers/usb/core/usb.c | 9 ++++++++-
>>   1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
>> index e9a10a33534c..8f2e05a5a015 100644
>> --- a/drivers/usb/core/usb.c
>> +++ b/drivers/usb/core/usb.c
>> @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
>>   u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>   				      const struct usb_host_endpoint *ep)
>>   {
>> +	u32 max_payload;
>> +
>>   	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
>>   	    !usb_endpoint_xfer_int(&ep->desc))
>>   		return 0;
>> @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>   			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
>>   		fallthrough;
>>   	case USB_SPEED_SUPER:
>> -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
>> +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
>> +		if (usb_endpoint_xfer_isoc(&ep->desc))
>> +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
>> +					ep->ss_ep_comp.wBytesPerInterval);
>> +		else
>> +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);
> 
> You dropped the conversion from le16 to cpu?  Why?
> 
> thanks,
> 
> greg k-h

Hi Greg,

Thank you for the review.

1、You're right, that was an oversight. I should keep the le16_to_cpu().
Here's the corrected version:

     max_payload = usb_endpoint_maxp(&ep->desc) * 
(ep->ss_ep_comp.bMaxBurst + 1);
     if (usb_endpoint_xfer_isoc(&ep->desc))
         return max_t(u32, max_payload * 
USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
                         le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));
     else
         return max_t(u32, max_payload, 
le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));

2、Following Alan's suggestion in another email, should I check whether 
wBytesPerInterval is a valid value and handle it in the 
usb_parse_ss_endpoint_companion() ?

However, when parsing the device descriptor, we do not know whether the 
actual data length transmitted by the peripheral is greater than 
wBytesPerInterval.

Therefore, would it be sufficient to only add a check for whether 
wBytesPerInterval is 0 in the existing flow, and if it is 0, set 
wBytesPerInterval to cpu_to_le16(max_tx) by default?

For example, modify it in the following way:

      if (le16_to_cpu(desc->wBytesPerInterval) > max_tx || 
le16_to_cpu(desc->wBytesPerInterval) == 0) {
         dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
                 "config %d interface %d altsetting %d ep %d: "
                 "setting to %d\n",
                 usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
                 le16_to_cpu(desc->wBytesPerInterval),
                 cfgno, inum, asnum, ep->desc.bEndpointAddress,
                 max_tx);
         ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
     }

  Could you please give me some advice? Thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  6:59   ` Xuetao (kirin)
@ 2026-04-02  7:10     ` Greg KH
  2026-04-02  8:26       ` Xuetao (kirin)
  2026-04-02 13:56     ` Alan Stern
  1 sibling, 1 reply; 21+ messages in thread
From: Greg KH @ 2026-04-02  7:10 UTC (permalink / raw)
  To: Xuetao (kirin); +Cc: linux-usb, linux-kernel, caiyadong, stable, stern

On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
> 
> 
> 在 2026/4/2 11:51, Greg KH 写道:
> > On Thu, Apr 02, 2026 at 10:14:00AM +0800, Tao Xue wrote:
> > > As specified in Section 4.14.2 of the xHCI Specification, the xHC
> > > reserves bandwidth for periodic endpoints according to bInterval and
> > > wBytesPerInterval (Max ESIT Payload).
> > > 
> > > Some peripherals report an invalid wBytesPerInterval in their device
> > > descriptor, which is either 0 or smaller than the actual data length
> > > transmitted. This issue is observed on ASIX AX88179 series USB 3.0
> > > Ethernet adapters.
> > > 
> > > These errors may lead to unexpected behavior on certain USB host
> > > controllers, causing USB peripherals to malfunction.
> > > 
> > > To address the issue, return max(wBytesPerInterval, max_payload) when
> > > calculating bandwidth reservation.
> > > 
> > > Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
> > > Cc: <stable@kernel.org>
> > > Signed-off-by: Tao Xue <xuetao09@huawei.com>
> > > ---
> > >   drivers/usb/core/usb.c | 9 ++++++++-
> > >   1 file changed, 8 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
> > > index e9a10a33534c..8f2e05a5a015 100644
> > > --- a/drivers/usb/core/usb.c
> > > +++ b/drivers/usb/core/usb.c
> > > @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
> > >   u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
> > >   				      const struct usb_host_endpoint *ep)
> > >   {
> > > +	u32 max_payload;
> > > +
> > >   	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
> > >   	    !usb_endpoint_xfer_int(&ep->desc))
> > >   		return 0;
> > > @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
> > >   			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
> > >   		fallthrough;
> > >   	case USB_SPEED_SUPER:
> > > -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
> > > +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
> > > +		if (usb_endpoint_xfer_isoc(&ep->desc))
> > > +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
> > > +					ep->ss_ep_comp.wBytesPerInterval);
> > > +		else
> > > +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);
> > 
> > You dropped the conversion from le16 to cpu?  Why?
> > 
> > thanks,
> > 
> > greg k-h
> 
> Hi Greg,
> 
> Thank you for the review.
> 
> 1、You're right, that was an oversight. I should keep the le16_to_cpu().
> Here's the corrected version:
> 
>     max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst +
> 1);
>     if (usb_endpoint_xfer_isoc(&ep->desc))
>         return max_t(u32, max_payload *
> USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
>                         le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));
>     else
>         return max_t(u32, max_payload,
> le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));

That's hard to follow as it is line-wrapped, just fix it up for your
next version and I'll be glad to review it then.

> 2、Following Alan's suggestion in another email, should I check whether
> wBytesPerInterval is a valid value and handle it in the
> usb_parse_ss_endpoint_companion() ?
> 
> However, when parsing the device descriptor, we do not know whether the
> actual data length transmitted by the peripheral is greater than
> wBytesPerInterval.
> 
> Therefore, would it be sufficient to only add a check for whether
> wBytesPerInterval is 0 in the existing flow, and if it is 0, set
> wBytesPerInterval to cpu_to_le16(max_tx) by default?

No, don't override a value given by a device.  Mark the descriptor as
invalid and fail attaching to the device.

> For example, modify it in the following way:
> 
>      if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
> le16_to_cpu(desc->wBytesPerInterval) == 0) {
>         dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
>                 "config %d interface %d altsetting %d ep %d: "
>                 "setting to %d\n",
>                 usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
>                 le16_to_cpu(desc->wBytesPerInterval),
>                 cfgno, inum, asnum, ep->desc.bEndpointAddress,
>                 max_tx);
>         ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
>     }

There's nothing a user can do with this type of error, and yet the
kernel is supposed to fix it up?  We should just fail it and tell the
user then, like we do for other broken descriptors.

Did you find this issue with a real device, or is this just due to
fuzzing invalid descriptor values?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  7:10     ` Greg KH
@ 2026-04-02  8:26       ` Xuetao (kirin)
  0 siblings, 0 replies; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-02  8:26 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb, linux-kernel, caiyadong, stable, stern



在 2026/4/2 15:10, Greg KH 写道:
> On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
>>
>>
>> 在 2026/4/2 11:51, Greg KH 写道:
>>> On Thu, Apr 02, 2026 at 10:14:00AM +0800, Tao Xue wrote:
>>>> As specified in Section 4.14.2 of the xHCI Specification, the xHC
>>>> reserves bandwidth for periodic endpoints according to bInterval and
>>>> wBytesPerInterval (Max ESIT Payload).
>>>>
>>>> Some peripherals report an invalid wBytesPerInterval in their device
>>>> descriptor, which is either 0 or smaller than the actual data length
>>>> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
>>>> Ethernet adapters.
>>>>
>>>> These errors may lead to unexpected behavior on certain USB host
>>>> controllers, causing USB peripherals to malfunction.
>>>>
>>>> To address the issue, return max(wBytesPerInterval, max_payload) when
>>>> calculating bandwidth reservation.
>>>>
>>>> Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
>>>> Cc: <stable@kernel.org>
>>>> Signed-off-by: Tao Xue <xuetao09@huawei.com>
>>>> ---
>>>>    drivers/usb/core/usb.c | 9 ++++++++-
>>>>    1 file changed, 8 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
>>>> index e9a10a33534c..8f2e05a5a015 100644
>>>> --- a/drivers/usb/core/usb.c
>>>> +++ b/drivers/usb/core/usb.c
>>>> @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
>>>>    u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>>>    				      const struct usb_host_endpoint *ep)
>>>>    {
>>>> +	u32 max_payload;
>>>> +
>>>>    	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
>>>>    	    !usb_endpoint_xfer_int(&ep->desc))
>>>>    		return 0;
>>>> @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>>>    			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
>>>>    		fallthrough;
>>>>    	case USB_SPEED_SUPER:
>>>> -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
>>>> +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
>>>> +		if (usb_endpoint_xfer_isoc(&ep->desc))
>>>> +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
>>>> +					ep->ss_ep_comp.wBytesPerInterval);
>>>> +		else
>>>> +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);
>>>
>>> You dropped the conversion from le16 to cpu?  Why?
>>>
>>> thanks,
>>>
>>> greg k-h
>>
>> Hi Greg,
>>
>> Thank you for the review.
>>
>> 1、You're right, that was an oversight. I should keep the le16_to_cpu().
>> Here's the corrected version:
>>
>>      max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst +
>> 1);
>>      if (usb_endpoint_xfer_isoc(&ep->desc))
>>          return max_t(u32, max_payload *
>> USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
>>                          le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));
>>      else
>>          return max_t(u32, max_payload,
>> le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval));
> 
> That's hard to follow as it is line-wrapped, just fix it up for your
> next version and I'll be glad to review it then.
> 
Thank you for the review.I will submit a new patch later.

>> 2、Following Alan's suggestion in another email, should I check whether
>> wBytesPerInterval is a valid value and handle it in the
>> usb_parse_ss_endpoint_companion() ?
>>
>> However, when parsing the device descriptor, we do not know whether the
>> actual data length transmitted by the peripheral is greater than
>> wBytesPerInterval.
>>
>> Therefore, would it be sufficient to only add a check for whether
>> wBytesPerInterval is 0 in the existing flow, and if it is 0, set
>> wBytesPerInterval to cpu_to_le16(max_tx) by default?
> 
> No, don't override a value given by a device.  Mark the descriptor as
> invalid and fail attaching to the device.
> 
>> For example, modify it in the following way:
>>
>>       if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
>> le16_to_cpu(desc->wBytesPerInterval) == 0) {
>>          dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
>>                  "config %d interface %d altsetting %d ep %d: "
>>                  "setting to %d\n",
>>                  usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
>>                  le16_to_cpu(desc->wBytesPerInterval),
>>                  cfgno, inum, asnum, ep->desc.bEndpointAddress,
>>                  max_tx);
>>          ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
>>      }
> 
> There's nothing a user can do with this type of error, and yet the
> kernel is supposed to fix it up?  We should just fail it and tell the
> user then, like we do for other broken descriptors.
> 
> Did you find this issue with a real device, or is this just due to
> fuzzing invalid descriptor values?
> 
> thanks,
> 
> greg k-h

This is not a fuzzing issue.I have encountered this issue on several USB 
3.0 docks (with built-in USB Ethernet adapters), such as UGREEN, 
thinkplus, and Baseus. They all use the ASIX AX88179 USB 3.0 Gigabit 
Ethernet Adapter (VID:0x0B95, PID: 0x1790). I am seeing two scenarios:

int ep:
Scenario 1:
	wMaxPacketSize = 16
	bMaxBurst = 0
	wBytesPerInterval = 8
	tx_data_len = 8/16

Scenario 2:
	wMaxPacketSize = 16
	bMaxBurst = 0
	wBytesPerInterval = 0
	tx_data_len = 8/16

These devices work perfectly on the dwc3 controller, but they 
consistently fail on another USB host controller. When I temporarily 
change wBytesPerInterval to 16, the problem is resolved.

 From the comparison results, different controllers behave differently 
when encountering invalid wBytesPerInterval values in the device 
descriptor.The dwc3 controller is tolerant of this error.



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  2:14 [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Tao Xue
  2026-04-02  2:45 ` Alan Stern
  2026-04-02  3:51 ` Greg KH
@ 2026-04-02  9:44 ` Michal Pecio
  2026-04-02 11:55   ` Xuetao (kirin)
  2 siblings, 1 reply; 21+ messages in thread
From: Michal Pecio @ 2026-04-02  9:44 UTC (permalink / raw)
  To: Tao Xue; +Cc: gregkh, linux-usb, linux-kernel, caiyadong, stable

On Thu, 2 Apr 2026 10:14:00 +0800, Tao Xue wrote:
> As specified in Section 4.14.2 of the xHCI Specification, the xHC
> reserves bandwidth for periodic endpoints according to bInterval and
> wBytesPerInterval (Max ESIT Payload).

For SuperSpeed endpoints, yes.
This follows from USB3 spec 9.6.7.

> Some peripherals report an invalid wBytesPerInterval in their device
> descriptor, which is either 0 or smaller than the actual data length
> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
> Ethernet adapters.

Damn, it really does.

      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              11
        bMaxBurst               0
        wBytesPerInterval       0

Any other examples besides AX88179?

> These errors may lead to unexpected behavior on certain USB host
> controllers, causing USB peripherals to malfunction.

Out of curiosity, Bandwidth Overrun Error or something worse?

It's an oversight that these URBs aren't rejected with EMSGSIZE in the
first place. IIRC zero-length interrupt transfers are allowed by USB
specs and a zero-payload endpoint is probably legal per xHCI, but then
submitting non-empty URBs to it is not.

> To address the issue, return max(wBytesPerInterval, max_payload) when
> calculating bandwidth reservation.
> 
> Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
> Cc: <stable@kernel.org>
> Signed-off-by: Tao Xue <xuetao09@huawei.com>
> ---
>  drivers/usb/core/usb.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
> index e9a10a33534c..8f2e05a5a015 100644
> --- a/drivers/usb/core/usb.c
> +++ b/drivers/usb/core/usb.c
> @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
>  u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>  				      const struct usb_host_endpoint *ep)
>  {
> +	u32 max_payload;
> +
>  	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
>  	    !usb_endpoint_xfer_int(&ep->desc))
>  		return 0;
> @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>  			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
>  		fallthrough;
>  	case USB_SPEED_SUPER:
> -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
> +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
> +		if (usb_endpoint_xfer_isoc(&ep->desc))
> +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
> +					ep->ss_ep_comp.wBytesPerInterval);
> +		else
> +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);

Obviously a kludge is necessary here to make these abominable devices
work reliably with xHCI, but OTOH exceeding wBytesPerInterval violates
USB3 9.6.7 and it's unclear if all devices would be happy.

There are devices which define such odd isochronous alt settings with
apparent intent to allow fine-grained bandwidth reservation:

        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               1
        bMaxBurst               0
        wBytesPerInterval     512

        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               1
        bMaxBurst               0
        wBytesPerInterval    1024

        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               1
        bMaxBurst               1  # 2 packets per interval
        wBytesPerInterval    1536

Isochronous drivers use this function to size their URBs or select the
right altsetting for given bandwidth. UVC has obeyed wBytesPerInterval
since forever with no apparent issues and UAC has recently been patched
to work like that too with no issues so far AFAIK.

Maybe start with something specific to the known bogus hardware, i.e.
interrupt endpoint with one packet and zero payload? In such case
it's high chance that the device actually meant it to be wMaxPacket.

>  	default:
>  		if (usb_endpoint_is_hs_isoc_double(udev, ep))
>  			return le32_to_cpu(ep->eusb2_isoc_ep_comp.dwBytesPerInterval);
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  9:44 ` Michal Pecio
@ 2026-04-02 11:55   ` Xuetao (kirin)
  2026-04-03  7:16     ` Michal Pecio
  0 siblings, 1 reply; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-02 11:55 UTC (permalink / raw)
  To: Michal Pecio; +Cc: gregkh, linux-usb, linux-kernel, caiyadong, stable



在 2026/4/2 17:44, Michal Pecio 写道:
> On Thu, 2 Apr 2026 10:14:00 +0800, Tao Xue wrote:
>> As specified in Section 4.14.2 of the xHCI Specification, the xHC
>> reserves bandwidth for periodic endpoints according to bInterval and
>> wBytesPerInterval (Max ESIT Payload).
> 
> For SuperSpeed endpoints, yes.
> This follows from USB3 spec 9.6.7.
> 
>> Some peripherals report an invalid wBytesPerInterval in their device
>> descriptor, which is either 0 or smaller than the actual data length
>> transmitted. This issue is observed on ASIX AX88179 series USB 3.0
>> Ethernet adapters.
> 
> Damn, it really does.
> 
>        Endpoint Descriptor:
>          bLength                 7
>          bDescriptorType         5
>          bEndpointAddress     0x81  EP 1 IN
>          bmAttributes            3
>            Transfer Type            Interrupt
>            Synch Type               None
>            Usage Type               Data
>          wMaxPacketSize     0x0008  1x 8 bytes
>          bInterval              11
>          bMaxBurst               0
>          wBytesPerInterval       0
> 
> Any other examples besides AX88179?

We tested 18 different USB 3.0 docks, but they only contained two 
different types of USB 3.0 Ethernet devices based on VID/PID.
The dwc3 controller works fine with all of the devices mentioned above. 
The other USB host controller works fine with all 12 Realtek devices,
but fails with all 6 ASIX devices.

1. Realtek USB 10/100/1000 LAN (12 devices)
All 12 devices share the same VID/PID and descriptor values.

VID = 0x0BDA, PID = 0x8153
wMaxPacketSize = 0x10
bMaxBurst = 0
wBytesPerInterval = 0x8

2. ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter (6 devices)
All 6 devices share the same VID/PID.

VID = 0x0B95, PID = 0x1790
(a) 4 devices:
wMaxPacketSize = 0x10
bMaxBurst = 0
wBytesPerInterval = 0x0

(b) 2 devices:
wMaxPacketSize = 0x10
bMaxBurst = 0
wBytesPerInterval = 0x8

We also tested 3 different USB 3.0 camera devices. On all of these 
devices, the wBytesPerInterval of all SuperSpeed isochronous endpoints 
is equal to Mult * wMaxPacketSize * (bMaxBurst + 1).

> 
>> These errors may lead to unexpected behavior on certain USB host
>> controllers, causing USB peripherals to malfunction.
> 
> Out of curiosity, Bandwidth Overrun Error or something worse?
> 

This host controller reports a Babble error.

> It's an oversight that these URBs aren't rejected with EMSGSIZE in the
> first place. IIRC zero-length interrupt transfers are allowed by USB
> specs and a zero-payload endpoint is probably legal per xHCI, but then
> submitting non-empty URBs to it is not.
> 
>> To address the issue, return max(wBytesPerInterval, max_payload) when
>> calculating bandwidth reservation.
>>
>> Fixes: 9238f25d5d32 ("USB: xhci: properly set endpoint context fields for periodic eps.")
>> Cc: <stable@kernel.org>
>> Signed-off-by: Tao Xue <xuetao09@huawei.com>
>> ---
>>   drivers/usb/core/usb.c | 9 ++++++++-
>>   1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
>> index e9a10a33534c..8f2e05a5a015 100644
>> --- a/drivers/usb/core/usb.c
>> +++ b/drivers/usb/core/usb.c
>> @@ -1125,6 +1125,8 @@ EXPORT_SYMBOL_GPL(usb_free_noncoherent);
>>   u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>   				      const struct usb_host_endpoint *ep)
>>   {
>> +	u32 max_payload;
>> +
>>   	if (!usb_endpoint_xfer_isoc(&ep->desc) &&
>>   	    !usb_endpoint_xfer_int(&ep->desc))
>>   		return 0;
>> @@ -1135,7 +1137,12 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
>>   			return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
>>   		fallthrough;
>>   	case USB_SPEED_SUPER:
>> -		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
>> +		max_payload = usb_endpoint_maxp(&ep->desc) * (ep->ss_ep_comp.bMaxBurst + 1);
>> +		if (usb_endpoint_xfer_isoc(&ep->desc))
>> +			return max_t(u32, max_payload * USB_SS_MULT(ep->ss_ep_comp.bmAttributes),
>> +					ep->ss_ep_comp.wBytesPerInterval);
>> +		else
>> +			return max_t(u32, max_payload, ep->ss_ep_comp.wBytesPerInterval);
> 
> Obviously a kludge is necessary here to make these abominable devices
> work reliably with xHCI, but OTOH exceeding wBytesPerInterval violates
> USB3 9.6.7 and it's unclear if all devices would be happy.
> 
> There are devices which define such odd isochronous alt settings with
> apparent intent to allow fine-grained bandwidth reservation:
> 
>          wMaxPacketSize     0x0400  1x 1024 bytes
>          bInterval               1
>          bMaxBurst               0
>          wBytesPerInterval     512
> 
>          wMaxPacketSize     0x0400  1x 1024 bytes
>          bInterval               1
>          bMaxBurst               0
>          wBytesPerInterval    1024
> 
>          wMaxPacketSize     0x0400  1x 1024 bytes
>          bInterval               1
>          bMaxBurst               1  # 2 packets per interval
>          wBytesPerInterval    1536
> 
> Isochronous drivers use this function to size their URBs or select the
> right altsetting for given bandwidth. UVC has obeyed wBytesPerInterval
> since forever with no apparent issues and UAC has recently been patched
> to work like that too with no issues so far AFAIK.
> 
> Maybe start with something specific to the known bogus hardware, i.e.
> interrupt endpoint with one packet and zero payload? In such case
> it's high chance that the device actually meant it to be wMaxPacket.
> 
>>   	default:
>>   		if (usb_endpoint_is_hs_isoc_double(udev, ep))
>>   			return le32_to_cpu(ep->eusb2_isoc_ep_comp.dwBytesPerInterval);
>> -- 
>> 2.17.1
>>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02  6:59   ` Xuetao (kirin)
  2026-04-02  7:10     ` Greg KH
@ 2026-04-02 13:56     ` Alan Stern
  2026-04-02 14:09       ` Greg KH
  2026-04-02 20:17       ` [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Michal Pecio
  1 sibling, 2 replies; 21+ messages in thread
From: Alan Stern @ 2026-04-02 13:56 UTC (permalink / raw)
  To: Xuetao (kirin); +Cc: Greg KH, linux-usb, linux-kernel, caiyadong, stable

On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
> 2、Following Alan's suggestion in another email, should I check whether
> wBytesPerInterval is a valid value and handle it in the
> usb_parse_ss_endpoint_companion() ?

Yes, IMO.

> However, when parsing the device descriptor, we do not know whether the
> actual data length transmitted by the peripheral is greater than
> wBytesPerInterval.

Note: wBytesPerInterval is in the endpoint descriptor, not the device 
descriptor.

> Therefore, would it be sufficient to only add a check for whether
> wBytesPerInterval is 0 in the existing flow, and if it is 0, set
> wBytesPerInterval to cpu_to_le16(max_tx) by default?
> 
> For example, modify it in the following way:
> 
>      if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
> le16_to_cpu(desc->wBytesPerInterval) == 0) {
>         dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
>                 "config %d interface %d altsetting %d ep %d: "
>                 "setting to %d\n",
>                 usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
>                 le16_to_cpu(desc->wBytesPerInterval),
>                 cfgno, inum, asnum, ep->desc.bEndpointAddress,
>                 max_tx);
>         ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
>     }
> 
>  Could you please give me some advice? Thanks.

Try it and see if it fixes the problems you see with the network 
adapters.

I saw the Greg said not to change the descriptors and just fail the 
device, but we already make this sort of change to correct other errors 
so there doesn't seem to be any reason not to do it here as well.  
Especially if it allows people to use devices that otherwise would not 
work.

Alan Stern

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02 13:56     ` Alan Stern
@ 2026-04-02 14:09       ` Greg KH
  2026-04-02 15:03         ` Michal Pecio
  2026-04-03  1:20         ` Xuetao (kirin)
  2026-04-02 20:17       ` [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Michal Pecio
  1 sibling, 2 replies; 21+ messages in thread
From: Greg KH @ 2026-04-02 14:09 UTC (permalink / raw)
  To: Alan Stern; +Cc: Xuetao (kirin), linux-usb, linux-kernel, caiyadong, stable

On Thu, Apr 02, 2026 at 09:56:51AM -0400, Alan Stern wrote:
> On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
> > 2、Following Alan's suggestion in another email, should I check whether
> > wBytesPerInterval is a valid value and handle it in the
> > usb_parse_ss_endpoint_companion() ?
> 
> Yes, IMO.
> 
> > However, when parsing the device descriptor, we do not know whether the
> > actual data length transmitted by the peripheral is greater than
> > wBytesPerInterval.
> 
> Note: wBytesPerInterval is in the endpoint descriptor, not the device 
> descriptor.
> 
> > Therefore, would it be sufficient to only add a check for whether
> > wBytesPerInterval is 0 in the existing flow, and if it is 0, set
> > wBytesPerInterval to cpu_to_le16(max_tx) by default?
> > 
> > For example, modify it in the following way:
> > 
> >      if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
> > le16_to_cpu(desc->wBytesPerInterval) == 0) {
> >         dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
> >                 "config %d interface %d altsetting %d ep %d: "
> >                 "setting to %d\n",
> >                 usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
> >                 le16_to_cpu(desc->wBytesPerInterval),
> >                 cfgno, inum, asnum, ep->desc.bEndpointAddress,
> >                 max_tx);
> >         ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
> >     }
> > 
> >  Could you please give me some advice? Thanks.
> 
> Try it and see if it fixes the problems you see with the network 
> adapters.
> 
> I saw the Greg said not to change the descriptors and just fail the 
> device, but we already make this sort of change to correct other errors 
> so there doesn't seem to be any reason not to do it here as well.  
> Especially if it allows people to use devices that otherwise would not 
> work.

I didn't realize this was on "real" devices, sorry.  I thought this was
only a fuzzing thing.  So yes, fix up the broken descriptor after
warning about it is the correct thing to do.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02 14:09       ` Greg KH
@ 2026-04-02 15:03         ` Michal Pecio
  2026-04-03  1:20         ` Xuetao (kirin)
  1 sibling, 0 replies; 21+ messages in thread
From: Michal Pecio @ 2026-04-02 15:03 UTC (permalink / raw)
  To: Greg KH
  Cc: Alan Stern, Xuetao (kirin), linux-usb, linux-kernel, caiyadong,
	stable

On Thu, 2 Apr 2026 16:09:51 +0200, Greg KH wrote:
> I didn't realize this was on "real" devices, sorry.  I thought this
> was only a fuzzing thing.  So yes, fix up the broken descriptor after
> warning about it is the correct thing to do.

Such descriptors are not illegal per USB3 spec and they are seen in the
wild, at least on isochronous endpoints, and they were correct so far.

What's broken is that some particular device specifies less than its
driver actually submits (and presumably needs to submit for it to work).

Regards,
Michal

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02 13:56     ` Alan Stern
  2026-04-02 14:09       ` Greg KH
@ 2026-04-02 20:17       ` Michal Pecio
  1 sibling, 0 replies; 21+ messages in thread
From: Michal Pecio @ 2026-04-02 20:17 UTC (permalink / raw)
  To: Alan Stern
  Cc: Xuetao (kirin), Greg KH, linux-usb, linux-kernel, caiyadong,
	stable

On Thu, 2 Apr 2026 09:56:51 -0400, Alan Stern wrote:
> On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
> > 2、Following Alan's suggestion in another email, should I check
> > whether wBytesPerInterval is a valid value and handle it in the
> > usb_parse_ss_endpoint_companion() ?  
> 
> Yes, IMO.

Not sure, this could backfire if it turns out that these workarounds
will need to become more elaborate and account for wBytesPerInterval.

These descriptors aren't blatantly invalid. USB3 9.6.7 doesn't require
that wBytesPerInterval == wMaxPacketSize * bMaxBurst * Mult.

Being greater would be blatantly invalid, but this is already being
sanitized by the descriptor parser.

> > However, when parsing the device descriptor, we do not know whether
> > the actual data length transmitted by the peripheral is greater than
> > wBytesPerInterval.  

Indeed. Device is allowed (actually: required) not to send more data
than its wBytesPerInterval on IN endpoints.

UVC driver uses this field to pick isochronous altsetting capable of
transmitting a particular payload each interval. If we overestimate,
there is risk that the device will deliver on its promise and truncate
instead of violating USB3 spec. We should rather pick a larger alt.

OTOH, when a device lies and sends more than specified, this happens.
Some HCs ignore the problem (and may overcommit bandwidth if we enable
million such endpoints), others get pedantic and return Babble Error
(my mistake, Bandwidth Overrun is specific to isochronous).


I think this patch is relatively safe for interrupt, because drivers
generally don't look at endpoint descriptors and submit URBs of class
specific size. Case in point, everything works when you override xHCI
allocation. It also works on HCs ignoring it.

Beind the pedant I am, I would restrict this to bMaxBurst==0 because
that's the known problem case and IDK off-hand what devices might use
bursting interrupt endpoints and what gotchas await there.

Maybe add a comment that it's a questionable, spec-violating hack.

Regards,
Michal 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02 14:09       ` Greg KH
  2026-04-02 15:03         ` Michal Pecio
@ 2026-04-03  1:20         ` Xuetao (kirin)
  2026-04-22 13:26           ` Xuetao (kirin)
  1 sibling, 1 reply; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-03  1:20 UTC (permalink / raw)
  To: Greg KH, Alan Stern; +Cc: linux-usb, linux-kernel, caiyadong, stable



在 2026/4/2 22:09, Greg KH 写道:
> On Thu, Apr 02, 2026 at 09:56:51AM -0400, Alan Stern wrote:
>> On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
>>> 2、Following Alan's suggestion in another email, should I check whether
>>> wBytesPerInterval is a valid value and handle it in the
>>> usb_parse_ss_endpoint_companion() ?
>>
>> Yes, IMO.
>>
>>> However, when parsing the device descriptor, we do not know whether the
>>> actual data length transmitted by the peripheral is greater than
>>> wBytesPerInterval.
>>
>> Note: wBytesPerInterval is in the endpoint descriptor, not the device
>> descriptor.
>>

Thank you for your review. I will correct the description in the 
subsequent patch.

>>> Therefore, would it be sufficient to only add a check for whether
>>> wBytesPerInterval is 0 in the existing flow, and if it is 0, set
>>> wBytesPerInterval to cpu_to_le16(max_tx) by default?
>>>
>>> For example, modify it in the following way:
>>>
>>>       if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
>>> le16_to_cpu(desc->wBytesPerInterval) == 0) {
>>>          dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
>>>                  "config %d interface %d altsetting %d ep %d: "
>>>                  "setting to %d\n",
>>>                  usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
>>>                  le16_to_cpu(desc->wBytesPerInterval),
>>>                  cfgno, inum, asnum, ep->desc.bEndpointAddress,
>>>                  max_tx);
>>>          ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
>>>      }
>>>
>>>   Could you please give me some advice? Thanks.
>>
>> Try it and see if it fixes the problems you see with the network
>> adapters.
>>

Okay, I will verify the effectiveness of this modification and provide 
feedback on the results.

I guess that for the scenario where wBytesPerInterval is 0, it should be 
solvable. However, for the scenario where wBytesPerInterval is 8 but the 
peripheral sends a data length greater than 8 (e.g., 16), there might be 
an issue. I will test both of the above scenarios.

>> I saw the Greg said not to change the descriptors and just fail the
>> device, but we already make this sort of change to correct other errors
>> so there doesn't seem to be any reason not to do it here as well.
>> Especially if it allows people to use devices that otherwise would not
>> work.
> 
> I didn't realize this was on "real" devices, sorry.  I thought this was
> only a fuzzing thing.  So yes, fix up the broken descriptor after
> warning about it is the correct thing to do.
> 
> thanks,
> 
> greg k-h


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-02 11:55   ` Xuetao (kirin)
@ 2026-04-03  7:16     ` Michal Pecio
  2026-04-22  6:32       ` Michal Pecio
  0 siblings, 1 reply; 21+ messages in thread
From: Michal Pecio @ 2026-04-03  7:16 UTC (permalink / raw)
  To: Xuetao (kirin); +Cc: gregkh, linux-usb, linux-kernel, caiyadong, stable

On Thu, 2 Apr 2026 19:55:16 +0800, Xuetao (kirin) wrote:
> > Any other examples besides AX88179?  
> 
> We tested 18 different USB 3.0 docks, but they only contained two 
> different types of USB 3.0 Ethernet devices based on VID/PID.
> The dwc3 controller works fine with all of the devices mentioned
> above. The other USB host controller works fine with all 12 Realtek
> devices, but fails with all 6 ASIX devices.
> 
> 1. Realtek USB 10/100/1000 LAN (12 devices)
> All 12 devices share the same VID/PID and descriptor values.
> 
> VID = 0x0BDA, PID = 0x8153
> wMaxPacketSize = 0x10
> bMaxBurst = 0
> wBytesPerInterval = 0x8

My RTL8153 has this endpoint for its default proprietary configuration:

        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0002  1x 2 bytes
        bInterval               8
        bMaxBurst               0
        wBytesPerInterval       2

which should be problem-free, and this for its CDC configuration:

        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               8
        bMaxBurst               0
        wBytesPerInterval       8

The CDC configuration needs to be enabled with a patch, I'm not sure
if there is any other way. It will then use the r8153_ecm driver.

--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -9641,6 +9641,7 @@ static int rtl_fw_init(struct r8152 *tp)
 
 static u8 __rtl_get_hw_ver(struct usb_device *udev)
 {
+	return 0;
 	u32 ocp_data = 0;
 	__le32 *tmp;
 	u8 version;

> 2. ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter (6 devices)
> All 6 devices share the same VID/PID.
> 
> VID = 0x0B95, PID = 0x1790
> (a) 4 devices:
> wMaxPacketSize = 0x10
> bMaxBurst = 0
> wBytesPerInterval = 0x0

This looks like my AX88179 and it's obviously broken.

> (b) 2 devices:
> wMaxPacketSize = 0x10
> bMaxBurst = 0
> wBytesPerInterval = 0x8

But this is odd. When I use mine, I see that the driver submits 8 byte
URBs and they complete successfully with 8 bytes received, no babble.

ffff888100981b40 3364969734 S Ii:2:010:1 -115:1024 8 <
ffff888100981b40 3365097706 C Ii:2:010:1 0:1024 8 = a1000800 79490000

So I think this should work even with bandwidth reservation set to 8.
Can you check what happens here, before and after your patch?

Regards,
Michal

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-03  7:16     ` Michal Pecio
@ 2026-04-22  6:32       ` Michal Pecio
  0 siblings, 0 replies; 21+ messages in thread
From: Michal Pecio @ 2026-04-22  6:32 UTC (permalink / raw)
  To: Xuetao (kirin); +Cc: gregkh, linux-usb, linux-kernel, caiyadong, stable

On Fri, 3 Apr 2026 09:16:21 +0200, Michal Pecio wrote:
> On Thu, 2 Apr 2026 19:55:16 +0800, Xuetao (kirin) wrote:
> > > Any other examples besides AX88179?    
> > 
> > We tested 18 different USB 3.0 docks, but they only contained two 
> > different types of USB 3.0 Ethernet devices based on VID/PID.
> > The dwc3 controller works fine with all of the devices mentioned
> > above. The other USB host controller works fine with all 12 Realtek
> > devices, but fails with all 6 ASIX devices.

I think this issue hasn't been solved yet?

> > 1. Realtek USB 10/100/1000 LAN (12 devices)
> > All 12 devices share the same VID/PID and descriptor values.
> > 
> > VID = 0x0BDA, PID = 0x8153
> > wMaxPacketSize = 0x10
> > bMaxBurst = 0
> > wBytesPerInterval = 0x8  
> 
> My RTL8153 has this endpoint for its default proprietary configuration:
> 
>         bEndpointAddress     0x83  EP 3 IN
>         bmAttributes            3
>           Transfer Type            Interrupt
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0002  1x 2 bytes
>         bInterval               8
>         bMaxBurst               0
>         wBytesPerInterval       2
> 
> which should be problem-free, and this for its CDC configuration:
> 
>         bEndpointAddress     0x83  EP 3 IN
>         bmAttributes            3
>           Transfer Type            Interrupt
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0010  1x 16 bytes
>         bInterval               8
>         bMaxBurst               0
>         wBytesPerInterval       8
> 
> The CDC configuration needs to be enabled with a patch, I'm not sure
> if there is any other way. It will then use the r8153_ecm driver.

I have done some experimentation with RTL8153 CDC configuration and
found that it responds with 8 and 16 byte packets alternately:

# modprobe usbmon
# cat /sys/kernel/debug/usb/usbmon/0u
# ifconfig eth1 up
[...]
ffff88812bcc1600 364545038 S Ii:11:007:3 -115:128 16 <
ffff88812bcc1600 364577011 C Ii:11:007:3 0:128 8 = a1000000 01000000
ffff88812bcc1600 364577037 S Ii:11:007:3 -115:128 16 <
ffff88812bcc1600 364608979 C Ii:11:007:3 0:128 16 = a12a0000 01000800 00000000 00000000

I'm curious how your HC would treat this, because technically it should
interpret the first packet of wBytesPerInterval size as a partial
transfer and continue the same URB in the next interval, then complete
it with babble due to 16B packet exceeding both wBPI and URB capacity.

Other HCs work like that if I do the opposite and reduce wMaxPacketSize
to match wBytesPerInterval.

We would need to perform this alternative fixup for devices where
wBytesPerInterval is correct and 16B transfers are sent as two 8B
packets oven two intervals, while wMaxPacketSize is more than wBPI.
I hope no such insane devices exist. Currently, they wouldn't work
on the vast majority of HCs.

> > 2. ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter (6 devices)
> > All 6 devices share the same VID/PID.
> > 
> > VID = 0x0B95, PID = 0x1790
> > (a) 4 devices:
> > wMaxPacketSize = 0x10
> > bMaxBurst = 0
> > wBytesPerInterval = 0x0  
> 
> This looks like my AX88179 and it's obviously broken.
> 
> > (b) 2 devices:
> > wMaxPacketSize = 0x10
> > bMaxBurst = 0
> > wBytesPerInterval = 0x8  
> 
> But this is odd. When I use mine, I see that the driver submits 8 byte
> URBs and they complete successfully with 8 bytes received, no babble.

My driver submits 8B URBs because my AX88179 has wMaxPacketSize of 8.
On your device usbnet would submit 16B URBs. So I'm curious, how much
does your AX88179 send in response to those URBs?

Regards,
Michal

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-03  1:20         ` Xuetao (kirin)
@ 2026-04-22 13:26           ` Xuetao (kirin)
  2026-04-23  9:05             ` Michal Pecio
  0 siblings, 1 reply; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-22 13:26 UTC (permalink / raw)
  To: Greg KH, Alan Stern
  Cc: linux-usb, linux-kernel, caiyadong, stable, Michal Pecio



在 2026/4/3 9:20, Xuetao (kirin) 写道:
> 
> 
> 在 2026/4/2 22:09, Greg KH 写道:
>> On Thu, Apr 02, 2026 at 09:56:51AM -0400, Alan Stern wrote:
>>> On Thu, Apr 02, 2026 at 02:59:35PM +0800, Xuetao (kirin) wrote:
>>>> 2、Following Alan's suggestion in another email, should I check whether
>>>> wBytesPerInterval is a valid value and handle it in the
>>>> usb_parse_ss_endpoint_companion() ?
>>>
>>> Yes, IMO.
>>>
>>>> However, when parsing the device descriptor, we do not know whether the
>>>> actual data length transmitted by the peripheral is greater than
>>>> wBytesPerInterval.
>>>
>>> Note: wBytesPerInterval is in the endpoint descriptor, not the device
>>> descriptor.
>>>
> 
> Thank you for your review. I will correct the description in the 
> subsequent patch.
> 
>>>> Therefore, would it be sufficient to only add a check for whether
>>>> wBytesPerInterval is 0 in the existing flow, and if it is 0, set
>>>> wBytesPerInterval to cpu_to_le16(max_tx) by default?
>>>>
>>>> For example, modify it in the following way:
>>>>
>>>>       if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
>>>> le16_to_cpu(desc->wBytesPerInterval) == 0) {
>>>>          dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d 
>>>> in "
>>>>                  "config %d interface %d altsetting %d ep %d: "
>>>>                  "setting to %d\n",
>>>>                  usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
>>>>                  le16_to_cpu(desc->wBytesPerInterval),
>>>>                  cfgno, inum, asnum, ep->desc.bEndpointAddress,
>>>>                  max_tx);
>>>>          ep->ss_ep_comp.wBytesPerInterval = cpu_to_le16(max_tx);
>>>>      }
>>>>
>>>>   Could you please give me some advice? Thanks.
>>>
>>> Try it and see if it fixes the problems you see with the network
>>> adapters.
>>>
> 
> Okay, I will verify the effectiveness of this modification and provide 
> feedback on the results.
> 

By adding debug and capturing USB protocol analyzer traces, I have 
identified the pattern of this issue:

1. Why doesn't the Realtek USB 3.0 network adapter have this problem?

Realtek has two different types of interrupt endpoints:
(1) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x8
(2) wMaxPacketSize = 0x2, bMaxBurst = 0, wBytesPerInterval = 0x2

The Realtek network adapter uses the r8152.c driver. In rtl8152_open() 
-> usb_submit_urb(tp->intr_urb, GFP_KERNEL), the length of tp->intr_urb 
is fixed at 0x2.
The Realtek USB 3.0 network adapter uses the endpoint with 
wBytesPerInterval = 0x2 for network status queries. Since 
wBytesPerInterval = wMaxPacketSize × (bMaxBurst + 1) = 2, there is no 
problem.

2. The ASIX AX88179 USB 3.0 network adapter exhibits two different symptoms:

ASIX AX88179 has two different interrupt endpoint descriptors:
(1) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x0
(2) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x8

The ASIX AX88179 network adapter uses the ax88179_178a.c driver. In 
usbnet_open() -> usbnet_status_start() -> usb_submit_urb(dev->interrupt, 
mem_flags), the length of dev->interrupt is 0x10.

(1) When wBytesPerInterval = 0x8: When the software submits the INT URB, 
the host controller can normally send an INT IN request. If the device 
returns data length ≤ 8 bytes, the host and device interact normally, 
and the network works.
However, if the network adapter responds within one interval with a 
packet carrying 16 bytes of data, a specific host controller reports a 
babble error, causing network failure.

(2) When wBytesPerInterval = 0x0: The host controller does not reserve 
any bandwidth for the device. When the software submits the INT URB, a 
specific host controller does not issue an INT IN request to the device, 
nor does it report an error to the software. The device controller never 
receives the INT IN request, so the network fails.


Verification results:

Patch 1:
In usb_parse_ss_endpoint_companion(), if the interrupt endpoint's 
wBytesPerInterval is 0, set wBytesPerInterval to wMaxPacketSize × 
(bMaxBurst + 1).

Result 1:
This resolves the issue for ASIX AX88179 adapters with wBytesPerInterval 
= 0. However, for the scenario where wBytesPerInterval = 0x8, 
wMaxPacketSize = 0x10, and the device returns a 16-byte data payload, a 
babble error still occurs.

Patch 2:
In xhci_get_max_esit_payload(), when udev->speed >= USB_SPEED_SUPER, for 
interrupt endpoints return the maximum value between 
ep->ss_ep_comp.wBytesPerInterval and (max_burst + 1) × max_packet.

Result 2:
This resolves both scenarios described above. The only downside is that 
this modification may cause the host to waste a small amount of bandwidth.


> I guess that for the scenario where wBytesPerInterval is 0, it should be 
> solvable. However, for the scenario where wBytesPerInterval is 8 but the 
> peripheral sends a data length greater than 8 (e.g., 16), there might be 
> an issue. I will test both of the above scenarios.
> 
>>> I saw the Greg said not to change the descriptors and just fail the
>>> device, but we already make this sort of change to correct other errors
>>> so there doesn't seem to be any reason not to do it here as well.
>>> Especially if it allows people to use devices that otherwise would not
>>> work.
>>
>> I didn't realize this was on "real" devices, sorry.  I thought this was
>> only a fuzzing thing.  So yes, fix up the broken descriptor after
>> warning about it is the correct thing to do.
>>
>> thanks,
>>
>> greg k-h
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval
  2026-04-22 13:26           ` Xuetao (kirin)
@ 2026-04-23  9:05             ` Michal Pecio
  2026-04-23  9:06               ` [PATCH 1/2] usb: core: Fix root hub descriptor wBytesPerInterval Michal Pecio
  0 siblings, 1 reply; 21+ messages in thread
From: Michal Pecio @ 2026-04-23  9:05 UTC (permalink / raw)
  To: Xuetao (kirin)
  Cc: Greg KH, Alan Stern, linux-usb, linux-kernel, caiyadong, stable

On Wed, 22 Apr 2026 21:26:23 +0800, Xuetao (kirin) wrote:
> By adding debug and capturing USB protocol analyzer traces, I have 
> identified the pattern of this issue:
> 
> 1. Why doesn't the Realtek USB 3.0 network adapter have this problem?
> 
> Realtek has two different types of interrupt endpoints:
> (1) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x8
> (2) wMaxPacketSize = 0x2, bMaxBurst = 0, wBytesPerInterval = 0x2
> 
> The Realtek network adapter uses the r8152.c driver. In
> rtl8152_open() -> usb_submit_urb(tp->intr_urb, GFP_KERNEL), the
> length of tp->intr_urb is fixed at 0x2.
> The Realtek USB 3.0 network adapter uses the endpoint with 
> wBytesPerInterval = 0x2 for network status queries. Since 
> wBytesPerInterval = wMaxPacketSize × (bMaxBurst + 1) = 2, there is no 
> problem.

... until it's switched to its CDC configuration with a kernel patch,
then there is a problem. That CDC endpoint sends more than 8 bytes.

CDC is used as fallback on chip revs not yet supported by r8152 and
we aren't sure if future chips will fix their descriptors.

> 2. The ASIX AX88179 USB 3.0 network adapter exhibits two different
> symptoms:
> 
> ASIX AX88179 has two different interrupt endpoint descriptors:
> (1) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x0
> (2) wMaxPacketSize = 0x10, bMaxBurst = 0, wBytesPerInterval = 0x8
> 
> The ASIX AX88179 network adapter uses the ax88179_178a.c driver. In 
> usbnet_open() -> usbnet_status_start() ->
> usb_submit_urb(dev->interrupt, mem_flags), the length of
> dev->interrupt is 0x10.
> 
> (1) When wBytesPerInterval = 0x8: When the software submits the INT
> URB, the host controller can normally send an INT IN request. If the
> device returns data length ≤ 8 bytes, the host and device interact
> normally, and the network works.
> However, if the network adapter responds within one interval with a 
> packet carrying 16 bytes of data, a specific host controller reports
> a babble error, causing network failure.
> 
> (2) When wBytesPerInterval = 0x0: The host controller does not
> reserve any bandwidth for the device. When the software submits the
> INT URB, a specific host controller does not issue an INT IN request
> to the device, nor does it report an error to the software.

I think it's a HW bug because USB specs allow zero-length interrupt
transfers, though an inconsequential one if no device uses them.

These patches will work around it, because zero wMaxPacketSize is
disallowed by USB3 spec (though not by earlier ones) so wBPI will
always increase to at least 1.

> Verification results:
> 
> Patch 1:
> In usb_parse_ss_endpoint_companion(), if the interrupt endpoint's 
> wBytesPerInterval is 0, set wBytesPerInterval to wMaxPacketSize × 
> (bMaxBurst + 1).
> 
> Result 1:
> This resolves the issue for ASIX AX88179 adapters with
> wBytesPerInterval = 0. However, for the scenario where
> wBytesPerInterval = 0x8, wMaxPacketSize = 0x10, and the device
> returns a 16-byte data payload, a babble error still occurs.

And it will be same thing for RTL8153 CDC. This is too strict.

> Patch 2:
> In xhci_get_max_esit_payload(), when udev->speed >= USB_SPEED_SUPER,
> for interrupt endpoints return the maximum value between 
> ep->ss_ep_comp.wBytesPerInterval and (max_burst + 1) × max_packet.
> 
> Result 2:
> This resolves both scenarios described above. The only downside is
> that this modification may cause the host to waste a small amount of
> bandwidth.

I wrote a small patch which adds very similar logic to
usb_parse_ss_endpoint_companion(). This has two benefits:

1. Backportability - ESIT payload code has been refactored recently.
2. We can easily log when the tweak is performed, once per device.
   Maybe some HW vendors will notice and clean up their act.

Regards,
Michal

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/2] usb: core: Fix root hub descriptor wBytesPerInterval
  2026-04-23  9:05             ` Michal Pecio
@ 2026-04-23  9:06               ` Michal Pecio
  2026-04-23  9:09                 ` [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval Michal Pecio
  0 siblings, 1 reply; 21+ messages in thread
From: Michal Pecio @ 2026-04-23  9:06 UTC (permalink / raw)
  To: Xuetao (kirin)
  Cc: Greg KH, Alan Stern, linux-usb, linux-kernel, caiyadong, stable

Per USB3 9.6.7, it's "the total number of bytes this endpoint will
transfer every service interval". There seems to be no good reason
to have wBytesPerInterval < wMaxPacketSize - either one is too low
or the other too high. Here, wBytesPerInterval is too low for hubs
with more than 15 ports and xHCI spec allows such root hubs.

This is inconsequential for emulated root hubs, but we may want to
override and log suspiciously low wBytesPerInterval in descriptors,
so fix this to prevent nuisance warnings.

Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
---
 drivers/usb/core/hcd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 89221f1ce769..fc8130f94ca5 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -339,7 +339,8 @@ static const u8 ss_rh_config_descriptor[] = {
 		     /* Companion */
 	0x00,        /* __u8 ss_bMaxBurst; allows 1 TX between ACKs */
 	0x00,        /* __u8 ss_bmAttributes; 1 packet per service interval */
-	0x02, 0x00   /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
+		     /* __le16 ss_wBytesPerInterval; same as wMaxPacketSize */
+	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
 };
 
 /* authorized_default behaviour:
-- 
2.48.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval
  2026-04-23  9:06               ` [PATCH 1/2] usb: core: Fix root hub descriptor wBytesPerInterval Michal Pecio
@ 2026-04-23  9:09                 ` Michal Pecio
  2026-04-23 14:04                   ` Alan Stern
  0 siblings, 1 reply; 21+ messages in thread
From: Michal Pecio @ 2026-04-23  9:09 UTC (permalink / raw)
  To: Xuetao (kirin)
  Cc: Greg KH, Alan Stern, linux-usb, linux-kernel, caiyadong, stable

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@huawei.com>
Closes: https://lore.kernel.org/linux-usb/20260402021400.28853-1-xuetao09@huawei.com/
Cc: stable@vger.kernel.org
Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
---

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))) {
 		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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval
  2026-04-23  9:09                 ` [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval Michal Pecio
@ 2026-04-23 14:04                   ` Alan Stern
  2026-04-23 14:55                     ` Xuetao (kirin)
  0 siblings, 1 reply; 21+ messages in thread
From: Alan Stern @ 2026-04-23 14:04 UTC (permalink / raw)
  To: Michal Pecio
  Cc: Xuetao (kirin), Greg KH, linux-usb, linux-kernel, caiyadong,
	stable

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@huawei.com>
> Closes: https://lore.kernel.org/linux-usb/20260402021400.28853-1-xuetao09@huawei.com/
> Cc: stable@vger.kernel.org
> Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
> ---
> 
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval
  2026-04-23 14:04                   ` Alan Stern
@ 2026-04-23 14:55                     ` Xuetao (kirin)
  0 siblings, 0 replies; 21+ messages in thread
From: Xuetao (kirin) @ 2026-04-23 14:55 UTC (permalink / raw)
  To: Alan Stern, Michal Pecio
  Cc: Greg KH, linux-usb, linux-kernel, caiyadong, stable



在 2026/4/23 22:04, Alan Stern 写道:
> 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@huawei.com>
>> Closes: https://lore.kernel.org/linux-usb/20260402021400.28853-1-xuetao09@huawei.com/
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
>> ---
>>
>> 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

I tested the current patch, and it resolves the issue I encountered 
before. I believe this patch is effective.

I also just tested the modification that replaces 
usb_endpoint_xfer_int(&ep->desc) && usb_endpoint_dir_in(&ep->desc) with 
usb_endpoint_is_int_in(&ep->desc), and it works as well.

> 
> ) {
>>   		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


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-04-23 14:55 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-02  2:14 [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Tao Xue
2026-04-02  2:45 ` Alan Stern
2026-04-02  3:51 ` Greg KH
2026-04-02  6:59   ` Xuetao (kirin)
2026-04-02  7:10     ` Greg KH
2026-04-02  8:26       ` Xuetao (kirin)
2026-04-02 13:56     ` Alan Stern
2026-04-02 14:09       ` Greg KH
2026-04-02 15:03         ` Michal Pecio
2026-04-03  1:20         ` Xuetao (kirin)
2026-04-22 13:26           ` Xuetao (kirin)
2026-04-23  9:05             ` Michal Pecio
2026-04-23  9:06               ` [PATCH 1/2] usb: core: Fix root hub descriptor wBytesPerInterval Michal Pecio
2026-04-23  9:09                 ` [PATCH 2/2] usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval Michal Pecio
2026-04-23 14:04                   ` Alan Stern
2026-04-23 14:55                     ` Xuetao (kirin)
2026-04-02 20:17       ` [PATCH] usb: core: Fix bandwidth for devices with invalid wBytesPerInterval Michal Pecio
2026-04-02  9:44 ` Michal Pecio
2026-04-02 11:55   ` Xuetao (kirin)
2026-04-03  7:16     ` Michal Pecio
2026-04-22  6:32       ` Michal Pecio

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox