Skip to contentSkip to conversation

acpi: add support for extended IRQ to PCI link

PATCH In review Sinan Kaya 2 participants 3 messages Nov 25, 2015 – Nov 30, 2015

Subsystems (2)
lore
Share & tools
lore

Sinan Kaya

author
#0 lore raw

PATCH v6 1/1 acpi: add support for extended IRQ to PCI link

The ACPI compiler uses the extended format when used interrupt numbers are greater than 256. The extended IRQ numbers use 32 bits for storing interrupts. The code already supports parsing extended IRQ type but is limited by 256 due to used data structure type (u8). This patch changes the interrupt number type to 32 bits and places an upper limit of 1020 as possible interrupt id. 1020 is the maximum interrupt ID that can be assigned to an ARM SPI interrupt according to ARM architecture.

Additional checks have been placed to return an error when ACPI_MAX_IRQS is exceeded.

---
 drivers/acpi/pci_link.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)
drivers/acpi/pci_link.c +24 -5
index 7c8408b..5ab83dc 100644
@@ -4,6 +4,7 @@
  *  Copyright (C) 2001, 2002 Andy Grover <[email protected]>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
  *  Copyright (C) 2002       Dominik Brodowski <[email protected]>
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -47,6 +48,14 @@ ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
 #define ACPI_PCI_LINK_MAX_POSSIBLE	16
 
+/*
+ * 1020 is the maximum interrupt ID that can be assigned to
+ * an ARM SPI interrupt according to ARM architecture.
+ */
+#define ACPI_MAX_IRQS		1020
+#define ACPI_MAX_ISA_IRQ	16
+
+
 static int acpi_pci_link_add(struct acpi_device *device,
 			     const struct acpi_device_id *not_used);
 static void acpi_pci_link_remove(struct acpi_device *device);
@@ -67,12 +76,12 @@ static struct acpi_scan_handler pci_link_handler = {
  * later even the link is disable. Instead, we just repick the active irq
  */
 struct acpi_pci_link_irq {
-	u8 active;		/* Current IRQ */
+	u32 active;		/* Current IRQ */
 	u8 triggering;		/* All IRQs */
 	u8 polarity;		/* All IRQs */
 	u8 resource_type;
 	u8 possible_count;
-	u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
 	u8 initialized:1;
 	u8 reserved:7;
 };
@@ -147,6 +156,13 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 					       p->interrupts[i]);
 					continue;
 				}
+				if (p->interrupts[i] >= ACPI_MAX_IRQS) {
+					dev_warn(&link->device->dev,
+						"Ignoring IRQ(%d) as it exceeds max(%d)\n",
+						p->interrupts[i],
+						ACPI_MAX_IRQS - 1);
+					continue;
+				}
 				link->irq.possible[i] = p->interrupts[i];
 				link->irq.possible_count++;
 			}
@@ -279,6 +295,12 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
 		result = -ENODEV;
 	}
 
+	if (irq >= ACPI_MAX_IRQS) {
+		dev_err(&link->device->dev,
+			"Ignoring IRQ(%d) as it exceeds max(%d)\n",
+			irq,  ACPI_MAX_IRQS - 1);
+		result = -ENODEV;
+	}
 	link->irq.active = irq;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
@@ -437,9 +459,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS		256
-#define ACPI_MAX_ISA_IRQ	16
-
 #define PIRQ_PENALTY_PCI_AVAILABLE	(0)
 #define PIRQ_PENALTY_PCI_POSSIBLE	(16*16)
 #define PIRQ_PENALTY_PCI_USING		(16*16*16)
Signature · 2 lines
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
#1 lore raw
Quoted 8 lines · Sinan Kaya

The ACPI compiler uses the extended format when used interrupt numbers are greater than 256. The extended IRQ numbers use 32 bits for storing interrupts. The code already supports parsing extended IRQ type but is limited by 256 due to used data structure type (u8). This patch changes the interrupt number type to 32 bits and places an upper limit of 1020 as possible interrupt id. 1020 is the maximum interrupt ID that can be assigned to an ARM SPI interrupt according to ARM architecture.

Quoted 4 lines

Additional checks have been placed to return an error when ACPI_MAX_IRQS is exceeded.

I don't think the description is quite accurate -- I think the extended IRQ descriptor is required for IRQs of *16* and greater, not IRQs greater than 256. Here's how I understand it:

The ACPI IRQ Descriptor contains a 16-bit mask with a bit for each IRQ, so it can describe interrupt numbers in the range [0-15]. Interrupt numbers greater than 15 must be described with an Extended IRQ Descriptor, which contains a table of 32-bit interrupt numbers and can describe interrupt numbers in the range [0-(2^32-1)]. See ACPI 5.0, sections 6.4.2.1 and 6.4.3.6.

Quoted 17 lines
---
 drivers/acpi/pci_link.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)
