From 63fb0e823653e7b3ca47142f68328ee220965da5 Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Sun, 4 Sep 2016 01:43:54 +0000 Subject: [PATCH] bhndb(4): Skip disabled cores when performing bridge configuration probing. On BCM4321 chipsets, both PCI and PCIe cores are included, with one of the cores potentially left floating. Since the PCI core appears first in the device table, and the PCI profiles appear first in the resource configuration tables, this resulted in incorrectly matching and using the PCI/v1 resource configuration on PCIe devices, rather than the correct PCIe/v1 profile. Approved by: adrian (mentor, implicit) --- sys/dev/bhnd/bhndb/bhnd_bhndb.c | 12 ++++++++++ sys/dev/bhnd/bhndb/bhndb.c | 40 ++++++++++++++++++--------------- sys/dev/bhnd/bhndb/bhndb_if.m | 27 +++++++++++++++++++++- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/sys/dev/bhnd/bhndb/bhnd_bhndb.c b/sys/dev/bhnd/bhndb/bhnd_bhndb.c index 1834f2700e7e..8a9f650bd151 100644 --- a/sys/dev/bhnd/bhndb/bhnd_bhndb.c +++ b/sys/dev/bhnd/bhndb/bhnd_bhndb.c @@ -66,6 +66,17 @@ bhnd_bhndb_get_attach_type(device_t dev, device_t child) return (BHND_ATTACH_ADAPTER); } + +static bool +bhnd_bhndb_is_hw_disabled(device_t dev, device_t child) +{ + struct bhnd_core_info core = bhnd_get_core_info(child); + + /* Delegate to parent bridge */ + return (BHNDB_IS_CORE_DISABLED(device_get_parent(dev), dev, &core)); +} + + static device_t bhnd_bhndb_find_hostb_device(device_t dev) { @@ -112,6 +123,7 @@ bhnd_bhndb_pwrctl_ungate_clock(device_t dev, device_t child, static device_method_t bhnd_bhndb_methods[] = { /* BHND interface */ DEVMETHOD(bhnd_bus_get_attach_type, bhnd_bhndb_get_attach_type), + DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bhndb_is_hw_disabled), DEVMETHOD(bhnd_bus_find_hostb_device, bhnd_bhndb_find_hostb_device), DEVMETHOD(bhnd_bus_read_board_info, bhnd_bhndb_read_board_info), diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 77f98c0028a9..8ce6b839b611 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -85,8 +85,9 @@ static int bhndb_init_full_config(struct bhndb_softc *sc, static struct bhnd_core_info *bhndb_get_bridge_core(struct bhndb_softc *sc); -static bool bhndb_hw_matches(struct bhnd_core_info *cores, - u_int ncores, const struct bhndb_hw *hw); +static bool bhndb_hw_matches(struct bhndb_softc *sc, + struct bhnd_core_info *cores, u_int ncores, + const struct bhndb_hw *hw); static int bhndb_init_region_cfg(struct bhndb_softc *sc, bhnd_erom_t *erom, @@ -212,14 +213,15 @@ bhndb_get_bridge_core(struct bhndb_softc *sc) /** * Return true if @p cores matches the @p hw specification. - * + * + * @param sc BHNDB device state. * @param cores A device table to match against. * @param ncores The number of cores in @p cores. * @param hw The hardware description to be matched against. */ static bool -bhndb_hw_matches(struct bhnd_core_info *cores, u_int ncores, - const struct bhndb_hw *hw) +bhndb_hw_matches(struct bhndb_softc *sc, struct bhnd_core_info *cores, + u_int ncores, const struct bhndb_hw *hw) { for (u_int i = 0; i < hw->num_hw_reqs; i++) { const struct bhnd_core_match *match; @@ -229,7 +231,12 @@ bhndb_hw_matches(struct bhnd_core_info *cores, u_int ncores, found = false; for (u_int d = 0; d < ncores; d++) { - if (!bhnd_core_matches(&cores[d], match)) + struct bhnd_core_info *core = &cores[d]; + + if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core)) + continue; + + if (!bhnd_core_matches(core, match)) continue; found = true; @@ -353,7 +360,7 @@ bhndb_init_region_cfg(struct bhndb_softc *sc, bhnd_erom_t *erom, */ /* ... do not require bridge resources */ - if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, sc->dev, core)) + if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core)) continue; /* ... do not have a priority table entry */ @@ -475,7 +482,7 @@ bhndb_find_hwspec(struct bhndb_softc *sc, struct bhnd_core_info *cores, /* Search for the first matching hardware config. */ hw_table = BHNDB_BUS_GET_HARDWARE_TABLE(sc->parent_dev, sc->dev); for (next = hw_table; next->hw_reqs != NULL; next++) { - if (!bhndb_hw_matches(cores, ncores, next)) + if (!bhndb_hw_matches(sc, cores, ncores, next)) continue; /* Found */ @@ -1166,30 +1173,27 @@ bhndb_get_chipid(device_t dev, device_t child) return (&sc->chipid); } - /** - * Default implementation of BHND_BUS_IS_HW_DISABLED(). + * Default implementation of BHNDB_IS_CORE_DISABLED(). */ static bool -bhndb_is_hw_disabled(device_t dev, device_t child) +bhndb_is_core_disabled(device_t dev, device_t child, + struct bhnd_core_info *core) { struct bhndb_softc *sc; struct bhnd_core_info *bridge_core; - struct bhnd_core_info core; sc = device_get_softc(dev); - core = bhnd_get_core_info(child); - /* Try to defer to the bhndb bus parent */ - if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, &core)) + if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, core)) return (true); /* Otherwise, we treat bridge-capable cores as unpopulated if they're * not the configured host bridge */ bridge_core = bhndb_get_bridge_core(sc); - if (BHND_DEVCLASS_SUPPORTS_HOSTB(bhnd_core_class(&core))) - return (!bhnd_cores_equal(&core, bridge_core)); + if (BHND_DEVCLASS_SUPPORTS_HOSTB(bhnd_core_class(core))) + return (!bhnd_cores_equal(core, bridge_core)); /* Assume the core is populated */ return (false); @@ -2153,12 +2157,12 @@ static device_method_t bhndb_methods[] = { /* BHNDB interface */ DEVMETHOD(bhndb_get_chipid, bhndb_get_chipid), + DEVMETHOD(bhndb_is_core_disabled, bhndb_is_core_disabled), DEVMETHOD(bhndb_get_hostb_core, bhndb_get_hostb_core), 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_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), diff --git a/sys/dev/bhnd/bhndb/bhndb_if.m b/sys/dev/bhnd/bhndb/bhndb_if.m index 093bfc626143..3f9ebd237b2c 100644 --- a/sys/dev/bhnd/bhndb/bhndb_if.m +++ b/sys/dev/bhnd/bhndb/bhndb_if.m @@ -61,7 +61,14 @@ CODE { { panic("bhndb_populate_board_info unimplemented"); } - + + static int + bhndb_null_is_core_disabled(device_t dev, device_t child, + struct bhnd_core_info *core) + { + panic("bhndb_is_core_disabled unimplemented"); + } + static int bhndb_null_get_hostb_core(device_t dev, device_t child, struct bhnd_core_info *core) @@ -117,6 +124,24 @@ METHOD int populate_board_info { struct bhnd_board_info *info; } DEFAULT bhndb_null_populate_board_info; +/** + * Return true if the hardware required by @p core is unpopulated or + * otherwise unusable. + * + * In some cases, the core's pins may be left floating, or the hardware + * may otherwise be non-functional; this method allows the parent device + * to explicitly specify whether @p core should be disabled. + * + * @param dev The parent device of @p child. + * @param child The attached bhnd device. + * @param core A core discovered on @p child. + */ +METHOD bool is_core_disabled { + device_t dev; + device_t child; + struct bhnd_core_info *core; +} DEFAULT bhndb_null_is_core_disabled; + /** * Get the host bridge core info for the attached bhnd bus. *