m68k/irq: Add genirq support
authorGeert Uytterhoeven <geert@linux-m68k.org>
Thu, 21 Apr 2011 20:50:52 +0000 (22:50 +0200)
committerGeert Uytterhoeven <geert@linux-m68k.org>
Tue, 8 Nov 2011 21:35:49 +0000 (22:35 +0100)
Disabled on all platforms for now

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
[v1] Acked-by: Thomas Gleixner <tglx@linutronix.de>

arch/m68k/Kconfig
arch/m68k/include/asm/hardirq.h
arch/m68k/include/asm/irq.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/ints.c

index 6c28582fb98f5559a39c3a0122104c561d4fa573..a7597e119ab031cd1b068d19ef1ad03a9c00c33a 100644 (file)
@@ -84,6 +84,23 @@ config MMU_SUN3
        bool
        depends on MMU && !MMU_MOTOROLA
 
+config USE_GENERIC_HARDIRQS
+       bool "Use genirq"
+       depends on MMU
+       depends on !AMIGA
+       depends on !ATARI
+       depends on !MAC
+       depends on !APOLLO
+       depends on !MVME147
+       depends on !MVME16x
+       depends on !BVME6000
+       depends on !HP300
+       depends on !SUN3X
+       depends on !Q40
+       depends on !SUN3
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_SHOW
+
 menu "Platform setup"
 
 source arch/m68k/Kconfig.cpu
index 870e5347155b373a386fd1a8a13c47c43395cd51..db30ed276878dcbf793e667d6edb279c5234a60a 100644 (file)
 
 #ifdef CONFIG_MMU
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+       pr_crit("unexpected IRQ trap at vector %02x\n", irq);
+}
+
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
        unsigned int __softirq_pending;
index 9a2bae8ef5b7aa82dd02b500419cb641557db001..518e61f2fccbe5686c5151911904f14eefa17336 100644 (file)
 
 #ifdef CONFIG_MMU
 
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
 /*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
 
 #define IRQ_USER       8
 
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - IRQF_DISABLED and
@@ -71,6 +62,15 @@ struct pt_regs;
 #define IRQ_FLG_STD    (0x8000)        /* internally used              */
 #endif
 
+#ifndef CONFIG_GENERIC_HARDIRQS
+
+#include <linux/linkage.h>
+#include <linux/hardirq.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock_types.h>
+
+struct pt_regs;
+
 /*
  * This structure is used to chain together the ISRs for a particular
  * interrupt source (if it supports chaining).
@@ -121,10 +121,33 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int);
 extern void generic_handle_irq(unsigned int);
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
 
+#else /* CONFIG_GENERIC_HARDIRQS */
+
+struct irq_data;
+struct irq_chip;
+struct irq_desc;
+extern unsigned int m68k_irq_startup(struct irq_data *data);
+extern unsigned int m68k_irq_startup_irq(unsigned int irq);
+extern void m68k_irq_shutdown(struct irq_data *data);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
+                                                     struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+                                     void (*handler)(unsigned int,
+                                                     struct pt_regs *));
+extern void m68k_setup_irq_controller(struct irq_chip *,
+                                     void (*handle)(unsigned int irq,
+                                                    struct irq_desc *desc),
+                                     unsigned int irq, unsigned int cnt);
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
+extern unsigned int irq_canonicalize(unsigned int irq);
+
 #else
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern atomic_t irq_err_count;
 
 #endif /* _M68K_IRQ_H_ */
index e7f0f2e5ad4478a767732c70f229b78aca753383..141425785c4ed4b9af952ec3b0a5d2dc0b7a67b3 100644 (file)
@@ -9,13 +9,18 @@ extra-y                       += vmlinux.lds
 obj-y  := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
           sys_m68k.o syscalltable.o time.o traps.o
 
-obj-$(CONFIG_MMU)      += ints.o devres.o vectors.o
+obj-$(CONFIG_MMU)      += ints.o vectors.o
 devres-$(CONFIG_MMU)   = ../../../kernel/irq/devres.o
 
 ifndef CONFIG_MMU_SUN3
 obj-y                  += dma.o
 endif
 ifndef CONFIG_MMU
-obj-y                  += init_task.o irq.o
+obj-y                  += init_task.o
+endif
+ifdef CONFIG_GENERIC_HARDIRQS
+obj-y                  += irq.o
+else
+obj-y                  += devres.o
 endif
 
