summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-04-16 08:07:04 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-12 14:57:03 -0700
commit0a0da543426241627580bda5fccb5ddf444a1aba (patch)
tree5d79997095b1500e75ed9813b4da2dd4cc26fb4e
parentdd13b9f4a90b5dcefb7ef36393a55c96f3f10a76 (diff)
USB: xhci: properly set the "Mult" field of the endpoint context.
commit 1cf62246c0e394021e494e0a8f1013e80db1a1a9 upstream. A SuperSpeed interrupt or isochronous endpoint can define the number of "burst transactions" it can handle in a service interval. This is indicated by the "Mult" bits in the bmAttributes of the SuperSpeed Endpoint Companion Descriptor. For example, if it has a max packet size of 1024, a max burst of 11, and a mult of 3, the host may send 33 1024-byte packets in one service interval. We must tell the xHCI host controller the number of multiple service opportunities (mults) the device can handle when the endpoint is installed. We do that by setting the Mult field of the Endpoint Context before a configure endpoint command is sent down. The Mult field is invalid for control or bulk SuperSpeed endpoints. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/xhci-mem.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b8fd270a8b0d..2ddf40c0a389 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -496,6 +496,19 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
return EP_INTERVAL(interval);
}
+/* The "Mult" field in the endpoint context is only set for SuperSpeed devices.
+ * 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 inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ if (udev->speed != USB_SPEED_SUPER || !ep->ss_ep_comp)
+ return 0;
+ return ep->ss_ep_comp->desc.bmAttributes;
+}
+
static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
@@ -550,6 +563,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
+ ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep));
/* FIXME dig Mult and streams info out of ep companion desc */