Module Name: src
Committed By: jmcneill
Date: Sun Apr 16 12:24:57 UTC 2017
Modified Files:
src/sys/dev/fdt: fdtbus.c fdtvar.h
Log Message:
Attach devices in order of "phandle" property inserted by DTC.
To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/fdt/fdtbus.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/fdt/fdtvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/fdt/fdtbus.c
diff -u src/sys/dev/fdt/fdtbus.c:1.7 src/sys/dev/fdt/fdtbus.c:1.8
--- src/sys/dev/fdt/fdtbus.c:1.7 Sat Apr 15 00:34:29 2017
+++ src/sys/dev/fdt/fdtbus.c Sun Apr 16 12:24:57 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: fdtbus.c,v 1.7 2017/04/15 00:34:29 jmcneill Exp $ */
+/* $NetBSD: fdtbus.c,v 1.8 2017/04/16 12:24:57 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.7 2017/04/15 00:34:29 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.8 2017/04/16 12:24:57 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,24 +43,33 @@ __KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1
#define FDT_MAX_PATH 256
struct fdt_node {
+ device_t n_bus;
device_t n_dev;
int n_phandle;
char *n_name;
+ u_int n_order;
+
TAILQ_ENTRY(fdt_node) n_nodes;
};
+static TAILQ_HEAD(, fdt_node) fdt_nodes =
+ TAILQ_HEAD_INITIALIZER(fdt_nodes);
+
struct fdt_softc {
device_t sc_dev;
int sc_phandle;
struct fdt_attach_args sc_faa;
-
- TAILQ_HEAD(, fdt_node) sc_nodes;
};
static int fdt_match(device_t, cfdata_t, void *);
static void fdt_attach(device_t, device_t, void *);
-static void fdt_scan(struct fdt_softc *, const char *, bool);
+static void fdt_scan_bus(struct fdt_softc *);
+static void fdt_scan(struct fdt_softc *);
+static void fdt_add_node(struct fdt_node *);
+static u_int fdt_get_order(int);
+
+static int fdt_print(void *, const char *);
static const char * const fdtbus_compatible[] =
{ "simple-bus", NULL };
@@ -68,17 +77,12 @@ static const char * const fdtbus_compati
CFATTACH_DECL_NEW(fdt, sizeof(struct fdt_softc),
fdt_match, fdt_attach, NULL, NULL);
-static int fdt_print(void *, const char *);
-
static int
fdt_match(device_t parent, cfdata_t cf, void *aux)
{
const struct fdt_attach_args *faa = aux;
int match;
- if (!OF_child(faa->faa_phandle))
- return 0;
-
match = of_match_compatible(faa->faa_phandle, fdtbus_compatible);
if (match)
return match;
@@ -94,12 +98,11 @@ fdt_attach(device_t parent, device_t sel
const int phandle = faa->faa_phandle;
struct fdt_node *node;
char *model, *name, *status;
- int len, n, child;
+ int len, child;
sc->sc_dev = self;
- sc->sc_phandle = faa->faa_phandle;
+ sc->sc_phandle = phandle;
sc->sc_faa = *faa;
- TAILQ_INIT(&sc->sc_nodes);
aprint_naive("\n");
len = OF_getproplen(phandle, "model");
@@ -141,71 +144,111 @@ fdt_attach(device_t parent, device_t sel
/* Add the node to our device list */
node = kmem_alloc(sizeof(*node), KM_SLEEP);
+ node->n_bus = self;
node->n_dev = NULL;
node->n_phandle = child;
node->n_name = name;
- TAILQ_INSERT_TAIL(&sc->sc_nodes, node, n_nodes);
+ node->n_order = fdt_get_order(node->n_phandle);
+ fdt_add_node(node);
}
/* Scan and attach all known busses in the tree. */
- for (n = 0; fdtbus_compatible[n] != NULL; n++)
- fdt_scan(sc, fdtbus_compatible[n], true);
+ fdt_scan_bus(sc);
/* Only the root bus should scan for devices */
if (OF_finddevice("/") != faa->faa_phandle)
return;
- /* Scan the tree for "early init" devices */
- for (n = 0; n < faa->faa_ninit; n++)
- fdt_scan(sc, faa->faa_init[n], false);
+ /* Scan devices */
+ fdt_scan(sc);
+}
- /* Finally, scan the tree for all other devices */
- fdt_scan(sc, NULL, false);
+static void
+fdt_init_attach_args(struct fdt_softc *sc, struct fdt_node *node,
+ struct fdt_attach_args *faa)
+{
+ *faa = sc->sc_faa;
+ faa->faa_phandle = node->n_phandle;
+ faa->faa_name = node->n_name;
}
static void
-fdt_scan(struct fdt_softc *sc, const char *compat, bool bus)
+fdt_scan_bus(struct fdt_softc *sc)
{
struct fdt_node *node;
struct fdt_attach_args faa;
cfdata_t cf;
- TAILQ_FOREACH(node, &sc->sc_nodes, n_nodes) {
- if (node->n_dev != NULL) {
- /*
- * Child is already attached. If it is a bus,
- * recursively scan.
- */
- if (device_is_a(node->n_dev, "fdt"))
- fdt_scan(device_private(node->n_dev), compat,
- bus);
+ TAILQ_FOREACH(node, &fdt_nodes, n_nodes) {
+ if (node->n_bus != sc->sc_dev)
+ continue;
+ if (node->n_dev != NULL)
continue;
- }
- faa = sc->sc_faa;
- faa.faa_phandle = node->n_phandle;
- faa.faa_name = node->n_name;
+ fdt_init_attach_args(sc, node, &faa);
/*
* Only attach busses to nodes where this driver is the best
* match.
*/
- if (compat && bus) {
- cf = config_search_loc(NULL, sc->sc_dev, NULL, NULL,
- &faa);
- if (cf == NULL || strcmp(cf->cf_name, "fdt") != 0)
- continue;
- }
+ cf = config_search_loc(NULL, node->n_bus, NULL, NULL, &faa);
+ if (cf == NULL || strcmp(cf->cf_name, "fdt") != 0)
+ continue;
/*
- * Attach the child device.
+ * Attach the bus.
*/
- const char * const compats[] = { compat, NULL };
- if (compat == NULL ||
- of_match_compatible(node->n_phandle, compats)) {
- node->n_dev = config_found(sc->sc_dev, &faa, fdt_print);
+ node->n_dev = config_found(node->n_bus, &faa, fdt_print);
+ }
+}
+
+static void
+fdt_scan(struct fdt_softc *sc)
+{
+ struct fdt_node *node;
+ struct fdt_attach_args faa;
+
+ TAILQ_FOREACH(node, &fdt_nodes, n_nodes) {
+ if (node->n_dev != NULL)
+ continue;
+
+ fdt_init_attach_args(sc, node, &faa);
+
+ /*
+ * Attach the device.
+ */
+ node->n_dev = config_found(node->n_bus, &faa, fdt_print);
+ }
+}
+
+static void
+fdt_add_node(struct fdt_node *new_node)
+{
+ struct fdt_node *node;
+
+ TAILQ_FOREACH(node, &fdt_nodes, n_nodes)
+ if (node->n_order > new_node->n_order) {
+ TAILQ_INSERT_BEFORE(node, new_node, n_nodes);
+ return;
}
+ TAILQ_INSERT_TAIL(&fdt_nodes, new_node, n_nodes);
+}
+
+static u_int
+fdt_get_order(int phandle)
+{
+ u_int val = UINT_MAX;
+ int child;
+
+ of_getprop_uint32(phandle, "phandle", &val);
+
+ for (child = OF_child(phandle); child; child = OF_peer(child)) {
+ u_int child_val = fdt_get_order(child);
+ if (child_val < val)
+ val = child_val;
}
+
+ return val;
}
static int
Index: src/sys/dev/fdt/fdtvar.h
diff -u src/sys/dev/fdt/fdtvar.h:1.8 src/sys/dev/fdt/fdtvar.h:1.9
--- src/sys/dev/fdt/fdtvar.h:1.8 Thu Apr 13 22:12:53 2017
+++ src/sys/dev/fdt/fdtvar.h Sun Apr 16 12:24:57 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: fdtvar.h,v 1.8 2017/04/13 22:12:53 jmcneill Exp $ */
+/* $NetBSD: fdtvar.h,v 1.9 2017/04/16 12:24:57 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -43,9 +43,6 @@ struct fdt_attach_args {
bus_space_tag_t faa_a4x_bst;
bus_dma_tag_t faa_dmat;
int faa_phandle;
-
- const char **faa_init;
- int faa_ninit;
};
/* flags for fdtbus_intr_establish */