]> www.infradead.org Git - users/hch/misc.git/commitdiff
usb: core: support eUSB2 double bandwidth large isoc URB frames
authorRai, Amardeep <amardeep.rai@intel.com>
Wed, 20 Aug 2025 14:38:23 +0000 (17:38 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 Sep 2025 13:25:05 +0000 (15:25 +0200)
eUSB2 double isochronous in bandwidth devices support up to 6 transactions
per microframe, and thus doubles the total bytes possible to receive per
microframe.

Support larger URB isoc frame sizes for eUSB2 double isoc in endpoints.

Also usb_endpoint_maxp() returns a natural number so there's no need to
assume it could be < 0.

Signed-off-by: Rai, Amardeep <amardeep.rai@intel.com>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Co-developed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250820143824.551777-9-sakari.ailus@linux.intel.com
drivers/usb/core/urb.c
drivers/usb/core/usb.c

index 7a76d5a62db1db221ab18cfccec277d5f0d65c83..ff8df16cca35431e05ced46b2d7b1513d5196419 100644 (file)
@@ -372,6 +372,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        struct usb_host_endpoint        *ep;
        int                             is_out;
        unsigned int                    allowed;
+       bool                            is_eusb2_isoch_double;
 
        if (!urb || !urb->complete)
                return -EINVAL;
@@ -434,7 +435,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                return -ENODEV;
 
        max = usb_endpoint_maxp(&ep->desc);
-       if (max <= 0) {
+       is_eusb2_isoch_double = usb_endpoint_is_hs_isoc_double(dev, ep);
+       if (!max && !is_eusb2_isoch_double) {
                dev_dbg(&dev->dev,
                        "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
                        usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
@@ -467,9 +469,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                        max = le32_to_cpu(isoc_ep_comp->dwBytesPerInterval);
                }
 
-               /* "high bandwidth" mode, 1-3 packets/uframe? */
-               if (dev->speed == USB_SPEED_HIGH)
-                       max *= usb_endpoint_maxp_mult(&ep->desc);
+               /* High speed, 1-3 packets/uframe, max 6 for eUSB2 double bw */
+               if (dev->speed == USB_SPEED_HIGH) {
+                       if (is_eusb2_isoch_double)
+                               max = le32_to_cpu(ep->eusb2_isoc_ep_comp.dwBytesPerInterval);
+                       else
+                               max *= usb_endpoint_maxp_mult(&ep->desc);
+               }
 
                if (urb->number_of_packets <= 0)
                        return -EINVAL;
index 939dc4aafb898c53e9c702d432b5ef488ea81532..b88b6271cb301896b1f6464f327b826a40183a2c 100644 (file)
@@ -1134,6 +1134,8 @@ u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
        case USB_SPEED_SUPER:
                return le16_to_cpu(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);
                return usb_endpoint_maxp(&ep->desc) * usb_endpoint_maxp_mult(&ep->desc);
        }
 }