Skip to contentSkip to conversation

acpi: add support for extended IRQ to PCI link

PATCH Superseded Sinan Kaya 3 participants 7 messages Nov 12, 2015

Subsystems (2)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore

Sinan Kaya

author
#0 lore raw

PATCH v2 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 PCI link code currently only supports simple interrupt format. The IRQ numbers are represented using 32 bits when extended IRQ syntax. 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 prevent out of bounds writes.

Changes from V1: (https://lkml.org/lkml/2015/11/8/162)
* change the commit text to include 1020 magic interrupt number limitation
* cleanup multiple levels of if statements

Sinan Kaya (1):
acpi: add support for extended IRQ to PCI link

 drivers/acpi/pci_link.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
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
author
#1 lore raw

PATCH 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 PCI link code currently only supports simple interrupt format. The IRQ numbers are represented using 32 bits when extended IRQ syntax. 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 prevent out of bounds writes.

---
 drivers/acpi/pci_link.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
drivers/acpi/pci_link.c +17 -11
index 7c8408b..a2becab 100644
@@ -1,6 +1,7 @@
 /*
  *  pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
  *
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *  Copyright (C) 2001, 2002 Andy Grover <[email protected]>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
  *  Copyright (C) 2002       Dominik Brodowski <[email protected]>
@@ -67,12 +68,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;
 };
@@ -437,7 +438,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS		256
+#define ACPI_MAX_IRQS		1020
 #define ACPI_MAX_ISA_IRQ	16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE	(0)
@@ -493,7 +494,8 @@ int __init acpi_irq_penalty_init(void)
 					    penalty;
 			}
 
-		} else if (link->irq.active) {
+		} else if (link->irq.active &&
+			(link->irq.active < ACPI_MAX_IRQS)) {
 			acpi_irq_penalty[link->irq.active] +=
 			    PIRQ_PENALTY_PCI_POSSIBLE;
 		}
@@ -541,14 +543,16 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
 	else
 		irq = link->irq.possible[link->irq.possible_count - 1];
 
-	if (acpi_irq_balance || !link->irq.active) {
+	if ((acpi_irq_balance || !link->irq.active) && (irq < ACPI_MAX_IRQS)) {
 		/*
-		 * Select the best IRQ.  This is done in reverse to promote
-		 * the use of IRQs 9, 10, 11, and >15.
+		 * Select the best IRQ.  This is done in reverse to
+		 * promote the use of IRQs 9, 10, 11, and >15.
 		 */
-		for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-			if (acpi_irq_penalty[irq] >
-			    acpi_irq_penalty[link->irq.possible[i]])
+		i = link->irq.possible_count;
+		while (--i) {
+			if ((link->irq.possible[i] < ACPI_MAX_IRQS) &&
+			    (acpi_irq_penalty[irq] >
+			    acpi_irq_penalty[link->irq.possible[i]]))
 				irq = link->irq.possible[i];
 		}
 	}
@@ -568,7 +572,9 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
 			    acpi_device_bid(link->device));
 		return -ENODEV;
 	} else {
-		acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
+		if (link->irq.active < ACPI_MAX_IRQS)
+			acpi_irq_penalty[link->irq.active] +=
+				PIRQ_PENALTY_PCI_USING;
 		printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
 		       acpi_device_name(link->device),
 		       acpi_device_bid(link->device), link->irq.active);
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
#2 lore raw
Quoted 10 lines · Sinan Kaya

The ACPI compiler uses the extended format when used interrupt numbers are greater than 256. The PCI link code currently only supports simple interrupt format. The IRQ numbers are represented using 32 bits when extended IRQ syntax. 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.

I think it worth to put these lines in the code as well.

Quoted 57 lines

Additional checks have been placed to prevent out of bounds writes.

---
 drivers/acpi/pci_link.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
