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) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to