summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
{