|
@@ -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 )
|