summaryrefslogtreecommitdiffstats
path: root/src/drivers/usb
diff options
context:
space:
mode:
authorMichael Brown2015-06-18 16:09:57 +0200
committerMichael Brown2015-06-18 16:09:57 +0200
commitbe3517c4ab4af8de973014e7e371a1c54dce8abf (patch)
tree0a956653685ebb3048b54be0aec69da94089f087 /src/drivers/usb
parent[xhci] Record device-specific quirks in xHCI device structure (diff)
downloadipxe-be3517c4ab4af8de973014e7e371a1c54dce8abf.tar.gz
ipxe-be3517c4ab4af8de973014e7e371a1c54dce8abf.tar.xz
ipxe-be3517c4ab4af8de973014e7e371a1c54dce8abf.zip
[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>
Diffstat (limited to 'src/drivers/usb')
-rw-r--r--src/drivers/usb/xhci.c9
-rw-r--r--src/drivers/usb/xhci.h3
2 files changed, 9 insertions, 3 deletions
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index 4f506dbc..49e67316 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -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 ),
};
diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h
index e35ef514..83bf71e7 100644
--- a/src/drivers/usb/xhci.h
+++ b/src/drivers/usb/xhci.h
@@ -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 */