svn commit: r302604 - in head/sys/dev/bhnd: . bhndb

Landon J. Fuller landonf at FreeBSD.org
Tue Jul 12 02:16:50 UTC 2016


Author: landonf
Date: Tue Jul 12 02:16:48 2016
New Revision: 302604
URL: https://svnweb.freebsd.org/changeset/base/302604

Log:
  bhnd(4): Add bus pass-aware discovery of platform devices (PMU,
  NVRAM, ChipCommon, etc).
  
  This extends the existing handling of NVRAM core discovery to support
  locating additional devices that may be attached either directly as real
  cores, or indirectly via ChipCommon (e.g. bhnd_pmu).
  
  When attached as a SoC root bus (as opposed to a bridged WiFi device),
  the platform devices may not be attached until later bus passes,
  necessitating delayed discovery/initialization.
  
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D6962

Modified:
  head/sys/dev/bhnd/bhnd.c
  head/sys/dev/bhnd/bhnd.h
  head/sys/dev/bhnd/bhnd_subr.c
  head/sys/dev/bhnd/bhndb/bhndb.c
  head/sys/dev/bhnd/bhndvar.h

Modified: head/sys/dev/bhnd/bhnd.c
==============================================================================
--- head/sys/dev/bhnd/bhnd.c	Tue Jul 12 02:12:31 2016	(r302603)
+++ head/sys/dev/bhnd/bhnd.c	Tue Jul 12 02:16:48 2016	(r302604)
@@ -58,11 +58,20 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <machine/resource.h>
 
+#include <dev/bhnd/cores/chipc/chipcvar.h>
+
+#include "bhnd_chipc_if.h"
+#include "bhnd_nvram_if.h"
+
 #include "bhnd.h"
 #include "bhndvar.h"
 
 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
 
+/* Bus pass at which all bus-required children must be available, and
+ * attachment may be finalized. */
+#define	BHND_FINISH_ATTACH_PASS	BUS_PASS_DEFAULT
+
 /**
  * bhnd_generic_probe_nomatch() reporting configuration.
  */
@@ -80,10 +89,22 @@ static const struct bhnd_nomatch {
 	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
 };
 
-static int	compare_ascending_probe_order(const void *lhs,
-		    const void *rhs);
-static int	compare_descending_probe_order(const void *lhs,
-		    const void *rhs);
+
+static int			 bhnd_delete_children(struct bhnd_softc *sc);
+
+static int			 bhnd_finish_attach(struct bhnd_softc *sc);
+
+static device_t			 bhnd_find_chipc(struct bhnd_softc *sc);
+static struct chipc_caps	*bhnd_find_chipc_caps(struct bhnd_softc *sc);
+static device_t			 bhnd_find_platform_dev(struct bhnd_softc *sc,
+				     const char *classname);
+static device_t			 bhnd_find_pmu(struct bhnd_softc *sc);
+static device_t			 bhnd_find_nvram(struct bhnd_softc *sc);
+
+static int			 compare_ascending_probe_order(const void *lhs,
+				     const void *rhs);
+static int			 compare_descending_probe_order(const void *lhs,
+				     const void *rhs);
 
 /**
  * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
@@ -94,44 +115,53 @@ static int	compare_descending_probe_orde
 int
 bhnd_generic_attach(device_t dev)
 {
-	device_t	*devs;
-	int		 ndevs;
-	int		 error;
+	struct bhnd_softc	*sc;
+	device_t		*devs;
+	int			 ndevs;
+	int			 error;
 
 	if (device_is_attached(dev))
 		return (EBUSY);
 
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
 	if ((error = device_get_children(dev, &devs, &ndevs)))
 		return (error);
 
+	/* Probe and attach all children */
 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
 	for (int i = 0; i < ndevs; i++) {
 		device_t child = devs[i];
 		device_probe_and_attach(child);
 	}
 
+	/* Try to finalize attachment */
+	if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
+		if ((error = bhnd_finish_attach(sc)))
+			goto cleanup;
+	}
+
+cleanup:
 	free(devs, M_TEMP);
-	return (0);
+
+	if (error)
+		bhnd_delete_children(sc);
+
+	return (error);
 }
 
 /**
- * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
- *
- * This implementation calls device_detach() for each of the device's
- * children, in reverse bhnd probe order, terminating if any call to
- * device_detach() fails.
+ * Detach and delete all children, in reverse of their attach order.
  */
