Alexandru Gagniuc ([email protected]) just uploaded a new patch set to 
gerrit, which you can find at http://review.coreboot.org/1482

-gerrit

commit 92ddf0152c2b1386f0b18a876728e8bd7106cc9b
Author: Alexandru Gagniuc <[email protected]>
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 four 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 4 in 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.
    The copyrights added were determined from git log filename.
    
    Change-Id: I4b565315404c65b871406f616474e2cc9e6e013e
    Signed-off-by: Alexandru Gagniuc <[email protected]>
---
 src/Kconfig                              | 12 ++++
 src/arch/x86/boot/pirq_routing.c         | 98 ++++++++++++++++++++++----------
 src/arch/x86/include/arch/pirq_routing.h | 35 +++++++++++-
 3 files changed, 112 insertions(+), 33 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 469266d..e0062dd 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -1,6 +1,7 @@
 ##
 ## This file is part of the coreboot project.
 ##
+## Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
 ## Copyright (C) 2009-2010 coresystems GmbH
 ##
 ## This program is free software; you can redistribute it and/or modify
@@ -374,6 +375,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_route_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..5b0a9da 100644
--- a/src/arch/x86/boot/pirq_routing.c
+++ b/src/arch/x86/boot/pirq_routing.c
@@ -1,3 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+ * Copyright (C) 2010 Stefan Reinauer <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 #include <console/console.h>
 #include <arch/pirq_routing.h>
 #include <string.h>
@@ -92,18 +111,50 @@ unsigned long copy_pirq_routing_table(unsigned long addr)
 #if CONFIG_DEBUG_PIRQ
        verify_copy_pirq_routing_table(addr);
 #endif
-       pirq_routing_irqs(addr);
+       pirq_route_irqs(addr);
        return addr + intel_irq_routing_table.size;
 }
 
 #if CONFIG_PIRQ_ROUTE
-void pirq_routing_irqs(unsigned long addr)
+static u8 pirq_get_next_free_irq(u8* pirq, u16 bitmap)
 {
-       int i, j, k, num_entries;
-       unsigned char irq_slot[4];
-       unsigned char pirq[4] = {0, 0, 0, 0};
+       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_route_irqs(unsigned long addr)
+{
+       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 +164,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 +191,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 +199,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 + 'A',  pirq[i]);
 
        pirq_assign_irqs(pirq);
 }
diff --git a/src/arch/x86/include/arch/pirq_routing.h 
b/src/arch/x86/include/arch/pirq_routing.h
index 08ba535..c5be5f4 100644
--- a/src/arch/x86/include/arch/pirq_routing.h
+++ b/src/arch/x86/include/arch/pirq_routing.h
@@ -1,6 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+ * Copyright (C) 2012 Patrick Georgi <[email protected]>
+ * Copyright (C) 2010 Stefan Reinauer <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 #ifndef ARCH_PIRQ_ROUTING_H
 #define ARCH_PIRQ_ROUTING_H
 
+/* This is the maximum number on interrupt entries that a PCI device may have.
+ *   This is NOT the number of slots or devices in the system
+ *   This is NOT the number of entries in the PIRQ table
+ * This tells us that in the PIRQ table, we are going to have 4 link-bitmap
+ * entries per PCI device
+ * It is fixed at 4: INTA, INTB, INTC, and INTD
+ * CAUTION: If you change this, pirq_routing will not work correctly*/
+#define MAX_INTX_ENTRIES 4
+
 #if CONFIG_GENERATE_PIRQ_TABLE
 #include <stdint.h>
 
@@ -40,10 +69,10 @@ unsigned long copy_pirq_routing_table(unsigned long start);
 unsigned long write_pirq_routing_table(unsigned long start);
 
 #if CONFIG_PIRQ_ROUTE
-void pirq_routing_irqs(unsigned long start);
-void pirq_assign_irqs(const unsigned char pIntAtoD[4]);
+void pirq_route_irqs(unsigned long start);
+void pirq_assign_irqs(const unsigned char pirq[CONFIG_MAX_PIRQ_LINKS]);
 #else
-#define pirq_routing_irqs(start) {}
+#define pirq_route_irqs(start) {}
 #endif
 
 #else

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to