xref: /src/sys/powerpc/powerpc/intr_machdep.c (revision 27cb2610ef0ba6871f2649658778fb83179c0b2e)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1991 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * William Jolitz.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 /*-
35  * Copyright (c) 2002 Benno Rice.
36  * All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  *	form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
59  */
60 
61 #include "opt_isa.h"
62 
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/queue.h>
67 #include <sys/bus.h>
68 #include <sys/cpuset.h>
69 #include <sys/interrupt.h>
70 #include <sys/ktr.h>
71 #include <sys/lock.h>
72 #include <sys/malloc.h>
73 #include <sys/mutex.h>
74 #include <sys/pcpu.h>
75 #include <sys/smp.h>
76 #include <sys/syslog.h>
77 #include <sys/vmmeter.h>
78 #include <sys/proc.h>
79 
80 #include <machine/frame.h>
81 #include <machine/intr_machdep.h>
82 #include <machine/md_var.h>
83 #include <machine/smp.h>
84 #include <machine/trap.h>
85 
86 #include "pic_if.h"
87 
88 static MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
89 
90 struct powerpc_intr {
91 	struct intr_event *event;
92 	long	*cntp;
93 	void	*priv;		/* PIC-private data */
94 	device_t pic;
95 	u_int	irq;
96 	u_int	intline;
97 	u_int	vector;
98 	u_int	cntindex;
99 	int	fwcode;
100 	int	ipi;
101 	int	pi_domain;
102 	enum intr_trigger trig;
103 	enum intr_polarity pol;
104 	cpuset_t pi_cpuset;
105 };
106 
107 struct pic {
108 	device_t dev;
109 	uint32_t node;
110 	u_int	irqs;
111 	u_int	ipis;
112 	int	base;
113 };
114 
115 static u_int intrcnt_index = 0;
116 static struct mtx intr_table_lock;
117 static struct powerpc_intr **powerpc_intrs;
118 static struct pic piclist[MAX_PICS];
119 static u_int nvectors;		/* Allocated vectors */
120 static u_int npics;		/* PICs registered */
121 #ifdef DEV_ISA
122 static u_int nirqs = 16;	/* Allocated IRQS (ISA pre-allocated). */
123 #else
124 static u_int nirqs = 0;		/* Allocated IRQs. */
125 #endif
126 static u_int stray_count;
127 
128 #define	INTRNAME_LEN	(MAXCOMLEN + 1)
129 u_long *intrcnt;
130 char *intrnames;
131 size_t sintrcnt = sizeof(intrcnt);
132 size_t sintrnames = sizeof(intrnames);
133 int nintrcnt;
134 
135 /*
136  * Just to start
137  */
138 #ifdef __powerpc64__
139 u_int num_io_irqs = 768;
140 #else
141 u_int num_io_irqs = 256;
142 #endif
143 
144 device_t root_pic;
145 
146 #ifdef SMP
147 static void *ipi_cookie;
148 #endif
149 
150 static int powerpc_setup_intr_int(const char *name, u_int irq, driver_filter_t
151     filter, driver_intr_t handler, void *arg, enum intr_type flags, void
152     **cookiep, int domain, bool ipi);
153 
154 static void
intrcnt_setname(const char * name,int index)155 intrcnt_setname(const char *name, int index)
156 {
157 
158 	snprintf(intrnames + INTRNAME_LEN * index, INTRNAME_LEN, "%-*s",
159 	    INTRNAME_LEN - 1, name);
160 }
161 
162 MTX_SYSINIT(intr_table_lock, &intr_table_lock, "intr sources lock", MTX_DEF);
163 
164 static void
intr_init_sources(void * arg __unused)165 intr_init_sources(void *arg __unused)
166 {
167 
168 	powerpc_intrs = mallocarray(num_io_irqs, sizeof(*powerpc_intrs),
169 	    M_INTR, M_WAITOK | M_ZERO);
170 	nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
171 #ifdef COUNT_IPIS
172 	if (mp_ncpus > 1)
173 		nintrcnt += 8 * mp_ncpus;
174 #endif
175 	intrcnt = mallocarray(nintrcnt, sizeof(u_long), M_INTR, M_WAITOK |
176 	    M_ZERO);
177 	intrnames = mallocarray(nintrcnt, INTRNAME_LEN, M_INTR, M_WAITOK |
178 	    M_ZERO);
179 	sintrcnt = nintrcnt * sizeof(u_long);
180 	sintrnames = nintrcnt * INTRNAME_LEN;
181 
182 	intrcnt_setname("???", 0);
183 	intrcnt_index = 1;
184 }
185 /*
186  * This needs to happen before SI_SUB_CPU
187  */
188 SYSINIT(intr_init_sources, SI_SUB_KLD, SI_ORDER_ANY, intr_init_sources, NULL);
189 
190 #ifdef SMP
191 static void
smp_intr_init(void * dummy __unused)192 smp_intr_init(void *dummy __unused)
193 {
194 	struct powerpc_intr *i;
195 	int vector;
196 
197 	for (vector = 0; vector < nvectors; vector++) {
198 		i = powerpc_intrs[vector];
199 		if (i != NULL && i->event != NULL && i->pic == root_pic)
200 			PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
201 	}
202 }
203 SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
204 #endif
205 
206 void
intrcnt_add(const char * name,u_long ** countp)207 intrcnt_add(const char *name, u_long **countp)
208 {
209 	int idx;
210 
211 	idx = atomic_fetchadd_int(&intrcnt_index, 1);
212 	KASSERT(idx < nintrcnt, ("intrcnt_add: Interrupt counter index %d/%d"
213 		"reached nintrcnt : %d", intrcnt_index, idx, nintrcnt));
214 	*countp = &intrcnt[idx];
215 	intrcnt_setname(name, idx);
216 }
217 
218 static struct powerpc_intr *
intr_lookup(u_int irq)219 intr_lookup(u_int irq)
220 {
221 	char intrname[16];
222 	struct powerpc_intr *i, *iscan;
223 	int vector;
224 
225 	mtx_lock(&intr_table_lock);
226 	for (vector = 0; vector < nvectors; vector++) {
227 		i = powerpc_intrs[vector];
228 		if (i != NULL && i->irq == irq) {
229 			mtx_unlock(&intr_table_lock);
230 			return (i);
231 		}
232 	}
233 
234 	i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
235 	if (i == NULL) {
236 		mtx_unlock(&intr_table_lock);
237 		return (NULL);
238 	}
239 
240 	i->event = NULL;
241 	i->cntp = NULL;
242 	i->priv = NULL;
243 	i->trig = INTR_TRIGGER_CONFORM;
244 	i->pol = INTR_POLARITY_CONFORM;
245 	i->irq = irq;
246 	i->pic = NULL;
247 	i->vector = -1;
248 	i->fwcode = 0;
249 	i->ipi = 0;
250 
251 #ifdef SMP
252 	i->pi_cpuset = all_cpus;
253 #else
254 	CPU_SETOF(0, &i->pi_cpuset);
255 #endif
256 
257 	for (vector = 0; vector < num_io_irqs && vector <= nvectors;
258 	    vector++) {
259 		iscan = powerpc_intrs[vector];
260 		if (iscan != NULL && iscan->irq == irq)
261 			break;
262 		if (iscan == NULL && i->vector == -1)
263 			i->vector = vector;
264 		iscan = NULL;
265 	}
266 
267 	if (iscan == NULL && i->vector != -1) {
268 		powerpc_intrs[i->vector] = i;
269 		i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
270 		i->cntp = &intrcnt[i->cntindex];
271 		sprintf(intrname, "irq%u:", i->irq);
272 		intrcnt_setname(intrname, i->cntindex);
273 		nvectors++;
274 	}
275 	mtx_unlock(&intr_table_lock);
276 
277 	if (iscan != NULL || i->vector == -1) {
278 		free(i, M_INTR);
279 		i = iscan;
280 	}
281 
282 	return (i);
283 }
284 
285 static int
powerpc_map_irq(struct powerpc_intr * i)286 powerpc_map_irq(struct powerpc_intr *i)
287 {
288 	struct pic *p;
289 	u_int cnt;
290 	int idx;
291 
292 	for (idx = 0; idx < npics; idx++) {
293 		p = &piclist[idx];
294 		cnt = p->irqs + p->ipis;
295 		if (i->irq >= p->base && i->irq < p->base + cnt)
296 			break;
297 	}
298 	if (idx == npics)
299 		return (EINVAL);
300 
301 	i->intline = i->irq - p->base;
302 	i->pic = p->dev;
303 
304 	/* Try a best guess if that failed */
305 	if (i->pic == NULL)
306 		i->pic = root_pic;
307 
308 	return (0);
309 }
310 
311 static void
powerpc_intr_eoi(void * arg)312 powerpc_intr_eoi(void *arg)
313 {
314 	struct powerpc_intr *i = arg;
315 
316 	PIC_EOI(i->pic, i->intline, i->priv);
317 }
318 
319 static void
powerpc_intr_pre_ithread(void * arg)320 powerpc_intr_pre_ithread(void *arg)
321 {
322 	struct powerpc_intr *i = arg;
323 
324 	PIC_MASK(i->pic, i->intline, i->priv);
325 	PIC_EOI(i->pic, i->intline, i->priv);
326 }
327 
328 static void
powerpc_intr_post_ithread(void * arg)329 powerpc_intr_post_ithread(void *arg)
330 {
331 	struct powerpc_intr *i = arg;
332 
333 	PIC_UNMASK(i->pic, i->intline, i->priv);
334 }
335 
336 static int
powerpc_assign_intr_cpu(void * arg,int cpu)337 powerpc_assign_intr_cpu(void *arg, int cpu)
338 {
339 #ifdef SMP
340 	struct powerpc_intr *i = arg;
341 
342 	if (cpu == NOCPU)
343 		i->pi_cpuset = all_cpus;
344 	else
345 		CPU_SETOF(cpu, &i->pi_cpuset);
346 
347 	if (!cold && i->pic != NULL && i->pic == root_pic)
348 		PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
349 
350 	return (0);
351 #else
352 	return (EOPNOTSUPP);
353 #endif
354 }
355 
356 u_int
powerpc_register_pic(device_t dev,uint32_t node,u_int irqs,u_int ipis,u_int atpic)357 powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
358     u_int atpic)
359 {
360 	struct pic *p;
361 	u_int irq;
362 	int idx;
363 
364 	mtx_lock(&intr_table_lock);
365 
366 	/* XXX see powerpc_get_irq(). */
367 	for (idx = 0; idx < npics; idx++) {
368 		p = &piclist[idx];
369 		if (p->node != node)
370 			continue;
371 		if (node != 0 || p->dev == dev)
372 			break;
373 	}
374 	p = &piclist[idx];
375 
376 	p->dev = dev;
377 	p->node = node;
378 	p->irqs = irqs;
379 	p->ipis = ipis;
380 	if (idx == npics) {
381 #ifdef DEV_ISA
382 		p->base = (atpic) ? 0 : nirqs;
383 #else
384 		p->base = nirqs;
385 #endif
386 		irq = p->base + irqs + ipis;
387 		nirqs = MAX(nirqs, irq);
388 		npics++;
389 	}
390 
391 	KASSERT(npics < MAX_PICS,
392 	    ("Number of PICs exceeds maximum (%d)", MAX_PICS));
393 
394 	mtx_unlock(&intr_table_lock);
395 
396 	return (p->base);
397 }
398 
399 u_int
powerpc_get_irq(uint32_t node,u_int pin)400 powerpc_get_irq(uint32_t node, u_int pin)
401 {
402 	int idx;
403 
404 	if (node == 0)
405 		return (pin);
406 
407 	mtx_lock(&intr_table_lock);
408 	for (idx = 0; idx < npics; idx++) {
409 		if (piclist[idx].node == node) {
410 			mtx_unlock(&intr_table_lock);
411 			return (piclist[idx].base + pin);
412 		}
413 	}
414 
415 	/*
416 	 * XXX we should never encounter an unregistered PIC, but that
417 	 * can only be done when we properly support bus enumeration
418 	 * using multiple passes. Until then, fake an entry and give it
419 	 * some adhoc maximum number of IRQs and IPIs.
420 	 */
421 	piclist[idx].dev = NULL;
422 	piclist[idx].node = node;
423 	piclist[idx].irqs = 124;
424 	piclist[idx].ipis = 4;
425 	piclist[idx].base = nirqs;
426 	nirqs += (1 << 25);
427 	npics++;
428 
429 	KASSERT(npics < MAX_PICS,
430 	    ("Number of PICs exceeds maximum (%d)", MAX_PICS));
431 
432 	mtx_unlock(&intr_table_lock);
433 
434 	return (piclist[idx].base + pin);
435 }
436 
437 int
powerpc_enable_intr(void)438 powerpc_enable_intr(void)
439 {
440 	struct powerpc_intr *i;
441 	int error, vector;
442 #ifdef SMP
443 	int n;
444 #endif
445 
446 	if (npics == 0)
447 		panic("no PIC detected\n");
448 
449 	if (root_pic == NULL)
450 		root_pic = piclist[0].dev;
451 
452 	KASSERT(root_pic != NULL, ("no root PIC!"));
453 
454 #ifdef SMP
455 	/* Install an IPI handler. */
456 	if (mp_ncpus > 1) {
457 		for (n = 0; n < npics; n++) {
458 			if (piclist[n].dev != root_pic)
459 				continue;
460 
461 			KASSERT(piclist[n].ipis != 0,
462 			    ("%s: SMP root PIC does not supply any IPIs",
463 			    __func__));
464 			error = powerpc_setup_intr_int("IPI",
465 			    MAP_IRQ(piclist[n].node, piclist[n].irqs),
466 			    powerpc_ipi_handler, NULL, NULL,
467 			    INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie,
468 			    0 /* domain XXX */, true);
469 			if (error) {
470 				printf("unable to setup IPI handler\n");
471 				return (error);
472 			}
473 		}
474 	}
475 #endif
476 
477 	for (vector = 0; vector < nvectors; vector++) {
478 		i = powerpc_intrs[vector];
479 		if (i == NULL)
480 			continue;
481 
482 		error = powerpc_map_irq(i);
483 		if (error)
484 			continue;
485 
486 		if (i->trig == INTR_TRIGGER_INVALID)
487 			PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode,
488 			    &i->trig, &i->pol);
489 		if (i->trig != INTR_TRIGGER_CONFORM ||
490 		    i->pol != INTR_POLARITY_CONFORM)
491 			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
492 
493 		if (i->event != NULL)
494 			PIC_ENABLE(i->pic, i->intline, vector, &i->priv);
495 	}
496 
497 	return (0);
498 }
499 
500 int
powerpc_setup_intr(const char * name,u_int irq,driver_filter_t filter,driver_intr_t handler,void * arg,enum intr_type flags,void ** cookiep,int domain)501 powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
502     driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep,
503     int domain)
504 {
505 
506 	return (powerpc_setup_intr_int(name, irq, filter, handler, arg, flags,
507 	    cookiep, domain, false));
508 }
509 
510 
511 static int
powerpc_setup_intr_int(const char * name,u_int irq,driver_filter_t filter,driver_intr_t handler,void * arg,enum intr_type flags,void ** cookiep,int domain,bool ipi)512 powerpc_setup_intr_int(const char *name, u_int irq, driver_filter_t filter,
513     driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep,
514     int domain, bool ipi)
515 {
516 	struct powerpc_intr *i;
517 	int error, enable = 0;
518 
519 	i = intr_lookup(irq);
520 	if (i == NULL)
521 		return (ENOMEM);
522 
523 	if (i->event == NULL) {
524 		error = intr_event_create(&i->event, (void *)i, 0, irq,
525 		    powerpc_intr_pre_ithread, powerpc_intr_post_ithread,
526 		    (ipi ? NULL : powerpc_intr_eoi), powerpc_assign_intr_cpu,
527 		    "irq%u:", irq);
528 		if (error)
529 			return (error);
530 
531 		enable = 1;
532 	}
533 	i->ipi = ipi;
534 
535 	error = intr_event_add_handler(i->event, name, filter, handler, arg,
536 	    intr_priority(flags), flags, cookiep);
537 	if (error)
538 		return (error);
539 	i->pi_domain = domain;
540 	if (strcmp(name, "IPI") != 0)  {
541 		CPU_ZERO(&i->pi_cpuset);
542 		CPU_COPY(&cpuset_domain[domain], &i->pi_cpuset);
543 	}
544 	mtx_lock(&intr_table_lock);
545 	intrcnt_setname(i->event->ie_fullname, i->cntindex);
546 	mtx_unlock(&intr_table_lock);
547 
548 	if (!cold) {
549 		error = powerpc_map_irq(i);
550 
551 		if (!error) {
552 			if (i->trig == INTR_TRIGGER_INVALID)
553 				PIC_TRANSLATE_CODE(i->pic, i->intline,
554 				    i->fwcode, &i->trig, &i->pol);
555 
556 			if (i->trig != INTR_TRIGGER_CONFORM ||
557 			    i->pol != INTR_POLARITY_CONFORM)
558 				PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
559 
560 			if (i->pic == root_pic)
561 				PIC_BIND(i->pic, i->intline, i->pi_cpuset, &i->priv);
562 
563 			if (enable)
564 				PIC_ENABLE(i->pic, i->intline, i->vector,
565 				    &i->priv);
566 		}
567 	}
568 	return (error);
569 }
570 
571 int
powerpc_teardown_intr(void * cookie)572 powerpc_teardown_intr(void *cookie)
573 {
574 
575 	return (intr_event_remove_handler(cookie));
576 }
577 
578 #ifdef SMP
579 int
powerpc_bind_intr(u_int irq,u_char cpu)580 powerpc_bind_intr(u_int irq, u_char cpu)
581 {
582 	struct powerpc_intr *i;
583 
584 	i = intr_lookup(irq);
585 	if (i == NULL)
586 		return (ENOMEM);
587 
588 	return (intr_event_bind(i->event, cpu));
589 }
590 #endif
591 
592 int
powerpc_fw_config_intr(int irq,int sense_code)593 powerpc_fw_config_intr(int irq, int sense_code)
594 {
595 	struct powerpc_intr *i;
596 
597 	i = intr_lookup(irq);
598 	if (i == NULL)
599 		return (ENOMEM);
600 
601 	i->trig = INTR_TRIGGER_INVALID;
602 	i->pol = INTR_POLARITY_CONFORM;
603 	i->fwcode = sense_code;
604 
605 	if (!cold && i->pic != NULL) {
606 		PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, &i->trig,
607 		    &i->pol);
608 		PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
609 	}
610 
611 	return (0);
612 }
613 
614 int
powerpc_config_intr(int irq,enum intr_trigger trig,enum intr_polarity pol)615 powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
616 {
617 	struct powerpc_intr *i;
618 
619 	i = intr_lookup(irq);
620 	if (i == NULL)
621 		return (ENOMEM);
622 
623 	i->trig = trig;
624 	i->pol = pol;
625 
626 	if (!cold && i->pic != NULL)
627 		PIC_CONFIG(i->pic, i->intline, trig, pol);
628 
629 	return (0);
630 }
631 
632 void
powerpc_dispatch_intr(u_int vector,struct trapframe * tf)633 powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
634 {
635 	struct powerpc_intr *i;
636 	struct intr_event *ie;
637 
638 	i = powerpc_intrs[vector];
639 	if (i == NULL)
640 		goto stray;
641 
642 	(*i->cntp)++;
643 
644 	ie = i->event;
645 	KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
646 
647 	/*
648 	 * IPIs are magical and need to be EOI'ed before filtering.
649 	 * This prevents races in IPI handling.
650 	 */
651 	if (i->ipi)
652 		PIC_EOI(i->pic, i->intline, i->priv);
653 
654 	if (intr_event_handle(ie, tf) != 0) {
655 		goto stray;
656 	}
657 	return;
658 
659 stray:
660 	stray_count++;
661 	if (stray_count <= INTR_STRAY_LOG_MAX) {
662 		printf("stray irq %d\n", i ? i->irq : -1);
663 		if (stray_count >= INTR_STRAY_LOG_MAX) {
664 			printf("got %d stray interrupts, not logging anymore\n",
665 			    INTR_STRAY_LOG_MAX);
666 		}
667 	}
668 	if (i != NULL)
669 		PIC_MASK(i->pic, i->intline, i->priv);
670 }
671 
672 void
powerpc_intr_mask(u_int irq)673 powerpc_intr_mask(u_int irq)
674 {
675 	struct powerpc_intr *i;
676 
677 	i = intr_lookup(irq);
678 	if (i == NULL || i->pic == NULL)
679 		return;
680 
681 	PIC_MASK(i->pic, i->intline, i->priv);
682 }
683 
684 void
powerpc_intr_unmask(u_int irq)685 powerpc_intr_unmask(u_int irq)
686 {
687 	struct powerpc_intr *i;
688 
689 	i = intr_lookup(irq);
690 	if (i == NULL || i->pic == NULL)
691 		return;
692 
693 	PIC_UNMASK(i->pic, i->intline, i->priv);
694 }
695