index f6a4698651256d1ab960ceedea0efdab1670665e..cea439f9819b709dcc945773a643e3bae66ec8b8 100644 (file)
@@ -31,6 +31,7 @@ extern u32 auto_irqhandler_fixup[];
 extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
 
+#ifndef CONFIG_GENERIC_HARDIRQS
 /* table for system interrupt handlers */
 static struct irq_data *irq_list[NR_IRQS];
 static struct irq_chip *irq_chip[NR_IRQS];
@@ -41,6 +42,8 @@ static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip)
        irq_chip[irq] = chip;
        return 0;
 }
+#define irq_set_chip_and_handler(irq, chip, dummy)     irq_set_chip(irq, chip)
+#endif /* !CONFIG_GENERIC_HARDIRQS */
 
 static int m68k_first_user_vec;
 
@@ -56,8 +59,10 @@ static struct irq_chip user_irq_chip = {
        .irq_shutdown   = m68k_irq_shutdown,
 };
 
+#ifndef CONFIG_GENERIC_HARDIRQS
 #define NUM_IRQ_NODES 100
 static struct irq_data nodes[NUM_IRQ_NODES];
+#endif /* !CONFIG_GENERIC_HARDIRQS */
 
 /*
  * void init_IRQ(void)
@@ -81,7 +86,7 @@ void __init init_IRQ(void)
        }
 
        for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
-               irq_set_chip(i, &auto_irq_chip);
+               irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
        mach_init_IRQ();
 }
@@ -128,6 +133,35 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
        flush_icache();
 }
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+
+/**
+ * m68k_setup_irq_controller
+ * @chip: irq chip which controls specified irq
+ * @handle: flow handler which handles specified irq
+ * @irq: first irq to be managed by the controller
+ * @cnt: number of irqs to be managed by the controller
+ *
+ * Change the controller for the specified range of irq, which will be used to
+ * manage these irq. auto/user irq already have a default controller, which can
+ * be changed as well, but the controller probably should use m68k_irq_startup/
+ * m68k_irq_shutdown.
+ */
+void m68k_setup_irq_controller(struct irq_chip *chip,
+                              irq_flow_handler_t handle, unsigned int irq,
+                              unsigned int cnt)
+{
+       int i;
+
+       for (i = 0; i < cnt; i++) {
+               irq_set_chip(irq + i, chip);
+               if (handle)
+                       irq_set_handler(irq + i, handle);
+       }
+}
+
+#else /* !CONFIG_GENERIC_HARDIRQS */
+
 /**
  * m68k_setup_irq_chip
  * @contr: irq controller which controls specified irq
@@ -316,6 +350,8 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
 
 EXPORT_SYMBOL(disable_irq_nosync);
 
+#endif /* !CONFIG_GENERIC_HARDIRQS */
+
 unsigned int m68k_irq_startup_irq(unsigned int irq)
 {
        if (irq <= IRQ_AUTO_7)
@@ -341,6 +377,8 @@ void m68k_irq_shutdown(struct irq_data *data)
 }
 
 
+#ifndef CONFIG_GENERIC_HARDIRQS
+
 /*
  * Do we need these probe functions on the m68k?
  *
@@ -367,6 +405,7 @@ int probe_irq_off (unsigned long irqs)
 }
 
 EXPORT_SYMBOL(probe_irq_off);
+#endif /* CONFIG_GENERIC_HARDIRQS */
 
 unsigned int irq_canonicalize(unsigned int irq)
 {
@@ -379,6 +418,7 @@ unsigned int irq_canonicalize(unsigned int irq)
 
 EXPORT_SYMBOL(irq_canonicalize);
 
+#ifndef CONFIG_GENERIC_HARDIRQS
 void generic_handle_irq(unsigned int irq)
 {
        struct irq_data *node;
@@ -428,3 +468,13 @@ void init_irq_proc(void)
        /* Insert /proc/irq driver here */
 }
 #endif
+
+#else /* CONFIG_GENERIC_HARDIRQS */
+
+asmlinkage void handle_badint(struct pt_regs *regs)
+{
+       atomic_inc(&irq_err_count);
+       pr_warn("unexpected interrupt from %u\n", regs->vector);
+}
+
+#endif /* CONFIG_GENERIC_HARDIRQS */