Date: Thu, 25 Sep 2014 15:02:34 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r272109 - in head/sys: dev/fdt dev/ofw mips/beri powerpc/ofw powerpc/pseries Message-ID: <201409251502.s8PF2Y5v021266@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Thu Sep 25 15:02:33 2014 New Revision: 272109 URL: http://svnweb.freebsd.org/changeset/base/272109 Log: Replace multiple nearly-identical copies of code to walk through an FDT node's interrupts=<...> property creating resource list entries with a single common implementation. This change makes ofw_bus_intr_to_rl() the one true copy of that code and removes the copies of it from other places. This also adds handling of the interrupts-extended property, which allows specifying multiple interrupts for a node where each interrupt can have a separate interrupt-parent. The bindings for this state that the property cells contain an xref phandle to the interrupt parent followed by whatever interrupt info that parent normally expects. This leads to having a variable number of icells per interrupt in the property. For example you could have <&intc1 1 &intc2 26 9 0 &intc3 9 4>. Differential Revision: https://reviews.freebsd.org/D803 Modified: head/sys/dev/fdt/fdt_common.c head/sys/dev/fdt/fdt_common.h head/sys/dev/fdt/simplebus.c head/sys/dev/ofw/ofw_bus_subr.c head/sys/dev/ofw/ofw_bus_subr.h head/sys/dev/ofw/ofwbus.c head/sys/mips/beri/beri_simplebus.c head/sys/powerpc/ofw/ofw_pcibus.c head/sys/powerpc/pseries/vdevice.c Modified: head/sys/dev/fdt/fdt_common.c ============================================================================== --- head/sys/dev/fdt/fdt_common.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/fdt/fdt_common.c Thu Sep 25 15:02:33 2014 (r272109) @@ -494,46 +494,6 @@ out: } int -fdt_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, - struct fdt_sense_level *intr_sl) -{ - phandle_t iparent; - uint32_t *intr, icells; - int nintr, i, k; - - nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), - (void **)&intr); - if (nintr > 0) { - if (OF_searchencprop(node, "interrupt-parent", &iparent, - sizeof(iparent)) == -1) { - device_printf(dev, "No interrupt-parent found, " - "assuming direct parent\n"); - iparent = OF_parent(node); - } - 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; - } - for (i = 0, k = 0; i < nintr; i += icells, k++) { - intr[i] = ofw_bus_map_intr(dev, iparent, icells, - &intr[i]); - resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i], - 1); - } - free(intr, M_OFWPROP); - } - - return (0); -} - -int fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc) { phandle_t phy_node; Modified: head/sys/dev/fdt/fdt_common.h ============================================================================== --- head/sys/dev/fdt/fdt_common.h Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/fdt/fdt_common.h Thu Sep 25 15:02:33 2014 (r272109) @@ -88,7 +88,6 @@ int fdt_get_phyaddr(phandle_t, device_t, int fdt_get_range(phandle_t, int, u_long *, u_long *); int fdt_immr_addr(vm_offset_t); int fdt_regsize(phandle_t, u_long *, u_long *); -int fdt_intr_to_rl(device_t, phandle_t, struct resource_list *, struct fdt_sense_level *); int fdt_is_compatible(phandle_t, const char *); int fdt_is_compatible_strict(phandle_t, const char *); int fdt_is_enabled(phandle_t); Modified: head/sys/dev/fdt/simplebus.c ============================================================================== --- head/sys/dev/fdt/simplebus.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/fdt/simplebus.c Thu Sep 25 15:02:33 2014 (r272109) @@ -247,11 +247,9 @@ simplebus_setup_dinfo(device_t dev, phan { struct simplebus_softc *sc; struct simplebus_devinfo *ndi; - uint32_t *reg, *intr, icells; + uint32_t *reg; uint64_t phys, size; - phandle_t iparent; int i, j, k; - int nintr; int nreg; sc = device_get_softc(dev); @@ -289,34 +287,7 @@ simplebus_setup_dinfo(device_t dev, phan } free(reg, M_OFWPROP); - nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), - (void **)&intr); - if (nintr > 0) { - if (OF_searchencprop(node, "interrupt-parent", &iparent, - sizeof(iparent)) == -1) { - device_printf(dev, "No interrupt-parent found, " - "assuming direct parent\n"); - iparent = OF_parent(node); - } - 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; - } - for (i = 0, k = 0; i < nintr; i += icells, k++) { - intr[i] = ofw_bus_map_intr(dev, iparent, icells, - &intr[i]); - resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i], - intr[i], 1); - } - free(intr, M_OFWPROP); - } + ofw_bus_intr_to_rl(dev, node, &ndi->rl); return (ndi); } Modified: head/sys/dev/ofw/ofw_bus_subr.c ============================================================================== --- head/sys/dev/ofw/ofw_bus_subr.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/ofw/ofw_bus_subr.c Thu Sep 25 15:02:33 2014 (r272109) @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <sys/errno.h> #include <sys/libkern.h> +#include <machine/resource.h> + #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/openfirm.h> @@ -367,3 +369,64 @@ ofw_bus_search_intrmap(void *intr, int i return (0); } +int +ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl) +{ + phandle_t iparent; + uint32_t icells, *intr; + int err, i, irqnum, nintr, rid; + boolean_t extended; + + nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), + (void **)&intr); + if (nintr > 0) { + if (OF_searchencprop(node, "interrupt-parent", &iparent, + sizeof(iparent)) == -1) { + device_printf(dev, "No interrupt-parent found, " + "assuming direct parent\n"); + iparent = OF_parent(node); + } + 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 (0); + extended = true; + } + err = 0; + rid = 0; + for (i = 0; i < nintr; i += icells) { + 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; + } + } + irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]); + resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1); + } + free(intr, M_OFWPROP); + return (err); +} Modified: head/sys/dev/ofw/ofw_bus_subr.h ============================================================================== --- head/sys/dev/ofw/ofw_bus_subr.h Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/ofw/ofw_bus_subr.h Thu Sep 25 15:02:33 2014 (r272109) @@ -72,6 +72,9 @@ int ofw_bus_lookup_imap(phandle_t, struc int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); +/* Routines for parsing device-tree data into resource lists. */ +int ofw_bus_intr_to_rl(device_t, phandle_t, struct resource_list *); + /* Helper to get device status property */ const char *ofw_bus_get_status(device_t dev); int ofw_bus_status_okay(device_t dev); Modified: head/sys/dev/ofw/ofwbus.c ============================================================================== --- head/sys/dev/ofw/ofwbus.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/dev/ofw/ofwbus.c Thu Sep 25 15:02:33 2014 (r272109) @@ -436,11 +436,9 @@ ofwbus_setup_dinfo(device_t dev, phandle struct ofwbus_softc *sc; struct ofwbus_devinfo *ndi; const char *nodename; - uint32_t *reg, *intr, icells; + uint32_t *reg; uint64_t phys, size; - phandle_t iparent; int i, j, rid; - int nintr; int nreg; sc = device_get_softc(dev); @@ -485,35 +483,7 @@ ofwbus_setup_dinfo(device_t dev, phandle } free(reg, M_OFWPROP); - nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), - (void **)&intr); - if (nintr > 0) { - if (OF_searchencprop(node, "interrupt-parent", &iparent, - sizeof(iparent)) == -1) { - device_printf(dev, "No interrupt-parent found, " - "assuming nexus on <%s>\n", nodename); - iparent = 0xffffffff; - } - if (OF_searchencprop(OF_node_from_xref(iparent), - "#interrupt-cells", &icells, sizeof(icells)) == -1) { - device_printf(dev, "Missing #interrupt-cells property, " - "assuming <1> on <%s>\n", nodename); - icells = 1; - } - if (icells < 1 || icells > nintr) { - device_printf(dev, "Invalid #interrupt-cells property " - "value <%d>, assuming <1> on <%s>\n", icells, - nodename); - icells = 1; - } - for (i = 0, rid = 0; i < nintr; i += icells, rid++) { - intr[i] = ofw_bus_map_intr(dev, iparent, icells, - &intr[i]); - resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, rid, intr[i], - intr[i], 1); - } - free(intr, M_OFWPROP); - } + ofw_bus_intr_to_rl(dev, node, &ndi->ndi_rl); return (ndi); } Modified: head/sys/mips/beri/beri_simplebus.c ============================================================================== --- head/sys/mips/beri/beri_simplebus.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/mips/beri/beri_simplebus.c Thu Sep 25 15:02:33 2014 (r272109) @@ -198,7 +198,7 @@ simplebus_attach(device_t dev) continue; } - if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) { + if (ofw_bus_intr_to_rl(dev, dt_child, &di->di_res)) { device_printf(dev, "%s: could not process " "'interrupts' property\n", di->di_ofw.obd_name); resource_list_free(&di->di_res); Modified: head/sys/powerpc/ofw/ofw_pcibus.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pcibus.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/powerpc/ofw/ofw_pcibus.c Thu Sep 25 15:02:33 2014 (r272109) @@ -200,29 +200,8 @@ ofw_pcibus_enum_devtree(device_t dev, u_ * interrupts property, so add that value to the device's * resource list. */ - if (dinfo->opd_dinfo.cfg.intpin == 0) { - ofw_pci_intr_t intr[2]; - phandle_t iparent; - int icells; - - if (OF_getprop(child, "interrupts", &intr, - sizeof(intr)) > 0) { - iparent = 0; - icells = 1; - OF_getprop(child, "interrupt-parent", &iparent, - sizeof(iparent)); - if (iparent != 0) { - OF_getprop(OF_node_from_xref(iparent), - "#interrupt-cells", &icells, - sizeof(icells)); - intr[0] = ofw_bus_map_intr(dev, iparent, - icells, intr); - } - - resource_list_add(&dinfo->opd_dinfo.resources, - SYS_RES_IRQ, 0, intr[0], intr[0], 1); - } - } + if (dinfo->opd_dinfo.cfg.intpin == 0) + ofw_bus_intr_to_rl(dev, node, &dinfo->opd_dinfo.resources); } } Modified: head/sys/powerpc/pseries/vdevice.c ============================================================================== --- head/sys/powerpc/pseries/vdevice.c Thu Sep 25 14:25:38 2014 (r272108) +++ head/sys/powerpc/pseries/vdevice.c Thu Sep 25 15:02:33 2014 (r272109) @@ -128,8 +128,6 @@ vdevice_attach(device_t dev) { phandle_t root, child; device_t cdev; - int icells, i, nintr, *intr; - phandle_t iparent; struct vdevice_devinfo *dinfo; root = ofw_bus_get_node(dev); @@ -144,25 +142,7 @@ vdevice_attach(device_t dev) } resource_list_init(&dinfo->mdi_resources); - if (OF_searchprop(child, "#interrupt-cells", &icells, - sizeof(icells)) <= 0) - icells = 2; - if (OF_getprop(child, "interrupt-parent", &iparent, - sizeof(iparent)) <= 0) - iparent = -1; - nintr = OF_getprop_alloc(child, "interrupts", sizeof(*intr), - (void **)&intr); - if (nintr > 0) { - for (i = 0; i < nintr; i += icells) { - u_int irq = intr[i]; - if (iparent != -1) - irq = ofw_bus_map_intr(dev, iparent, - icells, &intr[i]); - - resource_list_add(&dinfo->mdi_resources, - SYS_RES_IRQ, i, irq, irq, i); - } - } + ofw_bus_intr_to_rl(dev, child, &dinfo->mdi_resources); cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409251502.s8PF2Y5v021266>