40#include "opt_hwpmc_hooks.h"
45#include <sys/kernel.h>
48#include <sys/syslog.h>
49#include <sys/malloc.h>
53#include <sys/interrupt.h>
54#include <sys/taskqueue.h>
57#include <sys/cpuset.h>
61#include <sys/sysctl.h>
62#include <sys/vmmeter.h>
64#include <sys/pmckern.h>
67#include <machine/atomic.h>
68#include <machine/intr.h>
69#include <machine/cpu.h>
70#include <machine/smp.h>
71#include <machine/stdarg.h>
78#include <dev/iommu/iommu_msi.h>
84#define INTRNAME_LEN (2*MAXCOMLEN + 1)
87#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
88 printf(fmt,##args); } while (0)
90#define debugf(fmt, args...)
108 intr_child_irq_filter_t *pc_filter;
120#define FLAG_PIC (1 << 0)
121#define FLAG_MSI (1 << 1)
122#define FLAG_TYPE_MASK (FLAG_PIC | FLAG_MSI)
124 struct mtx pic_child_lock;
134static struct mtx isrc_table_lock;
135static struct intr_irqsrc **irq_sources;
139#ifdef EARLY_AP_STARTUP
140static bool irq_assign_cpu =
true;
142static bool irq_assign_cpu =
false;
146u_int intr_nirq = NIRQ;
147SYSCTL_UINT(_machdep, OID_AUTO, nirq, CTLFLAG_RDTUN, &intr_nirq, 0,
155static u_int intrcnt_index;
161 struct intr_map_data **
data);
167intr_irq_init(
void *
dummy __unused)
171 SLIST_INIT(&pic_list);
174 mtx_init(&isrc_table_lock,
"intr isrc table", NULL, MTX_DEF);
180 intrcnt_count = intr_nirq * 2;
182 intrcnt_count += INTR_IPI_COUNT * MAXCPU;
185 intrcnt =
mallocarray(intrcnt_count,
sizeof(u_long), M_INTRNG,
189 sintrcnt = intrcnt_count *
sizeof(u_long);
191 irq_sources =
mallocarray(intr_nirq,
sizeof(
struct intr_irqsrc*),
192 M_INTRNG, M_WAITOK | M_ZERO);
194SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL);
212 mtx_assert(&isrc_table_lock, MA_OWNED);
223 if (
isrc->isrc_flags & INTR_ISRCF_PPI)
224 atomic_add_long(&
isrc->isrc_count[0], 1);
226 isrc->isrc_count[0]++;
236 isrc->isrc_count[1]++;
247 mtx_assert(&isrc_table_lock, MA_OWNED);
275 index = atomic_fetchadd_int(&intrcnt_index, 2);
276 isrc->isrc_index = index;
277 isrc->isrc_count = &intrcnt[index];
288 panic(
"%s: not implemented", __func__);
296intr_ipi_setup_counters(
const char *
name)
301 index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
302 for (i = 0; i < MAXCPU; i++) {
306 return (&intrcnt[index]);
317 struct trapframe * oldframe;
325 oldframe = td->td_intr_frame;
326 td->td_intr_frame = tf;
328 td->td_intr_frame = oldframe;
331 if (
pmc_hook && TRAPF_USERMODE(tf) &&
332 (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
333 pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
344 mtx_lock_spin(&
parent->pic_child_lock);
345 SLIST_FOREACH(
child, &
parent->pic_children, pc_next) {
346 if (
child->pc_start <= irq &&
352 mtx_unlock_spin(&
parent->pic_child_lock);
355 return (
child->pc_filter(
child->pc_filter_arg, irq));
357 return (FILTER_STRAY);
369 KASSERT(
isrc != NULL, (
"%s: no source", __func__));
374 if (
isrc->isrc_filter != NULL) {
376 error =
isrc->isrc_filter(
isrc->isrc_arg, tf);
377 PIC_POST_FILTER(
isrc->isrc_dev,
isrc);
378 if (error == FILTER_HANDLED)
382 if (
isrc->isrc_event != NULL) {
406 mtx_assert(&isrc_table_lock, MA_OWNED);
408 if (irq_next_free >= intr_nirq)
411 for (irq = irq_next_free; irq < intr_nirq; irq++) {
412 if (irq_sources[irq] == NULL)
415 for (irq = 0; irq < irq_next_free; irq++) {
416 if (irq_sources[irq] == NULL)
420 irq_next_free = intr_nirq;
424 isrc->isrc_irq = irq;
425 irq_sources[irq] =
isrc;
427 irq_next_free = irq + 1;
428 if (irq_next_free >= intr_nirq)
440 mtx_assert(&isrc_table_lock, MA_OWNED);
442 if (
isrc->isrc_irq >= intr_nirq)
444 if (irq_sources[
isrc->isrc_irq] !=
isrc)
447 irq_sources[
isrc->isrc_irq] = NULL;
448 isrc->isrc_irq = INTR_IRQ_INVALID;
456 if (irq_next_free >= intr_nirq)
467 const char *fmt, ...)
472 bzero(
isrc,
sizeof(
struct intr_irqsrc));
473 isrc->isrc_dev = dev;
474 isrc->isrc_irq = INTR_IRQ_INVALID;
481 mtx_lock(&isrc_table_lock);
484 mtx_unlock(&isrc_table_lock);
492 if ((
isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
494 mtx_unlock(&isrc_table_lock);
506 mtx_lock(&isrc_table_lock);
507 if ((
isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
510 mtx_unlock(&isrc_table_lock);
525intr_isrc_init_on_cpu(
struct intr_irqsrc *
isrc, u_int cpu)
528 if (
isrc->isrc_handlers == 0)
530 if ((
isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI)) == 0)
532 if (
isrc->isrc_flags & INTR_ISRCF_BOUND)
533 return (CPU_ISSET(cpu, &
isrc->isrc_cpu));
535 CPU_SET(cpu, &
isrc->isrc_cpu);
545iscr_setup_filter(
struct intr_irqsrc *
isrc,
const char *
name,
546 intr_irq_filter_t *filter,
void *arg,
void **cookiep)
552 mtx_lock(&isrc_table_lock);
557 if (
isrc->isrc_filter != NULL ||
isrc->isrc_event != NULL) {
558 mtx_unlock(&isrc_table_lock);
561 isrc->isrc_filter = filter;
562 isrc->isrc_arg = arg;
564 mtx_unlock(&isrc_table_lock);
577 struct intr_irqsrc *
isrc = arg;
579 PIC_PRE_ITHREAD(
isrc->isrc_dev,
isrc);
588 struct intr_irqsrc *
isrc = arg;
590 PIC_POST_ITHREAD(
isrc->isrc_dev,
isrc);
599 struct intr_irqsrc *
isrc = arg;
601 PIC_POST_FILTER(
isrc->isrc_dev,
isrc);
611 struct intr_irqsrc *
isrc = arg;
614 mtx_lock(&isrc_table_lock);
616 CPU_ZERO(&
isrc->isrc_cpu);
617 isrc->isrc_flags &= ~INTR_ISRCF_BOUND;
619 CPU_SETOF(cpu, &
isrc->isrc_cpu);
620 isrc->isrc_flags |= INTR_ISRCF_BOUND;
629 if (irq_assign_cpu) {
630 error = PIC_BIND_INTR(
isrc->isrc_dev,
isrc);
632 CPU_ZERO(&
isrc->isrc_cpu);
633 mtx_unlock(&isrc_table_lock);
637 mtx_unlock(&isrc_table_lock);
650 struct intr_event *ie;
659 mtx_lock(&isrc_table_lock);
665 if (
isrc->isrc_filter != NULL ||
isrc->isrc_event != NULL) {
667 if (
isrc->isrc_event != NULL) {
669 mtx_unlock(&isrc_table_lock);
671 return (
isrc->isrc_event != NULL ? EBUSY : 0);
673 isrc->isrc_event = ie;
674 mtx_unlock(&isrc_table_lock);
683isrc_event_destroy(
struct intr_irqsrc *
isrc)
685 struct intr_event *ie;
687 mtx_lock(&isrc_table_lock);
688 ie =
isrc->isrc_event;
689 isrc->isrc_event = NULL;
690 mtx_unlock(&isrc_table_lock);
701 driver_filter_t filter, driver_intr_t handler,
void *arg,
702 enum intr_type
flags,
void **cookiep)
706 if (
isrc->isrc_event == NULL) {
715 mtx_lock(&isrc_table_lock);
717 mtx_unlock(&isrc_table_lock);
733 if (dev == NULL && xref == 0)
737 SLIST_FOREACH(
pic, &pic_list, pic_next) {
743 if (xref ==
pic->pic_xref)
745 }
else if (xref == 0 ||
pic->pic_xref == 0) {
746 if (dev ==
pic->pic_dev)
748 }
else if (xref ==
pic->pic_xref && dev ==
pic->pic_dev)
782 pic =
malloc(
sizeof(*
pic), M_INTRNG, M_NOWAIT | M_ZERO);
787 pic->pic_xref = xref;
790 mtx_init(&
pic->pic_child_lock,
"pic child lock", NULL, MTX_SPIN);
791 SLIST_INSERT_HEAD(&pic_list,
pic, pic_next);
801pic_destroy(device_t dev, intptr_t xref,
int flags)
831 debugf(
"PIC %p registered for %s <dev %p, xref %jx>\n",
pic,
843 panic(
"%s: not implemented", __func__);
860 void *arg, u_int ipicount)
871 (
"%s: Found a non-PIC controller: %s", __func__,
874 if (filter == NULL) {
903 intr_child_irq_filter_t *filter,
void *arg, uintptr_t
start,
914 if (parent_pic == NULL)
917 newchild =
malloc(
sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO);
918 newchild->pc_pic =
pic;
919 newchild->pc_filter = filter;
920 newchild->pc_filter_arg = arg;
921 newchild->pc_start =
start;
922 newchild->pc_length = length;
924 mtx_lock_spin(&parent_pic->pic_child_lock);
926 SLIST_FOREACH(
child, &parent_pic->pic_children, pc_next) {
927 KASSERT(
child->pc_pic !=
pic, (
"%s: Adding a child PIC twice",
931 SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next);
932 mtx_unlock_spin(&parent_pic->pic_child_lock);
939 struct intr_irqsrc **
isrc)
942 struct intr_map_data_msi *
msi;
952 switch (
data->type) {
953 case INTR_MAP_DATA_MSI:
955 (
"%s: Found a non-MSI controller: %s", __func__,
957 msi = (
struct intr_map_data_msi *)
data;
963 (
"%s: Found a non-PIC controller: %s", __func__,
973 struct intr_irqsrc *
isrc;
979 panic(
"Attempt to get isrc for non-active resource id: %u\n",
981 return ((
isrc->isrc_flags & INTR_ISRCF_PPI) != 0);
989 struct intr_map_data *
data;
990 struct intr_irqsrc *
isrc;
995 (
"%s: more interrupts in resource", __func__));
999 panic(
"Attempt to double activation of resource id: %u\n",
1017 struct intr_map_data *
data;
1018 struct intr_irqsrc *
isrc;
1023 (
"%s: more interrupts in resource", __func__));
1028 panic(
"Attempt to deactivate non-active resource id: %u\n",
1041 driver_intr_t hand,
void *arg,
int flags,
void **cookiep)
1044 struct intr_map_data *
data;
1045 struct intr_irqsrc *
isrc;
1050 (
"%s: more interrupts in resource", __func__));
1073 if (
flags & INTR_SOLO && hand != NULL) {
1074 debugf(
"irq %u cannot solo on %s\n", irq,
name);
1078 if (
flags & INTR_SOLO) {
1079 error = iscr_setup_filter(
isrc,
name, (intr_irq_filter_t *)filt,
1081 debugf(
"irq %u setup filter error %d on %s\n",
isrc->isrc_irq, error,
1088 debugf(
"irq %u add handler error %d on %s\n",
isrc->isrc_irq, error,
name);
1093 mtx_lock(&isrc_table_lock);
1096 isrc->isrc_handlers++;
1097 if (
isrc->isrc_handlers == 1)
1098 PIC_ENABLE_INTR(
isrc->isrc_dev,
isrc);
1100 mtx_unlock(&isrc_table_lock);
1110 struct intr_map_data *
data;
1111 struct intr_irqsrc *
isrc;
1115 (
"%s: more interrupts in resource", __func__));
1119 if (
isrc == NULL ||
isrc->isrc_handlers == 0)
1125 if (
isrc->isrc_filter != NULL) {
1129 mtx_lock(&isrc_table_lock);
1130 isrc->isrc_filter = NULL;
1131 isrc->isrc_arg = NULL;
1132 isrc->isrc_handlers = 0;
1133 PIC_DISABLE_INTR(
isrc->isrc_dev,
isrc);
1136 mtx_unlock(&isrc_table_lock);
1145 mtx_lock(&isrc_table_lock);
1146 isrc->isrc_handlers--;
1147 if (
isrc->isrc_handlers == 0)
1148 PIC_DISABLE_INTR(
isrc->isrc_dev,
isrc);
1151 mtx_unlock(&isrc_table_lock);
1161 struct intr_irqsrc *
isrc;
1165 (
"%s: more interrupts in resource", __func__));
1169 if (
isrc == NULL ||
isrc->isrc_handlers == 0)
1172 if (
isrc->isrc_filter != NULL) {
1176 mtx_lock(&isrc_table_lock);
1178 mtx_unlock(&isrc_table_lock);
1184 mtx_lock(&isrc_table_lock);
1186 mtx_unlock(&isrc_table_lock);
1193intr_bind_irq(device_t dev,
struct resource *
res,
int cpu)
1195 struct intr_irqsrc *
isrc;
1199 (
"%s: more interrupts in resource", __func__));
1203 if (
isrc == NULL ||
isrc->isrc_handlers == 0)
1206 if (
isrc->isrc_filter != NULL)
1221 KASSERT(!CPU_EMPTY(cpumask), (
"%s: Empty CPU mask", __func__));
1222 if (!irq_assign_cpu ||
mp_ncpus == 1) {
1223 cpu = PCPU_GET(cpuid);
1225 if (CPU_ISSET(cpu, cpumask))
1228 return (CPU_FFS(cpumask) - 1);
1235 }
while (!CPU_ISSET(last_cpu, cpumask));
1239#ifndef EARLY_AP_STARTUP
1245intr_irq_shuffle(
void *arg __unused)
1247 struct intr_irqsrc *
isrc;
1253 mtx_lock(&isrc_table_lock);
1254 irq_assign_cpu =
true;
1255 for (i = 0; i < intr_nirq; i++) {
1256 isrc = irq_sources[i];
1257 if (
isrc == NULL ||
isrc->isrc_handlers == 0 ||
1258 isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI))
1261 if (
isrc->isrc_event != NULL &&
1262 isrc->isrc_flags & INTR_ISRCF_BOUND &&
1263 isrc->isrc_event->ie_cpu != CPU_FFS(&
isrc->isrc_cpu) - 1)
1264 panic(
"%s: CPU inconsistency", __func__);
1266 if ((
isrc->isrc_flags & INTR_ISRCF_BOUND) == 0)
1267 CPU_ZERO(&
isrc->isrc_cpu);
1274 if (PIC_BIND_INTR(
isrc->isrc_dev,
isrc) != 0)
1275 CPU_ZERO(&
isrc->isrc_cpu);
1277 mtx_unlock(&isrc_table_lock);
1279SYSINIT(intr_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, intr_irq_shuffle, NULL);
1287 return (PCPU_GET(cpuid));
1295struct intr_map_data *
1298 struct intr_map_data *
data;
1326 debugf(
"PIC %p registered for %s <dev %p, xref %jx>\n",
pic,
1335 struct iommu_domain *
domain;
1336 struct intr_irqsrc **
isrc;
1339 struct intr_map_data_msi *
msi;
1347 (
"%s: Found a non-MSI controller: %s", __func__,
1365 for (i = 0; i <
count; i++) {
1368 INTR_MAP_DATA_MSI,
sizeof(*
msi), M_WAITOK | M_ZERO);
1372 (
struct intr_map_data *)
msi);
1383 struct intr_irqsrc **
isrc;
1385 struct intr_map_data_msi *
msi;
1393 (
"%s: Found a non-MSI controller: %s", __func__,
1398 for (i = 0; i <
count; i++) {
1399 msi = (
struct intr_map_data_msi *)
1401 KASSERT(
msi->hdr.type == INTR_MAP_DATA_MSI,
1402 (
"%s: irq %d map data is not MSI", __func__,
1407 MSI_IOMMU_DEINIT(
pic->pic_dev,
child);
1411 for (i = 0; i <
count; i++) {
1412 if (
isrc[i] != NULL)
1423 struct iommu_domain *
domain;
1424 struct intr_irqsrc *
isrc;
1427 struct intr_map_data_msi *
msi;
1435 (
"%s: Found a non-MSI controller: %s", __func__,
1446 err = MSI_ALLOC_MSIX(
pic->pic_dev,
child, &pdev, &
isrc);
1452 INTR_MAP_DATA_MSI,
sizeof(*
msi), M_WAITOK | M_ZERO);
1461 struct intr_irqsrc *
isrc;
1463 struct intr_map_data_msi *
msi;
1471 (
"%s: Found a non-MSI controller: %s", __func__,
1474 msi = (
struct intr_map_data_msi *)
1476 KASSERT(
msi->hdr.type == INTR_MAP_DATA_MSI,
1477 (
"%s: irq %d map data is not MSI", __func__,
1485 MSI_IOMMU_DEINIT(
pic->pic_dev,
child);
1497 struct intr_irqsrc *
isrc;
1506 (
"%s: Found a non-MSI controller: %s", __func__,
1516 if (
isrc->isrc_iommu != NULL)
1517 iommu_translate_msi(
isrc->isrc_iommu,
addr);
1534intr_pic_init_secondary(
void)
1549DB_SHOW_COMMAND(irqs, db_show_irqs)
1553 struct intr_irqsrc *
isrc;
1555 for (irqsum = 0, i = 0; i < intr_nirq; i++) {
1556 isrc = irq_sources[i];
1560 num =
isrc->isrc_count != NULL ?
isrc->isrc_count[0] : 0;
1561 db_printf(
"irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
1562 isrc->isrc_name,
isrc->isrc_cpu.__bits[0],
1563 isrc->isrc_flags & INTR_ISRCF_BOUND ?
" (bound)" :
"", num);
1566 db_printf(
"irq total %u\n", irqsum);
1592static struct intr_irqsrc *
1595 struct intr_irqsrc *
isrc;
1619static struct intr_map_data *
1622 struct intr_map_data *
data;
1627 panic(
"Attempt to copy invalid resource id: %u\n", res_id);
1639 struct intr_map_data **
data)
1646 panic(
"Attempt to copy invalid resource id: %u\n", res_id);
1647 if (
irq_map[res_id]->map_data != NULL)
1654 *
data =
malloc(len, M_INTRNG, M_WAITOK | M_ZERO);
1657 panic(
"Attempt to copy invalid resource id: %u\n", res_id);
1659 if (len !=
irq_map[res_id]->map_data->len)
1660 panic(
"Resource id: %u has changed.\n", res_id);
1678 entry =
malloc(
sizeof(*entry), M_INTRNG, M_WAITOK | M_ZERO);
1697 panic(
"IRQ mapping table is full.");
1710 panic(
"Attempt to unmap invalid resource id: %u\n", res_id);
1716 free(entry, M_INTRNG);
1727 struct intr_map_data *
data;
1737 mtx_init(&
irq_map_lock,
"intr map table", NULL, MTX_DEF);
1741 M_INTRNG, M_WAITOK | M_ZERO);
device_property_type_t type
SYSCTL_UINT(_kern_eventtimer, OID_AUTO, idletick, CTLFLAG_RWTUN, &idletick, 0, "Run periodic events when idle")
int intr_event_handle(struct intr_event *ie, struct trapframe *frame)
int intr_event_describe_handler(struct intr_event *ie, void *cookie, const char *descr)
int intr_event_add_handler(struct intr_event *ie, const char *name, driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri, enum intr_type flags, void **cookiep)
int intr_event_create(struct intr_event **event, void *source, int flags, int irq, void(*pre_ithread)(void *), void(*post_ithread)(void *), void(*post_filter)(void *), int(*assign_cpu)(void *, int), const char *fmt,...)
int intr_event_bind(struct intr_event *ie, int cpu)
int intr_event_destroy(struct intr_event *ie)
int intr_event_remove_handler(void *cookie)
void * intr_handler_source(void *cookie)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void * mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags)
void free(void *addr, struct malloc_type *mtp)
int __read_mostly(* pmc_hook)(struct thread *td, int function, void *arg)
void panic(const char *fmt,...)
struct iommu_domain ** domain
struct intr_irqsrc * isrc
struct intr_map_data * map_data
struct intr_irqsrc * isrc
int device_printf(device_t dev, const char *fmt,...)
Print the name of the device followed by a colon, a space and the result of calling vprintf() with th...
const char * device_get_name(device_t dev)
Return the name of the device's devclass or NULL if there is none.
const char * device_get_nameunit(device_t dev)
Return a string containing the device's devclass name followed by an ascii representation of the devi...
bool intr_is_per_cpu(struct resource *res)
static void intr_map_init(void *dummy __unused)
static int intr_resolve_irq(device_t dev, intptr_t xref, struct intr_map_data *data, struct intr_irqsrc **isrc)
int intr_isrc_deregister(struct intr_irqsrc *isrc)
u_int intr_map_clone_irq(u_int old_res_id)
void intr_free_intr_map_data(struct intr_map_data *data)
static int isrc_alloc_irq(struct intr_irqsrc *isrc)
int intr_activate_irq(device_t dev, struct resource *res)
static struct mtx pic_list_lock
void intr_irq_handler(struct trapframe *tf)
int intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq)
int intr_deactivate_irq(device_t dev, struct resource *res)
static struct intr_pic * pic_lookup(device_t dev, intptr_t xref, int flags)
static void intrcnt_setname(const char *name, int index)
static void isrc_update_name(struct intr_irqsrc *isrc, const char *name)
static int intr_isrc_assign_cpu(void *arg, int cpu)
u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
static void intr_map_copy_map_data(u_int res_id, device_t *map_dev, intptr_t *map_xref, struct intr_map_data **data)
static int isrc_add_handler(struct intr_irqsrc *isrc, const char *name, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
int intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq)
struct intr_map_data * intr_alloc_map_data(enum intr_map_data_type type, size_t len, int flags)
static void isrc_release_counters(struct intr_irqsrc *isrc)
static void isrc_increment_count(struct intr_irqsrc *isrc)
static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc)
static void intr_isrc_post_ithread(void *arg)
static void intrcnt_updatename(struct intr_irqsrc *isrc)
static struct intr_map_entry ** irq_map
static struct mtx irq_map_lock
int intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, int *irqs)
static struct intr_map_data * intr_map_get_map_data(u_int res_id)
u_int intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data)
int intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq, uint64_t *addr, uint32_t *data)
int intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags, const char *fmt,...)
int intr_describe_irq(device_t dev, struct resource *res, void *cookie, const char *descr)
int intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
static void intr_isrc_pre_ithread(void *arg)
static u_int irq_map_first_free_idx
static u_int irq_map_count
int intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
static void intr_isrc_post_filter(void *arg)
static int isrc_free_irq(struct intr_irqsrc *isrc)
static struct intr_pic * pic_create(device_t dev, intptr_t xref, int flags)
int intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, driver_intr_t hand, void *arg, int flags, void **cookiep)
void intr_unmap_irq(u_int res_id)
int intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq)
SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL)
int intr_pic_deregister(device_t dev, intptr_t xref)
device_t intr_irq_root_dev
int intr_msi_register(device_t dev, intptr_t xref)
static void * irq_root_arg
static u_int irq_root_ipicount
static struct intr_pic * pic_lookup_locked(device_t dev, intptr_t xref, int flags)
static struct intr_irqsrc * intr_map_get_isrc(u_int res_id)
static SLIST_HEAD(intr_pic)
#define debugf(fmt, args...)
static intr_irq_filter_t * irq_root_filter
int intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, int maxcount, int *irqs)
struct intr_pic * intr_pic_register(device_t dev, intptr_t xref)
MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling")
int intr_pic_add_handler(device_t parent, struct intr_pic *pic, intr_child_irq_filter_t *filter, void *arg, uintptr_t start, uintptr_t length)
static void isrc_increment_straycount(struct intr_irqsrc *isrc)
static void isrc_setup_counters(struct intr_irqsrc *isrc)
int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, void *arg, u_int ipicount)
static int isrc_event_create(struct intr_irqsrc *isrc)
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
int snprintf(char *str, size_t size, const char *format,...)
void rman_set_virtual(struct resource *r, void *v)
void * rman_get_virtual(struct resource *r)
rman_res_t rman_get_end(struct resource *r)
rman_res_t rman_get_start(struct resource *r)