Skip to contentSkip to conversation

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

PATCH In review Jiang Liu 3 participants 5 messages Sep 17, 2015 – Sep 28, 2015

Subsystems (2)
lore
Share & tools
lore

Jiang Liu

author
#0 lore raw

PATCH 1/2 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.

---
 drivers/acpi/pci_irq.c  |    1 +
 drivers/acpi/pci_link.c |   13 +++++++++++++
 include/linux/acpi.h    |    1 +
 3 files changed, 15 insertions(+)
drivers/acpi/pci_irq.c +1 -0
index 6da0f9beab19..c9336751e5e3 100644
@@ -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);
drivers/acpi/pci_link.c +13 -0
index 3b4ea98e3ea0..246e50d22120 100644
@@ -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)) {
@@ -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
include/linux/acpi.h +1 -0
index 7235c4851460..43856d19cf4d 100644
@@ -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);
 
Signature · 1 line
1.7.10.4
author
#1 lore raw

PATCH 2/2 ACPI / PCI: Remove duplicated penalty on SCI IRQ

Now we have dedicated interface acpi_penalize_sci_irq() to penalize ISA IRQ used by ACPI SCI, so remove duplicated code to penalize ACPI SCI in acpi_irq_penalty_init().

---
 drivers/acpi/pci_link.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/acpi/pci_link.c +1 -2
index 246e50d22120..7c8408b946ca 100644
@@ -498,8 +498,7 @@ int __init acpi_irq_penalty_init(void)
 			    PIRQ_PENALTY_PCI_POSSIBLE;
 		}
 	}
-	/* Add a penalty for the SCI */
-	acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING;
+
 	return 0;
 }
 
Signature · 1 line
1.7.10.4
Acked-by on v1 2/2
#2 lore raw

Re: [Bugfix 2/2] ACPI / PCI: Remove duplicated penalty on SCI IRQ

Quoted 5 lines · Jiang Liu

Now we have dedicated interface acpi_penalize_sci_irq() to penalize ISA IRQ used by ACPI SCI, so remove duplicated code to penalize ACPI SCI in acpi_irq_penalty_init().

Quoted 26 lines
---
 drivers/acpi/pci_link.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/acpi/pci_link.c +1 -2
index 246e50d22120..7c8408b946ca 100644
@@ -498,8 +498,7 @@ int __init acpi_irq_penalty_init(void)
 			    PIRQ_PENALTY_PCI_POSSIBLE;
 		}
 	}
-	/* Add a penalty for the SCI */
-	acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING;
+
 	return 0;
 }
 
Signature · 7 lines
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Acked-by on v1 1/2
#3 lore raw
In reply to Jiang Liu
Quoted 11 lines · Jiang Liu

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.

Quoted 1 line
Quoted 68 lines
---
 drivers/acpi/pci_irq.c  |    1 +
 drivers/acpi/pci_link.c |   13 +++++++++++++
 include/linux/acpi.h    |    1 +
 3 files changed, 15 insertions(+)
drivers/acpi/pci_irq.c +1 -0
index 6da0f9beab19..c9336751e5e3 100644
@@ -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);
drivers/acpi/pci_link.c +13 -0
index 3b4ea98e3ea0..246e50d22120 100644
@@ -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)) {
@@ -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
include/linux/acpi.h +1 -0
index 7235c4851460..43856d19cf4d 100644
@@ -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);
 
Signature · 6 lines
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#4 lore raw
Quoted 12 lines · Bjorn Helgaas
Quoted 11 lines · Jiang Liu

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.

Quoted 3 lines
Quoted 1 line

Thanks!

Queued up both this and the [2/2] for 4.3-rc4.

Thanks,
Rafael