intr.c revision 1.15 1 1.15 matt /* $NetBSD: intr.c,v 1.15 2007/02/18 07:13:18 matt Exp $ */
2 1.1 chris
3 1.1 chris /*
4 1.1 chris * Copyright (c) 1994-1998 Mark Brinicombe.
5 1.1 chris * All rights reserved.
6 1.1 chris *
7 1.1 chris * Redistribution and use in source and binary forms, with or without
8 1.1 chris * modification, are permitted provided that the following conditions
9 1.1 chris * are met:
10 1.1 chris * 1. Redistributions of source code must retain the above copyright
11 1.1 chris * notice, this list of conditions and the following disclaimer.
12 1.1 chris * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 chris * notice, this list of conditions and the following disclaimer in the
14 1.1 chris * documentation and/or other materials provided with the distribution.
15 1.1 chris * 3. All advertising materials mentioning features or use of this software
16 1.1 chris * must display the following acknowledgement:
17 1.1 chris * This product includes software developed by Mark Brinicombe
18 1.1 chris * for the NetBSD Project.
19 1.1 chris * 4. The name of the company nor the name of the author may be used to
20 1.1 chris * endorse or promote products derived from this software without specific
21 1.1 chris * prior written permission.
22 1.1 chris *
23 1.1 chris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 1.1 chris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 1.1 chris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.1 chris * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 1.1 chris * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 1.1 chris * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 1.1 chris * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 chris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 chris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 chris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 chris * SUCH DAMAGE.
34 1.1 chris *
35 1.1 chris * Soft interrupt and other generic interrupt functions.
36 1.1 chris */
37 1.12 lukem
38 1.12 lukem #include <sys/cdefs.h>
39 1.15 matt __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.15 2007/02/18 07:13:18 matt Exp $");
40 1.1 chris
41 1.1 chris #include "opt_irqstats.h"
42 1.1 chris
43 1.1 chris #include <sys/param.h>
44 1.1 chris #include <sys/systm.h>
45 1.1 chris #include <sys/syslog.h>
46 1.1 chris #include <sys/malloc.h>
47 1.9 gehenna #include <sys/conf.h>
48 1.1 chris
49 1.1 chris #include <uvm/uvm_extern.h>
50 1.1 chris
51 1.10 bsh #include <machine/atomic.h>
52 1.2 matt #include <machine/intr.h>
53 1.1 chris #include <machine/cpu.h>
54 1.1 chris
55 1.1 chris #include <net/netisr.h>
56 1.1 chris
57 1.6 chris #include <arm/arm32/machdep.h>
58 1.6 chris
59 1.15 matt extern int current_spl_level;
60 1.15 matt
61 1.15 matt extern unsigned spl_mask;
62 1.3 rearnsha
63 1.15 matt /* Generate soft interrupt counts if IRQSTATS is defined */
64 1.6 chris /* Prototypes */
65 1.15 matt static void clearsoftintr(u_int);
66 1.6 chris
67 1.1 chris u_int soft_interrupts = 0;
68 1.1 chris
69 1.15 matt #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
70 1.1 chris #ifdef IRQSTATS
71 1.1 chris extern u_int sintrcnt[];
72 1.1 chris #define INC_SINTRCNT(x) ++sintrcnt[x]
73 1.1 chris #else
74 1.1 chris #define INC_SINTRCNT(x)
75 1.1 chris #endif /* IRQSTATS */
76 1.15 matt #else
77 1.15 matt #define INC_SINTRCNT(x)
78 1.15 matt #endif /* !__HAVE_GENERIC_SOFT_INTERRUPTS */
79 1.1 chris
80 1.1 chris #define COUNT uvmexp.softs;
81 1.1 chris
82 1.1 chris /* Prototypes */
83 1.1 chris
84 1.1 chris #include "com.h"
85 1.1 chris #if NCOM > 0
86 1.15 matt extern void comsoft(void);
87 1.1 chris #endif /* NCOM > 0 */
88 1.1 chris
89 1.3 rearnsha #if NPLCOM > 0
90 1.15 matt extern void plcomsoft(void);
91 1.3 rearnsha #endif /* NPLCOM > 0 */
92 1.3 rearnsha
93 1.1 chris /* Eventually these will become macros */
94 1.1 chris
95 1.15 matt #define SI_SOFTMASK(si) (1U << (si))
96 1.15 matt
97 1.15 matt static inline void
98 1.15 matt clearsoftintr(u_int intrmask)
99 1.15 matt {
100 1.15 matt atomic_clear_bit(&soft_interrupts, intrmask);
101 1.15 matt }
102 1.15 matt
103 1.15 matt #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
104 1.15 matt void
105 1.15 matt _setsoftintr(int si)
106 1.15 matt {
107 1.15 matt atomic_set_bit(&soft_interrupts, SI_SOFTMASK(si));
108 1.15 matt }
109 1.15 matt #else /* __HAVE_GENERIC_SOFT_INTERRUPTS */
110 1.15 matt #define SI_SOFTNET SOFTIRQ_NET
111 1.15 matt #define SI_SOFTCLOCK SOFTIRQ_CLOCK
112 1.15 matt #define SI_SOFTSERIAL SOFTIRQ_SERIAL
113 1.1 chris void
114 1.15 matt setsoftintr(u_int intrmask)
115 1.1 chris {
116 1.1 chris atomic_set_bit(&soft_interrupts, intrmask);
117 1.1 chris }
118 1.1 chris
119 1.15 matt void
120 1.15 matt setsoftclock(void)
121 1.1 chris {
122 1.15 matt atomic_set_bit(&soft_interrupts, SI_MASK(SI_SOFTCLOCK));
123 1.1 chris }
124 1.1 chris
125 1.1 chris void
126 1.15 matt setsoftnet(void)
127 1.1 chris {
128 1.15 matt atomic_set_bit(&soft_interrupts, SI_MASK(SI_SOFTNET));
129 1.1 chris }
130 1.1 chris
131 1.1 chris void
132 1.15 matt setsoftserial(void)
133 1.1 chris {
134 1.15 matt atomic_set_bit(&soft_interrupts, SI_MASK(SI_SOFTSERIAL));
135 1.1 chris }
136 1.1 chris
137 1.15 matt static void
138 1.15 matt softnet(void)
139 1.1 chris {
140 1.15 matt #define DONETISR(bit, fn) do { \
141 1.15 matt if (netisr & (1 << bit)) { \
142 1.15 matt atomic_clear_bit(&netisr, (1 << bit)); \
143 1.15 matt fn(); \
144 1.15 matt } \
145 1.15 matt } while (0)
146 1.15 matt
147 1.15 matt #include <net/netisr_dispatch.h>
148 1.15 matt
149 1.15 matt #undef DONETISR
150 1.1 chris }
151 1.15 matt #endif /* !__HAVE_GENERIC_SOFT_INTERRUPTS */
152 1.1 chris
153 1.1 chris /* Handle software interrupts */
154 1.1 chris
155 1.1 chris void
156 1.15 matt dosoftints(void)
157 1.1 chris {
158 1.1 chris u_int softints;
159 1.1 chris int s;
160 1.1 chris
161 1.1 chris softints = soft_interrupts & spl_smasks[current_spl_level];
162 1.1 chris if (softints == 0) return;
163 1.1 chris
164 1.1 chris /*
165 1.15 matt * Serial software interrupts
166 1.1 chris */
167 1.15 matt if (softints & SI_SOFTMASK(SI_SOFTSERIAL)) {
168 1.15 matt s = splsoftserial();
169 1.1 chris ++COUNT;
170 1.15 matt INC_SINTRCNT(SI_SOFTSERIAL);
171 1.15 matt clearsoftintr(SI_SOFTMASK(SI_SOFTSERIAL));
172 1.15 matt #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
173 1.15 matt #if NCOM > 0
174 1.15 matt comsoft();
175 1.15 matt #endif /* NCOM > 0 */
176 1.15 matt #if NPLCOM > 0
177 1.15 matt plcomsoft();
178 1.15 matt #endif /* NPLCOM > 0 */
179 1.15 matt #else
180 1.15 matt softintr_dispatch(SI_SOFTSERIAL);
181 1.15 matt #endif
182 1.1 chris (void)splx(s);
183 1.1 chris }
184 1.1 chris
185 1.1 chris /*
186 1.1 chris * Network software interrupts
187 1.1 chris */
188 1.15 matt if (softints & SI_SOFTMASK(SI_SOFTNET)) {
189 1.1 chris s = splsoftnet();
190 1.1 chris ++COUNT;
191 1.15 matt INC_SINTRCNT(SI_SOFTNET);
192 1.15 matt clearsoftintr(SI_SOFTMASK(SI_SOFTNET));
193 1.15 matt #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
194 1.15 matt softnet();
195 1.15 matt #else
196 1.15 matt softintr_dispatch(SI_SOFTNET);
197 1.15 matt #endif
198 1.15 matt (void)splx(s);
199 1.15 matt }
200 1.1 chris
201 1.15 matt /*
202 1.15 matt * Software clock interrupts
203 1.15 matt */
204 1.15 matt if (softints & SI_SOFTMASK(SI_SOFTCLOCK)) {
205 1.15 matt s = splsoftclock();
206 1.15 matt ++COUNT;
207 1.15 matt INC_SINTRCNT(SI_SOFTCLOCK);
208 1.15 matt clearsoftintr(SI_SOFTMASK(SI_SOFTCLOCK));
209 1.15 matt #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
210 1.15 matt softclock(NULL);
211 1.15 matt #else
212 1.15 matt softintr_dispatch(SI_SOFTCLOCK);
213 1.15 matt #endif
214 1.1 chris (void)splx(s);
215 1.1 chris }
216 1.15 matt
217 1.1 chris /*
218 1.15 matt * Misc software interrupts
219 1.1 chris */
220 1.15 matt #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
221 1.15 matt if (softints & SI_SOFTMASK(SI_SOFT)) {
222 1.15 matt s = splsoft();
223 1.1 chris ++COUNT;
224 1.15 matt clearsoftintr(SI_SOFTMASK(SI_SOFT));
225 1.15 matt softintr_dispatch(SI_SOFT);
226 1.1 chris (void)splx(s);
227 1.1 chris }
228 1.15 matt #endif
229 1.1 chris }
230 1.4 thorpej
231 1.4 thorpej int current_spl_level = _SPL_SERIAL;
232 1.4 thorpej u_int spl_masks[_SPL_LEVELS + 1];
233 1.4 thorpej u_int spl_smasks[_SPL_LEVELS];
234 1.4 thorpej int safepri = _SPL_0;
235 1.7 thorpej
236 1.8 chris extern u_int irqmasks[];
237 1.4 thorpej
238 1.4 thorpej void
239 1.15 matt set_spl_masks(void)
240 1.4 thorpej {
241 1.4 thorpej int loop;
242 1.4 thorpej
243 1.4 thorpej for (loop = 0; loop < _SPL_LEVELS; ++loop) {
244 1.4 thorpej spl_masks[loop] = 0xffffffff;
245 1.4 thorpej spl_smasks[loop] = 0;
246 1.4 thorpej }
247 1.4 thorpej
248 1.4 thorpej spl_masks[_SPL_BIO] = irqmasks[IPL_BIO];
249 1.4 thorpej spl_masks[_SPL_NET] = irqmasks[IPL_NET];
250 1.4 thorpej spl_masks[_SPL_SOFTSERIAL] = irqmasks[IPL_TTY];
251 1.4 thorpej spl_masks[_SPL_TTY] = irqmasks[IPL_TTY];
252 1.11 thorpej spl_masks[_SPL_VM] = irqmasks[IPL_VM];
253 1.4 thorpej spl_masks[_SPL_AUDIO] = irqmasks[IPL_AUDIO];
254 1.4 thorpej spl_masks[_SPL_CLOCK] = irqmasks[IPL_CLOCK];
255 1.4 thorpej #ifdef IPL_STATCLOCK
256 1.4 thorpej spl_masks[_SPL_STATCLOCK] = irqmasks[IPL_STATCLOCK];
257 1.4 thorpej #else
258 1.4 thorpej spl_masks[_SPL_STATCLOCK] = irqmasks[IPL_CLOCK];
259 1.4 thorpej #endif
260 1.4 thorpej spl_masks[_SPL_HIGH] = irqmasks[IPL_HIGH];
261 1.4 thorpej spl_masks[_SPL_SERIAL] = irqmasks[IPL_SERIAL];
262 1.4 thorpej spl_masks[_SPL_LEVELS] = 0;
263 1.4 thorpej
264 1.4 thorpej spl_smasks[_SPL_0] = 0xffffffff;
265 1.4 thorpej for (loop = 0; loop < _SPL_SOFTSERIAL; ++loop)
266 1.15 matt spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTSERIAL);
267 1.4 thorpej for (loop = 0; loop < _SPL_SOFTNET; ++loop)
268 1.15 matt spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTNET);
269 1.4 thorpej for (loop = 0; loop < _SPL_SOFTCLOCK; ++loop)
270 1.15 matt spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTCLOCK);
271 1.15 matt #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
272 1.15 matt for (loop = 0; loop < _SPL_SOFT; ++loop)
273 1.15 matt spl_smasks[loop] |= SI_SOFTMASK(SI_SOFT);
274 1.15 matt #endif
275 1.4 thorpej }
276 1.4 thorpej
277 1.15 matt static const int ipl_to_spl_map[] = {
278 1.15 matt [IPL_NONE] = 1 + _SPL_0,
279 1.15 matt #ifdef IPL_SOFT
280 1.15 matt [IPL_SOFT] = 1 + _SPL_SOFT,
281 1.15 matt #endif /* IPL_SOFTCLOCK */
282 1.14 yamt #if defined(IPL_SOFTCLOCK)
283 1.15 matt [IPL_SOFTCLOCK] = 1 + _SPL_SOFTCLOCK,
284 1.14 yamt #endif /* defined(IPL_SOFTCLOCK) */
285 1.14 yamt #if defined(IPL_SOFTNET)
286 1.15 matt [IPL_SOFTNET] = 1 + _SPL_SOFTNET,
287 1.14 yamt #endif /* defined(IPL_SOFTNET) */
288 1.15 matt [IPL_BIO] = 1 + _SPL_BIO,
289 1.15 matt [IPL_NET] = 1 + _SPL_NET,
290 1.14 yamt #if defined(IPL_SOFTSERIAL)
291 1.15 matt [IPL_SOFTSERIAL] = 1 + _SPL_SOFTSERIAL,
292 1.14 yamt #endif /* defined(IPL_SOFTSERIAL) */
293 1.15 matt [IPL_TTY] = 1 + _SPL_TTY,
294 1.15 matt [IPL_VM] = 1 + _SPL_VM,
295 1.15 matt [IPL_AUDIO] = 1 + _SPL_AUDIO,
296 1.15 matt [IPL_CLOCK] = 1 + _SPL_CLOCK,
297 1.15 matt [IPL_STATCLOCK] = 1 + _SPL_STATCLOCK,
298 1.15 matt [IPL_HIGH] = 1 + _SPL_HIGH,
299 1.15 matt [IPL_SERIAL] = 1 + _SPL_SERIAL,
300 1.15 matt };
301 1.15 matt
302 1.15 matt int
303 1.15 matt ipl_to_spl(int ipl)
304 1.15 matt {
305 1.15 matt KASSERT(ipl < __arraycount(ipl_to_spl_map));
306 1.15 matt KASSERT(ipl_to_spl_map[ipl]);
307 1.15 matt
308 1.15 matt return ipl_to_spl_map[ipl] - 1;
309 1.14 yamt }
310 1.14 yamt
311 1.4 thorpej #ifdef DIAGNOSTIC
312 1.4 thorpej void
313 1.15 matt dump_spl_masks(void)
314 1.4 thorpej {
315 1.4 thorpej int loop;
316 1.4 thorpej
317 1.4 thorpej for (loop = 0; loop < _SPL_LEVELS; ++loop) {
318 1.4 thorpej printf("spl_mask[%d]=%08x splsmask[%d]=%08x\n", loop,
319 1.4 thorpej spl_masks[loop], loop, spl_smasks[loop]);
320 1.4 thorpej }
321 1.4 thorpej }
322 1.4 thorpej #endif
323 1.1 chris
324 1.1 chris /* End of intr.c */
325