[coreboot] Patch set updated for coreboot: 3bcbfa3 pirq_routing: Allow routing with more than 4 PIRQ links

Alexandru Gagniuc (mr.nuke.me@gmail.com) gerrit at coreboot.org
Sat Aug 25 00:56:41 CEST 2012


Alexandru Gagniuc (mr.nuke.me at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1482

-gerrit

commit 3bcbfa3d58496480434c6d9fa4eefcc667365f81
Author: Alexandru Gagniuc <mr.nuke.me at gmail.com>
Date:   Thu Aug 23 02:32:58 2012 -0500

    pirq_routing: Allow routing with more than 4 PIRQ links
    
    pirq_routing_irqs assumed that only for links are available for PIRQ
    routing, INTA to INTD. Some chipsets provide more, up to INTH.
    When pirq_routing_irqs found a link number greater than 4in the pirq table,
    it would not assign that IRQ. This is a shame, as it limits the flexibility
    of routing IRQs.
    Make the maximum number of links a Kconfig variable, and modify the code to
    respect it. This works beatifully on the VX900, which provides 8 routable
    interrupts.
    While we're at it, also refactor pirq_routing_irqs, and add some much
    needed comments.
    
    Change-Id: I4b565315404c65b871406f616474e2cc9e6e013e
    Signed-off-by: Alexandru Gagniuc <mr.nuke.me at gmail.com>
---
 src/Kconfig                      | 11 ++++++
 src/arch/x86/boot/pirq_routing.c | 77 +++++++++++++++++++++++++---------------
 2 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 469266d..6da906d 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -374,6 +374,17 @@ config HAVE_PIRQ_TABLE
 	  Whether or not the PIRQ table is actually generated by coreboot
 	  is configurable by the user via GENERATE_PIRQ_TABLE.
 
+config MAX_PIRQ_LINKS
+	int
+	default 4
+	help
+	  This variable specifies the number of PIRQ interrupt links which are
+	  routable. On most chipsets, this is 4, INTA through INTD. Some
+	  chipsets offer more than four links, commonly up to INTH. They may
+	  also have a separate link for ATA or IOAPIC interrupts. When the PIRQ
+	  table specifies links greater than 4, pirq_routing_irqs will not
+	  function properly, unless this variable is correctly set.
+
 #These Options are here to avoid "undefined" warnings.
 #The actual selection and help texts are in the following menu.
 
diff --git a/src/arch/x86/boot/pirq_routing.c b/src/arch/x86/boot/pirq_routing.c
index bb8a7b6..dd147c6 100644
--- a/src/arch/x86/boot/pirq_routing.c
+++ b/src/arch/x86/boot/pirq_routing.c
@@ -97,13 +97,47 @@ unsigned long copy_pirq_routing_table(unsigned long addr)
 }
 
 #if CONFIG_PIRQ_ROUTE
+
+#define MAX_INTX_ENTRIES 4
+static u8 pirq_get_next_free_irq(u8* pirq, u16 bitmap)
+{
+	int i, link;
+	u8 irq = 0;
+	for (i = 2; i <= 15; i++)
+	{
+		/* Can we assign this IRQ ? */
+		if (!((bitmap >> i) & 1))
+			continue;
+		/* We can, Now let's assume we can use this IRQ */
+		irq = i;
+		/* And assume we have not yet routed it */
+		int already_routed = 0;
+		/* Have we already routed it ? */
+		for(link = 0; link < CONFIG_MAX_PIRQ_LINKS; link++) {
+			if (pirq[link] == irq) {
+				already_routed = 1;
+				break;
+			}
+		}
+		/* If it's not yet routed, use it */
+		if(!already_routed)
+			break;
+		/* But if it was already routed, try the next one */
+		continue;
+	}
+	/* Now we got our IRQ */
+	return irq;
+}
+
 void pirq_routing_irqs(unsigned long addr)
 {
-	int i, j, k, num_entries;
-	unsigned char irq_slot[4];
-	unsigned char pirq[4] = {0, 0, 0, 0};
+	int i, intx, num_entries;
+	unsigned char irq_slot[MAX_INTX_ENTRIES];
+	unsigned char pirq[CONFIG_MAX_PIRQ_LINKS];
 	struct irq_routing_table *pirq_tbl;
 
+	memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS);
+
 	pirq_tbl = (struct irq_routing_table *)(addr);
 	num_entries = (pirq_tbl->size - 32) / 16;
 
@@ -113,37 +147,26 @@ void pirq_routing_irqs(unsigned long addr)
 		printk(BIOS_DEBUG, "PIRQ Entry %d Dev/Fn: %X Slot: %d\n", i,
 			pirq_tbl->slots[i].devfn >> 3, pirq_tbl->slots[i].slot);
 
-		for (j = 0; j < 4; j++) {
+		for (intx = 0; intx < MAX_INTX_ENTRIES; intx++) {
 
-			int link = pirq_tbl->slots[i].irq[j].link;
-			int bitmap = pirq_tbl->slots[i].irq[j].bitmap;
+			int link = pirq_tbl->slots[i].irq[intx].link;
+			int bitmap = pirq_tbl->slots[i].irq[intx].bitmap;
 			int irq = 0;
 
 			printk(BIOS_DEBUG, "INT: %c link: %x bitmap: %x  ",
-				'A' + j, link, bitmap);
+				'A' + intx, link, bitmap);
 
-			if (!bitmap|| !link || link > 4) {
+			if (!bitmap|| !link || link > CONFIG_MAX_PIRQ_LINKS) {
 
 				printk(BIOS_DEBUG, "not routed\n");
-				irq_slot[j] = irq;
+				irq_slot[intx] = irq;
 				continue;
 			}
 
 			/* yet not routed */
-			if (!pirq[link - 1]) {
-
-				for (k = 2; k <= 15; k++) {
-
-					if (!((bitmap >> k) & 1))
-						continue;
-
-					irq = k;
-
-					/* yet not routed */
-					if (pirq[0] != irq && pirq[1] != irq && pirq[2] != irq && pirq[3] != irq)
-						break;
-				}
-
+			if (!pirq[link - 1])
+			{
+				irq = pirq_get_next_free_irq(pirq, bitmap);
 				if (irq)
 					pirq[link - 1] = irq;
 			}
@@ -151,7 +174,7 @@ void pirq_routing_irqs(unsigned long addr)
 				irq = pirq[link - 1];
 
 			printk(BIOS_DEBUG, "IRQ: %d\n", irq);
-			irq_slot[j] = irq;
+			irq_slot[intx] = irq;
 		}
 
 		/* Bus, device, slots IRQs for {A,B,C,D}. */
@@ -159,10 +182,8 @@ void pirq_routing_irqs(unsigned long addr)
 			pirq_tbl->slots[i].devfn >> 3, irq_slot);
 	}
 
-	printk(BIOS_DEBUG, "PIRQ1: %d\n", pirq[0]);
-	printk(BIOS_DEBUG, "PIRQ2: %d\n", pirq[1]);
-	printk(BIOS_DEBUG, "PIRQ3: %d\n", pirq[2]);
-	printk(BIOS_DEBUG, "PIRQ4: %d\n", pirq[3]);
+	for(i = 0; i < CONFIG_MAX_PIRQ_LINKS; i++)
+		printk(BIOS_DEBUG, "PIRQ%u: %d\n", i+1,  pirq[i]);
 
 	pirq_assign_irqs(pirq);
 }




More information about the coreboot mailing list