Browse Source

[undi] Work around specific devices with known broken interrupt behaviour

Some PXE stacks are known to claim that IRQs are supported, but then
never generate interrupts.  No satisfactory solution has been found to
this problem; the workaround is to add the PCI vendor and device IDs
to a list of devices which will be treated as simply not supporting
interrupts.

This is something of a hack, since it will generate false positives
for identical devices with a working PXE stack (e.g. those that have
been reflashed with iPXE), but it's an improvement on the current
situation.

Reported-by: Richard Moore <rich@richud.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
9373ca8ea2
1 changed files with 52 additions and 0 deletions
  1. 52
    0
      src/arch/i386/drivers/net/undinet.c

+ 52
- 0
src/arch/i386/drivers/net/undinet.c View File

@@ -531,6 +531,53 @@ static struct net_device_operations undinet_operations = {
531 531
 	.irq   		= undinet_irq,
532 532
 };
533 533
 
534
+/** A device with broken support for generating interrupts */
535
+struct undinet_irq_broken {
536
+	/** PCI vendor ID */
537
+	uint16_t pci_vendor;
538
+	/** PCI device ID */
539
+	uint16_t pci_device;
540
+};
541
+
542
+/**
543
+ * List of devices with broken support for generating interrupts
544
+ *
545
+ * Some PXE stacks are known to claim that IRQs are supported, but
546
+ * then never generate interrupts.  No satisfactory solution has been
547
+ * found to this problem; the workaround is to add the PCI vendor and
548
+ * device IDs to this list.  This is something of a hack, since it
549
+ * will generate false positives for identical devices with a working
550
+ * PXE stack (e.g. those that have been reflashed with iPXE), but it's
551
+ * an improvement on the current situation.
552
+ */
553
+static const struct undinet_irq_broken undinet_irq_broken_list[] = {
554
+	/* HP XX70x laptops */
555
+	{ .pci_vendor = 0x8086, .pci_device = 0x1502 },
556
+	{ .pci_vendor = 0x8086, .pci_device = 0x1503 },
557
+};
558
+
559
+/**
560
+ * Check for devices with broken support for generating interrupts
561
+ *
562
+ * @v undi		UNDI device
563
+ * @ret irq_is_broken	Interrupt support is broken; no interrupts are generated
564
+ */
565
+static int undinet_irq_is_broken ( struct undi_device *undi ) {
566
+	const struct undinet_irq_broken *broken;
567
+	unsigned int i;
568
+
569
+	for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
570
+			    sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
571
+		broken = &undinet_irq_broken_list[i];
572
+		if ( ( undi->dev.desc.bus_type == BUS_TYPE_PCI ) &&
573
+		     ( undi->dev.desc.vendor == broken->pci_vendor ) &&
574
+		     ( undi->dev.desc.device == broken->pci_device ) ) {
575
+			return 1;
576
+		}
577
+	}
578
+	return 0;
579
+}
580
+
534 581
 /**
535 582
  * Probe UNDI device
536 583
  *
@@ -647,6 +694,11 @@ int undinet_probe ( struct undi_device *undi ) {
647 694
 		       undinic );
648 695
 		undinic->hacks |= UNDI_HACK_EB54;
649 696
 	}
697
+	if ( undinet_irq_is_broken ( undi ) ) {
698
+		DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
699
+		       "broken interrupts\n", undinic );
700
+		undinic->irq_supported = 0;
701
+	}
650 702
 
651 703
 	/* Register network device */
652 704
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )

Loading…
Cancel
Save