|
@@ -2072,14 +2072,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
|
|
{
|
|
|
u32 temp, port_offset, port_count;
|
|
|
int i;
|
|
|
+ struct xhci_hub *rhub;
|
|
|
|
|
|
- if (major_revision > 0x03) {
|
|
|
+ temp = readl(addr);
|
|
|
+
|
|
|
+ if (XHCI_EXT_PORT_MAJOR(temp) == 0x03) {
|
|
|
+ rhub = &xhci->usb3_rhub;
|
|
|
+ } else if (XHCI_EXT_PORT_MAJOR(temp) <= 0x02) {
|
|
|
+ rhub = &xhci->usb2_rhub;
|
|
|
+ } else {
|
|
|
xhci_warn(xhci, "Ignoring unknown port speed, "
|
|
|
"Ext Cap %p, revision = 0x%x\n",
|
|
|
addr, major_revision);
|
|
|
/* Ignoring port protocol we can't understand. FIXME */
|
|
|
return;
|
|
|
}
|
|
|
+ rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
|
|
|
+ rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
|
|
|
|
|
|
/* Port offset and count in the third dword, see section 7.2 */
|
|
|
temp = readl(addr + 2);
|
|
@@ -2094,6 +2103,33 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
|
|
/* WTF? "Valid values are ‘1’ to MaxPorts" */
|
|
|
return;
|
|
|
|
|
|
+ rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
|
|
|
+ if (rhub->psi_count) {
|
|
|
+ rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!rhub->psi)
|
|
|
+ rhub->psi_count = 0;
|
|
|
+
|
|
|
+ rhub->psi_uid_count++;
|
|
|
+ for (i = 0; i < rhub->psi_count; i++) {
|
|
|
+ rhub->psi[i] = readl(addr + 4 + i);
|
|
|
+
|
|
|
+ /* count unique ID values, two consecutive entries can
|
|
|
+ * have the same ID if link is assymetric
|
|
|
+ */
|
|
|
+ if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
|
|
|
+ XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
|
|
|
+ rhub->psi_uid_count++;
|
|
|
+
|
|
|
+ xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
|
|
|
+ XHCI_EXT_PORT_PSIV(rhub->psi[i]),
|
|
|
+ XHCI_EXT_PORT_PSIE(rhub->psi[i]),
|
|
|
+ XHCI_EXT_PORT_PLT(rhub->psi[i]),
|
|
|
+ XHCI_EXT_PORT_PFD(rhub->psi[i]),
|
|
|
+ XHCI_EXT_PORT_LP(rhub->psi[i]),
|
|
|
+ XHCI_EXT_PORT_PSIM(rhub->psi[i]));
|
|
|
+ }
|
|
|
+ }
|
|
|
/* cache usb2 port capabilities */
|
|
|
if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
|
|
|
xhci->ext_caps[xhci->num_ext_caps++] = temp;
|