aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2015-09-17 02:02:45 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-25 19:53:07 -0400
commit5ebc76035303016ec41bb752bec156ea9fde7c34 (patch)
tree50b32017fe7f9771a1fa2a97cba4ec64b34b046c
parent1f93e4a96c9109378204c147b3eec0d0e8100fde (diff)
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>
-rw-r--r--drivers/acpi/pci_irq.c1
-rw-r--r--drivers/acpi/pci_link.c13
-rw-r--r--include/linux/acpi.h1
3 files changed, 15 insertions, 0 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 6da0f9beab19..c9336751e5e3 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -372,6 +372,7 @@ static int acpi_isa_register_gsi(struct pci_dev *dev)
372 372
373 /* Interrupt Line values above 0xF are forbidden */ 373 /* Interrupt Line values above 0xF are forbidden */
374 if (dev->irq > 0 && (dev->irq <= 0xF) && 374 if (dev->irq > 0 && (dev->irq <= 0xF) &&
375 acpi_isa_irq_available(dev->irq) &&
375 (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { 376 (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
376 dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n", 377 dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
377 pin_name(dev->pin), dev->irq); 378 pin_name(dev->pin), dev->irq);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 3b4ea98e3ea0..246e50d22120 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -553,6 +553,13 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
553 irq = link->irq.possible[i]; 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 /* Attempt to enable the link device at this IRQ. */ 564 /* Attempt to enable the link device at this IRQ. */
558 if (acpi_pci_link_set(link, irq)) { 565 if (acpi_pci_link_set(link, irq)) {
@@ -821,6 +828,12 @@ void acpi_penalize_isa_irq(int irq, int active)
821 } 828 }
822} 829}
823 830
831bool acpi_isa_irq_available(int irq)
832{
833 return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
834 acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
835}
836
824/* 837/*
825 * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with 838 * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
826 * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for 839 * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7235c4851460..43856d19cf4d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -217,6 +217,7 @@ struct pci_dev;
217 217
218int acpi_pci_irq_enable (struct pci_dev *dev); 218int acpi_pci_irq_enable (struct pci_dev *dev);
219void acpi_penalize_isa_irq(int irq, int active); 219void acpi_penalize_isa_irq(int irq, int active);
220bool acpi_isa_irq_available(int irq);
220void acpi_penalize_sci_irq(int irq, int trigger, int polarity); 221void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
221void acpi_pci_irq_disable (struct pci_dev *dev); 222void acpi_pci_irq_disable (struct pci_dev *dev);
222 223