summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRai, Amardeep <amardeep.rai@intel.com>2025-08-20 17:38:19 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-09-06 15:25:05 +0200
commit20f988320d2718ef28b1f0635acc88c12a216d29 (patch)
tree9ca695cfe32987f5d63335cef70fd54f3fbb7f62
parent53d76c6866a0362320b837dd292db4befcac31ba (diff)
usb: core: Add a function to get USB version independent periodic payload
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
-rw-r--r--drivers/usb/core/usb.c29
-rw-r--r--include/linux/usb.h3
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index fca7735fc660..ca9ff6ad8e73 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -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
*/
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 9d662c6abb4d..e9cf2786d8bd 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -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)
{