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)
This commit is contained in:
Landon J. Fuller 2016-09-04 01:43:54 +00:00
parent f32befd1a2
commit 63fb0e8236
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=305374
3 changed files with 60 additions and 19 deletions

View File

@ -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),

View File

@ -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),

View File

@ -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.
*