Changeset View
Standalone View
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 13 Lines | |||||
/* 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; | ||||
}; | }; | ||||
static struct mtx pic_list_lock; | struct intr_pic_list { | ||||
static SLIST_HEAD(, intr_pic) pic_list; | struct mtx lock; | ||||
SLIST_HEAD(, intr_pic) list; | |||||
}; | |||||
static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); | struct intr_pic_list pic_list; | ||||
struct intr_pic_list msi_list; | |||||
skra: I'm not sure that two (or more if it comes) lists is good option. What about to add a flag to… | |||||
Not Done Inline ActionsThey are lists of different things. Having two lists help ensure we can only get the correct device type when looking it up. andrew: They are lists of different things. Having two lists help ensure we can only get the correct… | |||||
Not Done Inline ActionsWell, I disagree with you. For me, they are all PIC. Will we start to have one list for gpio PICs, one list for i2c PICs, another list for pci PICs? Tell me, the device_t pointers which are registered into INTRNG are different for gic and gicv2m? The xrefs are different too? Maybe, no flag is needed at all to distinguish these devices. skra: Well, I disagree with you. For me, they are all PIC. Will we start to have one list for gpio… | |||||
Not Done Inline ActionsAll your examples implement the PIC interface. the MSI interface is different and may or may not implement any of the PIC functions. The gic implements the PIC interface, the gicv2m implements the MSI interface. andrew: All your examples implement the PIC interface. the MSI interface is different and may or may… | |||||
Not Done Inline ActionsHmm, I see your point. But when your argument is two different interfaces - PIC and MSI - then there should be two different structs - struct pic and struct msi. So I suggest to split that totally. Further, when isrc_lookup() will be made global, the msi stuff can be in separate file. BTW, I plan to change the way how the struct pic is kept in list, so there will be the possibility to register more xrefs for one device. I.e., there will be triplet - device_t, xref, struct pic * - in the list. When the triplet will be - device_t, xref, void* - it would be used for both struct pic and struct msi. skra: Hmm, I see your point. But when your argument is two different interfaces - PIC and MSI - then… | |||||
static struct intr_pic *pic_lookup(struct intr_pic_list *list, device_t dev, | |||||
intptr_t xref); | |||||
/* 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; | ||||
#define IRQ_INVALID nitems(irq_sources) | #define IRQ_INVALID nitems(irq_sources) | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 48 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.list); | ||||
mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); | mtx_init(&pic_list.lock, "intr pic list", NULL, MTX_DEF); | ||||
SLIST_INIT(&msi_list.list); | |||||
mtx_init(&msi_list.lock, "intr msi 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 402 Lines • ▼ Show 20 Lines | intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) | ||||
u_int cellsize; | u_int cellsize; | ||||
cellsize = ncells * sizeof(*cells); | cellsize = ncells * sizeof(*cells); | ||||
ddata = intr_ddata_alloc(cellsize); | ddata = intr_ddata_alloc(cellsize); | ||||
if (ddata == NULL) | if (ddata == NULL) | ||||
return (0xFFFFFFFF); /* no space left */ | return (0xFFFFFFFF); /* no space left */ | ||||
ddata->idd_xref = (intptr_t)node; | ddata->idd_xref = (intptr_t)node; | ||||
ddata->idd_data.type = INTR_MAP_DATA_FDT; | ddata->idd_data.type = INTR_MAP_DATA_FDT; | ||||
Not Done Inline ActionsIMO, this is not needed at all as there is no configuration data saved in the struct for this type. Global interrupt number is stored in ISRC. Note that all stuff around struct intr_dev_data is temporary and should not be used for new cases. It will be removed when OFW buses will be fixed for INTRNG. skra: IMO, this is not needed at all as there is no configuration data saved in the struct for this… | |||||
ddata->idd_data.fdt.ncells = ncells; | ddata->idd_data.fdt.ncells = ncells; | ||||
ddata->idd_data.fdt.cells = (pcell_t *)(ddata + 1); | ddata->idd_data.fdt.cells = (pcell_t *)(ddata + 1); | ||||
memcpy(ddata->idd_data.fdt.cells, cells, cellsize); | memcpy(ddata->idd_data.fdt.cells, cells, cellsize); | ||||
return (ddata->idd_irq); | return (ddata->idd_irq); | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef INTR_SOLO | #ifdef INTR_SOLO | ||||
▲ Show 20 Lines • Show All 181 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(struct intr_pic_list *list, device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_assert(&pic_list_lock, MA_OWNED); | mtx_assert(&list->lock, MA_OWNED); | ||||
if (dev == NULL && xref == 0) | if (dev == NULL && xref == 0) | ||||
return (NULL); | return (NULL); | ||||
/* 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, &list->list, pic_next) { | ||||
if (dev == NULL) { | if (dev == NULL) { | ||||
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 == 0 || pic->pic_xref == 0) { | ||||
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) | ||||
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(struct intr_pic_list *list, device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_lock(&pic_list_lock); | mtx_lock(&list->lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(list, dev, xref); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&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(struct intr_pic_list *list, device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_lock(&pic_list_lock); | mtx_lock(&list->lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(list, dev, xref); | ||||
if (pic != NULL) { | if (pic != NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&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); | ||||
pic->pic_xref = xref; | pic->pic_xref = xref; | ||||
pic->pic_dev = dev; | pic->pic_dev = dev; | ||||
SLIST_INSERT_HEAD(&pic_list, pic, pic_next); | SLIST_INSERT_HEAD(&list->list, pic, pic_next); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&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(struct intr_pic_list *list, device_t dev, intptr_t xref) | ||||
{ | { | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
mtx_lock(&pic_list_lock); | mtx_lock(&list->lock); | ||||
pic = pic_lookup_locked(dev, xref); | pic = pic_lookup_locked(list, dev, xref); | ||||
if (pic == NULL) { | if (pic == NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&list->lock); | ||||
return; | return; | ||||
} | } | ||||
SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next); | SLIST_REMOVE(&list->list, pic, intr_pic, pic_next); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&list->lock); | ||||
free(pic, M_INTRNG); | free(pic, M_INTRNG); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Register interrupt controller. | * Register interrupt controller. | ||||
*/ | */ | ||||
int | int | ||||
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 (EINVAL); | return (EINVAL); | ||||
pic = pic_create(dev, xref); | pic = pic_create(&pic_list, dev, xref); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
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); | ||||
} | } | ||||
Show All 19 Lines | |||||
* 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) | ||||
{ | { | ||||
if (pic_lookup(dev, xref) == NULL) { | if (pic_lookup(&pic_list, dev, xref) == NULL) { | ||||
device_printf(dev, "not registered\n"); | device_printf(dev, "not registered\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (filter == NULL) { | if (filter == NULL) { | ||||
device_printf(dev, "filter missing\n"); | device_printf(dev, "filter missing\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
Show All 22 Lines | |||||
{ | { | ||||
int error; | int error; | ||||
struct intr_irqsrc *isrc; | struct intr_irqsrc *isrc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
if (data == NULL) | if (data == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pic = pic_lookup(dev, xref); | pic = pic_lookup(&pic_list, dev, xref); | ||||
if (pic == NULL || pic->pic_dev == NULL) | if (pic == NULL || pic->pic_dev == NULL) | ||||
return (ESRCH); | return (ESRCH); | ||||
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); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 253 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(&msi_list, dev, xref); | |||||
if (pic == NULL) | |||||
return (ENOMEM); | |||||
printf("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(&msi_list, NULL, xref); | |||||
if (pic == NULL) | |||||
Not Done Inline ActionsHmm, pic_dev is never NULL here. It should be fixed in intr_map_irq() too. My bad. skra: Hmm, pic_dev is never NULL here. It should be fixed in intr_map_irq() too. My bad. | |||||
return (ESRCH); | |||||
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; | |||||
Not Done Inline Actionsirqs[i] = isrc[i]->isrc_irq; Related to note in intr_internal_map_irq(). skra: irqs[i] = isrc[i]->isrc_irq;
Related to note in intr_internal_map_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(&msi_list, NULL, xref); | |||||
if (pic == NULL) | |||||
Not Done Inline ActionsSame note as in intr_alloc_msi(). skra: Same note as in intr_alloc_msi(). | |||||
return (ESRCH); | |||||
isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); | |||||
for (i = 0; i < count; i++) { | |||||
isrc[i] = intr_ddata_lookup(irqs[i], NULL); | |||||
Not Done Inline Actionsisrc[i] = isrc_lookup(irq[i]); Related to note in intr_internal_map_irq(). skra: isrc[i] = isrc_lookup(irq[i]);
Related to note in intr_internal_map_irq().
| |||||
Not Done Inline ActionsHow do you propose handling the unknown number of interrupt ids we will need to handle with the GICv3? The MSI space starts at 8192 and is an implementation defined size. From my quick reading of the GICv3 spec it could be up to 2^24 interrupt IDs. andrew: How do you propose handling the unknown number of interrupt ids we will need to handle with the… | |||||
Not Done Inline ActionsSystem has some limitions always. A maximal number of processes, threads, opened files. So, NIRQS says how many interrupts can be serviced by system. This defines a size of global (system scope) interrupt number (name)space. If you have enough memory then it can be 2^24. Maybe, the question was about a size of local (gic scope) interrupt IDs (name)space. Then it's up to gic implementation how it wants to manage its interrupts IDs. If gic wants to make public some interrupt ID, it creates ISRC and registers it to INTRNG. No one dictates that gic must keep its ISRCs in a table. It could be a list, some kind of tree, whatever. However, when an interrupt comes, gic must be able to find corresponding ISRC quickly. It's the only limitation. Of course, gic also should save an interrupt ID in its extension of ISRC as INTRNG communicates with gic by ISRCs. However, I think that even gic could make some limitation of how many interrupts it can service. So ISRCs in a table is good for me. There could be holes in interrupts IDs which are used. Then only thing you must know is how to process an interrupt ID to get an index to ISRC table. Or are you saying that gic has no control over how interrupt IDs are allocated by consumers? Then the main problem is still how to find ISRC quickly when an interrupt comes. Ideally, it would be nice to be able to save some cookie to "hardware" so when an interrupt comes, associated ISRC could be find by this cookie. But now, I probably ran far away from your question. BTW, do you have any reason why you did not replace all appearance of intr_ddata_lookup() by isrc_lookup() in your diff? Of course, it works this way too as isrc_lookup() is called inside of intr_ddata_lookup(), but using intr_ddata_lookup() is wrong now. skra: System has some limitions always. A maximal number of processes, threads, opened files. So… | |||||
Not Done Inline ActionsOn the GICv3 interrupts are mapped as: 0 - 15: SGI 16 - 31: PPI 32 - 1019: SPI 1020 - 1023: Special interrupts 1024 - 8191: Reserved 8192 - n: LPI -- a message based interrupt, e.g. Used to handle MSI and MSI-X We don't control the mapping within the PPI or SPI space. The size of n is implementation defined, but if LPIs are implemented it will be a power of 2 between 2^14 and 2^24, but we do have some control over its allocation for MSI interrupts. I would prefer to not have a static array of pointers as I would expect having 128MB of BSS will cause the early boot to fail. The LPI space will be a little separate as there will be children each managing a contiguous blocks in the LPI space. andrew: On the GICv3 interrupts are mapped as:
0 - 15: SGI
16 - 31: PPI
32 - 1019: SPI
1020… | |||||
Not Done Inline ActionsInterrupts on which we don't control how they are allocated by consumers, the corresponding ISRCs must be allocated and registered in advance. Otherwise any request to setup such interrupt will end with EINVAL. In MSI/MSI-X case, where we assign some interrupt to a consumer, the corresponding ISRC may be registered in time of assignment. So even allocation of ISRC may be done at that time. But PIC must know about its ISRCs, so it must keep pointers to them somewhere. For example, for interrupts 0 - 1019, it will be table, while for interrupts 8192 - n, it will be a list, a tree, or a set of small dynamically allocated tables, whatever. BTW, the way how the ISRCs are stored and lookup for MSI/MSI-X interrupts may be general and in MSI specific file. ;) But remember what I said. When an interrupt comes, PIC must be able to find corresponding ISRC quickly. skra: Interrupts on which we don't control how they are allocated by consumers, the corresponding… | |||||
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(&msi_list, NULL, xref); | |||||
if (pic == NULL) | |||||
Not Done Inline ActionsSame note as in intr_alloc_msi(). skra: Same note as in intr_alloc_msi().
| |||||
return (ESRCH); | |||||
err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc); | |||||
if (err != 0) | |||||
return (err); | |||||
*irq = isrc->isrc_irq; | |||||
Not Done Inline Actions*irq = isrc->isrc_irq; Related to note in intr_internal_map_irq(). skra: *irq = isrc->isrc_irq;
Related to note in intr_internal_map_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(&msi_list, NULL, xref); | |||||
if (pic == NULL) | |||||
Not Done Inline ActionsSame note as in intr_alloc_msi(). skra: Same note as in intr_alloc_msi().
| |||||
return (ESRCH); | |||||
isrc = intr_ddata_lookup(irq, NULL); | |||||
Not Done Inline Actionsisrc = isrc_lookup(irq); Related to note in intr_internal_map_irq(). skra: isrc = isrc_lookup(irq);
Related to note in intr_internal_map_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(&msi_list, NULL, xref); | |||||
if (pic == NULL) | |||||
Not Done Inline ActionsSame note as in intr_alloc_msi(). skra: Same note as in intr_alloc_msi().
| |||||
return (ESRCH); | |||||
isrc = intr_ddata_lookup(irq, NULL); | |||||
Not Done Inline Actionsisrc = isrc_lookup(irq); Related to note in intr_internal_map_irq(). skra: isrc = isrc_lookup(irq);
Related to note in intr_internal_map_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 |
I'm not sure that two (or more if it comes) lists is good option. What about to add a flag to struct intr_pic and to related functions? How many PICs will be in a system? If 10 or 20, one list should be enough for them.