aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-11 19:14:58 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-27 15:08:14 -0400
commit2cf95c18d5069e13c02a8667d91e064df8e17e09 (patch)
tree05ae0e90ceab6790ccd1e624b695b984c6081f87 /drivers/usb/host/xhci-ring.c
parentad808333d8201d53075a11bc8dd83b81f3d68f0b (diff)
Intel xhci: Limit number of active endpoints to 64.
The Panther Point chipset has an xHCI host controller that has a limit to the number of active endpoints it can handle. Ideally, it would signal that it can't handle anymore endpoints by returning a Resource Error for the Configure Endpoint command, but they don't. Instead it needs software to keep track of the number of active endpoints, across configure endpoint commands, reset device commands, disable slot commands, and address device commands. Add a new endpoint context counter, xhci_hcd->num_active_eps, and use it to track the number of endpoints the xHC has active. This gets a little tricky, because commands to change the number of active endpoints can fail. This patch adds a new xHCI quirk for these Intel hosts, and the new code should not have any effect on other xHCI host controllers. Fail a new device allocation if we don't have room for the new default control endpoint. Use the endpoint ring pointers to determine what endpoints were active before a Reset Device command or a Disable Slot command, and drop those once the command completes. Fail a configure endpoint command if it would add too many new endpoints. We have to be a bit over zealous here, and only count the number of new endpoints to be added, without subtracting the number of dropped endpoints. That's because a second configure endpoint command for a different device could sneak in before we know if the first command is completed. If the first command dropped resources, the host controller fails the command for some reason, and we're nearing the limit of endpoints, we could end up oversubscribing the host. To fix this race condition, when evaluating whether a configure endpoint command will fix in our bandwidth budget, only add the new endpoints to xhci->num_active_eps, and don't subtract the dropped endpoints. Ignore changed endpoints (ones that are dropped and then re-added), as that shouldn't effect the host's endpoint resources. When the configure endpoint command completes, subtract off the dropped endpoints. This may mean some configuration changes may temporarily fail, but it's always better to under-subscribe than over-subscribe resources. (Originally my plan had been to push the resource allocation down into the ring allocation functions. However, that would cause us to allocate unnecessary resources when endpoints were changed, because the xHCI driver allocates a new ring for the changed endpoint, and only deletes the old ring once the Configure Endpoint command succeeds. A further complication would have been dealing with the per-device endpoint ring cache.) Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 56f6c584c651..cc1485bfed38 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1081,8 +1081,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
1081 complete(&xhci->addr_dev); 1081 complete(&xhci->addr_dev);
1082 break; 1082 break;
1083 case TRB_TYPE(TRB_DISABLE_SLOT): 1083 case TRB_TYPE(TRB_DISABLE_SLOT):
1084 if (xhci->devs[slot_id]) 1084 if (xhci->devs[slot_id]) {
1085 if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
1086 /* Delete default control endpoint resources */
1087 xhci_free_device_endpoint_resources(xhci,
1088 xhci->devs[slot_id], true);
1085 xhci_free_virt_device(xhci, slot_id); 1089 xhci_free_virt_device(xhci, slot_id);
1090 }
1086 break; 1091 break;
1087 case TRB_TYPE(TRB_CONFIG_EP): 1092 case TRB_TYPE(TRB_CONFIG_EP):
1088 virt_dev = xhci->devs[slot_id]; 1093 virt_dev = xhci->devs[slot_id];