[Concept,v2,04/30] video: Avoid uclass allocation in video_idle() cyclic

Message ID 20260102005112.552256-5-sjg@u-boot.org
State New
Headers
Series ext4l: Add write support (part L) |

Commit Message

Simon Glass Jan. 2, 2026, 12:50 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

When the test framework reinits driver model, it orphans existing
uclasses without calling their destroy callbacks. The video_idle()
callback remains registered and when it runs, it calls uclass_get()
which creates new uclasses if they don't exist.

A surprising time when it runs is when any environment variable is
read.

Use uclass_find() instead, which returns NULL if the uclass doesn't
exist, allowing video_idle to gracefully exit without allocating memory.
This avoids memory-leak detection failures in tests like dm_test_host()

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

(no changes since v1)

 drivers/video/video-uclass.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)
  

Patch

diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index f50452cc956..383be0d96b8 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -669,10 +669,14 @@  static void video_idle(struct cyclic_info *cyc)
 {
 	struct video_uc_priv *uc_priv;
 	struct uclass *uc;
-	int ret;
 
-	ret = uclass_get(UCLASS_VIDEO, &uc);
-	if (ret)
+	/*
+	 * Use uclass_find() rather than uclass_get() since the latter may
+	 * create a new uclass if the test framework has reinitialised driver
+	 * model while this cyclic function is still registered.
+	 */
+	uc = uclass_find(UCLASS_VIDEO);
+	if (!uc)
 		return;
 
 	uc_priv = uclass_get_priv(uc);
@@ -683,13 +687,15 @@  static void video_idle(struct cyclic_info *cyc)
 
 	if (CONFIG_IS_ENABLED(CURSOR)) {
 		struct udevice *cons;
-		struct uclass *uc;
 
 		/* Handle cursor display for each video console */
-		uclass_id_foreach_dev(UCLASS_VIDEO_CONSOLE, cons, uc) {
-			if (device_active(cons)) {
-				vidconsole_idle(cons);
-				video_sync(cons->parent, true);
+		uc = uclass_find(UCLASS_VIDEO_CONSOLE);
+		if (uc) {
+			list_for_each_entry(cons, &uc->dev_head, uclass_node) {
+				if (device_active(cons)) {
+					vidconsole_idle(cons);
+					video_sync(cons->parent, true);
+				}
 			}
 		}
 	} else {