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 */