Browse Source

[xhci] Ignore invalid protocol speed ID values on Intel Skylake platforms

Some Intel Skylake platforms (observed on a prototype Lenovo ThinkPad)
report the list of available USB3 protocol speed ID values as {1,2,3}
but then report a port's speed using ID value 4.

The value 4 happens to be the default value for SuperSpeed (when no
protocol speed ID value list is explicitly defined), and the hardware
seems to function correctly if we simply ignore its protocol speed ID
table and assume that it uses the default values.

Fix by adding a "broken PSI values" quirk for this controller.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
be3517c4ab
2 changed files with 9 additions and 3 deletions
  1. 6
    3
      src/drivers/usb/xhci.c
  2. 3
    0
      src/drivers/usb/xhci.h

+ 6
- 3
src/drivers/usb/xhci.c View File

@@ -743,6 +743,8 @@ static unsigned int xhci_port_protocol ( struct xhci_device *xhci,
743 743
 					xhci_speed_name ( psi ) );
744 744
 			}
745 745
 		}
746
+		if ( xhci->quirks & XHCI_BAD_PSIV )
747
+			DBGC2 ( xhci, " (ignored)" );
746 748
 		DBGC2 ( xhci, "\n" );
747 749
 	}
748 750
 
@@ -800,7 +802,7 @@ static int xhci_port_speed ( struct xhci_device *xhci, unsigned int port,
800 802
 	psic = XHCI_SUPPORTED_PORTS_PSIC ( ports );
801 803
 
802 804
 	/* Use the default mappings if applicable */
803
-	if ( ! psic ) {
805
+	if ( ( psic == 0 ) || ( xhci->quirks & XHCI_BAD_PSIV ) ) {
804 806
 		switch ( psiv ) {
805 807
 		case XHCI_SPEED_LOW :	return USB_SPEED_LOW;
806 808
 		case XHCI_SPEED_FULL :	return USB_SPEED_FULL;
@@ -857,14 +859,14 @@ static int xhci_port_psiv ( struct xhci_device *xhci, unsigned int port,
857 859
 	psic = XHCI_SUPPORTED_PORTS_PSIC ( ports );
858 860
 
859 861
 	/* Use the default mappings if applicable */
860
-	if ( ! psic ) {
862
+	if ( ( psic == 0 ) || ( xhci->quirks & XHCI_BAD_PSIV ) ) {
861 863
 		switch ( speed ) {
862 864
 		case USB_SPEED_LOW :	return XHCI_SPEED_LOW;
863 865
 		case USB_SPEED_FULL :	return XHCI_SPEED_FULL;
864 866
 		case USB_SPEED_HIGH :	return XHCI_SPEED_HIGH;
865 867
 		case USB_SPEED_SUPER :	return XHCI_SPEED_SUPER;
866 868
 		default:
867
-			DBGC ( xhci, "XHCI %s-%d non-standad speed %d\n",
869
+			DBGC ( xhci, "XHCI %s-%d non-standard speed %d\n",
868 870
 			       xhci->name, port, speed );
869 871
 			return -ENOTSUP;
870 872
 		}
@@ -3286,6 +3288,7 @@ static void xhci_remove ( struct pci_device *pci ) {
3286 3288
 
3287 3289
 /** XHCI PCI device IDs */
3288 3290
 static struct pci_device_id xhci_ids[] = {
3291
+	PCI_ROM ( 0x8086, 0x9d2f, "xhci-skylake", "xHCI (Skylake)", ( XHCI_PCH | XHCI_BAD_PSIV ) ),
3289 3292
 	PCI_ROM ( 0x8086, 0xffff, "xhci-pch", "xHCI (Intel PCH)", XHCI_PCH ),
3290 3293
 	PCI_ROM ( 0xffff, 0xffff, "xhci", "xHCI", 0 ),
3291 3294
 };

+ 3
- 0
src/drivers/usb/xhci.h View File

@@ -1032,6 +1032,9 @@ struct xhci_pch {
1032 1032
 /** Intel PCH USB3 port routing mask register */
1033 1033
 #define XHCI_PCH_USB3PRM 0xdc
1034 1034
 
1035
+/** Invalid protocol speed ID values quirk */
1036
+#define XHCI_BAD_PSIV 0x0002
1037
+
1035 1038
 /** An xHCI device */
1036 1039
 struct xhci_device {
1037 1040
 	/** Registers */

Loading…
Cancel
Save