sh: intc: Handle legacy IRQ reservation in vector map.
authorPaul Mundt <lethal@linux-sh.org>
Mon, 2 Nov 2009 06:43:20 +0000 (15:43 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 2 Nov 2009 06:43:20 +0000 (15:43 +0900)
Different CPUs will have different starting vectors, with varying
amounts of reserved or unusable vector space prior to the first slot.
This introduces a legacy vector reservation system that inserts itself in
between the CPU vector map registration and the platform specific IRQ
setup. This works fine in practice as the only new vectors that boards
need to establish on their own should be dynamically allocated rather
than arbitrarily assigned. As a plus, this also makes all of the
converted platforms sparseirq ready.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/irq.c
drivers/sh/intc.c
include/linux/sh_intc.h

index 7aa89fac1f815977d46e1011ccb3f8657b376d30..e1913f28f4189b17493c5492b6e3e0aeb223d15a 100644 (file)
@@ -263,6 +263,12 @@ void __init init_IRQ(void)
 {
        plat_irq_setup();
 
+       /*
+        * Pin any of the legacy IRQ vectors that haven't already been
+        * grabbed by the platform
+        */
+       reserve_irq_legacy();
+
        /* Perform the machine specific initialisation */
        if (sh_mv.mv_init_irq)
                sh_mv.mv_init_irq();
index 4789df43c0f94c62a8aa440da03c2fb642e61096..a7e5c2e9986c0c700cf76f154f5c3c907914166d 100644 (file)
@@ -928,3 +928,28 @@ void destroy_irq(unsigned int irq)
        __clear_bit(irq, intc_irq_map);
        spin_unlock_irqrestore(&vector_lock, flags);
 }
+
+int reserve_irq_vector(unsigned int irq)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&vector_lock, flags);
+       if (test_and_set_bit(irq, intc_irq_map))
+               ret = -EBUSY;
+       spin_unlock_irqrestore(&vector_lock, flags);
+
+       return ret;
+}
+
+void reserve_irq_legacy(void)
+{
+       unsigned long flags;
+       int i, j;
+
+       spin_lock_irqsave(&vector_lock, flags);
+       j = find_first_bit(intc_irq_map, nr_irqs);
+       for (i = 0; i < j; i++)
+               __set_bit(i, intc_irq_map);
+       spin_unlock_irqrestore(&vector_lock, flags);
+}
index 4e4b22d501647e723a07ff62cb3e2cd1f11956c8..4ef246f14654f389197738105c5d5a75a2965e74 100644 (file)
@@ -84,4 +84,7 @@ struct intc_desc symbol __initdata = {                                        \
 void __init register_intc_controller(struct intc_desc *desc);
 int intc_set_priority(unsigned int irq, unsigned int prio);
 
+int reserve_irq_vector(unsigned int irq);
+void reserve_irq_legacy(void);
+
 #endif /* __SH_INTC_H */