aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r--kernel/irq/handle.c165
1 files changed, 122 insertions, 43 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 0f6530117105..4c6cdbaed661 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -1,9 +1,13 @@
1/* 1/*
2 * linux/kernel/irq/handle.c 2 * linux/kernel/irq/handle.c
3 * 3 *
4 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar 4 * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
5 * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
5 * 6 *
6 * This file contains the core interrupt handling code. 7 * This file contains the core interrupt handling code.
8 *
9 * Detailed information is available in Documentation/DocBook/genericirq
10 *
7 */ 11 */
8 12
9#include <linux/irq.h> 13#include <linux/irq.h>
@@ -14,11 +18,27 @@
14 18
15#include "internals.h" 19#include "internals.h"
16 20
21/**
22 * handle_bad_irq - handle spurious and unhandled irqs
23 * @irq: the interrupt number
24 * @desc: description of the interrupt
25 * @regs: pointer to a register structure
26 *
27 * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
28 */
29void fastcall
30handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
31{
32 print_irq_desc(irq, desc);
33 kstat_this_cpu.irqs[irq]++;
34 ack_bad_irq(irq);
35}
36
17/* 37/*
18 * Linux has a controller-independent interrupt architecture. 38 * Linux has a controller-independent interrupt architecture.
19 * Every controller has a 'controller-template', that is used 39 * Every controller has a 'controller-template', that is used
20 * by the main code to do the right thing. Each driver-visible 40 * by the main code to do the right thing. Each driver-visible
21 * interrupt source is transparently wired to the apropriate 41 * interrupt source is transparently wired to the appropriate
22 * controller. Thus drivers need not be aware of the 42 * controller. Thus drivers need not be aware of the
23 * interrupt-controller. 43 * interrupt-controller.
24 * 44 *
@@ -28,41 +48,68 @@
28 * 48 *
29 * Controller mappings for all interrupt sources: 49 * Controller mappings for all interrupt sources:
30 */ 50 */
31irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { 51struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
32 [0 ... NR_IRQS-1] = { 52 [0 ... NR_IRQS-1] = {
33 .status = IRQ_DISABLED, 53 .status = IRQ_DISABLED,
34 .handler = &no_irq_type, 54 .chip = &no_irq_chip,
35 .lock = SPIN_LOCK_UNLOCKED 55 .handle_irq = handle_bad_irq,
56 .depth = 1,
57 .lock = SPIN_LOCK_UNLOCKED,
58#ifdef CONFIG_SMP
59 .affinity = CPU_MASK_ALL
60#endif
36 } 61 }
37}; 62};
38 63
39/* 64/*
40 * Generic 'no controller' code 65 * What should we do if we get a hw irq event on an illegal vector?
66 * Each architecture has to answer this themself.
41 */ 67 */
42static void end_none(unsigned int irq) { } 68static void ack_bad(unsigned int irq)
43static void enable_none(unsigned int irq) { }
44static void disable_none(unsigned int irq) { }
45static void shutdown_none(unsigned int irq) { }
46static unsigned int startup_none(unsigned int irq) { return 0; }
47
48static void ack_none(unsigned int irq)
49{ 69{
50 /* 70 print_irq_desc(irq, irq_desc + irq);
51 * 'what should we do if we get a hw irq event on an illegal vector'.
52 * each architecture has to answer this themself.
53 */
54 ack_bad_irq(irq); 71 ack_bad_irq(irq);
55} 72}
56 73
57struct hw_interrupt_type no_irq_type = { 74/*
58 .typename = "none", 75 * NOP functions
59 .startup = startup_none, 76 */
60 .shutdown = shutdown_none, 77static void noop(unsigned int irq)
61 .enable = enable_none, 78{
62 .disable = disable_none, 79}
63 .ack = ack_none, 80
64 .end = end_none, 81static unsigned int noop_ret(unsigned int irq)
65 .set_affinity = NULL 82{
83 return 0;
84}
85
86/*
87 * Generic no controller implementation
88 */
89struct irq_chip no_irq_chip = {
90 .name = "none",
91 .startup = noop_ret,
92 .shutdown = noop,
93 .enable = noop,
94 .disable = noop,
95 .ack = ack_bad,
96 .end = noop,
97};
98
99/*
100 * Generic dummy implementation which can be used for
101 * real dumb interrupt sources
102 */
103struct irq_chip dummy_irq_chip = {
104 .name = "dummy",
105 .startup = noop_ret,
106 .shutdown = noop,
107 .enable = noop,
108 .disable = noop,
109 .ack = noop,
110 .mask = noop,
111 .unmask = noop,
112 .end = noop,
66}; 113};
67 114
68/* 115/*
@@ -73,17 +120,24 @@ irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
73 return IRQ_NONE; 120 return IRQ_NONE;
74} 121}
75 122
76/* 123/**
77 * Have got an event to handle: 124 * handle_IRQ_event - irq action chain handler
125 * @irq: the interrupt number
126 * @regs: pointer to a register structure
127 * @action: the interrupt action chain for this irq
128 *
129 * Handles the action chain of an irq event
78 */ 130 */
79fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, 131irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
80 struct irqaction *action) 132 struct irqaction *action)
81{ 133{
82 irqreturn_t ret, retval = IRQ_NONE; 134 irqreturn_t ret, retval = IRQ_NONE;
83 unsigned int status = 0; 135 unsigned int status = 0;
84 136
85 if (!(action->flags & SA_INTERRUPT)) 137 handle_dynamic_tick(action);
86 local_irq_enable(); 138
139 if (!(action->flags & IRQF_DISABLED))
140 local_irq_enable_in_hardirq();
87 141
88 do { 142 do {
89 ret = action->handler(irq, action->dev_id, regs); 143 ret = action->handler(irq, action->dev_id, regs);
@@ -93,22 +147,30 @@ fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
93 action = action->next; 147 action = action->next;
94 } while (action); 148 } while (action);
95 149
96 if (status & SA_SAMPLE_RANDOM) 150 if (status & IRQF_SAMPLE_RANDOM)
97 add_interrupt_randomness(irq); 151 add_interrupt_randomness(irq);
98 local_irq_disable(); 152 local_irq_disable();
99 153
100 return retval; 154 return retval;
101} 155}
102 156
103/* 157#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
104 * do_IRQ handles all normal device IRQ's (the special 158/**
159 * __do_IRQ - original all in one highlevel IRQ handler
160 * @irq: the interrupt number
161 * @regs: pointer to a register structure
162 *
163 * __do_IRQ handles all normal device IRQ's (the special
105 * SMP cross-CPU interrupts have their own specific 164 * SMP cross-CPU interrupts have their own specific
106 * handlers). 165 * handlers).
166 *
167 * This is the original x86 implementation which is used for every
168 * interrupt type.
107 */ 169 */
108fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) 170fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
109{ 171{
110 irq_desc_t *desc = irq_desc + irq; 172 struct irq_desc *desc = irq_desc + irq;
111 struct irqaction * action; 173 struct irqaction *action;
112 unsigned int status; 174 unsigned int status;
113 175
114 kstat_this_cpu.irqs[irq]++; 176 kstat_this_cpu.irqs[irq]++;
@@ -118,16 +180,16 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
118 /* 180 /*
119 * No locking required for CPU-local interrupts: 181 * No locking required for CPU-local interrupts:
120 */ 182 */
121 if (desc->handler->ack) 183 if (desc->chip->ack)
122 desc->handler->ack(irq); 184 desc->chip->ack(irq);
123 action_ret = handle_IRQ_event(irq, regs, desc->action); 185 action_ret = handle_IRQ_event(irq, regs, desc->action);
124 desc->handler->end(irq); 186 desc->chip->end(irq);
125 return 1; 187 return 1;
126 } 188 }
127 189
128 spin_lock(&desc->lock); 190 spin_lock(&desc->lock);
129 if (desc->handler->ack) 191 if (desc->chip->ack)
130 desc->handler->ack(irq); 192 desc->chip->ack(irq);
131 /* 193 /*
132 * REPLAY is when Linux resends an IRQ that was dropped earlier 194 * REPLAY is when Linux resends an IRQ that was dropped earlier
133 * WAITING is used by probe to mark irqs that are being tested 195 * WAITING is used by probe to mark irqs that are being tested
@@ -187,9 +249,26 @@ out:
187 * The ->end() handler has to deal with interrupts which got 249 * The ->end() handler has to deal with interrupts which got
188 * disabled while the handler was running. 250 * disabled while the handler was running.
189 */ 251 */
190 desc->handler->end(irq); 252 desc->chip->end(irq);
191 spin_unlock(&desc->lock); 253 spin_unlock(&desc->lock);
192 254
193 return 1; 255 return 1;
194} 256}
257#endif
258
259#ifdef CONFIG_TRACE_IRQFLAGS
260
261/*
262 * lockdep: we want to handle all irq_desc locks as a single lock-class:
263 */
264static struct lock_class_key irq_desc_lock_class;
265
266void early_init_irq_lock_class(void)
267{
268 int i;
269
270 for (i = 0; i < NR_IRQS; i++)
271 lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
272}
195 273
274#endif