[PATCH] dm: core: Don't allow uclass use before ready

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 | 3 +++ include/dm/uclass.h | 3 ++- test/dm/core.c | 1 + 3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 117d35ac49c..3146dfd0320 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -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) { diff --git a/include/dm/uclass.h b/include/dm/uclass.h index 2778818b528..da0c1bfadb1 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -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);
diff --git a/test/dm/core.c b/test/dm/core.c index 48e66b73335..c9a7606666c 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -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; }

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 | 3 +++ include/dm/uclass.h | 3 ++- test/dm/core.c | 1 + 3 files changed, 6 insertions(+), 1 deletion(-)
Applied to u-boot-dm, thanks!
participants (1)
-
Simon Glass