Commit f8bbeabc34aa945ab4275abc9a4dfde0aea798ca
1 parent
cf7d7e5a19
Exists in
master
and in
39 other branches
xhci: Fix issue with port array setup and buggy hosts.
Fix two bugs with the port array setup. The first bug will only show up with broken xHCI hosts with Extended Capabilities registers that have duplicate port speed entries for the same port. The idea with the original code was to set the port_array entry to -1 if the duplicate port speed entry said the port was a different speed than the original port speed entry. That would mean that later, the port would not be exposed to the USB core. Unfortunately, I forgot a continue statement, and the port_array entry would just be overwritten in the next line. The second bug would happen if there are conflicting port speed registers (so that some entry in port_array is -1), or one of the hardware port registers was not described in the port speed registers (so that some entry in port_array is 0). The code that sets up the usb2_ports array would accidentally claim those ports. That wouldn't really cause any user-visible issues, but it is a bug. This patch should go into the stable trees that have the port array and USB 3.0 port disabling prevention patches. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@kernel.org
Showing 1 changed file with 15 additions and 10 deletions Side-by-side Diff
drivers/usb/host/xhci-mem.c
... | ... | @@ -1680,6 +1680,7 @@ |
1680 | 1680 | xhci->port_array[i] = (u8) -1; |
1681 | 1681 | } |
1682 | 1682 | /* FIXME: Should we disable the port? */ |
1683 | + continue; | |
1683 | 1684 | } |
1684 | 1685 | xhci->port_array[i] = major_revision; |
1685 | 1686 | if (major_revision == 0x03) |
... | ... | @@ -1758,16 +1759,20 @@ |
1758 | 1759 | return -ENOMEM; |
1759 | 1760 | |
1760 | 1761 | 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 | - } | |
1762 | + for (i = 0; i < num_ports; i++) { | |
1763 | + if (xhci->port_array[i] == 0x03 || | |
1764 | + xhci->port_array[i] == 0 || | |
1765 | + xhci->port_array[i] == -1) | |
1766 | + continue; | |
1767 | + | |
1768 | + xhci->usb2_ports[port_index] = | |
1769 | + &xhci->op_regs->port_status_base + | |
1770 | + NUM_PORT_REGS*i; | |
1771 | + xhci_dbg(xhci, "USB 2.0 port at index %u, " | |
1772 | + "addr = %p\n", i, | |
1773 | + xhci->usb2_ports[port_index]); | |
1774 | + port_index++; | |
1775 | + } | |
1771 | 1776 | } |
1772 | 1777 | if (xhci->num_usb3_ports) { |
1773 | 1778 | xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* |