Commit 8ef8a9f5 authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

xhci: Add SuperSpeedPlus high bandwidth isoc support to xhci endpoints

SuperSpeedPlus doubled the number of transactions per service interval
the isoc endpoints supports.

To support this, xhci 1.1 added Large ESIT Capability (LEC), which
takes into use new bits in the endpoint context to fit the parameters.

If xhci supports LEC, and the device has a SuperSpeedPlus Isoc companion
descriptor then take into use the high bits of max esit payload, and
skip calculating the Mult field as it wouldn't fit. LEC capable
host will calculate the Mult based on other paramenters.
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent def4e6f7
...@@ -1390,7 +1390,12 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, ...@@ -1390,7 +1390,12 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev,
usb_endpoint_xfer_bulk(&ep->desc)) usb_endpoint_xfer_bulk(&ep->desc))
return 0; return 0;
if (udev->speed >= USB_SPEED_SUPER) /* SuperSpeedPlus Isoc ep sending over 48k per esit */
if ((udev->speed >= USB_SPEED_SUPER_PLUS) &&
USB_SS_SSP_ISOC_COMP(ep->ss_ep_comp.bmAttributes))
return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval);
/* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */
else if (udev->speed >= USB_SPEED_SUPER)
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
...@@ -1470,9 +1475,13 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ...@@ -1470,9 +1475,13 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
/* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */ /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
avg_trb_len = 8; avg_trb_len = 8;
/* xhci 1.1 with LEC support doesn't use mult field, use RsvdZ */
if ((xhci->hci_version > 0x100) && HCC2_LEC(xhci->hcc_params2))
mult = 0;
/* Fill the endpoint context */ /* Fill the endpoint context */
ep_ctx->ep_info = cpu_to_le32(EP_INTERVAL(interval) | ep_ctx->ep_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) |
EP_INTERVAL(interval) |
EP_MULT(mult)); EP_MULT(mult));
ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) | ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) |
MAX_PACKET(max_packet) | MAX_PACKET(max_packet) |
......
...@@ -751,6 +751,7 @@ struct xhci_ep_ctx { ...@@ -751,6 +751,7 @@ struct xhci_ep_ctx {
/* tx_info bitmasks */ /* tx_info bitmasks */
#define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) #define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff)
#define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) #define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16)
#define EP_MAX_ESIT_PAYLOAD_HI(p) ((((p) >> 16) & 0xff) << 24)
#define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) #define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff)
/* deq bitmasks */ /* deq bitmasks */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment