1 /* $NetBSD: intr.c,v 1.25 2007/12/03 15:33:16 ad 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.25 2007/12/03 15:33:16 ad 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 extern int current_spl_level; 60 61 /* Generate soft interrupt counts if IRQSTATS is defined */ 62 /* Prototypes */ 63 static void clearsoftintr(u_int); 64 65 static u_int soft_interrupts = 0; 66 static u_int spl_smasks[_SPL_LEVELS]; 67 68 /* Eventually these will become macros */ 69 70 #define SI_SOFTMASK(si) (1U << (si)) 71 72 static inline void 73 clearsoftintr(u_int intrmask) 74 { 75 atomic_clear_bit(&soft_interrupts, intrmask); 76 } 77 78 void 79 _setsoftintr(int si) 80 { 81 atomic_set_bit(&soft_interrupts, SI_SOFTMASK(si)); 82 } 83 84 #ifdef __HAVE_FAST_SOFTINTS 85 /* Handle software interrupts */ 86 87 void 88 dosoftints(void) 89 { 90 u_int softints; 91 int s; 92 93 softints = soft_interrupts & spl_smasks[current_spl_level]; 94 if (softints == 0) return; 95 96 /* 97 * Serial software interrupts 98 */ 99 if (softints & SI_SOFTMASK(SI_SOFTSERIAL)) { 100 s = splsoftserial(); 101 clearsoftintr(SI_SOFTMASK(SI_SOFTSERIAL)); 102 softintr_dispatch(SI_SOFTSERIAL); 103 (void)splx(s); 104 } 105 106 /* 107 * Network software interrupts 108 */ 109 if (softints & SI_SOFTMASK(SI_SOFTNET)) { 110 s = splsoftnet(); 111 clearsoftintr(SI_SOFTMASK(SI_SOFTNET)); 112 softintr_dispatch(SI_SOFTNET); 113 (void)splx(s); 114 } 115 116 /* 117 * Block software interrupts 118 */ 119 if (softints & SI_SOFTMASK(SI_SOFTBIO)) { 120 s = splsoftbio(); 121 clearsoftintr(SI_SOFTMASK(SI_SOFTBIO)); 122 softintr_dispatch(SI_SOFTBIO); 123 (void)splx(s); 124 } 125 126 /* 127 * Software clock interrupts 128 */ 129 if (softints & SI_SOFTMASK(SI_SOFTCLOCK)) { 130 s = splsoftclock(); 131 clearsoftintr(SI_SOFTMASK(SI_SOFTCLOCK)); 132 softintr_dispatch(SI_SOFTCLOCK); 133 (void)splx(s); 134 } 135 } 136 #endif 137 138 int current_spl_level = _SPL_HIGH; 139 u_int spl_masks[_SPL_LEVELS + 1]; 140 int safepri = _SPL_0; 141 142 extern u_int irqmasks[]; 143 144 void 145 set_spl_masks(void) 146 { 147 int loop; 148 149 for (loop = 0; loop < _SPL_LEVELS; ++loop) { 150 spl_masks[loop] = 0xffffffff; 151 spl_smasks[loop] = 0; 152 } 153 154 spl_masks[_SPL_VM] = irqmasks[IPL_VM]; 155 spl_masks[_SPL_SCHED] = irqmasks[IPL_SCHED]; 156 spl_masks[_SPL_HIGH] = irqmasks[IPL_HIGH]; 157 spl_masks[_SPL_LEVELS] = 0; 158 159 spl_smasks[_SPL_0] = 0xffffffff; 160 for (loop = 0; loop < _SPL_SOFTSERIAL; ++loop) 161 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTSERIAL); 162 for (loop = 0; loop < _SPL_SOFTNET; ++loop) 163 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTNET); 164 for (loop = 0; loop < _SPL_SOFTCLOCK; ++loop) 165 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTCLOCK); 166 for (loop = 0; loop < _SPL_SOFTBIO; ++loop) 167 spl_smasks[loop] |= SI_SOFTMASK(SI_SOFTBIO); 168 } 169 170 static const int ipl_to_spl_map[] = { 171 [IPL_NONE] = 1 + _SPL_0, 172 [IPL_SOFTCLOCK] = 1 + _SPL_SOFTCLOCK, 173 [IPL_SOFTBIO] = 1 + _SPL_SOFTBIO, 174 [IPL_SOFTNET] = 1 + _SPL_SOFTNET, 175 [IPL_SOFTSERIAL] = 1 + _SPL_SOFTSERIAL, 176 [IPL_VM] = 1 + _SPL_VM, 177 [IPL_SCHED] = 1 + _SPL_SCHED, 178 [IPL_HIGH] = 1 + _SPL_HIGH, 179 }; 180 181 int 182 ipl_to_spl(ipl_t ipl) 183 { 184 int spl; 185 186 KASSERT(ipl < __arraycount(ipl_to_spl_map)); 187 KASSERT(ipl_to_spl_map[ipl]); 188 189 spl = ipl_to_spl_map[ipl] - 1; 190 KASSERT(spl < 0x100); 191 192 return spl; 193 } 194 195 #ifdef DIAGNOSTIC 196 void 197 dump_spl_masks(void) 198 { 199 int loop; 200 201 for (loop = 0; loop < _SPL_LEVELS; ++loop) { 202 printf("spl_masks[%d]=%08x splsmask[%d]=%08x\n", loop, 203 spl_masks[loop], loop, spl_smasks[loop]); 204 } 205 } 206 #endif 207 208 /* End of intr.c */ 209