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.c173
1 files changed, 171 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4e51343ddffc..6627a956fa8e 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1043,7 +1043,7 @@ static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
1043 if (udev->speed == USB_SPEED_SUPER) 1043 if (udev->speed == USB_SPEED_SUPER)
1044 return ep->ss_ep_comp.wBytesPerInterval; 1044 return ep->ss_ep_comp.wBytesPerInterval;
1045 1045
1046 max_packet = ep->desc.wMaxPacketSize & 0x3ff; 1046 max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
1047 max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; 1047 max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
1048 /* A 0 in max burst means 1 transfer per ESIT */ 1048 /* A 0 in max burst means 1 transfer per ESIT */
1049 return max_packet * (max_burst + 1); 1049 return max_packet * (max_burst + 1);
@@ -1133,7 +1133,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
1133 /* Fall through */ 1133 /* Fall through */
1134 case USB_SPEED_FULL: 1134 case USB_SPEED_FULL:
1135 case USB_SPEED_LOW: 1135 case USB_SPEED_LOW:
1136 max_packet = ep->desc.wMaxPacketSize & 0x3ff; 1136 max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
1137 ep_ctx->ep_info2 |= MAX_PACKET(max_packet); 1137 ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
1138 break; 1138 break;
1139 default: 1139 default:
@@ -1441,6 +1441,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
1441 xhci->dcbaa = NULL; 1441 xhci->dcbaa = NULL;
1442 1442
1443 scratchpad_free(xhci); 1443 scratchpad_free(xhci);
1444
1445 xhci->num_usb2_ports = 0;
1446 xhci->num_usb3_ports = 0;
1447 kfree(xhci->usb2_ports);
1448 kfree(xhci->usb3_ports);
1449 kfree(xhci->port_array);
1450
1444 xhci->page_size = 0; 1451 xhci->page_size = 0;
1445 xhci->page_shift = 0; 1452 xhci->page_shift = 0;
1446} 1453}
@@ -1624,6 +1631,166 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
1624 &xhci->ir_set->erst_dequeue); 1631 &xhci->ir_set->erst_dequeue);
1625} 1632}
1626 1633
1634static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
1635 u32 __iomem *addr, u8 major_revision)
1636{
1637 u32 temp, port_offset, port_count;
1638 int i;
1639
1640 if (major_revision > 0x03) {
1641 xhci_warn(xhci, "Ignoring unknown port speed, "
1642 "Ext Cap %p, revision = 0x%x\n",
1643 addr, major_revision);
1644 /* Ignoring port protocol we can't understand. FIXME */
1645 return;
1646 }
1647
1648 /* Port offset and count in the third dword, see section 7.2 */
1649 temp = xhci_readl(xhci, addr + 2);
1650 port_offset = XHCI_EXT_PORT_OFF(temp);
1651 port_count = XHCI_EXT_PORT_COUNT(temp);
1652 xhci_dbg(xhci, "Ext Cap %p, port offset = %u, "
1653 "count = %u, revision = 0x%x\n",
1654 addr, port_offset, port_count, major_revision);
1655 /* Port count includes the current port offset */
1656 if (port_offset == 0 || (port_offset + port_count - 1) > num_ports)
1657 /* WTF? "Valid values are ‘1’ to MaxPorts" */
1658 return;
1659 port_offset--;
1660 for (i = port_offset; i < (port_offset + port_count); i++) {
1661 /* Duplicate entry. Ignore the port if the revisions differ. */
1662 if (xhci->port_array[i] != 0) {
1663 xhci_warn(xhci, "Duplicate port entry, Ext Cap %p,"
1664 " port %u\n", addr, i);
1665 xhci_warn(xhci, "Port was marked as USB %u, "
1666 "duplicated as USB %u\n",
1667 xhci->port_array[i], major_revision);
1668 /* Only adjust the roothub port counts if we haven't
1669 * found a similar duplicate.
1670 */
1671 if (xhci->port_array[i] != major_revision &&
1672 xhci->port_array[i] != (u8) -1) {
1673 if (xhci->port_array[i] == 0x03)
1674 xhci->num_usb3_ports--;
1675 else
1676 xhci->num_usb2_ports--;
1677 xhci->port_array[i] = (u8) -1;
1678 }
1679 /* FIXME: Should we disable the port? */
1680 continue;
1681 }
1682 xhci->port_array[i] = major_revision;
1683 if (major_revision == 0x03)
1684 xhci->num_usb3_ports++;
1685 else
1686 xhci->num_usb2_ports++;
1687 }
1688 /* FIXME: Should we disable ports not in the Extended Capabilities? */
1689}
1690
1691/*
1692 * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
1693 * specify what speeds each port is supposed to be. We can't count on the port
1694 * speed bits in the PORTSC register being correct until a device is connected,
1695 * but we need to set up the two fake roothubs with the correct number of USB
1696 * 3.0 and USB 2.0 ports at host controller initialization time.
1697 */
1698static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
1699{
1700 u32 __iomem *addr;
1701 u32 offset;
1702 unsigned int num_ports;
1703 int i, port_index;
1704
1705 addr = &xhci->cap_regs->hcc_params;
1706 offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
1707 if (offset == 0) {
1708 xhci_err(xhci, "No Extended Capability registers, "
1709 "unable to set up roothub.\n");
1710 return -ENODEV;
1711 }
1712
1713 num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
1714 xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags);
1715 if (!xhci->port_array)
1716 return -ENOMEM;
1717
1718 /*
1719 * For whatever reason, the first capability offset is from the
1720 * capability register base, not from the HCCPARAMS register.
1721 * See section 5.3.6 for offset calculation.
1722 */
1723 addr = &xhci->cap_regs->hc_capbase + offset;
1724 while (1) {
1725 u32 cap_id;
1726
1727 cap_id = xhci_readl(xhci, addr);
1728 if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL)
1729 xhci_add_in_port(xhci, num_ports, addr,
1730 (u8) XHCI_EXT_PORT_MAJOR(cap_id));
1731 offset = XHCI_EXT_CAPS_NEXT(cap_id);
1732 if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports)
1733 == num_ports)
1734 break;
1735 /*
1736 * Once you're into the Extended Capabilities, the offset is
1737 * always relative to the register holding the offset.
1738 */
1739 addr += offset;
1740 }
1741
1742 if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) {
1743 xhci_warn(xhci, "No ports on the roothubs?\n");
1744 return -ENODEV;
1745 }
1746 xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n",
1747 xhci->num_usb2_ports, xhci->num_usb3_ports);
1748 /*
1749 * Note we could have all USB 3.0 ports, or all USB 2.0 ports.
1750 * Not sure how the USB core will handle a hub with no ports...
1751 */
1752 if (xhci->num_usb2_ports) {
1753 xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)*
1754 xhci->num_usb2_ports, flags);
1755 if (!xhci->usb2_ports)
1756 return -ENOMEM;
1757
1758 port_index = 0;
1759 for (i = 0; i < num_ports; i++) {
1760 if (xhci->port_array[i] == 0x03 ||
1761 xhci->port_array[i] == 0 ||
1762 xhci->port_array[i] == -1)
1763 continue;
1764
1765 xhci->usb2_ports[port_index] =
1766 &xhci->op_regs->port_status_base +
1767 NUM_PORT_REGS*i;
1768 xhci_dbg(xhci, "USB 2.0 port at index %u, "
1769 "addr = %p\n", i,
1770 xhci->usb2_ports[port_index]);
1771 port_index++;
1772 }
1773 }
1774 if (xhci->num_usb3_ports) {
1775 xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)*
1776 xhci->num_usb3_ports, flags);
1777 if (!xhci->usb3_ports)
1778 return -ENOMEM;
1779
1780 port_index = 0;
1781 for (i = 0; i < num_ports; i++)
1782 if (xhci->port_array[i] == 0x03) {
1783 xhci->usb3_ports[port_index] =
1784 &xhci->op_regs->port_status_base +
1785 NUM_PORT_REGS*i;
1786 xhci_dbg(xhci, "USB 3.0 port at index %u, "
1787 "addr = %p\n", i,
1788 xhci->usb3_ports[port_index]);
1789 port_index++;
1790 }
1791 }
1792 return 0;
1793}
1627 1794
1628int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) 1795int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
1629{ 1796{
@@ -1804,6 +1971,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
1804 1971
1805 if (scratchpad_alloc(xhci, flags)) 1972 if (scratchpad_alloc(xhci, flags))
1806 goto fail; 1973 goto fail;
1974 if (xhci_setup_port_arrays(xhci, flags))
1975 goto fail;
1807 1976
1808 return 0; 1977 return 0;
1809 1978