mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01:00 
			
		
		
		
	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: 8a715530bb ("dm: core: Allow the uclass list to move")
			
			
This commit is contained in:
		| @@ -146,6 +146,9 @@ int uclass_get(enum uclass_id id, struct uclass **ucp) | |||||||
| { | { | ||||||
| 	struct uclass *uc; | 	struct uclass *uc; | ||||||
|  |  | ||||||
|  | 	/* Immediately fail if driver model is not set up */ | ||||||
|  | 	if (!gd->uclass_root) | ||||||
|  | 		return -EDEADLK; | ||||||
| 	*ucp = NULL; | 	*ucp = NULL; | ||||||
| 	uc = uclass_find(id); | 	uc = uclass_find(id); | ||||||
| 	if (!uc) { | 	if (!uc) { | ||||||
|   | |||||||
| @@ -159,7 +159,8 @@ void *uclass_get_priv(const struct uclass *uc); | |||||||
|  * |  * | ||||||
|  * @key: ID to look up |  * @key: ID to look up | ||||||
|  * @ucp: Returns pointer to uclass (there is only one per ID) |  * @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); | int uclass_get(enum uclass_id key, struct uclass **ucp); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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)); | 	memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root)); | ||||||
|  |  | ||||||
| 	ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST)); | 	ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST)); | ||||||
|  | 	ut_asserteq(-EDEADLK, uclass_get(UCLASS_TEST, &uc)); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user