Index: dev/ofw/ofw_bus_subr.c =================================================================== --- dev/ofw/ofw_bus_subr.c (revision 255388) +++ dev/ofw/ofw_bus_subr.c (working copy) @@ -300,7 +300,7 @@ i = imapsz; while (i > 0) { bcopy(mptr + physsz + intrsz, &parent, sizeof(parent)); - if (OF_searchprop(parent, "#interrupt-cells", + if (OF_searchprop(OF_xref_phandle(parent), "#interrupt-cells", &pintrsz, sizeof(pintrsz)) == -1) pintrsz = 1; /* default */ pintrsz *= sizeof(pcell_t); @@ -307,7 +307,10 @@ /* Compute the map stride size. */ tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz; - KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map")); + KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map " + "(imapsz: %d, tsz: %d, physsz: %d, intrsz: %d, " + "sizeof(phandle_t): %zd, pintrsz: %d)", imapsz, tsz, + physsz, intrsz, sizeof(phandle_t), pintrsz)); /* * XXX: Apple hardware uses a second cell to set information Index: dev/ofw/openfirm.c =================================================================== --- dev/ofw/openfirm.c (revision 255388) +++ dev/ofw/openfirm.c (working copy) @@ -386,6 +386,47 @@ return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len)); } +/* Look up effective phandle (see FDT/PAPR spec) */ +static phandle_t +OF_child_xref_phandle(phandle_t parent, phandle_t xref) +{ + /* + * Recursively descend from parent, looking for a node with a property + * named either "phandle", "ibm,phandle", or "linux,phandle" that + * matches the xref we are looking for. + */ + phandle_t child, rxref; + + for (child = OF_child(parent); child != 0; child = OF_peer(child)) { + rxref = OF_child_xref_phandle(child, xref); + if (rxref != -1) + return (rxref); + + if (OF_getprop(child, "phandle", &rxref, sizeof(rxref)) == -1 && + OF_getprop(child, "ibm,phandle", &rxref, + sizeof(rxref)) == -1 && OF_getprop(child, + "linux,phandle", &rxref, sizeof(rxref)) == -1) + continue; + + if (rxref == xref) + return (child); + } + + return (-1); +} + +phandle_t +OF_xref_phandle(phandle_t xref) +{ + phandle_t node; + + node = OF_child_xref_phandle(OF_peer(0), xref); + if (node == -1) + return (xref); + + return (node); +} + /* Call the method in the scope of a given instance. */ int OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns, Index: dev/ofw/openfirm.h =================================================================== --- dev/ofw/openfirm.h (revision 255388) +++ dev/ofw/openfirm.h (working copy) @@ -118,6 +118,14 @@ phandle_t OF_finddevice(const char *path); ssize_t OF_package_to_path(phandle_t node, char *buf, size_t len); +/* + * Some OF implementations (IBM, FDT) have a concept of effective phandles + * used for device-tree cross-references. Given one of these, returns the + * real phandle. If one can't be found (or running on OF implementations + * without this property), returns its input. + */ +phandle_t OF_xref_phandle(phandle_t xref); + /* Device I/O functions */ ihandle_t OF_open(const char *path); void OF_close(ihandle_t instance); Index: powerpc/ofw/ofw_pcibus.c =================================================================== --- powerpc/ofw/ofw_pcibus.c (revision 255388) +++ powerpc/ofw/ofw_pcibus.c (working copy) @@ -101,6 +101,9 @@ MODULE_VERSION(ofw_pcibus, 1); MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); +static int ofw_devices_only=0; +TUNABLE_INT("hw.pci.ofw_devices_only", &ofw_devices_only); + static int ofw_pcibus_probe(device_t dev) { @@ -137,7 +140,8 @@ * functions on multi-function cards. */ - ofw_pcibus_enum_bus(dev, domain, busno); + if (!ofw_devices_only) + ofw_pcibus_enum_bus(dev, domain, busno); return (bus_generic_attach(dev)); } @@ -210,11 +214,12 @@ icells = 1; OF_getprop(child, "interrupt-parent", &iparent, sizeof(iparent)); - OF_getprop(iparent, "#interrupt-cells", &icells, - sizeof(icells)); - - if (iparent != 0) + if (iparent != 0) { + OF_getprop(OF_xref_phandle(iparent), + "#interrupt-cells", &icells, + sizeof(icells)); intr[0] = MAP_IRQ(iparent, intr[0]); + } if (iparent != 0 && icells > 1) { powerpc_config_intr(intr[0],