Author: nwhitehorn
Date: Sat Jan  3 19:38:47 2009
New Revision: 186728
URL: http://svn.freebsd.org/changeset/base/186728

Log:
  Fix the OFW interrupt map parser to use its own idea of the number of 
interrupt
  cells in the map, instead of using a value passed to it and then panicing if 
it
  disagrees. This fixes interrupt map parsing for PCI bridges on some Apple
  Uninorth PCI controllers.
  
  Reported by:  marcel
  Tested on:    G4 iBook, Sun Ultra 5

Modified:
  head/sys/dev/ofw/ofw_bus_subr.c
  head/sys/dev/ofw/openfirm.c
  head/sys/dev/ofw/openfirm.h
  head/sys/powerpc/powermac/grackle.c
  head/sys/powerpc/powermac/gracklevar.h
  head/sys/powerpc/powermac/macio.c
  head/sys/powerpc/powermac/uninorth.c
  head/sys/powerpc/powermac/uninorthvar.h

Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c     Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/dev/ofw/ofw_bus_subr.c     Sat Jan  3 19:38:47 2009        
(r186728)
@@ -146,18 +146,6 @@ ofw_bus_gen_get_type(device_t bus, devic
        return (obd->obd_type);
 }
 
-static int
-ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
-{
-       int rv;
-
-       for (; node != 0; node = OF_parent(node)) {
-               if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
-                       return (rv);
-       }
-       return (-1);
-}
-
 void
 ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
 {
@@ -249,17 +237,16 @@ ofw_bus_search_intrmap(void *intr, int i
 
        mptr = imap;
        i = imapsz;
-       tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
        while (i > 0) {
-               KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
                bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
-               if (ofw_bus_searchprop(parent, "#interrupt-cells",
+               if (OF_searchprop(parent, "#interrupt-cells",
                    &pintrsz, sizeof(pintrsz)) == -1)
                        pintrsz = 1;    /* default */
                pintrsz *= sizeof(pcell_t);
-               if (pintrsz != rintrsz)
-                       panic("ofw_bus_search_intrmap: expected interrupt cell "
-                           "size incorrect: %d > %d", rintrsz, pintrsz);
+
+               /* Compute the map stride size */
+               tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz;
+               KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
        
                /*
                 * XXX: Apple hardware uses a second cell to set information

Modified: head/sys/dev/ofw/openfirm.c
==============================================================================
--- head/sys/dev/ofw/openfirm.c Sat Jan  3 18:51:49 2009        (r186727)
+++ head/sys/dev/ofw/openfirm.c Sat Jan  3 19:38:47 2009        (r186728)
@@ -220,6 +220,23 @@ OF_getprop(phandle_t package, const char
 }
 
 /*
+ * Resursively search the node and its parent for the given property, working
+ * downward from the node to the device tree root.  Returns the value of the
+ * first match.
+ */
+ssize_t
+OF_searchprop(phandle_t node, char *propname, void *buf, size_t len)
+{
+       ssize_t rv;
+
+       for (; node != 0; node = OF_parent(node)) {
+               if ((rv = OF_getprop(node, propname, buf, len)) != -1)
+                       return (rv);
+       }
+       return (-1);
+}
+
+/*
  * Store the value of a property of a package into newly allocated memory
  * (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a
  * single element, the number of elements is return in number.

Modified: head/sys/dev/ofw/openfirm.h
==============================================================================
--- head/sys/dev/ofw/openfirm.h Sat Jan  3 18:51:49 2009        (r186727)
+++ head/sys/dev/ofw/openfirm.h Sat Jan  3 19:38:47 2009        (r186728)
@@ -104,6 +104,8 @@ phandle_t   OF_parent(phandle_t node);
 ssize_t                OF_getproplen(phandle_t node, const char *propname);
 ssize_t                OF_getprop(phandle_t node, const char *propname, void 
*buf,
                    size_t len);
+ssize_t                OF_searchprop(phandle_t node, char *propname, void *buf,
+                   size_t len);
 ssize_t                OF_getprop_alloc(phandle_t node, const char *propname,
                    int elsz, void **buf);
 int            OF_nextprop(phandle_t node, const char *propname, char *buf,

Modified: head/sys/powerpc/powermac/grackle.c
==============================================================================
--- head/sys/powerpc/powermac/grackle.c Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/powerpc/powermac/grackle.c Sat Jan  3 19:38:47 2009        
(r186728)
@@ -165,7 +165,7 @@ static int
 grackle_attach(device_t dev)
 {
        struct          grackle_softc *sc;
-       phandle_t       node, iparent;
+       phandle_t       node;
        u_int32_t       busrange[2];
        struct          grackle_range *rp, *io, *mem[2];
        int             nmem, i, error;
@@ -254,14 +254,6 @@ grackle_attach(device_t dev)
 
        ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
 
-       /* We need the number of interrupt cells to read the imap */
-       if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) <= 0)
-               iparent = node;
-
-       if (OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells, 
-           sizeof(sc->sc_icells)) <= 0)
-               sc->sc_icells = 1;
-
        device_add_child(dev, "pci", device_get_unit(dev));
        return (bus_generic_attach(dev));
 }
@@ -348,15 +340,14 @@ grackle_route_interrupt(device_t bus, de
 {
        struct grackle_softc *sc;
        struct ofw_pci_register reg;
-       uint32_t pintr, mintr[2];
+       uint32_t pintr, mintr;
        uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
        sc = device_get_softc(bus);
        pintr = pin;
        if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
-           sizeof(reg), &pintr, sizeof(pintr), &mintr, 
-           sizeof(mintr[0])*sc->sc_icells, maskbuf))
-               return (mintr[0]);
+           sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+               return (mintr);
 
        /* Maybe it's a real interrupt, not an intpin */
        if (pin > 4)

Modified: head/sys/powerpc/powermac/gracklevar.h
==============================================================================
--- head/sys/powerpc/powermac/gracklevar.h      Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/powerpc/powermac/gracklevar.h      Sat Jan  3 19:38:47 2009        
(r186728)
@@ -52,7 +52,6 @@ struct grackle_softc {
        struct                  rman sc_mem_rman;
        bus_space_tag_t         sc_memt;
        bus_dma_tag_t           sc_dmat;
-       int                     sc_icells;
 
        struct ofw_bus_iinfo    sc_pci_iinfo;
 };

Modified: head/sys/powerpc/powermac/macio.c
==============================================================================
--- head/sys/powerpc/powermac/macio.c   Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/powerpc/powermac/macio.c   Sat Jan  3 19:38:47 2009        
(r186728)
@@ -185,7 +185,6 @@ macio_add_intr(phandle_t devnode, struct
 {
        int     *intr;
        int     i, nintr;
-       phandle_t iparent;
        int     icells;
 
        if (dinfo->mdi_ninterrupts >= 6) {
@@ -193,10 +192,9 @@ macio_add_intr(phandle_t devnode, struct
                return;
        }
 
-       icells = 1;
-       
-       if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent)) 
== sizeof(iparent))
-               OF_getprop(iparent, "#interrupt-cells", &icells, 
sizeof(icells));
+       if (OF_searchprop(devnode, "#interrupt-cells", &icells, sizeof(icells))
+           <= 0)
+               icells = 1;
 
        nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr), 
                (void **)&intr);

