svn commit: r261351 - in head/sys: arm/arm arm/mv dev/fdt dev/ofw powerpc/ofw powerpc/powerpc powerpc/pseries

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sat Feb 1 17:17:38 UTC 2014


Author: nwhitehorn
Date: Sat Feb  1 17:17:35 2014
New Revision: 261351
URL: http://svnweb.freebsd.org/changeset/base/261351

Log:
  Open Firmware interrupt specifiers can consist of arbitrary-length byte
  strings and include arbitrary information (IRQ line/domain/sense). When the
  ofw_bus_map_intr() API was introduced, it assumed that, as on most systems,
  these were either 1 cell, containing an interrupt line, or 2, containing
  a line number plus a sense code. It turns out a non-negligible number of
  ARM systems use 3 (or even 4!) cells for interrupts, so make this more
  general.

Modified:
  head/sys/arm/arm/nexus.c
  head/sys/arm/mv/mv_pci.c
  head/sys/dev/fdt/fdt_common.c
  head/sys/dev/ofw/ofw_bus.h
  head/sys/dev/ofw/ofw_bus_if.m
  head/sys/dev/ofw/ofw_nexus.c
  head/sys/powerpc/ofw/ofw_pci.c
  head/sys/powerpc/ofw/ofw_pcib_pci.c
  head/sys/powerpc/ofw/ofw_pcibus.c
  head/sys/powerpc/powerpc/nexus.c
  head/sys/powerpc/pseries/vdevice.c

Modified: head/sys/arm/arm/nexus.c
==============================================================================
--- head/sys/arm/arm/nexus.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/arm/arm/nexus.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -98,7 +98,7 @@ static int nexus_teardown_intr(device_t,
 
 #ifdef FDT
 static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
-    int irq);
+    int icells, pcell_t *intr);
 #endif
 
 static device_method_t nexus_methods[] = {
@@ -339,15 +339,16 @@ nexus_deactivate_resource(device_t bus, 
 
 #ifdef FDT
 static int
-nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+    pcell_t *intr)
 {
-	pcell_t intr[2];
 	fdt_pic_decode_t intr_decode;
 	phandle_t intr_offset;
 	int i, rv, interrupt, trig, pol;
 
 	intr_offset = OF_xref_phandle(iparent);
-	intr[0] = cpu_to_fdt32(irq);
+	for (i = 0; i < icells; i++)
+		intr[i] = cpu_to_fdt32(intr[i]);
 
 	for (i = 0; fdt_pic_table[i] != NULL; i++) {
 		intr_decode = fdt_pic_table[i];
@@ -355,13 +356,13 @@ nexus_ofw_map_intr(device_t dev, device_
 
 		if (rv == 0) {
 			/* This was recognized as our PIC and decoded. */
-			interrupt = FDT_MAP_IRQ(intr_parent, interrupt);
+			interrupt = FDT_MAP_IRQ(intr_parent, intr[0]);
 			return (interrupt);
 		}
 	}
 
 	/* Not in table, so guess */
-	interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr));
+	interrupt = FDT_MAP_IRQ(intr_parent, intr[0]);
 
 	return (interrupt);
 }

Modified: head/sys/arm/mv/mv_pci.c
==============================================================================
--- head/sys/arm/mv/mv_pci.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/arm/mv/mv_pci.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -1050,7 +1050,8 @@ mv_pcib_route_interrupt(device_t bus, de
 {
 	struct mv_pcib_softc *sc;
 	struct ofw_pci_register reg;
-	uint32_t pintr, mintr;
+	uint32_t pintr, mintr[4];
+	int icells;
 	phandle_t iparent;
 
 	sc = device_get_softc(bus);
@@ -1062,10 +1063,11 @@ mv_pcib_route_interrupt(device_t bus, de
 	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
 	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
 
-	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
-	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
-	    &iparent))
-		return (ofw_bus_map_intr(dev, iparent, mintr));
+	icells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
+	    &reg, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr),
+	    &iparent);
+	if (icells > 0)
+		return (ofw_bus_map_intr(dev, iparent, icells, mintr));
 
 	/* Maybe it's a real interrupt, not an intpin */
 	if (pin > 4)

Modified: head/sys/dev/fdt/fdt_common.c
==============================================================================
--- head/sys/dev/fdt/fdt_common.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/dev/fdt/fdt_common.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -501,11 +501,9 @@ fdt_intr_to_rl(device_t dev, phandle_t n
 			icells = 1;
 		}
 		for (i = 0, k = 0; i < nintr; i += icells, k++) {
-			intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);
+			intr[i] = ofw_bus_map_intr(dev, iparent, icells, intr);
 			resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i],
 			    1);
-			if (icells > 1)
-				ofw_bus_config_intr(dev, intr[i], intr[i+1]);
 		}
 		free(intr, M_OFWPROP);
 	}

Modified: head/sys/dev/ofw/ofw_bus.h
==============================================================================
--- head/sys/dev/ofw/ofw_bus.h	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/dev/ofw/ofw_bus.h	Sat Feb  1 17:17:35 2014	(r261351)
@@ -71,15 +71,9 @@ ofw_bus_get_type(device_t dev)
 }
 
 static __inline int
-ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq)
+ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr)
 {
-	return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq));
-}
-
-static __inline int
-ofw_bus_config_intr(device_t dev, int irq, int sense)
-{
-	return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense));
+	return (OFW_BUS_MAP_INTR(dev, dev, iparent, icells, intr));
 }
 
 #endif /* !_DEV_OFW_OFW_BUS_H_ */

Modified: head/sys/dev/ofw/ofw_bus_if.m
==============================================================================
--- head/sys/dev/ofw/ofw_bus_if.m	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/dev/ofw/ofw_bus_if.m	Sat Feb  1 17:17:35 2014	(r261351)
@@ -57,7 +57,6 @@ CODE {
 	static ofw_bus_get_node_t ofw_bus_default_get_node;
 	static ofw_bus_get_type_t ofw_bus_default_get_type;
 	static ofw_bus_map_intr_t ofw_bus_default_map_intr;
-	static ofw_bus_config_intr_t ofw_bus_default_config_intr;
 
 	static const struct ofw_bus_devinfo *
 	ofw_bus_default_get_devinfo(device_t bus, device_t dev)
@@ -103,27 +102,15 @@ CODE {
 
 	int
 	ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent,
-	    int irq)
+	    int icells, pcell_t *interrupt)
 	{
 		/* Propagate up the bus hierarchy until someone handles it. */	
 		if (device_get_parent(bus) != NULL)
 			return OFW_BUS_MAP_INTR(device_get_parent(bus), dev,
-			    iparent, irq);
+			    iparent, icells, interrupt);
 
 		/* If that fails, then assume a one-domain system */
-		return (irq);
-	}
-
-	int
-	ofw_bus_default_config_intr(device_t bus, device_t dev, int irq,
-	    int sense)
-	{
-		/* Propagate up the bus hierarchy until someone handles it. */	
-		if (device_get_parent(bus) != NULL)
-			return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev,
-			    irq, sense);
-
-		return (ENXIO);
+		return (interrupt[0]);
 	}
 };
 
@@ -172,20 +159,14 @@ METHOD const char * get_type {
 } DEFAULT ofw_bus_default_get_type;
 
 # Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number.
+# If the interrupt encoding includes a sense field, the interrupt sense will
+# also be configured.
 METHOD int map_intr {
 	device_t bus;
 	device_t dev;
 	phandle_t iparent;
-	int irq;
+	int icells;
+	pcell_t *interrupt;
 } DEFAULT ofw_bus_default_map_intr;
 
-# Configure an interrupt using the device-tree encoded sense key (the second
-# value in the interrupts property if interrupt-cells is 2). IRQ should be
-# encoded as from ofw_bus_map_intr().
-METHOD int config_intr {
-	device_t bus;
-	device_t dev;
-	int irq;
-	int sense;
-} DEFAULT ofw_bus_default_config_intr;
 

Modified: head/sys/dev/ofw/ofw_nexus.c
==============================================================================
--- head/sys/dev/ofw/ofw_nexus.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/dev/ofw/ofw_nexus.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -467,11 +467,10 @@ nexus_setup_dinfo(device_t dev, phandle_
 		OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
 		    &icells, sizeof(icells));
 		for (i = 0; i < nintr; i+= icells) {
-			intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);
+			intr[i] = ofw_bus_map_intr(dev, iparent, icells,
+			    &intr[i]);
 			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
 			    intr[i], 1);
-			if (icells > 1)
-				ofw_bus_config_intr(dev, intr[i], intr[i+1]);
 		}
 		free(intr, M_OFWPROP);
 	}

Modified: head/sys/powerpc/ofw/ofw_pci.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pci.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/powerpc/ofw/ofw_pci.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -273,9 +273,7 @@ ofw_pci_route_interrupt(device_t bus, de
 	    &sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
 	    mintr, sizeof(mintr), &iparent);
 	if (intrcells) {
-		pintr = ofw_bus_map_intr(dev, iparent, mintr[0]);
-		if (intrcells == 2)
-			ofw_bus_config_intr(dev, pintr, mintr[1]);
+		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
 		return (pintr);
 	}
 

Modified: head/sys/powerpc/ofw/ofw_pcib_pci.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcib_pci.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/powerpc/ofw/ofw_pcib_pci.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -158,10 +158,8 @@ ofw_pcib_pci_route_interrupt(device_t br
 			 * it again on higher levels - that causes problems
 			 * in some cases, and never seems to be required.
 			 */
-			mintr[0] = ofw_bus_map_intr(dev, iparent, mintr[0]);
-			if (intrcells == 2)
-				ofw_bus_config_intr(dev, mintr[0], mintr[1]);
-			
+			mintr[0] = ofw_bus_map_intr(dev, iparent, intrcells,
+			    mintr);
 			return (mintr[0]);
 		}
 	} else if (intpin >= 1 && intpin <= 4) {

Modified: head/sys/powerpc/ofw/ofw_pcibus.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcibus.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/powerpc/ofw/ofw_pcibus.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -216,13 +216,9 @@ ofw_pcibus_enum_devtree(device_t dev, u_
 					    "#interrupt-cells", &icells,
 					    sizeof(icells));
 					intr[0] = ofw_bus_map_intr(dev, iparent,
-					    intr[0]);
+					    icells, intr);
 				}
 
