diff options
author | skra <skra@FreeBSD.org> | 2016-06-05 16:20:12 +0000 |
---|---|---|
committer | skra <skra@FreeBSD.org> | 2016-06-05 16:20:12 +0000 |
commit | 612e6958e467e3c02b826846aba5b685d486c07c (patch) | |
tree | 09f7a3292cf97e27a58700773b3817ba12f58e1b | |
parent | ff4d6f61950f6358d7cdc508dfa92042f30d88d6 (diff) | |
download | FreeBSD-src-612e6958e467e3c02b826846aba5b685d486c07c.zip FreeBSD-src-612e6958e467e3c02b826846aba5b685d486c07c.tar.gz |
INTRNG - change the way how an interrupt mapping data are provided
to the framework in OFW (FDT) case.
This is a follow-up to r301451.
Differential Revision: https://reviews.freebsd.org/D6634
-rw-r--r-- | sys/arm/arm/nexus.c | 4 | ||||
-rw-r--r-- | sys/arm64/arm64/gic_v3.c | 4 | ||||
-rw-r--r-- | sys/arm64/arm64/nexus.c | 2 | ||||
-rw-r--r-- | sys/dev/fdt/simplebus.c | 2 | ||||
-rw-r--r-- | sys/dev/gpio/ofw_gpiobus.c | 2 | ||||
-rw-r--r-- | sys/dev/iicbus/ofw_iicbus.c | 2 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.c | 73 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.h | 11 | ||||
-rw-r--r-- | sys/dev/ofw/ofwbus.c | 59 | ||||
-rw-r--r-- | sys/dev/pci/pci_host_generic.c | 2 | ||||
-rw-r--r-- | sys/dev/vnic/mrml_bridge.c | 2 | ||||
-rw-r--r-- | sys/dev/vnic/thunder_mdio_fdt.c | 2 | ||||
-rw-r--r-- | sys/kern/subr_intr.c | 57 | ||||
-rw-r--r-- | sys/mips/mips/nexus.c | 4 | ||||
-rw-r--r-- | sys/sys/intr.h | 11 |
15 files changed, 189 insertions, 48 deletions
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c index a84e0a8..0c5d1cf 100644 --- a/sys/arm/arm/nexus.c +++ b/sys/arm/arm/nexus.c @@ -412,6 +412,10 @@ 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 } #endif diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c index f2d019a..1f9557e 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -58,6 +58,10 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/intr.h> +#ifdef FDT +#include <dev/ofw/ofw_bus_subr.h> +#endif + #include "pic_if.h" #include "gic_v3_reg.h" diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c index 93f55ae..c57a309 100644 --- a/sys/arm64/arm64/nexus.c +++ b/sys/arm64/arm64/nexus.c @@ -448,7 +448,7 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { #ifdef INTRNG - return (intr_fdt_map_irq(iparent, intr, icells)); + return (INTR_IRQ_INVALID); #else int irq; diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c index 8d43a70..4173160 100644 --- a/sys/dev/fdt/simplebus.c +++ b/sys/dev/fdt/simplebus.c @@ -251,7 +251,9 @@ simplebus_setup_dinfo(device_t dev, phandle_t node, 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); } diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c index 96775dc..804b33e 100644 --- a/sys/dev/gpio/ofw_gpiobus.c +++ b/sys/dev/gpio/ofw_gpiobus.c @@ -321,11 +321,13 @@ ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node) 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); diff --git a/sys/dev/iicbus/ofw_iicbus.c b/sys/dev/iicbus/ofw_iicbus.c index 0820bbf..2da1691 100644 --- a/sys/dev/iicbus/ofw_iicbus.c +++ b/sys/dev/iicbus/ofw_iicbus.c @@ -187,8 +187,10 @@ ofw_iicbus_attach(device_t dev) 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); } diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 8e159d4..b58d041 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -516,6 +516,7 @@ ofw_bus_find_iparent(phandle_t node) return (iparent); } +#ifndef INTRNG int ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, int *rlen) @@ -581,6 +582,78 @@ ofw_bus_intr_to_rl(device_t dev, phandle_t node, free(intr, M_OFWPROP); return (err); } +#endif + +int +ofw_bus_intr_by_rid(device_t dev, phandle_t node, int wanted_rid, + phandle_t *producer, int *ncells, pcell_t **cells) +{ + phandle_t iparent; + uint32_t icells, *intr; + int err, i, nintr, rid; + boolean_t extended; + + nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), + (void **)&intr); + if (nintr > 0) { + iparent = ofw_bus_find_iparent(node); + if (iparent == 0) { + device_printf(dev, "No interrupt-parent found, " + "assuming direct parent\n"); + iparent = OF_parent(node); + iparent = OF_xref_from_node(iparent); + } + if (OF_searchencprop(OF_node_from_xref(iparent), + "#interrupt-cells", &icells, sizeof(icells)) == -1) { + device_printf(dev, "Missing #interrupt-cells " + "property, assuming <1>\n"); + icells = 1; + } + if (icells < 1 || icells > nintr) { + device_printf(dev, "Invalid #interrupt-cells property " + "value <%d>, assuming <1>\n", icells); + icells = 1; + } + extended = false; + } else { + nintr = OF_getencprop_alloc(node, "interrupts-extended", + sizeof(*intr), (void **)&intr); + if (nintr <= 0) + return (ESRCH); + extended = true; + } + err = ESRCH; + rid = 0; + for (i = 0; i < nintr; i += icells, rid++) { + if (extended) { + iparent = intr[i++]; + if (OF_searchencprop(OF_node_from_xref(iparent), + "#interrupt-cells", &icells, sizeof(icells)) == -1) { + device_printf(dev, "Missing #interrupt-cells " + "property\n"); + err = ENOENT; + break; + } + if (icells < 1 || (i + icells) > nintr) { + device_printf(dev, "Invalid #interrupt-cells " + "property value <%d>\n", icells); + err = ERANGE; + break; + } + } + if (rid == wanted_rid) { + *cells = malloc(icells * sizeof(**cells), M_OFWPROP, + M_WAITOK); + *producer = iparent; + *ncells= icells; + memcpy(*cells, intr + i, icells * sizeof(**cells)); + err = 0; + break; + } + } + free(intr, M_OFWPROP); + return (err); +} phandle_t ofw_bus_find_child(phandle_t start, const char *child_name) diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index 578c3ec..3c2b4e1 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -52,6 +52,13 @@ struct ofw_compat_data { uintptr_t ocd_data; }; +struct intr_map_data_fdt { + struct intr_map_data hdr; + phandle_t iparent; + u_int ncells; + pcell_t *cells; +}; + #define SIMPLEBUS_PNP_DESCR "Z:compat;P:private;" #define SIMPLEBUS_PNP_INFO(t) \ MODULE_PNP_INFO(SIMPLEBUS_PNP_DESCR, simplebus, t, t, sizeof(t[0]), sizeof(t) / sizeof(t[0])); @@ -82,7 +89,11 @@ int ofw_bus_msimap(phandle_t, uint16_t, phandle_t *, uint32_t *); /* 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 **); /* Helper to get device status property */ const char *ofw_bus_get_status(device_t dev); diff --git a/sys/dev/ofw/ofwbus.c b/sys/dev/ofw/ofwbus.c index fc43410..1e048c4 100644 --- a/sys/dev/ofw/ofwbus.c +++ b/sys/dev/ofw/ofwbus.c @@ -43,6 +43,9 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/pcpu.h> #include <sys/rman.h> +#ifdef INTRNG +#include <sys/intr.h> +#endif #include <vm/vm.h> #include <vm/pmap.h> @@ -77,6 +80,9 @@ static device_attach_t ofwbus_attach; 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 */ @@ -90,6 +96,9 @@ static device_method_t ofwbus_methods[] = { 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 }; @@ -290,3 +299,53 @@ ofwbus_release_resource(device_t bus, device_t child, int type, } 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 diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c index ef18146..7bb4b42 100644 --- a/sys/dev/pci/pci_host_generic.c +++ b/sys/dev/pci/pci_host_generic.c @@ -949,7 +949,9 @@ generic_pcie_ofw_bus_attach(device_t dev) 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); diff --git a/sys/dev/vnic/mrml_bridge.c b/sys/dev/vnic/mrml_bridge.c index 7f4dc12..8d5006b 100644 --- a/sys/dev/vnic/mrml_bridge.c +++ b/sys/dev/vnic/mrml_bridge.c @@ -263,7 +263,9 @@ mrmlb_ofw_bus_attach(device_t dev) 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); diff --git a/sys/dev/vnic/thunder_mdio_fdt.c b/sys/dev/vnic/thunder_mdio_fdt.c index cc94150..c05c906 100644 --- a/sys/dev/vnic/thunder_mdio_fdt.c +++ b/sys/dev/vnic/thunder_mdio_fdt.c @@ -271,7 +271,9 @@ mdionexus_ofw_bus_attach(device_t dev) 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); diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 4e55bad..5d18ea2 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -64,12 +64,6 @@ __FBSDID("$FreeBSD$"); #include <machine/smp.h> #include <machine/stdarg.h> -#ifdef FDT -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif - #ifdef DDB #include <ddb/ddb.h> #endif @@ -625,33 +619,6 @@ intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, return (ddata->idd_irq); } #endif -#ifdef FDT -/* - * Map interrupt source according to FDT data into framework. If such mapping - * does not exist, create it. Return unique interrupt number (resource handle) - * associated with mapped interrupt source. - */ -u_int -intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) -{ - size_t cellsize; - struct intr_dev_data *ddata; - struct intr_map_data_fdt *daf; - - cellsize = ncells * sizeof(*cells); - ddata = intr_ddata_alloc(sizeof(struct intr_map_data_fdt) + cellsize); - if (ddata == NULL) - return (INTR_IRQ_INVALID); /* no space left */ - - ddata->idd_xref = (intptr_t)node; - ddata->idd_data->type = INTR_MAP_DATA_FDT; - - daf = (struct intr_map_data_fdt *)ddata->idd_data; - daf->ncells = ncells; - memcpy(daf->cells, cells, cellsize); - return (ddata->idd_irq); -} -#endif /* * Store GPIO interrupt decription in framework and return unique interrupt @@ -1107,7 +1074,11 @@ intr_alloc_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1123,7 +1094,11 @@ intr_release_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1142,7 +1117,11 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); @@ -1202,7 +1181,11 @@ intr_teardown_irq(device_t dev, struct resource *res, void *cookie) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), &data); + data = rman_get_virtual(res); + if (data == NULL) + isrc = intr_ddata_lookup(rman_get_start(res), &data); + else + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c index 28e16e8..a253b7e 100644 --- a/sys/mips/mips/nexus.c +++ b/sys/mips/mips/nexus.c @@ -524,7 +524,11 @@ 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 } #endif #endif /* INTRNG */ diff --git a/sys/sys/intr.h b/sys/sys/intr.h index c137a6e..e513517 100644 --- a/sys/sys/intr.h +++ b/sys/sys/intr.h @@ -42,13 +42,6 @@ struct intr_map_data_acpi { enum intr_trigger trig; }; #endif -#ifdef FDT -struct intr_map_data_fdt { - struct intr_map_data hdr; - u_int ncells; - pcell_t cells[0]; -}; -#endif struct intr_map_data_gpio { struct intr_map_data hdr; @@ -135,9 +128,7 @@ int intr_release_msix(device_t, device_t, intptr_t, int); u_int intr_acpi_map_irq(device_t, u_int, enum intr_polarity, enum intr_trigger); #endif -#ifdef FDT -u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int); -#endif + u_int intr_gpio_map_irq(device_t dev, u_int pin_num, u_int pin_flags, u_int intr_mode); |