summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2018-04-18 17:38:36 +0200
committerMichael Brown2018-04-18 17:57:05 +0200
commitd6f02c72c984aaeab11741d54f9d9e81d9ce79f2 (patch)
tree0aa45654ea788d5c82e1c32ad4fc0ed088e5dec6
parent[intelx] Add PCI_ROM entry for Intel X553 NIC (diff)
downloadipxe-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>
-rw-r--r--src/arch/x86/drivers/net/undinet.c33
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;
}
}