Browse Source

[xhci] Assume an invalid PSI table if any invalid PSI value is observed

Invalid protocol speed ID tables appear to be increasingly common in
the wild, to the point that it is infeasible to apply an explicit
XHCI_BAD_PSIV flag for each offending PCI device ID.

Fix by assuming an invalid PSI table as soon as any invalid value is
reported by the hardware.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 6 years ago
parent
commit
c900751fa6
1 changed files with 30 additions and 23 deletions
  1. 30
    23
      src/drivers/usb/xhci.c

+ 30
- 23
src/drivers/usb/xhci.c View File

@@ -801,34 +801,41 @@ static int xhci_port_speed ( struct xhci_device *xhci, unsigned int port,
801 801
 	ports = readl ( xhci->cap + supported + XHCI_SUPPORTED_PORTS );
802 802
 	psic = XHCI_SUPPORTED_PORTS_PSIC ( ports );
803 803
 
804
-	/* Use the default mappings if applicable */
805
-	if ( ( psic == 0 ) || ( xhci->quirks & XHCI_BAD_PSIV ) ) {
806
-		switch ( psiv ) {
807
-		case XHCI_SPEED_LOW :	return USB_SPEED_LOW;
808
-		case XHCI_SPEED_FULL :	return USB_SPEED_FULL;
809
-		case XHCI_SPEED_HIGH :	return USB_SPEED_HIGH;
810
-		case XHCI_SPEED_SUPER :	return USB_SPEED_SUPER;
811
-		default:
812
-			DBGC ( xhci, "XHCI %s-%d non-standard PSI value %d\n",
813
-			       xhci->name, port, psiv );
814
-			return -ENOTSUP;
804
+	/* Use protocol speed ID table unless device is known to be faulty */
805
+	if ( ! ( xhci->quirks & XHCI_BAD_PSIV ) ) {
806
+
807
+		/* Iterate over PSI dwords looking for a match */
808
+		for ( i = 0 ; i < psic ; i++ ) {
809
+			psi = readl ( xhci->cap + supported +
810
+				      XHCI_SUPPORTED_PSI ( i ) );
811
+			if ( psiv == XHCI_SUPPORTED_PSI_VALUE ( psi ) ) {
812
+				mantissa = XHCI_SUPPORTED_PSI_MANTISSA ( psi );
813
+				exponent = XHCI_SUPPORTED_PSI_EXPONENT ( psi );
814
+				speed = USB_SPEED ( mantissa, exponent );
815
+				return speed;
816
+			}
815 817
 		}
816
-	}
817 818
 
818
-	/* Iterate over PSI dwords looking for a match */
819
-	for ( i = 0 ; i < psic ; i++ ) {
820
-		psi = readl ( xhci->cap + supported + XHCI_SUPPORTED_PSI ( i ));
821
-		if ( psiv == XHCI_SUPPORTED_PSI_VALUE ( psi ) ) {
822
-			mantissa = XHCI_SUPPORTED_PSI_MANTISSA ( psi );
823
-			exponent = XHCI_SUPPORTED_PSI_EXPONENT ( psi );
824
-			speed = USB_SPEED ( mantissa, exponent );
825
-			return speed;
819
+		/* Record device as faulty if no match is found */
820
+		if ( psic != 0 ) {
821
+			DBGC ( xhci, "XHCI %s-%d spurious PSI value %d: "
822
+			       "assuming PSI table is invalid\n",
823
+			       xhci->name, port, psiv );
824
+			xhci->quirks |= XHCI_BAD_PSIV;
826 825
 		}
827 826
 	}
828 827
 
829
-	DBGC ( xhci, "XHCI %s-%d spurious PSI value %d\n",
830
-	       xhci->name, port, psiv );
831
-	return -ENOENT;
828
+	/* Use the default mappings */
829
+	switch ( psiv ) {
830
+	case XHCI_SPEED_LOW :	return USB_SPEED_LOW;
831
+	case XHCI_SPEED_FULL :	return USB_SPEED_FULL;
832
+	case XHCI_SPEED_HIGH :	return USB_SPEED_HIGH;
833
+	case XHCI_SPEED_SUPER :	return USB_SPEED_SUPER;
834
+	default:
835
+		DBGC ( xhci, "XHCI %s-%d unrecognised PSI value %d\n",
836
+		       xhci->name, port, psiv );
837
+		return -ENOTSUP;
838
+	}
832 839
 }
833 840
 
834 841
 /**

Loading…
Cancel
Save