This repository has been archived by the owner on Jul 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
0049-media-Use-routing-info-during-graph-traversal.patch
211 lines (189 loc) · 6.59 KB
/
0049-media-Use-routing-info-during-graph-traversal.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Meng Wei <[email protected]>
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 <[email protected]>
Signed-off-by: Meng Wei <[email protected]>
---
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