-				if (iparent != 0 && icells > 1)
-					ofw_bus_config_intr(dev, intr[0],
-					    intr[1]);
-
 				resource_list_add(&dinfo->opd_dinfo.resources,
 				    SYS_RES_IRQ, 0, intr[0], intr[0], 1);
 			}
@@ -309,18 +305,18 @@ ofw_pcibus_child_pnpinfo_str_method(devi
 static int
 ofw_pcibus_assign_interrupt(device_t dev, device_t child)
 {
-	ofw_pci_intr_t intr;
+	ofw_pci_intr_t intr[2];
 	phandle_t node, iparent;
-	int isz;
+	int isz, icells;
 
 	node = ofw_bus_get_node(child);
 
 	if (node == -1) {
 		/* Non-firmware enumerated child, use standard routing */
 	
-		intr = pci_get_intpin(child);
+		intr[0] = pci_get_intpin(child);
 		return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, 
-		    intr));
+		    intr[0]));
 	}
 	
 	/*
@@ -331,24 +327,28 @@ ofw_pcibus_assign_interrupt(device_t dev
 	iparent = -1;
 	if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0)
 		iparent = -1;
+	icells = 1;
+	if (iparent != -1)
+		OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells",
+		    &icells, sizeof(icells));
 	
 	/*
 	 * Any AAPL,interrupts property gets priority and is
 	 * fully specified (i.e. does not need routing)
 	 */
 
-	isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
-	if (isz == sizeof(intr))
-		return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent,
-		    intr));
+	isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr));
+	if (isz == sizeof(intr[0])*icells)
+		return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev,
+		    iparent, icells, intr));
 
-	isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
-	if (isz == sizeof(intr)) {
+	isz = OF_getprop(node, "interrupts", intr, sizeof(intr));
+	if (isz == sizeof(intr[0])*icells) {
 		if (iparent != -1)
-			intr = ofw_bus_map_intr(dev, iparent, intr);
+			intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr);
 	} else {
 		/* No property: our best guess is the intpin. */
-		intr = pci_get_intpin(child);
+		intr[0] = pci_get_intpin(child);
 	}
 	
 	/*
@@ -361,7 +361,7 @@ ofw_pcibus_assign_interrupt(device_t dev
 	 * will always use the route_interrupt method, and treat exceptions
 	 * on the level they become apparent.
 	 */
-	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0]));
 }
 
 static const struct ofw_bus_devinfo *

Modified: head/sys/powerpc/powerpc/nexus.c
==============================================================================
--- head/sys/powerpc/powerpc/nexus.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/powerpc/powerpc/nexus.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -75,7 +75,6 @@ static bus_bind_intr_t nexus_bind_intr;
 #endif
 static bus_config_intr_t nexus_config_intr;
 static ofw_bus_map_intr_t nexus_ofw_map_intr;
-static ofw_bus_config_intr_t nexus_ofw_config_intr;
 
 static device_method_t nexus_methods[] = {
 	/* Bus interface */
@@ -90,7 +89,6 @@ static device_method_t nexus_methods[] =
 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_map_intr,	nexus_ofw_map_intr),
-	DEVMETHOD(ofw_bus_config_intr,	nexus_ofw_config_intr),
 
 	DEVMETHOD_END
 };
@@ -157,19 +155,16 @@ nexus_config_intr(device_t dev, int irq,
 } 
 
 static int
-nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+    pcell_t *irq)
 {
-	return (MAP_IRQ(iparent, irq));
+	u_int intr = MAP_IRQ(iparent, irq[0]);
+	if (icells > 1)
+		powerpc_fw_config_intr(irq[0], irq[1]);
+	return (intr);
 }
 
 static int
-nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense)
-{
- 
-	return (powerpc_fw_config_intr(irq, sense));
-} 
-
-static int
 nexus_activate_resource(device_t bus __unused, device_t child __unused,
     int type, int rid __unused, struct resource *r)
 {

Modified: head/sys/powerpc/pseries/vdevice.c
==============================================================================
--- head/sys/powerpc/pseries/vdevice.c	Sat Feb  1 12:33:58 2014	(r261350)
+++ head/sys/powerpc/pseries/vdevice.c	Sat Feb  1 17:17:35 2014	(r261351)
@@ -157,7 +157,7 @@ vdevice_attach(device_t dev) 
 				u_int irq = intr[i];
 				if (iparent != -1)
 					irq = ofw_bus_map_intr(dev, iparent,
-					    intr[i]);
+					    icells, &intr[i]);
 
 				resource_list_add(&dinfo->mdi_resources,
 				    SYS_RES_IRQ, i, irq, irq, i);


More information about the svn-src-head mailing list