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