Page MenuHomeFreeBSD

D6962.id.diff
No OneTemporary

D6962.id.diff

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

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)

Event Timeline