]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dm: core: Don't allow uclass use before ready
authorSimon Glass <sjg@chromium.org>
Sun, 1 Aug 2021 18:05:23 +0000 (12:05 -0600)
committerSimon Glass <sjg@chromium.org>
Sun, 8 Aug 2021 17:27:27 +0000 (11:27 -0600)
At present it is possible to call uclass_get() before driver model is
inited. In fact this happens on x86 boards which use Intel FSPv1, since
mrccache_get_region() tries to get the SPI flash device very early
during init.

This has always been undefined behaviour. Previously it generally worked,
i.e. returned an error code without crashing, because gd->uclass_root_s
is zeroed and the uclass can be added despite driver model not being
ready, due to the way lists are implemented. With the change to use a
gd->uclass_root pointer, this no-longer works. For example, it causes a
hang on minnowmax.

Fix this by adding a check that driver model is ready when uclass_get() is
called. This function is called in the process of locating any device, so
it is a good place to add the check.

This fixes booting on minnowmax.

Signed-off-by: Simon Glass <sjg@chromium.org>
Fixes: 8a715530bb1 ("dm: core: Allow the uclass list to move")
drivers/core/uclass.c
include/dm/uclass.h
test/dm/core.c

index 117d35ac49c8f6fe43de141be525466460fbabf3..3146dfd0320d75be404cda41819e6d5933f32331 100644 (file)
@@ -146,6 +146,9 @@ int uclass_get(enum uclass_id id, struct uclass **ucp)
 {
        struct uclass *uc;
 
+       /* Immediately fail if driver model is not set up */
+       if (!gd->uclass_root)
+               return -EDEADLK;
        *ucp = NULL;
        uc = uclass_find(id);
        if (!uc) {
index 2778818b52810e0fa3babc46e2ec6b0881118eb6..da0c1bfadb1efb02641d9febd7ad2c9e1f64cf55 100644 (file)
@@ -159,7 +159,8 @@ void *uclass_get_priv(const struct uclass *uc);
  *
  * @key: ID to look up
  * @ucp: Returns pointer to uclass (there is only one per ID)
- * @return 0 if OK, -ve on error
+ * @return 0 if OK, -EDEADLK if driver model is not yet inited, other -ve on
+ *     other error
  */
 int uclass_get(enum uclass_id key, struct uclass **ucp);
 
index 48e66b7333567d54f4b8191bae56ce4d5d771842..c9a7606666c0769eb4c90b5b140b0ceb1561e4fa 100644 (file)
@@ -994,6 +994,7 @@ static int dm_test_uclass_before_ready(struct unit_test_state *uts)
        memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root));
 
        ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST));
+       ut_asserteq(-EDEADLK, uclass_get(UCLASS_TEST, &uc));
 
        return 0;
 }