drivers/acpi/pci_link.c +1 -0
index 7c8408b..5ab83dc 100644
@@ -4,6 +4,7 @@
  *  Copyright (C) 2001, 2002 Andy Grover <[email protected]>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
  *  Copyright (C) 2002       Dominik Brodowski <[email protected]>
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *

drivers/acpi/pci_link.c ACPI_MODULE_NAME("pci_link"); · line 56

Quoted 9 lines
drivers/acpi/pci_link.c +6 -0
@@ -47,6 +48,14 @@ ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
 #define ACPI_PCI_LINK_MAX_POSSIBLE	16
 
+/*
+ * 1020 is the maximum interrupt ID that can be assigned to
+ * an ARM SPI interrupt according to ARM architecture.
+ */
+#define ACPI_MAX_IRQS		1020
+#define ACPI_MAX_ISA_IRQ	16

ACPI_MAX_IRQS is only used to size the acpi_irq_penalty[] table (and after your patch, to validate IRQ numbers from ACPI). But I think the acpi_irq_penalty[] table is a design we've outgrown. I *think* we only care about penalties for IRQs 0-15, so even a 256-entry table is more than we need.

If we could make acpi_irq_penalty[] a fixed size of 16 entries or replace it with a linked list, I think we could get rid of ACPI_MAX_IRQS completely. Then the validation checks you add below would be unnecessary and we could handle any interrupt number supplied from ACPI.

Bjorn

Quoted 65 lines
drivers/acpi/pci_link.c +17 -5
+
+
 static int acpi_pci_link_add(struct acpi_device *device,
 			     const struct acpi_device_id *not_used);
 static void acpi_pci_link_remove(struct acpi_device *device);
@@ -67,12 +76,12 @@ static struct acpi_scan_handler pci_link_handler = {
  * later even the link is disable. Instead, we just repick the active irq
  */
 struct acpi_pci_link_irq {
-	u8 active;		/* Current IRQ */
+	u32 active;		/* Current IRQ */
 	u8 triggering;		/* All IRQs */
 	u8 polarity;		/* All IRQs */
 	u8 resource_type;
 	u8 possible_count;
-	u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
 	u8 initialized:1;
 	u8 reserved:7;
 };
@@ -147,6 +156,13 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 					       p->interrupts[i]);
 					continue;
 				}
+				if (p->interrupts[i] >= ACPI_MAX_IRQS) {
+					dev_warn(&link->device->dev,
+						"Ignoring IRQ(%d) as it exceeds max(%d)\n",
+						p->interrupts[i],
+						ACPI_MAX_IRQS - 1);
+					continue;
+				}
 				link->irq.possible[i] = p->interrupts[i];
 				link->irq.possible_count++;
 			}
@@ -279,6 +295,12 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
 		result = -ENODEV;
 	}
 
+	if (irq >= ACPI_MAX_IRQS) {
+		dev_err(&link->device->dev,
+			"Ignoring IRQ(%d) as it exceeds max(%d)\n",
+			irq,  ACPI_MAX_IRQS - 1);
+		result = -ENODEV;
+	}
 	link->irq.active = irq;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
@@ -437,9 +459,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS		256
-#define ACPI_MAX_ISA_IRQ	16
-
 #define PIRQ_PENALTY_PCI_AVAILABLE	(0)
 #define PIRQ_PENALTY_PCI_POSSIBLE	(16*16)
 #define PIRQ_PENALTY_PCI_USING		(16*16*16)
Signature · 7 lines
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

--
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
author
#2 lore raw
Quoted 8 lines · Bjorn Helgaas
Quoted 4 lines
Quoted 4 lines

Additional checks have been placed to return an error when ACPI_MAX_IRQS is exceeded.

I don't think the description is quite accurate -- I think the extended IRQ descriptor is required for IRQs of *16* and greater, not IRQs greater than 256. Here's how I understand it:

Quoted 7 lines

The ACPI IRQ Descriptor contains a 16-bit mask with a bit for each IRQ, so it can describe interrupt numbers in the range [0-15]. Interrupt numbers greater than 15 must be described with an Extended IRQ Descriptor, which contains a table of 32-bit interrupt numbers and can describe interrupt numbers in the range [0-(2^32-1)]. See ACPI 5.0, sections 6.4.2.1 and 6.4.3.6.

You are right. I'm pasting from the spec.

"6.4.2.1 IRQ Descriptor
Type 0, Small Item Name 0x4, Length = 2 or 3
The IRQ data structure indicates that the device uses an interrupt level and supplies a mask with bits set indicating the levels implemented in this device. For standard PC-AT implementation there are 15 possible interrupts so a two-byte field is used. This structure is repeated for each separate interrupt required"

"6.4.3.6 Extended Interrupt Descriptor
Type 1, Large Item Name 0x9
The Extended Interrupt Descriptor is necessary to describe interrupt settings and possibilities for systems that support interrupts above 15."

I'll reword correctly. This was a Linux implementation bug not a spec compliance issue.

Signature · 4 lines
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
Linux Foundation Collaborative Project