diff options
author | Michael Brown | 2018-04-18 17:38:36 +0200 |
---|---|---|
committer | Michael Brown | 2018-04-18 17:57:05 +0200 |
commit | d6f02c72c984aaeab11741d54f9d9e81d9ce79f2 (patch) | |
tree | 0aa45654ea788d5c82e1c32ad4fc0ed088e5dec6 /src | |
parent | [intelx] Add PCI_ROM entry for Intel X553 NIC (diff) | |
download | ipxe-d6f02c72c984aaeab11741d54f9d9e81d9ce79f2.tar.gz ipxe-d6f02c72c984aaeab11741d54f9d9e81d9ce79f2.tar.xz ipxe-d6f02c72c984aaeab11741d54f9d9e81d9ce79f2.zip |
[undi] Include subsystem IDs in broken interrupt device check
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/x86/drivers/net/undinet.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/arch/x86/drivers/net/undinet.c b/src/arch/x86/drivers/net/undinet.c index e8ec772e..9b7d6d84 100644 --- a/src/arch/x86/drivers/net/undinet.c +++ b/src/arch/x86/drivers/net/undinet.c @@ -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; } } |