[bhnd] Add bhnd bridge support for bus_adjust_resource().
Adds support for adjusting active bus resource allocations, limiting the range to the constraints of the register window within which the resource is mapped. This is the final set of bhnd changes required to support delegating ChipCommon's register space to child devices. Submitted by: Landon Fuller <landonf@landonf.org> Differential Revision: https://reviews.freebsd.org/D6470
This commit is contained in:
parent
0e141e3c32
commit
249f3d3f77
@ -1144,11 +1144,16 @@ bhndb_adjust_resource(device_t dev, device_t child, int type,
|
||||
{
|
||||
struct bhndb_softc *sc;
|
||||
struct rman *rm;
|
||||
rman_res_t mstart, mend;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = 0;
|
||||
|
||||
/* Verify basic constraints */
|
||||
if (end <= start)
|
||||
return (EINVAL);
|
||||
|
||||
/* Fetch resource manager */
|
||||
rm = bhndb_get_rman(sc, child, type);
|
||||
if (rm == NULL)
|
||||
@ -1157,16 +1162,29 @@ bhndb_adjust_resource(device_t dev, device_t child, int type,
|
||||
if (!rman_is_region_manager(r, rm))
|
||||
return (ENXIO);
|
||||
|
||||
/* If active, adjustment is limited by the assigned window. */
|
||||
BHNDB_LOCK(sc);
|
||||
|
||||
// TODO: Currently unsupported
|
||||
error = ENODEV;
|
||||
/* If not active, allow any range permitted by the resource manager */
|
||||
if (!(rman_get_flags(r) & RF_ACTIVE))
|
||||
goto done;
|
||||
|
||||
BHNDB_UNLOCK(sc);
|
||||
/* Otherwise, the range is limited to the existing register window
|
||||
* mapping */
|
||||
error = bhndb_find_resource_limits(sc->bus_res, r, &mstart, &mend);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
if (start < mstart || end > mend) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
done:
|
||||
if (!error)
|
||||
error = rman_adjust_resource(r, start, end);
|
||||
|
||||
BHNDB_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1536,7 +1554,8 @@ bhndb_activate_bhnd_resource(device_t dev, device_t child,
|
||||
if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) {
|
||||
bhndb_priority_t r_prio;
|
||||
|
||||
region = bhndb_find_resource_region(sc->bus_res, r_start, r_size);
|
||||
region = bhndb_find_resource_region(sc->bus_res, r_start,
|
||||
r_size);
|
||||
if (region != NULL)
|
||||
r_prio = region->priority;
|
||||
else
|
||||
|
@ -71,6 +71,11 @@ int bhndb_add_resource_region(
|
||||
bhndb_priority_t priority,
|
||||
const struct bhndb_regwin *static_regwin);
|
||||
|
||||
int bhndb_find_resource_limits(
|
||||
struct bhndb_resources *br,
|
||||
struct resource *r, rman_res_t *start,
|
||||
rman_res_t *end);
|
||||
|
||||
struct bhndb_region *bhndb_find_resource_region(
|
||||
struct bhndb_resources *br,
|
||||
bhnd_addr_t addr, bhnd_size_t size);
|
||||
@ -133,7 +138,7 @@ const struct bhndb_hw_priority *bhndb_hw_priority_find_device(
|
||||
* Dynamic register window allocation reference.
|
||||
*/
|
||||
struct bhndb_dw_rentry {
|
||||
struct resource *dw_res; /**< child resource */
|
||||
struct resource *dw_res; /**< child resource */
|
||||
LIST_ENTRY(bhndb_dw_rentry) dw_link;
|
||||
};
|
||||
|
||||
|
@ -563,8 +563,52 @@ bhndb_add_resource_region(struct bhndb_resources *br, bhnd_addr_t addr,
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a bus region that maps @p size bytes at @p addr.
|
||||
* Find the maximum start and end limits of the register window mapping
|
||||
* resource @p r.
|
||||
*
|
||||
* If the memory range is not mapped by an existing dynamic or static register
|
||||
* window, ENOENT will be returned.
|
||||
*
|
||||
* @param br The resource state to search.
|
||||
* @param r The resource to search for in @p br.
|
||||
* @param addr The requested starting address.
|
||||
* @param size The requested size.
|
||||
*
|
||||
* @retval bhndb_region A region that fully contains the requested range.
|
||||
* @retval NULL If no mapping region can be found.
|
||||
*/
|
||||
int
|
||||
bhndb_find_resource_limits(struct bhndb_resources *br, struct resource *r,
|
||||
rman_res_t *start, rman_res_t *end)
|
||||
{
|
||||
struct bhndb_dw_alloc *dynamic;
|
||||
struct bhndb_region *sregion;
|
||||
|
||||
/* Check for an enclosing dynamic register window */
|
||||
if ((dynamic = bhndb_dw_find_resource(br, r))) {
|
||||
*start = dynamic->target;
|
||||
*end = dynamic->target + dynamic->win->win_size - 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check for a static region */
|
||||
sregion = bhndb_find_resource_region(br, rman_get_start(r),
|
||||
rman_get_size(r));
|
||||
if (sregion != NULL && sregion->static_regwin != NULL) {
|
||||
*start = sregion->addr;
|
||||
*end = sregion->addr + sregion->size - 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the bus region that maps @p size bytes at @p addr.
|
||||
*
|
||||
* @param br The resource state to search.
|
||||
* @param addr The requested starting address.
|
||||
|
Loading…
x
Reference in New Issue
Block a user