Index: head/sys/arm/arm/nexus.c =================================================================== --- head/sys/arm/arm/nexus.c +++ head/sys/arm/arm/nexus.c @@ -64,6 +64,7 @@ #ifdef FDT #include +#include #include "ofw_bus_if.h" #endif @@ -379,6 +380,11 @@ #endif rman_set_virtual(r, (void *)vaddr); rman_set_bushandle(r, vaddr); + return (0); + } else if (type == SYS_RES_IRQ) { +#ifdef INTRNG + intr_activate_irq(child, r); +#endif } return (0); } @@ -390,17 +396,23 @@ bus_size_t psize; bus_space_handle_t vaddr; - psize = (bus_size_t)rman_get_size(r); - vaddr = rman_get_bushandle(r); + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + psize = (bus_size_t)rman_get_size(r); + vaddr = rman_get_bushandle(r); - if (vaddr != 0) { + if (vaddr != 0) { #ifdef FDT - bus_space_unmap(fdtbus_bs_tag, vaddr, psize); + bus_space_unmap(fdtbus_bs_tag, vaddr, psize); #else - pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize); + pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize); +#endif + rman_set_virtual(r, NULL); + rman_set_bushandle(r, 0); + } + } else if (type == SYS_RES_IRQ) { +#ifdef INTRNG + intr_deactivate_irq(child, r); #endif - rman_set_virtual(r, NULL); - rman_set_bushandle(r, 0); } return (rman_deactivate_resource(r)); @@ -411,11 +423,22 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - -#ifdef INTRNG - return (INTR_IRQ_INVALID); -#else +#ifndef INTRNG return (intr_fdt_map_irq(iparent, intr, icells)); -#endif +#else + u_int irq; + struct intr_map_data_fdt *fdt_data; + size_t len; + + len = sizeof(*fdt_data) + icells * sizeof(pcell_t); + fdt_data = (struct intr_map_data_fdt *)intr_alloc_map_data( + INTR_MAP_DATA_FDT, len, M_WAITOK | M_ZERO); + fdt_data->iparent = iparent; + fdt_data->ncells = icells; + memcpy(fdt_data->cells, intr, icells * sizeof(pcell_t)); + irq = intr_map_irq(NULL, iparent, (struct intr_map_data *)fdt_data); + return (irq); +#endif /* INTRNG */ } -#endif +#endif /* FDT */ + Index: head/sys/arm/nvidia/tegra_lic.c =================================================================== --- head/sys/arm/nvidia/tegra_lic.c +++ head/sys/arm/nvidia/tegra_lic.c @@ -88,12 +88,12 @@ }; static int -tegra_lic_alloc_intr(device_t dev, struct intr_irqsrc *isrc, +tegra_lic_activate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct tegra_lic_sc *sc = device_get_softc(dev); - return (PIC_ALLOC_INTR(sc->parent, isrc, res, data)); + return (PIC_ACTIVATE_INTR(sc->parent, isrc, res, data)); } static void @@ -122,12 +122,12 @@ } static int -tegra_lic_release_intr(device_t dev, struct intr_irqsrc *isrc, +tegra_lic_deactivate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct tegra_lic_sc *sc = device_get_softc(dev); - return (PIC_RELEASE_INTR(sc->parent, isrc, res, data)); + return (PIC_DEACTIVATE_INTR(sc->parent, isrc, res, data)); } static int @@ -266,11 +266,11 @@ DEVMETHOD(device_detach, tegra_lic_detach), /* Interrupt controller interface */ - DEVMETHOD(pic_alloc_intr, tegra_lic_alloc_intr), + DEVMETHOD(pic_activate_intr, tegra_lic_activate_intr), DEVMETHOD(pic_disable_intr, tegra_lic_disable_intr), DEVMETHOD(pic_enable_intr, tegra_lic_enable_intr), DEVMETHOD(pic_map_intr, tegra_lic_map_intr), - DEVMETHOD(pic_release_intr, tegra_lic_release_intr), + DEVMETHOD(pic_deactivate_intr, tegra_lic_deactivate_intr), DEVMETHOD(pic_setup_intr, tegra_lic_setup_intr), DEVMETHOD(pic_teardown_intr, tegra_lic_teardown_intr), DEVMETHOD(pic_pre_ithread, tegra_lic_pre_ithread), Index: head/sys/arm/ti/omap4/omap4_wugen.c =================================================================== --- head/sys/arm/ti/omap4/omap4_wugen.c +++ head/sys/arm/ti/omap4/omap4_wugen.c @@ -57,12 +57,12 @@ }; static int -omap4_wugen_alloc_intr(device_t dev, struct intr_irqsrc *isrc, +omap4_wugen_activate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct omap4_wugen_sc *sc = device_get_softc(dev); - return (PIC_ALLOC_INTR(sc->sc_parent, isrc, res, data)); + return (PIC_ACTIVATE_INTR(sc->sc_parent, isrc, res, data)); } static void @@ -91,12 +91,12 @@ } static int -omap4_wugen_release_intr(device_t dev, struct intr_irqsrc *isrc, +omap4_wugen_deactivate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct omap4_wugen_sc *sc = device_get_softc(dev); - return (PIC_RELEASE_INTR(sc->sc_parent, isrc, res, data)); + return (PIC_DEACTIVATE_INTR(sc->sc_parent, isrc, res, data)); } static int @@ -227,11 +227,11 @@ DEVMETHOD(device_detach, omap4_wugen_detach), /* Interrupt controller interface */ - DEVMETHOD(pic_alloc_intr, omap4_wugen_alloc_intr), + DEVMETHOD(pic_activate_intr, omap4_wugen_activate_intr), DEVMETHOD(pic_disable_intr, omap4_wugen_disable_intr), DEVMETHOD(pic_enable_intr, omap4_wugen_enable_intr), DEVMETHOD(pic_map_intr, omap4_wugen_map_intr), - DEVMETHOD(pic_release_intr, omap4_wugen_release_intr), + DEVMETHOD(pic_deactivate_intr, omap4_wugen_deactivate_intr), DEVMETHOD(pic_setup_intr, omap4_wugen_setup_intr), DEVMETHOD(pic_teardown_intr, omap4_wugen_teardown_intr), DEVMETHOD(pic_pre_ithread, omap4_wugen_pre_ithread), Index: head/sys/arm64/arm64/nexus.c =================================================================== --- head/sys/arm64/arm64/nexus.c +++ head/sys/arm64/arm64/nexus.c @@ -65,6 +65,7 @@ #include #ifdef FDT +#include #include #include "ofw_bus_if.h" #endif @@ -345,6 +346,8 @@ rman_set_bustag(r, &memmap_bus); rman_set_virtual(r, (void *)vaddr); rman_set_bushandle(r, vaddr); + } else if (type == SYS_RES_IRQ) { + intr_activate_irq(child, r); } return (0); } @@ -378,13 +381,17 @@ bus_size_t psize; bus_space_handle_t vaddr; - psize = (bus_size_t)rman_get_size(r); - vaddr = rman_get_bushandle(r); + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + psize = (bus_size_t)rman_get_size(r); + vaddr = rman_get_bushandle(r); - if (vaddr != 0) { - bus_space_unmap(&memmap_bus, vaddr, psize); - rman_set_virtual(r, NULL); - rman_set_bushandle(r, 0); + if (vaddr != 0) { + bus_space_unmap(&memmap_bus, vaddr, psize); + rman_set_virtual(r, NULL); + rman_set_bushandle(r, 0); + } + } else if (type == SYS_RES_IRQ) { + intr_deactivate_irq(child, r); } return (rman_deactivate_resource(r)); @@ -431,8 +438,18 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - - return (INTR_IRQ_INVALID); + u_int irq; + struct intr_map_data_fdt *fdt_data; + size_t len; + + len = sizeof(*fdt_data) + icells * sizeof(pcell_t); + fdt_data = (struct intr_map_data_fdt *)intr_alloc_map_data( + INTR_MAP_DATA_FDT, len, M_WAITOK | M_ZERO); + fdt_data->iparent = iparent; + fdt_data->ncells = icells; + memcpy(fdt_data->cells, intr, icells * sizeof(pcell_t)); + irq = intr_map_irq(NULL, iparent, (struct intr_map_data *)fdt_data); + return (irq); } #endif Index: head/sys/dev/fdt/simplebus.c =================================================================== --- head/sys/dev/fdt/simplebus.c +++ head/sys/dev/fdt/simplebus.c @@ -251,9 +251,7 @@ resource_list_init(&ndi->rl); ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->rl); -#ifndef INTRNG ofw_bus_intr_to_rl(dev, node, &ndi->rl, NULL); -#endif return (ndi); } Index: head/sys/dev/gpio/gpiobus.c =================================================================== --- head/sys/dev/gpio/gpiobus.c +++ head/sys/dev/gpio/gpiobus.c @@ -31,7 +31,9 @@ #include #include #include +#ifdef INTRNG #include +#endif #include #include #include @@ -79,43 +81,26 @@ * data will be moved into struct resource. */ #ifdef INTRNG -static void -gpio_destruct_map_data(struct intr_map_data *map_data) -{ - - KASSERT(map_data->type == INTR_MAP_DATA_GPIO, - ("%s: bad map_data type %d", __func__, map_data->type)); - - free(map_data, M_DEVBUF); -} struct resource * gpio_alloc_intr_resource(device_t consumer_dev, int *rid, u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode) { - int rv; u_int irq; struct intr_map_data_gpio *gpio_data; struct resource *res; - gpio_data = malloc(sizeof(*gpio_data), M_DEVBUF, M_WAITOK | M_ZERO); - gpio_data->hdr.type = INTR_MAP_DATA_GPIO; - gpio_data->hdr.destruct = gpio_destruct_map_data; + gpio_data = (struct intr_map_data_gpio *)intr_alloc_map_data( + INTR_MAP_DATA_GPIO, sizeof(*gpio_data), M_WAITOK | M_ZERO); gpio_data->gpio_pin_num = pin->pin; gpio_data->gpio_pin_flags = pin->flags; gpio_data->gpio_intr_mode = intr_mode; - rv = intr_map_irq(pin->dev, 0, (struct intr_map_data *)gpio_data, - &irq); - if (rv != 0) { - gpio_destruct_map_data((struct intr_map_data *)gpio_data); - return (NULL); - } - + irq = intr_map_irq(pin->dev, 0, (struct intr_map_data *)gpio_data); res = bus_alloc_resource(consumer_dev, SYS_RES_IRQ, rid, irq, irq, 1, alloc_flags); if (res == NULL) { - gpio_destruct_map_data((struct intr_map_data *)gpio_data); + intr_free_intr_map_data((struct intr_map_data *)gpio_data); return (NULL); } rman_set_virtual(res, gpio_data); Index: head/sys/dev/gpio/gpiobusvar.h =================================================================== --- head/sys/dev/gpio/gpiobusvar.h +++ head/sys/dev/gpio/gpiobusvar.h @@ -70,12 +70,14 @@ char *name; /* pin name. */ }; +#ifdef INTRNG struct intr_map_data_gpio { struct intr_map_data hdr; u_int gpio_pin_num; u_int gpio_pin_flags; u_int gpio_intr_mode; }; +#endif struct gpiobus_softc { Index: head/sys/dev/gpio/ofw_gpiobus.c =================================================================== --- head/sys/dev/gpio/ofw_gpiobus.c +++ head/sys/dev/gpio/ofw_gpiobus.c @@ -321,13 +321,11 @@ devi->pins[i] = pins[i].pin; } free(pins, M_DEVBUF); -#ifndef INTRNG /* Parse the interrupt resources. */ if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) { ofw_gpiobus_destroy_devinfo(bus, dinfo); return (NULL); } -#endif device_set_ivars(child, dinfo); return (dinfo); Index: head/sys/dev/iicbus/ofw_iicbus.c =================================================================== --- head/sys/dev/iicbus/ofw_iicbus.c +++ head/sys/dev/iicbus/ofw_iicbus.c @@ -187,10 +187,8 @@ childdev = device_add_child(dev, NULL, -1); resource_list_init(&dinfo->opd_dinfo.rl); -#ifndef INTRNG ofw_bus_intr_to_rl(childdev, child, &dinfo->opd_dinfo.rl, NULL); -#endif device_set_ivars(childdev, dinfo); } Index: head/sys/dev/ofw/ofw_bus_subr.h =================================================================== --- head/sys/dev/ofw/ofw_bus_subr.h +++ head/sys/dev/ofw/ofw_bus_subr.h @@ -32,7 +32,9 @@ #define _DEV_OFW_OFW_BUS_SUBR_H_ #include - +#ifdef INTRNG +#include +#endif #include #include "ofw_bus_if.h" @@ -52,12 +54,14 @@ uintptr_t ocd_data; }; +#ifdef INTRNG struct intr_map_data_fdt { struct intr_map_data hdr; phandle_t iparent; u_int ncells; - pcell_t *cells; + pcell_t cells[]; }; +#endif #define SIMPLEBUS_PNP_DESCR "Z:compat;P:private;" #define SIMPLEBUS_PNP_INFO(t) \ @@ -89,9 +93,7 @@ /* Routines for parsing device-tree data into resource lists. */ int ofw_bus_reg_to_rl(device_t, phandle_t, pcell_t, pcell_t, struct resource_list *); -#ifndef INTRNG int ofw_bus_intr_to_rl(device_t, phandle_t, struct resource_list *, int *); -#endif int ofw_bus_intr_by_rid(device_t, phandle_t, int, phandle_t *, int *, pcell_t **); Index: head/sys/dev/ofw/ofw_bus_subr.c =================================================================== --- head/sys/dev/ofw/ofw_bus_subr.c +++ head/sys/dev/ofw/ofw_bus_subr.c @@ -516,7 +516,6 @@ return (iparent); } -#ifndef INTRNG int ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, int *rlen) @@ -582,7 +581,6 @@ free(intr, M_OFWPROP); return (err); } -#endif int ofw_bus_intr_by_rid(device_t dev, phandle_t node, int wanted_rid, Index: head/sys/dev/ofw/ofwbus.c =================================================================== --- head/sys/dev/ofw/ofwbus.c +++ head/sys/dev/ofw/ofwbus.c @@ -80,9 +80,6 @@ static bus_alloc_resource_t ofwbus_alloc_resource; static bus_adjust_resource_t ofwbus_adjust_resource; static bus_release_resource_t ofwbus_release_resource; -#ifdef INTRNG -static bus_map_intr_t ofwbus_map_intr; -#endif static device_method_t ofwbus_methods[] = { /* Device interface */ @@ -96,9 +93,6 @@ DEVMETHOD(bus_alloc_resource, ofwbus_alloc_resource), DEVMETHOD(bus_adjust_resource, ofwbus_adjust_resource), DEVMETHOD(bus_release_resource, ofwbus_release_resource), -#ifdef INTRNG - DEVMETHOD(bus_map_intr, ofwbus_map_intr), -#endif DEVMETHOD_END }; @@ -299,53 +293,3 @@ } return (rman_release_resource(r)); } - -#ifdef INTRNG -static void -ofwbus_destruct_map_data(struct intr_map_data *map_data) -{ - struct intr_map_data_fdt *fdt_map_data; - - KASSERT(map_data->type == INTR_MAP_DATA_FDT, - ("%s: bad map_data type %d", __func__, map_data->type)); - - fdt_map_data = (struct intr_map_data_fdt *)map_data; - OF_prop_free(fdt_map_data->cells); - free(fdt_map_data, M_OFWPROP); -} - -static int -ofwbus_map_intr(device_t bus, device_t child, int *rid, rman_res_t *start, - rman_res_t *end, rman_res_t *count, struct intr_map_data **imd) -{ - phandle_t iparent, node; - pcell_t *cells; - int ncells, rv; - u_int irq; - struct intr_map_data_fdt *fdt_data; - - node = ofw_bus_get_node(child); - rv = ofw_bus_intr_by_rid(child, node, *rid, &iparent, &ncells, &cells); - if (rv != 0) - return (rv); - - fdt_data = malloc(sizeof(*fdt_data), M_OFWPROP, M_WAITOK | M_ZERO); - fdt_data->hdr.type = INTR_MAP_DATA_FDT; - fdt_data->hdr.destruct = ofwbus_destruct_map_data; - fdt_data->iparent = iparent; - fdt_data->ncells = ncells; - fdt_data->cells = cells; - rv = intr_map_irq(NULL, iparent, (struct intr_map_data *)fdt_data, - &irq); - if (rv != 0) { - ofwbus_destruct_map_data((struct intr_map_data *)fdt_data); - return (rv); - } - - *start = irq; - *end = irq; - *count = 1; - *imd = (struct intr_map_data *)fdt_data; - return (0); -} -#endif Index: head/sys/dev/pci/pci_host_generic.c =================================================================== --- head/sys/dev/pci/pci_host_generic.c +++ head/sys/dev/pci/pci_host_generic.c @@ -939,9 +939,7 @@ resource_list_init(&di->di_rl); ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells, &di->di_rl); -#ifndef INTRNG ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); -#endif /* Add newbus device for this FDT node */ child = device_add_child(dev, NULL, -1); Index: head/sys/dev/vnic/mrml_bridge.c =================================================================== --- head/sys/dev/vnic/mrml_bridge.c +++ head/sys/dev/vnic/mrml_bridge.c @@ -263,9 +263,7 @@ resource_list_init(&di->di_rl); ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &di->di_rl); -#ifndef INTRNG ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); -#endif /* Add newbus device for this FDT node */ child = device_add_child(dev, NULL, -1); Index: head/sys/dev/vnic/thunder_mdio_fdt.c =================================================================== --- head/sys/dev/vnic/thunder_mdio_fdt.c +++ head/sys/dev/vnic/thunder_mdio_fdt.c @@ -271,9 +271,7 @@ resource_list_init(&di->di_rl); ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &di->di_rl); -#ifndef INTRNG ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL); -#endif /* Add newbus device for this FDT node */ child = device_add_child(dev, NULL, -1); Index: head/sys/kern/bus_if.m =================================================================== --- head/sys/kern/bus_if.m +++ head/sys/kern/bus_if.m @@ -418,35 +418,6 @@ }; /** - * @brief Map an interrupt - * - * This method is used to get an interrupt mapping data according to provided - * hints. The hints could be modified afterwards, but only if mapping data was - * allocated. This method is intended to be called before BUS_ALLOC_RESOURCE(). - * - * @param _dev the parent device of @p _child - * @param _child the device which is requesting an allocation - * @param _rid a pointer to the resource identifier - * @param _start a pointer to the hint at the start of the resource - * range - pass @c 0 for any start address - * @param _end a pointer to the hint at the end of the resource - * range - pass @c ~0 for any end address - * @param _count a pointer to the hint at the size of resource - * range required - pass @c 1 for any size - * @param _imd a pointer to the interrupt mapping data which was - * allocated - */ -METHOD int map_intr { - device_t _dev; - device_t _child; - int *_rid; - rman_res_t *_start; - rman_res_t *_end; - rman_res_t *_count; - struct intr_map_data **_imd; -} DEFAULT bus_generic_map_intr; - -/** * @brief Install an interrupt handler * * This method is used to associate an interrupt handler function with Index: head/sys/kern/pic_if.m =================================================================== --- head/sys/kern/pic_if.m +++ head/sys/kern/pic_if.m @@ -43,7 +43,7 @@ } static int - null_pic_alloc_intr(device_t dev, struct intr_irqsrc *isrc, + null_pic_activate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { @@ -51,7 +51,7 @@ } static int - null_pic_release_intr(device_t dev, struct intr_irqsrc *isrc, + null_pic_deactivate_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { @@ -92,12 +92,12 @@ } }; -METHOD int alloc_intr { +METHOD int activate_intr { device_t dev; struct intr_irqsrc *isrc; struct resource *res; struct intr_map_data *data; -} DEFAULT null_pic_alloc_intr; +} DEFAULT null_pic_activate_intr; METHOD int bind_intr { device_t dev; @@ -120,12 +120,12 @@ struct intr_irqsrc **isrcp; }; -METHOD int release_intr { +METHOD int deactivate_intr { device_t dev; struct intr_irqsrc *isrc; struct resource *res; struct intr_map_data *data; -} DEFAULT null_pic_release_intr; +} DEFAULT null_pic_deactivate_intr; METHOD int setup_intr { device_t dev; Index: head/sys/kern/subr_bus.c =================================================================== --- head/sys/kern/subr_bus.c +++ head/sys/kern/subr_bus.c @@ -3951,23 +3951,6 @@ } /** - * @brief Helper function for implementing BUS_MAP_INTR(). - * - * This simple implementation of BUS_MAP_INTR() simply calls the - * BUS_MAP_INTR() method of the parent of @p dev. - */ -int -bus_generic_map_intr(device_t dev, device_t child, int *rid, rman_res_t *start, - rman_res_t *end, rman_res_t *count, struct intr_map_data **imd) -{ - /* Propagate up the bus hierarchy until someone handles it. */ - if (dev->parent) - return (BUS_MAP_INTR(dev->parent, child, rid, start, end, count, - imd)); - return (EINVAL); -} - -/** * @brief Helper function for implementing BUS_SETUP_INTR(). * * This simple implementation of BUS_SETUP_INTR() simply calls the @@ -4422,41 +4405,6 @@ } } -#ifdef INTRNG -/** - * @internal - * - * This can be converted to bus method later. (XXX) - */ -static struct intr_map_data * -bus_extend_resource(device_t dev, int type, int *rid, rman_res_t *start, - rman_res_t *end, rman_res_t *count) -{ - struct intr_map_data *imd; - struct resource_list *rl; - int rv; - - if (dev->parent == NULL) - return (NULL); - if (type != SYS_RES_IRQ) - return (NULL); - - if (!RMAN_IS_DEFAULT_RANGE(*start, *end)) - return (NULL); - rl = BUS_GET_RESOURCE_LIST(dev->parent, dev); - if (rl != NULL) { - if (resource_list_find(rl, type, *rid) != NULL) - return (NULL); - } - rv = BUS_MAP_INTR(dev->parent, dev, rid, start, end, count, &imd); - if (rv != 0) - return (NULL); - if (rl != NULL) - resource_list_add(rl, type, *rid, *start, *end, *count); - return (imd); -} -#endif - /** * @brief Wrapper function for BUS_ALLOC_RESOURCE(). * @@ -4468,26 +4416,11 @@ rman_res_t end, rman_res_t count, u_int flags) { struct resource *res; -#ifdef INTRNG - struct intr_map_data *imd; -#endif if (dev->parent == NULL) return (NULL); - -#ifdef INTRNG - imd = bus_extend_resource(dev, type, rid, &start, &end, &count); -#endif res = BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, count, flags); -#ifdef INTRNG - if (imd != NULL) { - if (res != NULL && rman_get_virtual(res) == NULL) - rman_set_virtual(res, imd); - else - imd->destruct(imd); - } -#endif return (res); } @@ -4574,21 +4507,10 @@ bus_release_resource(device_t dev, int type, int rid, struct resource *r) { int rv; -#ifdef INTRNG - struct intr_map_data *imd; -#endif if (dev->parent == NULL) return (EINVAL); - -#ifdef INTRNG - imd = (type == SYS_RES_IRQ) ? rman_get_virtual(r) : NULL; -#endif rv = BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r); -#ifdef INTRNG - if (imd != NULL) - imd->destruct(imd); -#endif return (rv); } Index: head/sys/kern/subr_intr.c =================================================================== --- head/sys/kern/subr_intr.c +++ head/sys/kern/subr_intr.c @@ -31,8 +31,9 @@ /* * New-style Interrupt Framework * - * TODO: - to support IPI (PPI) enabling on other CPUs if already started - * - to complete things for removable PICs + * TODO: - add support for disconnected PICs. + * - to support IPI (PPI) enabling on other CPUs if already started. + * - to complete things for removable PICs. */ #include "opt_ddb.h" @@ -142,6 +143,11 @@ size_t sintrnames = sizeof(intrnames); static u_int intrcnt_index; +static struct intr_irqsrc *intr_map_get_isrc(u_int res_id); +static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc); +static void intr_map_copy_map_data(u_int res_id, device_t *dev, intptr_t *xref, + struct intr_map_data **data); + /* * Interrupt framework initialization routine. */ @@ -414,18 +420,6 @@ } /* - * Lookup interrupt source by interrupt number (resource handle). - */ -static inline struct intr_irqsrc * -isrc_lookup(u_int irq) -{ - - if (irq < nitems(irq_sources)) - return (irq_sources[irq]); - return (NULL); -} - -/* * Initialize interrupt source and register it into global interrupt table. */ int @@ -899,13 +893,12 @@ return (pic); } -int -intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, - u_int *irqp) +static int +intr_resolve_irq(device_t dev, intptr_t xref, struct intr_map_data *data, + struct intr_irqsrc **isrc) { - int error; - struct intr_irqsrc *isrc; struct intr_pic *pic; + struct intr_map_data_msi *msi; if (data == NULL) return (EINVAL); @@ -914,48 +907,77 @@ if (pic == NULL) return (ESRCH); - KASSERT((pic->pic_flags & FLAG_PIC) != 0, - ("%s: Found a non-PIC controller: %s", __func__, - device_get_name(pic->pic_dev))); + switch (data->type) { + case INTR_MAP_DATA_MSI: + KASSERT((pic->pic_flags & FLAG_MSI) != 0, + ("%s: Found a non-MSI controller: %s", __func__, + device_get_name(pic->pic_dev))); + msi = (struct intr_map_data_msi *)data; + *isrc = msi->isrc; + return (0); - error = PIC_MAP_INTR(pic->pic_dev, data, &isrc); - if (error == 0) - *irqp = isrc->isrc_irq; - return (error); + default: + KASSERT((pic->pic_flags & FLAG_PIC) != 0, + ("%s: Found a non-PIC controller: %s", __func__, + device_get_name(pic->pic_dev))); + return (PIC_MAP_INTR(pic->pic_dev, data, isrc)); + + } } int -intr_alloc_irq(device_t dev, struct resource *res) +intr_activate_irq(device_t dev, struct resource *res) { + device_t map_dev; + intptr_t map_xref; struct intr_map_data *data; struct intr_irqsrc *isrc; + u_int res_id; + int error; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); - if (isrc == NULL) - return (EINVAL); - - data = rman_get_virtual(res); - return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data)); + res_id = (u_int)rman_get_start(res); + if (intr_map_get_isrc(res_id) != NULL) + panic("Attempt to double activation of resource id: %u\n", + res_id); + intr_map_copy_map_data(res_id, &map_dev, &map_xref, &data); + error = intr_resolve_irq(map_dev, map_xref, data, &isrc); + if (error != 0) { + free(data, M_INTRNG); + /* XXX TODO DISCONECTED PICs */ + /* if (error == EINVAL) return(0); */ + return (error); + } + intr_map_set_isrc(res_id, isrc); + rman_set_virtual(res, data); + return (PIC_ACTIVATE_INTR(isrc->isrc_dev, isrc, res, data)); } int -intr_release_irq(device_t dev, struct resource *res) +intr_deactivate_irq(device_t dev, struct resource *res) { struct intr_map_data *data; struct intr_irqsrc *isrc; + u_int res_id; + int error; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); + res_id = (u_int)rman_get_start(res); + isrc = intr_map_get_isrc(res_id); if (isrc == NULL) - return (EINVAL); + panic("Attempt to deactivate non-active resource id: %u\n", + res_id); data = rman_get_virtual(res); - return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data)); + error = PIC_DEACTIVATE_INTR(isrc->isrc_dev, isrc, res, data); + intr_map_set_isrc(res_id, NULL); + rman_set_virtual(res, NULL); + free(data, M_INTRNG); + return (error); } int @@ -966,13 +988,17 @@ struct intr_map_data *data; struct intr_irqsrc *isrc; const char *name; + u_int res_id; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); - if (isrc == NULL) + res_id = (u_int)rman_get_start(res); + isrc = intr_map_get_isrc(res_id); + if (isrc == NULL) { + /* XXX TODO DISCONECTED PICs */ return (EINVAL); + } data = rman_get_virtual(res); name = device_get_nameunit(dev); @@ -1027,11 +1053,13 @@ int error; struct intr_map_data *data; struct intr_irqsrc *isrc; + u_int res_id; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); + res_id = (u_int)rman_get_start(res); + isrc = intr_map_get_isrc(res_id); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); @@ -1075,11 +1103,13 @@ { int error; struct intr_irqsrc *isrc; + u_int res_id; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); + res_id = (u_int)rman_get_start(res); + isrc = intr_map_get_isrc(res_id); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); #ifdef INTR_SOLO @@ -1107,11 +1137,13 @@ intr_bind_irq(device_t dev, struct resource *res, int cpu) { struct intr_irqsrc *isrc; + u_int res_id; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = isrc_lookup(rman_get_start(res)); + res_id = (u_int)rman_get_start(res); + isrc = intr_map_get_isrc(res_id); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); #ifdef INTR_SOLO @@ -1191,6 +1223,28 @@ #endif /* + * Allocate memory for new intr_map_data structure. + * Initialize common fields. + */ +struct intr_map_data * +intr_alloc_map_data(enum intr_map_data_type type, size_t len, int flags) +{ + struct intr_map_data *data; + + data = malloc(len, M_INTRNG, flags); + data->type = type; + data->len = len; + return (data); +} + +void intr_free_intr_map_data(struct intr_map_data *data) +{ + + free(data, M_INTRNG); +} + + +/* * Register a MSI/MSI-X interrupt controller */ int @@ -1218,6 +1272,7 @@ struct intr_irqsrc **isrc; struct intr_pic *pic; device_t pdev; + struct intr_map_data_msi *msi; int err, i; pic = pic_lookup(NULL, xref); @@ -1230,12 +1285,19 @@ 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; - } + if (err != 0) { + free(isrc, M_INTRNG); + return (err); } + for (i = 0; i < count; i++) { + msi = (struct intr_map_data_msi *)intr_alloc_map_data( + INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); + msi-> isrc = isrc[i]; + irqs[i] = intr_map_irq(pic->pic_dev, xref, + (struct intr_map_data *)msi); + + } free(isrc, M_INTRNG); return (err); @@ -1259,15 +1321,16 @@ isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); + for (i = 0; i < count; i++) + isrc[i] = intr_map_get_isrc(irqs[i]); + + err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc); + for (i = 0; i < count; i++) { - isrc[i] = isrc_lookup(irqs[i]); - if (isrc == NULL) { - free(isrc, M_INTRNG); - return (EINVAL); - } + if (isrc[i] != NULL) + intr_unmap_irq(irqs[i]); } - err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc); free(isrc, M_INTRNG); return (err); } @@ -1278,6 +1341,7 @@ struct intr_irqsrc *isrc; struct intr_pic *pic; device_t pdev; + struct intr_map_data_msi *msi; int err; pic = pic_lookup(NULL, xref); @@ -1288,11 +1352,15 @@ ("%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; + msi = (struct intr_map_data_msi *)intr_alloc_map_data( + INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); + msi->isrc = isrc; + *irq = intr_map_irq(pic->pic_dev, xref, (struct intr_map_data *)msi); return (0); } @@ -1311,11 +1379,15 @@ ("%s: Found a non-MSI controller: %s", __func__, device_get_name(pic->pic_dev))); - isrc = isrc_lookup(irq); - if (isrc == NULL) + isrc = intr_map_get_isrc(irq); + if (isrc == NULL) { + intr_unmap_irq(irq); return (EINVAL); + } err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc); + intr_unmap_irq(irq); + return (err); } @@ -1335,7 +1407,7 @@ ("%s: Found a non-MSI controller: %s", __func__, device_get_name(pic->pic_dev))); - isrc = isrc_lookup(irq); + isrc = intr_map_get_isrc(irq); if (isrc == NULL) return (EINVAL); @@ -1390,3 +1462,161 @@ db_printf("irq total %u\n", irqsum); } #endif + +/* + * Interrupt mapping table functions. + * + * Please, keep this part separately, it can be transformed to + * extension of standard resources. + */ +struct intr_map_entry +{ + device_t dev; + intptr_t xref; + struct intr_map_data *map_data; + struct intr_irqsrc *isrc; + /* XXX TODO DISCONECTED PICs */ + /*int flags */ +}; + +/* XXX Convert irq_map[] to dynamicaly expandable one. */ +static struct intr_map_entry *irq_map[2 * NIRQ]; +static int irq_map_count = nitems(irq_map); +static int irq_map_first_free_idx; +static struct mtx irq_map_lock; + +static struct intr_irqsrc * +intr_map_get_isrc(u_int res_id) +{ + struct intr_irqsrc *isrc; + + mtx_lock(&irq_map_lock); + if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL)) { + mtx_unlock(&irq_map_lock); + return (NULL); + } + isrc = irq_map[res_id]->isrc; + mtx_unlock(&irq_map_lock); + return (isrc); +} + +static void +intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc) +{ + + mtx_lock(&irq_map_lock); + if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL)) { + mtx_unlock(&irq_map_lock); + return; + } + irq_map[res_id]->isrc = isrc; + mtx_unlock(&irq_map_lock); +} + +/* + * Get a copy of intr_map_entry data + */ +static void +intr_map_copy_map_data(u_int res_id, device_t *map_dev, intptr_t *map_xref, + struct intr_map_data **data) +{ + size_t len; + + len = 0; + mtx_lock(&irq_map_lock); + if (res_id >= irq_map_count || irq_map[res_id] == NULL) + panic("Attempt to copy invalid resource id: %u\n", res_id); + if (irq_map[res_id]->map_data != NULL) + len = irq_map[res_id]->map_data->len; + mtx_unlock(&irq_map_lock); + + if (len == 0) + *data = NULL; + else + *data = malloc(len, M_INTRNG, M_WAITOK | M_ZERO); + mtx_lock(&irq_map_lock); + if (irq_map[res_id] == NULL) + panic("Attempt to copy invalid resource id: %u\n", res_id); + if (len != 0) { + if (len != irq_map[res_id]->map_data->len) + panic("Resource id: %u has changed.\n", res_id); + memcpy(*data, irq_map[res_id]->map_data, len); + } + *map_dev = irq_map[res_id]->dev; + *map_xref = irq_map[res_id]->xref; + mtx_unlock(&irq_map_lock); +} + + +/* + * Allocate and fill new entry in irq_map table. + */ +u_int +intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data) +{ + u_int i; + struct intr_map_entry *entry; + + /* Prepare new entry first. */ + entry = malloc(sizeof(*entry), M_INTRNG, M_WAITOK | M_ZERO); + + entry->dev = dev; + entry->xref = xref; + entry->map_data = data; + entry->isrc = NULL; + + mtx_lock(&irq_map_lock); + for (i = irq_map_first_free_idx; i < irq_map_count; i++) { + if (irq_map[i] == NULL) { + irq_map[i] = entry; + irq_map_first_free_idx = i + 1; + mtx_unlock(&irq_map_lock); + return (i); + } + } + mtx_unlock(&irq_map_lock); + + /* XXX Expand irq_map table */ + panic("IRQ mapping table is full."); +} + +/* + * Remove and free mapping entry. + */ +void +intr_unmap_irq(u_int res_id) +{ + struct intr_map_entry *entry; + + mtx_lock(&irq_map_lock); + if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL)) + panic("Attempt to unmap invalid resource id: %u\n", res_id); + entry = irq_map[res_id]; + irq_map[res_id] = NULL; + irq_map_first_free_idx = res_id; + mtx_unlock(&irq_map_lock); + intr_free_intr_map_data(entry->map_data); + free(entry, M_INTRNG); +} + +/* + * Clone mapping entry. + */ +u_int +intr_map_clone_irq(u_int old_res_id) +{ + device_t map_dev; + intptr_t map_xref; + struct intr_map_data *data; + + intr_map_copy_map_data(old_res_id, &map_dev, &map_xref, &data); + return (intr_map_irq(map_dev, map_xref, data)); +} + +static void +intr_map_init(void *dummy __unused) +{ + + mtx_init(&irq_map_lock, "intr map table", NULL, MTX_DEF); +} +SYSINIT(intr_map_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_map_init, NULL); Index: head/sys/mips/mips/nexus.c =================================================================== --- head/sys/mips/mips/nexus.c +++ head/sys/mips/mips/nexus.c @@ -64,6 +64,7 @@ #endif #ifdef FDT +#include #include #include "ofw_bus_if.h" #endif @@ -429,6 +430,10 @@ } rman_set_virtual(r, vaddr); rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr); + } else if (type == SYS_RES_IRQ) { +#ifdef INTRNG + intr_activate_irq(child, r); +#endif } return (rman_activate_resource(r)); @@ -448,6 +453,10 @@ bus_space_unmap(rman_get_bustag(r), vaddr, psize); rman_set_virtual(r, NULL); rman_set_bushandle(r, 0); + } else if (type == SYS_RES_IRQ) { +#ifdef INTRNG + intr_deactivate_irq(child, r); +#endif } return (rman_deactivate_resource(r)); @@ -523,12 +532,18 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - -#ifdef INTRNG - return (INTR_IRQ_INVALID); -#else - return (intr_fdt_map_irq(iparent, intr, icells)); -#endif + u_int irq; + struct intr_map_data_fdt *fdt_data; + size_t len; + + len = sizeof(*fdt_data) + icells * sizeof(pcell_t); + fdt_data = (struct intr_map_data_fdt *)intr_alloc_map_data( + INTR_MAP_DATA_FDT, len, M_WAITOK | M_ZERO); + fdt_data->iparent = iparent; + fdt_data->ncells = icells; + memcpy(fdt_data->cells, intr, icells * sizeof(pcell_t)); + irq = intr_map_irq(NULL, iparent, (struct intr_map_data *)fdt_data); + return (irq); } #endif #endif /* INTRNG */ Index: head/sys/sys/bus.h =================================================================== --- head/sys/sys/bus.h +++ head/sys/sys/bus.h @@ -272,17 +272,6 @@ INTR_POLARITY_LOW = 2 }; -enum intr_map_data_type { - INTR_MAP_DATA_ACPI, - INTR_MAP_DATA_FDT, - INTR_MAP_DATA_GPIO, -}; - -struct intr_map_data { - enum intr_map_data_type type; - void (*destruct)(struct intr_map_data *); -}; - /** * CPU sets supported by bus_get_cpus(). Note that not all sets may be * supported for a given device. If a request is not supported by a @@ -459,9 +448,6 @@ int type, int rid, struct resource *r); int bus_generic_resume(device_t dev); int bus_generic_resume_child(device_t dev, device_t child); -int bus_generic_map_intr(device_t dev, device_t child, int *rid, - rman_res_t *start, rman_res_t *end, - rman_res_t *count, struct intr_map_data **imd); int bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *intr, Index: head/sys/sys/intr.h =================================================================== --- head/sys/sys/intr.h +++ head/sys/sys/intr.h @@ -29,11 +29,38 @@ #ifndef _SYS_INTR_H_ #define _SYS_INTR_H_ +#ifndef INTRNG +#error Need INTRNG for this file +#endif #include #define INTR_IRQ_INVALID 0xFFFFFFFF +enum intr_map_data_type { + INTR_MAP_DATA_ACPI = 0, + INTR_MAP_DATA_FDT, + INTR_MAP_DATA_GPIO, + INTR_MAP_DATA_MSI, + + /* Placeholders for platform specific types */ + INTR_MAP_DATA_PLAT_1 = 1000, + INTR_MAP_DATA_PLAT_2, + INTR_MAP_DATA_PLAT_3, + INTR_MAP_DATA_PLAT_4, + INTR_MAP_DATA_PLAT_5, +}; + +struct intr_map_data { + size_t len; + enum intr_map_data_type type; +}; + +struct intr_map_data_msi { + struct intr_map_data hdr; + struct intr_irqsrc *isrc; +}; + #ifdef notyet #define INTR_SOLO INTR_MD1 typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); @@ -88,10 +115,9 @@ extern device_t intr_irq_root_dev; /* Intr interface for BUS. */ -int intr_map_irq(device_t, intptr_t, struct intr_map_data *, u_int *); -int intr_alloc_irq(device_t, struct resource *); -int intr_release_irq(device_t, struct resource *); +int intr_activate_irq(device_t, struct resource *); +int intr_deactivate_irq(device_t, struct resource *); int intr_setup_irq(device_t, struct resource *, driver_filter_t, driver_intr_t, void *, int, void **); @@ -100,6 +126,13 @@ int intr_describe_irq(device_t, struct resource *, void *, const char *); int intr_child_irq_handler(struct intr_pic *, uintptr_t); +/* Intr resources mapping. */ +struct intr_map_data *intr_alloc_map_data(enum intr_map_data_type, size_t, int); +void intr_free_intr_map_data(struct intr_map_data *); +u_int intr_map_irq(device_t, intptr_t, struct intr_map_data *); +void intr_unmap_irq(u_int ); +u_int intr_map_clone_irq(u_int ); + /* MSI/MSI-X handling */ int intr_msi_register(device_t, intptr_t); int intr_alloc_msi(device_t, device_t, intptr_t, int, int, int *);