aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2010-11-30 18:38:41 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-30 18:38:41 -0500
commit8244272341f00cab845cabc445dbd3665fc01f87 (patch)
tree3a0d426b2aaf24c78e5b3b1f7c31e9210186aa8d /drivers/usb/host
parentabf03184a31a3286fc0ab30f838ddee8ba9f9b7b (diff)
parent6dd0a3a7e0793dbeae1b951f091025d8cf896cb4 (diff)
Merge branch 'for-usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into work
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-hub.c7
-rw-r--r--drivers/usb/host/xhci-mem.c164
-rw-r--r--drivers/usb/host/xhci.c18
-rw-r--r--drivers/usb/host/xhci.h26
4 files changed, 215 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index fef5a1f9d483..5d963e350494 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -229,6 +229,13 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
229static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex, 229static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
230 u32 __iomem *addr, u32 port_status) 230 u32 __iomem *addr, u32 port_status)
231{ 231{
232 /* Don't allow the USB core to disable SuperSpeed ports. */
233 if (xhci->port_array[wIndex] == 0x03) {
234 xhci_dbg(xhci, "Ignoring request to disable "
235 "SuperSpeed port.\n");
236 return;
237 }
238
232 /* Write 1 to disable the port */ 239 /* Write 1 to disable the port */
233 xhci_writel(xhci, port_status | PORT_PE, addr); 240 xhci_writel(xhci, port_status | PORT_PE, addr);
234 port_status = xhci_readl(xhci, addr); 241 port_status = xhci_readl(xhci, addr);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d178761c3981..0fae58ef8afe 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1443,6 +1443,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
1443 xhci->dcbaa = NULL; 1443 xhci->dcbaa = NULL;
1444 1444
1445 scratchpad_free(xhci); 1445 scratchpad_free(xhci);
1446
1447 xhci->num_usb2_ports = 0;
1448 xhci->num_usb3_ports = 0;
1449 kfree(xhci->usb2_ports);
1450 kfree(xhci->usb3_ports);
1451 kfree(xhci->port_array);
1452
1446 xhci->page_size = 0; 1453 xhci->page_size = 0;
1447 xhci->page_shift = 0; 1454 xhci->page_shift = 0;
1448 xhci->bus_suspended = 0; 1455 xhci->bus_suspended = 0;
@@ -1627,6 +1634,161 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
1627 &xhci->ir_set->erst_dequeue); 1634 &xhci->ir_set->erst_dequeue);
1628} 1635}
1629 1636
1637static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
1638 u32 __iomem *addr, u8 major_revision)
1639{
1640 u32 temp, port_offset, port_count;
1641 int i;
1642
1643 if (major_revision > 0x03) {
1644 xhci_warn(xhci, "Ignoring unknown port speed, "
1645 "Ext Cap %p, revision = 0x%x\n",
1646 addr, major_revision);
1647 /* Ignoring port protocol we can't understand. FIXME */
1648 return;
1649 }
1650
1651 /* Port offset and count in the third dword, see section 7.2 */
1652 temp = xhci_readl(xhci, addr + 2);
1653 port_offset = XHCI_EXT_PORT_OFF(temp);
1654 port_count = XHCI_EXT_PORT_COUNT(temp);
1655 xhci_dbg(xhci, "Ext Cap %p, port offset = %u, "
1656 "count = %u, revision = 0x%x\n",
1657 addr, port_offset, port_count, major_revision);
1658 /* Port count includes the current port offset */
1659 if (port_offset == 0 || (port_offset + port_count - 1) > num_ports)
1660 /* WTF? "Valid values are ‘1’ to MaxPorts" */
1661 return;
1662 port_offset--;
1663 for (i = port_offset; i < (port_offset + port_count); i++) {
1664 /* Duplicate entry. Ignore the port if the revisions differ. */
1665 if (xhci->port_array[i] != 0) {
1666 xhci_warn(xhci, "Duplicate port entry, Ext Cap %p,"
1667 " port %u\n", addr, i);
1668 xhci_warn(xhci, "Port was marked as USB %u, "
1669 "duplicated as USB %u\n",
1670 xhci->port_array[i], major_revision);
1671 /* Only adjust the roothub port counts if we haven't
1672 * found a similar duplicate.
1673 */
1674 if (xhci->port_array[i] != major_revision &&
1675 xhci->port_array[i] != (u8) -1) {
1676 if (xhci->port_array[i] == 0x03)
1677 xhci->num_usb3_ports--;
1678 else
1679 xhci->num_usb2_ports--;
1680 xhci->port_array[i] = (u8) -1;
1681 }
1682 /* FIXME: Should we disable the port? */
1683 }
1684 xhci->port_array[i] = major_revision;
1685 if (major_revision == 0x03)
1686 xhci->num_usb3_ports++;
1687 else
1688 xhci->num_usb2_ports++;
1689 }
1690 /* FIXME: Should we disable ports not in the Extended Capabilities? */
1691}
1692
1693/*
1694 * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
1695 * specify what speeds each port is supposed to be. We can't count on the port
1696 * speed bits in the PORTSC register being correct until a device is connected,
1697 * but we need to set up the two fake roothubs with the correct number of USB
1698 * 3.0 and USB 2.0 ports at host controller initialization time.
1699 */
1700static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
1701{
1702 u32 __iomem *addr;
1703 u32 offset;
1704 unsigned int num_ports;
1705 int i, port_index;
1706
1707 addr = &xhci->cap_regs->hcc_params;
1708 offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
1709 if (offset == 0) {
1710 xhci_err(xhci, "No Extended Capability registers, "
1711 "unable to set up roothub.\n");
1712 return -ENODEV;
1713 }
1714
1715 num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
1716 xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags);
1717 if (!xhci->port_array)
1718 return -ENOMEM;
1719
1720 /*
1721 * For whatever reason, the first capability offset is from the
1722 * capability register base, not from the HCCPARAMS register.
1723 * See section 5.3.6 for offset calculation.
1724 */
1725 addr = &xhci->cap_regs->hc_capbase + offset;
1726 while (1) {
1727 u32 cap_id;
1728
1729 cap_id = xhci_readl(xhci, addr);
1730 if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL)
1731 xhci_add_in_port(xhci, num_ports, addr,
1732 (u8) XHCI_EXT_PORT_MAJOR(cap_id));
1733 offset = XHCI_EXT_CAPS_NEXT(cap_id);
1734 if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports)
1735 == num_ports)
1736 break;
1737 /*
1738 * Once you're into the Extended Capabilities, the offset is
1739 * always relative to the register holding the offset.
1740 */
1741 addr += offset;
1742 }
1743
1744 if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) {
1745 xhci_warn(xhci, "No ports on the roothubs?\n");
1746 return -ENODEV;
1747 }
1748 xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n",
1749 xhci->num_usb2_ports, xhci->num_usb3_ports);
1750 /*
1751 * Note we could have all USB 3.0 ports, or all USB 2.0 ports.
1752 * Not sure how the USB core will handle a hub with no ports...
1753 */
1754 if (xhci->num_usb2_ports) {
1755 xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)*
1756 xhci->num_usb2_ports, flags);
1757 if (!xhci->usb2_ports)
1758 return -ENOMEM;
1759
1760 port_index = 0;
1761 for (i = 0; i < num_ports; i++)
1762 if (xhci->port_array[i] != 0x03) {
1763 xhci->usb2_ports[port_index] =
1764 &xhci->op_regs->port_status_base +
1765 NUM_PORT_REGS*i;
1766 xhci_dbg(xhci, "USB 2.0 port at index %u, "
1767 "addr = %p\n", i,
1768 xhci->usb2_ports[port_index]);
1769 port_index++;
1770 }
1771 }
1772 if (xhci->num_usb3_ports) {
1773 xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)*
1774 xhci->num_usb3_ports, flags);
1775 if (!xhci->usb3_ports)
1776 return -ENOMEM;
1777
1778 port_index = 0;
1779 for (i = 0; i < num_ports; i++)
1780 if (xhci->port_array[i] == 0x03) {
1781 xhci->usb3_ports[port_index] =
1782 &xhci->op_regs->port_status_base +
1783 NUM_PORT_REGS*i;
1784 xhci_dbg(xhci, "USB 3.0 port at index %u, "
1785 "addr = %p\n", i,
1786 xhci->usb3_ports[port_index]);
1787 port_index++;
1788 }
1789 }
1790 return 0;
1791}
1630 1792
1631int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) 1793int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
1632{ 1794{
@@ -1809,6 +1971,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
1809 1971
1810 if (scratchpad_alloc(xhci, flags)) 1972 if (scratchpad_alloc(xhci, flags))
1811 goto fail; 1973 goto fail;
1974 if (xhci_setup_port_arrays(xhci, flags))
1975 goto fail;
1812 1976
1813 return 0; 1977 return 0;
1814 1978
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 06fca0835b52..45e4a3108cc3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1549,6 +1549,15 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
1549 cmd_completion = command->completion; 1549 cmd_completion = command->completion;
1550 cmd_status = &command->status; 1550 cmd_status = &command->status;
1551 command->command_trb = xhci->cmd_ring->enqueue; 1551 command->command_trb = xhci->cmd_ring->enqueue;
1552
1553 /* Enqueue pointer can be left pointing to the link TRB,
1554 * we must handle that
1555 */
1556 if ((command->command_trb->link.control & TRB_TYPE_BITMASK)
1557 == TRB_TYPE(TRB_LINK))
1558 command->command_trb =
1559 xhci->cmd_ring->enq_seg->next->trbs;
1560
1552 list_add_tail(&command->cmd_list, &virt_dev->cmd_list); 1561 list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
1553 } else { 1562 } else {
1554 in_ctx = virt_dev->in_ctx; 1563 in_ctx = virt_dev->in_ctx;
@@ -2272,6 +2281,15 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
2272 /* Attempt to submit the Reset Device command to the command ring */ 2281 /* Attempt to submit the Reset Device command to the command ring */
2273 spin_lock_irqsave(&xhci->lock, flags); 2282 spin_lock_irqsave(&xhci->lock, flags);
2274 reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; 2283 reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
2284
2285 /* Enqueue pointer can be left pointing to the link TRB,
2286 * we must handle that
2287 */
2288 if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK)
2289 == TRB_TYPE(TRB_LINK))
2290 reset_device_cmd->command_trb =
2291 xhci->cmd_ring->enq_seg->next->trbs;
2292
2275 list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); 2293 list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
2276 ret = xhci_queue_reset_device(xhci, slot_id); 2294 ret = xhci_queue_reset_device(xhci, slot_id);
2277 if (ret) { 2295 if (ret) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 85e65647d445..170c367112d2 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -454,6 +454,24 @@ struct xhci_doorbell_array {
454 454
455 455
456/** 456/**
457 * struct xhci_protocol_caps
458 * @revision: major revision, minor revision, capability ID,
459 * and next capability pointer.
460 * @name_string: Four ASCII characters to say which spec this xHC
461 * follows, typically "USB ".
462 * @port_info: Port offset, count, and protocol-defined information.
463 */
464struct xhci_protocol_caps {
465 u32 revision;
466 u32 name_string;
467 u32 port_info;
468};
469
470#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff)
471#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff)
472#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff)
473
474/**
457 * struct xhci_container_ctx 475 * struct xhci_container_ctx
458 * @type: Type of context. Used to calculated offsets to contained contexts. 476 * @type: Type of context. Used to calculated offsets to contained contexts.
459 * @size: Size of the context data 477 * @size: Size of the context data
@@ -1240,6 +1258,14 @@ struct xhci_hcd {
1240 u32 suspended_ports[8]; /* which ports are 1258 u32 suspended_ports[8]; /* which ports are
1241 suspended */ 1259 suspended */
1242 unsigned long resume_done[MAX_HC_PORTS]; 1260 unsigned long resume_done[MAX_HC_PORTS];
1261 /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
1262 u8 *port_array;
1263 /* Array of pointers to USB 3.0 PORTSC registers */
1264 u32 __iomem **usb3_ports;
1265 unsigned int num_usb3_ports;
1266 /* Array of pointers to USB 2.0 PORTSC registers */
1267 u32 __iomem **usb2_ports;
1268 unsigned int num_usb2_ports;
1243}; 1269};
1244 1270
1245/* For testing purposes */ 1271/* For testing purposes */