xref: /freebsd/sys/kern/subr_intr.c (revision 80a87461087caa71c74d891c5b7cddf0156ad58a)
1 /*-
2  * Copyright (c) 2012-2014 Jakub Wojciech Klama <jceel@FreeBSD.org>.
3  * Copyright (c) 2015 Svatopluk Kraus
4  * Copyright (c) 2015 Michal Meloun
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 /*
35  *	New-style Interrupt Framework
36  *
37  *  TODO: - to support IPI (PPI) enabling on other CPUs if already started
38  *        - to complete things for removable PICs
39  */
40 
41 #include "opt_ddb.h"
42 #include "opt_platform.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/syslog.h>
48 #include <sys/malloc.h>
49 #include <sys/proc.h>
50 #include <sys/queue.h>
51 #include <sys/bus.h>
52 #include <sys/interrupt.h>
53 #include <sys/conf.h>
54 #include <sys/cpuset.h>
55 #include <sys/sched.h>
56 #include <sys/smp.h>
57 #include <machine/atomic.h>
58 #include <machine/intr.h>
59 #include <machine/cpu.h>
60 #include <machine/smp.h>
61 #include <machine/stdarg.h>
62 
63 #ifdef FDT
64 #include <dev/ofw/openfirm.h>
65 #include <dev/ofw/ofw_bus.h>
66 #include <dev/ofw/ofw_bus_subr.h>
67 #endif
68 
69 #ifdef DDB
70 #include <ddb/ddb.h>
71 #endif
72 
73 #include "pic_if.h"
74 
75 #define	INTRNAME_LEN	(2*MAXCOMLEN + 1)
76 
77 #ifdef DEBUG
78 #define debugf(fmt, args...) do { printf("%s(): ", __func__);	\
79     printf(fmt,##args); } while (0)
80 #else
81 #define debugf(fmt, args...)
82 #endif
83 
84 MALLOC_DECLARE(M_INTRNG);
85 MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
86 
87 /* Main interrupt handler called from assembler -> 'hidden' for C code. */
88 void intr_irq_handler(struct trapframe *tf);
89 
90 /* Root interrupt controller stuff. */
91 static struct intr_irqsrc *irq_root_isrc;
92 device_t intr_irq_root_dev;
93 static intr_irq_filter_t *irq_root_filter;
94 static void *irq_root_arg;
95 static u_int irq_root_ipicount;
96 
97 /* Interrupt controller definition. */
98 struct intr_pic {
99 	SLIST_ENTRY(intr_pic)	pic_next;
100 	intptr_t		pic_xref;	/* hardware identification */
101 	device_t		pic_dev;
102 };
103 
104 static struct mtx pic_list_lock;
105 static SLIST_HEAD(, intr_pic) pic_list;
106 
107 static struct intr_pic *pic_lookup(device_t dev, intptr_t xref);
108 
109 /* Interrupt source definition. */
110 static struct mtx isrc_table_lock;
111 static struct intr_irqsrc *irq_sources[NIRQ];
112 u_int irq_next_free;
113 
114 #define IRQ_INVALID	nitems(irq_sources)
115 
116 #ifdef SMP
117 static boolean_t irq_assign_cpu = FALSE;
118 #endif
119 
120 /*
121  * - 2 counters for each I/O interrupt.
122  * - MAXCPU counters for each IPI counters for SMP.
123  */
124 #ifdef SMP
125 #define INTRCNT_COUNT   (NIRQ * 2 + INTR_IPI_COUNT * MAXCPU)
126 #else
127 #define INTRCNT_COUNT   (NIRQ * 2)
128 #endif
129 
130 /* Data for MI statistics reporting. */
131 u_long intrcnt[INTRCNT_COUNT];
132 char intrnames[INTRCNT_COUNT * INTRNAME_LEN];
133 size_t sintrcnt = sizeof(intrcnt);
134 size_t sintrnames = sizeof(intrnames);
135 static u_int intrcnt_index;
136 
137 /*
138  *  Interrupt framework initialization routine.
139  */
140 static void
141 intr_irq_init(void *dummy __unused)
142 {
143 
144 	SLIST_INIT(&pic_list);
145 	mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
146 	mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF);
147 }
148 SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL);
149 
150 static void
151 intrcnt_setname(const char *name, int index)
152 {
153 
154 	snprintf(intrnames + INTRNAME_LEN * index, INTRNAME_LEN, "%-*s",
155 	    INTRNAME_LEN - 1, name);
156 }
157 
158 /*
159  *  Update name for interrupt source with interrupt event.
160  */
161 static void
162 intrcnt_updatename(struct intr_irqsrc *isrc)
163 {
164 
165 	/* QQQ: What about stray counter name? */
166 	mtx_assert(&isrc_table_lock, MA_OWNED);
167 	intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index);
168 }
169 
170 /*
171  *  Virtualization for interrupt source interrupt counter increment.
172  */
173 static inline void
174 isrc_increment_count(struct intr_irqsrc *isrc)
175 {
176 
177 	/*
178 	 * XXX - It should be atomic for PPI interrupts. It was proven that
179 	 *       the lost is measurable easily for timer PPI interrupts.
180 	 */
181 	isrc->isrc_count[0]++;
182 	/*atomic_add_long(&isrc->isrc_count[0], 1);*/
183 }
184 
185 /*
186  *  Virtualization for interrupt source interrupt stray counter increment.
187  */
188 static inline void
189 isrc_increment_straycount(struct intr_irqsrc *isrc)
190 {
191 
192 	isrc->isrc_count[1]++;
193 }
194 
195 /*
196  *  Virtualization for interrupt source interrupt name update.
197  */
198 static void
199 isrc_update_name(struct intr_irqsrc *isrc, const char *name)
200 {
201 	char str[INTRNAME_LEN];
202 
203 	mtx_assert(&isrc_table_lock, MA_OWNED);
204 
205 	if (name != NULL) {
206 		snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name);
207 		intrcnt_setname(str, isrc->isrc_index);
208 		snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name,
209 		    name);
210 		intrcnt_setname(str, isrc->isrc_index + 1);
211 	} else {
212 		snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name);
213 		intrcnt_setname(str, isrc->isrc_index);
214 		snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name);
215 		intrcnt_setname(str, isrc->isrc_index + 1);
216 	}
217 }
218 
219 /*
220  *  Virtualization for interrupt source interrupt counters setup.
221  */
222 static void
223 isrc_setup_counters(struct intr_irqsrc *isrc)
224 {
225 	u_int index;
226 
227 	/*
228 	 *  XXX - it does not work well with removable controllers and
229 	 *        interrupt sources !!!
230 	 */
231 	index = atomic_fetchadd_int(&intrcnt_index, 2);
232 	isrc->isrc_index = index;
233 	isrc->isrc_count = &intrcnt[index];
234 	isrc_update_name(isrc, NULL);
235 }
236 
237 #ifdef SMP
238 /*
239  *  Virtualization for interrupt source IPI counters setup.
240  */
241 u_long *
242 intr_ipi_setup_counters(const char *name)
243 {
244 	u_int index, i;
245 	char str[INTRNAME_LEN];
246 
247 	index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
248 	for (i = 0; i < MAXCPU; i++) {
249 		snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name);
250 		intrcnt_setname(str, index + i);
251 	}
252 	return (&intrcnt[index]);
253 }
254 #endif
255 
256 /*
257  *  Main interrupt dispatch handler. It's called straight
258  *  from the assembler, where CPU interrupt is served.
259  */
260 void
261 intr_irq_handler(struct trapframe *tf)
262 {
263 	struct trapframe * oldframe;
264 	struct thread * td;
265 
266 	KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__));
267 
268 	PCPU_INC(cnt.v_intr);
269 	critical_enter();
270 	td = curthread;
271 	oldframe = td->td_intr_frame;
272 	td->td_intr_frame = tf;
273 	irq_root_filter(irq_root_arg);
274 	td->td_intr_frame = oldframe;
275 	critical_exit();
276 }
277 
278 /*
279  *  interrupt controller dispatch function for interrupts. It should
280  *  be called straight from the interrupt controller, when associated interrupt
281  *  source is learned.
282  */
283 void
284 intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
285 {
286 
287 	KASSERT(isrc != NULL, ("%s: no source", __func__));
288 
289 	isrc_increment_count(isrc);
290 
291 #ifdef INTR_SOLO
292 	if (isrc->isrc_filter != NULL) {
293 		int error;
294 		error = isrc->isrc_filter(isrc->isrc_arg, tf);
295 		PIC_POST_FILTER(isrc->isrc_dev, isrc);
296 		if (error == FILTER_HANDLED)
297 			return;
298 	} else
299 #endif
300 	if (isrc->isrc_event != NULL) {
301 		if (intr_event_handle(isrc->isrc_event, tf) == 0)
302 			return;
303 	}
304 
305 	isrc_increment_straycount(isrc);
306 	PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
307 
308 	device_printf(isrc->isrc_dev, "stray irq <%s> disabled",
309 	    isrc->isrc_name);
310 }
311 
312 /*
313  *  Allocate interrupt source.
314  */
315 static struct intr_irqsrc *
316 isrc_alloc(u_int type, u_int extsize)
317 {
318 	struct intr_irqsrc *isrc;
319 
320 	isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
321 	isrc->isrc_irq = IRQ_INVALID;	/* just to be safe */
322 	isrc->isrc_type = type;
323 	isrc->isrc_nspc_type = INTR_IRQ_NSPC_NONE;
324 	isrc->isrc_trig = INTR_TRIGGER_CONFORM;
325 	isrc->isrc_pol = INTR_POLARITY_CONFORM;
326 	CPU_ZERO(&isrc->isrc_cpu);
327 	return (isrc);
328 }
329 
330 /*
331  *  Free interrupt source.
332  */
333 static void
334 isrc_free(struct intr_irqsrc *isrc)
335 {
336 
337 	free(isrc, M_INTRNG);
338 }
339 
340 void
341 intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
342 {
343 	va_list ap;
344 
345 	va_start(ap, fmt);
346 	vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
347 	va_end(ap);
348 }
349 
350 /*
351  *  Alloc unique interrupt number (resource handle) for interrupt source.
352  *
353  *  There could be various strategies how to allocate free interrupt number
354  *  (resource handle) for new interrupt source.
355  *
356  *  1. Handles are always allocated forward, so handles are not recycled
357  *     immediately. However, if only one free handle left which is reused
358  *     constantly...
359  */
360 static int
361 isrc_alloc_irq_locked(struct intr_irqsrc *isrc)
362 {
363 	u_int maxirqs, irq;
364 
365 	mtx_assert(&isrc_table_lock, MA_OWNED);
366 
367 	maxirqs = nitems(irq_sources);
368 	if (irq_next_free >= maxirqs)
369 		return (ENOSPC);
370 
371 	for (irq = irq_next_free; irq < maxirqs; irq++) {
372 		if (irq_sources[irq] == NULL)
373 			goto found;
374 	}
375 	for (irq = 0; irq < irq_next_free; irq++) {
376 		if (irq_sources[irq] == NULL)
377 			goto found;
378 	}
379 
380 	irq_next_free = maxirqs;
381 	return (ENOSPC);
382 
383 found:
384 	isrc->isrc_irq = irq;
385 	irq_sources[irq] = isrc;
386 
387 	intr_irq_set_name(isrc, "irq%u", irq);
388 	isrc_setup_counters(isrc);
389 
390 	irq_next_free = irq + 1;
391 	if (irq_next_free >= maxirqs)
392 		irq_next_free = 0;
393 	return (0);
394 }
395 #ifdef notyet
396 /*
397  *  Free unique interrupt number (resource handle) from interrupt source.
398  */
399 static int
400 isrc_free_irq(struct intr_irqsrc *isrc)
401 {
402 	u_int maxirqs;
403 
404 	mtx_assert(&isrc_table_lock, MA_NOTOWNED);
405 
406 	maxirqs = nitems(irq_sources);
407 	if (isrc->isrc_irq >= maxirqs)
408 		return (EINVAL);
409 
410 	mtx_lock(&isrc_table_lock);
411 	if (irq_sources[isrc->isrc_irq] != isrc) {
412 		mtx_unlock(&isrc_table_lock);
413 		return (EINVAL);
414 	}
415 
416 	irq_sources[isrc->isrc_irq] = NULL;
417 	isrc->isrc_irq = IRQ_INVALID;	/* just to be safe */
418 	mtx_unlock(&isrc_table_lock);
419 
420 	return (0);
421 }
422 #endif
423 /*
424  *  Lookup interrupt source by interrupt number (resource handle).
425  */
426 static struct intr_irqsrc *
427 isrc_lookup(u_int irq)
428 {
429 
430 	if (irq < nitems(irq_sources))
431 		return (irq_sources[irq]);
432 	return (NULL);
433 }
434 
435 /*
436  *  Lookup interrupt source by namespace description.
437  */
438 static struct intr_irqsrc *
439 isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
440 {
441 	u_int irq;
442 	struct intr_irqsrc *isrc;
443 
444 	mtx_assert(&isrc_table_lock, MA_OWNED);
445 
446 	for (irq = 0; irq < nitems(irq_sources); irq++) {
447 		isrc = irq_sources[irq];
448 		if (isrc != NULL && isrc->isrc_dev == dev &&
449 		    isrc->isrc_nspc_type == type && isrc->isrc_nspc_num == num)
450 			return (isrc);
451 	}
452 	return (NULL);
453 }
454 
455 /*
456  *  Map interrupt source according to namespace into framework. If such mapping
457  *  does not exist, create it. Return unique interrupt number (resource handle)
458  *  associated with mapped interrupt source.
459  */
460 u_int
461 intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
462 {
463 	struct intr_irqsrc *isrc, *new_isrc;
464 	int error;
465 
466 	new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0);
467 
468 	mtx_lock(&isrc_table_lock);
469 	isrc = isrc_namespace_lookup(dev, type, num);
470 	if (isrc != NULL) {
471 		mtx_unlock(&isrc_table_lock);
472 		isrc_free(new_isrc);
473 		return (isrc->isrc_irq);	/* already mapped */
474 	}
475 
476 	error = isrc_alloc_irq_locked(new_isrc);
477 	if (error != 0) {
478 		mtx_unlock(&isrc_table_lock);
479 		isrc_free(new_isrc);
480 		return (IRQ_INVALID);		/* no space left */
481 	}
482 
483 	new_isrc->isrc_dev = dev;
484 	new_isrc->isrc_nspc_type = type;
485 	new_isrc->isrc_nspc_num = num;
486 	mtx_unlock(&isrc_table_lock);
487 
488 	return (new_isrc->isrc_irq);
489 }
490 
491 #ifdef FDT
492 /*
493  *  Lookup interrupt source by FDT description.
494  */
495 static struct intr_irqsrc *
496 isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
497 {
498 	u_int irq, cellsize;
499 	struct intr_irqsrc *isrc;
500 
501 	mtx_assert(&isrc_table_lock, MA_OWNED);
502 
503 	cellsize = ncells * sizeof(*cells);
504 	for (irq = 0; irq < nitems(irq_sources); irq++) {
505 		isrc = irq_sources[irq];
506 		if (isrc != NULL && isrc->isrc_type == INTR_ISRCT_FDT &&
507 		    isrc->isrc_xref == xref && isrc->isrc_ncells == ncells &&
508 		    memcmp(isrc->isrc_cells, cells, cellsize) == 0)
509 			return (isrc);
510 	}
511 	return (NULL);
512 }
513 
514 /*
515  *  Map interrupt source according to FDT data into framework. If such mapping
516  *  does not exist, create it. Return unique interrupt number (resource handle)
517  *  associated with mapped interrupt source.
518  */
519 u_int
520 intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
521 {
522 	struct intr_irqsrc *isrc, *new_isrc;
523 	u_int cellsize;
524 	intptr_t xref;
525 	int error;
526 
527 	xref = (intptr_t)node;	/* It's so simple for now. */
528 
529 	cellsize = ncells * sizeof(*cells);
530 	new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize);
531 
532 	mtx_lock(&isrc_table_lock);
533 	isrc = isrc_fdt_lookup(xref, cells, ncells);
534 	if (isrc != NULL) {
535 		mtx_unlock(&isrc_table_lock);
536 		isrc_free(new_isrc);
537 		return (isrc->isrc_irq);	/* already mapped */
538 	}
539 
540 	error = isrc_alloc_irq_locked(new_isrc);
541 	if (error != 0) {
542 		mtx_unlock(&isrc_table_lock);
543 		isrc_free(new_isrc);
544 		return (IRQ_INVALID);		/* no space left */
545 	}
546 
547 	new_isrc->isrc_xref = xref;
548 	new_isrc->isrc_ncells = ncells;
549 	memcpy(new_isrc->isrc_cells, cells, cellsize);
550 	mtx_unlock(&isrc_table_lock);
551 
552 	return (new_isrc->isrc_irq);
553 }
554 #endif
555 
556 /*
557  *  Register interrupt source into interrupt controller.
558  */
559 static int
560 isrc_register(struct intr_irqsrc *isrc)
561 {
562 	struct intr_pic *pic;
563 	boolean_t is_percpu;
564 	int error;
565 
566 	if (isrc->isrc_flags & INTR_ISRCF_REGISTERED)
567 		return (0);
568 
569 	if (isrc->isrc_dev == NULL) {
570 		pic = pic_lookup(NULL, isrc->isrc_xref);
571 		if (pic == NULL || pic->pic_dev == NULL)
572 			return (ESRCH);
573 		isrc->isrc_dev = pic->pic_dev;
574 	}
575 
576 	error = PIC_REGISTER(isrc->isrc_dev, isrc, &is_percpu);
577 	if (error != 0)
578 		return (error);
579 
580 	mtx_lock(&isrc_table_lock);
581 	isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
582 	if (is_percpu)
583 		isrc->isrc_flags |= INTR_ISRCF_PERCPU;
584 	isrc_update_name(isrc, NULL);
585 	mtx_unlock(&isrc_table_lock);
586 	return (0);
587 }
588 
589 #ifdef INTR_SOLO
590 /*
591  *  Setup filter into interrupt source.
592  */
593 static int
594 iscr_setup_filter(struct intr_irqsrc *isrc, const char *name,
595     intr_irq_filter_t *filter, void *arg, void **cookiep)
596 {
597 
598 	if (filter == NULL)
599 		return (EINVAL);
600 
601 	mtx_lock(&isrc_table_lock);
602 	/*
603 	 * Make sure that we do not mix the two ways
604 	 * how we handle interrupt sources.
605 	 */
606 	if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) {
607 		mtx_unlock(&isrc_table_lock);
608 		return (EBUSY);
609 	}
610 	isrc->isrc_filter = filter;
611 	isrc->isrc_arg = arg;
612 	isrc_update_name(isrc, name);
613 	mtx_unlock(&isrc_table_lock);
614 
615 	*cookiep = isrc;
616 	return (0);
617 }
618 #endif
619 
620 /*
621  *  Interrupt source pre_ithread method for MI interrupt framework.
622  */
623 static void
624 intr_isrc_pre_ithread(void *arg)
625 {
626 	struct intr_irqsrc *isrc = arg;
627 
628 	PIC_PRE_ITHREAD(isrc->isrc_dev, isrc);
629 }
630 
631 /*
632  *  Interrupt source post_ithread method for MI interrupt framework.
633  */
634 static void
635 intr_isrc_post_ithread(void *arg)
636 {
637 	struct intr_irqsrc *isrc = arg;
638 
639 	PIC_POST_ITHREAD(isrc->isrc_dev, isrc);
640 }
641 
642 /*
643  *  Interrupt source post_filter method for MI interrupt framework.
644  */
645 static void
646 intr_isrc_post_filter(void *arg)
647 {
648 	struct intr_irqsrc *isrc = arg;
649 
650 	PIC_POST_FILTER(isrc->isrc_dev, isrc);
651 }
652 
653 /*
654  *  Interrupt source assign_cpu method for MI interrupt framework.
655  */
656 static int
657 intr_isrc_assign_cpu(void *arg, int cpu)
658 {
659 #ifdef SMP
660 	struct intr_irqsrc *isrc = arg;
661 	int error;
662 
663 	if (isrc->isrc_dev != intr_irq_root_dev)
664 		return (EINVAL);
665 
666 	mtx_lock(&isrc_table_lock);
667 	if (cpu == NOCPU) {
668 		CPU_ZERO(&isrc->isrc_cpu);
669 		isrc->isrc_flags &= ~INTR_ISRCF_BOUND;
670 	} else {
671 		CPU_SETOF(cpu, &isrc->isrc_cpu);
672 		isrc->isrc_flags |= INTR_ISRCF_BOUND;
673 	}
674 
675 	/*
676 	 * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or
677 	 * re-balance it to another CPU or enable it on more CPUs. However,
678 	 * PIC is expected to change isrc_cpu appropriately to keep us well
679 	 * informed if the call is successfull.
680 	 */
681 	if (irq_assign_cpu) {
682 		error = PIC_BIND(isrc->isrc_dev, isrc);
683 		if (error) {
684 			CPU_ZERO(&isrc->isrc_cpu);
685 			mtx_unlock(&isrc_table_lock);
686 			return (error);
687 		}
688 	}
689 	mtx_unlock(&isrc_table_lock);
690 	return (0);
691 #else
692 	return (EOPNOTSUPP);
693 #endif
694 }
695 
696 /*
697  *  Create interrupt event for interrupt source.
698  */
699 static int
700 isrc_event_create(struct intr_irqsrc *isrc)
701 {
702 	struct intr_event *ie;
703 	int error;
704 
705 	error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq,
706 	    intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter,
707 	    intr_isrc_assign_cpu, "%s:", isrc->isrc_name);
708 	if (error)
709 		return (error);
710 
711 	mtx_lock(&isrc_table_lock);
712 	/*
713 	 * Make sure that we do not mix the two ways
714 	 * how we handle interrupt sources. Let contested event wins.
715 	 */
716 	if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) {
717 		mtx_unlock(&isrc_table_lock);
718 		intr_event_destroy(ie);
719 		return (isrc->isrc_event != NULL ? EBUSY : 0);
720 	}
721 	isrc->isrc_event = ie;
722 	mtx_unlock(&isrc_table_lock);
723 
724 	return (0);
725 }
726 #ifdef notyet
727 /*
728  *  Destroy interrupt event for interrupt source.
729  */
730 static void
731 isrc_event_destroy(struct intr_irqsrc *isrc)
732 {
733 	struct intr_event *ie;
734 
735 	mtx_lock(&isrc_table_lock);
736 	ie = isrc->isrc_event;
737 	isrc->isrc_event = NULL;
738 	mtx_unlock(&isrc_table_lock);
739 
740 	if (ie != NULL)
741 		intr_event_destroy(ie);
742 }
743 #endif
744 /*
745  *  Add handler to interrupt source.
746  */
747 static int
748 isrc_add_handler(struct intr_irqsrc *isrc, const char *name,
749     driver_filter_t filter, driver_intr_t handler, void *arg,
750     enum intr_type flags, void **cookiep)
751 {
752 	int error;
753 
754 	if (isrc->isrc_event == NULL) {
755 		error = isrc_event_create(isrc);
756 		if (error)
757 			return (error);
758 	}
759 
760 	error = intr_event_add_handler(isrc->isrc_event, name, filter, handler,
761 	    arg, intr_priority(flags), flags, cookiep);
762 	if (error == 0) {
763 		mtx_lock(&isrc_table_lock);
764 		intrcnt_updatename(isrc);
765 		mtx_unlock(&isrc_table_lock);
766 	}
767 
768 	return (error);
769 }
770 
771 /*
772  *  Lookup interrupt controller locked.
773  */
774 static struct intr_pic *
775 pic_lookup_locked(device_t dev, intptr_t xref)
776 {
777 	struct intr_pic *pic;
778 
779 	mtx_assert(&pic_list_lock, MA_OWNED);
780 
781 	SLIST_FOREACH(pic, &pic_list, pic_next) {
782 		if (pic->pic_xref != xref)
783 			continue;
784 		if (pic->pic_xref != 0 || pic->pic_dev == dev)
785 			return (pic);
786 	}
787 	return (NULL);
788 }
789 
790 /*
791  *  Lookup interrupt controller.
792  */
793 static struct intr_pic *
794 pic_lookup(device_t dev, intptr_t xref)
795 {
796 	struct intr_pic *pic;
797 
798 	mtx_lock(&pic_list_lock);
799 	pic = pic_lookup_locked(dev, xref);
800 	mtx_unlock(&pic_list_lock);
801 
802 	return (pic);
803 }
804 
805 /*
806  *  Create interrupt controller.
807  */
808 static struct intr_pic *
809 pic_create(device_t dev, intptr_t xref)
810 {
811 	struct intr_pic *pic;
812 
813 	mtx_lock(&pic_list_lock);
814 	pic = pic_lookup_locked(dev, xref);
815 	if (pic != NULL) {
816 		mtx_unlock(&pic_list_lock);
817 		return (pic);
818 	}
819 	pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO);
820 	pic->pic_xref = xref;
821 	pic->pic_dev = dev;
822 	SLIST_INSERT_HEAD(&pic_list, pic, pic_next);
823 	mtx_unlock(&pic_list_lock);
824 
825 	return (pic);
826 }
827 #ifdef notyet
828 /*
829  *  Destroy interrupt controller.
830  */
831 static void
832 pic_destroy(device_t dev, intptr_t xref)
833 {
834 	struct intr_pic *pic;
835 
836 	mtx_lock(&pic_list_lock);
837 	pic = pic_lookup_locked(dev, xref);
838 	if (pic == NULL) {
839 		mtx_unlock(&pic_list_lock);
840 		return;
841 	}
842 	SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next);
843 	mtx_unlock(&pic_list_lock);
844 
845 	free(pic, M_INTRNG);
846 }
847 #endif
848 /*
849  *  Register interrupt controller.
850  */
851 int
852 intr_pic_register(device_t dev, intptr_t xref)
853 {
854 	struct intr_pic *pic;
855 
856 	pic = pic_create(dev, xref);
857 	if (pic == NULL)
858 		return (ENOMEM);
859 	if (pic->pic_dev != dev)
860 		return (EINVAL);	/* XXX it could be many things. */
861 
862 	debugf("PIC %p registered for %s <xref %x>\n", pic,
863 	    device_get_nameunit(dev), xref);
864 	return (0);
865 }
866 
867 /*
868  *  Unregister interrupt controller.
869  */
870 int
871 intr_pic_unregister(device_t dev, intptr_t xref)
872 {
873 
874 	panic("%s: not implemented", __func__);
875 }
876 
877 /*
878  *  Mark interrupt controller (itself) as a root one.
879  *
880  *  Note that only an interrupt controller can really know its position
881  *  in interrupt controller's tree. So root PIC must claim itself as a root.
882  *
883  *  In FDT case, according to ePAPR approved version 1.1 from 08 April 2011,
884  *  page 30:
885  *    "The root of the interrupt tree is determined when traversal
886  *     of the interrupt tree reaches an interrupt controller node without
887  *     an interrupts property and thus no explicit interrupt parent."
888  */
889 int
890 intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
891     void *arg, u_int ipicount)
892 {
893 	int error;
894 	u_int rootirq;
895 
896 	if (pic_lookup(dev, xref) == NULL) {
897 		device_printf(dev, "not registered\n");
898 		return (EINVAL);
899 	}
900 	if (filter == NULL) {
901 		device_printf(dev, "filter missing\n");
902 		return (EINVAL);
903 	}
904 
905 	/*
906 	 * Only one interrupt controllers could be on the root for now.
907 	 * Note that we further suppose that there is not threaded interrupt
908 	 * routine (handler) on the root. See intr_irq_handler().
909 	 */
910 	if (intr_irq_root_dev != NULL) {
911 		device_printf(dev, "another root already set\n");
912 		return (EBUSY);
913 	}
914 
915 	rootirq = intr_namespace_map_irq(device_get_parent(dev), 0, 0);
916 	if (rootirq == IRQ_INVALID) {
917 		device_printf(dev, "failed to map an irq for the root pic\n");
918 		return (ENOMEM);
919 	}
920 
921         /* Create the isrc. */
922 	irq_root_isrc = isrc_lookup(rootirq);
923 
924         /* XXX "register" with the PIC.  We are the "pic" here, so fake it. */
925 	irq_root_isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
926 
927 	error = intr_irq_add_handler(device_get_parent(dev),
928 		(void*)filter, NULL, arg, rootirq, INTR_TYPE_CLK, NULL);
929 	if (error != 0) {
930 		device_printf(dev, "failed to install root pic handler\n");
931 		return (error);
932 	}
933 	intr_irq_root_dev = dev;
934 	irq_root_filter = filter;
935 	irq_root_arg = arg;
936 	irq_root_ipicount = ipicount;
937 
938 	debugf("irq root set to %s\n", device_get_nameunit(dev));
939 	return (0);
940 }
941 
942 int
943 intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
944     void *arg, u_int irq, int flags, void **cookiep)
945 {
946 	const char *name;
947 	struct intr_irqsrc *isrc;
948 	int error;
949 
950 	name = device_get_nameunit(dev);
951 
952 #ifdef INTR_SOLO
953 	/*
954 	 * Standard handling is done thru MI interrupt framework. However,
955 	 * some interrupts could request solely own special handling. This
956 	 * non standard handling can be used for interrupt controllers without
957 	 * handler (filter only), so in case that interrupt controllers are
958 	 * chained, MI interrupt framework is called only in leaf controller.
959 	 *
960 	 * Note that root interrupt controller routine is served as well,
961 	 * however in intr_irq_handler(), i.e. main system dispatch routine.
962 	 */
963 	if (flags & INTR_SOLO && hand != NULL) {
964 		debugf("irq %u cannot solo on %s\n", irq, name);
965 		return (EINVAL);
966 	}
967 #endif
968 
969 	isrc = isrc_lookup(irq);
970 	if (isrc == NULL) {
971 		debugf("irq %u without source on %s\n", irq, name);
972 		return (EINVAL);
973 	}
974 
975 	error = isrc_register(isrc);
976 	if (error != 0) {
977 		debugf("irq %u map error %d on %s\n", irq, error, name);
978 		return (error);
979 	}
980 
981 #ifdef INTR_SOLO
982 	if (flags & INTR_SOLO) {
983 		error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt,
984 		    arg, cookiep);
985 		debugf("irq %u setup filter error %d on %s\n", irq, error,
986 		    name);
987 	} else
988 #endif
989 		{
990 		error = isrc_add_handler(isrc, name, filt, hand, arg, flags,
991 		    cookiep);
992 		debugf("irq %u add handler error %d on %s\n", irq, error, name);
993 	}
994 	if (error != 0)
995 		return (error);
996 
997 	mtx_lock(&isrc_table_lock);
998 	isrc->isrc_handlers++;
999 	if (isrc->isrc_handlers == 1) {
1000 		PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
1001 		PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
1002 	}
1003 	mtx_unlock(&isrc_table_lock);
1004 	return (0);
1005 }
1006 
1007 int
1008 intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
1009 {
1010 	struct intr_irqsrc *isrc;
1011 	int error;
1012 
1013 	isrc = isrc_lookup(irq);
1014 	if (isrc == NULL || isrc->isrc_handlers == 0)
1015 		return (EINVAL);
1016 
1017 	if (isrc->isrc_filter != NULL) {
1018 		if (isrc != cookie)
1019 			return (EINVAL);
1020 
1021 		mtx_lock(&isrc_table_lock);
1022 		isrc->isrc_filter = NULL;
1023 		isrc->isrc_arg = NULL;
1024 		isrc->isrc_handlers = 0;
1025 		PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
1026 		PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
1027 		isrc_update_name(isrc, NULL);
1028 		mtx_unlock(&isrc_table_lock);
1029 		return (0);
1030 	}
1031 
1032 	if (isrc != intr_handler_source(cookie))
1033 		return (EINVAL);
1034 
1035 	error = intr_event_remove_handler(cookie);
1036 	if (error == 0) {
1037 		mtx_lock(&isrc_table_lock);
1038 		isrc->isrc_handlers--;
1039 		if (isrc->isrc_handlers == 0) {
1040 			PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
1041 			PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
1042 		}
1043 		intrcnt_updatename(isrc);
1044 		mtx_unlock(&isrc_table_lock);
1045 	}
1046 	return (error);
1047 }
1048 
1049 int
1050 intr_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
1051 {
1052 	struct intr_irqsrc *isrc;
1053 
1054 	isrc = isrc_lookup(irq);
1055 	if (isrc == NULL)
1056 		return (EINVAL);
1057 
1058 	if (isrc->isrc_handlers != 0)
1059 		return (EBUSY);	/* interrrupt is enabled (active) */
1060 
1061 	/*
1062 	 * Once an interrupt is enabled, we do not change its configuration.
1063 	 * A controller PIC_ENABLE_INTR() method is called when an interrupt
1064 	 * is going to be enabled. In this method, a controller should setup
1065 	 * the interrupt according to saved configuration parameters.
1066 	 */
1067 	isrc->isrc_trig = trig;
1068 	isrc->isrc_pol = pol;
1069 
1070 	return (0);
1071 }
1072 
1073 int
1074 intr_irq_describe(u_int irq, void *cookie, const char *descr)
1075 {
1076 	struct intr_irqsrc *isrc;
1077 	int error;
1078 
1079 	isrc = isrc_lookup(irq);
1080 	if (isrc == NULL || isrc->isrc_handlers == 0)
1081 		return (EINVAL);
1082 
1083 	if (isrc->isrc_filter != NULL) {
1084 		if (isrc != cookie)
1085 			return (EINVAL);
1086 
1087 		mtx_lock(&isrc_table_lock);
1088 		isrc_update_name(isrc, descr);
1089 		mtx_unlock(&isrc_table_lock);
1090 		return (0);
1091 	}
1092 
1093 	error = intr_event_describe_handler(isrc->isrc_event, cookie, descr);
1094 	if (error == 0) {
1095 		mtx_lock(&isrc_table_lock);
1096 		intrcnt_updatename(isrc);
1097 		mtx_unlock(&isrc_table_lock);
1098 	}
1099 	return (error);
1100 }
1101 
1102 #ifdef SMP
1103 int
1104 intr_irq_bind(u_int irq, int cpu)
1105 {
1106 	struct intr_irqsrc *isrc;
1107 
1108 	isrc = isrc_lookup(irq);
1109 	if (isrc == NULL || isrc->isrc_handlers == 0)
1110 		return (EINVAL);
1111 
1112 	if (isrc->isrc_filter != NULL)
1113 		return (intr_isrc_assign_cpu(isrc, cpu));
1114 
1115 	return (intr_event_bind(isrc->isrc_event, cpu));
1116 }
1117 
1118 /*
1119  * Return the CPU that the next interrupt source should use.
1120  * For now just returns the next CPU according to round-robin.
1121  */
1122 u_int
1123 intr_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask)
1124 {
1125 
1126 	if (!irq_assign_cpu || mp_ncpus == 1)
1127 		return (PCPU_GET(cpuid));
1128 
1129 	do {
1130 		last_cpu++;
1131 		if (last_cpu > mp_maxid)
1132 			last_cpu = 0;
1133 	} while (!CPU_ISSET(last_cpu, cpumask));
1134 	return (last_cpu);
1135 }
1136 
1137 /*
1138  *  Distribute all the interrupt sources among the available
1139  *  CPUs once the AP's have been launched.
1140  */
1141 static void
1142 intr_irq_shuffle(void *arg __unused)
1143 {
1144 	struct intr_irqsrc *isrc;
1145 	u_int i;
1146 
1147 	if (mp_ncpus == 1)
1148 		return;
1149 
1150 	mtx_lock(&isrc_table_lock);
1151 	irq_assign_cpu = TRUE;
1152 	for (i = 0; i < NIRQ; i++) {
1153 		isrc = irq_sources[i];
1154 		if (isrc == NULL || isrc->isrc_handlers == 0 ||
1155 		    isrc->isrc_flags & INTR_ISRCF_PERCPU)
1156 			continue;
1157 
1158 		if (isrc->isrc_event != NULL &&
1159 		    isrc->isrc_flags & INTR_ISRCF_BOUND &&
1160 		    isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1)
1161 			panic("%s: CPU inconsistency", __func__);
1162 
1163 		if ((isrc->isrc_flags & INTR_ISRCF_BOUND) == 0)
1164 			CPU_ZERO(&isrc->isrc_cpu); /* start again */
1165 
1166 		/*
1167 		 * We are in wicked position here if the following call fails
1168 		 * for bound ISRC. The best thing we can do is to clear
1169 		 * isrc_cpu so inconsistency with ie_cpu will be detectable.
1170 		 */
1171 		if (PIC_BIND(isrc->isrc_dev, isrc) != 0)
1172 			CPU_ZERO(&isrc->isrc_cpu);
1173 	}
1174 	mtx_unlock(&isrc_table_lock);
1175 }
1176 SYSINIT(intr_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, intr_irq_shuffle, NULL);
1177 
1178 #else
1179 u_int
1180 intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
1181 {
1182 
1183 	return (PCPU_GET(cpuid));
1184 }
1185 #endif
1186 
1187 void dosoftints(void);
1188 void
1189 dosoftints(void)
1190 {
1191 }
1192 
1193 #ifdef SMP
1194 /*
1195  *  Init interrupt controller on another CPU.
1196  */
1197 void
1198 intr_pic_init_secondary(void)
1199 {
1200 
1201 	/*
1202 	 * QQQ: Only root PIC is aware of other CPUs ???
1203 	 */
1204 	KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
1205 
1206 	//mtx_lock(&isrc_table_lock);
1207 	PIC_INIT_SECONDARY(intr_irq_root_dev);
1208 	//mtx_unlock(&isrc_table_lock);
1209 }
1210 #endif
1211 
1212 #ifdef DDB
1213 DB_SHOW_COMMAND(irqs, db_show_irqs)
1214 {
1215 	u_int i, irqsum;
1216 	struct intr_irqsrc *isrc;
1217 
1218 	for (irqsum = 0, i = 0; i < NIRQ; i++) {
1219 		isrc = irq_sources[i];
1220 		if (isrc == NULL)
1221 			continue;
1222 
1223 		db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
1224 		    isrc->isrc_name, isrc->isrc_cpu.__bits[0],
1225 		    isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "",
1226 		    isrc->isrc_count[0]);
1227 		irqsum += isrc->isrc_count[0];
1228 	}
1229 	db_printf("irq total %u\n", irqsum);
1230 }
1231 #endif
1232