]> www.infradead.org Git - users/hch/misc.git/commitdiff
usb: core: Add a function to get USB version independent periodic payload
authorRai, Amardeep <amardeep.rai@intel.com>
Wed, 20 Aug 2025 14:38:19 +0000 (17:38 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 Sep 2025 13:25:05 +0000 (15:25 +0200)
Add usb_endpoint_max_periodic_payload() to obtain maximum payload bytes in
a service interval for isochronous and interrupt endpoints in a USB
version independent way.

Signed-off-by: Rai, Amardeep <amardeep.rai@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>
Reviewed-by: Hans de Goede <hansg@kernel.org>
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-5-sakari.ailus@linux.intel.com
drivers/usb/core/usb.c
include/linux/usb.h

index fca7735fc660eb7ef561007e8bf0ba7daeb311b4..ca9ff6ad8e739f147f4e37497b027453153d518a 100644 (file)
@@ -1110,6 +1110,35 @@ void usb_free_noncoherent(struct usb_device *dev, size_t size,
 }
 EXPORT_SYMBOL_GPL(usb_free_noncoherent);
 
+/**
+ * usb_endpoint_max_periodic_payload - Get maximum payload bytes per service
+ *                                    interval
+ * @udev: The USB device
+ * @ep: The endpoint
+ *
+ * Returns: the maximum number of bytes isochronous or interrupt endpoint @ep
+ * can transfer during a service interval, or 0 for other endpoints.
+ */
+u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
+                                     const struct usb_host_endpoint *ep)
+{
+       if (!usb_endpoint_xfer_isoc(&ep->desc) &&
+           !usb_endpoint_xfer_int(&ep->desc))
+               return 0;
+
+       switch (udev->speed) {
+       case USB_SPEED_SUPER_PLUS:
+               if (USB_SS_SSP_ISOC_COMP(ep->ss_ep_comp.bmAttributes))
+                       return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
+               fallthrough;
+       case USB_SPEED_SUPER:
+               return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
+       default:
+               return usb_endpoint_maxp(&ep->desc) * usb_endpoint_maxp_mult(&ep->desc);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_endpoint_max_periodic_payload);
+
 /*
  * Notifications of device and interface registration
  */
index 9d662c6abb4d7d1bd06b16b345612b0c7f3b8a23..e9cf2786d8bdcd0c5142044ab820120b9c84b95e 100644 (file)
@@ -2039,6 +2039,9 @@ static inline u16 usb_maxpacket(struct usb_device *udev, int pipe)
        return usb_endpoint_maxp(&ep->desc);
 }
 
+u32 usb_endpoint_max_periodic_payload(struct usb_device *udev,
+                                     const struct usb_host_endpoint *ep);
+
 /* translate USB error codes to codes user space understands */
 static inline int usb_translate_errors(int error_code)
 {