svn commit: r300251 - head/sys/dev/bhnd/bhndb

Adrian Chadd adrian at FreeBSD.org
Fri May 20 00:49:12 UTC 2016


Author: adrian
Date: Fri May 20 00:49:10 2016
New Revision: 300251
URL: https://svnweb.freebsd.org/changeset/base/300251

Log:
  [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 at landonf.org>
  Differential Revision:	https://reviews.freebsd.org/D6470

Modified:
  head/sys/dev/bhnd/bhndb/bhndb.c
  head/sys/dev/bhnd/bhndb/bhndb_private.h
  head/sys/dev/bhnd/bhndb/bhndb_subr.c

Modified: head/sys/dev/bhnd/bhndb/bhndb.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.c	Fri May 20 00:45:16 2016	(r300250)
+++ head/sys/dev/bhnd/bhndb/bhndb.c	Fri May 20 00:49:10 2016	(r300251)
@@ -1144,11 +1144,16 @@ bhndb_adjust_resource(device_t dev, devi
 {
 	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, devi
 	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;
+
+	/* 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;
 
-	BHNDB_UNLOCK(sc);
+	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 de
 	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

Modified: head/sys/dev/bhnd/bhndb/bhndb_private.h
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_private.h	Fri May 20 00:45:16 2016	(r300250)
+++ head/sys/dev/bhnd/bhndb/bhndb_private.h	Fri May 20 00:49:10 2016	(r300251)
@@ -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
  * 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;
 };
 

Modified: head/sys/dev/bhnd/bhndb/bhndb_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_subr.c	Fri May 20 00:45:16 2016	(r300250)
+++ head/sys/dev/bhnd/bhndb/bhndb_subr.c	Fri May 20 00:49:10 2016	(r300251)
@@ -563,8 +563,52 @@ bhndb_add_resource_region(struct bhndb_r
 	return (0);
 }
 
+
+/**
+ * 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 a bus region that maps @p size bytes at @p addr.
+ * 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.


More information about the svn-src-all mailing list