Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/subr_intr.c
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#endif | #endif | ||||
#ifdef DDB | #ifdef DDB | ||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
#endif | #endif | ||||
#include "pic_if.h" | #include "pic_if.h" | ||||
#include "msi_if.h" | |||||
#define INTRNAME_LEN (2*MAXCOMLEN + 1) | #define INTRNAME_LEN (2*MAXCOMLEN + 1) | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ | #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ | ||||
printf(fmt,##args); } while (0) | printf(fmt,##args); } while (0) | ||||
#else | #else | ||||
#define debugf(fmt, args...) | #define debugf(fmt, args...) | ||||
Show All 11 Lines | |||||
static void *irq_root_arg; | static void *irq_root_arg; | ||||
static u_int irq_root_ipicount; | static u_int irq_root_ipicount; | ||||
/* Interrupt controller definition. */ | /* Interrupt controller definition. */ | ||||
struct intr_pic { | struct intr_pic { | ||||
SLIST_ENTRY(intr_pic) pic_next; | SLIST_ENTRY(intr_pic) pic_next; | ||||
intptr_t pic_xref; /* hardware identification */ | intptr_t pic_xref; /* hardware identification */ | ||||
device_t pic_dev; | device_t pic_dev; | ||||
#define FLAG_PIC (1 << 0) | |||||
#define FLAG_MSI (1 << 1) | |||||
u_int pic_flags; | |||||
}; | }; | ||||
static struct mtx pic_list_lock; | static struct mtx pic_list_lock; | ||||
static SLIST_HEAD(, intr_pic) pic_list; | static SLIST_HEAD(, intr_pic) pic_list; | ||||
static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); | static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); | ||||
/* Interrupt source definition. */ | /* Interrupt source definition. */ | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
* Interrupt framework initialization routine. | * Interrupt framework initialization routine. | ||||
*/ | */ | ||||
static void | static void | ||||
intr_irq_init(void *dummy __unused) | intr_irq_init(void *dummy __unused) | ||||
{ | { | ||||
SLIST_INIT(&pic_list); | SLIST_INIT(&pic_list); | ||||
mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); | mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); | ||||
mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF); | mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF); | ||||
} | } | ||||
SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL); | SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL); | ||||
static void | static void | ||||
intrcnt_setname(const char *name, int index) | intrcnt_setname(const char *name, int index) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 733 Lines • ▼ Show 20 Lines | intr_pic_register(device_t dev, intptr_t xref) | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
if (dev == NULL) | if (dev == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pic = pic_create(dev, xref); | pic = pic_create(dev, xref); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
pic->pic_flags |= FLAG_PIC; | |||||
debugf("PIC %p registered for %s <dev %p, xref %x>\n", pic, | debugf("PIC %p registered for %s <dev %p, xref %x>\n", pic, | ||||
device_get_nameunit(dev), dev, xref); | device_get_nameunit(dev), dev, xref); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Unregister interrupt controller. | * Unregister interrupt controller. | ||||
*/ | */ | ||||
Show All 15 Lines | |||||
* "The root of the interrupt tree is determined when traversal | * "The root of the interrupt tree is determined when traversal | ||||
* of the interrupt tree reaches an interrupt controller node without | * of the interrupt tree reaches an interrupt controller node without | ||||
* an interrupts property and thus no explicit interrupt parent." | * an interrupts property and thus no explicit interrupt parent." | ||||
*/ | */ | ||||
int | int | ||||
intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, | intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, | ||||
void *arg, u_int ipicount) | void *arg, u_int ipicount) | ||||
{ | { | ||||
struct intr_pic *pic; | |||||
if (pic_lookup(dev, xref) == NULL) { | pic = pic_lookup(dev, xref); | ||||
if (pic == NULL) { | |||||
device_printf(dev, "not registered\n"); | device_printf(dev, "not registered\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
KASSERT((pic->pic_flags & FLAG_PIC) != 0, | |||||
("%s: Found a non-PIC controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
if (filter == NULL) { | if (filter == NULL) { | ||||
device_printf(dev, "filter missing\n"); | device_printf(dev, "filter missing\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* Only one interrupt controllers could be on the root for now. | * Only one interrupt controllers could be on the root for now. | ||||
* Note that we further suppose that there is not threaded interrupt | * Note that we further suppose that there is not threaded interrupt | ||||
Show All 23 Lines | intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, | ||||
if (data == NULL) | if (data == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pic = pic_lookup(dev, xref); | pic = pic_lookup(dev, xref); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_PIC) != 0, | |||||
("%s: Found a non-PIC controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
error = PIC_MAP_INTR(pic->pic_dev, data, &isrc); | error = PIC_MAP_INTR(pic->pic_dev, data, &isrc); | ||||
if (error == 0) | if (error == 0) | ||||
*irqp = isrc->isrc_irq; | *irqp = isrc->isrc_irq; | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
intr_alloc_irq(device_t dev, struct resource *res) | intr_alloc_irq(device_t dev, struct resource *res) | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
u_int | u_int | ||||
intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask) | intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask) | ||||
{ | { | ||||
return (PCPU_GET(cpuid)); | return (PCPU_GET(cpuid)); | ||||
} | } | ||||
#endif | #endif | ||||
/* | |||||
* Register a MSI/MSI-X interrupt controller | |||||
*/ | |||||
int | |||||
intr_msi_register(device_t dev, intptr_t xref) | |||||
{ | |||||
struct intr_pic *pic; | |||||
if (dev == NULL) | |||||
return (EINVAL); | |||||
pic = pic_create(dev, xref); | |||||
if (pic == NULL) | |||||
return (ENOMEM); | |||||
pic->pic_flags |= FLAG_MSI; | |||||
debugf("PIC %p registered for %s <dev %p, xref %jx>\n", pic, | |||||
device_get_nameunit(dev), dev, (uintmax_t)xref); | |||||
return (0); | |||||
} | |||||
int | |||||
intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, | |||||
int maxcount, int *irqs) | |||||
{ | |||||
struct intr_irqsrc **isrc; | |||||
struct intr_pic *pic; | |||||
device_t pdev; | |||||
int err, i; | |||||
pic = pic_lookup(NULL, xref); | |||||
if (pic == NULL) | |||||
return (ESRCH); | |||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | |||||
("%s: Found a non-MSI controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | |||||
err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc); | |||||
if (err == 0) { | |||||
for (i = 0; i < count; i++) { | |||||
irqs[i] = isrc[i]->isrc_irq; | |||||
} | |||||
} | |||||
free(isrc, M_INTRNG); | |||||
return (err); | |||||
} | |||||
int | |||||
intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, | |||||
int *irqs) | |||||
{ | |||||
struct intr_irqsrc **isrc; | |||||
struct intr_pic *pic; | |||||
int i, err; | |||||
pic = pic_lookup(NULL, xref); | |||||
if (pic == NULL) | |||||
return (ESRCH); | |||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | |||||
("%s: Found a non-MSI controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | |||||
for (i = 0; i < count; i++) { | |||||
isrc[i] = isrc_lookup(irqs[i]); | |||||
if (isrc == NULL) { | |||||
free(isrc, M_INTRNG); | |||||
return (EINVAL); | |||||
} | |||||
} | |||||
err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc); | |||||
free(isrc, M_INTRNG); | |||||
return (err); | |||||
} | |||||
int | |||||
intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq) | |||||
{ | |||||
struct intr_irqsrc *isrc; | |||||
struct intr_pic *pic; | |||||
device_t pdev; | |||||
int err; | |||||
pic = pic_lookup(NULL, xref); | |||||
if (pic == NULL) | |||||
return (ESRCH); | |||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | |||||
("%s: Found a non-MSI controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc); | |||||
if (err != 0) | |||||
return (err); | |||||
*irq = isrc->isrc_irq; | |||||
return (0); | |||||
} | |||||
int | |||||
intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq) | |||||
{ | |||||
struct intr_irqsrc *isrc; | |||||
struct intr_pic *pic; | |||||
int err; | |||||
pic = pic_lookup(NULL, xref); | |||||
if (pic == NULL) | |||||
return (ESRCH); | |||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | |||||
("%s: Found a non-MSI controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
isrc = isrc_lookup(irq); | |||||
if (isrc == NULL) | |||||
return (EINVAL); | |||||
err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc); | |||||
return (err); | |||||
} | |||||
int | |||||
intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq, | |||||
uint64_t *addr, uint32_t *data) | |||||
{ | |||||
struct intr_irqsrc *isrc; | |||||
struct intr_pic *pic; | |||||
int err; | |||||
pic = pic_lookup(NULL, xref); | |||||
if (pic == NULL) | |||||
return (ESRCH); | |||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | |||||
("%s: Found a non-MSI controller: %s", __func__, | |||||
device_get_name(pic->pic_dev))); | |||||
isrc = isrc_lookup(irq); | |||||
if (isrc == NULL) | |||||
return (EINVAL); | |||||
err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data); | |||||
return (err); | |||||
} | |||||
void dosoftints(void); | void dosoftints(void); | ||||
void | void | ||||
dosoftints(void) | dosoftints(void) | ||||
{ | { | ||||
} | } | ||||
#ifdef SMP | #ifdef SMP | ||||
Show All 39 Lines |