aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-09-04 13:53:20 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:40 -0400
commitac1c1b7f16ed287fcec5bcfae06d0165c3941ec3 (patch)
tree977be3ee0c12da25d453b35a419151eafcd19406 /drivers/usb
parent07b6de102843b717ecd962cf35ec4ad9b1fbed9d (diff)
USB: xhci: Support USB hubs.
For a USB hub to work under an xHCI host controller, the xHC's internal scheduler must be made aware of the hub's characteristics. Add an xHCI hook that the USB core will call after it fetches the hub descriptor. This hook will add hub information to the slot context for that device, including whether it has multiple TTs or a single TT, the number of ports on the hub, and TT think time. Setting up the slot context for the device is different for 0.95 and 0.96 xHCI host controllers. Some of the slot context reserved fields in the 0.95 specification were changed into hub fields in the 0.96 specification. Don't set the TT think time or number of ports for a hub if we're dealing with a 0.95-compliant xHCI host controller. The 0.95 xHCI specification says that to modify the hub flag, we need to issue an evaluate context command. The 0.96 specification says that flag can be set with a configure endpoint command. Issue the correct command based on the version reported by the hardware. This patch does not add support for multi-TT hubs. Multi-TT hubs expose a single TT on alt setting 0, and multi-TT on alt setting 1. The xHCI driver can't handle setting alternate interfaces yet. 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')
-rw-r--r--drivers/usb/host/xhci-hcd.c82
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/host/xhci-ring.c3
-rw-r--r--drivers/usb/host/xhci.h5
4 files changed, 92 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index 2fcc360f064..99911e727e0 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -1594,6 +1594,88 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
1594 return 0; 1594 return 0;
1595} 1595}
1596 1596
1597/* Once a hub descriptor is fetched for a device, we need to update the xHC's
1598 * internal data structures for the device.
1599 */
1600int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
1601 struct usb_tt *tt, gfp_t mem_flags)
1602{
1603 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
1604 struct xhci_virt_device *vdev;
1605 struct xhci_command *config_cmd;
1606 struct xhci_input_control_ctx *ctrl_ctx;
1607 struct xhci_slot_ctx *slot_ctx;
1608 unsigned long flags;
1609 unsigned think_time;
1610 int ret;
1611
1612 /* Ignore root hubs */
1613 if (!hdev->parent)
1614 return 0;
1615
1616 vdev = xhci->devs[hdev->slot_id];
1617 if (!vdev) {
1618 xhci_warn(xhci, "Cannot update hub desc for unknown device.\n");
1619 return -EINVAL;
1620 }
1621 config_cmd = xhci_alloc_command(xhci, true, mem_flags);
1622 if (!config_cmd) {
1623 xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
1624 return -ENOMEM;
1625 }
1626
1627 spin_lock_irqsave(&xhci->lock, flags);
1628 xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
1629 ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx);
1630 ctrl_ctx->add_flags |= SLOT_FLAG;
1631 slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
1632 slot_ctx->dev_info |= DEV_HUB;
1633 if (tt->multi)
1634 slot_ctx->dev_info |= DEV_MTT;
1635 if (xhci->hci_version > 0x95) {
1636 xhci_dbg(xhci, "xHCI version %x needs hub "
1637 "TT think time and number of ports\n",
1638 (unsigned int) xhci->hci_version);
1639 slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild);
1640 /* Set TT think time - convert from ns to FS bit times.
1641 * 0 = 8 FS bit times, 1 = 16 FS bit times,
1642 * 2 = 24 FS bit times, 3 = 32 FS bit times.
1643 */
1644 think_time = tt->think_time;
1645 if (think_time != 0)
1646 think_time = (think_time / 666) - 1;
1647 slot_ctx->tt_info |= TT_THINK_TIME(think_time);
1648 } else {
1649 xhci_dbg(xhci, "xHCI version %x doesn't need hub "
1650 "TT think time or number of ports\n",
1651 (unsigned int) xhci->hci_version);
1652 }
1653 slot_ctx->dev_state = 0;
1654 spin_unlock_irqrestore(&xhci->lock, flags);
1655
1656 xhci_dbg(xhci, "Set up %s for hub device.\n",
1657 (xhci->hci_version > 0x95) ?
1658 "configure endpoint" : "evaluate context");
1659 xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id);
1660 xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0);
1661
1662 /* Issue and wait for the configure endpoint or
1663 * evaluate context command.
1664 */
1665 if (xhci->hci_version > 0x95)
1666 ret = xhci_configure_endpoint(xhci, hdev, config_cmd,
1667 false, false);
1668 else
1669 ret = xhci_configure_endpoint(xhci, hdev, config_cmd,
1670 true, false);
1671
1672 xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id);
1673 xhci_dbg_ctx(xhci, vdev->out_ctx, 0);
1674
1675 xhci_free_command(xhci, config_cmd);
1676 return ret;
1677}
1678
1597int xhci_get_frame(struct usb_hcd *hcd) 1679int xhci_get_frame(struct usb_hcd *hcd)
1598{ 1680{
1599 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1681 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 8fb308d43bc..b7712f22a9f 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -63,6 +63,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
63 xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1); 63 xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1);
64 xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2); 64 xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2);
65 xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); 65 xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
66 xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
67 xhci->hci_version = HC_VERSION(xhci->hcc_params);
66 xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params); 68 xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
67 xhci_print_registers(xhci); 69 xhci_print_registers(xhci);
68 70
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2274604e863..173c39c7648 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -789,6 +789,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
789 } 789 }
790 break; 790 break;
791 case TRB_TYPE(TRB_EVAL_CONTEXT): 791 case TRB_TYPE(TRB_EVAL_CONTEXT):
792 virt_dev = xhci->devs[slot_id];
793 if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
794 break;
792 xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); 795 xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
793 complete(&xhci->devs[slot_id]->cmd_completion); 796 complete(&xhci->devs[slot_id]->cmd_completion);
794 break; 797 break;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 36f7d4f91d9..4b254b6fa24 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -509,6 +509,8 @@ struct xhci_slot_ctx {
509#define MAX_EXIT (0xffff) 509#define MAX_EXIT (0xffff)
510/* Root hub port number that is needed to access the USB device */ 510/* Root hub port number that is needed to access the USB device */
511#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16) 511#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16)
512/* Maximum number of ports under a hub device */
513#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24)
512 514
513/* tt_info bitmasks */ 515/* tt_info bitmasks */
514/* 516/*
@@ -522,6 +524,7 @@ struct xhci_slot_ctx {
522 * '0' if the device is not low or full speed. 524 * '0' if the device is not low or full speed.
523 */ 525 */
524#define TT_PORT (0xff << 8) 526#define TT_PORT (0xff << 8)
527#define TT_THINK_TIME(p) (((p) & 0x3) << 16)
525 528
526/* dev_state bitmasks */ 529/* dev_state bitmasks */
527/* USB device address - assigned by the HC */ 530/* USB device address - assigned by the HC */
@@ -1231,6 +1234,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd);
1231int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); 1234int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
1232void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); 1235void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
1233int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); 1236int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
1237int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
1238 struct usb_tt *tt, gfp_t mem_flags);
1234int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); 1239int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
1235int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); 1240int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
1236int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); 1241int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);