summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-28 04:58:38 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 06:44:49 +0200
commitf94e0186312b0fc39f41eed4e21836ed74b7efe1 (patch)
treed445d846f62c23cfbefc4958168d9cf4bacea3a4 /drivers/usb/host/xhci-ring.c
parentUSB: Support for bandwidth allocation. (diff)
downloadlinux-f94e0186312b0fc39f41eed4e21836ed74b7efe1.tar.xz
linux-f94e0186312b0fc39f41eed4e21836ed74b7efe1.zip
USB: xhci: Bandwidth allocation support
Since the xHCI host controller hardware (xHC) has an internal schedule, it needs a better representation of what devices are consuming bandwidth on the bus. Each device is represented by a device context, with data about the device, endpoints, and pointers to each endpoint ring. We need to update the endpoint information for a device context before a new configuration or alternate interface setting is selected. We setup an input device context with modified endpoint information and newly allocated endpoint rings, and then submit a Configure Endpoint Command to the hardware. The host controller can reject the new configuration if it exceeds the bus bandwidth, or the host controller doesn't have enough internal resources for the configuration. If the command fails, we still have the older device context with the previous configuration. If the command succeeds, we free the old endpoint rings. The root hub isn't a real device, so always say yes to any bandwidth changes for it. The USB core will enable, disable, and then enable endpoint 0 several times during the initialization sequence. The device will always have an endpoint ring for endpoint 0 and bandwidth allocated for that, unless the device is disconnected or gets a SetAddress 0 request. So we don't pay attention for when xhci_check_bandwidth() is called for a re-add of endpoint 0. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f04162ae4374..b4ccf0d72c17 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -281,6 +281,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
if (xhci->devs[slot_id])
xhci_free_virt_device(xhci, slot_id);
break;
+ case TRB_TYPE(TRB_CONFIG_EP):
+ xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ break;
case TRB_TYPE(TRB_ADDR_DEV):
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
complete(&xhci->addr_dev);
@@ -809,3 +813,10 @@ int queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_
return queue_command(xhci, in_ctx_ptr, 0, 0,
TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
}
+
+/* Queue a configure endpoint command TRB */
+int queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id)
+{
+ return queue_command(xhci, in_ctx_ptr, 0, 0,
+ TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
+}