summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c87
1 files changed, 42 insertions, 45 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 81eaad87a3d9..6e5b6057de79 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
out:
/* we are now at a leaf device */
xhci_debugfs_remove_slot(xhci, slot_id);
- xhci_free_virt_device(xhci, vdev, slot_id);
+ xhci_free_virt_device(xhci, xhci->devs[slot_id], slot_id);
}
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
@@ -1330,18 +1330,33 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
return interval;
}
-/* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
+/*
+ * xHCs without LEC use the "Mult" field in the endpoint context for SuperSpeed
+ * isoc eps, and High speed isoc eps that support bandwidth doubling. Standard
* High speed endpoint descriptors can define "the number of additional
* transaction opportunities per microframe", but that goes in the Max Burst
* endpoint context field.
*/
-static u32 xhci_get_endpoint_mult(struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static u32 xhci_get_endpoint_mult(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
- if (udev->speed < USB_SPEED_SUPER ||
- !usb_endpoint_xfer_isoc(&ep->desc))
- return 0;
- return ep->ss_ep_comp.bmAttributes;
+ bool lec;
+
+ /* xHCI 1.1 with LEC set does not use mult field, except intel eUSB2 */
+ lec = xhci->hci_version > 0x100 && HCC2_LEC(xhci->hcc_params2);
+
+ /* eUSB2 double isoc bw devices are the only USB2 devices using mult */
+ if (usb_endpoint_is_hs_isoc_double(udev, ep) &&
+ (!lec || xhci->quirks & XHCI_INTEL_HOST))
+ return 1;
+
+ /* SuperSpeed isoc transfers on hosts without LEC uses mult field */
+ if (udev->speed >= USB_SPEED_SUPER &&
+ usb_endpoint_xfer_isoc(&ep->desc) && !lec)
+ return ep->ss_ep_comp.bmAttributes;
+
+ return 0;
}
static u32 xhci_get_endpoint_max_burst(struct usb_device *udev,
@@ -1353,8 +1368,16 @@ static u32 xhci_get_endpoint_max_burst(struct usb_device *udev,
if (udev->speed == USB_SPEED_HIGH &&
(usb_endpoint_xfer_isoc(&ep->desc) ||
- usb_endpoint_xfer_int(&ep->desc)))
+ usb_endpoint_xfer_int(&ep->desc))) {
+ /*
+ * USB 2 Isochronous Double IN Bandwidth ECN uses fixed burst
+ * size and max packets bits 12:11 are invalid.
+ */
+ if (usb_endpoint_is_hs_isoc_double(udev, ep))
+ return 2;
+
return usb_endpoint_maxp_mult(&ep->desc) - 1;
+ }
return 0;
}
@@ -1378,36 +1401,6 @@ static u32 xhci_get_endpoint_type(struct usb_host_endpoint *ep)
return 0;
}
-/* Return the maximum endpoint service interval time (ESIT) payload.
- * Basically, this is the maxpacket size, multiplied by the burst size
- * and mult size.
- */
-static u32 xhci_get_max_esit_payload(struct usb_device *udev,
- struct usb_host_endpoint *ep)
-{
- int max_burst;
- int max_packet;
-
- /* Only applies for interrupt or isochronous endpoints */
- if (usb_endpoint_xfer_control(&ep->desc) ||
- usb_endpoint_xfer_bulk(&ep->desc))
- return 0;
-
- /* 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 */
- if (udev->speed >= USB_SPEED_SUPER)
- return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
-
- max_packet = usb_endpoint_maxp(&ep->desc);
- max_burst = usb_endpoint_maxp_mult(&ep->desc);
- /* A 0 in max burst means 1 transfer per ESIT */
- return max_packet * max_burst;
-}
-
/* Set up an endpoint with one ring segment. Do not allocate stream rings.
* Drivers will have to call usb_alloc_streams() to do that.
*/
@@ -1439,13 +1432,20 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
ring_type = usb_endpoint_type(&ep->desc);
+ /* Ensure host supports double isoc bandwidth for eUSB2 devices */
+ if (usb_endpoint_is_hs_isoc_double(udev, ep) &&
+ !HCC2_EUSB2_DIC(xhci->hcc_params2)) {
+ dev_dbg(&udev->dev, "Double Isoc Bandwidth not supported by xhci\n");
+ return -EINVAL;
+ }
+
/*
* Get values to fill the endpoint context, mostly from ep descriptor.
* The average TRB buffer lengt for bulk endpoints is unclear as we
* have no clue on scatter gather list entry size. For Isoc and Int,
* set it to max available. See xHCI 1.1 spec 4.14.1.1 for details.
*/
- max_esit_payload = xhci_get_max_esit_payload(udev, ep);
+ max_esit_payload = usb_endpoint_max_periodic_payload(udev, ep);
interval = xhci_get_endpoint_interval(udev, ep);
/* Periodic endpoint bInterval limit quirk */
@@ -1462,8 +1462,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
}
}
- mult = xhci_get_endpoint_mult(udev, ep);
- max_packet = usb_endpoint_maxp(&ep->desc);
+ mult = xhci_get_endpoint_mult(xhci, udev, ep);
+ max_packet = xhci_usb_endpoint_maxp(udev, ep);
max_burst = xhci_get_endpoint_max_burst(udev, ep);
avg_trb_len = max_esit_payload;
@@ -1484,9 +1484,6 @@ 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;
/* Set up the endpoint ring */
virt_dev->eps[ep_index].new_ring =