| From 1cf62246c0e394021e494e0a8f1013e80db1a1a9 Mon Sep 17 00:00:00 2001 |
| From: Sarah Sharp <sarah.a.sharp@linux.intel.com> |
| Date: Fri, 16 Apr 2010 08:07:04 -0700 |
| Subject: USB: xhci: properly set the "Mult" field of the endpoint context. |
| |
| From: Sarah Sharp <sarah.a.sharp@linux.intel.com> |
| |
| 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> |
| |
| --- |
| drivers/usb/host/xhci-mem.c | 14 ++++++++++++++ |
| 1 file changed, 14 insertions(+) |
| |
| --- a/drivers/usb/host/xhci-mem.c |
| +++ b/drivers/usb/host/xhci-mem.c |
| @@ -549,6 +549,19 @@ static inline unsigned int xhci_get_endp |
| 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) |
| { |
| @@ -611,6 +624,7 @@ int xhci_endpoint_init(struct xhci_hcd * |
| 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 */ |
| |