aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/handle.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
commit026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (patch)
tree2624a44924c625c367f3cebf937853b9da2de282 /kernel/irq/handle.c
parent9f2fa466383ce100b90fe52cb4489d7a26bf72a9 (diff)
parent29454dde27d8e340bb1987bad9aa504af7081eba (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r--kernel/irq/handle.c140
1 files changed, 98 insertions, 42 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 0f6530117105..aeb6e391276c 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,22 @@
14 18
15#include "internals.h" 19#include "internals.h"
16 20
21/**
22 * handle_bad_irq - handle spurious and unhandled irqs
23 */
24void fastcall
25handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
26{
27 print_irq_desc(irq, desc);
28 kstat_this_cpu.irqs[irq]++;
29 ack_bad_irq(irq);
30}
31
17/* 32/*
18 * Linux has a controller-independent interrupt architecture. 33 * Linux has a controller-independent interrupt architecture.
19 * Every controller has a 'controller-template', that is used 34 * Every controller has a 'controller-template', that is used
20 * by the main code to do the right thing. Each driver-visible 35 * by the main code to do the right thing. Each driver-visible
21 * interrupt source is transparently wired to the apropriate 36 * interrupt source is transparently wired to the appropriate
22 * controller. Thus drivers need not be aware of the 37 * controller. Thus drivers need not be aware of the
23 * interrupt-controller. 38 * interrupt-controller.
24 * 39 *
@@ -28,41 +43,68 @@
28 * 43 *
29 * Controller mappings for all interrupt sources: 44 * Controller mappings for all interrupt sources:
30 */ 45 */
31irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { 46struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
32 [0 ... NR_IRQS-1] = { 47 [0 ... NR_IRQS-1] = {
33 .status = IRQ_DISABLED, 48 .status = IRQ_DISABLED,
34 .handler = &no_irq_type, 49 .chip = &no_irq_chip,
35 .lock = SPIN_LOCK_UNLOCKED 50 .handle_irq = handle_bad_irq,
51 .depth = 1,
52 .lock = SPIN_LOCK_UNLOCKED,
53#ifdef CONFIG_SMP
54 .affinity = CPU_MASK_ALL
55#endif
36 } 56 }
37}; 57};
38 58
39/* 59/*
40 * Generic 'no controller' code 60 * What should we do if we get a hw irq event on an illegal vector?
61 * Each architecture has to answer this themself.
41 */ 62 */
42static void end_none(unsigned int irq) { } 63static 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{ 64{
50 /* 65 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); 66 ack_bad_irq(irq);
55} 67}
56 68
57struct hw_interrupt_type no_irq_type = { 69/*
58 .typename = "none", 70 * NOP functions
59 .startup = startup_none, 71 */
60 .shutdown = shutdown_none, 72static void noop(unsigned int irq)
61 .enable = enable_none, 73{
62 .disable = disable_none, 74}
63 .ack = ack_none, 75
64 .end = end_none, 76static unsigned int noop_ret(unsigned int irq)
65 .set_affinity = NULL 77{
78 return 0;
79}
80
81/*
82 * Generic no controller implementation
83 */
84struct irq_chip no_irq_chip = {
85 .name = "none",
86 .startup = noop_ret,
87 .shutdown = noop,
88 .enable = noop,
89 .disable = noop,
90 .ack = ack_bad,
91 .end = noop,
92};
93
94/*
95 * Generic dummy implementation which can be used for
96 * real dumb interrupt sources
97 */
98struct irq_chip dummy_irq_chip = {
99 .name = "dummy",
100 .startup = noop_ret,
101 .shutdown = noop,
102 .enable = noop,
103 .disable = noop,
104 .ack = noop,
105 .mask = noop,
106 .unmask = noop,
107 .end = noop,
66}; 108};
67 109
68/* 110/*
@@ -73,16 +115,23 @@ irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
73 return IRQ_NONE; 115 return IRQ_NONE;
74} 116}
75 117
76/* 118/**
77 * Have got an event to handle: 119 * handle_IRQ_event - irq action chain handler
120 * @irq: the interrupt number
121 * @regs: pointer to a register structure
122 * @action: the interrupt action chain for this irq
123 *
124 * Handles the action chain of an irq event
78 */ 125 */
79fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, 126irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
80 struct irqaction *action) 127 struct irqaction *action)
81{ 128{
82 irqreturn_t ret, retval = IRQ_NONE; 129 irqreturn_t ret, retval = IRQ_NONE;
83 unsigned int status = 0; 130 unsigned int status = 0;
84 131
85 if (!(action->flags & SA_INTERRUPT)) 132 handle_dynamic_tick(action);
133
134 if (!(action->flags & IRQF_DISABLED))
86 local_irq_enable(); 135 local_irq_enable();
87 136
88 do { 137 do {
@@ -93,22 +142,29 @@ fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
93 action = action->next; 142 action = action->next;
94 } while (action); 143 } while (action);
95 144
96 if (status & SA_SAMPLE_RANDOM) 145 if (status & IRQF_SAMPLE_RANDOM)
97 add_interrupt_randomness(irq); 146 add_interrupt_randomness(irq);
98 local_irq_disable(); 147 local_irq_disable();
99 148
100 return retval; 149 return retval;
101} 150}
102 151
103/* 152/**
104 * do_IRQ handles all normal device IRQ's (the special 153 * __do_IRQ - original all in one highlevel IRQ handler
154 * @irq: the interrupt number
155 * @regs: pointer to a register structure
156 *
157 * __do_IRQ handles all normal device IRQ's (the special
105 * SMP cross-CPU interrupts have their own specific 158 * SMP cross-CPU interrupts have their own specific
106 * handlers). 159 * handlers).
160 *
161 * This is the original x86 implementation which is used for every
162 * interrupt type.
107 */ 163 */
108fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) 164fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
109{ 165{
110 irq_desc_t *desc = irq_desc + irq; 166 struct irq_desc *desc = irq_desc + irq;
111 struct irqaction * action; 167 struct irqaction *action;
112 unsigned int status; 168 unsigned int status;
113 169
114 kstat_this_cpu.irqs[irq]++; 170 kstat_this_cpu.irqs[irq]++;
@@ -118,16 +174,16 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
118 /* 174 /*
119 * No locking required for CPU-local interrupts: 175 * No locking required for CPU-local interrupts:
120 */ 176 */
121 if (desc->handler->ack) 177 if (desc->chip->ack)
122 desc->handler->ack(irq); 178 desc->chip->ack(irq);
123 action_ret = handle_IRQ_event(irq, regs, desc->action); 179 action_ret = handle_IRQ_event(irq, regs, desc->action);
124 desc->handler->end(irq); 180 desc->chip->end(irq);
125 return 1; 181 return 1;
126 } 182 }
127 183
128 spin_lock(&desc->lock); 184 spin_lock(&desc->lock);
129 if (desc->handler->ack) 185 if (desc->chip->ack)
130 desc->handler->ack(irq); 186 desc->chip->ack(irq);
131 /* 187 /*
132 * REPLAY is when Linux resends an IRQ that was dropped earlier 188 * REPLAY is when Linux resends an IRQ that was dropped earlier
133 * WAITING is used by probe to mark irqs that are being tested 189 * WAITING is used by probe to mark irqs that are being tested
@@ -187,7 +243,7 @@ out:
187 * The ->end() handler has to deal with interrupts which got 243 * The ->end() handler has to deal with interrupts which got
188 * disabled while the handler was running. 244 * disabled while the handler was running.
189 */ 245 */
190 desc->handler->end(irq); 246 desc->chip->end(irq);
191 spin_unlock(&desc->lock); 247 spin_unlock(&desc->lock);
192 248
193 return 1; 249 return 1;