-int
-bhnd_generic_detach(device_t dev)
+static int
+bhnd_delete_children(struct bhnd_softc *sc)
 {
-	device_t	*devs;
-	int		 ndevs;
-	int		 error;
+	device_t		*devs;
+	int			 ndevs;
+	int			 error;
 
-	if (!device_is_attached(dev))
-		return (EBUSY);
-
-	if ((error = device_get_children(dev, &devs, &ndevs)))
+	if ((error = device_get_children(sc->dev, &devs, &ndevs)))
 		return (error);
 
 	/* Detach in the reverse of attach order */
@@ -140,7 +170,7 @@ bhnd_generic_detach(device_t dev)
 		device_t child = devs[i];
 
 		/* Terminate on first error */
-		if ((error = device_detach(child)))
+		if ((error = device_delete_child(sc->dev, child)))
 			goto cleanup;
 	}
 
@@ -150,6 +180,25 @@ cleanup:
 }
 
 /**
+ * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
+ *
+ * This implementation calls device_detach() for each of the device's
+ * children, in reverse bhnd probe order, terminating if any call to
+ * device_detach() fails.
+ */
+int
+bhnd_generic_detach(device_t dev)
+{
+	struct bhnd_softc	*sc;
+
+	if (!device_is_attached(dev))
+		return (EBUSY);
+
+	sc = device_get_softc(dev);
+	return (bhnd_delete_children(sc));
+}
+
+/**
  * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
  * 
  * This implementation calls device_shutdown() for each of the device's
@@ -262,6 +311,223 @@ cleanup:
 	return (error);
 }
 
+static void
+bhnd_new_pass(device_t dev)
+{
+	struct bhnd_softc	*sc;
+	int			 error;
+
+	sc = device_get_softc(dev);
+
+	/* Attach any permissible children */ 
+	bus_generic_new_pass(dev);
+
+	/* Finalize attachment */
+	if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
+		if ((error = bhnd_finish_attach(sc))) {
+			panic("bhnd_finish_attach() failed: %d", error);
+		}
+	}
+}
+
+/*
+ * Finish any pending bus attachment operations.
+ *
+ * When attached as a SoC bus (as opposed to a bridged WiFi device), our
+ * platform devices may not be attached until later bus passes, necessitating
+ * delayed initialization on our part.
+ */
+static int
+bhnd_finish_attach(struct bhnd_softc *sc)
+{
+	struct chipc_caps	*ccaps;
+
+	GIANT_REQUIRED;	/* newbus */
+
+	KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
+	    ("bhnd_finish_attach() called in pass %d", bus_current_pass));
+
+	KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()"));
+
+	/* Locate chipc device */
+	if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) {
+		device_printf(sc->dev, "error: ChipCommon device not found\n");
+		return (ENXIO);
+	}
+
+	ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
+
+	/* Look for NVRAM device */
+	if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
+		if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
+			device_printf(sc->dev,
+			    "warning: %s NVRAM device not found\n",
+			    bhnd_nvram_src_name(ccaps->nvram_src));
+		}
+	}
+
+	/* Look for a PMU  */
+	if (ccaps->pmu) {
+		if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
+			device_printf(sc->dev,
+			    "warning: PMU device not found\n");
+		}
+	}
+
+	/* Mark attach as completed */
+	sc->attach_done = true;
+
+	return (0);
+}
+
+/* Locate the ChipCommon core. */
+static device_t
+bhnd_find_chipc(struct bhnd_softc *sc)
+{
+	device_t chipc;
+
+        /* Make sure we're holding Giant for newbus */
+	GIANT_REQUIRED;
+
+	/* chipc_dev is initialized during attachment */
+	if (sc->attach_done) {
+		if ((chipc = sc->chipc_dev) == NULL)
+			return (NULL);
+
+		goto found;
+	}
+
+	/* Locate chipc core with a core unit of 0 */
+	chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0);
+	if (chipc == NULL)
+		return (NULL);
+
+found:
+	if (device_get_state(chipc) < DS_ATTACHING) {
+		device_printf(sc->dev, "chipc found, but did not attach\n");
+		return (NULL);
+	}
+
+	return (chipc);
+}
+
+/* Locate the ChipCommon core and return the device capabilities  */
+static struct chipc_caps *
+bhnd_find_chipc_caps(struct bhnd_softc *sc)
+{
+	device_t chipc;
+
+	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
+		device_printf(sc->dev, 
+		    "chipc unavailable; cannot fetch capabilities\n");
+		return (NULL);
+	}
+
+	return (BHND_CHIPC_GET_CAPS(chipc));
+}
+
+/**
+ * Find an attached platform device on @p dev, searching first for cores
+ * matching @p classname, and if not found, searching the children of the first
+ * bhnd_chipc device on the bus.
+ * 
+ * @param sc Driver state.
+ * @param chipc Attached ChipCommon device.
+ * @param classname Device class to search for.
+ * 
+ * @retval device_t A matching device.
+ * @retval NULL If no matching device is found.
+ */
+static device_t
+bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname)
+{
+	device_t chipc, child;
+
+        /* Make sure we're holding Giant for newbus */
+	GIANT_REQUIRED;
+
+	/* Look for a directly-attached child */
+	child = device_find_child(sc->dev, classname, -1);
+	if (child != NULL)
+		goto found;
+
+	/* Look for the first matching ChipCommon child */
+	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
+		device_printf(sc->dev, 
+		    "chipc unavailable; cannot locate %s\n", classname);
+		return (NULL);
+	}
+
+	child = device_find_child(chipc, classname, -1);
+	if (child == NULL)
+		return (NULL);
+
+found:
+	if (device_get_state(child) < DS_ATTACHING)
+		return (NULL);
+
+	return (child);
+}
+
+/* Locate the PMU device, if any */
+static device_t
+bhnd_find_pmu(struct bhnd_softc *sc)
+{
+	struct chipc_caps	*ccaps;
+
+        /* Make sure we're holding Giant for newbus */
+	GIANT_REQUIRED;
+
+	/* pmu_dev is initialized during attachment */
+	if (sc->attach_done) {
+		if (sc->pmu_dev == NULL)
+			return (NULL);
+
+		if (device_get_state(sc->pmu_dev) < DS_ATTACHING)
+			return (NULL);
+
+		return (sc->pmu_dev);
+	}
+
+	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
+		return (NULL);
+
+	if (!ccaps->pmu)
+		return (NULL);
+
+	return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
+}
+
+/* Locate the NVRAM device, if any */
+static device_t
+bhnd_find_nvram(struct bhnd_softc *sc)
+{
+	struct chipc_caps *ccaps;
+
+        /* Make sure we're holding Giant for newbus */
+	GIANT_REQUIRED;
+
+
+	/* nvram_dev is initialized during attachment */
+	if (sc->attach_done) {
+		if (sc->nvram_dev == NULL)
+			return (NULL);
+
+		if (device_get_state(sc->nvram_dev) < DS_ATTACHING)
+			return (NULL);
+
+		return (sc->nvram_dev);
+	}
+
+	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
+		return (NULL);
+
+	if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN)
+		return (NULL);
+
+	return (bhnd_find_platform_dev(sc, "bhnd_nvram"));
+}
+
 /*
  * Ascending comparison of bhnd device's probe order.
  */
