aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c164
1 files changed, 164 insertions, 0 deletions
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