Commit 1cf62246 authored by Sarah Sharp's avatar Sarah Sharp Committed by Greg Kroah-Hartman

USB: xhci: properly set the "Mult" field of the endpoint context.

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: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent fcf7d214
...@@ -582,6 +582,19 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, ...@@ -582,6 +582,19 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
return EP_INTERVAL(interval); 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, static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
struct usb_host_endpoint *ep) struct usb_host_endpoint *ep)
{ {
...@@ -644,6 +657,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ...@@ -644,6 +657,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; 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 = 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 */ /* FIXME dig Mult and streams info out of ep companion desc */
......
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