Changeset View
Standalone View
sys/kern/subr_intr.c
Show First 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | struct intr_pic_child { | ||||
void *pc_filter_arg; | void *pc_filter_arg; | ||||
uintptr_t pc_start; | uintptr_t pc_start; | ||||
uintptr_t pc_length; | uintptr_t pc_length; | ||||
}; | }; | ||||
/* 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 */ | ||||
mmel: imho, It would be better to group this with XREF_NONE | |||||
device_t pic_dev; | device_t pic_dev; | ||||
#define FLAG_PIC (1 << 0) | #define FLAG_PIC (1 << 0) | ||||
#define FLAG_MSI (1 << 1) | #define FLAG_MSI (1 << 1) | ||||
#define FLAG_TYPE_MASK (FLAG_PIC | FLAG_MSI) | |||||
u_int pic_flags; | u_int pic_flags; | ||||
struct mtx pic_child_lock; | struct mtx pic_child_lock; | ||||
SLIST_HEAD(, intr_pic_child) pic_children; | SLIST_HEAD(, intr_pic_child) pic_children; | ||||
}; | }; | ||||
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, int flags); | ||||
/* Interrupt source definition. */ | /* Interrupt source definition. */ | ||||
static struct mtx isrc_table_lock; | static struct mtx isrc_table_lock; | ||||
static struct intr_irqsrc *irq_sources[NIRQ]; | static struct intr_irqsrc *irq_sources[NIRQ]; | ||||
u_int irq_next_free; | u_int irq_next_free; | ||||
#ifdef SMP | #ifdef SMP | ||||
static boolean_t irq_assign_cpu = FALSE; | static boolean_t irq_assign_cpu = FALSE; | ||||
▲ Show 20 Lines • Show All 556 Lines • ▼ Show 20 Lines | isrc_add_handler(struct intr_irqsrc *isrc, const char *name, | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Lookup interrupt controller locked. | * Lookup interrupt controller locked. | ||||
*/ | */ | ||||
static inline struct intr_pic * | static inline struct intr_pic * | ||||
pic_lookup_locked(device_t dev, intptr_t xref) | pic_lookup_locked(device_t dev, intptr_t xref, int flags) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_assert(&pic_list_lock, MA_OWNED); | mtx_assert(&pic_list_lock, MA_OWNED); | ||||
if (dev == NULL && xref == 0) | KASSERT(dev != NULL || xref != -1, | ||||
mmelUnsubmitted Not Done Inline ActionsI thing that KASSERT is not right at this place. pic_lookup can be probably called from intr_alloc_msi() with dev == NULL and xref == invalid, if MSI controller is not registered. Then intr_alloc_msi() fails and card can fallback to old LSI interrupt. mmel: I thing that KASSERT is not right at this place. pic_lookup can be probably called from… | |||||
andrewAuthorUnsubmitted Not Done Inline ActionsWe shouldn't be calling intr_alloc_msi with an invalid xref. The callers should be checking the msi parent is valid. andrew: We shouldn't be calling intr_alloc_msi with an invalid xref. The callers should be checking the… | |||||
return (NULL); | ("pic_lookup_locked: Either the device or the xref must be valid")); | ||||
Not Done Inline ActionsThat's not fully true.
mmel: That's not fully true.
- INTRNG *must* works also in case where you known only device, but not… | |||||
Not Done Inline ActionsHow does this KASSERT break the case where you know a dev but not xref? If the dev is NULL and the xref is not invalid the second case will pass. I don't see where we break the case where the bus only knows the dev. In these cases it generates an xref for its own use. I suspect we should create a second value for these to use to stop INTRNG from searching for an common xref, but with a NULL dev. For xref the callers should filter out calls to INTRNG when they don't have an MSI parent, it should be considered to be a bug if they fail to do this so a KASSERT is appropriate. andrew: How does this KASSERT break the case where you know a dev but not xref? If the dev is NULL and… | |||||
Not Done Inline ActionsKASSERT(xref != XREF_INVALID, ("%s: Invalid xref", func)); ??? mmel: KASSERT(xref != XREF_INVALID, ("%s: Invalid xref", __func__)); ??? | |||||
Not Done Inline ActionsAgain, I prefer original version (returning NULL for dev == NULL && xref != XREF_NONE ). mmel: Again, I prefer original version (returning NULL for dev == NULL && xref != XREF_NONE ).
It… | |||||
/* Note that pic->pic_dev is never NULL on registered PIC. */ | /* Note that pic->pic_dev is never NULL on registered PIC. */ | ||||
SLIST_FOREACH(pic, &pic_list, pic_next) { | SLIST_FOREACH(pic, &pic_list, pic_next) { | ||||
if ((pic->pic_flags & FLAG_TYPE_MASK) != | |||||
(flags & FLAG_TYPE_MASK)) | |||||
continue; | |||||
if (dev == NULL) { | if (dev == NULL) { | ||||
/* No dev, check the xref */ | |||||
if (xref == pic->pic_xref) | if (xref == pic->pic_xref) | ||||
return (pic); | return (pic); | ||||
} else if (xref == 0 || pic->pic_xref == 0) { | } else if (xref == -1) { | ||||
/* No xref, check the dev */ | |||||
mmelUnsubmitted Not Done Inline ActionsMatch logic is incorrectly changed here. You cannot expect that PIC itself have valid xref. For example, you may want to create PIC for PCI gpio card. mmel: Match logic is incorrectly changed here. You cannot expect that PIC itself have valid xref. For… | |||||
andrewAuthorUnsubmitted Not Done Inline ActionsSo we would be searching using a dev and xref with a valid xref that doesn't refer to the dev? That seems broken to begin with, and should be something we don't support. andrew: So we would be searching using a dev and xref with a valid xref that doesn't refer to the dev? | |||||
Not Done Inline ActionsNo, but this change returns valid result if someone calls pic_lookup() with valid dev a invalid xref, while pic itself have valid xref.
The real example is interrupt controller in tegra (not a fully implemented yet) - Next one is above mentioned PCI gpio card with interrupt support. mmel: No, but this change returns valid result if someone calls pic_lookup() with valid dev a invalid… | |||||
Not Done Inline ActionsThe MSI interrupt would be passed to the MSI struct intr_pic *, while the legacy and error interrupts would be passed to the PIC struct intr_pic *. For the PCI GPIO case we can use any xref not used by an existing bus. It may pay to create a macro with a safe value for devices to use when only the dev is applicable. andrew: The MSI interrupt would be passed to the MSI `struct intr_pic *`, while the legacy and error… | |||||
Not Done Inline ActionsXREF_NONE mmel: XREF_NONE | |||||
Not Done Inline ActionsI significantly disagree with this change. Why you want to limit INTRNG functionality (see above)? mmel: I significantly disagree with this change. Why you want to limit INTRNG functionality (see… | |||||
if (dev == pic->pic_dev) | if (dev == pic->pic_dev) | ||||
return (pic); | return (pic); | ||||
} else if (xref == pic->pic_xref && dev == pic->pic_dev) | } else if (xref == pic->pic_xref && dev == pic->pic_dev) { | ||||
/* Have both, check both */ | |||||
return (pic); | return (pic); | ||||
} | } | ||||
} | |||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Lookup interrupt controller. | * Lookup interrupt controller. | ||||
*/ | */ | ||||
static struct intr_pic * | static struct intr_pic * | ||||
pic_lookup(device_t dev, intptr_t xref) | pic_lookup(device_t dev, intptr_t xref, int flags) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_lock(&pic_list_lock); | mtx_lock(&pic_list_lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(dev, xref, flags); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (pic); | return (pic); | ||||
} | } | ||||
/* | /* | ||||
* Create interrupt controller. | * Create interrupt controller. | ||||
*/ | */ | ||||
static struct intr_pic * | static struct intr_pic * | ||||
pic_create(device_t dev, intptr_t xref) | pic_create(device_t dev, intptr_t xref, int flags) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | |||||
mtx_lock(&pic_list_lock); | mtx_lock(&pic_list_lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(dev, xref, flags & FLAG_TYPE_MASK); | ||||
if (pic != NULL) { | if (pic != NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (pic); | return (pic); | ||||
} | } | ||||
pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); | pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); | ||||
if (pic == NULL) { | if (pic == NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
pic->pic_xref = xref; | pic->pic_xref = xref; | ||||
pic->pic_dev = dev; | pic->pic_dev = dev; | ||||
pic->pic_flags = flags; | |||||
mtx_init(&pic->pic_child_lock, "pic child lock", NULL, MTX_SPIN); | mtx_init(&pic->pic_child_lock, "pic child lock", NULL, MTX_SPIN); | ||||
SLIST_INSERT_HEAD(&pic_list, pic, pic_next); | SLIST_INSERT_HEAD(&pic_list, pic, pic_next); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (pic); | return (pic); | ||||
} | } | ||||
#ifdef notyet | #ifdef notyet | ||||
/* | /* | ||||
* Destroy interrupt controller. | * Destroy interrupt controller. | ||||
*/ | */ | ||||
static void | static void | ||||
pic_destroy(device_t dev, intptr_t xref) | pic_destroy(device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | |||||
mtx_lock(&pic_list_lock); | mtx_lock(&pic_list_lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(dev, xref); | ||||
if (pic == NULL) { | if (pic == NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return; | return; | ||||
} | } | ||||
SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next); | SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
free(pic, M_INTRNG); | free(pic, M_INTRNG); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Register interrupt controller. | * Register interrupt controller. | ||||
*/ | */ | ||||
struct intr_pic * | struct intr_pic * | ||||
intr_pic_register(device_t dev, intptr_t xref) | intr_pic_register(device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
if (dev == NULL) | if (dev == NULL) | ||||
return (NULL); | return (NULL); | ||||
pic = pic_create(dev, xref); | pic = pic_create(dev, xref, FLAG_PIC); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (NULL); | return (NULL); | ||||
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 (pic); | return (pic); | ||||
} | } | ||||
/* | /* | ||||
* Unregister interrupt controller. | * Unregister interrupt controller. | ||||
*/ | */ | ||||
Show All 17 Lines | |||||
* 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; | struct intr_pic *pic; | ||||
pic = pic_lookup(dev, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
pic = pic_lookup(dev, xref, FLAG_PIC); | |||||
if (pic == NULL) { | 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, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_PIC, | ||||
("%s: Found a non-PIC controller: %s", __func__, | ("%s: Found a non-PIC controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | 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); | ||||
} | } | ||||
Show All 25 Lines | intr_pic_add_handler(device_t parent, struct intr_pic *pic, | ||||
uintptr_t length) | uintptr_t length) | ||||
{ | { | ||||
struct intr_pic *parent_pic; | struct intr_pic *parent_pic; | ||||
struct intr_pic_child *newchild; | struct intr_pic_child *newchild; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
struct intr_pic_child *child; | struct intr_pic_child *child; | ||||
#endif | #endif | ||||
parent_pic = pic_lookup(parent, 0); | parent_pic = pic_lookup(parent, -1, FLAG_PIC); | ||||
Not Done Inline ActionsTypo? XREF_NONE looks more appropriate. mmel: Typo? XREF_NONE looks more appropriate. | |||||
if (parent_pic == NULL) | if (parent_pic == NULL) | ||||
return (NULL); | return (NULL); | ||||
newchild = malloc(sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO); | newchild = malloc(sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO); | ||||
newchild->pc_pic = pic; | newchild->pc_pic = pic; | ||||
newchild->pc_filter = filter; | newchild->pc_filter = filter; | ||||
newchild->pc_filter_arg = arg; | newchild->pc_filter_arg = arg; | ||||
newchild->pc_start = start; | newchild->pc_start = start; | ||||
Show All 17 Lines | intr_resolve_irq(device_t dev, intptr_t xref, struct intr_map_data *data, | ||||
struct intr_irqsrc **isrc) | struct intr_irqsrc **isrc) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
struct intr_map_data_msi *msi; | struct intr_map_data_msi *msi; | ||||
if (data == NULL) | if (data == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pic = pic_lookup(dev, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
pic = pic_lookup(dev, xref, | |||||
(data->type == INTR_MAP_DATA_MSI) ? FLAG_MSI : FLAG_PIC); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
switch (data->type) { | switch (data->type) { | ||||
case INTR_MAP_DATA_MSI: | case INTR_MAP_DATA_MSI: | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
msi = (struct intr_map_data_msi *)data; | msi = (struct intr_map_data_msi *)data; | ||||
*isrc = msi->isrc; | *isrc = msi->isrc; | ||||
return (0); | return (0); | ||||
default: | default: | ||||
KASSERT((pic->pic_flags & FLAG_PIC) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_PIC, | ||||
("%s: Found a non-PIC controller: %s", __func__, | ("%s: Found a non-PIC controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
return (PIC_MAP_INTR(pic->pic_dev, data, isrc)); | return (PIC_MAP_INTR(pic->pic_dev, data, isrc)); | ||||
} | } | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 320 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
intr_msi_register(device_t dev, intptr_t xref) | intr_msi_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, FLAG_MSI); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
pic->pic_flags |= FLAG_MSI; | |||||
debugf("PIC %p registered for %s <dev %p, xref %jx>\n", pic, | debugf("PIC %p registered for %s <dev %p, xref %jx>\n", pic, | ||||
device_get_nameunit(dev), dev, (uintmax_t)xref); | device_get_nameunit(dev), dev, (uintmax_t)xref); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, | intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, | ||||
int maxcount, int *irqs) | int maxcount, int *irqs) | ||||
{ | { | ||||
struct intr_irqsrc **isrc; | struct intr_irqsrc **isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
device_t pdev; | device_t pdev; | ||||
struct intr_map_data_msi *msi; | struct intr_map_data_msi *msi; | ||||
int err, i; | int err, i; | ||||
pic = pic_lookup(NULL, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
mmelUnsubmitted Not Done Inline ActionsThis function can be called with 'INVALID' xref and it's expected that it return error. mmel: This function can be called with 'INVALID' xref and it's expected that it return error. | |||||
pic = pic_lookup(NULL, xref, FLAG_MSI); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | ||||
err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc); | err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc); | ||||
if (err != 0) { | if (err != 0) { | ||||
free(isrc, M_INTRNG); | free(isrc, M_INTRNG); | ||||
return (err); | return (err); | ||||
Show All 16 Lines | |||||
intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, | intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, | ||||
int *irqs) | int *irqs) | ||||
{ | { | ||||
struct intr_irqsrc **isrc; | struct intr_irqsrc **isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
struct intr_map_data_msi *msi; | struct intr_map_data_msi *msi; | ||||
int i, err; | int i, err; | ||||
pic = pic_lookup(NULL, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
pic = pic_lookup(NULL, xref, FLAG_MSI); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | ||||
for (i = 0; i < count; i++) { | for (i = 0; i < count; i++) { | ||||
msi = (struct intr_map_data_msi *) | msi = (struct intr_map_data_msi *) | ||||
intr_map_get_map_data(irqs[i]); | intr_map_get_map_data(irqs[i]); | ||||
Show All 18 Lines | |||||
intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq) | intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq) | ||||
{ | { | ||||
struct intr_irqsrc *isrc; | struct intr_irqsrc *isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
device_t pdev; | device_t pdev; | ||||
struct intr_map_data_msi *msi; | struct intr_map_data_msi *msi; | ||||
int err; | int err; | ||||
pic = pic_lookup(NULL, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
mmelUnsubmitted Not Done Inline ActionsDitto mmel: Ditto | |||||
pic = pic_lookup(NULL, xref, FLAG_MSI); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc); | err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
msi = (struct intr_map_data_msi *)intr_alloc_map_data( | msi = (struct intr_map_data_msi *)intr_alloc_map_data( | ||||
INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); | INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); | ||||
msi->isrc = isrc; | msi->isrc = isrc; | ||||
*irq = intr_map_irq(pic->pic_dev, xref, (struct intr_map_data *)msi); | *irq = intr_map_irq(pic->pic_dev, xref, (struct intr_map_data *)msi); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq) | intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq) | ||||
{ | { | ||||
struct intr_irqsrc *isrc; | struct intr_irqsrc *isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
struct intr_map_data_msi *msi; | struct intr_map_data_msi *msi; | ||||
int err; | int err; | ||||
pic = pic_lookup(NULL, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
pic = pic_lookup(NULL, xref, FLAG_MSI); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
msi = (struct intr_map_data_msi *) | msi = (struct intr_map_data_msi *) | ||||
intr_map_get_map_data(irq); | intr_map_get_map_data(irq); | ||||
KASSERT(msi->hdr.type == INTR_MAP_DATA_MSI, | KASSERT(msi->hdr.type == INTR_MAP_DATA_MSI, | ||||
("%s: irq %d map data is not MSI", __func__, | ("%s: irq %d map data is not MSI", __func__, | ||||
irq)); | irq)); | ||||
Show All 12 Lines | |||||
int | int | ||||
intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq, | intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq, | ||||
uint64_t *addr, uint32_t *data) | uint64_t *addr, uint32_t *data) | ||||
{ | { | ||||
struct intr_irqsrc *isrc; | struct intr_irqsrc *isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
int err; | int err; | ||||
pic = pic_lookup(NULL, xref); | KASSERT(xref != -1, ("%s: Invalid xref", __func__)); | ||||
pic = pic_lookup(NULL, xref, FLAG_MSI); | |||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
KASSERT((pic->pic_flags & FLAG_MSI) != 0, | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, | ||||
("%s: Found a non-MSI controller: %s", __func__, | ("%s: Found a non-MSI controller: %s", __func__, | ||||
device_get_name(pic->pic_dev))); | device_get_name(pic->pic_dev))); | ||||
isrc = intr_map_get_isrc(irq); | isrc = intr_map_get_isrc(irq); | ||||
if (isrc == NULL) | if (isrc == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data); | err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data); | ||||
▲ Show 20 Lines • Show All 226 Lines • Show Last 20 Lines |
imho, It would be better to group this with XREF_NONE