drivers/acpi/pci_link.c +6 -4
index 7c8408b..a2becab 100644
@@ -1,6 +1,7 @@
 /*
  *  pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
  *
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *  Copyright (C) 2001, 2002 Andy Grover <[email protected]>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
  *  Copyright (C) 2002       Dominik Brodowski <[email protected]>
@@ -67,12 +68,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;
 };
@@ -437,7 +438,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS          256
+#define ACPI_MAX_IRQS          1020
 #define ACPI_MAX_ISA_IRQ       16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE     (0)
@@ -493,7 +494,8 @@ int __init acpi_irq_penalty_init(void)
                                            penalty;
                        }
 
-               } else if (link->irq.active) {
+               } else if (link->irq.active &&
+                       (link->irq.active < ACPI_MAX_IRQS)) {
                        acpi_irq_penalty[link->irq.active] +=
                            PIRQ_PENALTY_PCI_POSSIBLE;
                }
@@ -541,14 +543,16 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
        else

drivers/acpi/pci_link.c static int acpi_pci_link_allocate(struct acpi_pci_link *link) · line 550

Quoted 10 lines
drivers/acpi/pci_link.c +3 -3
                irq = link->irq.possible[link->irq.possible_count - 1];
 
-       if (acpi_irq_balance || !link->irq.active) {
+       if ((acpi_irq_balance || !link->irq.active) && (irq < ACPI_MAX_IRQS)) {
                /*
 
-                * Select the best IRQ.  This is done in reverse to promote
-                * the use of IRQs 9, 10, 11, and >15.
+                * Select the best IRQ.  This is done in reverse to
+                * promote the use of IRQs 9, 10, 11, and >15.

What was changed here?

Quoted 23 lines
drivers/acpi/pci_link.c +5 -3
                 */
-               for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_penalty[irq] >
-                           acpi_irq_penalty[link->irq.possible[i]])
+               i = link->irq.possible_count;
+               while (--i) {
+                       if ((link->irq.possible[i] < ACPI_MAX_IRQS) &&
+                           (acpi_irq_penalty[irq] >
+                           acpi_irq_penalty[link->irq.possible[i]]))
                                irq = link->irq.possible[i];
                }
        }
drivers/acpi/pci_link.c +3 -1
@@ -568,7 +572,9 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
-               acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
+               if (link->irq.active < ACPI_MAX_IRQS)
+                       acpi_irq_penalty[link->irq.active] +=
+                               PIRQ_PENALTY_PCI_USING;
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
Signature · 2 lines
With Best Regards,
Andy Shevchenko
author
#3 lore raw
Quoted 9 lines · Andy Shevchenko
Quoted 8 lines · Sinan Kaya

The ACPI compiler uses the extended format when used interrupt numbers are greater than 256. The PCI link code currently only supports simple interrupt format. The IRQ numbers are represented using 32 bits when extended IRQ syntax. This patch changes the interrupt number type to 32 bits and places an upper limit of 1020 as possible interrupt id.

Quoted 5 lines
Quoted 2 lines

1020 is the maximum interrupt ID that can be assigned to an ARM SPI interrupt according to ARM architecture.

I think it worth to put these lines in the code as well.

ok

Quoted 63 lines
Quoted 62 lines

Additional checks have been placed to prevent out of bounds writes.

---
 drivers/acpi/pci_link.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
drivers/acpi/pci_link.c +7 -5
index 7c8408b..a2becab 100644
@@ -1,6 +1,7 @@
 /*
  *  pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
  *
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *  Copyright (C) 2001, 2002 Andy Grover <[email protected]>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
  *  Copyright (C) 2002       Dominik Brodowski <[email protected]>
@@ -67,12 +68,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;
 };
@@ -437,7 +438,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS          256
+#define ACPI_MAX_IRQS          1020
 #define ACPI_MAX_ISA_IRQ       16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE     (0)
@@ -493,7 +494,8 @@ int __init acpi_irq_penalty_init(void)
                                            penalty;
                        }
 
-               } else if (link->irq.active) {
+               } else if (link->irq.active &&
+                       (link->irq.active < ACPI_MAX_IRQS)) {
                        acpi_irq_penalty[link->irq.active] +=
                            PIRQ_PENALTY_PCI_POSSIBLE;
                }
@@ -541,14 +543,16 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
        else
                irq = link->irq.possible[link->irq.possible_count - 1];
 
-       if (acpi_irq_balance || !link->irq.active) {
+       if ((acpi_irq_balance || !link->irq.active) && (irq < ACPI_MAX_IRQS)) {
                /*
Quoted 6 lines

drivers/acpi/pci_link.c static int acpi_pci_link_allocate(struct acpi_pci_link *link) · line 549

Quoted 4 lines
drivers/acpi/pci_link.c +2 -2
-                * Select the best IRQ.  This is done in reverse to promote
-                * the use of IRQs 9, 10, 11, and >15.
+                * Select the best IRQ.  This is done in reverse to
+                * promote the use of IRQs 9, 10, 11, and >15.

What was changed here?

See your comments here.
https://lkml.org/lkml/2015/11/8/231

Quoted 26 lines
Quoted 24 lines
drivers/acpi/pci_link.c +8 -4
                 */
