clear-pkgs-linux-iot-lts2018/0049-media-Use-routing-info...

212 lines
6.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Meng Wei <wei.meng@intel.com>
Date: Fri, 26 Oct 2018 09:52:19 +0800
Subject: [PATCH] media: Use routing info during graph traversal
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
index 3498551e618e..0ad584518db7 100644
--- 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
index 3aa3d58d1d58..0faaf936302b 100644
--- 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
--
https://clearlinux.org