[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:
Adrian Chadd 2016-05-20 00:49:10 +00:00
parent 0e141e3c32
commit 249f3d3f77
3 changed files with 75 additions and 7 deletions

View File

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

View File

@ -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;
};

View File

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