2019-03-29 14:12:17 +08:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2018-11-06 04:14:04 +08:00
|
|
|
From: Meng Wei <wei.meng@intel.com>
|
|
|
|
Date: Fri, 26 Oct 2018 09:52:19 +0800
|
2019-03-29 14:12:17 +08:00
|
|
|
Subject: [PATCH] media: Use routing info during graph traversal
|
2018-11-06 04:14:04 +08:00
|
|
|
|
|
|
|
Take internal routing information as reported
|
|
|
|
by the entity has_route operation into account
|
|
|
|
during graph traversal to avoid following
|
|
|
|
unrelated links.
|
|
|
|
|
|
|
|
Signed-off-by: Chang Ying <ying.chang@intel.com>
|
|
|
|
Signed-off-by: Meng Wei <wei.meng@intel.com>
|
|
|
|
---
|
|
|
|
drivers/media/media-entity.c | 82 +++++++++++++++++++++++++++---------
|
|
|
|
include/media/media-entity.h | 10 +++++
|
|
|
|
2 files changed, 72 insertions(+), 20 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index 3498551e618e..0ad584518db7 100644
|
2018-11-06 04:14:04 +08:00
|
|
|
--- a/drivers/media/media-entity.c
|
|
|
|
+++ b/drivers/media/media-entity.c
|
|
|
|
@@ -237,18 +237,38 @@ EXPORT_SYMBOL_GPL(media_entity_pads_init);
|
|
|
|
* Graph traversal
|
|
|
|
*/
|
|
|
|
|
|
|
|
-static struct media_entity *
|
|
|
|
-media_entity_other(struct media_entity *entity, struct media_link *link)
|
|
|
|
+/**
|
|
|
|
+ * media_entity_has_route - Check if two entity pads are connected internally
|
|
|
|
+ * @entity: The entity
|
|
|
|
+ * @pad0: The first pad index
|
|
|
|
+ * @pad1: The second pad index
|
|
|
|
+ *
|
|
|
|
+ * This function can be used to check whether two pads of an entity are
|
|
|
|
+ * connected internally in the entity.
|
|
|
|
+ *
|
|
|
|
+ * The caller must hold entity->source->parent->mutex.
|
|
|
|
+ *
|
|
|
|
+ * Return: true if the pads are connected internally and false otherwise.
|
|
|
|
+ */
|
|
|
|
+bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
|
|
|
|
+ unsigned int pad1)
|
|
|
|
{
|
|
|
|
- if (link->source->entity == entity)
|
|
|
|
- return link->sink->entity;
|
|
|
|
- else
|
|
|
|
- return link->source->entity;
|
|
|
|
+ if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ if (pad0 == pad1)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ if (!entity->ops || !entity->ops->has_route)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ return entity->ops->has_route(entity, pad0, pad1, NULL);
|
|
|
|
}
|
|
|
|
+EXPORT_SYMBOL_GPL(media_entity_has_route);
|
|
|
|
|
|
|
|
/* push an entity to traversal stack */
|
|
|
|
static void stack_push(struct media_graph *graph,
|
|
|
|
- struct media_entity *entity)
|
|
|
|
+ struct media_entity *entity, int pad, int stream)
|
|
|
|
{
|
|
|
|
if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
|
|
|
|
WARN_ON(1);
|
|
|
|
@@ -257,6 +277,8 @@ static void stack_push(struct media_graph *graph,
|
|
|
|
graph->top++;
|
|
|
|
graph->stack[graph->top].link = entity->links.next;
|
|
|
|
graph->stack[graph->top].entity = entity;
|
|
|
|
+ graph->stack[graph->top].pad = pad;
|
|
|
|
+ graph->stack[graph->top].stream = stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct media_entity *stack_pop(struct media_graph *graph)
|
|
|
|
@@ -271,6 +293,8 @@ static struct media_entity *stack_pop(struct media_graph *graph)
|
|
|
|
|
|
|
|
#define link_top(en) ((en)->stack[(en)->top].link)
|
|
|
|
#define stack_top(en) ((en)->stack[(en)->top].entity)
|
|
|
|
+#define pad_top(en) ((en)->stack[(en)->top].pad)
|
|
|
|
+#define stream_top(en) ((en)->stack[(en)->top].stream)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* media_graph_walk_init - Allocate resources for graph walk
|
|
|
|
@@ -308,7 +332,7 @@ void media_graph_walk_start(struct media_graph *graph,
|
|
|
|
|
|
|
|
graph->top = 0;
|
|
|
|
graph->stack[graph->top].entity = NULL;
|
|
|
|
- stack_push(graph, entity);
|
|
|
|
+ stack_push(graph, entity, 0, -1);
|
|
|
|
dev_dbg(entity->graph_obj.mdev->dev,
|
|
|
|
"begin graph walk at '%s'\n", entity->name);
|
|
|
|
}
|
|
|
|
@@ -319,6 +343,10 @@ static void media_graph_walk_iter(struct media_graph *graph)
|
|
|
|
struct media_entity *entity = stack_top(graph);
|
|
|
|
struct media_link *link;
|
|
|
|
struct media_entity *next;
|
|
|
|
+ struct media_pad *remote;
|
|
|
|
+ struct media_pad *local;
|
|
|
|
+ unsigned int from_pad = pad_top(graph);
|
|
|
|
+ int stream = stream_top(graph);
|
|
|
|
|
|
|
|
link = list_entry(link_top(graph), typeof(*link), list);
|
|
|
|
|
|
|
|
@@ -332,8 +360,31 @@ static void media_graph_walk_iter(struct media_graph *graph)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- /* Get the entity in the other end of the link . */
|
|
|
|
- next = media_entity_other(entity, link);
|
|
|
|
+ /*
|
|
|
|
+ * Get the local pad, the remote pad and the entity at the other
|
|
|
|
+ * end of the link.
|
|
|
|
+ */
|
|
|
|
+ if (link->source->entity == entity) {
|
|
|
|
+ remote = link->sink;
|
|
|
|
+ local = link->source;
|
|
|
|
+ } else {
|
|
|
|
+ remote = link->source;
|
|
|
|
+ local = link->sink;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ next = remote->entity;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Are the local pad and the pad we came from connected
|
|
|
|
+ * internally in the entity ?
|
|
|
|
+ */
|
|
|
|
+ if (entity->ops && entity->ops->has_route) {
|
|
|
|
+ if (!entity->ops->has_route(entity, from_pad,
|
|
|
|
+ local->index, &stream)) {
|
|
|
|
+ link_top(graph) = link_top(graph)->next;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/* Has the entity already been visited? */
|
|
|
|
if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
|
|
|
|
@@ -346,7 +397,7 @@ static void media_graph_walk_iter(struct media_graph *graph)
|
|
|
|
|
|
|
|
/* Push the new entity to stack and start over. */
|
|
|
|
link_top(graph) = link_top(graph)->next;
|
|
|
|
- stack_push(graph, next);
|
|
|
|
+ stack_push(graph, next, remote->index, stream);
|
|
|
|
dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
|
|
|
|
next->name);
|
|
|
|
}
|
|
|
|
@@ -436,17 +487,8 @@ __must_check int __media_pipeline_start(struct media_entity *entity,
|
|
|
|
|
|
|
|
entity->stream_count++;
|
|
|
|
|
|
|
|
- if (WARN_ON(entity->pipe && entity->pipe != pipe)) {
|
|
|
|
- ret = -EBUSY;
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
entity->pipe = pipe;
|
|
|
|
|
|
|
|
- /* Already streaming --- no need to check. */
|
|
|
|
- if (entity->stream_count > 1)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
if (!entity->ops || !entity->ops->link_validate)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
|
2020-10-27 02:14:06 +08:00
|
|
|
index 3aa3d58d1d58..0faaf936302b 100644
|
2018-11-06 04:14:04 +08:00
|
|
|
--- a/include/media/media-entity.h
|
|
|
|
+++ b/include/media/media-entity.h
|
|
|
|
@@ -97,6 +97,8 @@ struct media_graph {
|
|
|
|
struct {
|
|
|
|
struct media_entity *entity;
|
|
|
|
struct list_head *link;
|
|
|
|
+ int stream;
|
|
|
|
+ int pad;
|
|
|
|
} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
|
|
|
|
|
|
|
|
struct media_entity_enum ent_enum;
|
|
|
|
@@ -183,6 +185,9 @@ struct media_pad {
|
|
|
|
* @link_validate: Return whether a link is valid from the entity point of
|
|
|
|
* view. The media_pipeline_start() function
|
|
|
|
* validates all links by calling this operation. Optional.
|
|
|
|
+ * @has_route: Return whether a route exists inside the entity between
|
|
|
|
+ * two given pads. Optional. If the operation isn't
|
|
|
|
+ * implemented all pads will be considered as connected.
|
|
|
|
*
|
|
|
|
* .. note::
|
|
|
|
*
|
|
|
|
@@ -195,6 +200,8 @@ struct media_entity_operations {
|
|
|
|
const struct media_pad *local,
|
|
|
|
const struct media_pad *remote, u32 flags);
|
|
|
|
int (*link_validate)(struct media_link *link);
|
|
|
|
+ bool (*has_route)(struct media_entity *entity, unsigned int pad0,
|
|
|
|
+ unsigned int pad1, int *stream);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -879,6 +886,9 @@ void media_graph_walk_cleanup(struct media_graph *graph);
|
|
|
|
*/
|
|
|
|
void media_entity_put(struct media_entity *entity);
|
|
|
|
|
|
|
|
+bool media_entity_has_route(struct media_entity *entity, unsigned int sink,
|
|
|
|
+ unsigned int source);
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* media_graph_walk_start - Start walking the media graph at a
|
|
|
|
* given entity
|
|
|
|
--
|
2019-04-08 18:08:36 +08:00
|
|
|
https://clearlinux.org
|
2018-11-06 04:14:04 +08:00
|
|
|
|