diff mbox series

[2/4] media: vsp1: Sort entities in the pipeline

Message ID 20240822212445.2037-3-laurent.pinchart+renesas@ideasonboard.com (mailing list archive)
State New
Delegated to: Kieran Bingham
Headers show
Series media: Drop one user of the deprecated graph walk API | expand

Commit Message

Laurent Pinchart Aug. 22, 2024, 9:24 p.m. UTC
The driver relies on the pipe->entities list being sorted in graph
order, in particular for the partition management code to correctly
compute partitions from source to sink. The media graph walk API happens
to produce that order, but doesn't offer any guarantee, which makes the
code fairly fragile. Harden it by sorting the list in the order we need.

While at it fix an unrelated white space issue.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../media/platform/renesas/vsp1/vsp1_entity.c |  1 -
 .../media/platform/renesas/vsp1/vsp1_video.c  | 66 +++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.c b/drivers/media/platform/renesas/vsp1/vsp1_entity.c
index 8b8945bd8f10..b2e6c0ed8744 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.c
@@ -500,7 +500,6 @@  struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad)
 	}
 
 	return NULL;
-
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c
index ca2d00c9be35..f0288968bd55 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_video.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c
@@ -442,6 +442,7 @@  static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 	struct media_graph graph;
 	struct media_entity *entity = &video->video.entity;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct list_head *cursor;
 	unsigned int i;
 	int ret;
 
@@ -520,6 +521,71 @@  static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 			return ret;
 	}
 
+	/*
+	 * Sort the pipe->entities list from RPF to WPF, as the partition code
+	 * relies on that order. Iterate over the list in reverse order and
+	 * place each entry before any entry that follows it in pipeline order.
+	 *
+	 * The cursor points to the list entry immediately after the entry
+	 * being processed. When the cursor reaches the entry after the list
+	 * head we are thus done.
+	 */
+	for (cursor = &pipe->entities; cursor->prev != &pipe->entities; ) {
+		struct vsp1_entity *to_sort;
+		struct vsp1_entity *e;
+
+		/*
+		 * Sort the entity just before the cursor. Place it before the
+		 * first entry in the list that is connected to the sort
+		 * entry's source pad.
+		 */
+		to_sort = list_entry(cursor->prev, struct vsp1_entity, list_pipe);
+
+		list_for_each_entry(e, &pipe->entities, list_pipe) {
+			struct media_link *link;
+			struct media_pad *pad;
+			bool connected = false;
+
+			if (e == to_sort)
+				break;
+
+			/*
+			 * Check if to_sort's source pad is connected through
+			 * an active link to entity e.
+			 */
+			pad = &to_sort->pads[to_sort->source_pad];
+
+			list_for_each_entry(link, &pad->entity->links, list) {
+				if (!(link->flags & MEDIA_LNK_FL_ENABLED) ||
+				    link->source != pad)
+					continue;
+
+				if (link->sink->entity == &e->subdev.entity) {
+					connected = true;
+					break;
+				}
+			}
+
+			/* If connected, move to_sort right before e. */
+			if (connected) {
+				dev_dbg(video->vsp1->dev,
+					"sorting pipeline: moving %s before %s\n",
+					to_sort->subdev.name, e->subdev.name);
+				list_move_tail(&to_sort->list_pipe, &e->list_pipe);
+				break;
+			}
+		}
+
+		/*
+		 * If the entry before the cursor hasn't changed it means it's
+		 * correctly positioned, and the cursor can then be updated.
+		 * Otherwise the next iteration will process the cursor's new
+		 * previous entry.
+		 */
+		if (cursor->prev == &to_sort->list_pipe)
+			cursor = cursor->prev;
+	}
+
 	vsp1_pipeline_dump(pipe, "video");
 
 	return 0;