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, ®,
- 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,
+ ®, 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, ®, 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-all
mailing list