Pārlūkot izejas kodu

[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 gadus atpakaļ
vecāks
revīzija
c900751fa6
1 mainītis faili ar 30 papildinājumiem un 23 dzēšanām
  1. 30
    23
      src/drivers/usb/xhci.c

+ 30
- 23
src/drivers/usb/xhci.c Parādīt failu

@@ -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
 /**

Notiek ielāde…
Atcelt
Saglabāt