sparc32, leon: Do not overwrite previously set irq flow handlers
authorAndreas Larsson <andreas@gaisler.com>
Sun, 21 Apr 2013 21:23:06 +0000 (21:23 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 5 May 2013 00:38:18 +0000 (17:38 -0700)
This is needed because when scan_of_devices finds the GAISLER_GPTIMER
core that corresponds to the SMP "ticker" timer, the previously set
proper irq flow handler gets overwritten with an incorrect one. This
leads to very flaky timer interrupt handling on some hardware. Proper
updates to handlers can still be done using leon_update_virq_handling.

Signed-off-by: Andreas Larsson <andreas@gaisler.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/kernel/leon_kernel.c

index 87f60ee6543394b4aea00d3d5e91082ef0b8a41f..7c0231dabe445f1021190aafe4527b68c113a421 100644 (file)
@@ -213,6 +213,7 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
 {
        unsigned int irq;
        unsigned long mask;
+       struct irq_desc *desc;
 
        irq = 0;
        mask = leon_get_irqmask(real_irq);
@@ -226,9 +227,12 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
        if (do_ack)
                mask |= LEON_DO_ACK_HW;
 
-       irq_set_chip_and_handler_name(irq, &leon_irq,
-                                     flow_handler, name);
-       irq_set_chip_data(irq, (void *)mask);
+       desc = irq_to_desc(irq);
+       if (!desc || !desc->handle_irq || desc->handle_irq == handle_bad_irq) {
+               irq_set_chip_and_handler_name(irq, &leon_irq,
+                                             flow_handler, name);
+               irq_set_chip_data(irq, (void *)mask);
+       }
 
 out:
        return irq;