MIPS: Octeon: Fix broken interrupt controller code.
authorDavid Daney <david.daney@cavium.com>
Fri, 10 Aug 2012 23:00:31 +0000 (16:00 -0700)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 17 Aug 2012 08:57:26 +0000 (10:57 +0200)
Since 3.6.0-rc1,  We are getting many messages like:

WARNING: at kernel/irq/irqdomain.c:444 irq_domain_associate_many+0x23c/0x260()
Modules linked in:
Call Trace:
[<ffffffff814cb698>] dump_stack+0x8/0x34
[<ffffffff81133d00>] warn_slowpath_common+0x78/0xa8
[<ffffffff81187e44>] irq_domain_associate_many+0x23c/0x260
[<ffffffff81187f38>] irq_create_mapping+0xd0/0x220
[<ffffffff81188104>] irq_create_of_mapping+0x7c/0x158
[<ffffffff813e5f08>] irq_of_parse_and_map+0x28/0x40
.
.
.

Both the CIU and GPIO interrupt domains were somewhat screwed up.

For the CIU domain, we need to call irq_domain_associate() for each of
the preassigned irq numbers.  For the GPIO domain, we were applying
the register bit offset in octeon_irq_gpio_xlat, but it should be done
in octeon_irq_gpio_map instead.

Also: Reserve all 8 'core' irqs for the 'core' irq_chip so that they
don't get used by the other domains.  Remove unused OCTEON_IRQ_*
symbols.

Signed-off-by: David Daney <david.daney@cavium.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/4190/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/include/asm/mach-cavium-octeon/irq.h

index 7fb1f222b8a538b9b000e99375899f37a0c069a9..274cd4fad30c4810f29a420e2dc1e4b139adba73 100644 (file)
@@ -61,6 +61,12 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
        octeon_irq_ciu_to_irq[line][bit] = irq;
 }
 
+static void octeon_irq_force_ciu_mapping(struct irq_domain *domain,
+                                        int irq, int line, int bit)
+{
+       irq_domain_associate(domain, irq, line << 6 | bit);
+}
+
 static int octeon_coreid_for_cpu(int cpu)
 {
 #ifdef CONFIG_SMP
@@ -183,19 +189,9 @@ static void __init octeon_irq_init_core(void)
                mutex_init(&cd->core_irq_mutex);
 
                irq = OCTEON_IRQ_SW0 + i;
-               switch (irq) {
-               case OCTEON_IRQ_TIMER:
-               case OCTEON_IRQ_SW0:
-               case OCTEON_IRQ_SW1:
-               case OCTEON_IRQ_5:
-               case OCTEON_IRQ_PERF:
-                       irq_set_chip_data(irq, cd);
-                       irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
-                                                handle_percpu_irq);
-                       break;
-               default:
-                       break;
-               }
+               irq_set_chip_data(irq, cd);
+               irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
+                                        handle_percpu_irq);
        }
 }
 
@@ -890,7 +886,6 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
        unsigned int type;
        unsigned int pin;
        unsigned int trigger;
-       struct octeon_irq_gpio_domain_data *gpiod;
 
        if (d->of_node != node)
                return -EINVAL;
@@ -925,8 +920,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
                break;
        }
        *out_type = type;
-       gpiod = d->host_data;
-       *out_hwirq = gpiod->base_hwirq + pin;
+       *out_hwirq = pin;
 
        return 0;
 }
@@ -996,19 +990,21 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
 static int octeon_irq_gpio_map(struct irq_domain *d,
                               unsigned int virq, irq_hw_number_t hw)
 {
-       unsigned int line = hw >> 6;
-       unsigned int bit = hw & 63;
+       struct octeon_irq_gpio_domain_data *gpiod = d->host_data;
+       unsigned int line, bit;
 
        if (!octeon_irq_virq_in_range(virq))
                return -EINVAL;
 
+       hw += gpiod->base_hwirq;
+       line = hw >> 6;
+       bit = hw & 63;
        if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
        octeon_irq_set_ciu_mapping(virq, line, bit,
                                   octeon_irq_gpio_chip,
                                   octeon_irq_handle_gpio);
-
        return 0;
 }
 
@@ -1149,6 +1145,7 @@ static void __init octeon_irq_init_ciu(void)
        struct irq_chip *chip_wd;
        struct device_node *gpio_node;
        struct device_node *ciu_node;
+       struct irq_domain *ciu_domain = NULL;
 
        octeon_irq_init_ciu_percpu();
        octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
@@ -1177,31 +1174,6 @@ static void __init octeon_irq_init_ciu(void)
        /* Mips internal */
        octeon_irq_init_core();
 
-       /* CIU_0 */
-       for (i = 0; i < 16; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
-
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
-
-       /* CIU_1 */
-       for (i = 0; i < 16; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
-
        gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
        if (gpio_node) {
                struct octeon_irq_gpio_domain_data *gpiod;
@@ -1219,10 +1191,35 @@ static void __init octeon_irq_init_ciu(void)
 
        ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
        if (ciu_node) {
-               irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
+               ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
                of_node_put(ciu_node);
        } else
-               pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n");
+               panic("Cannot find device node for cavium,octeon-3860-ciu.");
+
+       /* CIU_0 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
+
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36);
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63);
+
+       /* CIU_1 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
 
        /* Enable the CIU lines */
        set_c0_status(STATUSF_IP3 | STATUSF_IP2);
index 418992042f6fcbc23f1612a82ee886cd969c5fa5..c22a3078bf11b69f2da21547fc1c337da7b51206 100644 (file)
@@ -21,14 +21,10 @@ enum octeon_irq {
        OCTEON_IRQ_TIMER,
 /* sources in CIU_INTX_EN0 */
        OCTEON_IRQ_WORKQ0,
-       OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16,
-       OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
+       OCTEON_IRQ_WDOG0 = OCTEON_IRQ_WORKQ0 + 16,
        OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
        OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
        OCTEON_IRQ_MBOX1,
-       OCTEON_IRQ_UART0,
-       OCTEON_IRQ_UART1,
-       OCTEON_IRQ_UART2,
        OCTEON_IRQ_PCI_INT0,
        OCTEON_IRQ_PCI_INT1,
        OCTEON_IRQ_PCI_INT2,
@@ -38,8 +34,6 @@ enum octeon_irq {
        OCTEON_IRQ_PCI_MSI2,
        OCTEON_IRQ_PCI_MSI3,
 
-       OCTEON_IRQ_TWSI,
-       OCTEON_IRQ_TWSI2,
        OCTEON_IRQ_RML,
        OCTEON_IRQ_TIMER0,
        OCTEON_IRQ_TIMER1,
@@ -47,8 +41,6 @@ enum octeon_irq {
        OCTEON_IRQ_TIMER3,
        OCTEON_IRQ_USB0,
        OCTEON_IRQ_USB1,
-       OCTEON_IRQ_MII0,
-       OCTEON_IRQ_MII1,
        OCTEON_IRQ_BOOTDMA,
 #ifndef CONFIG_PCI_MSI
        OCTEON_IRQ_LAST = 127