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 <jmcne...@invisible.ca>
@@ -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 <jmcne...@invisible.ca>
@@ -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 */

Reply via email to