1 1.30 thorpej /* $NetBSD: shared_intr.c,v 1.30 2023/11/21 17:52:51 thorpej Exp $ */ 2 1.25 thorpej 3 1.25 thorpej /* 4 1.25 thorpej * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 1.25 thorpej * All rights reserved. 6 1.25 thorpej * 7 1.25 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.25 thorpej * by Jason R. Thorpe. 9 1.25 thorpej * 10 1.25 thorpej * Redistribution and use in source and binary forms, with or without 11 1.25 thorpej * modification, are permitted provided that the following conditions 12 1.25 thorpej * are met: 13 1.25 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.25 thorpej * notice, this list of conditions and the following disclaimer. 15 1.25 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.25 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.25 thorpej * documentation and/or other materials provided with the distribution. 18 1.25 thorpej * 19 1.25 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.25 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.25 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.25 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.25 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.25 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.25 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.25 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.25 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.25 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.25 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.25 thorpej */ 31 1.1 cgd 32 1.1 cgd /* 33 1.1 cgd * Copyright (c) 1996 Carnegie-Mellon University. 34 1.1 cgd * All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Authors: Chris G. Demetriou 37 1.21 matt * 38 1.1 cgd * Permission to use, copy, modify and distribute this software and 39 1.1 cgd * its documentation is hereby granted, provided that both the copyright 40 1.1 cgd * notice and this permission notice appear in all copies of the 41 1.1 cgd * software, derivative works or modified versions, and any portions 42 1.1 cgd * thereof, and that both notices appear in supporting documentation. 43 1.21 matt * 44 1.21 matt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 45 1.21 matt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 46 1.1 cgd * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 47 1.21 matt * 48 1.1 cgd * Carnegie Mellon requests users of this software to return to 49 1.1 cgd * 50 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 51 1.1 cgd * School of Computer Science 52 1.1 cgd * Carnegie Mellon University 53 1.1 cgd * Pittsburgh PA 15213-3890 54 1.1 cgd * 55 1.1 cgd * any improvements or extensions that they make and grant Carnegie the 56 1.1 cgd * rights to redistribute these changes. 57 1.1 cgd */ 58 1.1 cgd 59 1.1 cgd /* 60 1.1 cgd * Common shared-interrupt-line functionality. 61 1.1 cgd */ 62 1.2 cgd 63 1.3 cgd #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 64 1.3 cgd 65 1.30 thorpej __KERNEL_RCSID(0, "$NetBSD: shared_intr.c,v 1.30 2023/11/21 17:52:51 thorpej Exp $"); 66 1.1 cgd 67 1.1 cgd #include <sys/param.h> 68 1.7 thorpej #include <sys/kernel.h> 69 1.25 thorpej #include <sys/cpu.h> 70 1.25 thorpej #include <sys/kmem.h> 71 1.25 thorpej #include <sys/kmem.h> 72 1.1 cgd #include <sys/systm.h> 73 1.1 cgd #include <sys/syslog.h> 74 1.1 cgd #include <sys/queue.h> 75 1.19 ad #include <sys/atomic.h> 76 1.19 ad #include <sys/intr.h> 77 1.25 thorpej #include <sys/xcall.h> 78 1.1 cgd 79 1.1 cgd static const char * 80 1.14 thorpej intr_typename(int type) 81 1.1 cgd { 82 1.1 cgd 83 1.1 cgd switch (type) { 84 1.1 cgd case IST_UNUSABLE: 85 1.1 cgd return ("disabled"); 86 1.1 cgd case IST_NONE: 87 1.1 cgd return ("none"); 88 1.1 cgd case IST_PULSE: 89 1.1 cgd return ("pulsed"); 90 1.1 cgd case IST_EDGE: 91 1.1 cgd return ("edge-triggered"); 92 1.1 cgd case IST_LEVEL: 93 1.1 cgd return ("level-triggered"); 94 1.1 cgd } 95 1.1 cgd panic("intr_typename: unknown type %d", type); 96 1.1 cgd } 97 1.1 cgd 98 1.1 cgd struct alpha_shared_intr * 99 1.29 thorpej alpha_shared_intr_alloc(unsigned int n) 100 1.1 cgd { 101 1.1 cgd struct alpha_shared_intr *intr; 102 1.1 cgd unsigned int i; 103 1.1 cgd 104 1.29 thorpej KASSERT(n != 0); 105 1.29 thorpej 106 1.25 thorpej intr = kmem_alloc(n * sizeof(*intr), KM_SLEEP); 107 1.1 cgd for (i = 0; i < n; i++) { 108 1.1 cgd TAILQ_INIT(&intr[i].intr_q); 109 1.1 cgd intr[i].intr_sharetype = IST_NONE; 110 1.1 cgd intr[i].intr_dfltsharetype = IST_NONE; 111 1.1 cgd intr[i].intr_nstrays = 0; 112 1.29 thorpej intr[i].intr_maxstrays = 0; 113 1.11 mjacob intr[i].intr_private = NULL; 114 1.25 thorpej intr[i].intr_cpu = NULL; 115 1.29 thorpej intr[i].intr_string = kmem_asprintf("irq %u", i); 116 1.1 cgd } 117 1.1 cgd 118 1.1 cgd return (intr); 119 1.1 cgd } 120 1.1 cgd 121 1.1 cgd int 122 1.14 thorpej alpha_shared_intr_dispatch(struct alpha_shared_intr *intr, unsigned int num) 123 1.1 cgd { 124 1.1 cgd struct alpha_shared_intrhand *ih; 125 1.30 thorpej int rv = 0; 126 1.1 cgd 127 1.19 ad atomic_add_long(&intr[num].intr_evcnt.ev_count, 1); 128 1.15 thorpej 129 1.30 thorpej TAILQ_FOREACH(ih, &intr[num].intr_q, ih_q) { 130 1.1 cgd /* 131 1.1 cgd * The handler returns one of three values: 132 1.1 cgd * 0: This interrupt wasn't for me. 133 1.1 cgd * 1: This interrupt was for me. 134 1.1 cgd * -1: This interrupt might have been for me, but I can't say 135 1.1 cgd * for sure. 136 1.1 cgd */ 137 1.30 thorpej rv |= (*ih->ih_fn)(ih->ih_arg); 138 1.1 cgd } 139 1.1 cgd 140 1.30 thorpej return (rv ? 1 : 0); 141 1.1 cgd } 142 1.1 cgd 143 1.24 thorpej static int 144 1.24 thorpej alpha_shared_intr_wrapper(void * const arg) 145 1.24 thorpej { 146 1.24 thorpej struct alpha_shared_intrhand * const ih = arg; 147 1.24 thorpej int rv; 148 1.24 thorpej 149 1.24 thorpej KERNEL_LOCK(1, NULL); 150 1.24 thorpej rv = (*ih->ih_real_fn)(ih->ih_real_arg); 151 1.24 thorpej KERNEL_UNLOCK_ONE(NULL); 152 1.24 thorpej 153 1.24 thorpej return rv; 154 1.24 thorpej } 155 1.24 thorpej 156 1.25 thorpej struct alpha_shared_intrhand * 157 1.25 thorpej alpha_shared_intr_alloc_intrhand(struct alpha_shared_intr *intr, 158 1.25 thorpej unsigned int num, int type, int level, int flags, 159 1.23 thorpej int (*fn)(void *), void *arg, const char *basename) 160 1.1 cgd { 161 1.1 cgd struct alpha_shared_intrhand *ih; 162 1.1 cgd 163 1.1 cgd if (intr[num].intr_sharetype == IST_UNUSABLE) { 164 1.28 thorpej printf("%s: %s irq %d: unusable\n", __func__, 165 1.1 cgd basename, num); 166 1.1 cgd return NULL; 167 1.1 cgd } 168 1.1 cgd 169 1.25 thorpej KASSERT(type != IST_NONE); 170 1.25 thorpej 171 1.25 thorpej ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 172 1.25 thorpej 173 1.25 thorpej ih->ih_intrhead = intr; 174 1.25 thorpej ih->ih_fn = ih->ih_real_fn = fn; 175 1.25 thorpej ih->ih_arg = ih->ih_real_arg = arg; 176 1.25 thorpej ih->ih_level = level; 177 1.25 thorpej ih->ih_type = type; 178 1.25 thorpej ih->ih_num = num; 179 1.25 thorpej 180 1.25 thorpej /* 181 1.25 thorpej * Non-MPSAFE interrupts get a wrapper that takes the 182 1.25 thorpej * KERNEL_LOCK. 183 1.25 thorpej */ 184 1.25 thorpej if ((flags & ALPHA_INTR_MPSAFE) == 0) { 185 1.25 thorpej ih->ih_fn = alpha_shared_intr_wrapper; 186 1.25 thorpej ih->ih_arg = ih; 187 1.25 thorpej } 188 1.25 thorpej 189 1.25 thorpej return (ih); 190 1.25 thorpej } 191 1.25 thorpej 192 1.25 thorpej void 193 1.25 thorpej alpha_shared_intr_free_intrhand(struct alpha_shared_intrhand *ih) 194 1.25 thorpej { 195 1.25 thorpej 196 1.25 thorpej kmem_free(ih, sizeof(*ih)); 197 1.25 thorpej } 198 1.25 thorpej 199 1.25 thorpej static void 200 1.25 thorpej alpha_shared_intr_link_unlink_xcall(void *arg1, void *arg2) 201 1.25 thorpej { 202 1.25 thorpej struct alpha_shared_intrhand *ih = arg1; 203 1.25 thorpej struct alpha_shared_intr *intr = ih->ih_intrhead; 204 1.25 thorpej unsigned int num = ih->ih_num; 205 1.25 thorpej 206 1.26 thorpej struct cpu_info *ci = intr[num].intr_cpu; 207 1.26 thorpej 208 1.26 thorpej KASSERT(ci != NULL); 209 1.25 thorpej KASSERT(ci == curcpu() || !mp_online); 210 1.25 thorpej KASSERT(!cpu_intr_p()); 211 1.25 thorpej 212 1.25 thorpej const unsigned long psl = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); 213 1.25 thorpej 214 1.25 thorpej if (arg2 != NULL) { 215 1.25 thorpej TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q); 216 1.25 thorpej ci->ci_nintrhand++; 217 1.25 thorpej } else { 218 1.25 thorpej TAILQ_REMOVE(&intr[num].intr_q, ih, ih_q); 219 1.25 thorpej ci->ci_nintrhand--; 220 1.25 thorpej } 221 1.25 thorpej 222 1.25 thorpej alpha_pal_swpipl(psl); 223 1.25 thorpej } 224 1.25 thorpej 225 1.25 thorpej bool 226 1.25 thorpej alpha_shared_intr_link(struct alpha_shared_intr *intr, 227 1.25 thorpej struct alpha_shared_intrhand *ih, const char *basename) 228 1.25 thorpej { 229 1.25 thorpej int type = ih->ih_type; 230 1.25 thorpej unsigned int num = ih->ih_num; 231 1.25 thorpej 232 1.25 thorpej KASSERT(mutex_owned(&cpu_lock)); 233 1.25 thorpej KASSERT(ih->ih_intrhead == intr); 234 1.1 cgd 235 1.1 cgd switch (intr[num].intr_sharetype) { 236 1.1 cgd case IST_EDGE: 237 1.1 cgd case IST_LEVEL: 238 1.1 cgd if (type == intr[num].intr_sharetype) 239 1.1 cgd break; 240 1.1 cgd case IST_PULSE: 241 1.1 cgd if (type != IST_NONE) { 242 1.30 thorpej if (TAILQ_FIRST(&intr[num].intr_q) == NULL) { 243 1.28 thorpej printf("alpha_shared_intr_establish: %s irq %d: warning: using %s on %s\n", 244 1.1 cgd basename, num, intr_typename(type), 245 1.1 cgd intr_typename(intr[num].intr_sharetype)); 246 1.1 cgd type = intr[num].intr_sharetype; 247 1.1 cgd } else { 248 1.28 thorpej printf("alpha_shared_intr_establish: %s irq %d: can't share %s with %s\n", 249 1.1 cgd basename, num, intr_typename(type), 250 1.1 cgd intr_typename(intr[num].intr_sharetype)); 251 1.25 thorpej return (false); 252 1.1 cgd } 253 1.1 cgd } 254 1.1 cgd break; 255 1.1 cgd 256 1.1 cgd case IST_NONE: 257 1.1 cgd /* not currently used; safe */ 258 1.1 cgd break; 259 1.1 cgd } 260 1.1 cgd 261 1.25 thorpej intr[num].intr_sharetype = type; 262 1.24 thorpej 263 1.24 thorpej /* 264 1.25 thorpej * If a CPU hasn't been assigned yet, just give it to the 265 1.25 thorpej * primary. 266 1.24 thorpej */ 267 1.26 thorpej if (intr[num].intr_cpu == NULL) { 268 1.26 thorpej intr[num].intr_cpu = &cpu_info_primary; 269 1.24 thorpej } 270 1.1 cgd 271 1.25 thorpej kpreempt_disable(); 272 1.26 thorpej if (intr[num].intr_cpu == curcpu() || !mp_online) { 273 1.26 thorpej alpha_shared_intr_link_unlink_xcall(ih, ih); 274 1.25 thorpej } else { 275 1.25 thorpej uint64_t where = xc_unicast(XC_HIGHPRI, 276 1.26 thorpej alpha_shared_intr_link_unlink_xcall, ih, ih, 277 1.26 thorpej intr->intr_cpu); 278 1.25 thorpej xc_wait(where); 279 1.25 thorpej } 280 1.25 thorpej kpreempt_enable(); 281 1.1 cgd 282 1.25 thorpej return (true); 283 1.6 thorpej } 284 1.6 thorpej 285 1.6 thorpej void 286 1.25 thorpej alpha_shared_intr_unlink(struct alpha_shared_intr *intr, 287 1.25 thorpej struct alpha_shared_intrhand *ih, const char *basename) 288 1.6 thorpej { 289 1.26 thorpej unsigned int num = ih->ih_num; 290 1.6 thorpej 291 1.25 thorpej KASSERT(mutex_owned(&cpu_lock)); 292 1.25 thorpej 293 1.25 thorpej kpreempt_disable(); 294 1.26 thorpej if (intr[num].intr_cpu == curcpu() || !mp_online) { 295 1.25 thorpej alpha_shared_intr_link_unlink_xcall(ih, NULL); 296 1.25 thorpej } else { 297 1.25 thorpej uint64_t where = xc_unicast(XC_HIGHPRI, 298 1.25 thorpej alpha_shared_intr_link_unlink_xcall, ih, NULL, 299 1.26 thorpej intr->intr_cpu); 300 1.25 thorpej xc_wait(where); 301 1.25 thorpej } 302 1.25 thorpej kpreempt_enable(); 303 1.1 cgd } 304 1.1 cgd 305 1.1 cgd int 306 1.14 thorpej alpha_shared_intr_get_sharetype(struct alpha_shared_intr *intr, 307 1.14 thorpej unsigned int num) 308 1.1 cgd { 309 1.1 cgd 310 1.1 cgd return (intr[num].intr_sharetype); 311 1.1 cgd } 312 1.1 cgd 313 1.1 cgd int 314 1.14 thorpej alpha_shared_intr_isactive(struct alpha_shared_intr *intr, unsigned int num) 315 1.1 cgd { 316 1.1 cgd 317 1.30 thorpej return TAILQ_FIRST(&intr[num].intr_q) != NULL; 318 1.16 thorpej } 319 1.16 thorpej 320 1.16 thorpej int 321 1.16 thorpej alpha_shared_intr_firstactive(struct alpha_shared_intr *intr, unsigned int num) 322 1.16 thorpej { 323 1.30 thorpej struct alpha_shared_intrhand *ih; 324 1.16 thorpej 325 1.30 thorpej return (ih = TAILQ_FIRST(&intr[num].intr_q)) != NULL && 326 1.30 thorpej TAILQ_NEXT(ih, ih_q) == NULL; 327 1.1 cgd } 328 1.1 cgd 329 1.1 cgd void 330 1.14 thorpej alpha_shared_intr_set_dfltsharetype(struct alpha_shared_intr *intr, 331 1.14 thorpej unsigned int num, int newdfltsharetype) 332 1.1 cgd { 333 1.1 cgd 334 1.1 cgd #ifdef DIAGNOSTIC 335 1.1 cgd if (alpha_shared_intr_isactive(intr, num)) 336 1.1 cgd panic("alpha_shared_intr_set_dfltsharetype on active intr"); 337 1.1 cgd #endif 338 1.1 cgd 339 1.1 cgd intr[num].intr_dfltsharetype = newdfltsharetype; 340 1.1 cgd intr[num].intr_sharetype = intr[num].intr_dfltsharetype; 341 1.1 cgd } 342 1.1 cgd 343 1.1 cgd void 344 1.14 thorpej alpha_shared_intr_set_maxstrays(struct alpha_shared_intr *intr, 345 1.14 thorpej unsigned int num, int newmaxstrays) 346 1.1 cgd { 347 1.12 mjacob int s = splhigh(); 348 1.1 cgd intr[num].intr_maxstrays = newmaxstrays; 349 1.1 cgd intr[num].intr_nstrays = 0; 350 1.12 mjacob splx(s); 351 1.1 cgd } 352 1.1 cgd 353 1.1 cgd void 354 1.17 thorpej alpha_shared_intr_reset_strays(struct alpha_shared_intr *intr, 355 1.17 thorpej unsigned int num) 356 1.17 thorpej { 357 1.17 thorpej 358 1.17 thorpej /* 359 1.17 thorpej * Don't bother blocking interrupts; this doesn't have to be 360 1.17 thorpej * precise, but it does need to be fast. 361 1.17 thorpej */ 362 1.17 thorpej intr[num].intr_nstrays = 0; 363 1.17 thorpej } 364 1.17 thorpej 365 1.17 thorpej void 366 1.14 thorpej alpha_shared_intr_stray(struct alpha_shared_intr *intr, unsigned int num, 367 1.14 thorpej const char *basename) 368 1.1 cgd { 369 1.1 cgd 370 1.1 cgd intr[num].intr_nstrays++; 371 1.5 thorpej 372 1.5 thorpej if (intr[num].intr_maxstrays == 0) 373 1.5 thorpej return; 374 1.5 thorpej 375 1.1 cgd if (intr[num].intr_nstrays <= intr[num].intr_maxstrays) 376 1.28 thorpej log(LOG_ERR, "stray %s irq %d%s\n", basename, num, 377 1.1 cgd intr[num].intr_nstrays >= intr[num].intr_maxstrays ? 378 1.1 cgd "; stopped logging" : ""); 379 1.8 thorpej } 380 1.8 thorpej 381 1.8 thorpej void 382 1.14 thorpej alpha_shared_intr_set_private(struct alpha_shared_intr *intr, 383 1.14 thorpej unsigned int num, void *v) 384 1.8 thorpej { 385 1.8 thorpej 386 1.8 thorpej intr[num].intr_private = v; 387 1.8 thorpej } 388 1.8 thorpej 389 1.8 thorpej void * 390 1.14 thorpej alpha_shared_intr_get_private(struct alpha_shared_intr *intr, 391 1.14 thorpej unsigned int num) 392 1.8 thorpej { 393 1.8 thorpej 394 1.8 thorpej return (intr[num].intr_private); 395 1.15 thorpej } 396 1.15 thorpej 397 1.26 thorpej static unsigned int 398 1.26 thorpej alpha_shared_intr_q_count_handlers(struct alpha_shared_intr *intr_q) 399 1.26 thorpej { 400 1.26 thorpej unsigned int cnt = 0; 401 1.26 thorpej struct alpha_shared_intrhand *ih; 402 1.26 thorpej 403 1.26 thorpej TAILQ_FOREACH(ih, &intr_q->intr_q, ih_q) { 404 1.26 thorpej cnt++; 405 1.26 thorpej } 406 1.26 thorpej 407 1.26 thorpej return cnt; 408 1.26 thorpej } 409 1.26 thorpej 410 1.26 thorpej static void 411 1.26 thorpej alpha_shared_intr_set_cpu_xcall(void *arg1, void *arg2) 412 1.26 thorpej { 413 1.26 thorpej struct alpha_shared_intr *intr_q = arg1; 414 1.26 thorpej struct cpu_info *ci = arg2; 415 1.26 thorpej unsigned int cnt = alpha_shared_intr_q_count_handlers(intr_q); 416 1.26 thorpej 417 1.26 thorpej KASSERT(ci == curcpu() || !mp_online); 418 1.26 thorpej 419 1.26 thorpej ci->ci_nintrhand += cnt; 420 1.26 thorpej KASSERT(cnt <= ci->ci_nintrhand); 421 1.26 thorpej } 422 1.26 thorpej 423 1.26 thorpej static void 424 1.26 thorpej alpha_shared_intr_unset_cpu_xcall(void *arg1, void *arg2) 425 1.26 thorpej { 426 1.26 thorpej struct alpha_shared_intr *intr_q = arg1; 427 1.26 thorpej struct cpu_info *ci = arg2; 428 1.26 thorpej unsigned int cnt = alpha_shared_intr_q_count_handlers(intr_q); 429 1.26 thorpej 430 1.26 thorpej KASSERT(ci == curcpu() || !mp_online); 431 1.26 thorpej 432 1.26 thorpej KASSERT(cnt <= ci->ci_nintrhand); 433 1.26 thorpej ci->ci_nintrhand -= cnt; 434 1.26 thorpej } 435 1.26 thorpej 436 1.25 thorpej void 437 1.25 thorpej alpha_shared_intr_set_cpu(struct alpha_shared_intr *intr, unsigned int num, 438 1.25 thorpej struct cpu_info *ci) 439 1.25 thorpej { 440 1.26 thorpej struct cpu_info *old_ci; 441 1.26 thorpej 442 1.26 thorpej KASSERT(mutex_owned(&cpu_lock)); 443 1.25 thorpej 444 1.26 thorpej old_ci = intr[num].intr_cpu; 445 1.25 thorpej intr[num].intr_cpu = ci; 446 1.26 thorpej 447 1.26 thorpej if (old_ci != NULL && old_ci != ci) { 448 1.26 thorpej kpreempt_disable(); 449 1.26 thorpej 450 1.26 thorpej if (ci == curcpu() || !mp_online) { 451 1.26 thorpej alpha_shared_intr_set_cpu_xcall(&intr[num], ci); 452 1.26 thorpej } else { 453 1.26 thorpej uint64_t where = xc_unicast(XC_HIGHPRI, 454 1.26 thorpej alpha_shared_intr_set_cpu_xcall, &intr[num], 455 1.26 thorpej ci, ci); 456 1.26 thorpej xc_wait(where); 457 1.26 thorpej } 458 1.26 thorpej 459 1.26 thorpej if (old_ci == curcpu() || !mp_online) { 460 1.26 thorpej alpha_shared_intr_unset_cpu_xcall(&intr[num], old_ci); 461 1.26 thorpej } else { 462 1.26 thorpej uint64_t where = xc_unicast(XC_HIGHPRI, 463 1.26 thorpej alpha_shared_intr_unset_cpu_xcall, &intr[num], 464 1.26 thorpej old_ci, old_ci); 465 1.26 thorpej xc_wait(where); 466 1.26 thorpej } 467 1.26 thorpej 468 1.26 thorpej kpreempt_enable(); 469 1.26 thorpej } 470 1.25 thorpej } 471 1.25 thorpej 472 1.25 thorpej struct cpu_info * 473 1.25 thorpej alpha_shared_intr_get_cpu(struct alpha_shared_intr *intr, unsigned int num) 474 1.25 thorpej { 475 1.25 thorpej 476 1.25 thorpej return (intr[num].intr_cpu); 477 1.25 thorpej } 478 1.25 thorpej 479 1.15 thorpej struct evcnt * 480 1.15 thorpej alpha_shared_intr_evcnt(struct alpha_shared_intr *intr, 481 1.15 thorpej unsigned int num) 482 1.15 thorpej { 483 1.15 thorpej 484 1.15 thorpej return (&intr[num].intr_evcnt); 485 1.15 thorpej } 486 1.15 thorpej 487 1.29 thorpej void 488 1.29 thorpej alpha_shared_intr_set_string(struct alpha_shared_intr *intr, 489 1.29 thorpej unsigned int num, char *str) 490 1.29 thorpej { 491 1.29 thorpej char *ostr = intr[num].intr_string; 492 1.29 thorpej intr[num].intr_string = str; 493 1.29 thorpej kmem_strfree(ostr); 494 1.29 thorpej } 495 1.29 thorpej 496 1.29 thorpej const char * 497 1.15 thorpej alpha_shared_intr_string(struct alpha_shared_intr *intr, 498 1.15 thorpej unsigned int num) 499 1.15 thorpej { 500 1.15 thorpej 501 1.15 thorpej return (intr[num].intr_string); 502 1.1 cgd } 503