]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[undi] Include subsystem IDs in broken interrupt device check
authorMichael Brown <mcb30@ipxe.org>
Wed, 18 Apr 2018 15:38:36 +0000 (16:38 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 18 Apr 2018 15:57:05 +0000 (16:57 +0100)
Allow the subsystem IDs to be used when checking for PXE stacks with
broken interrupt support.

Suggested-by: Levi Hsieh <Levi.Hsieh@dell.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/drivers/net/undinet.c

index e8ec772ef3752871f0bad43a49498d5044924e2c..9b7d6d8492707efbd81a078dfe985771cbc16358 100644 (file)
@@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/netdevice.h>
 #include <ipxe/if_ether.h>
 #include <ipxe/ethernet.h>
+#include <ipxe/pci.h>
 #include <ipxe/profile.h>
 #include <undi.h>
 #include <undinet.h>
@@ -807,6 +808,10 @@ struct undinet_irq_broken {
        uint16_t pci_vendor;
        /** PCI device ID */
        uint16_t pci_device;
+       /** PCI subsystem vendor ID */
+       uint16_t pci_subsys_vendor;
+       /** PCI subsystem ID */
+       uint16_t pci_subsys;
 };
 
 /**
@@ -822,10 +827,10 @@ struct undinet_irq_broken {
  */
 static const struct undinet_irq_broken undinet_irq_broken_list[] = {
        /* HP XX70x laptops */
-       { .pci_vendor = 0x8086, .pci_device = 0x1502 },
-       { .pci_vendor = 0x8086, .pci_device = 0x1503 },
+       { 0x8086, 0x1502, PCI_ANY_ID, PCI_ANY_ID },
+       { 0x8086, 0x1503, PCI_ANY_ID, PCI_ANY_ID },
        /* HP 745 G3 laptop */
-       { .pci_vendor = 0x14e4, .pci_device = 0x1687 },
+       { 0x14e4, 0x1687, PCI_ANY_ID, PCI_ANY_ID },
 };
 
 /**
@@ -836,14 +841,30 @@ static const struct undinet_irq_broken undinet_irq_broken_list[] = {
  */
 static int undinet_irq_is_broken ( struct device_description *desc ) {
        const struct undinet_irq_broken *broken;
+       struct pci_device pci;
+       uint16_t subsys_vendor;
+       uint16_t subsys;
        unsigned int i;
 
+       /* Ignore non-PCI devices */
+       if ( desc->bus_type != BUS_TYPE_PCI )
+               return 0;
+
+       /* Read subsystem IDs */
+       pci_init ( &pci, desc->location );
+       pci_read_config_word ( &pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor );
+       pci_read_config_word ( &pci, PCI_SUBSYSTEM_ID, &subsys );
+
+       /* Check for a match against the broken device list */
        for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
                            sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
                broken = &undinet_irq_broken_list[i];
-               if ( ( desc->bus_type == BUS_TYPE_PCI ) &&
-                    ( desc->vendor == broken->pci_vendor ) &&
-                    ( desc->device == broken->pci_device ) ) {
+               if ( ( broken->pci_vendor == desc->vendor ) &&
+                    ( broken->pci_device == desc->device ) &&
+                    ( ( broken->pci_subsys_vendor == subsys_vendor ) ||
+                      ( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
+                    ( ( broken->pci_subsys == subsys ) ||
+                      ( broken->pci_subsys == PCI_ANY_ID ) ) ) {
                        return 1;
                }
        }