Modified: head/sys/powerpc/powermac/uninorth.c
==============================================================================
--- head/sys/powerpc/powermac/uninorth.c        Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/powerpc/powermac/uninorth.c        Sat Jan  3 19:38:47 2009        
(r186728)
@@ -164,7 +164,7 @@ uninorth_attach(device_t dev)
 {
        struct          uninorth_softc *sc;
        const char      *compatible;
-       phandle_t       node, child, iparent;
+       phandle_t       node, child;
        u_int32_t       reg[2], busrange[2];
        struct          uninorth_range *rp, *io, *mem[2];
        int             nmem, i, error;
@@ -296,12 +296,6 @@ uninorth_attach(device_t dev)
 
        ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
 
-       /* We need the number of interrupt cells to read the imap */
-       sc->sc_icells = 2;
-       if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) > 0)
-               OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells, 
-                   sizeof(sc->sc_icells));
-
        device_add_child(dev, "pci", device_get_unit(dev));
        return (bus_generic_attach(dev));
 }
@@ -370,15 +364,14 @@ uninorth_route_interrupt(device_t bus, d
 {
        struct uninorth_softc *sc;
        struct ofw_pci_register reg;
-       uint32_t pintr, mintr[2];
+       uint32_t pintr, mintr;
        uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
        sc = device_get_softc(bus);
        pintr = pin;
        if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
-           sizeof(reg), &pintr, sizeof(pintr), mintr, 
-           sizeof(mintr[0])*sc->sc_icells, maskbuf))
-               return (mintr[0]);
+           sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+               return (mintr);
 
        /* Maybe it's a real interrupt, not an intpin */
        if (pin > 4)

Modified: head/sys/powerpc/powermac/uninorthvar.h
==============================================================================
--- head/sys/powerpc/powermac/uninorthvar.h     Sat Jan  3 18:51:49 2009        
(r186727)
+++ head/sys/powerpc/powermac/uninorthvar.h     Sat Jan  3 19:38:47 2009        
(r186728)
@@ -64,7 +64,6 @@ struct uninorth_softc {
        struct ofw_bus_iinfo    sc_pci_iinfo;
 
        int                     sc_u3;
-       int                     sc_icells;
 };
 
 struct unin_chip_softc {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to