]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[xhci] Ignore invalid protocol speed ID values on Intel Skylake platforms
authorMichael Brown <mcb30@ipxe.org>
Thu, 18 Jun 2015 14:09:57 +0000 (15:09 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 18 Jun 2015 14:09:57 +0000 (15:09 +0100)
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>
src/drivers/usb/xhci.c
src/drivers/usb/xhci.h

index 4f506dbc275e7fbc58dc69db7e84e2d939f1c3ea..49e67316ba8f31917a1a7bd94e86db3df18727f1 100644 (file)
@@ -743,6 +743,8 @@ static unsigned int xhci_port_protocol ( struct xhci_device *xhci,
                                        xhci_speed_name ( psi ) );
                        }
                }
+               if ( xhci->quirks & XHCI_BAD_PSIV )
+                       DBGC2 ( xhci, " (ignored)" );
                DBGC2 ( xhci, "\n" );
        }
 
@@ -800,7 +802,7 @@ static int xhci_port_speed ( struct xhci_device *xhci, unsigned int port,
        psic = XHCI_SUPPORTED_PORTS_PSIC ( ports );
 
        /* Use the default mappings if applicable */
-       if ( ! psic ) {
+       if ( ( psic == 0 ) || ( xhci->quirks & XHCI_BAD_PSIV ) ) {
                switch ( psiv ) {
                case XHCI_SPEED_LOW :   return USB_SPEED_LOW;
                case XHCI_SPEED_FULL :  return USB_SPEED_FULL;
@@ -857,14 +859,14 @@ static int xhci_port_psiv ( struct xhci_device *xhci, unsigned int port,
        psic = XHCI_SUPPORTED_PORTS_PSIC ( ports );
 
        /* Use the default mappings if applicable */
-       if ( ! psic ) {
+       if ( ( psic == 0 ) || ( xhci->quirks & XHCI_BAD_PSIV ) ) {
                switch ( speed ) {
                case USB_SPEED_LOW :    return XHCI_SPEED_LOW;
                case USB_SPEED_FULL :   return XHCI_SPEED_FULL;
                case USB_SPEED_HIGH :   return XHCI_SPEED_HIGH;
                case USB_SPEED_SUPER :  return XHCI_SPEED_SUPER;
                default:
-                       DBGC ( xhci, "XHCI %s-%d non-standad speed %d\n",
+                       DBGC ( xhci, "XHCI %s-%d non-standard speed %d\n",
                               xhci->name, port, speed );
                        return -ENOTSUP;
                }
@@ -3286,6 +3288,7 @@ static void xhci_remove ( struct pci_device *pci ) {
 
 /** XHCI PCI device IDs */
 static struct pci_device_id xhci_ids[] = {
+       PCI_ROM ( 0x8086, 0x9d2f, "xhci-skylake", "xHCI (Skylake)", ( XHCI_PCH | XHCI_BAD_PSIV ) ),
        PCI_ROM ( 0x8086, 0xffff, "xhci-pch", "xHCI (Intel PCH)", XHCI_PCH ),
        PCI_ROM ( 0xffff, 0xffff, "xhci", "xHCI", 0 ),
 };
index e35ef514e2ff05a126ae43ff807e4ced61a5221c..83bf71e7e37791d2f347e90ab7c31427ce3adb65 100644 (file)
@@ -1032,6 +1032,9 @@ struct xhci_pch {
 /** Intel PCH USB3 port routing mask register */
 #define XHCI_PCH_USB3PRM 0xdc
 
+/** Invalid protocol speed ID values quirk */
+#define XHCI_BAD_PSIV 0x0002
+
 /** An xHCI device */
 struct xhci_device {
        /** Registers */