[PATCH] genirq: doc: handle_IRQ_event() and __do_IRQ() comments
[deliverable/linux.git] / kernel / irq / handle.c
CommitLineData
1da177e4
LT
1/*
2 * linux/kernel/irq/handle.c
3 *
4 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5 *
6 * This file contains the core interrupt handling code.
7 */
8
9#include <linux/irq.h>
10#include <linux/module.h>
11#include <linux/random.h>
12#include <linux/interrupt.h>
13#include <linux/kernel_stat.h>
14
15#include "internals.h"
16
17/*
18 * Linux has a controller-independent interrupt architecture.
19 * Every controller has a 'controller-template', that is used
20 * by the main code to do the right thing. Each driver-visible
06fcb0c6 21 * interrupt source is transparently wired to the appropriate
1da177e4
LT
22 * controller. Thus drivers need not be aware of the
23 * interrupt-controller.
24 *
25 * The code is designed to be easily extended with new/different
26 * interrupt controllers, without having to do assembly magic or
27 * having to touch the generic code.
28 *
29 * Controller mappings for all interrupt sources:
30 */
34ffdb72 31struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
1da177e4 32 [0 ... NR_IRQS-1] = {
4f167fb4 33 .status = IRQ_DISABLED,
d1bef4ed 34 .chip = &no_irq_type,
a53da52f
IM
35 .lock = SPIN_LOCK_UNLOCKED,
36#ifdef CONFIG_SMP
37 .affinity = CPU_MASK_ALL
38#endif
1da177e4
LT
39 }
40};
41
42/*
43 * Generic 'no controller' code
44 */
45static void end_none(unsigned int irq) { }
46static void enable_none(unsigned int irq) { }
47static void disable_none(unsigned int irq) { }
48static void shutdown_none(unsigned int irq) { }
49static unsigned int startup_none(unsigned int irq) { return 0; }
50
51static void ack_none(unsigned int irq)
52{
53 /*
54 * 'what should we do if we get a hw irq event on an illegal vector'.
55 * each architecture has to answer this themself.
56 */
57 ack_bad_irq(irq);
58}
59
60struct hw_interrupt_type no_irq_type = {
61 .typename = "none",
62 .startup = startup_none,
63 .shutdown = shutdown_none,
64 .enable = enable_none,
65 .disable = disable_none,
66 .ack = ack_none,
67 .end = end_none,
68 .set_affinity = NULL
69};
70
71/*
72 * Special, empty irq handler:
73 */
74irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
75{
76 return IRQ_NONE;
77}
78
8d28bc75
IM
79/**
80 * handle_IRQ_event - irq action chain handler
81 * @irq: the interrupt number
82 * @regs: pointer to a register structure
83 * @action: the interrupt action chain for this irq
84 *
85 * Handles the action chain of an irq event
1da177e4 86 */
2e60bbb6
IM
87irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
88 struct irqaction *action)
1da177e4 89{
908dcecd
JB
90 irqreturn_t ret, retval = IRQ_NONE;
91 unsigned int status = 0;
1da177e4
LT
92
93 if (!(action->flags & SA_INTERRUPT))
94 local_irq_enable();
95
96 do {
97 ret = action->handler(irq, action->dev_id, regs);
98 if (ret == IRQ_HANDLED)
99 status |= action->flags;
100 retval |= ret;
101 action = action->next;
102 } while (action);
103
104 if (status & SA_SAMPLE_RANDOM)
105 add_interrupt_randomness(irq);
106 local_irq_disable();
107
108 return retval;
109}
110
8d28bc75
IM
111/**
112 * __do_IRQ - original all in one highlevel IRQ handler
113 * @irq: the interrupt number
114 * @regs: pointer to a register structure
115 *
116 * __do_IRQ handles all normal device IRQ's (the special
1da177e4
LT
117 * SMP cross-CPU interrupts have their own specific
118 * handlers).
8d28bc75
IM
119 *
120 * This is the original x86 implementation which is used for every
121 * interrupt type.
1da177e4
LT
122 */
123fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
124{
34ffdb72 125 struct irq_desc *desc = irq_desc + irq;
06fcb0c6 126 struct irqaction *action;
1da177e4
LT
127 unsigned int status;
128
129 kstat_this_cpu.irqs[irq]++;
f26fdd59 130 if (CHECK_IRQ_PER_CPU(desc->status)) {
1da177e4
LT
131 irqreturn_t action_ret;
132
133 /*
134 * No locking required for CPU-local interrupts:
135 */
d1bef4ed
IM
136 if (desc->chip->ack)
137 desc->chip->ack(irq);
1da177e4 138 action_ret = handle_IRQ_event(irq, regs, desc->action);
d1bef4ed 139 desc->chip->end(irq);
1da177e4
LT
140 return 1;
141 }
142
143 spin_lock(&desc->lock);
d1bef4ed
IM
144 if (desc->chip->ack)
145 desc->chip->ack(irq);
1da177e4
LT
146 /*
147 * REPLAY is when Linux resends an IRQ that was dropped earlier
148 * WAITING is used by probe to mark irqs that are being tested
149 */
150 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
151 status |= IRQ_PENDING; /* we _want_ to handle it */
152
153 /*
154 * If the IRQ is disabled for whatever reason, we cannot
155 * use the action we have.
156 */
157 action = NULL;
158 if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
159 action = desc->action;
160 status &= ~IRQ_PENDING; /* we commit to handling */
161 status |= IRQ_INPROGRESS; /* we are handling it */
162 }
163 desc->status = status;
164
165 /*
166 * If there is no IRQ handler or it was disabled, exit early.
167 * Since we set PENDING, if another processor is handling
168 * a different instance of this same irq, the other processor
169 * will take care of it.
170 */
171 if (unlikely(!action))
172 goto out;
173
174 /*
175 * Edge triggered interrupts need to remember
176 * pending events.
177 * This applies to any hw interrupts that allow a second
178 * instance of the same irq to arrive while we are in do_IRQ
179 * or in the handler. But the code here only handles the _second_
180 * instance of the irq, not the third or fourth. So it is mostly
181 * useful for irq hardware that does not mask cleanly in an
182 * SMP environment.
183 */
184 for (;;) {
185 irqreturn_t action_ret;
186
187 spin_unlock(&desc->lock);
188
189 action_ret = handle_IRQ_event(irq, regs, action);
190
191 spin_lock(&desc->lock);
192 if (!noirqdebug)
200803df 193 note_interrupt(irq, desc, action_ret, regs);
1da177e4
LT
194 if (likely(!(desc->status & IRQ_PENDING)))
195 break;
196 desc->status &= ~IRQ_PENDING;
197 }
198 desc->status &= ~IRQ_INPROGRESS;
199
200out:
201 /*
202 * The ->end() handler has to deal with interrupts which got
203 * disabled while the handler was running.
204 */
d1bef4ed 205 desc->chip->end(irq);
1da177e4
LT
206 spin_unlock(&desc->lock);
207
208 return 1;
209}
210
This page took 0.206434 seconds and 5 git commands to generate.