summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2016-02-12 16:40:16 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-02-14 17:03:23 -0800
commit8ef8a9f5c148ae1dbeae926e5b6129e396faded2 (patch)
treeb4ef5dbf8f0d7736c584e3c9f32ddfe0e3ee4963 /drivers/usb/host
parentdef4e6f7b419c4092c82222d0896d6c409692326 (diff)
downloadop-kernel-dev-8ef8a9f5c148ae1dbeae926e5b6129e396faded2.zip
op-kernel-dev-8ef8a9f5c148ae1dbeae926e5b6129e396faded2.tar.gz
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: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-mem.c13
-rw-r--r--drivers/usb/host/xhci.h1
2 files changed, 12 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4e3abdd..80c1de2 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1390,7 +1390,12 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev,
usb_endpoint_xfer_bulk(&ep->desc))
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);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
@@ -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 */
if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
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 */
- 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_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) |
MAX_PACKET(max_packet) |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index a0279cf..40a7efd 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -751,6 +751,7 @@ struct xhci_ep_ctx {
/* tx_info bitmasks */
#define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff)
#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)
/* deq bitmasks */
OpenPOWER on IntegriCloud