@@ -376,6 +642,35 @@ bhnd_generic_is_region_valid(device_t de
 }
 
 /**
+ * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
+ * 
+ * This implementation searches @p dev for a usable NVRAM child device.
+ * 
+ * If no usable child device is found on @p dev, the request is delegated to
+ * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
+ */
+int
+bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
+    void *buf, size_t *size)
+{
+	struct bhnd_softc	*sc;
+	device_t		 nvram, parent;
+
+	sc = device_get_softc(dev);
+
+	/* If a NVRAM device is available, consult it first */
+	if ((nvram = bhnd_find_nvram(sc)) != NULL)
+		return BHND_NVRAM_GETVAR(nvram, name, buf, size);
+
+	/* Otherwise, try to delegate to parent */
+	if ((parent = device_get_parent(dev)) == NULL)
+		return (ENODEV);
+
+	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
+	    name, buf, size));
+}
+
+/**
  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
  * 
  * This implementation requests the device's struct resource_list via
@@ -538,6 +833,15 @@ bhnd_generic_child_deleted(device_t dev,
 	/* Free device info */
 	if ((dinfo = device_get_ivars(child)) != NULL)
 		BHND_BUS_FREE_DEVINFO(dev, dinfo);
+
+	/* Clean up platform device references */
+	if (sc->chipc_dev == child) {
+		sc->chipc_dev = NULL;
+	} else if (sc->nvram_dev == child) {
+		sc->nvram_dev = NULL;
+	} else if (sc->pmu_dev == child) {
+		sc->pmu_dev = NULL;
+	}
 }
 
 /**
@@ -659,6 +963,7 @@ static device_method_t bhnd_methods[] = 
 	DEVMETHOD(device_resume,		bhnd_generic_resume),
 
 	/* Bus interface */
