Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI, PCI, irq: Do not share PCI IRQ with ISA IRQ

Avoid IRQs occupied by ISA IRQs when allocating IRQs for PCI link devices,
otherwise it may cause interrupt storm due to incompatible pin attributes.

This issue was triggered on a KVM virtual machine, which
1) uses IRQ9 for SCI in high level mode.
2) defines an PCI interrupt link device (LNKS) with IRQ9 as the only
possible irq.
3) has an PCI device referring to link device LNKS.
So it causes interrupt storm when enabling the PCI device because PCI IRQ
works in low level mode.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jiang Liu and committed by
Rafael J. Wysocki
5ebc7603 1f93e4a9

+15
+1
drivers/acpi/pci_irq.c
··· 372 372 373 373 /* Interrupt Line values above 0xF are forbidden */ 374 374 if (dev->irq > 0 && (dev->irq <= 0xF) && 375 + acpi_isa_irq_available(dev->irq) && 375 376 (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { 376 377 dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n", 377 378 pin_name(dev->pin), dev->irq);
+13
drivers/acpi/pci_link.c
··· 553 553 irq = link->irq.possible[i]; 554 554 } 555 555 } 556 + if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { 557 + printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " 558 + "Try pci=noacpi or acpi=off\n", 559 + acpi_device_name(link->device), 560 + acpi_device_bid(link->device)); 561 + return -ENODEV; 562 + } 556 563 557 564 /* Attempt to enable the link device at this IRQ. */ 558 565 if (acpi_pci_link_set(link, irq)) { ··· 826 819 else 827 820 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; 828 821 } 822 + } 823 + 824 + bool acpi_isa_irq_available(int irq) 825 + { 826 + return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || 827 + acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); 829 828 } 830 829 831 830 /*
+1
include/linux/acpi.h
··· 217 217 218 218 int acpi_pci_irq_enable (struct pci_dev *dev); 219 219 void acpi_penalize_isa_irq(int irq, int active); 220 + bool acpi_isa_irq_available(int irq); 220 221 void acpi_penalize_sci_irq(int irq, int trigger, int polarity); 221 222 void acpi_pci_irq_disable (struct pci_dev *dev); 222 223