diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2006-07-01 17:30:09 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-07-01 17:30:09 -0400 |
| commit | 4a2581a080098ca3a0c4e416d7a282e96c75ebf8 (patch) | |
| tree | 6709b53f00a271fe8dd76b6cfb821419c8afb206 | |
| parent | f8b5473fcbddbfde827ecf82aa0e81fa2a878220 (diff) | |
[ARM] 3692/1: ARM: coswitch irq handling to the generic implementation
Patch from Thomas Gleixner
From: Thomas Gleixner <tglx@linutronix.de>
Switch the ARM irq core handling to the generic implementation. The
ARM specific header files now contain mostly migration stubs and
helper macros. Note that each machine type must be converted after
this step seperately. This was seperated out from the patch for easier
review.
The main changes for the machine type code is the conversion of the
type handlers to a 'type flow' and 'chip' model. This affects only the
multiplex interrupt handlers. A conversion macro needs to be added to
those implementations, which defines the data structure which is
registered by the set_irq_chained_handler() macro.
Some minor fixups of include files and the conversion of data
structure access is necessary all over the place.
The mostly macro based conversion was provided to allow an easy
migration of the existing implementations.
The code compiles on all defconfigs available in arch/arm/configs
except those which were broken also before applying the conversion
patches.
The code has been boot and runtime tested on most ARM platforms. The
results of an extensive testing and bugfixing series can be found
at: http://www.linutronix.de/index.php?page=testing
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/Kconfig | 12 | ||||
| -rw-r--r-- | arch/arm/kernel/fiq.c | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/irq.c | 951 | ||||
| -rw-r--r-- | include/asm-arm/dyntick.h | 6 | ||||
| -rw-r--r-- | include/asm-arm/hw_irq.h | 9 | ||||
| -rw-r--r-- | include/asm-arm/irq.h | 22 | ||||
| -rw-r--r-- | include/asm-arm/mach/irq.h | 135 |
7 files changed, 93 insertions, 1043 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f123c7c9fc98..531661ac01b4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -47,6 +47,18 @@ config MCA | |||
| 47 | <file:Documentation/mca.txt> (and especially the web page given | 47 | <file:Documentation/mca.txt> (and especially the web page given |
| 48 | there) before attempting to build an MCA bus kernel. | 48 | there) before attempting to build an MCA bus kernel. |
| 49 | 49 | ||
| 50 | config GENERIC_HARDIRQS | ||
| 51 | bool | ||
| 52 | default y | ||
| 53 | |||
| 54 | config HARDIRQS_SW_RESEND | ||
| 55 | bool | ||
| 56 | default y | ||
| 57 | |||
| 58 | config GENERIC_IRQ_PROBE | ||
| 59 | bool | ||
| 60 | default y | ||
| 61 | |||
| 50 | config RWSEM_GENERIC_SPINLOCK | 62 | config RWSEM_GENERIC_SPINLOCK |
| 51 | bool | 63 | bool |
| 52 | default y | 64 | default y |
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 1ec3f7faa259..e8e90346f11c 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
| 40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
| 41 | #include <linux/interrupt.h> | ||
| 41 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
| 42 | 43 | ||
| 43 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 4d31cf8d02d5..c3d4e94ef5bf 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
| 27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
| 28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
| 29 | #include <linux/irq.h> | ||
| 29 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
| 30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 31 | #include <linux/random.h> | 32 | #include <linux/random.h> |
| @@ -37,192 +38,18 @@ | |||
| 37 | #include <linux/kallsyms.h> | 38 | #include <linux/kallsyms.h> |
| 38 | #include <linux/proc_fs.h> | 39 | #include <linux/proc_fs.h> |
| 39 | 40 | ||
| 40 | #include <asm/irq.h> | ||
| 41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
| 42 | #include <asm/mach/irq.h> | ||
| 43 | #include <asm/mach/time.h> | 42 | #include <asm/mach/time.h> |
| 44 | 43 | ||
| 45 | /* | 44 | /* |
| 46 | * Maximum IRQ count. Currently, this is arbitary. However, it should | ||
| 47 | * not be set too low to prevent false triggering. Conversely, if it | ||
| 48 | * is set too high, then you could miss a stuck IRQ. | ||
| 49 | * | ||
| 50 | * Maybe we ought to set a timer and re-enable the IRQ at a later time? | ||
| 51 | */ | ||
| 52 | #define MAX_IRQ_CNT 100000 | ||
| 53 | |||
| 54 | static int noirqdebug __read_mostly; | ||
| 55 | static volatile unsigned long irq_err_count; | ||
| 56 | static DEFINE_SPINLOCK(irq_controller_lock); | ||
| 57 | static LIST_HEAD(irq_pending); | ||
| 58 | |||
| 59 | struct irqdesc irq_desc[NR_IRQS]; | ||
| 60 | void (*init_arch_irq)(void) __initdata = NULL; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * No architecture-specific irq_finish function defined in arm/arch/irqs.h. | 45 | * No architecture-specific irq_finish function defined in arm/arch/irqs.h. |
| 64 | */ | 46 | */ |
| 65 | #ifndef irq_finish | 47 | #ifndef irq_finish |
| 66 | #define irq_finish(irq) do { } while (0) | 48 | #define irq_finish(irq) do { } while (0) |
| 67 | #endif | 49 | #endif |
| 68 | 50 | ||
| 69 | /* | 51 | void (*init_arch_irq)(void) __initdata = NULL; |
| 70 | * Dummy mask/unmask handler | 52 | unsigned long irq_err_count; |
| 71 | */ | ||
| 72 | void dummy_mask_unmask_irq(unsigned int irq) | ||
| 73 | { | ||
| 74 | } | ||
| 75 | |||
| 76 | irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs) | ||
| 77 | { | ||
| 78 | return IRQ_NONE; | ||
| 79 | } | ||
| 80 | |||
| 81 | void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) | ||
| 82 | { | ||
| 83 | irq_err_count++; | ||
| 84 | printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct irqchip bad_chip = { | ||
| 88 | .ack = dummy_mask_unmask_irq, | ||
| 89 | .mask = dummy_mask_unmask_irq, | ||
| 90 | .unmask = dummy_mask_unmask_irq, | ||
| 91 | }; | ||
| 92 | |||
| 93 | static struct irqdesc bad_irq_desc = { | ||
| 94 | .chip = &bad_chip, | ||
| 95 | .handle = do_bad_IRQ, | ||
| 96 | .pend = LIST_HEAD_INIT(bad_irq_desc.pend), | ||
| 97 | .disable_depth = 1, | ||
| 98 | }; | ||
| 99 | |||
| 100 | #ifdef CONFIG_SMP | ||
| 101 | void synchronize_irq(unsigned int irq) | ||
| 102 | { | ||
| 103 | struct irqdesc *desc = irq_desc + irq; | ||
| 104 | |||
| 105 | while (desc->running) | ||
| 106 | barrier(); | ||
| 107 | } | ||
| 108 | EXPORT_SYMBOL(synchronize_irq); | ||
| 109 | |||
| 110 | #define smp_set_running(desc) do { desc->running = 1; } while (0) | ||
| 111 | #define smp_clear_running(desc) do { desc->running = 0; } while (0) | ||
| 112 | #else | ||
| 113 | #define smp_set_running(desc) do { } while (0) | ||
| 114 | #define smp_clear_running(desc) do { } while (0) | ||
| 115 | #endif | ||
| 116 | |||
| 117 | /** | ||
| 118 | * disable_irq_nosync - disable an irq without waiting | ||
| 119 | * @irq: Interrupt to disable | ||
| 120 | * | ||
| 121 | * Disable the selected interrupt line. Enables and disables | ||
| 122 | * are nested. We do this lazily. | ||
| 123 | * | ||
| 124 | * This function may be called from IRQ context. | ||
| 125 | */ | ||
| 126 | void disable_irq_nosync(unsigned int irq) | ||
| 127 | { | ||
| 128 | struct irqdesc *desc = irq_desc + irq; | ||
| 129 | unsigned long flags; | ||
| 130 | |||
| 131 | spin_lock_irqsave(&irq_controller_lock, flags); | ||
| 132 | desc->disable_depth++; | ||
| 133 | list_del_init(&desc->pend); | ||
| 134 | spin_unlock_irqrestore(&irq_controller_lock, flags); | ||
| 135 | } | ||
| 136 | EXPORT_SYMBOL(disable_irq_nosync); | ||
| 137 | |||
| 138 | /** | ||
| 139 | * disable_irq - disable an irq and wait for completion | ||
| 140 | * @irq: Interrupt to disable | ||
| 141 | * | ||
| 142 | * Disable the selected interrupt line. Enables and disables | ||
| 143 | * are nested. This functions waits for any pending IRQ | ||
| 144 | * handlers for this interrupt to complete before returning. | ||
| 145 | * If you use this function while holding a resource the IRQ | ||
| 146 | * handler may need you will deadlock. | ||
| 147 | * | ||
| 148 | * This function may be called - with care - from IRQ context. | ||
| 149 | */ | ||
| 150 | void disable_irq(unsigned int irq) | ||
| 151 | { | ||
| 152 | struct irqdesc *desc = irq_desc + irq; | ||
| 153 | |||
| 154 | disable_irq_nosync(irq); | ||
| 155 | if (desc->action) | ||
| 156 | synchronize_irq(irq); | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL(disable_irq); | ||
| 159 | |||
| 160 | /** | ||
| 161 | * enable_irq - enable interrupt handling on an irq | ||
| 162 | * @irq: Interrupt to enable | ||
| 163 | * | ||
| 164 | * Re-enables the processing of interrupts on this IRQ line. | ||
| 165 | * Note that this may call the interrupt handler, so you may | ||
| 166 | * get unexpected results if you hold IRQs disabled. | ||
| 167 | * | ||
| 168 | * This function may be called from IRQ context. | ||
| 169 | */ | ||
| 170 | void enable_irq(unsigned int irq) | ||