-               for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_penalty[irq] >
-                           acpi_irq_penalty[link->irq.possible[i]])
+               i = link->irq.possible_count;
+               while (--i) {
+                       if ((link->irq.possible[i] < ACPI_MAX_IRQS) &&
+                           (acpi_irq_penalty[irq] >
+                           acpi_irq_penalty[link->irq.possible[i]]))
                                irq = link->irq.possible[i];
                }
        }
@@ -568,7 +572,9 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
-               acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
+               if (link->irq.active < ACPI_MAX_IRQS)
+                       acpi_irq_penalty[link->irq.active] +=
+                               PIRQ_PENALTY_PCI_USING;
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
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
#4 lore raw
Quoted 11 lines · Sinan Kaya
Quoted 10 lines · Andy Shevchenko
Quoted 8 lines · Sinan Kaya
drivers/acpi/pci_link.c +3 -3
-       if (acpi_irq_balance || !link->irq.active) {
+       if ((acpi_irq_balance || !link->irq.active) && (irq < ACPI_MAX_IRQS)) {
                /*
 
-                * Select the best IRQ.  This is done in reverse to promote
-                * the use of IRQs 9, 10, 11, and >15.
+                * Select the best IRQ.  This is done in reverse to
+                * promote the use of IRQs 9, 10, 11, and >15.
Quoted 4 lines
Quoted 1 line

What was changed here?

See your comments here.
https://lkml.org/lkml/2015/11/8/231

So, you refer to narrow commentary blocks, right?
It was about *new* code, leave as is what was before your patch series.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#5 lore raw
Quoted 20 lines · Sinan Kaya
Quoted 14 lines · Andy Shevchenko
Quoted 13 lines
Quoted 10 lines · Sinan Kaya
(quoted diff) +1 -1
-       if (acpi_irq_balance || !link->irq.active) {
+       if ((acpi_irq_balance || !link->irq.active) && (irq <
ACPI_MAX_IRQS)) {
                /*

- * Select the best IRQ. This is done in reverse to
promote

drivers/acpi/pci_link.c +2 -1
-                * the use of IRQs 9, 10, 11, and >15.
+                * Select the best IRQ.  This is done in reverse to
+                * promote the use of IRQs 9, 10, 11, and >15.
Quoted 4 lines
Quoted 1 line

What was changed here?

See your comments here.
https://lkml.org/lkml/2015/11/8/231

Quoted 7 lines

So, you refer to narrow commentary blocks, right?
It was about *new* code, leave as is what was before your patch series.

--
With Best Regards,
Andy Shevchenko

This is what it was before.

drivers/acpi/pci_link.c static int acpi_pci_link_allocate(struct acpi_pci_link *link)

Quoted 9 lines
        if (acpi_irq_balance || !link->irq.active) {
drivers/acpi/pci_link.c +0 -8
-               /*
-                * Select the best IRQ.  This is done in reverse to promote
-                * the use of IRQs 9, 10, 11, and >15.
-                */
-               for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_penalty[irq] >
-                           acpi_irq_penalty[link->irq.possible[i]])
-                               irq = link->irq.possible[i];

I added a range check for link->irq.possible[i] and irq into this code.

#6 lore raw
Quoted 11 lines · [email protected] wrote:

This is what it was before.

Quoted 9 lines

drivers/acpi/pci_link.c static int acpi_pci_link_allocate(struct acpi_pci_link *link)

Quoted 9 lines
        if (acpi_irq_balance || !link->irq.active) {
drivers/acpi/pci_link.c +0 -8
-               /*
-                * Select the best IRQ.  This is done in reverse to promote
-                * the use of IRQs 9, 10, 11, and >15.
-                */
-               for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_penalty[irq] >
-                           acpi_irq_penalty[link->irq.possible[i]])
-                               irq = link->irq.possible[i];
Quoted 3 lines

I added a range check for link->irq.possible[i] and irq into this code.

This change:

- * Select the best IRQ. This is done in reverse to promote
- * the use of IRQs 9, 10, 11, and >15.
+ * Select the best IRQ. This is done in reverse to
+ * promote the use of IRQs 9, 10, 11, and >15.

is an unrelated whitespace change. It doesn't belong in this patch.

Signature · 3 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.