Skip to content

Commit

Permalink
ACPI, PCI, irq: Do not share PCI IRQ with ISA IRQ
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jiang Liu authored and Rafael J. Wysocki committed Sep 25, 2015
1 parent 1f93e4a commit 5ebc760
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/acpi/pci_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ static int acpi_isa_register_gsi(struct pci_dev *dev)

/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF) &&
acpi_isa_irq_available(dev->irq) &&
(acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
pin_name(dev->pin), dev->irq);
Expand Down
13 changes: 13 additions & 0 deletions drivers/acpi/pci_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,13 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
irq = link->irq.possible[i];
}
}
if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
"Try pci=noacpi or acpi=off\n",
acpi_device_name(link->device),
acpi_device_bid(link->device));
return -ENODEV;
}

/* Attempt to enable the link device at this IRQ. */
if (acpi_pci_link_set(link, irq)) {
Expand Down Expand Up @@ -821,6 +828,12 @@ void acpi_penalize_isa_irq(int irq, int active)
}
}

bool acpi_isa_irq_available(int irq)
{
return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
}

/*
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
* PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
Expand Down
1 change: 1 addition & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ struct pci_dev;

int acpi_pci_irq_enable (struct pci_dev *dev);
void acpi_penalize_isa_irq(int irq, int active);
bool acpi_isa_irq_available(int irq);
void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
void acpi_pci_irq_disable (struct pci_dev *dev);

Expand Down

0 comments on commit 5ebc760

Please sign in to comment.