Date: Sat, 3 Jan 2009 19:38:47 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r186728 - in head/sys: dev/ofw powerpc/powermac Message-ID: <200901031938.n03Jcl4o035993@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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, ®, - 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, ®, - 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 {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901031938.n03Jcl4o035993>