+	DEVMETHOD(bus_new_pass,			bhnd_new_pass),
 	DEVMETHOD(bus_add_child,		bhnd_generic_add_child),
 	DEVMETHOD(bus_child_deleted,		bhnd_generic_child_deleted),
 	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
@@ -691,7 +996,7 @@ static device_method_t bhnd_methods[] = 
 	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_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
-	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_bus_generic_get_nvram_var),
+	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
 
 	/* BHND interface (bus I/O) */
 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),

Modified: head/sys/dev/bhnd/bhnd.h
==============================================================================
--- head/sys/dev/bhnd/bhnd.h	Tue Jul 12 02:12:31 2016	(r302603)
+++ head/sys/dev/bhnd/bhnd.h	Tue Jul 12 02:16:48 2016	(r302604)
@@ -43,6 +43,8 @@
 #include "bhnd_bus_if.h"
 #include "bhnd_match.h"
 
+#include "nvram/bhnd_nvram.h"
+
 extern devclass_t bhnd_devclass;
 extern devclass_t bhnd_hostb_devclass;
 extern devclass_t bhnd_nvram_devclass;
@@ -242,6 +244,7 @@ struct bhnd_device {
 
 const char			*bhnd_vendor_name(uint16_t vendor);
 const char			*bhnd_port_type_name(bhnd_port_type port_type);
+const char			*bhnd_nvram_src_name(bhnd_nvram_src nvram_src);
 
 const char 			*bhnd_find_core_name(uint16_t vendor,
 				     uint16_t device);
@@ -324,7 +327,7 @@ bool				 bhnd_bus_generic_is_hw_disabled
 bool				 bhnd_bus_generic_is_region_valid(device_t dev,
 				     device_t child, bhnd_port_type type,
 				     u_int port, u_int region);
-int				 bhnd_bus_generic_read_nvram_var(device_t dev,
+int				 bhnd_bus_generic_get_nvram_var(device_t dev,
 				     device_t child, const char *name,
 				     void *buf, size_t *size);
 const struct bhnd_chipid	*bhnd_bus_generic_get_chipid(device_t dev,
@@ -332,9 +335,6 @@ const struct bhnd_chipid	*bhnd_bus_gener
 int				 bhnd_bus_generic_read_board_info(device_t dev,
 				     device_t child,
 				     struct bhnd_board_info *info);
-int				 bhnd_bus_generic_get_nvram_var(device_t dev,
-				    device_t child, const char *name,
-				    void *buf, size_t *size);
 struct bhnd_resource		*bhnd_bus_generic_alloc_resource (device_t dev,
 				     device_t child, int type, int *rid,
 				     rman_res_t start, rman_res_t end,

Modified: head/sys/dev/bhnd/bhnd_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhnd_subr.c	Tue Jul 12 02:12:31 2016	(r302603)
+++ head/sys/dev/bhnd/bhnd_subr.c	Tue Jul 12 02:16:48 2016	(r302604)
@@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$");
 #include "bhndreg.h"
 #include "bhndvar.h"
 
-static device_t		find_nvram_child(device_t dev);
-
 /* BHND core device description table. */
 static const struct bhnd_core_desc {
 	uint16_t	 vendor;
@@ -198,6 +196,25 @@ bhnd_port_type_name(bhnd_port_type port_
 	}
 }
 
+/**
+ * Return the name of an NVRAM source.
+ */
+const char *
+bhnd_nvram_src_name(bhnd_nvram_src nvram_src)
+{
+	switch (nvram_src) {
+	case BHND_NVRAM_SRC_FLASH:
+		return ("flash");
+	case BHND_NVRAM_SRC_OTP:
+		return ("OTP");
+	case BHND_NVRAM_SRC_SPROM:
+		return ("SPROM");
+	case BHND_NVRAM_SRC_UNKNOWN:
+		return ("none");
+	default:
+		return ("unknown");
+	}
+}
 
 static const struct bhnd_core_desc *
 bhnd_find_core_desc(uint16_t vendor, uint16_t device)
@@ -293,7 +310,7 @@ bhnd_get_core_info(device_t dev) {
  * 
  * @param parent The bhnd-compatible bus to be searched.
  * @param class The device class to match on.
- * @param unit The device unit number; specify -1 to return the first match
+ * @param unit The core unit number; specify -1 to return the first match
  * regardless of unit number.
  * 
  * @retval device_t if a matching child device is found.
@@ -990,47 +1007,10 @@ bhnd_bus_generic_read_board_info(device_
 #undef	BHND_GV_REQ
 #undef	BHND_GV_OPT
 
-
-/**
- * Find an NVRAM child device on @p dev, if any.
- * 
- * @retval device_t An NVRAM device.
- * @retval NULL If no NVRAM device is found.
- */
-static device_t
-find_nvram_child(device_t dev)
-{
-	device_t	chipc, nvram;
-
-	/* Look for a directly-attached NVRAM child */
-	nvram = device_find_child(dev, "bhnd_nvram", 0);
-	if (nvram != NULL)
-		return (nvram);
-
-	/* Remaining checks are only applicable when searching a bhnd(4)
-	 * bus. */
-	if (device_get_devclass(dev) != bhnd_devclass)
-		return (NULL);
-
-	/* Look for a ChipCommon-attached NVRAM device */
-	if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) {
-		nvram = device_find_child(chipc, "bhnd_nvram", 0);
-		if (nvram != NULL)
-			return (nvram);
-	}
-
-	/* Not found */
-	return (NULL);
-}
-
 /**
  * Helper function for implementing BHND_BUS_GET_NVRAM_VAR().
  * 
- * This implementation searches @p dev for a usable NVRAM child device:
- * - The first child device implementing the bhnd_nvram devclass is
- *   returned, otherwise
- * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an
- *   attached NVRAM source.
+ * This implementation searches @p dev for a usable NVRAM child device.
  * 
  * If no usable child device is found on @p dev, the request is delegated to
  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
@@ -1042,8 +1022,11 @@ bhnd_bus_generic_get_nvram_var(device_t 
 	device_t	nvram;
 	device_t	parent;
 
-	/* Try to find an NVRAM device applicable to @p child */
-	if ((nvram = find_nvram_child(dev)) != NULL)
+        /* Make sure we're holding Giant for newbus */
+	GIANT_REQUIRED;
+
+	/* Look for a directly-attached NVRAM child */
+	if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL)
 		return BHND_NVRAM_GETVAR(nvram, name, buf, size);
 
 	/* Try to delegate to parent */

Modified: head/sys/dev/bhnd/bhndb/bhndb.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.c	Tue Jul 12 02:12:31 2016	(r302603)
+++ head/sys/dev/bhnd/bhndb/bhndb.c	Tue Jul 12 02:16:48 2016	(r302604)
@@ -1121,7 +1121,11 @@ static int
 bhndb_release_resource(device_t dev, device_t child, int type, int rid,
     struct resource *r)
 {
-	int error;
+	struct resource_list_entry	*rle;
+	bool				 passthrough;
+	int				 error;
+	
+	passthrough = (device_get_parent(child) != dev);
 
 	/* Deactivate resources */
 	if (rman_get_flags(r) & RF_ACTIVE) {
@@ -1133,6 +1137,14 @@ bhndb_release_resource(device_t dev, dev
 	if ((error = rman_release_resource(r)))
 		return (error);
 
+	if (!passthrough) {
+		/* Clean resource list entry */
+		rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child),
+		    type, rid);
+		if (rle != NULL)
+			rle->res = NULL;
+	}
+
 	return (0);
 }
 

Modified: head/sys/dev/bhnd/bhndvar.h
==============================================================================
--- head/sys/dev/bhnd/bhndvar.h	Tue Jul 12 02:12:31 2016	(r302603)
+++ head/sys/dev/bhnd/bhndvar.h	Tue Jul 12 02:16:48 2016	(r302604)
@@ -56,8 +56,16 @@ struct bhnd_devinfo {
  * bhnd driver instance state. Must be first member of all subclass
  * softc structures.
  */
-struct bhnd_softc {};
+struct bhnd_softc {
+	device_t	dev;		/**< bus device */
 
+	bool		attach_done;	/**< true if initialization of all
+					  *  platform devices has been
+					  *  completed */
+	device_t	chipc_dev;	/**< bhnd_chipc device */ 
+	device_t	nvram_dev;	/**< bhnd_nvram device, if any */
+	device_t	pmu_dev;	/**< bhnd_pmu device, if any */
+};
 
 int			 bhnd_generic_attach(device_t dev);
 int			 bhnd_generic_detach(device_t dev);
@@ -82,4 +90,8 @@ int			 bhnd_generic_suspend_child(device
 int			 bhnd_generic_resume_child(device_t dev,
 			     device_t child);
 
+int			 bhnd_generic_get_nvram_var(device_t dev,
+			     device_t child, const char *name, void *buf,
+			     size_t *size);
+
 #endif /* _BHND_BHNDVAR_H_ */


More information about the svn-src-head mailing list