Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150080219
D6962.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D6962.id.diff
View Options
Index: head/sys/dev/bhnd/bhnd.h
===================================================================
--- head/sys/dev/bhnd/bhnd.h
+++ head/sys/dev/bhnd/bhnd.h
@@ -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 @@
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_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 @@
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,
Index: head/sys/dev/bhnd/bhnd.c
===================================================================
--- head/sys/dev/bhnd/bhnd.c
+++ head/sys/dev/bhnd/bhnd.c
@@ -58,11 +58,20 @@
#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 @@
{ 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 @@
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 @@
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 @@
}
/**
+ * 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 @@
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 @@
}
/**
+ * 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 @@
/* 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 @@
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 @@
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),
Index: head/sys/dev/bhnd/bhnd_subr.c
===================================================================
--- head/sys/dev/bhnd/bhnd_subr.c
+++ head/sys/dev/bhnd/bhnd_subr.c
@@ -51,8 +51,6 @@
#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 @@
}
}
+/**
+ * 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 @@
*
* @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 @@
#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 @@
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 */
Index: head/sys/dev/bhnd/bhndb/bhndb.c
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.c
+++ head/sys/dev/bhnd/bhndb/bhndb.c
@@ -1121,7 +1121,11 @@
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 @@
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);
}
Index: head/sys/dev/bhnd/bhndvar.h
===================================================================
--- head/sys/dev/bhnd/bhndvar.h
+++ head/sys/dev/bhnd/bhndvar.h
@@ -56,8 +56,16 @@
* 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_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_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 30, 5:42 AM (17 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30575797
Default Alt Text
D6962.id.diff (17 KB)
Attached To
Mode
D6962: bhnd(4): Implement generic support for discovery of platform devices (PMU, NVRAM, ChipCommon, etc).
Attached
Detach File
Event Timeline
Log In to Comment