summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorjmcneill <jmcneill@NetBSD.org>2020-09-20 11:25:36 +0000
committerjmcneill <jmcneill@NetBSD.org>2020-09-20 11:25:36 +0000
commit92ded9cc50d690a69cc15eae9d3dfd7f1b27e209 (patch)
tree60795a03d9f1a1c92b52a0199a7d79583c3d4420 /sys/dev/fdt
parent540f33d12982703618d82ba3b32f4c08718aa343 (diff)
Adjust fdt_rescan to speed up booting by significantly reducing the number
of times that we call config_match. Now we only call it 11 times per node. Previously, each scan pass of an unconfigured device triggered 11 calls to config_match, and adding a new simplebus causes the scan to restart, so we are avoiding potentially hundreds of calls to config_match per node now.
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/fdtbus.c73
1 files changed, 35 insertions, 38 deletions
diff --git a/sys/dev/fdt/fdtbus.c b/sys/dev/fdt/fdtbus.c
index 02afb216a6f..1d5edb7b349 100644
--- a/sys/dev/fdt/fdtbus.c
+++ b/sys/dev/fdt/fdtbus.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fdtbus.c,v 1.34 2020/06/11 02:39:30 thorpej Exp $ */
+/* $NetBSD: fdtbus.c,v 1.35 2020/09/20 11:25:36 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.34 2020/06/11 02:39:30 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.35 2020/09/20 11:25:36 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,6 +53,8 @@ struct fdt_node {
int n_phandle;
const char *n_name;
struct fdt_attach_args n_faa;
+
+ int n_cfpass;
cfdata_t n_cf;
u_int n_order;
@@ -78,7 +80,7 @@ static int fdt_rescan(device_t, const char *, const int *);
static void fdt_childdet(device_t, device_t);
static int fdt_scan_submatch(device_t, cfdata_t, const int *, void *);
-static cfdata_t fdt_scan_best(struct fdt_softc *, struct fdt_node *);
+static void fdt_scan_best(struct fdt_softc *, struct fdt_node *);
static void fdt_scan(struct fdt_softc *, int);
static void fdt_add_node(struct fdt_node *);
static u_int fdt_get_order(int);
@@ -161,7 +163,7 @@ fdt_rescan(device_t self, const char *ifattr, const int *locs)
int pass;
TAILQ_FOREACH(node, &fdt_nodes, n_nodes)
- node->n_cf = fdt_scan_best(sc, node);
+ fdt_scan_best(sc, node);
pass = 0;
fdt_need_rescan = false;
@@ -170,8 +172,8 @@ fdt_rescan(device_t self, const char *ifattr, const int *locs)
if (fdt_need_rescan == true) {
pass = 0;
TAILQ_FOREACH(node, &fdt_nodes, n_nodes) {
- if (node->n_dev == NULL)
- node->n_cf = fdt_scan_best(sc, node);
+ if (node->n_cfpass == -1)
+ fdt_scan_best(sc, node);
}
fdt_need_rescan = false;
} else {
@@ -298,11 +300,13 @@ fdt_add_child(device_t bus, const int child, struct fdt_attach_args *faa,
struct fdt_node *node;
/* Add the node to our device list */
- node = kmem_alloc(sizeof(*node), KM_SLEEP);
+ node = kmem_zalloc(sizeof(*node), KM_SLEEP);
node->n_bus = bus;
node->n_dev = NULL;
node->n_phandle = child;
node->n_name = fdtbus_get_string(child, "name");
+ node->n_cfpass = -1;
+ node->n_cf = NULL;
node->n_order = order;
node->n_faa = *faa;
node->n_faa.faa_phandle = child;
@@ -323,15 +327,16 @@ fdt_scan_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
return config_stdsubmatch(parent, cf, locs, aux);
}
-static cfdata_t
+static void
fdt_scan_best(struct fdt_softc *sc, struct fdt_node *node)
{
struct fdt_attach_args faa;
cfdata_t cf, best_cf;
- int match, best_match;
+ int match, best_match, best_pass;
best_cf = NULL;
best_match = 0;
+ best_pass = FDTCF_PASS_DEFAULT;
for (int pass = 0; pass <= FDTCF_PASS_DEFAULT; pass++) {
const int locs[FDTCF_NLOCS] = {
@@ -345,10 +350,12 @@ fdt_scan_best(struct fdt_softc *sc, struct fdt_node *node)
if (match > best_match) {
best_match = match;
best_cf = cf;
+ best_pass = pass;
}
}
- return best_cf;
+ node->n_cf = best_cf;
+ node->n_cfpass = best_pass;
}
static void
@@ -360,54 +367,38 @@ fdt_scan(struct fdt_softc *sc, int pass)
[FDTCF_PASS] = pass
};
bool quiet = pass != FDTCF_PASS_DEFAULT;
- prop_dictionary_t dict;
- char buf[FDT_MAX_PATH];
TAILQ_FOREACH(node, &fdt_nodes, n_nodes) {
- if (node->n_dev != NULL)
+ if (node->n_cfpass != pass || node->n_dev != NULL)
continue;
fdt_init_attach_args(&sc->sc_faa, node, quiet, &faa);
- if (quiet) {
+ if (quiet && node->n_cf == NULL) {
/*
* No match for this device, skip it.
*/
- if (node->n_cf == NULL)
- continue;
+ continue;
+ }
- /*
- * Make sure we don't attach before a better match in a later pass.
- */
- cfdata_t cf_pass =
- config_search_loc(fdt_scan_submatch, node->n_bus, "fdt", locs, &faa);
- if (node->n_cf != cf_pass)
- continue;
+ /*
+ * Attach the device.
+ */
+ fdt_pre_attach(node);
- /*
- * Attach the device.
- */
- fdt_pre_attach(node);
- node->n_dev = config_attach_loc(node->n_bus, cf_pass, locs,
+ if (quiet) {
+ node->n_dev = config_attach_loc(node->n_bus, node->n_cf, locs,
&faa, fdtbus_print);
- if (node->n_dev != NULL)
- fdt_post_attach(node);
} else {
/*
* Default pass.
*/
- fdt_pre_attach(node);
node->n_dev = config_found_sm_loc(node->n_bus, "fdt", locs,
&faa, fdtbus_print, fdt_scan_submatch);
- if (node->n_dev != NULL)
- fdt_post_attach(node);
}
- if (node->n_dev) {
- dict = device_properties(node->n_dev);
- if (fdtbus_get_path(node->n_phandle, buf, sizeof(buf)))
- prop_dictionary_set_string(dict, "fdt-path", buf);
- }
+ if (node->n_dev != NULL)
+ fdt_post_attach(node);
}
}
@@ -433,8 +424,14 @@ fdt_pre_attach(struct fdt_node *node)
static void
fdt_post_attach(struct fdt_node *node)
{
+ char buf[FDT_MAX_PATH];
+ prop_dictionary_t dict;
int error;
+ dict = device_properties(node->n_dev);
+ if (fdtbus_get_path(node->n_phandle, buf, sizeof(buf)))
+ prop_dictionary_set_string(dict, "fdt-path", buf);
+
if (node->n_pinctrl_init) {
aprint_debug_dev(node->n_bus, "set default config for %s\n", node->n_name);
error = fdtbus_pinctrl_set_config(node->n_phandle, "default");