Index: head/sys/dev/bhnd/bcma/bcma.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma.c +++ head/sys/dev/bhnd/bcma/bcma.c @@ -194,6 +194,14 @@ return (&dinfo->resources); } +static device_t +bcma_find_hostb_device(device_t dev) +{ + struct bcma_softc *sc = device_get_softc(dev); + + /* This is set (or not) by the concrete bcma driver subclass. */ + return (sc->hostb_dev); +} static int bcma_reset_core(device_t dev, device_t child, uint16_t flags) @@ -471,6 +479,7 @@ DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), /* BHND interface */ + DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device), DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core), DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core), DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count), Index: head/sys/dev/bhnd/bcma/bcma_bhndb.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma_bhndb.c +++ head/sys/dev/bhnd/bcma/bcma_bhndb.c @@ -65,14 +65,16 @@ static int bcma_bhndb_attach(device_t dev) { + struct bcma_softc *sc; const struct bhnd_chipid *cid; struct resource *erom_res; int error; int rid; - cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); + sc = device_get_softc(dev); /* Map the EROM resource and enumerate our children. */ + cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); rid = 0; erom_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr, cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE, @@ -95,6 +97,9 @@ if (error) return (error); + /* Ask our parent bridge to find the corresponding bridge core */ + sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev); + /* Call our superclass' implementation */ return (bcma_attach(dev)); } Index: head/sys/dev/bhnd/bcma/bcmavar.h =================================================================== --- head/sys/dev/bhnd/bcma/bcmavar.h +++ head/sys/dev/bhnd/bcma/bcmavar.h @@ -144,6 +144,7 @@ /** BMCA per-instance state */ struct bcma_softc { struct bhnd_softc bhnd_sc; /**< bhnd state */ + device_t hostb_dev; /**< host bridge core, or NULL */ }; #endif /* _BCMA_BCMAVAR_H_ */ \ No newline at end of file Index: head/sys/dev/bhnd/bhnd.h =================================================================== --- head/sys/dev/bhnd/bhnd.h +++ head/sys/dev/bhnd/bhnd.h @@ -335,8 +335,6 @@ void bhnd_set_default_core_desc(device_t dev); -bool bhnd_bus_generic_is_hostb_device(device_t dev, - device_t child); bool bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child); bool bhnd_bus_generic_is_region_valid(device_t dev, @@ -364,14 +362,14 @@ /** - * Return true if @p dev is serving as a host bridge for its parent bhnd - * bus. + * Return the active host bridge core for the bhnd bus, if any, or NULL if + * not found. * - * @param dev A bhnd bus child device. + * @param dev A bhnd bus device. */ -static inline bool -bhnd_is_hostb_device(device_t dev) { - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), dev)); +static inline device_t +bhnd_find_hostb_device(device_t dev) { + return (BHND_BUS_FIND_HOSTB_DEVICE(dev)); } /** Index: head/sys/dev/bhnd/bhnd.c =================================================================== --- head/sys/dev/bhnd/bhnd.c +++ head/sys/dev/bhnd/bhnd.c @@ -347,7 +347,7 @@ case BHND_DEVCLASS_EROM: case BHND_DEVCLASS_OTHER: case BHND_DEVCLASS_INVALID: - if (bhnd_is_hostb_device(child)) + if (bhnd_find_hostb_device(dev) == child) return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); return (BHND_PROBE_DEFAULT); @@ -676,7 +676,6 @@ DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), - DEVMETHOD(bhnd_bus_is_hostb_device, bhnd_bus_generic_is_hostb_device), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), DEVMETHOD(bhnd_bus_read_nvram_var, bhnd_generic_read_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), Index: head/sys/dev/bhnd/bhnd_bus_if.m =================================================================== --- head/sys/dev/bhnd/bhnd_bus_if.m +++ head/sys/dev/bhnd/bhnd_bus_if.m @@ -55,10 +55,10 @@ panic("bhnd_bus_get_chipid unimplemented"); } - static bool - bhnd_bus_null_is_hostb_device(device_t dev, device_t child) + static device_t + bhnd_bus_null_find_hostb_device(device_t dev) { - panic("bhnd_bus_is_hostb_device unimplemented"); + panic("bhnd_bus_find_hostb_device unimplemented"); } static bool @@ -105,19 +105,16 @@ } /** - * Returns true if @p child is serving as a host bridge for the bhnd - * bus. + * Return the active host bridge core for the bhnd bus, if any. * - * The default implementation will walk the parent device tree until - * the root node is hit, returning false. + * @param dev The bhnd bus device. * - * @param dev The device whose child is being examined. - * @param child The child device. + * @retval device_t if a hostb device exists + * @retval NULL if no hostb device is found. */ -METHOD bool is_hostb_device { +METHOD device_t find_hostb_device { device_t dev; - device_t child; -} DEFAULT bhnd_bus_null_is_hostb_device; +} DEFAULT bhnd_bus_null_find_hostb_device; /** * Return true if the hardware components required by @p child are unpopulated Index: head/sys/dev/bhnd/bhnd_subr.c =================================================================== --- head/sys/dev/bhnd/bhnd_subr.c +++ head/sys/dev/bhnd/bhnd_subr.c @@ -486,7 +486,11 @@ bhnd_device_lookup(device_t dev, const struct bhnd_device *table, size_t entry_size) { - const struct bhnd_device *entry; + const struct bhnd_device *entry; + device_t hostb, parent; + + parent = device_get_parent(dev); + hostb = bhnd_find_hostb_device(parent); for (entry = table; entry->desc != NULL; entry = (const struct bhnd_device *) ((const char *) entry + entry_size)) @@ -496,8 +500,8 @@ continue; /* match device flags */ - if (entry->device_flags & BHND_DF_HOSTB) { - if (!bhnd_is_hostb_device(dev)) + if (entry->device_flags & BHND_DF_HOSTB) { + if (dev != hostb) continue; } @@ -738,24 +742,6 @@ } /** - * Helper function for implementing BHND_BUS_IS_HOSTB_DEVICE(). - * - * If a parent device is available, this implementation delegates the - * request to the BHND_BUS_IS_HOSTB_DEVICE() method on the parent of @p dev. - * - * If no parent device is available (i.e. on a the bus root), false - * is returned. - */ -bool -bhnd_bus_generic_is_hostb_device(device_t dev, device_t child) { - if (device_get_parent(dev) != NULL) - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), - child)); - - return (false); -} - -/** * Helper function for implementing BHND_BUS_IS_HW_DISABLED(). * * If a parent device is available, this implementation delegates the Index: head/sys/dev/bhnd/bhndb/bhndb.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb.c +++ head/sys/dev/bhnd/bhndb/bhndb.c @@ -589,18 +589,12 @@ sc = device_get_softc(dev); hostb = NULL; - /* Fetch the full set of attached devices */ + /* Fetch the full set of bhnd-attached cores */ if ((error = device_get_children(sc->bus_dev, &devs, &ndevs))) return (error); /* Find our host bridge device */ - for (int i = 0; i < ndevs; i++) { - if (bhnd_is_hostb_device(devs[i])) { - hostb = devs[i]; - break; - } - } - + hostb = BHNDB_FIND_HOSTB_DEVICE(dev, child); if (hostb == NULL) { device_printf(sc->dev, "no host bridge core found\n"); error = ENODEV; @@ -950,13 +944,13 @@ /* Otherwise, we treat bridge-capable cores as unpopulated if they're * not the configured host bridge */ if (BHND_DEVCLASS_SUPPORTS_HOSTB(bhnd_core_class(&core))) - return (!BHND_BUS_IS_HOSTB_DEVICE(dev, child)); + return (BHNDB_FIND_HOSTB_DEVICE(dev, sc->bus_dev) != child); /* Otherwise, assume the core is populated */ return (false); } -/* ascending core index comparison used by bhndb_is_hostb_device() */ +/* ascending core index comparison used by bhndb_find_hostb_device() */ static int compare_core_index(const void *lhs, const void *rhs) { @@ -972,7 +966,7 @@ } /** - * Default bhndb(4) implementation of BHND_BUS_IS_HOSTB_DEVICE(). + * Default bhndb(4) implementation of BHND_BUS_FIND_HOSTB_DEVICE(). * * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged * bhnd(4) devices to determine the hostb core: @@ -982,27 +976,19 @@ * - The core must be the first device on the bus with the bridged device * class. * - * @param sc The bridge device state. - * @param cores The table of bridge-enumerated cores. - * @param num_cores The length of @p cores. - * @param core The core to check. + * @param dev The bhndb device + * @param child The requesting bhnd bus. */ -static bool -bhndb_is_hostb_device(device_t dev, device_t child) +static device_t +bhndb_find_hostb_device(device_t dev, device_t child) { struct bhndb_softc *sc; struct bhnd_core_match md; device_t hostb_dev, *devlist; int devcnt, error; - sc = device_get_softc(dev); - /* Requestor must be attached to the bhnd bus */ - if (device_get_parent(child) != sc->bus_dev) - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), - child)); - /* Determine required device class and set up a match descriptor. */ md = (struct bhnd_core_match) { .vendor = BHND_MFGID_BCM, @@ -1011,19 +997,15 @@ .class = sc->bridge_class, .unit = 0 }; - - /* Pre-screen the device before searching over the full device list. */ - if (!bhnd_device_matches(child, &md)) - return (false); /* Must be the absolute first matching device on the bus. */ - if ((error = device_get_children(sc->bus_dev, &devlist, &devcnt))) + if ((error = device_get_children(child, &devlist, &devcnt))) return (false); /* Sort by core index value, ascending */ qsort(devlist, devcnt, sizeof(*devlist), compare_core_index); - /* Find the actual hostb device */ + /* Find the hostb device */ hostb_dev = NULL; for (int i = 0; i < devcnt; i++) { if (bhnd_device_matches(devlist[i], &md)) { @@ -1035,7 +1017,7 @@ /* Clean up */ free(devlist, M_TEMP); - return (child == hostb_dev); + return (hostb_dev); } /** @@ -1922,12 +1904,12 @@ /* BHNDB interface */ DEVMETHOD(bhndb_get_chipid, bhndb_get_chipid), DEVMETHOD(bhndb_init_full_config, bhndb_generic_init_full_config), + DEVMETHOD(bhndb_find_hostb_device, bhndb_find_hostb_device), DEVMETHOD(bhndb_suspend_resource, bhndb_suspend_resource), DEVMETHOD(bhndb_resume_resource, bhndb_resume_resource), /* BHND interface */ DEVMETHOD(bhnd_bus_is_hw_disabled, bhndb_is_hw_disabled), - DEVMETHOD(bhnd_bus_is_hostb_device, bhndb_is_hostb_device), DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), Index: head/sys/dev/bhnd/bhndb/bhndb_if.m =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_if.m +++ head/sys/dev/bhnd/bhndb/bhndb_if.m @@ -62,6 +62,12 @@ panic("bhndb_init_full_config unimplemented"); } + static device_t + bhndb_null_find_hostb_device(device_t dev, device_t child) + { + panic("bhndb_find_hostb_device unimplemented"); + } + static void bhndb_null_suspend_resource(device_t dev, device_t child, int type, struct resource *r) @@ -120,6 +126,17 @@ } DEFAULT bhndb_null_init_full_config; /** + * Locate the active host bridge core for the attached bhnd bus. + * + * @param dev The bridge device. + * @param child The bhnd bus device attached to @p dev. + */ +METHOD device_t find_hostb_device { + device_t dev; + device_t child; +} DEFAULT bhndb_null_find_hostb_device; + +/** * Mark a resource as 'suspended', gauranteeing to the bridge that no * further use of the resource will be made until BHNDB_RESUME_RESOURCE() * is called. Index: head/sys/dev/bhnd/siba/siba.c =================================================================== --- head/sys/dev/bhnd/siba/siba.c +++ head/sys/dev/bhnd/siba/siba.c @@ -216,6 +216,15 @@ return (&dinfo->resources); } +static device_t +siba_find_hostb_device(device_t dev) +{ + struct siba_softc *sc = device_get_softc(dev); + + /* This is set (or not) by the concrete siba driver subclass. */ + return (sc->hostb_dev); +} + static int siba_reset_core(device_t dev, device_t child, uint16_t flags) { @@ -662,6 +671,7 @@ DEVMETHOD(bus_get_resource_list, siba_get_resource_list), /* BHND interface */ + DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), Index: head/sys/dev/bhnd/siba/siba_bhndb.c =================================================================== --- head/sys/dev/bhnd/siba/siba_bhndb.c +++ head/sys/dev/bhnd/siba/siba_bhndb.c @@ -73,9 +73,12 @@ static int siba_bhndb_attach(device_t dev) { + struct siba_softc *sc; const struct bhnd_chipid *chipid; int error; + sc = device_get_softc(dev); + /* Enumerate our children. */ chipid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); if ((error = siba_add_children(dev, chipid))) @@ -87,6 +90,9 @@ if (error) return (error); + /* Ask our parent bridge to find the corresponding bridge core */ + sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev); + /* Call our superclass' implementation */ return (siba_attach(dev)); } Index: head/sys/dev/bhnd/siba/sibavar.h =================================================================== --- head/sys/dev/bhnd/siba/sibavar.h +++ head/sys/dev/bhnd/siba/sibavar.h @@ -145,6 +145,7 @@ /** siba(4) per-instance state */ struct siba_softc { struct bhnd_softc bhnd_sc; /**< bhnd state */ + device_t hostb_dev; /**< host bridge core, or NULL */ }; #endif /* _SIBA_SIBAVAR_H_ */