[bhnd] Replace is_hostb_device() with a more general find_hostb_device()
This allows bus children to query for the host bridge device, rather than having to iterate over all attached devices. Submitted by: Landon Fuller <landonf@landonf.org> Differential Revision: https://reviews.freebsd.org/D6193
This commit is contained in:
parent
7206c4fc60
commit
d935257080
@ -194,6 +194,14 @@ bcma_get_resource_list(device_t dev, device_t child)
|
||||
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 @@ static device_method_t bcma_methods[] = {
|
||||
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),
|
||||
|
@ -65,14 +65,16 @@ bcma_bhndb_probe(device_t dev)
|
||||
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 @@ bcma_bhndb_attach(device_t dev)
|
||||
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));
|
||||
}
|
||||
|
@ -144,6 +144,7 @@ struct bcma_devinfo {
|
||||
/** 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_ */
|
@ -347,7 +347,7 @@ bhnd_generic_get_probe_order(device_t dev, device_t child)
|
||||
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 @@ static device_method_t bhnd_methods[] = {
|
||||
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),
|
||||
|
@ -335,8 +335,6 @@ void bhnd_set_custom_core_desc(device_t dev,
|
||||
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 @@ int bhnd_bus_generic_deactivate_resource (device_t dev,
|
||||
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,10 +55,10 @@ CODE {
|
||||
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 @@ CODE {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -486,7 +486,11 @@ const struct bhnd_device *
|
||||
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 @@ bhnd_device_lookup(device_t dev, const struct bhnd_device *table,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -737,24 +741,6 @@ bhnd_set_default_core_desc(device_t dev)
|
||||
bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*
|
||||
|
@ -589,18 +589,12 @@ bhndb_generic_init_full_config(device_t dev, device_t child,
|
||||
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 @@ bhndb_is_hw_disabled(device_t dev, device_t child) {
|
||||
/* 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 @@ compare_core_index(const void *lhs, const void *rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ compare_core_index(const void *lhs, const void *rhs)
|
||||
* - 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 @@ bhndb_is_hostb_device(device_t dev, device_t child)
|
||||
.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 @@ bhndb_is_hostb_device(device_t dev, device_t child)
|
||||
/* Clean up */
|
||||
free(devlist, M_TEMP);
|
||||
|
||||
return (child == hostb_dev);
|
||||
return (hostb_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1922,12 +1904,12 @@ static device_method_t bhndb_methods[] = {
|
||||
/* 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),
|
||||
|
@ -62,6 +62,12 @@ CODE {
|
||||
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)
|
||||
@ -119,6 +125,17 @@ METHOD int init_full_config {
|
||||
const struct bhndb_hw_priority *priority_table;
|
||||
} 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()
|
||||
|
@ -216,6 +216,15 @@ siba_get_resource_list(device_t dev, device_t child)
|
||||
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 @@ static device_method_t siba_methods[] = {
|
||||
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),
|
||||
|
@ -73,9 +73,12 @@ siba_bhndb_probe(device_t dev)
|
||||
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 @@ siba_bhndb_attach(device_t dev)
|
||||
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));
|
||||
}
|
||||
|
@ -145,6 +145,7 @@ struct siba_devinfo {
|
||||
/** 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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user