summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorskra <skra@FreeBSD.org>2016-06-05 16:20:12 +0000
committerskra <skra@FreeBSD.org>2016-06-05 16:20:12 +0000
commit612e6958e467e3c02b826846aba5b685d486c07c (patch)
tree09f7a3292cf97e27a58700773b3817ba12f58e1b /sys
parentff4d6f61950f6358d7cdc508dfa92042f30d88d6 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys')
-rw-r--r--sys/arm/arm/nexus.c4
-rw-r--r--sys/arm64/arm64/gic_v3.c4
-rw-r--r--sys/arm64/arm64/nexus.c2
-rw-r--r--sys/dev/fdt/simplebus.c2
-rw-r--r--sys/dev/gpio/ofw_gpiobus.c2
-rw-r--r--sys/dev/iicbus/ofw_iicbus.c2
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c73
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h11
-rw-r--r--sys/dev/ofw/ofwbus.c59
-rw-r--r--sys/dev/pci/pci_host_generic.c2
-rw-r--r--sys/dev/vnic/mrml_bridge.c2
-rw-r--r--sys/dev/vnic/thunder_mdio_fdt.c2
-rw-r--r--sys/kern/subr_intr.c57
-rw-r--r--sys/mips/mips/nexus.c4
-rw-r--r--sys/sys/intr.h11
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);
OpenPOWER on IntegriCloud