aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-07-02 18:07:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-02 18:07:45 -0400
commitb4b9034132c7e1e4474999e688dd7d03b7d97a99 (patch)
treec02c571b9e0e59b9ffa18baae23c83f09ff07adb
parenta8c4c20dfa8b28a3c99e33c639d9c2ea5657741e (diff)
parent07d265dd59456f702b7d2a1ac471f06ee4adc9ef (diff)
Merge branch 'genirq' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'genirq' of master.kernel.org:/home/rmk/linux-2.6-arm: (24 commits) [ARM] 3683/2: ARM: Convert at91rm9200 to generic irq handling [ARM] 3682/2: ARM: Convert ixp4xx to generic irq handling [ARM] 3702/1: ARM: Convert ixp23xx to generic irq handling [ARM] 3701/1: ARM: Convert plat-omap to generic irq handling [ARM] 3700/1: ARM: Convert lh7a40x to generic irq handling [ARM] 3699/1: ARM: Convert s3c2410 to generic irq handling [ARM] 3698/1: ARM: Convert sa1100 to generic irq handling [ARM] 3697/1: ARM: Convert shark to generic irq handling [ARM] 3696/1: ARM: Convert clps711x to generic irq handling [ARM] 3694/1: ARM: Convert ecard driver to generic irq handling [ARM] 3693/1: ARM: Convert omap1 to generic irq handling [ARM] 3691/1: ARM: Convert imx to generic irq handling [ARM] 3688/1: ARM: Convert clps7500 to generic irq handling [ARM] 3687/1: ARM: Convert integrator to generic irq handling [ARM] 3685/1: ARM: Convert pxa to generic irq handling [ARM] 3684/1: ARM: Convert l7200 to generic irq handling [ARM] 3681/1: ARM: Convert ixp2000 to generic irq handling [ARM] 3680/1: ARM: Convert footbridge to generic irq handling [ARM] 3695/1: ARM drivers/pcmcia: Fixup includes [ARM] 3689/1: ARM drivers/input/touchscreen: Fixup includes ... Manual conflict resolved in kernel/irq/handle.c (butt-ugly ARM tickless code).
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/common/gic.c18
-rw-r--r--arch/arm/common/sa1111.c6
-rw-r--r--arch/arm/common/time-acorn.c1
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/arm/kernel/fiq.c1
-rw-r--r--arch/arm/kernel/irq.c951
-rw-r--r--arch/arm/mach-at91rm9200/at91rm9200_time.c2
-rw-r--r--arch/arm/mach-at91rm9200/gpio.c11
-rw-r--r--arch/arm/mach-clps711x/time.c1
-rw-r--r--arch/arm/mach-clps7500/core.c1
-rw-r--r--arch/arm/mach-footbridge/dc21285-timer.c1
-rw-r--r--arch/arm/mach-footbridge/isa-timer.c1
-rw-r--r--arch/arm/mach-imx/time.c1
-rw-r--r--arch/arm/mach-integrator/core.c1
-rw-r--r--arch/arm/mach-ixp2000/core.c3
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c2
-rw-r--r--arch/arm/mach-ixp23xx/core.c2
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c10
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c2
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-power.c4
-rw-r--r--arch/arm/mach-l7200/core.c1
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c1
-rw-r--r--arch/arm/mach-lh7a40x/time.c1
-rw-r--r--arch/arm/mach-omap1/board-osk.c2
-rw-r--r--arch/arm/mach-omap1/serial.c1
-rw-r--r--arch/arm/mach-pxa/idp.c1
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c2
-rw-r--r--arch/arm/mach-s3c2410/bast-irq.c6
-rw-r--r--arch/arm/mach-s3c2410/time.c1
-rw-r--r--arch/arm/mach-sa1100/cerf.c1
-rw-r--r--arch/arm/mach-sa1100/h3600.c2
-rw-r--r--arch/arm/mach-sa1100/irq.c3
-rw-r--r--arch/arm/mach-sa1100/pleb.c1
-rw-r--r--arch/arm/mach-sa1100/time.c1
-rw-r--r--arch/arm/mach-shark/core.c1
-rw-r--r--arch/arm/plat-omap/dma.c2
-rw-r--r--arch/arm/plat-omap/gpio.c2
-rw-r--r--drivers/input/touchscreen/corgi_ts.c2
-rw-r--r--drivers/pcmcia/soc_common.c2
-rw-r--r--include/asm-arm/dyntick.h6
-rw-r--r--include/asm-arm/hw_irq.h9
-rw-r--r--include/asm-arm/irq.h22
-rw-r--r--include/asm-arm/mach/irq.h135
-rw-r--r--include/linux/irq.h3
-rw-r--r--kernel/irq/chip.c15
-rw-r--r--kernel/irq/handle.c29
51 files changed, 208 insertions, 1082 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 919d8b92aaa4..f81a62380add 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
50config GENERIC_HARDIRQS
51 bool
52 default y
53
54config HARDIRQS_SW_RESEND
55 bool
56 default y
57
58config GENERIC_IRQ_PROBE
59 bool
60 default y
61
50config RWSEM_GENERIC_SPINLOCK 62config RWSEM_GENERIC_SPINLOCK
51 bool 63 bool
52 default y 64 default y
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index c02dc8116a18..f3c1ebfdd0aa 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -33,6 +33,7 @@
33 33
34static void __iomem *gic_dist_base; 34static void __iomem *gic_dist_base;
35static void __iomem *gic_cpu_base; 35static void __iomem *gic_cpu_base;
36static DEFINE_SPINLOCK(irq_controller_lock);
36 37
37/* 38/*
38 * Routines to acknowledge, disable and enable interrupts 39 * Routines to acknowledge, disable and enable interrupts
@@ -52,32 +53,45 @@ static void __iomem *gic_cpu_base;
52static void gic_ack_irq(unsigned int irq) 53static void gic_ack_irq(unsigned int irq)
53{ 54{
54 u32 mask = 1 << (irq % 32); 55 u32 mask = 1 << (irq % 32);
56
57 spin_lock(&irq_controller_lock);
55 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 58 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
56 writel(irq, gic_cpu_base + GIC_CPU_EOI); 59 writel(irq, gic_cpu_base + GIC_CPU_EOI);
60 spin_unlock(&irq_controller_lock);
57} 61}
58 62
59static void gic_mask_irq(unsigned int irq) 63static void gic_mask_irq(unsigned int irq)
60{ 64{
61 u32 mask = 1 << (irq % 32); 65 u32 mask = 1 << (irq % 32);
66
67 spin_lock(&irq_controller_lock);
62 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 68 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
69 spin_unlock(&irq_controller_lock);
63} 70}
64 71
65static void gic_unmask_irq(unsigned int irq) 72static void gic_unmask_irq(unsigned int irq)
66{ 73{
67 u32 mask = 1 << (irq % 32); 74 u32 mask = 1 << (irq % 32);
75
76 spin_lock(&irq_controller_lock);
68 writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4); 77 writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
78 spin_unlock(&irq_controller_lock);
69} 79}
70 80
71#ifdef CONFIG_SMP 81#ifdef CONFIG_SMP
72static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu) 82static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
73{ 83{
74 void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3); 84 void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
75 unsigned int shift = (irq % 4) * 8; 85 unsigned int shift = (irq % 4) * 8;
86 unsigned int cpu = first_cpu(mask_val);
76 u32 val; 87 u32 val;
77 88
89 spin_lock(&irq_controller_lock);
90 irq_desc[irq].cpu = cpu;
78 val = readl(reg) & ~(0xff << shift); 91 val = readl(reg) & ~(0xff << shift);
79 val |= 1 << (cpu + shift); 92 val |= 1 << (cpu + shift);
80 writel(val, reg); 93 writel(val, reg);
94 spin_unlock(&irq_controller_lock);
81} 95}
82#endif 96#endif
83 97
@@ -86,7 +100,7 @@ static struct irqchip gic_chip = {
86 .mask = gic_mask_irq, 100 .mask = gic_mask_irq,
87 .unmask = gic_unmask_irq, 101 .unmask = gic_unmask_irq,
88#ifdef CONFIG_SMP 102#ifdef CONFIG_SMP
89 .set_cpu = gic_set_cpu, 103 .set_affinity = gic_set_cpu,
90#endif 104#endif
91}; 105};
92 106
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index fe06a36a2130..1cdb26a47e1f 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -150,7 +150,7 @@ static void
150sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) 150sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
151{ 151{
152 unsigned int stat0, stat1, i; 152 unsigned int stat0, stat1, i;
153 void __iomem *base = desc->data; 153 void __iomem *base = get_irq_data(irq);
154 154
155 stat0 = sa1111_readl(base + SA1111_INTSTATCLR0); 155 stat0 = sa1111_readl(base + SA1111_INTSTATCLR0);
156 stat1 = sa1111_readl(base + SA1111_INTSTATCLR1); 156 stat1 = sa1111_readl(base + SA1111_INTSTATCLR1);
@@ -168,11 +168,11 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
168 168
169 for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1) 169 for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
170 if (stat0 & 1) 170 if (stat0 & 1)
171 do_edge_IRQ(i, irq_desc + i, regs); 171 handle_edge_irq(i, irq_desc + i, regs);
172 172
173 for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1) 173 for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
174 if (stat1 & 1) 174 if (stat1 & 1)
175 do_edge_IRQ(i, irq_desc + i, regs); 175 handle_edge_irq(i, irq_desc + i, regs);
176 176
177 /* For level-based interrupts */ 177 /* For level-based interrupts */
178 desc->chip->unmask(irq); 178 desc->chip->unmask(irq);
diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c
index 486add853fb8..31b65e2231d9 100644
--- a/arch/arm/common/time-acorn.c
+++ b/arch/arm/common/time-acorn.c
@@ -16,6 +16,7 @@
16#include <linux/timex.h> 16#include <linux/timex.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/irq.h>
19 20
20#include <asm/hardware.h> 21#include <asm/hardware.h>
21#include <asm/io.h> 22#include <asm/io.h>
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 68a257666d95..ab4ad9562eee 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -619,7 +619,7 @@ ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
619 ecard_t *ec = slot_to_ecard(slot); 619 ecard_t *ec = slot_to_ecard(slot);
620 620
621 if (ec->claimed) { 621 if (ec->claimed) {
622 struct irqdesc *d = irqdesc + ec->irq; 622 struct irq_desc *d = irq_desc + ec->irq;
623 /* 623 /*
624 * this ugly code is so that we can operate a 624 * this ugly code is so that we can operate a
625 * prioritorising system: 625 * prioritorising system:
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
54static int noirqdebug __read_mostly;
55static volatile unsigned long irq_err_count;
56static DEFINE_SPINLOCK(irq_controller_lock);
57static LIST_HEAD(irq_pending);
58
59struct irqdesc irq_desc[NR_IRQS];
60void (*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/* 51void (*init_arch_irq)(void) __initdata = NULL;
70 * Dummy mask/unmask handler 52unsigned long irq_err_count;
71 */
72void dummy_mask_unmask_irq(unsigned int irq)
73{
74}
75
76irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs)
77{
78 return IRQ_NONE;
79}
80
81void 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
87static struct irqchip bad_chip = {
88 .ack = dummy_mask_unmask_irq,
89 .mask = dummy_mask_unmask_irq,
90 .unmask = dummy_mask_unmask_irq,
91};
92
93static 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
101void synchronize_irq(unsigned int irq)
102{
103 struct irqdesc *desc = irq_desc + irq;
104
105 while (desc->running)
106 barrier();
107}
108EXPORT_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 */
126void 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}
136EXPORT_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 */
150void 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}
158EXPORT_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 */
170void enable_irq(unsigned int irq)
171{
172 struct irqdesc *desc = irq_desc + irq;
173 unsigned long flags;
174
175 spin_lock_irqsave(&irq_controller_lock, flags);
176 if (unlikely(!desc->disable_depth)) {
177 printk("enable_irq(%u) unbalanced from %p\n", irq,
178 __builtin_return_address(0));
179 } else if (!--desc->disable_depth) {
180 desc->probing = 0;
181 desc->chip->unmask(irq);
182
183 /*
184 * If the interrupt is waiting to be processed,
185 * try to re-run it. We can't directly run it
186 * from here since the caller might be in an
187 * interrupt-protected region.
188 */
189 if (desc->pending && list_empty(&desc->pend)) {
190 desc->pending = 0;
191 if (!desc->chip->retrigger ||
192 desc->chip->retrigger(irq))
193 list_add(&desc->pend, &irq_pending);
194 }
195 }
196 spin_unlock_irqrestore(&irq_controller_lock, flags);
197}
198EXPORT_SYMBOL(enable_irq);
199
200/*
201 * Enable wake on selected irq
202 */
203void enable_irq_wake(unsigned int irq)
204{
205 struct irqdesc *desc = irq_desc + irq;
206 unsigned long flags;
207
208 spin_lock_irqsave(&irq_controller_lock, flags);
209 if (desc->chip->set_wake)
210 desc->chip->set_wake(irq, 1);
211 spin_unlock_irqrestore(&irq_controller_lock, flags);
212}
213EXPORT_SYMBOL(enable_irq_wake);
214
215void disable_irq_wake(unsigned int irq)
216{
217 struct irqdesc *desc = irq_desc + irq;
218 unsigned long flags;
219
220 spin_lock_irqsave(&irq_controller_lock, flags);
221 if (desc->chip->set_wake)
222 desc->chip->set_wake(irq, 0);
223 spin_unlock_irqrestore(&irq_controller_lock, flags);
224}
225EXPORT_SYMBOL(disable_irq_wake);
226 53
227int show_interrupts(struct seq_file *p, void *v) 54int show_interrupts(struct seq_file *p, void *v)
228{ 55{
@@ -242,8 +69,8 @@ int show_interrupts(struct seq_file *p, void *v)
242 } 69 }
243 70
244 if (i < NR_IRQS) { 71 if (i < NR_IRQS) {
245 spin_lock_irqsave(&irq_controller_lock, flags); 72 spin_lock_irqsave(&irq_desc[i].lock, flags);
246 action = irq_desc[i].action; 73 action = irq_desc[i].action;
247 if (!action) 74 if (!action)
248 goto unlock; 75 goto unlock;
249 76
@@ -256,7 +83,7 @@ int show_interrupts(struct seq_file *p, void *v)
256 83
257 seq_putc(p, '\n'); 84 seq_putc(p, '\n');
258unlock: 85unlock:
259 spin_unlock_irqrestore(&irq_controller_lock, flags); 86 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
260 } else if (i == NR_IRQS) { 87 } else if (i == NR_IRQS) {
261#ifdef CONFIG_ARCH_ACORN 88#ifdef CONFIG_ARCH_ACORN
262 show_fiq_list(p, v); 89 show_fiq_list(p, v);
@@ -270,267 +97,11 @@ unlock:
270 return 0; 97 return 0;
271} 98}
272 99
273/* 100/* Handle bad interrupts */
274 * IRQ lock detection. 101static struct irq_desc bad_irq_desc = {
275 * 102 .handle_irq = handle_bad_irq,
276 * Hopefully, this should get us out of a few locked situations. 103 .lock = SPIN_LOCK_UNLOCKED
277 * However, it may take a while for this to happen, since we need 104};
278 * a large number if IRQs to appear in the same jiffie with the
279 * same instruction pointer (or within 2 instructions).
280 */
281static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs)
282{
283 unsigned long instr_ptr = instruction_pointer(regs);
284
285 if (desc->lck_jif == jiffies &&
286 desc->lck_pc >= instr_ptr && desc->lck_pc < instr_ptr + 8) {
287 desc->lck_cnt += 1;
288
289 if (desc->lck_cnt > MAX_IRQ_CNT) {
290 printk(KERN_ERR "IRQ LOCK: IRQ%d is locking the system, disabled\n", irq);
291 return 1;
292 }
293 } else {
294 desc->lck_cnt = 0;
295 desc->lck_pc = instruction_pointer(regs);
296 desc->lck_jif = jiffies;
297 }
298 return 0;
299}
300
301static void
302report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int ret)
303{
304 static int count = 100;
305 struct irqaction *action;
306
307 if (noirqdebug)
308 return;
309
310 if (ret != IRQ_HANDLED && ret != IRQ_NONE) {
311 if (!count)
312 return;
313 count--;
314 printk("irq%u: bogus retval mask %x\n", irq, ret);
315 } else {
316 desc->irqs_unhandled++;
317 if (desc->irqs_unhandled <= 99900)
318 return;
319 desc->irqs_unhandled = 0;
320 printk("irq%u: nobody cared\n", irq);
321 }
322 show_regs(regs);
323 dump_stack();
324 printk(KERN_ERR "handlers:");
325 action = desc->action;
326 do {
327 printk("\n" KERN_ERR "[<%p>]", action->handler);
328 print_symbol(" (%s)", (unsigned long)action->handler);
329 action = action->next;
330 } while (action);
331 printk("\n");
332}
333
334static int
335__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
336{
337 unsigned int status;
338 int ret, retval = 0;
339
340 spin_unlock(&irq_controller_lock);
341
342#ifdef CONFIG_NO_IDLE_HZ
343 if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
344 spin_lock(&system_timer->dyn_tick->lock);
345 if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
346 system_timer->dyn_tick->handler(irq, 0, regs);
347 spin_unlock(&system_timer->dyn_tick->lock);
348 }
349#endif
350
351 if (!(action->flags & SA_INTERRUPT))
352 local_irq_enable();
353
354 status = 0;
355 do {
356 ret = action->handler(irq, action->dev_id, regs);
357 if (ret == IRQ_HANDLED)
358 status |= action->flags;
359 retval |= ret;
360 action = action->next;
361 } while (action);
362
363 if (status & SA_SAMPLE_RANDOM)
364 add_interrupt_randomness(irq);
365
366 spin_lock_irq(&irq_controller_lock);
367
368 return retval;
369}
370
371/*
372 * This is for software-decoded IRQs. The caller is expected to
373 * handle the ack, clear, mask and unmask issues.
374 */
375void
376do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
377{
378 struct irqaction *action;
379 const unsigned int cpu = smp_processor_id();
380
381 desc->triggered = 1;
382
383 kstat_cpu(cpu).irqs[irq]++;
384
385 smp_set_running(desc);
386
387 action = desc->action;
388 if (action) {
389 int ret = __do_irq(irq, action, regs);
390 if (ret != IRQ_HANDLED)
391 report_bad_irq(irq, regs, desc, ret);
392 }
393
394 smp_clear_running(desc);
395}
396
397/*
398 * Most edge-triggered IRQ implementations seem to take a broken
399 * approach to this. Hence the complexity.
400 */
401void
402do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
403{
404 const unsigned int cpu = smp_processor_id();
405
406 desc->triggered = 1;
407
408 /*
409 * If we're currently running this IRQ, or its disabled,
410 * we shouldn't process the IRQ. Instead, turn on the
411 * hardware masks.
412 */
413 if (unlikely(desc->running || desc->disable_depth))
414 goto running;
415
416 /*
417 * Acknowledge and clear the IRQ, but don't mask it.
418 */
419 desc->chip->ack(irq);
420
421 /*
422 * Mark the IRQ currently in progress.
423 */
424 desc->running = 1;
425
426 kstat_cpu(cpu).irqs[irq]++;
427
428 do {
429 struct irqaction *action;
430
431 action = desc->action;
432 if (!action)
433 break;
434
435 if (desc->pending && !desc->disable_depth) {
436 desc->pending = 0;
437 desc->chip->unmask(irq);
438 }
439
440 __do_irq(irq, action, regs);
441 } while (desc->pending && !desc->disable_depth);
442
443 desc->running = 0;
444
445 /*
446 * If we were disabled or freed, shut down the handler.
447 */
448 if (likely(desc->action && !check_irq_lock(desc, irq, regs)))
449 return;
450
451 running:
452 /*
453 * We got another IRQ while this one was masked or
454 * currently running. Delay it.
455 */
456 desc->pending = 1;
457 desc->chip->mask(irq);
458 desc->chip->ack(irq);
459}
460
461/*
462 * Level-based IRQ handler. Nice and simple.
463 */
464void
465do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
466{
467 struct irqaction *action;
468 const unsigned int cpu = smp_processor_id();
469
470 desc->triggered = 1;
471
472 /*
473 * Acknowledge, clear _AND_ disable the interrupt.
474 */
475 desc->chip->ack(irq);
476
477 if (likely(!desc->disable_depth)) {
478 kstat_cpu(cpu).irqs[irq]++;
479
480 smp_set_running(desc);
481
482 /*
483 * Return with this interrupt masked if no action
484 */
485 action = desc->action;
486 if (action) {
487 int ret = __do_irq(irq, desc->action, regs);
488
489 if (ret != IRQ_HANDLED)
490 report_bad_irq(irq, regs, desc, ret);
491
492 if (likely(!desc->disable_depth &&
493 !check_irq_lock(desc, irq, regs)))
494 desc->chip->unmask(irq);
495 }
496
497 smp_clear_running(desc);
498 }
499}
500
501static void do_pending_irqs(struct pt_regs *regs)
502{
503 struct list_head head, *l, *n;
504
505 do {
506 struct irqdesc *desc;
507
508 /*
509 * First, take the pending interrupts off the list.
510 * The act of calling the handlers may add some IRQs
511 * back onto the list.
512 */
513 head = irq_pending;
514 INIT_LIST_HEAD(&irq_pending);
515 head.next->prev = &head;
516 head.prev->next = &head;
517
518 /*
519 * Now run each entry. We must delete it from our
520 * list before calling the handler.
521 */
522 list_for_each_safe(l, n, &head) {
523 desc = list_entry(l, struct irqdesc, pend);
524 list_del_init(&desc->pend);
525 desc_handle_irq(desc - irq_desc, desc, regs);
526 }
527
528 /*
529 * The list must be empty.
530 */
531 BUG_ON(!list_empty(&head));
532 } while (!list_empty(&irq_pending));
533}
534 105
535/* 106/*
536 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not 107 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
@@ -549,96 +120,15 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
549 desc = &bad_irq_desc; 120 desc = &bad_irq_desc;
550 121
551 irq_enter(); 122 irq_enter();
552 spin_lock(&irq_controller_lock);
553 desc_handle_irq(irq, desc, regs);
554 123
555 /* 124 desc_handle_irq(irq, desc, regs);
556 * Now re-run any pending interrupts.
557 */
558 if (!list_empty(&irq_pending))
559 do_pending_irqs(regs);
560 125
126 /* AT91 specific workaround */
561 irq_finish(irq); 127 irq_finish(irq);
562 128
563 spin_unlock(&irq_controller_lock);
564 irq_exit(); 129 irq_exit();
565} 130}
566 131
567void __set_irq_handler(unsigned int irq, irq_handler_t handle, int is_chained)
568{
569 struct irqdesc *desc;
570 unsigned long flags;
571
572 if (irq >= NR_IRQS) {
573 printk(KERN_ERR "Trying to install handler for IRQ%d\n", irq);
574 return;
575 }
576
577 if (handle == NULL)
578 handle = do_bad_IRQ;
579
580 desc = irq_desc + irq;
581
582 if (is_chained && desc->chip == &bad_chip)
583 printk(KERN_WARNING "Trying to install chained handler for IRQ%d\n", irq);
584
585 spin_lock_irqsave(&irq_controller_lock, flags);
586 if (handle == do_bad_IRQ) {
587 desc->chip->mask(irq);
588 desc->chip->ack(irq);
589 desc->disable_depth = 1;
590 }
591 desc->handle = handle;
592 if (handle != do_bad_IRQ && is_chained) {
593 desc->valid = 0;
594 desc->probe_ok = 0;
595 desc->disable_depth = 0;
596 desc->chip->unmask(irq);
597 }
598 spin_unlock_irqrestore(&irq_controller_lock, flags);
599}
600
601void set_irq_chip(unsigned int irq, struct irqchip *chip)
602{
603 struct irqdesc *desc;
604 unsigned long flags;
605
606 if (irq >= NR_IRQS) {
607 printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq);
608 return;
609 }
610
611 if (chip == NULL)
612 chip = &bad_chip;
613
614 desc = irq_desc + irq;
615 spin_lock_irqsave(&irq_controller_lock, flags);
616 desc->chip = chip;
617 spin_unlock_irqrestore(&irq_controller_lock, flags);
618}
619
620int set_irq_type(unsigned int irq, unsigned int type)
621{
622 struct irqdesc *desc;
623 unsigned long flags;
624 int ret = -ENXIO;
625
626 if (irq >= NR_IRQS) {
627 printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
628 return -ENODEV;
629 }
630
631 desc = irq_desc + irq;
632 if (desc->chip->set_type) {
633 spin_lock_irqsave(&irq_controller_lock, flags);
634 ret = desc->chip->set_type(irq, type);
635 spin_unlock_irqrestore(&irq_controller_lock, flags);
636 }
637
638 return ret;
639}
640EXPORT_SYMBOL(set_irq_type);
641
642void set_irq_flags(unsigned int irq, unsigned int iflags) 132void set_irq_flags(unsigned int irq, unsigned int iflags)
643{ 133{
644 struct irqdesc *desc; 134 struct irqdesc *desc;
@@ -650,421 +140,32 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
650 } 140 }
651 141
652 desc = irq_desc + irq; 142 desc = irq_desc + irq;
653 spin_lock_irqsave(&irq_controller_lock, flags); 143 spin_lock_irqsave(&desc->lock, flags);
654 desc->valid = (iflags & IRQF_VALID) != 0; 144 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
655 desc->probe_ok = (iflags & IRQF_PROBE) != 0; 145 if (iflags & IRQF_VALID)
656 desc->noautoenable = (iflags & IRQF_NOAUTOEN) != 0; 146 desc->status &= ~IRQ_NOREQUEST;
657 spin_unlock_irqrestore(&irq_controller_lock, flags); 147 if (iflags & IRQF_PROBE)
658} 148 desc->status &= ~IRQ_NOPROBE;
659 149 if (!(iflags & IRQF_NOAUTOEN))
660int setup_irq(unsigned int irq, struct irqaction *new) 150 desc->status &= ~IRQ_NOAUTOEN;
661{ 151 spin_unlock_irqrestore(&desc->lock, flags);
662 int shared = 0;
663 struct irqaction *old, **p;
664 unsigned long flags;
665 struct irqdesc *desc;
666
667 /*
668 * Some drivers like serial.c use request_irq() heavily,
669 * so we have to be careful not to interfere with a
670 * running system.
671 */
672 if (new->flags & SA_SAMPLE_RANDOM) {
673 /*
674 * This function might sleep, we want to call it first,
675 * outside of the atomic block.
676 * Yes, this might clear the entropy pool if the wrong
677 * driver is attempted to be loaded, without actually
678 * installing a new handler, but is this really a problem,
679 * only the sysadmin is able to do this.
680 */
681 rand_initialize_irq(irq);
682 }
683
684 /*
685 * The following block of code has to be executed atomically
686 */
687 desc = irq_desc + irq;
688 spin_lock_irqsave(&irq_controller_lock, flags);
689 p = &desc->action;
690 if ((old = *p) != NULL) {
691 /*
692 * Can't share interrupts unless both agree to and are
693 * the same type.
694 */
695 if (!(old->flags & new->flags & SA_SHIRQ) ||
696 (~old->flags & new->flags) & SA_TRIGGER_MASK) {
697 spin_unlock_irqrestore(&irq_controller_lock, flags);
698 return -EBUSY;
699 }
700
701 /* add new interrupt at end of irq queue */
702 do {
703 p = &old->next;
704 old = *p;
705 } while (old);
706 shared = 1;
707 }
708
709 *p = new;
710
711 if (!shared) {
712 desc->probing = 0;
713 desc->running = 0;
714 desc->pending = 0;
715 desc->disable_depth = 1;
716
717 if (new->flags & SA_TRIGGER_MASK &&
718 desc->chip->set_type) {
719 unsigned int type = new->flags & SA_TRIGGER_MASK;
720 desc->chip->set_type(irq, type);
721 }
722
723 if (!desc->noautoenable) {
724 desc->disable_depth = 0;
725 desc->chip->unmask(irq);
726 }
727 }
728
729 spin_unlock_irqrestore(&irq_controller_lock, flags);
730 return 0;
731}
732
733/**
734 * request_irq - allocate an interrupt line
735 * @irq: Interrupt line to allocate
736 * @handler: Function to be called when the IRQ occurs
737 * @irqflags: Interrupt type flags
738 * @devname: An ascii name for the claiming device
739 * @dev_id: A cookie passed back to the handler function
740 *
741 * This call allocates interrupt resources and enables the
742 * interrupt line and IRQ handling. From the point this
743 * call is made your handler function may be invoked. Since
744 * your handler function must clear any interrupt the board
745 * raises, you must take care both to initialise your hardware
746 * and to set up the interrupt handler in the right order.
747 *
748 * Dev_id must be globally unique. Normally the address of the
749 * device data structure is used as the cookie. Since the handler
750 * receives this value it makes sense to use it.
751 *
752 * If your interrupt is shared you must pass a non NULL dev_id
753 * as this is required when freeing the interrupt.
754 *
755 * Flags:
756 *
757 * SA_SHIRQ Interrupt is shared
758 *
759 * SA_INTERRUPT Disable local interrupts while processing
760 *
761 * SA_SAMPLE_RANDOM The interrupt can be used for entropy
762 *
763 */
764int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
765 unsigned long irq_flags, const char * devname, void *dev_id)
766{
767 unsigned long retval;
768 struct irqaction *action;
769
770 if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||
771 (irq_flags & SA_SHIRQ && !dev_id))
772 return -EINVAL;
773
774 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
775 if (!action)
776 return -ENOMEM;
777
778 action->handler = handler;
779 action->flags = irq_flags;
780 cpus_clear(action->mask);
781 action->name = devname;
782 action->next = NULL;
783 action->dev_id = dev_id;
784
785 retval = setup_irq(irq, action);
786
787 if (retval)
788 kfree(action);
789 return retval;
790}
791
792EXPORT_SYMBOL(request_irq);
793
794/**
795 * free_irq - free an interrupt
796 * @irq: Interrupt line to free
797 * @dev_id: Device identity to free
798 *
799 * Remove an interrupt handler. The handler is removed and if the
800 * interrupt line is no longer in use by any driver it is disabled.
801 * On a shared IRQ the caller must ensure the interrupt is disabled
802 * on the card it drives before calling this function.
803 *
804 * This function must not be called from interrupt context.
805 */
806void free_irq(unsigned int irq, void *dev_id)
807{
808 struct irqaction * action, **p;
809 unsigned long flags;
810
811 if (irq >= NR_IRQS || !irq_desc[irq].valid) {
812 printk(KERN_ERR "Trying to free IRQ%d\n",irq);
813 dump_stack();
814 return;
815 }
816
817 spin_lock_irqsave(&irq_controller_lock, flags);
818 for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
819 if (action->dev_id != dev_id)
820 continue;
821
822 /* Found it - now free it */
823 *p = action->next;
824 break;
825 }
826 spin_unlock_irqrestore(&irq_controller_lock, flags);
827
828 if (!action) {
829 printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
830 dump_stack();
831 } else {
832 synchronize_irq(irq);
833 kfree(action);
834 }
835}
836
837EXPORT_SYMBOL(free_irq);
838
839static DECLARE_MUTEX(probe_sem);
840
841/* Start the interrupt probing. Unlike other architectures,
842 * we don't return a mask of interrupts from probe_irq_on,
843 * but return the number of interrupts enabled for the probe.
844 * The interrupts which have been enabled for probing is
845 * instead recorded in the irq_desc structure.
846 */
847unsigned long probe_irq_on(void)
848{
849 unsigned int i, irqs = 0;
850 unsigned long delay;
851
852 down(&probe_sem);
853
854 /*
855 * first snaffle up any unassigned but
856 * probe-able interrupts
857 */
858 spin_lock_irq(&irq_controller_lock);
859 for (i = 0; i < NR_IRQS; i++) {
860 if (!irq_desc[i].probe_ok || irq_desc[i].action)
861 continue;
862
863 irq_desc[i].probing = 1;
864 irq_desc[i].triggered = 0;
865 if (irq_desc[i].chip->set_type)
866 irq_desc[i].chip->set_type(i, IRQT_PROBE);
867 irq_desc[i].chip->unmask(i);
868 irqs += 1;
869 }
870 spin_unlock_irq(&irq_controller_lock);
871
872 /*
873 * wait for spurious interrupts to mask themselves out again
874 */
875 for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
876 /* min 100ms delay */;
877
878 /*
879 * now filter out any obviously spurious interrupts
880 */
881 spin_lock_irq(&irq_controller_lock);
882 for (i = 0; i < NR_IRQS; i++) {
883 if (irq_desc[i].probing && irq_desc[i].triggered) {
884 irq_desc[i].probing = 0;
885 irqs -= 1;
886 }
887 }
888 spin_unlock_irq(&irq_controller_lock);
889
890 return irqs;
891}
892
893EXPORT_SYMBOL(probe_irq_on);
894
895unsigned int probe_irq_mask(unsigned long irqs)
896{
897 unsigned int mask = 0, i;
898
899 spin_lock_irq(&irq_controller_lock);
900 for (i = 0; i < 16 && i < NR_IRQS; i++)
901 if (irq_desc[i].probing && irq_desc[i].triggered)
902 mask |= 1 << i;
903 spin_unlock_irq(&irq_controller_lock);
904
905 up(&probe_sem);
906
907 return mask;
908}
909EXPORT_SYMBOL(probe_irq_mask);
910
911/*
912 * Possible return values:
913 * >= 0 - interrupt number
914 * -1 - no interrupt/many interrupts
915 */
916int probe_irq_off(unsigned long irqs)
917{
918 unsigned int i;
919 int irq_found = NO_IRQ;
920
921 /*
922 * look at the interrupts, and find exactly one
923 * that we were probing has been triggered
924 */
925 spin_lock_irq(&irq_controller_lock);
926 for (i = 0; i < NR_IRQS; i++) {
927 if (irq_desc[i].probing &&
928 irq_desc[i].triggered) {
929 if (irq_found != NO_IRQ) {
930 irq_found = NO_IRQ;
931 goto out;
932 }
933 irq_found = i;
934 }
935 }
936
937 if (irq_found == -1)
938 irq_found = NO_IRQ;
939out:
940 spin_unlock_irq(&irq_controller_lock);
941
942 up(&probe_sem);
943
944 return irq_found;
945}
946
947EXPORT_SYMBOL(probe_irq_off);
948
949#ifdef CONFIG_SMP
950static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
951{
952 pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu);
953
954 spin_lock_irq(&irq_controller_lock);
955 desc->cpu = cpu;
956 desc->chip->set_cpu(desc, irq, cpu);
957 spin_unlock_irq(&irq_controller_lock);
958}
959
960#ifdef CONFIG_PROC_FS
961static int
962irq_affinity_read_proc(char *page, char **start, off_t off, int count,
963 int *eof, void *data)
964{
965 struct irqdesc *desc = irq_desc + ((int)data);
966 int len = cpumask_scnprintf(page, count, desc->affinity);
967
968 if (count - len < 2)
969 return -EINVAL;
970 page[len++] = '\n';
971 page[len] = '\0';
972
973 return len;
974}
975
976static int
977irq_affinity_write_proc(struct file *file, const char __user *buffer,
978 unsigned long count, void *data)
979{
980 unsigned int irq = (unsigned int)data;
981 struct irqdesc *desc = irq_desc + irq;
982 cpumask_t affinity, tmp;
983 int ret = -EIO;
984
985 if (!desc->chip->set_cpu)
986 goto out;
987
988 ret = cpumask_parse(buffer, count, affinity);
989 if (ret)
990 goto out;
991
992 cpus_and(tmp, affinity, cpu_online_map);
993 if (cpus_empty(tmp)) {
994 ret = -EINVAL;
995 goto out;
996 }
997
998 desc->affinity = affinity;
999 route_irq(desc, irq, first_cpu(tmp));
1000 ret = count;
1001
1002 out:
1003 return ret;
1004}
1005#endif
1006#endif
1007
1008void __init init_irq_proc(void)
1009{
1010#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS)
1011 struct proc_dir_entry *dir;
1012 int irq;
1013
1014 dir = proc_mkdir("irq", NULL);
1015 if (!dir)
1016 return;
1017
1018 for (irq = 0; irq < NR_IRQS; irq++) {
1019 struct proc_dir_entry *entry;
1020 struct irqdesc *desc;
1021 char name[16];
1022
1023 desc = irq_desc + irq;
1024 memset(name, 0, sizeof(name));
1025 snprintf(name, sizeof(name) - 1, "%u", irq);
1026
1027 desc->procdir = proc_mkdir(name, dir);
1028 if (!desc->procdir)
1029 continue;
1030
1031 entry = create_proc_entry("smp_affinity", 0600, desc->procdir);
1032 if (entry) {
1033 entry->nlink = 1;
1034 entry->data = (void *)irq;
1035 entry->read_proc = irq_affinity_read_proc;
1036 entry->write_proc = irq_affinity_write_proc;
1037 }
1038 }
1039#endif
1040} 152}
1041 153
1042void __init init_IRQ(void) 154void __init init_IRQ(void)
1043{ 155{
1044 struct irqdesc *desc;
1045 int irq; 156 int irq;
1046 157
158 for (irq = 0; irq < NR_IRQS; irq++)
159 irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_DELAYED_DISABLE |
160 IRQ_NOPROBE;
161
1047#ifdef CONFIG_SMP 162#ifdef CONFIG_SMP
1048 bad_irq_desc.affinity = CPU_MASK_ALL; 163 bad_irq_desc.affinity = CPU_MASK_ALL;
1049 bad_irq_desc.cpu = smp_processor_id(); 164 bad_irq_desc.cpu = smp_processor_id();
1050#endif 165#endif
1051
1052 for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
1053 *desc = bad_irq_desc;
1054 INIT_LIST_HEAD(&desc->pend);
1055 }
1056
1057 init_arch_irq(); 166 init_arch_irq();
1058} 167}
1059 168
1060static int __init noirqdebug_setup(char *str)
1061{
1062 noirqdebug = 1;
1063 return 1;
1064}
1065
1066__setup("noirqdebug", noirqdebug_setup);
1067
1068#ifdef CONFIG_HOTPLUG_CPU 169#ifdef CONFIG_HOTPLUG_CPU
1069/* 170/*
1070 * The CPU has been marked offline. Migrate IRQs off this CPU. If 171 * The CPU has been marked offline. Migrate IRQs off this CPU. If
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c
index dc38e06ada63..0aa22650a00f 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_time.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c
@@ -21,13 +21,13 @@
21 21
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/irq.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/sched.h> 26#include <linux/sched.h>
26#include <linux/time.h> 27#include <linux/time.h>
27 28
28#include <asm/hardware.h> 29#include <asm/hardware.h>
29#include <asm/io.h> 30#include <asm/io.h>
30#include <asm/irq.h>
31#include <asm/mach/time.h> 31#include <asm/mach/time.h>
32 32
33static unsigned long last_crtr; 33static unsigned long last_crtr;
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 83c34747087b..5783c282ae7b 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -10,12 +10,13 @@
10 */ 10 */
11 11
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
13#include <linux/kernel.h> 15#include <linux/kernel.h>
14#include <linux/list.h> 16#include <linux/list.h>
15#include <linux/module.h> 17#include <linux/module.h>
16 18
17#include <asm/io.h> 19#include <asm/io.h>
18#include <asm/mach/irq.h>
19#include <asm/hardware.h> 20#include <asm/hardware.h>
20#include <asm/arch/gpio.h> 21#include <asm/arch/gpio.h>
21 22
@@ -340,7 +341,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs
340 void __iomem *pio; 341 void __iomem *pio;
341 u32 isr; 342 u32 isr;
342 343
343 pio = desc->base; 344 pio = get_irq_chip_data(irq);
344 345
345 /* temporarily mask (level sensitive) parent IRQ */ 346 /* temporarily mask (level sensitive) parent IRQ */
346 desc->chip->ack(irq); 347 desc->chip->ack(irq);
@@ -350,12 +351,12 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs
350 if (!isr) 351 if (!isr)
351 break; 352 break;
352 353
353 pin = (unsigned) desc->data; 354 pin = (unsigned) get_irq_data(irq);
354 gpio = &irq_desc[pin]; 355 gpio = &irq_desc[pin];
355 356
356 while (isr) { 357 while (isr) {
357 if (isr & 1) { 358 if (isr & 1) {
358 if (unlikely(gpio->disable_depth)) { 359 if (unlikely(gpio->depth)) {
359 /* 360 /*
360 * The core ARM interrupt handler lazily disables IRQs so 361 * The core ARM interrupt handler lazily disables IRQs so
361 * another IRQ must be generated before it actually gets 362 * another IRQ must be generated before it actually gets
@@ -364,7 +365,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs
364 gpio_irq_mask(pin); 365 gpio_irq_mask(pin);
365 } 366 }
366 else 367 else
367 gpio->handle(pin, gpio, regs); 368 desc_handle_irq(pin, gpio, regs);
368 } 369 }
369 pin++; 370 pin++;
370 gpio++; 371 gpio++;
diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
index 1a23f0dcd4b8..b0f1db258e80 100644
--- a/arch/arm/mach-clps711x/time.c
+++ b/arch/arm/mach-clps711x/time.c
@@ -19,6 +19,7 @@
19#include <linux/timex.h> 19#include <linux/timex.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/irq.h>
22#include <linux/sched.h> 23#include <linux/sched.h>
23 24
24#include <asm/hardware.h> 25#include <asm/hardware.h>
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index 5b12cab0e691..cd66df896364 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -9,6 +9,7 @@
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/irq.h>
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/sched.h> 14#include <linux/sched.h>
14#include <linux/init.h> 15#include <linux/init.h>
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index 14a62d6008fe..e668d4acd808 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -6,6 +6,7 @@
6 */ 6 */
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/interrupt.h> 8#include <linux/interrupt.h>
9#include <linux/irq.h>
9 10
10#include <asm/irq.h> 11#include <asm/irq.h>
11 12
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index c1d74f7ab669..282b473c21f2 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -6,6 +6,7 @@
6 */ 6 */
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/interrupt.h> 8#include <linux/interrupt.h>
9#include <linux/irq.h>
9 10
10#include <asm/io.h> 11#include <asm/io.h>
11#include <asm/irq.h> 12#include <asm/irq.h>
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 294b1c450f21..5f9a04775a47 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -12,6 +12,7 @@
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/irq.h>
15#include <linux/time.h> 16#include <linux/time.h>
16 17
17#include <asm/hardware.h> 18#include <asm/hardware.h>
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 576a5e979c00..2d7e505e748f 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -13,6 +13,7 @@
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/spinlock.h> 14#include <linux/spinlock.h>
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/irq.h>
16#include <linux/sched.h> 17#include <linux/sched.h>
17#include <linux/smp.h> 18#include <linux/smp.h>
18#include <linux/termios.h> 19#include <linux/termios.h>
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 3cfc5aab8259..b31f31ac937b 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -19,6 +19,7 @@
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/irq.h>
22#include <linux/serial.h> 23#include <linux/serial.h>
23#include <linux/tty.h> 24#include <linux/tty.h>
24#include <linux/bitops.h> 25#include <linux/bitops.h>
@@ -408,7 +409,7 @@ static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, str
408 for(i = 31; i >= 0; i--) { 409 for(i = 31; i >= 0; i--) {
409 if(status & (1 << i)) { 410 if(status & (1 << i)) {
410 desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; 411 desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
411 desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); 412 desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
412 } 413 }
413 } 414 }
414} 415}
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 9b8ded259807..40eef8b36740 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -167,7 +167,7 @@ void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long
167 } 167 }
168 168
169 /* Hook into PCI interrupt */ 169 /* Hook into PCI interrupt */
170 set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler); 170 set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
171} 171}
172 172
173/************************************************************************* 173/*************************************************************************
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 8477ae1d8f72..7f42366f60d1 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -127,7 +127,7 @@ void __init ixdp2x01_init_irq(void)
127 } 127 }
128 128
129 /* Hook into PCI interrupts */ 129 /* Hook into PCI interrupts */
130 set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler); 130 set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
131} 131}
132 132
133 133
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
index 82ad6ef90a38..7c218aecf443 100644
--- a/arch/arm/mach-ixp23xx/core.c
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -271,7 +271,7 @@ static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *
271 } 271 }
272 272
273 int_desc = irq_desc + irqno; 273 int_desc = irq_desc + irqno;
274 int_desc->handle(irqno, int_desc, regs); 274 desc_handle_irq(irqno, int_desc, regs);
275 275
276 desc->chip->unmask(irq); 276 desc->chip->unmask(irq);
277} 277}
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index bba9d9f08691..37a32e6bcca2 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -19,6 +19,7 @@
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/irq.h>
22#include <linux/serial.h> 23#include <linux/serial.h>
23#include <linux/tty.h> 24#include <linux/tty.h>
24#include <linux/bitops.h> 25#include <linux/bitops.h>
@@ -36,7 +37,6 @@
36#include <asm/memory.h> 37#include <asm/memory.h>
37#include <asm/hardware.h> 38#include <asm/hardware.h>
38#include <asm/mach-types.h> 39#include <asm/mach-types.h>
39#include <asm/irq.h>
40#include <asm/system.h> 40#include <asm/system.h>
41#include <asm/tlbflush.h> 41#include <asm/tlbflush.h>
42#include <asm/pgtable.h> 42#include <asm/pgtable.h>
@@ -74,7 +74,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct
74 int cpld_irq = 74 int cpld_irq =
75 IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); 75 IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
76 cpld_desc = irq_desc + cpld_irq; 76 cpld_desc = irq_desc + cpld_irq;
77 cpld_desc->handle(cpld_irq, cpld_desc, regs); 77 desc_handle_irq(cpld_irq, cpld_desc, regs);
78 } 78 }
79 } 79 }
80 80
@@ -111,7 +111,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct
111 int cpld_irq = 111 int cpld_irq =
112 IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); 112 IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
113 cpld_desc = irq_desc + cpld_irq; 113 cpld_desc = irq_desc + cpld_irq;
114 cpld_desc->handle(cpld_irq, cpld_desc, regs); 114 desc_handle_irq(cpld_irq, cpld_desc, regs);
115 } 115 }
116 } 116 }
117 117
@@ -158,8 +158,8 @@ void ixdp2351_init_irq(void)
158 } 158 }
159 } 159 }
160 160
161 set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler); 161 set_irq_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
162 set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler); 162 set_irq_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
163} 163}
164 164
165/* 165/*
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index e6b7fcd923fa..2cebb2878895 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -17,6 +17,7 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/pci.h> 18#include <linux/pci.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/irq.h>
20 21
21#include <asm/mach-types.h> 22#include <asm/mach-types.h>
22#include <asm/hardware.h> 23#include <asm/hardware.h>
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index 8b8ca80c9449..d5156c043f0b 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -17,6 +17,7 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/pci.h> 18#include <linux/pci.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/irq.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
21 22
22#include <asm/mach/pci.h> 23#include <asm/mach/pci.h>
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 526fb6175bc3..ed5270800217 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -16,10 +16,10 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/irq.h>
19 20
20#include <asm/mach-types.h> 21#include <asm/mach-types.h>
21#include <asm/hardware.h> 22#include <asm/hardware.h>
22#include <asm/irq.h>
23 23
24#include <asm/mach/pci.h> 24#include <asm/mach/pci.h>
25 25
diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c
index 2d3b770d9e82..b8ebaf4a9c8e 100644
--- a/arch/arm/mach-ixp4xx/nas100d-pci.c
+++ b/arch/arm/mach-ixp4xx/nas100d-pci.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/pci.h> 18#include <linux/pci.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/irq.h>
20 21
21#include <asm/mach/pci.h> 22#include <asm/mach/pci.h>
22#include <asm/mach-types.h> 23#include <asm/mach-types.h>
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
index a3745ed37f9f..f58a1d05a02e 100644
--- a/arch/arm/mach-ixp4xx/nas100d-power.c
+++ b/arch/arm/mach-ixp4xx/nas100d-power.c
@@ -17,9 +17,9 @@
17 * 17 *
18 */ 18 */
19 19
20#include <linux/module.h>
21#include <linux/reboot.h>
22#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/irq.h>
22#include <linux/module.h>
23#include <linux/reboot.h> 23#include <linux/reboot.h>
24 24
25#include <asm/mach-types.h> 25#include <asm/mach-types.h>
diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c
index ac626436e96f..b7af5640ea7b 100644
--- a/arch/arm/mach-l7200/core.c
+++ b/arch/arm/mach-l7200/core.c
@@ -7,6 +7,7 @@
7 */ 7 */
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/irq.h>
10#include <linux/device.h> 11#include <linux/device.h>
11 12
12#include <asm/types.h> 13#include <asm/types.h>
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index c0e6854289f1..35c3606a2079 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -12,6 +12,7 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/irq.h>
15 16
16#include <asm/hardware.h> 17#include <asm/hardware.h>
17#include <asm/setup.h> 18#include <asm/setup.h>
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index 1919835d9610..4d26c9f62c71 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/irq.h>
14#include <linux/time.h> 15#include <linux/time.h>
15 16
16#include <asm/hardware.h> 17#include <asm/hardware.h>
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e0711d23a6b0..91933301bb73 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -29,7 +29,7 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/interrupt.h> 32#include <linux/irq.h>
33 33
34#include <linux/mtd/mtd.h> 34#include <linux/mtd/mtd.h>
35#include <linux/mtd/partitions.h> 35#include <linux/mtd/partitions.h>
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 56319742aa1b..5615fb8a3d5b 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/irq.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/serial.h> 16#include <linux/serial.h>
16#include <linux/tty.h> 17#include <linux/tty.h>
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 347b9dea24c6..6914d22bc20f 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -18,6 +18,7 @@
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/irq.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/fb.h> 23#include <linux/fb.h>
23 24
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 0f1648780c41..1e5e6ca693ee 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -18,11 +18,11 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/irq.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22 23
23#include <asm/hardware.h> 24#include <asm/hardware.h>
24#include <asm/mach-types.h> 25#include <asm/mach-types.h>
25#include <asm/irq.h>
26#include <asm/apm.h> 26#include <asm/apm.h>
27#include <asm/arch/pm.h> 27#include <asm/arch/pm.h>
28#include <asm/arch/pxa-regs.h> 28#include <asm/arch/pxa-regs.h>
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index fbbeb0553006..def4441d2442 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -136,8 +136,8 @@ bast_irq_pc104_demux(unsigned int irq,
136 for (i = 0; stat != 0; i++, stat >>= 1) { 136 for (i = 0; stat != 0; i++, stat >>= 1) {
137 if (stat & 1) { 137 if (stat & 1) {
138 irqno = bast_pc104_irqs[i]; 138 irqno = bast_pc104_irqs[i];
139 139 desc = irq_desc + irqno;
140 desc_handle_irq(irqno, irq_desc + irqno, regs); 140 desc_handle_irq(irqno, desc, regs);
141 } 141 }
142 } 142 }
143 } 143 }
@@ -156,7 +156,7 @@ static __init int bast_irq_init(void)
156 156
157 set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux); 157 set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
158 158
159 /* reigster our IRQs */ 159 /* register our IRQs */
160 160
161 for (i = 0; i < 4; i++) { 161 for (i = 0; i < 4; i++) {
162 unsigned int irqno = bast_pc104_irqs[i]; 162 unsigned int irqno = bast_pc104_irqs[i];
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 47387c5b9723..c153c49c75dc 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -22,6 +22,7 @@
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/irq.h>
25#include <linux/err.h> 26#include <linux/err.h>
26#include <linux/clk.h> 27#include <linux/clk.h>
27 28
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index e0f6d57b5065..31afe50d7cd5 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/tty.h> 15#include <linux/tty.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/irq.h>
17#include <linux/mtd/mtd.h> 18#include <linux/mtd/mtd.h>
18#include <linux/mtd/partitions.h> 19#include <linux/mtd/partitions.h>
19 20
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index e727ba87b9f2..e10d661c015f 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -835,7 +835,7 @@ static void __init h3800_init_irq(void)
835 } 835 }
836#endif 836#endif
837 set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING); 837 set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
838 set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux); 838 set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux);
839} 839}
840 840
841 841
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index b3a56024182e..2891b8ca86dd 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -11,12 +11,13 @@
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
14#include <linux/ioport.h> 16#include <linux/ioport.h>
15#include <linux/ptrace.h> 17#include <linux/ptrace.h>
16#include <linux/sysdev.h> 18#include <linux/sysdev.h>
17 19
18#include <asm/hardware.h> 20#include <asm/hardware.h>
19#include <asm/irq.h>
20#include <asm/mach/irq.h> 21#include <asm/mach/irq.h>
21 22
22#include "generic.h" 23#include "generic.h"
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 0709ebab531c..c7bf7e0038f0 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -7,6 +7,7 @@
7#include <linux/tty.h> 7#include <linux/tty.h>
8#include <linux/ioport.h> 8#include <linux/ioport.h>
9#include <linux/platform_device.h> 9#include <linux/platform_device.h>
10#include <linux/irq.h>
10 11
11#include <linux/mtd/partitions.h> 12#include <linux/mtd/partitions.h>
12 13
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index e4b435e634e4..688b1e109a40 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/irq.h>
14#include <linux/timex.h> 15#include <linux/timex.h>
15#include <linux/signal.h> 16#include <linux/signal.h>
16 17
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 877600e212dd..2f2c6e97b7a3 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -6,6 +6,7 @@
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/interrupt.h> 8#include <linux/interrupt.h>
9#include <linux/irq.h>
9#include <linux/sched.h> 10#include <linux/sched.h>
10#include <linux/serial_8250.h> 11#include <linux/serial_8250.h>
11 12
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c5d0214ef191..c2c05ef86348 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -24,9 +24,9 @@
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/irq.h>
27 28
28#include <asm/system.h> 29#include <asm/system.h>
29#include <asm/irq.h>
30#include <asm/hardware.h> 30#include <asm/hardware.h>
31#include <asm/dma.h> 31#include <asm/dma.h>
32#include <asm/io.h> 32#include <asm/io.h>
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index ae08eeec7aad..cb0c21d384c0 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -783,7 +783,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
783 783
784 desc->chip->ack(irq); 784 desc->chip->ack(irq);
785 785
786 bank = (struct gpio_bank *) desc->data; 786 bank = get_irq_data(irq);
787 if (bank->method == METHOD_MPUIO) 787 if (bank->method == METHOD_MPUIO)
788 isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; 788 isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
789#ifdef CONFIG_ARCH_OMAP15XX 789#ifdef CONFIG_ARCH_OMAP15XX
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index d2f9759cd3ed..9b66271d3ba8 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -17,7 +17,7 @@
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20//#include <asm/irq.h> 20#include <linux/irq.h>
21 21
22#include <asm/arch/sharpsl.h> 22#include <asm/arch/sharpsl.h>
23#include <asm/arch/hardware.h> 23#include <asm/arch/hardware.h>
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 888358fac598..ecaa132fa592 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -38,12 +38,12 @@
38#include <linux/timer.h> 38#include <linux/timer.h>
39#include <linux/mm.h> 39#include <linux/mm.h>
40#include <linux/interrupt.h> 40#include <linux/interrupt.h>
41#include <linux/irq.h>
41#include <linux/spinlock.h> 42#include <linux/spinlock.h>
42#include <linux/cpufreq.h> 43#include <linux/cpufreq.h>
43 44
44#include <asm/hardware.h> 45#include <asm/hardware.h>
45#include <asm/io.h> 46#include <asm/io.h>
46#include <asm/irq.h>
47#include <asm/system.h> 47#include <asm/system.h>
48 48
49#include "soc_common.h" 49#include "soc_common.h"
diff --git a/include/asm-arm/dyntick.h b/include/asm-arm/dyntick.h
new file mode 100644
index 000000000000..19fab2d2b760
--- /dev/null
+++ b/include/asm-arm/dyntick.h
@@ -0,0 +1,6 @@
1#ifndef _ASMARM_DYNTICK_H
2#define _ASMARM_DYNTICK_H
3
4#include <asm/mach/time.h>
5
6#endif /* _ASMARM_DYNTICK_H */
diff --git a/include/asm-arm/hw_irq.h b/include/asm-arm/hw_irq.h
new file mode 100644
index 000000000000..f1a08a500604
--- /dev/null
+++ b/include/asm-arm/hw_irq.h
@@ -0,0 +1,9 @@
1/*
2 * Nothing to see here yet
3 */
4#ifndef _ARCH_ARM_HW_IRQ_H
5#define _ARCH_ARM_HW_IRQ_H
6
7#include <asm/mach/irq.h>
8
9#endif
diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
index 66e67e60bc56..283af50a16cb 100644
--- a/include/asm-arm/irq.h
+++ b/include/asm-arm/irq.h
@@ -21,18 +21,13 @@
21 21
22struct irqaction; 22struct irqaction;
23 23
24extern void disable_irq_nosync(unsigned int);
25extern void disable_irq(unsigned int);
26extern void enable_irq(unsigned int);
27
28/* 24/*
29 * These correspond with the SA_TRIGGER_* defines, and therefore the 25 * Migration helpers
30 * IORESOURCE_IRQ_* defines.
31 */ 26 */
32#define __IRQT_RISEDGE (1 << 0) 27#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
33#define __IRQT_FALEDGE (1 << 1) 28#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
34#define __IRQT_HIGHLVL (1 << 2) 29#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
35#define __IRQT_LOWLVL (1 << 3) 30#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
36 31
37#define IRQT_NOEDGE (0) 32#define IRQT_NOEDGE (0)
38#define IRQT_RISING (__IRQT_RISEDGE) 33#define IRQT_RISING (__IRQT_RISEDGE)
@@ -40,12 +35,7 @@ extern void enable_irq(unsigned int);
40#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE) 35#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
41#define IRQT_LOW (__IRQT_LOWLVL) 36#define IRQT_LOW (__IRQT_LOWLVL)
42#define IRQT_HIGH (__IRQT_HIGHLVL) 37#define IRQT_HIGH (__IRQT_HIGHLVL)
43#define IRQT_PROBE (1 << 4) 38#define IRQT_PROBE IRQ_TYPE_PROBE
44
45int set_irq_type(unsigned int irq, unsigned int type);
46void disable_irq_wake(unsigned int irq);
47void enable_irq_wake(unsigned int irq);
48int setup_irq(unsigned int, struct irqaction *);
49 39
50extern void migrate_irqs(void); 40extern void migrate_irqs(void);
51#endif 41#endif
diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
index d4d420ecf3a8..131f33733d25 100644
--- a/include/asm-arm/mach/irq.h
+++ b/include/asm-arm/mach/irq.h
@@ -10,95 +10,9 @@
10#ifndef __ASM_ARM_MACH_IRQ_H 10#ifndef __ASM_ARM_MACH_IRQ_H
11#define __ASM_ARM_MACH_IRQ_H 11#define __ASM_ARM_MACH_IRQ_H
12 12
13struct irqdesc; 13#include <linux/irq.h>
14struct pt_regs;
15struct seq_file;
16
17typedef void (*irq_handler_t)(unsigned int, struct irqdesc *, struct pt_regs *);
18typedef void (*irq_control_t)(unsigned int);
19
20struct irqchip {
21 /*
22 * Acknowledge the IRQ.
23 * If this is a level-based IRQ, then it is expected to mask the IRQ
24 * as well.
25 */
26 void (*ack)(unsigned int);
27 /*
28 * Mask the IRQ in hardware.
29 */
30 void (*mask)(unsigned int);
31 /*
32 * Unmask the IRQ in hardware.
33 */
34 void (*unmask)(unsigned int);
35 /*
36 * Ask the hardware to re-trigger the IRQ.
37 * Note: This method _must_ _not_ call the interrupt handler.
38 * If you are unable to retrigger the interrupt, do not
39 * provide a function, or if you do, return non-zero.
40 */
41 int (*retrigger)(unsigned int);
42 /*
43 * Set the type of the IRQ.
44 */
45 int (*set_type)(unsigned int, unsigned int);
46 /*
47 * Set wakeup-enable on the selected IRQ
48 */
49 int (*set_wake)(unsigned int, unsigned int);
50
51#ifdef CONFIG_SMP
52 /*
53 * Route an interrupt to a CPU
54 */
55 void (*set_cpu)(struct irqdesc *desc, unsigned int irq, unsigned int cpu);
56#endif
57};
58
59struct irqdesc {
60 irq_handler_t handle;
61 struct irqchip *chip;
62 struct irqaction *action;
63 struct list_head pend;
64 void __iomem *base;
65 void *data;
66 unsigned int disable_depth;
67
68 unsigned int triggered: 1; /* IRQ has occurred */
69 unsigned int running : 1; /* IRQ is running */
70 unsigned int pending : 1; /* IRQ is pending */
71 unsigned int probing : 1; /* IRQ in use for a probe */
72 unsigned int probe_ok : 1; /* IRQ can be used for probe */
73 unsigned int valid : 1; /* IRQ claimable */
74 unsigned int noautoenable : 1; /* don't automatically enable IRQ */
75 unsigned int unused :25;
76
77 unsigned int irqs_unhandled;
78 struct proc_dir_entry *procdir;
79
80#ifdef CONFIG_SMP
81 cpumask_t affinity;
82 unsigned int cpu;
83#endif
84
85 /*
86 * IRQ lock detection
87 */
88 unsigned int lck_cnt;
89 unsigned int lck_pc;
90 unsigned int lck_jif;
91};
92
93extern struct irqdesc irq_desc[];
94 14
95/* 15struct seq_file;
96 * Helpful inline function for calling irq descriptor handlers.
97 */
98static inline void desc_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
99{
100 desc->handle(irq, desc, regs);
101}
102 16
103/* 17/*
104 * This is internal. Do not use it. 18 * This is internal. Do not use it.
@@ -106,18 +20,22 @@ static inline void desc_handle_irq(unsigned int irq, struct irqdesc *desc, struc
106extern void (*init_arch_irq)(void); 20extern void (*init_arch_irq)(void);
107extern void init_FIQ(void); 21extern void init_FIQ(void);
108extern int show_fiq_list(struct seq_file *, void *); 22extern int show_fiq_list(struct seq_file *, void *);
109void __set_irq_handler(unsigned int irq, irq_handler_t, int);
110 23
111/* 24/*
112 * External stuff. 25 * Function wrappers
26 */
27#define set_irq_chipdata(irq, d) set_irq_chip_data(irq, d)
28#define get_irq_chipdata(irq) get_irq_chip_data(irq)
29
30/*
31 * Obsolete inline function for calling irq descriptor handlers.
113 */ 32 */
114#define set_irq_handler(irq,handler) __set_irq_handler(irq,handler,0) 33static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc,
115#define set_irq_chained_handler(irq,handler) __set_irq_handler(irq,handler,1) 34 struct pt_regs *regs)
116#define set_irq_data(irq,d) do { irq_desc[irq].data = d; } while (0) 35{
117#define set_irq_chipdata(irq,d) do { irq_desc[irq].base = d; } while (0) 36 desc->handle_irq(irq, desc, regs);
118#define get_irq_chipdata(irq) (irq_desc[irq].base) 37}
119 38
120void set_irq_chip(unsigned int irq, struct irqchip *);
121void set_irq_flags(unsigned int irq, unsigned int flags); 39void set_irq_flags(unsigned int irq, unsigned int flags);
122 40
123#define IRQF_VALID (1 << 0) 41#define IRQF_VALID (1 << 0)
@@ -125,12 +43,25 @@ void set_irq_flags(unsigned int irq, unsigned int flags);
125#define IRQF_NOAUTOEN (1 << 2) 43#define IRQF_NOAUTOEN (1 << 2)
126 44
127/* 45/*
128 * Built-in IRQ handlers. 46 * This is for easy migration, but should be changed in the source
129 */ 47 */
130void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); 48#define do_level_IRQ handle_level_irq
131void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); 49#define do_edge_IRQ handle_edge_irq
132void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); 50#define do_simple_IRQ handle_simple_irq
133void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); 51#define irqdesc irq_desc
134void dummy_mask_unmask_irq(unsigned int irq); 52#define irqchip irq_chip
53
54#define do_bad_IRQ(irq,desc,regs) \
55do { \
56 spin_lock(&desc->lock); \
57 handle_bad_irq(irq, desc, regs); \
58 spin_unlock(&desc->lock); \
59} while(0)
60
61extern unsigned long irq_err_count;
62static inline void ack_bad_irq(int irq)
63{
64 irq_err_count++;
65}
135 66
136#endif 67#endif
diff --git a/include/linux/irq.h b/include/linux/irq.h
index ae1e422f18e3..95d7aa7954d2 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -347,8 +347,9 @@ extern int noirqdebug_setup(char *str);
347/* Checks whether the interrupt can be requested by request_irq(): */ 347/* Checks whether the interrupt can be requested by request_irq(): */
348extern int can_request_irq(unsigned int irq, unsigned long irqflags); 348extern int can_request_irq(unsigned int irq, unsigned long irqflags);
349 349
350/* Dummy irq-chip implementation: */ 350/* Dummy irq-chip implementations: */
351extern struct irq_chip no_irq_chip; 351extern struct irq_chip no_irq_chip;
352extern struct irq_chip dummy_irq_chip;
352 353
353extern void 354extern void
354set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, 355set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 4a0952d9458b..54105bdfe20d 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -462,9 +462,18 @@ __set_irq_handler(unsigned int irq,
462 if (!handle) 462 if (!handle)
463 handle = handle_bad_irq; 463 handle = handle_bad_irq;
464 464
465 if (is_chained && desc->chip == &no_irq_chip) 465 if (desc->chip == &no_irq_chip) {
466 printk(KERN_WARNING "Trying to install " 466 printk(KERN_WARNING "Trying to install %sinterrupt handler "
467 "chained interrupt type for IRQ%d\n", irq); 467 "for IRQ%d\n", is_chained ? "chained " : " ", irq);
468 /*
469 * Some ARM implementations install a handler for really dumb
470 * interrupt hardware without setting an irq_chip. This worked
471 * with the ARM no_irq_chip but the check in setup_irq would
472 * prevent us to setup the interrupt at all. Switch it to
473 * dummy_irq_chip for easy transition.
474 */
475 desc->chip = &dummy_irq_chip;
476 }
468 477
469 spin_lock_irqsave(&desc->lock, flags); 478 spin_lock_irqsave(&desc->lock, flags);
470 479
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 6070e0464690..6d8b30114961 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -16,6 +16,10 @@
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/kernel_stat.h> 17#include <linux/kernel_stat.h>
18 18
19#if defined(CONFIG_NO_IDLE_HZ) && defined(CONFIG_ARM)
20#include <asm/dyntick.h>
21#endif
22
19#include "internals.h" 23#include "internals.h"
20 24
21/** 25/**
@@ -92,6 +96,22 @@ struct irq_chip no_irq_chip = {
92}; 96};
93 97
94/* 98/*
99 * Generic dummy implementation which can be used for
100 * real dumb interrupt sources
101 */
102struct irq_chip dummy_irq_chip = {
103 .name = "dummy",
104 .startup = noop_ret,
105 .shutdown = noop,
106 .enable = noop,
107 .disable = noop,
108 .ack = noop,
109 .mask = noop,
110 .unmask = noop,
111 .end = noop,
112};
113
114/*
95 * Special, empty irq handler: 115 * Special, empty irq handler:
96 */ 116 */
97irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) 117irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
@@ -113,6 +133,15 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
113 irqreturn_t ret, retval = IRQ_NONE; 133 irqreturn_t ret, retval = IRQ_NONE;
114 unsigned int status = 0; 134 unsigned int status = 0;
115 135
136#if defined(CONFIG_NO_IDLE_HZ) && defined(CONFIG_ARM)
137 if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
138 write_seqlock(&xtime_lock);
139 if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
140 system_timer->dyn_tick->handler(irq, 0, regs);
141 write_sequnlock(&xtime_lock);
142 }
143#endif
144
116 if (!(action->flags & IRQF_DISABLED)) 145 if (!(action->flags & IRQF_DISABLED))
117 local_irq_enable(); 146 local_irq_enable();
118 147