svn commit: r186728 - in head/sys: dev/ofw powerpc/powermac

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sat Jan 3 11:38:48 PST 2009


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 {


More information about the svn-src-head mailing list