INTRNG: As follow up of r301451, implement mapping and configuration
[freebsd.git] / sys / kern / subr_intr.c
1 /*-
2  * Copyright (c) 2015-2016 Svatopluk Kraus
3  * Copyright (c) 2015-2016 Michal Meloun
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  *      New-style Interrupt Framework
33  *
34  *  TODO: - to support IPI (PPI) enabling on other CPUs if already started
35  *        - to complete things for removable PICs
36  */
37
38 #include "opt_acpi.h"
39 #include "opt_ddb.h"
40 #include "opt_hwpmc_hooks.h"
41 #include "opt_platform.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/syslog.h>
47 #include <sys/malloc.h>
48 #include <sys/proc.h>
49 #include <sys/queue.h>
50 #include <sys/bus.h>
51 #include <sys/interrupt.h>
52 #include <sys/conf.h>
53 #include <sys/cpuset.h>
54 #include <sys/rman.h>
55 #include <sys/sched.h>
56 #include <sys/smp.h>
57 #ifdef HWPMC_HOOKS
58 #include <sys/pmckern.h>
59 #endif
60
61 #include <machine/atomic.h>
62 #include <machine/intr.h>
63 #include <machine/cpu.h>
64 #include <machine/smp.h>
65 #include <machine/stdarg.h>
66
67 #ifdef DDB
68 #include <ddb/ddb.h>
69 #endif
70
71 #include "pic_if.h"
72 #include "msi_if.h"
73
74 #define INTRNAME_LEN    (2*MAXCOMLEN + 1)
75
76 #ifdef DEBUG
77 #define debugf(fmt, args...) do { printf("%s(): ", __func__);   \
78     printf(fmt,##args); } while (0)
79 #else
80 #define debugf(fmt, args...)
81 #endif
82
83 MALLOC_DECLARE(M_INTRNG);
84 MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
85
86 /* Main interrupt handler called from assembler -> 'hidden' for C code. */
87 void intr_irq_handler(struct trapframe *tf);
88
89 /* Root interrupt controller stuff. */
90 device_t intr_irq_root_dev;
91 static intr_irq_filter_t *irq_root_filter;
92 static void *irq_root_arg;
93 static u_int irq_root_ipicount;
94
95 struct intr_pic_child {
96         SLIST_ENTRY(intr_pic_child)      pc_next;
97         struct intr_pic                 *pc_pic;
98         intr_child_irq_filter_t         *pc_filter;
99         void                            *pc_filter_arg;
100         uintptr_t                        pc_start;
101         uintptr_t                        pc_length;
102 };
103
104 /* Interrupt controller definition. */
105 struct intr_pic {
106         SLIST_ENTRY(intr_pic)   pic_next;
107         intptr_t                pic_xref;       /* hardware identification */
108         device_t                pic_dev;
109 #define FLAG_PIC        (1 << 0)
110 #define FLAG_MSI        (1 << 1)
111         u_int                   pic_flags;
112         struct mtx              pic_child_lock;
113         SLIST_HEAD(, intr_pic_child) pic_children;
114 };
115
116 static struct mtx pic_list_lock;
117 static SLIST_HEAD(, intr_pic) pic_list;
118
119 static struct intr_pic *pic_lookup(device_t dev, intptr_t xref);
120
121 /* Interrupt source definition. */
122 static struct mtx isrc_table_lock;
123 static struct intr_irqsrc *irq_sources[NIRQ];
124 u_int irq_next_free;
125
126 /*
127  *  XXX - All stuff around struct intr_dev_data is considered as temporary
128  *  until better place for storing struct intr_map_data will be find.
129  *
130  *  For now, there are two global interrupt numbers spaces:
131  *  <0, NIRQ)                      ... interrupts without config data
132  *                                     managed in irq_sources[]
133  *  IRQ_DDATA_BASE + <0, 2 * NIRQ) ... interrupts with config data
134  *                                     managed in intr_ddata_tab[]
135  *
136  *  Read intr_ddata_lookup() to see how these spaces are worked with.
137  *  Note that each interrupt number from second space duplicates some number
138  *  from first space at this moment. An interrupt number from first space can
139  *  be duplicated even multiple times in second space.
140  */
141 struct intr_dev_data {
142         device_t                idd_dev;
143         intptr_t                idd_xref;
144         u_int                   idd_irq;
145         struct intr_map_data *  idd_data;
146         struct intr_irqsrc *    idd_isrc;
147 };
148
149 static struct intr_dev_data *intr_ddata_tab[2 * NIRQ];
150 #if 0
151 static u_int intr_ddata_first_unused;
152 #endif
153
154 #define IRQ_DDATA_BASE  10000
155 CTASSERT(IRQ_DDATA_BASE > nitems(irq_sources));
156
157 #ifdef SMP
158 static boolean_t irq_assign_cpu = FALSE;
159 #endif
160
161 /*
162  * - 2 counters for each I/O interrupt.
163  * - MAXCPU counters for each IPI counters for SMP.
164  */
165 #ifdef SMP
166 #define INTRCNT_COUNT   (NIRQ * 2 + INTR_IPI_COUNT * MAXCPU)
167 #else
168 #define INTRCNT_COUNT   (NIRQ * 2)
169 #endif
170
171 /* Data for MI statistics reporting. */
172 u_long intrcnt[INTRCNT_COUNT];
173 char intrnames[INTRCNT_COUNT * INTRNAME_LEN];
174 size_t sintrcnt = sizeof(intrcnt);
175 size_t sintrnames = sizeof(intrnames);
176 static u_int intrcnt_index;
177
178 /*
179  *  Interrupt framework initialization routine.
180  */
181 static void
182 intr_irq_init(void *dummy __unused)
183 {
184
185         SLIST_INIT(&pic_list);
186         mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
187
188         mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF);
189 }
190 SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL);
191
192 static void
193 intrcnt_setname(const char *name, int index)
194 {
195
196         snprintf(intrnames + INTRNAME_LEN * index, INTRNAME_LEN, "%-*s",
197             INTRNAME_LEN - 1, name);
198 }
199
200 /*
201  *  Update name for interrupt source with interrupt event.
202  */
203 static void
204 intrcnt_updatename(struct intr_irqsrc *isrc)
205 {
206
207         /* QQQ: What about stray counter name? */
208         mtx_assert(&isrc_table_lock, MA_OWNED);
209         intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index);
210 }
211
212 /*
213  *  Virtualization for interrupt source interrupt counter increment.
214  */
215 static inline void
216 isrc_increment_count(struct intr_irqsrc *isrc)
217 {
218
219         if (isrc->isrc_flags & INTR_ISRCF_PPI)
220                 atomic_add_long(&isrc->isrc_count[0], 1);
221         else
222                 isrc->isrc_count[0]++;
223 }
224
225 /*
226  *  Virtualization for interrupt source interrupt stray counter increment.
227  */
228 static inline void
229 isrc_increment_straycount(struct intr_irqsrc *isrc)
230 {
231
232         isrc->isrc_count[1]++;
233 }
234
235 /*
236  *  Virtualization for interrupt source interrupt name update.
237  */
238 static void
239 isrc_update_name(struct intr_irqsrc *isrc, const char *name)
240 {
241         char str[INTRNAME_LEN];
242
243         mtx_assert(&isrc_table_lock, MA_OWNED);
244
245         if (name != NULL) {
246                 snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name);
247                 intrcnt_setname(str, isrc->isrc_index);
248                 snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name,
249                     name);
250                 intrcnt_setname(str, isrc->isrc_index + 1);
251         } else {
252                 snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name);
253                 intrcnt_setname(str, isrc->isrc_index);
254                 snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name);
255                 intrcnt_setname(str, isrc->isrc_index + 1);
256         }
257 }
258
259 /*
260  *  Virtualization for interrupt source interrupt counters setup.
261  */
262 static void
263 isrc_setup_counters(struct intr_irqsrc *isrc)
264 {
265         u_int index;
266
267         /*
268          *  XXX - it does not work well with removable controllers and
269          *        interrupt sources !!!
270          */
271         index = atomic_fetchadd_int(&intrcnt_index, 2);
272         isrc->isrc_index = index;
273         isrc->isrc_count = &intrcnt[index];
274         isrc_update_name(isrc, NULL);
275 }
276
277 /*
278  *  Virtualization for interrupt source interrupt counters release.
279  */
280 static void
281 isrc_release_counters(struct intr_irqsrc *isrc)
282 {
283
284         panic("%s: not implemented", __func__);
285 }
286
287 #ifdef SMP
288 /*
289  *  Virtualization for interrupt source IPI counters setup.
290  */
291 u_long *
292 intr_ipi_setup_counters(const char *name)
293 {
294         u_int index, i;
295         char str[INTRNAME_LEN];
296
297         index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
298         for (i = 0; i < MAXCPU; i++) {
299                 snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name);
300                 intrcnt_setname(str, index + i);
301         }
302         return (&intrcnt[index]);
303 }
304 #endif
305
306 /*
307  *  Main interrupt dispatch handler. It's called straight
308  *  from the assembler, where CPU interrupt is served.
309  */
310 void
311 intr_irq_handler(struct trapframe *tf)
312 {
313         struct trapframe * oldframe;
314         struct thread * td;
315
316         KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__));
317
318         PCPU_INC(cnt.v_intr);
319         critical_enter();
320         td = curthread;
321         oldframe = td->td_intr_frame;
322         td->td_intr_frame = tf;
323         irq_root_filter(irq_root_arg);
324         td->td_intr_frame = oldframe;
325         critical_exit();
326 #ifdef HWPMC_HOOKS
327         if (pmc_hook && TRAPF_USERMODE(tf) &&
328             (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
329                 pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
330 #endif
331 }
332
333 int
334 intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq)
335 {
336         struct intr_pic_child *child;
337         bool found;
338
339         found = false;
340         mtx_lock_spin(&parent->pic_child_lock);
341         SLIST_FOREACH(child, &parent->pic_children, pc_next) {
342                 if (child->pc_start <= irq &&
343                     irq < (child->pc_start + child->pc_length)) {
344                         found = true;
345                         break;
346                 }
347         }
348         mtx_unlock_spin(&parent->pic_child_lock);
349
350         if (found)
351                 return (child->pc_filter(child->pc_filter_arg, irq));
352
353         return (FILTER_STRAY);
354 }
355
356 /*
357  *  interrupt controller dispatch function for interrupts. It should
358  *  be called straight from the interrupt controller, when associated interrupt
359  *  source is learned.
360  */
361 int
362 intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
363 {
364
365         KASSERT(isrc != NULL, ("%s: no source", __func__));
366
367         isrc_increment_count(isrc);
368
369 #ifdef INTR_SOLO
370         if (isrc->isrc_filter != NULL) {
371                 int error;
372                 error = isrc->isrc_filter(isrc->isrc_arg, tf);
373                 PIC_POST_FILTER(isrc->isrc_dev, isrc);
374                 if (error == FILTER_HANDLED)
375                         return (0);
376         } else
377 #endif
378         if (isrc->isrc_event != NULL) {
379                 if (intr_event_handle(isrc->isrc_event, tf) == 0)
380                         return (0);
381         }
382
383         isrc_increment_straycount(isrc);
384         return (EINVAL);
385 }
386
387 /*
388  *  Alloc unique interrupt number (resource handle) for interrupt source.
389  *
390  *  There could be various strategies how to allocate free interrupt number
391  *  (resource handle) for new interrupt source.
392  *
393  *  1. Handles are always allocated forward, so handles are not recycled
394  *     immediately. However, if only one free handle left which is reused
395  *     constantly...
396  */
397 static inline int
398 isrc_alloc_irq(struct intr_irqsrc *isrc)
399 {
400         u_int maxirqs, irq;
401
402         mtx_assert(&isrc_table_lock, MA_OWNED);
403
404         maxirqs = nitems(irq_sources);
405         if (irq_next_free >= maxirqs)
406                 return (ENOSPC);
407
408         for (irq = irq_next_free; irq < maxirqs; irq++) {
409                 if (irq_sources[irq] == NULL)
410                         goto found;
411         }
412         for (irq = 0; irq < irq_next_free; irq++) {
413                 if (irq_sources[irq] == NULL)
414                         goto found;
415         }
416
417         irq_next_free = maxirqs;
418         return (ENOSPC);
419
420 found:
421         isrc->isrc_irq = irq;
422         irq_sources[irq] = isrc;
423
424         irq_next_free = irq + 1;
425         if (irq_next_free >= maxirqs)
426                 irq_next_free = 0;
427         return (0);
428 }
429
430 /*
431  *  Free unique interrupt number (resource handle) from interrupt source.
432  */
433 static inline int
434 isrc_free_irq(struct intr_irqsrc *isrc)
435 {
436
437         mtx_assert(&isrc_table_lock, MA_OWNED);
438
439         if (isrc->isrc_irq >= nitems(irq_sources))
440                 return (EINVAL);
441         if (irq_sources[isrc->isrc_irq] != isrc)
442                 return (EINVAL);
443
444         irq_sources[isrc->isrc_irq] = NULL;
445         isrc->isrc_irq = INTR_IRQ_INVALID;      /* just to be safe */
446         return (0);
447 }
448
449 /*
450  *  Lookup interrupt source by interrupt number (resource handle).
451  */
452 static inline struct intr_irqsrc *
453 isrc_lookup(u_int irq)
454 {
455
456         if (irq < nitems(irq_sources))
457                 return (irq_sources[irq]);
458         return (NULL);
459 }
460
461 /*
462  *  Initialize interrupt source and register it into global interrupt table.
463  */
464 int
465 intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
466     const char *fmt, ...)
467 {
468         int error;
469         va_list ap;
470
471         bzero(isrc, sizeof(struct intr_irqsrc));
472         isrc->isrc_dev = dev;
473         isrc->isrc_irq = INTR_IRQ_INVALID;      /* just to be safe */
474         isrc->isrc_flags = flags;
475
476         va_start(ap, fmt);
477         vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
478         va_end(ap);
479
480         mtx_lock(&isrc_table_lock);
481         error = isrc_alloc_irq(isrc);
482         if (error != 0) {
483                 mtx_unlock(&isrc_table_lock);
484                 return (error);
485         }
486         /*
487          * Setup interrupt counters, but not for IPI sources. Those are setup
488          * later and only for used ones (up to INTR_IPI_COUNT) to not exhaust
489          * our counter pool.
490          */
491         if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
492                 isrc_setup_counters(isrc);
493         mtx_unlock(&isrc_table_lock);
494         return (0);
495 }
496
497 /*
498  *  Deregister interrupt source from global interrupt table.
499  */
500 int
501 intr_isrc_deregister(struct intr_irqsrc *isrc)
502 {
503         int error;
504
505         mtx_lock(&isrc_table_lock);
506         if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
507                 isrc_release_counters(isrc);
508         error = isrc_free_irq(isrc);
509         mtx_unlock(&isrc_table_lock);
510         return (error);
511 }
512
513 #ifdef SMP
514 /*
515  *  A support function for a PIC to decide if provided ISRC should be inited
516  *  on given cpu. The logic of INTR_ISRCF_BOUND flag and isrc_cpu member of
517  *  struct intr_irqsrc is the following:
518  *
519  *     If INTR_ISRCF_BOUND is set, the ISRC should be inited only on cpus
520  *     set in isrc_cpu. If not, the ISRC should be inited on every cpu and
521  *     isrc_cpu is kept consistent with it. Thus isrc_cpu is always correct.
522  */
523 bool
524 intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu)
525 {
526
527         if (isrc->isrc_handlers == 0)
528                 return (false);
529         if ((isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI)) == 0)
530                 return (false);
531         if (isrc->isrc_flags & INTR_ISRCF_BOUND)
532                 return (CPU_ISSET(cpu, &isrc->isrc_cpu));
533
534         CPU_SET(cpu, &isrc->isrc_cpu);
535         return (true);
536 }
537 #endif
538
539 #if 0
540 static struct intr_dev_data *
541 intr_ddata_alloc(u_int extsize)
542 {
543         struct intr_dev_data *ddata;
544         size_t size;
545
546         size = sizeof(*ddata);
547         ddata = malloc(size + extsize, M_INTRNG, M_WAITOK | M_ZERO);
548
549         mtx_lock(&isrc_table_lock);
550         if (intr_ddata_first_unused >= nitems(intr_ddata_tab)) {
551                 mtx_unlock(&isrc_table_lock);
552                 free(ddata, M_INTRNG);
553                 return (NULL);
554         }
555         intr_ddata_tab[intr_ddata_first_unused] = ddata;
556         ddata->idd_irq = IRQ_DDATA_BASE + intr_ddata_first_unused++;
557         mtx_unlock(&isrc_table_lock);
558
559         ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size);
560         return (ddata);
561 }
562 #endif
563
564 static struct intr_irqsrc *
565 intr_ddata_lookup(u_int irq, struct intr_map_data **datap)
566 {
567         int error;
568         struct intr_irqsrc *isrc;
569         struct intr_dev_data *ddata;
570
571         isrc = isrc_lookup(irq);
572         if (isrc != NULL) {
573                 if (datap != NULL)
574                         *datap = NULL;
575                 return (isrc);
576         }
577
578         if (irq < IRQ_DDATA_BASE)
579                 return (NULL);
580
581         irq -= IRQ_DDATA_BASE;
582         if (irq >= nitems(intr_ddata_tab))
583                 return (NULL);
584
585         ddata = intr_ddata_tab[irq];
586         if (ddata->idd_isrc == NULL) {
587                 error = intr_map_irq(ddata->idd_dev, ddata->idd_xref,
588                     ddata->idd_data, &irq);
589                 if (error != 0)
590                         return (NULL);
591                 ddata->idd_isrc = isrc_lookup(irq);
592         }
593         if (datap != NULL)
594                 *datap = ddata->idd_data;
595         return (ddata->idd_isrc);
596 }
597
598 #ifdef DEV_ACPI
599 /*
600  *  Map interrupt source according to ACPI info into framework. If such mapping
601  *  does not exist, create it. Return unique interrupt number (resource handle)
602  *  associated with mapped interrupt source.
603  */
604 u_int
605 intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol,
606     enum intr_trigger trig)
607 {
608         struct intr_map_data_acpi *daa;
609         struct intr_dev_data *ddata;
610
611         ddata = intr_ddata_alloc(sizeof(struct intr_map_data_acpi));
612         if (ddata == NULL)
613                 return (INTR_IRQ_INVALID);      /* no space left */
614
615         ddata->idd_dev = dev;
616         ddata->idd_data->type = INTR_MAP_DATA_ACPI;
617
618         daa = (struct intr_map_data_acpi *)ddata->idd_data;
619         daa->irq = irq;
620         daa->pol = pol;
621         daa->trig = trig;
622
623         return (ddata->idd_irq);
624 }
625 #endif
626
627 #ifdef INTR_SOLO
628 /*
629  *  Setup filter into interrupt source.
630  */
631 static int
632 iscr_setup_filter(struct intr_irqsrc *isrc, const char *name,
633     intr_irq_filter_t *filter, void *arg, void **cookiep)
634 {
635
636         if (filter == NULL)
637                 return (EINVAL);
638
639         mtx_lock(&isrc_table_lock);
640         /*
641          * Make sure that we do not mix the two ways
642          * how we handle interrupt sources.
643          */
644         if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) {
645                 mtx_unlock(&isrc_table_lock);
646                 return (EBUSY);
647         }
648         isrc->isrc_filter = filter;
649         isrc->isrc_arg = arg;
650         isrc_update_name(isrc, name);
651         mtx_unlock(&isrc_table_lock);
652
653         *cookiep = isrc;
654         return (0);
655 }
656 #endif
657
658 /*
659  *  Interrupt source pre_ithread method for MI interrupt framework.
660  */
661 static void
662 intr_isrc_pre_ithread(void *arg)
663 {
664         struct intr_irqsrc *isrc = arg;
665
666         PIC_PRE_ITHREAD(isrc->isrc_dev, isrc);
667 }
668
669 /*
670  *  Interrupt source post_ithread method for MI interrupt framework.
671  */
672 static void
673 intr_isrc_post_ithread(void *arg)
674 {
675         struct intr_irqsrc *isrc = arg;
676
677         PIC_POST_ITHREAD(isrc->isrc_dev, isrc);
678 }
679
680 /*
681  *  Interrupt source post_filter method for MI interrupt framework.
682  */
683 static void
684 intr_isrc_post_filter(void *arg)
685 {
686         struct intr_irqsrc *isrc = arg;
687
688         PIC_POST_FILTER(isrc->isrc_dev, isrc);
689 }
690
691 /*
692  *  Interrupt source assign_cpu method for MI interrupt framework.
693  */
694 static int
695 intr_isrc_assign_cpu(void *arg, int cpu)
696 {
697 #ifdef SMP
698         struct intr_irqsrc *isrc = arg;
699         int error;
700
701         if (isrc->isrc_dev != intr_irq_root_dev)
702                 return (EINVAL);
703
704         mtx_lock(&isrc_table_lock);
705         if (cpu == NOCPU) {
706                 CPU_ZERO(&isrc->isrc_cpu);
707                 isrc->isrc_flags &= ~INTR_ISRCF_BOUND;
708         } else {
709                 CPU_SETOF(cpu, &isrc->isrc_cpu);
710                 isrc->isrc_flags |= INTR_ISRCF_BOUND;
711         }
712
713         /*
714          * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or
715          * re-balance it to another CPU or enable it on more CPUs. However,
716          * PIC is expected to change isrc_cpu appropriately to keep us well
717          * informed if the call is successful.
718          */
719         if (irq_assign_cpu) {
720                 error = PIC_BIND_INTR(isrc->isrc_dev, isrc);
721                 if (error) {
722                         CPU_ZERO(&isrc->isrc_cpu);
723                         mtx_unlock(&isrc_table_lock);
724                         return (error);
725                 }
726         }
727         mtx_unlock(&isrc_table_lock);
728         return (0);
729 #else
730         return (EOPNOTSUPP);
731 #endif
732 }
733
734 /*
735  *  Create interrupt event for interrupt source.
736  */
737 static int
738 isrc_event_create(struct intr_irqsrc *isrc)
739 {
740         struct intr_event *ie;
741         int error;
742
743         error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq,
744             intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter,
745             intr_isrc_assign_cpu, "%s:", isrc->isrc_name);
746         if (error)
747                 return (error);
748
749         mtx_lock(&isrc_table_lock);
750         /*
751          * Make sure that we do not mix the two ways
752          * how we handle interrupt sources. Let contested event wins.
753          */
754 #ifdef INTR_SOLO
755         if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) {
756 #else
757         if (isrc->isrc_event != NULL) {
758 #endif
759                 mtx_unlock(&isrc_table_lock);
760                 intr_event_destroy(ie);
761                 return (isrc->isrc_event != NULL ? EBUSY : 0);
762         }
763         isrc->isrc_event = ie;
764         mtx_unlock(&isrc_table_lock);
765
766         return (0);
767 }
768 #ifdef notyet
769 /*
770  *  Destroy interrupt event for interrupt source.
771  */
772 static void
773 isrc_event_destroy(struct intr_irqsrc *isrc)
774 {
775         struct intr_event *ie;
776
777         mtx_lock(&isrc_table_lock);
778         ie = isrc->isrc_event;
779         isrc->isrc_event = NULL;
780         mtx_unlock(&isrc_table_lock);
781
782         if (ie != NULL)
783                 intr_event_destroy(ie);
784 }
785 #endif
786 /*
787  *  Add handler to interrupt source.
788  */
789 static int
790 isrc_add_handler(struct intr_irqsrc *isrc, const char *name,
791     driver_filter_t filter, driver_intr_t handler, void *arg,
792     enum intr_type flags, void **cookiep)
793 {
794         int error;
795
796         if (isrc->isrc_event == NULL) {
797                 error = isrc_event_create(isrc);
798                 if (error)
799                         return (error);
800         }
801
802         error = intr_event_add_handler(isrc->isrc_event, name, filter, handler,
803             arg, intr_priority(flags), flags, cookiep);
804         if (error == 0) {
805                 mtx_lock(&isrc_table_lock);
806                 intrcnt_updatename(isrc);
807                 mtx_unlock(&isrc_table_lock);
808         }
809
810         return (error);
811 }
812
813 /*
814  *  Lookup interrupt controller locked.
815  */
816 static inline struct intr_pic *
817 pic_lookup_locked(device_t dev, intptr_t xref)
818 {
819         struct intr_pic *pic;
820
821         mtx_assert(&pic_list_lock, MA_OWNED);
822
823         if (dev == NULL && xref == 0)
824                 return (NULL);
825
826         /* Note that pic->pic_dev is never NULL on registered PIC. */
827         SLIST_FOREACH(pic, &pic_list, pic_next) {
828                 if (dev == NULL) {
829                         if (xref == pic->pic_xref)
830                                 return (pic);
831                 } else if (xref == 0 || pic->pic_xref == 0) {
832                         if (dev == pic->pic_dev)
833                                 return (pic);
834                 } else if (xref == pic->pic_xref && dev == pic->pic_dev)
835                                 return (pic);
836         }
837         return (NULL);
838 }
839
840 /*
841  *  Lookup interrupt controller.
842  */
843 static struct intr_pic *
844 pic_lookup(device_t dev, intptr_t xref)
845 {
846         struct intr_pic *pic;
847
848         mtx_lock(&pic_list_lock);
849         pic = pic_lookup_locked(dev, xref);
850         mtx_unlock(&pic_list_lock);
851         return (pic);
852 }
853
854 /*
855  *  Create interrupt controller.
856  */
857 static struct intr_pic *
858 pic_create(device_t dev, intptr_t xref)
859 {
860         struct intr_pic *pic;
861
862         mtx_lock(&pic_list_lock);
863         pic = pic_lookup_locked(dev, xref);
864         if (pic != NULL) {
865                 mtx_unlock(&pic_list_lock);
866                 return (pic);
867         }
868         pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO);
869         if (pic == NULL) {
870                 mtx_unlock(&pic_list_lock);
871                 return (NULL);
872         }
873         pic->pic_xref = xref;
874         pic->pic_dev = dev;
875         mtx_init(&pic->pic_child_lock, "pic child lock", NULL, MTX_SPIN);
876         SLIST_INSERT_HEAD(&pic_list, pic, pic_next);
877         mtx_unlock(&pic_list_lock);
878
879         return (pic);
880 }
881 #ifdef notyet
882 /*
883  *  Destroy interrupt controller.
884  */
885 static void
886 pic_destroy(device_t dev, intptr_t xref)
887 {
888         struct intr_pic *pic;
889
890         mtx_lock(&pic_list_lock);
891         pic = pic_lookup_locked(dev, xref);
892         if (pic == NULL) {
893                 mtx_unlock(&pic_list_lock);
894                 return;
895         }
896         SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next);
897         mtx_unlock(&pic_list_lock);
898
899         free(pic, M_INTRNG);
900 }
901 #endif
902 /*
903  *  Register interrupt controller.
904  */
905 struct intr_pic *
906 intr_pic_register(device_t dev, intptr_t xref)
907 {
908         struct intr_pic *pic;
909
910         if (dev == NULL)
911                 return (NULL);
912         pic = pic_create(dev, xref);
913         if (pic == NULL)
914                 return (NULL);
915
916         pic->pic_flags |= FLAG_PIC;
917
918         debugf("PIC %p registered for %s <dev %p, xref %x>\n", pic,
919             device_get_nameunit(dev), dev, xref);
920         return (pic);
921 }
922
923 /*
924  *  Unregister interrupt controller.
925  */
926 int
927 intr_pic_deregister(device_t dev, intptr_t xref)
928 {
929
930         panic("%s: not implemented", __func__);
931 }
932
933 /*
934  *  Mark interrupt controller (itself) as a root one.
935  *
936  *  Note that only an interrupt controller can really know its position
937  *  in interrupt controller's tree. So root PIC must claim itself as a root.
938  *
939  *  In FDT case, according to ePAPR approved version 1.1 from 08 April 2011,
940  *  page 30:
941  *    "The root of the interrupt tree is determined when traversal
942  *     of the interrupt tree reaches an interrupt controller node without
943  *     an interrupts property and thus no explicit interrupt parent."
944  */
945 int
946 intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
947     void *arg, u_int ipicount)
948 {
949         struct intr_pic *pic;
950
951         pic = pic_lookup(dev, xref);
952         if (pic == NULL) {
953                 device_printf(dev, "not registered\n");
954                 return (EINVAL);
955         }
956
957         KASSERT((pic->pic_flags & FLAG_PIC) != 0,
958             ("%s: Found a non-PIC controller: %s", __func__,
959              device_get_name(pic->pic_dev)));
960
961         if (filter == NULL) {
962                 device_printf(dev, "filter missing\n");
963                 return (EINVAL);
964         }
965
966         /*
967          * Only one interrupt controllers could be on the root for now.
968          * Note that we further suppose that there is not threaded interrupt
969          * routine (handler) on the root. See intr_irq_handler().
970          */
971         if (intr_irq_root_dev != NULL) {
972                 device_printf(dev, "another root already set\n");
973                 return (EBUSY);
974         }
975
976         intr_irq_root_dev = dev;
977         irq_root_filter = filter;
978         irq_root_arg = arg;
979         irq_root_ipicount = ipicount;
980
981         debugf("irq root set to %s\n", device_get_nameunit(dev));
982         return (0);
983 }
984
985 /*
986  * Add a handler to manage a sub range of a parents interrupts.
987  */
988 struct intr_pic *
989 intr_pic_add_handler(device_t parent, struct intr_pic *pic,
990     intr_child_irq_filter_t *filter, void *arg, uintptr_t start,
991     uintptr_t length)
992 {
993         struct intr_pic *parent_pic;
994         struct intr_pic_child *newchild;
995 #ifdef INVARIANTS
996         struct intr_pic_child *child;
997 #endif
998
999         parent_pic = pic_lookup(parent, 0);
1000         if (parent_pic == NULL)
1001                 return (NULL);
1002
1003         newchild = malloc(sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO);
1004         newchild->pc_pic = pic;
1005         newchild->pc_filter = filter;
1006         newchild->pc_filter_arg = arg;
1007         newchild->pc_start = start;
1008         newchild->pc_length = length;
1009
1010         mtx_lock_spin(&parent_pic->pic_child_lock);
1011 #ifdef INVARIANTS
1012         SLIST_FOREACH(child, &parent_pic->pic_children, pc_next) {
1013                 KASSERT(child->pc_pic != pic, ("%s: Adding a child PIC twice",
1014                     __func__));
1015         }
1016 #endif
1017         SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next);
1018         mtx_unlock_spin(&parent_pic->pic_child_lock);
1019
1020         return (pic);
1021 }
1022
1023 int
1024 intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data,
1025     u_int *irqp)
1026 {
1027         int error;
1028         struct intr_irqsrc *isrc;
1029         struct intr_pic *pic;
1030
1031         if (data == NULL)
1032                 return (EINVAL);
1033
1034         pic = pic_lookup(dev, xref);
1035         if (pic == NULL)
1036                 return (ESRCH);
1037
1038         KASSERT((pic->pic_flags & FLAG_PIC) != 0,
1039             ("%s: Found a non-PIC controller: %s", __func__,
1040              device_get_name(pic->pic_dev)));
1041
1042         error = PIC_MAP_INTR(pic->pic_dev, data, &isrc);
1043         if (error == 0)
1044                 *irqp = isrc->isrc_irq;
1045         return (error);
1046 }
1047
1048 int
1049 intr_alloc_irq(device_t dev, struct resource *res)
1050 {
1051         struct intr_map_data *data;
1052         struct intr_irqsrc *isrc;
1053
1054         KASSERT(rman_get_start(res) == rman_get_end(res),
1055             ("%s: more interrupts in resource", __func__));
1056
1057         data = rman_get_virtual(res);
1058         if (data == NULL)
1059                 isrc = intr_ddata_lookup(rman_get_start(res), &data);
1060         else
1061                 isrc = isrc_lookup(rman_get_start(res));
1062         if (isrc == NULL)
1063                 return (EINVAL);
1064
1065         return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data));
1066 }
1067
1068 int
1069 intr_release_irq(device_t dev, struct resource *res)
1070 {
1071         struct intr_map_data *data;
1072         struct intr_irqsrc *isrc;
1073
1074         KASSERT(rman_get_start(res) == rman_get_end(res),
1075             ("%s: more interrupts in resource", __func__));
1076
1077         data = rman_get_virtual(res);
1078         if (data == NULL)
1079                 isrc = intr_ddata_lookup(rman_get_start(res), &data);
1080         else
1081                 isrc = isrc_lookup(rman_get_start(res));
1082         if (isrc == NULL)
1083                 return (EINVAL);
1084
1085         return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data));
1086 }
1087
1088 int
1089 intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt,
1090     driver_intr_t hand, void *arg, int flags, void **cookiep)
1091 {
1092         int error;
1093         struct intr_map_data *data;
1094         struct intr_irqsrc *isrc;
1095         const char *name;
1096
1097         KASSERT(rman_get_start(res) == rman_get_end(res),
1098             ("%s: more interrupts in resource", __func__));
1099
1100         data = rman_get_virtual(res);
1101         if (data == NULL)
1102                 isrc = intr_ddata_lookup(rman_get_start(res), &data);
1103         else
1104                 isrc = isrc_lookup(rman_get_start(res));
1105         if (isrc == NULL)
1106                 return (EINVAL);
1107
1108         name = device_get_nameunit(dev);
1109
1110 #ifdef INTR_SOLO
1111         /*
1112          * Standard handling is done through MI interrupt framework. However,
1113          * some interrupts could request solely own special handling. This
1114          * non standard handling can be used for interrupt controllers without
1115          * handler (filter only), so in case that interrupt controllers are
1116          * chained, MI interrupt framework is called only in leaf controller.
1117          *
1118          * Note that root interrupt controller routine is served as well,
1119          * however in intr_irq_handler(), i.e. main system dispatch routine.
1120          */
1121         if (flags & INTR_SOLO && hand != NULL) {
1122                 debugf("irq %u cannot solo on %s\n", irq, name);
1123                 return (EINVAL);
1124         }
1125
1126         if (flags & INTR_SOLO) {
1127                 error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt,
1128                     arg, cookiep);
1129                 debugf("irq %u setup filter error %d on %s\n", irq, error,
1130                     name);
1131         } else
1132 #endif
1133                 {
1134                 error = isrc_add_handler(isrc, name, filt, hand, arg, flags,
1135                     cookiep);
1136                 debugf("irq %u add handler error %d on %s\n", irq, error, name);
1137         }
1138         if (error != 0)
1139                 return (error);
1140
1141         mtx_lock(&isrc_table_lock);
1142         error = PIC_SETUP_INTR(isrc->isrc_dev, isrc, res, data);
1143         if (error == 0) {
1144                 isrc->isrc_handlers++;
1145                 if (isrc->isrc_handlers == 1)
1146                         PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
1147         }
1148         mtx_unlock(&isrc_table_lock);
1149         if (error != 0)
1150                 intr_event_remove_handler(*cookiep);
1151         return (error);
1152 }
1153
1154 int
1155 intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
1156 {
1157         int error;
1158         struct intr_map_data *data;
1159         struct intr_irqsrc *isrc;
1160
1161         KASSERT(rman_get_start(res) == rman_get_end(res),
1162             ("%s: more interrupts in resource", __func__));
1163
1164         data = rman_get_virtual(res);
1165         if (data == NULL)
1166                 isrc = intr_ddata_lookup(rman_get_start(res), &data);
1167         else
1168                 isrc = isrc_lookup(rman_get_start(res));
1169         if (isrc == NULL || isrc->isrc_handlers == 0)
1170                 return (EINVAL);
1171
1172 #ifdef INTR_SOLO
1173         if (isrc->isrc_filter != NULL) {
1174                 if (isrc != cookie)
1175                         return (EINVAL);
1176
1177                 mtx_lock(&isrc_table_lock);
1178                 isrc->isrc_filter = NULL;
1179                 isrc->isrc_arg = NULL;
1180                 isrc->isrc_handlers = 0;
1181                 PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
1182                 PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
1183                 isrc_update_name(isrc, NULL);
1184                 mtx_unlock(&isrc_table_lock);
1185                 return (0);
1186         }
1187 #endif
1188         if (isrc != intr_handler_source(cookie))
1189                 return (EINVAL);
1190
1191         error = intr_event_remove_handler(cookie);
1192         if (error == 0) {
1193                 mtx_lock(&isrc_table_lock);
1194                 isrc->isrc_handlers--;
1195                 if (isrc->isrc_handlers == 0)
1196                         PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
1197                 PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
1198                 intrcnt_updatename(isrc);
1199                 mtx_unlock(&isrc_table_lock);
1200         }
1201         return (error);
1202 }
1203
1204 int
1205 intr_describe_irq(device_t dev, struct resource *res, void *cookie,
1206     const char *descr)
1207 {
1208         int error;
1209         struct intr_irqsrc *isrc;
1210
1211         KASSERT(rman_get_start(res) == rman_get_end(res),
1212             ("%s: more interrupts in resource", __func__));
1213
1214         isrc = intr_ddata_lookup(rman_get_start(res), NULL);
1215         if (isrc == NULL || isrc->isrc_handlers == 0)
1216                 return (EINVAL);
1217 #ifdef INTR_SOLO
1218         if (isrc->isrc_filter != NULL) {
1219                 if (isrc != cookie)
1220                         return (EINVAL);
1221
1222                 mtx_lock(&isrc_table_lock);
1223                 isrc_update_name(isrc, descr);
1224                 mtx_unlock(&isrc_table_lock);
1225                 return (0);
1226         }
1227 #endif
1228         error = intr_event_describe_handler(isrc->isrc_event, cookie, descr);
1229         if (error == 0) {
1230                 mtx_lock(&isrc_table_lock);
1231                 intrcnt_updatename(isrc);
1232                 mtx_unlock(&isrc_table_lock);
1233         }
1234         return (error);
1235 }
1236
1237 #ifdef SMP
1238 int
1239 intr_bind_irq(device_t dev, struct resource *res, int cpu)
1240 {
1241         struct intr_irqsrc *isrc;
1242
1243         KASSERT(rman_get_start(res) == rman_get_end(res),
1244             ("%s: more interrupts in resource", __func__));
1245
1246         isrc = intr_ddata_lookup(rman_get_start(res), NULL);
1247         if (isrc == NULL || isrc->isrc_handlers == 0)
1248                 return (EINVAL);
1249 #ifdef INTR_SOLO
1250         if (isrc->isrc_filter != NULL)
1251                 return (intr_isrc_assign_cpu(isrc, cpu));
1252 #endif
1253         return (intr_event_bind(isrc->isrc_event, cpu));
1254 }
1255
1256 /*
1257  * Return the CPU that the next interrupt source should use.
1258  * For now just returns the next CPU according to round-robin.
1259  */
1260 u_int
1261 intr_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask)
1262 {
1263
1264         if (!irq_assign_cpu || mp_ncpus == 1)
1265                 return (PCPU_GET(cpuid));
1266
1267         do {
1268                 last_cpu++;
1269                 if (last_cpu > mp_maxid)
1270                         last_cpu = 0;
1271         } while (!CPU_ISSET(last_cpu, cpumask));
1272         return (last_cpu);
1273 }
1274
1275 /*
1276  *  Distribute all the interrupt sources among the available
1277  *  CPUs once the AP's have been launched.
1278  */
1279 static void
1280 intr_irq_shuffle(void *arg __unused)
1281 {
1282         struct intr_irqsrc *isrc;
1283         u_int i;
1284
1285         if (mp_ncpus == 1)
1286                 return;
1287
1288         mtx_lock(&isrc_table_lock);
1289         irq_assign_cpu = TRUE;
1290         for (i = 0; i < NIRQ; i++) {
1291                 isrc = irq_sources[i];
1292                 if (isrc == NULL || isrc->isrc_handlers == 0 ||
1293                     isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI))
1294                         continue;
1295
1296                 if (isrc->isrc_event != NULL &&
1297                     isrc->isrc_flags & INTR_ISRCF_BOUND &&
1298                     isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1)
1299                         panic("%s: CPU inconsistency", __func__);
1300
1301                 if ((isrc->isrc_flags & INTR_ISRCF_BOUND) == 0)
1302                         CPU_ZERO(&isrc->isrc_cpu); /* start again */
1303
1304                 /*
1305                  * We are in wicked position here if the following call fails
1306                  * for bound ISRC. The best thing we can do is to clear
1307                  * isrc_cpu so inconsistency with ie_cpu will be detectable.
1308                  */
1309                 if (PIC_BIND_INTR(isrc->isrc_dev, isrc) != 0)
1310                         CPU_ZERO(&isrc->isrc_cpu);
1311         }
1312         mtx_unlock(&isrc_table_lock);
1313 }
1314 SYSINIT(intr_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, intr_irq_shuffle, NULL);
1315
1316 #else
1317 u_int
1318 intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
1319 {
1320
1321         return (PCPU_GET(cpuid));
1322 }
1323 #endif
1324
1325 /*
1326  *  Register a MSI/MSI-X interrupt controller
1327  */
1328 int
1329 intr_msi_register(device_t dev, intptr_t xref)
1330 {
1331         struct intr_pic *pic;
1332
1333         if (dev == NULL)
1334                 return (EINVAL);
1335         pic = pic_create(dev, xref);
1336         if (pic == NULL)
1337                 return (ENOMEM);
1338
1339         pic->pic_flags |= FLAG_MSI;
1340
1341         debugf("PIC %p registered for %s <dev %p, xref %jx>\n", pic,
1342             device_get_nameunit(dev), dev, (uintmax_t)xref);
1343         return (0);
1344 }
1345
1346 int
1347 intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count,
1348     int maxcount, int *irqs)
1349 {
1350         struct intr_irqsrc **isrc;
1351         struct intr_pic *pic;
1352         device_t pdev;
1353         int err, i;
1354
1355         pic = pic_lookup(NULL, xref);
1356         if (pic == NULL)
1357                 return (ESRCH);
1358
1359         KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1360             ("%s: Found a non-MSI controller: %s", __func__,
1361              device_get_name(pic->pic_dev)));
1362
1363         isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1364         err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc);
1365         if (err == 0) {
1366                 for (i = 0; i < count; i++) {
1367                         irqs[i] = isrc[i]->isrc_irq;
1368                 }
1369         }
1370
1371         free(isrc, M_INTRNG);
1372
1373         return (err);
1374 }
1375
1376 int
1377 intr_release_msi(device_t pci, device_t child, intptr_t xref, int count,
1378     int *irqs)
1379 {
1380         struct intr_irqsrc **isrc;
1381         struct intr_pic *pic;
1382         int i, err;
1383
1384         pic = pic_lookup(NULL, xref);
1385         if (pic == NULL)
1386                 return (ESRCH);
1387
1388         KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1389             ("%s: Found a non-MSI controller: %s", __func__,
1390              device_get_name(pic->pic_dev)));
1391
1392         isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1393
1394         for (i = 0; i < count; i++) {
1395                 isrc[i] = isrc_lookup(irqs[i]);
1396                 if (isrc == NULL) {
1397                         free(isrc, M_INTRNG);
1398                         return (EINVAL);
1399                 }
1400         }
1401
1402         err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc);
1403         free(isrc, M_INTRNG);
1404         return (err);
1405 }
1406
1407 int
1408 intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq)
1409 {
1410         struct intr_irqsrc *isrc;
1411         struct intr_pic *pic;
1412         device_t pdev;
1413         int err;
1414
1415         pic = pic_lookup(NULL, xref);
1416         if (pic == NULL)
1417                 return (ESRCH);
1418
1419         KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1420             ("%s: Found a non-MSI controller: %s", __func__,
1421              device_get_name(pic->pic_dev)));
1422
1423         err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc);
1424         if (err != 0)
1425                 return (err);
1426
1427         *irq = isrc->isrc_irq;
1428         return (0);
1429 }
1430
1431 int
1432 intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq)
1433 {
1434         struct intr_irqsrc *isrc;
1435         struct intr_pic *pic;
1436         int err;
1437
1438         pic = pic_lookup(NULL, xref);
1439         if (pic == NULL)
1440                 return (ESRCH);
1441
1442         KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1443             ("%s: Found a non-MSI controller: %s", __func__,
1444              device_get_name(pic->pic_dev)));
1445
1446         isrc = isrc_lookup(irq);
1447         if (isrc == NULL)
1448                 return (EINVAL);
1449
1450         err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc);
1451         return (err);
1452 }
1453
1454 int
1455 intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq,
1456     uint64_t *addr, uint32_t *data)
1457 {
1458         struct intr_irqsrc *isrc;
1459         struct intr_pic *pic;
1460         int err;
1461
1462         pic = pic_lookup(NULL, xref);
1463         if (pic == NULL)
1464                 return (ESRCH);
1465
1466         KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1467             ("%s: Found a non-MSI controller: %s", __func__,
1468              device_get_name(pic->pic_dev)));
1469
1470         isrc = isrc_lookup(irq);
1471         if (isrc == NULL)
1472                 return (EINVAL);
1473
1474         err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data);
1475         return (err);
1476 }
1477
1478
1479 void dosoftints(void);
1480 void
1481 dosoftints(void)
1482 {
1483 }
1484
1485 #ifdef SMP
1486 /*
1487  *  Init interrupt controller on another CPU.
1488  */
1489 void
1490 intr_pic_init_secondary(void)
1491 {
1492
1493         /*
1494          * QQQ: Only root PIC is aware of other CPUs ???
1495          */
1496         KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
1497
1498         //mtx_lock(&isrc_table_lock);
1499         PIC_INIT_SECONDARY(intr_irq_root_dev);
1500         //mtx_unlock(&isrc_table_lock);
1501 }
1502 #endif
1503
1504 #ifdef DDB
1505 DB_SHOW_COMMAND(irqs, db_show_irqs)
1506 {
1507         u_int i, irqsum;
1508         u_long num;
1509         struct intr_irqsrc *isrc;
1510
1511         for (irqsum = 0, i = 0; i < NIRQ; i++) {
1512                 isrc = irq_sources[i];
1513                 if (isrc == NULL)
1514                         continue;
1515
1516                 num = isrc->isrc_count != NULL ? isrc->isrc_count[0] : 0;
1517                 db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
1518                     isrc->isrc_name, isrc->isrc_cpu.__bits[0],
1519                     isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
1520                 irqsum += num;
1521         }
1522         db_printf("irq total %u\n", irqsum);
1523 }
1524 #endif