xref: /openbmc/linux/drivers/media/mc/mc-entity.c (revision 6eaff06a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Media entity
4  *
5  * Copyright (C) 2010 Nokia Corporation
6  *
7  * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8  *	     Sakari Ailus <sakari.ailus@iki.fi>
9  */
10 
11 #include <linux/bitmap.h>
12 #include <linux/list.h>
13 #include <linux/property.h>
14 #include <linux/slab.h>
15 #include <media/media-entity.h>
16 #include <media/media-device.h>
17 
18 static inline const char *intf_type(struct media_interface *intf)
19 {
20 	switch (intf->type) {
21 	case MEDIA_INTF_T_DVB_FE:
22 		return "dvb-frontend";
23 	case MEDIA_INTF_T_DVB_DEMUX:
24 		return "dvb-demux";
25 	case MEDIA_INTF_T_DVB_DVR:
26 		return "dvb-dvr";
27 	case MEDIA_INTF_T_DVB_CA:
28 		return  "dvb-ca";
29 	case MEDIA_INTF_T_DVB_NET:
30 		return "dvb-net";
31 	case MEDIA_INTF_T_V4L_VIDEO:
32 		return "v4l-video";
33 	case MEDIA_INTF_T_V4L_VBI:
34 		return "v4l-vbi";
35 	case MEDIA_INTF_T_V4L_RADIO:
36 		return "v4l-radio";
37 	case MEDIA_INTF_T_V4L_SUBDEV:
38 		return "v4l-subdev";
39 	case MEDIA_INTF_T_V4L_SWRADIO:
40 		return "v4l-swradio";
41 	case MEDIA_INTF_T_V4L_TOUCH:
42 		return "v4l-touch";
43 	default:
44 		return "unknown-intf";
45 	}
46 };
47 
48 static inline const char *link_type_name(struct media_link *link)
49 {
50 	switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
51 	case MEDIA_LNK_FL_DATA_LINK:
52 		return "data";
53 	case MEDIA_LNK_FL_INTERFACE_LINK:
54 		return "interface";
55 	case MEDIA_LNK_FL_ANCILLARY_LINK:
56 		return "ancillary";
57 	default:
58 		return "unknown";
59 	}
60 }
61 
62 __must_check int media_entity_enum_init(struct media_entity_enum *ent_enum,
63 					struct media_device *mdev)
64 {
65 	int idx_max;
66 
67 	idx_max = ALIGN(mdev->entity_internal_idx_max + 1, BITS_PER_LONG);
68 	ent_enum->bmap = bitmap_zalloc(idx_max, GFP_KERNEL);
69 	if (!ent_enum->bmap)
70 		return -ENOMEM;
71 
72 	ent_enum->idx_max = idx_max;
73 
74 	return 0;
75 }
76 EXPORT_SYMBOL_GPL(media_entity_enum_init);
77 
78 void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
79 {
80 	bitmap_free(ent_enum->bmap);
81 }
82 EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
83 
84 /**
85  *  dev_dbg_obj - Prints in debug mode a change on some object
86  *
87  * @event_name:	Name of the event to report. Could be __func__
88  * @gobj:	Pointer to the object
89  *
90  * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
91  * won't produce any code.
92  */
93 static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
94 {
95 #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
96 	switch (media_type(gobj)) {
97 	case MEDIA_GRAPH_ENTITY:
98 		dev_dbg(gobj->mdev->dev,
99 			"%s id %u: entity '%s'\n",
100 			event_name, media_id(gobj),
101 			gobj_to_entity(gobj)->name);
102 		break;
103 	case MEDIA_GRAPH_LINK:
104 	{
105 		struct media_link *link = gobj_to_link(gobj);
106 
107 		dev_dbg(gobj->mdev->dev,
108 			"%s id %u: %s link id %u ==> id %u\n",
109 			event_name, media_id(gobj), link_type_name(link),
110 			media_id(link->gobj0),
111 			media_id(link->gobj1));
112 		break;
113 	}
114 	case MEDIA_GRAPH_PAD:
115 	{
116 		struct media_pad *pad = gobj_to_pad(gobj);
117 
118 		dev_dbg(gobj->mdev->dev,
119 			"%s id %u: %s%spad '%s':%d\n",
120 			event_name, media_id(gobj),
121 			pad->flags & MEDIA_PAD_FL_SINK   ? "sink " : "",
122 			pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "",
123 			pad->entity->name, pad->index);
124 		break;
125 	}
126 	case MEDIA_GRAPH_INTF_DEVNODE:
127 	{
128 		struct media_interface *intf = gobj_to_intf(gobj);
129 		struct media_intf_devnode *devnode = intf_to_devnode(intf);
130 
131 		dev_dbg(gobj->mdev->dev,
132 			"%s id %u: intf_devnode %s - major: %d, minor: %d\n",
133 			event_name, media_id(gobj),
134 			intf_type(intf),
135 			devnode->major, devnode->minor);
136 		break;
137 	}
138 	}
139 #endif
140 }
141 
142 void media_gobj_create(struct media_device *mdev,
143 			   enum media_gobj_type type,
144 			   struct media_gobj *gobj)
145 {
146 	BUG_ON(!mdev);
147 
148 	gobj->mdev = mdev;
149 
150 	/* Create a per-type unique object ID */
151 	gobj->id = media_gobj_gen_id(type, ++mdev->id);
152 
153 	switch (type) {
154 	case MEDIA_GRAPH_ENTITY:
155 		list_add_tail(&gobj->list, &mdev->entities);
156 		break;
157 	case MEDIA_GRAPH_PAD:
158 		list_add_tail(&gobj->list, &mdev->pads);
159 		break;
160 	case MEDIA_GRAPH_LINK:
161 		list_add_tail(&gobj->list, &mdev->links);
162 		break;
163 	case MEDIA_GRAPH_INTF_DEVNODE:
164 		list_add_tail(&gobj->list, &mdev->interfaces);
165 		break;
166 	}
167 
168 	mdev->topology_version++;
169 
170 	dev_dbg_obj(__func__, gobj);
171 }
172 
173 void media_gobj_destroy(struct media_gobj *gobj)
174 {
175 	/* Do nothing if the object is not linked. */
176 	if (gobj->mdev == NULL)
177 		return;
178 
179 	dev_dbg_obj(__func__, gobj);
180 
181 	gobj->mdev->topology_version++;
182 
183 	/* Remove the object from mdev list */
184 	list_del(&gobj->list);
185 
186 	gobj->mdev = NULL;
187 }
188 
189 /*
190  * TODO: Get rid of this.
191  */
192 #define MEDIA_ENTITY_MAX_PADS		512
193 
194 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
195 			   struct media_pad *pads)
196 {
197 	struct media_device *mdev = entity->graph_obj.mdev;
198 	struct media_pad *iter;
199 	unsigned int i = 0;
200 
201 	if (num_pads >= MEDIA_ENTITY_MAX_PADS)
202 		return -E2BIG;
203 
204 	entity->num_pads = num_pads;
205 	entity->pads = pads;
206 
207 	if (mdev)
208 		mutex_lock(&mdev->graph_mutex);
209 
210 	media_entity_for_each_pad(entity, iter) {
211 		iter->entity = entity;
212 		iter->index = i++;
213 		if (mdev)
214 			media_gobj_create(mdev, MEDIA_GRAPH_PAD,
215 					  &iter->graph_obj);
216 	}
217 
218 	if (mdev)
219 		mutex_unlock(&mdev->graph_mutex);
220 
221 	return 0;
222 }
223 EXPORT_SYMBOL_GPL(media_entity_pads_init);
224 
225 /* -----------------------------------------------------------------------------
226  * Graph traversal
227  */
228 
229 static struct media_entity *
230 media_entity_other(struct media_entity *entity, struct media_link *link)
231 {
232 	if (link->source->entity == entity)
233 		return link->sink->entity;
234 	else
235 		return link->source->entity;
236 }
237 
238 /* push an entity to traversal stack */
239 static void stack_push(struct media_graph *graph,
240 		       struct media_entity *entity)
241 {
242 	if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
243 		WARN_ON(1);
244 		return;
245 	}
246 	graph->top++;
247 	graph->stack[graph->top].link = entity->links.next;
248 	graph->stack[graph->top].entity = entity;
249 }
250 
251 static struct media_entity *stack_pop(struct media_graph *graph)
252 {
253 	struct media_entity *entity;
254 
255 	entity = graph->stack[graph->top].entity;
256 	graph->top--;
257 
258 	return entity;
259 }
260 
261 #define link_top(en)	((en)->stack[(en)->top].link)
262 #define stack_top(en)	((en)->stack[(en)->top].entity)
263 
264 /**
265  * media_graph_walk_init - Allocate resources for graph walk
266  * @graph: Media graph structure that will be used to walk the graph
267  * @mdev: Media device
268  *
269  * Reserve resources for graph walk in media device's current
270  * state. The memory must be released using
271  * media_graph_walk_free().
272  *
273  * Returns error on failure, zero on success.
274  */
275 __must_check int media_graph_walk_init(
276 	struct media_graph *graph, struct media_device *mdev)
277 {
278 	return media_entity_enum_init(&graph->ent_enum, mdev);
279 }
280 EXPORT_SYMBOL_GPL(media_graph_walk_init);
281 
282 /**
283  * media_graph_walk_cleanup - Release resources related to graph walking
284  * @graph: Media graph structure that was used to walk the graph
285  */
286 void media_graph_walk_cleanup(struct media_graph *graph)
287 {
288 	media_entity_enum_cleanup(&graph->ent_enum);
289 }
290 EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
291 
292 void media_graph_walk_start(struct media_graph *graph,
293 			    struct media_entity *entity)
294 {
295 	media_entity_enum_zero(&graph->ent_enum);
296 	media_entity_enum_set(&graph->ent_enum, entity);
297 
298 	graph->top = 0;
299 	graph->stack[graph->top].entity = NULL;
300 	stack_push(graph, entity);
301 	dev_dbg(entity->graph_obj.mdev->dev,
302 		"begin graph walk at '%s'\n", entity->name);
303 }
304 EXPORT_SYMBOL_GPL(media_graph_walk_start);
305 
306 static void media_graph_walk_iter(struct media_graph *graph)
307 {
308 	struct media_entity *entity = stack_top(graph);
309 	struct media_link *link;
310 	struct media_entity *next;
311 
312 	link = list_entry(link_top(graph), typeof(*link), list);
313 
314 	/* If the link is not a data link, don't follow it */
315 	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
316 		link_top(graph) = link_top(graph)->next;
317 		return;
318 	}
319 
320 	/* The link is not enabled so we do not follow. */
321 	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
322 		link_top(graph) = link_top(graph)->next;
323 		dev_dbg(entity->graph_obj.mdev->dev,
324 			"walk: skipping disabled link '%s':%u -> '%s':%u\n",
325 			link->source->entity->name, link->source->index,
326 			link->sink->entity->name, link->sink->index);
327 		return;
328 	}
329 
330 	/* Get the entity at the other end of the link. */
331 	next = media_entity_other(entity, link);
332 
333 	/* Has the entity already been visited? */
334 	if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
335 		link_top(graph) = link_top(graph)->next;
336 		dev_dbg(entity->graph_obj.mdev->dev,
337 			"walk: skipping entity '%s' (already seen)\n",
338 			next->name);
339 		return;
340 	}
341 
342 	/* Push the new entity to stack and start over. */
343 	link_top(graph) = link_top(graph)->next;
344 	stack_push(graph, next);
345 	dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
346 		next->name);
347 	lockdep_assert_held(&entity->graph_obj.mdev->graph_mutex);
348 }
349 
350 struct media_entity *media_graph_walk_next(struct media_graph *graph)
351 {
352 	struct media_entity *entity;
353 
354 	if (stack_top(graph) == NULL)
355 		return NULL;
356 
357 	/*
358 	 * Depth first search. Push entity to stack and continue from
359 	 * top of the stack until no more entities on the level can be
360 	 * found.
361 	 */
362 	while (link_top(graph) != &stack_top(graph)->links)
363 		media_graph_walk_iter(graph);
364 
365 	entity = stack_pop(graph);
366 	dev_dbg(entity->graph_obj.mdev->dev,
367 		"walk: returning entity '%s'\n", entity->name);
368 
369 	return entity;
370 }
371 EXPORT_SYMBOL_GPL(media_graph_walk_next);
372 
373 /* -----------------------------------------------------------------------------
374  * Pipeline management
375  */
376 
377 __must_check int __media_pipeline_start(struct media_entity *entity,
378 					struct media_pipeline *pipe)
379 {
380 	struct media_device *mdev = entity->graph_obj.mdev;
381 	struct media_graph *graph = &pipe->graph;
382 	struct media_entity *entity_err = entity;
383 	struct media_link *link;
384 	int ret;
385 
386 	if (pipe->start_count) {
387 		pipe->start_count++;
388 		return 0;
389 	}
390 
391 	ret = media_graph_walk_init(&pipe->graph, mdev);
392 	if (ret)
393 		return ret;
394 
395 	media_graph_walk_start(&pipe->graph, entity);
396 
397 	while ((entity = media_graph_walk_next(graph))) {
398 		DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
399 		DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
400 
401 		if (entity->pipe && entity->pipe != pipe) {
402 			pr_err("Pipe active for %s. Can't start for %s\n",
403 				entity->name,
404 				entity_err->name);
405 			ret = -EBUSY;
406 			goto error;
407 		}
408 
409 		/* Already streaming --- no need to check. */
410 		if (entity->pipe)
411 			continue;
412 
413 		entity->pipe = pipe;
414 
415 		if (!entity->ops || !entity->ops->link_validate)
416 			continue;
417 
418 		bitmap_zero(active, entity->num_pads);
419 		bitmap_fill(has_no_links, entity->num_pads);
420 
421 		for_each_media_entity_data_link(entity, link) {
422 			struct media_pad *pad = link->sink->entity == entity
423 						? link->sink : link->source;
424 
425 			/* Mark that a pad is connected by a link. */
426 			bitmap_clear(has_no_links, pad->index, 1);
427 
428 			/*
429 			 * Pads that either do not need to connect or
430 			 * are connected through an enabled link are
431 			 * fine.
432 			 */
433 			if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
434 			    link->flags & MEDIA_LNK_FL_ENABLED)
435 				bitmap_set(active, pad->index, 1);
436 
437 			/*
438 			 * Link validation will only take place for
439 			 * sink ends of the link that are enabled.
440 			 */
441 			if (link->sink != pad ||
442 			    !(link->flags & MEDIA_LNK_FL_ENABLED))
443 				continue;
444 
445 			ret = entity->ops->link_validate(link);
446 			if (ret < 0 && ret != -ENOIOCTLCMD) {
447 				dev_dbg(entity->graph_obj.mdev->dev,
448 					"link validation failed for '%s':%u -> '%s':%u, error %d\n",
449 					link->source->entity->name,
450 					link->source->index,
451 					entity->name, link->sink->index, ret);
452 				goto error;
453 			}
454 		}
455 
456 		/* Either no links or validated links are fine. */
457 		bitmap_or(active, active, has_no_links, entity->num_pads);
458 
459 		if (!bitmap_full(active, entity->num_pads)) {
460 			ret = -ENOLINK;
461 			dev_dbg(entity->graph_obj.mdev->dev,
462 				"'%s':%u must be connected by an enabled link\n",
463 				entity->name,
464 				(unsigned)find_first_zero_bit(
465 					active, entity->num_pads));
466 			goto error;
467 		}
468 	}
469 
470 	pipe->start_count++;
471 
472 	return 0;
473 
474 error:
475 	/*
476 	 * Link validation on graph failed. We revert what we did and
477 	 * return the error.
478 	 */
479 	media_graph_walk_start(graph, entity_err);
480 
481 	while ((entity_err = media_graph_walk_next(graph))) {
482 		entity_err->pipe = NULL;
483 
484 		/*
485 		 * We haven't started entities further than this so we quit
486 		 * here.
487 		 */
488 		if (entity_err == entity)
489 			break;
490 	}
491 
492 	media_graph_walk_cleanup(graph);
493 
494 	return ret;
495 }
496 EXPORT_SYMBOL_GPL(__media_pipeline_start);
497 
498 __must_check int media_pipeline_start(struct media_entity *entity,
499 				      struct media_pipeline *pipe)
500 {
501 	struct media_device *mdev = entity->graph_obj.mdev;
502 	int ret;
503 
504 	mutex_lock(&mdev->graph_mutex);
505 	ret = __media_pipeline_start(entity, pipe);
506 	mutex_unlock(&mdev->graph_mutex);
507 	return ret;
508 }
509 EXPORT_SYMBOL_GPL(media_pipeline_start);
510 
511 void __media_pipeline_stop(struct media_entity *entity)
512 {
513 	struct media_graph *graph = &entity->pipe->graph;
514 	struct media_pipeline *pipe = entity->pipe;
515 
516 	/*
517 	 * If the following check fails, the driver has performed an
518 	 * unbalanced call to media_pipeline_stop()
519 	 */
520 	if (WARN_ON(!pipe))
521 		return;
522 
523 	if (--pipe->start_count)
524 		return;
525 
526 	media_graph_walk_start(graph, entity);
527 
528 	while ((entity = media_graph_walk_next(graph)))
529 		entity->pipe = NULL;
530 
531 	media_graph_walk_cleanup(graph);
532 
533 	if (pipe->allocated)
534 		kfree(pipe);
535 }
536 EXPORT_SYMBOL_GPL(__media_pipeline_stop);
537 
538 void media_pipeline_stop(struct media_entity *entity)
539 {
540 	struct media_device *mdev = entity->graph_obj.mdev;
541 
542 	mutex_lock(&mdev->graph_mutex);
543 	__media_pipeline_stop(entity);
544 	mutex_unlock(&mdev->graph_mutex);
545 }
546 EXPORT_SYMBOL_GPL(media_pipeline_stop);
547 
548 __must_check int media_pipeline_alloc_start(struct media_entity *entity)
549 {
550 	struct media_device *mdev = entity->graph_obj.mdev;
551 	struct media_pipeline *new_pipe = NULL;
552 	struct media_pipeline *pipe;
553 	int ret;
554 
555 	mutex_lock(&mdev->graph_mutex);
556 
557 	/*
558 	 * Is the entity already part of a pipeline? If not, we need to allocate
559 	 * a pipe.
560 	 */
561 	pipe = media_entity_pipeline(entity);
562 	if (!pipe) {
563 		new_pipe = kzalloc(sizeof(*new_pipe), GFP_KERNEL);
564 		if (!new_pipe) {
565 			ret = -ENOMEM;
566 			goto out;
567 		}
568 
569 		pipe = new_pipe;
570 		pipe->allocated = true;
571 	}
572 
573 	ret = __media_pipeline_start(entity, pipe);
574 	if (ret)
575 		kfree(new_pipe);
576 
577 out:
578 	mutex_unlock(&mdev->graph_mutex);
579 
580 	return ret;
581 }
582 EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
583 
584 /* -----------------------------------------------------------------------------
585  * Links management
586  */
587 
588 static struct media_link *media_add_link(struct list_head *head)
589 {
590 	struct media_link *link;
591 
592 	link = kzalloc(sizeof(*link), GFP_KERNEL);
593 	if (link == NULL)
594 		return NULL;
595 
596 	list_add_tail(&link->list, head);
597 
598 	return link;
599 }
600 
601 static void __media_entity_remove_link(struct media_entity *entity,
602 				       struct media_link *link)
603 {
604 	struct media_link *rlink, *tmp;
605 	struct media_entity *remote;
606 
607 	/* Remove the reverse links for a data link. */
608 	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
609 		if (link->source->entity == entity)
610 			remote = link->sink->entity;
611 		else
612 			remote = link->source->entity;
613 
614 		list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
615 			if (rlink != link->reverse)
616 				continue;
617 
618 			if (link->source->entity == entity)
619 				remote->num_backlinks--;
620 
621 			/* Remove the remote link */
622 			list_del(&rlink->list);
623 			media_gobj_destroy(&rlink->graph_obj);
624 			kfree(rlink);
625 
626 			if (--remote->num_links == 0)
627 				break;
628 		}
629 	}
630 
631 	list_del(&link->list);
632 	media_gobj_destroy(&link->graph_obj);
633 	kfree(link);
634 }
635 
636 int media_get_pad_index(struct media_entity *entity, bool is_sink,
637 			enum media_pad_signal_type sig_type)
638 {
639 	int i;
640 	bool pad_is_sink;
641 
642 	if (!entity)
643 		return -EINVAL;
644 
645 	for (i = 0; i < entity->num_pads; i++) {
646 		if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
647 			pad_is_sink = true;
648 		else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
649 			pad_is_sink = false;
650 		else
651 			continue;	/* This is an error! */
652 
653 		if (pad_is_sink != is_sink)
654 			continue;
655 		if (entity->pads[i].sig_type == sig_type)
656 			return i;
657 	}
658 	return -EINVAL;
659 }
660 EXPORT_SYMBOL_GPL(media_get_pad_index);
661 
662 int
663 media_create_pad_link(struct media_entity *source, u16 source_pad,
664 			 struct media_entity *sink, u16 sink_pad, u32 flags)
665 {
666 	struct media_link *link;
667 	struct media_link *backlink;
668 
669 	if (WARN_ON(!source || !sink) ||
670 	    WARN_ON(source_pad >= source->num_pads) ||
671 	    WARN_ON(sink_pad >= sink->num_pads))
672 		return -EINVAL;
673 	if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
674 		return -EINVAL;
675 	if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
676 		return -EINVAL;
677 
678 	link = media_add_link(&source->links);
679 	if (link == NULL)
680 		return -ENOMEM;
681 
682 	link->source = &source->pads[source_pad];
683 	link->sink = &sink->pads[sink_pad];
684 	link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
685 
686 	/* Initialize graph object embedded at the new link */
687 	media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
688 			&link->graph_obj);
689 
690 	/* Create the backlink. Backlinks are used to help graph traversal and
691 	 * are not reported to userspace.
692 	 */
693 	backlink = media_add_link(&sink->links);
694 	if (backlink == NULL) {
695 		__media_entity_remove_link(source, link);
696 		return -ENOMEM;
697 	}
698 
699 	backlink->source = &source->pads[source_pad];
700 	backlink->sink = &sink->pads[sink_pad];
701 	backlink->flags = flags;
702 	backlink->is_backlink = true;
703 
704 	/* Initialize graph object embedded at the new link */
705 	media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
706 			&backlink->graph_obj);
707 
708 	link->reverse = backlink;
709 	backlink->reverse = link;
710 
711 	sink->num_backlinks++;
712 	sink->num_links++;
713 	source->num_links++;
714 
715 	return 0;
716 }
717 EXPORT_SYMBOL_GPL(media_create_pad_link);
718 
719 int media_create_pad_links(const struct media_device *mdev,
720 			   const u32 source_function,
721 			   struct media_entity *source,
722 			   const u16 source_pad,
723 			   const u32 sink_function,
724 			   struct media_entity *sink,
725 			   const u16 sink_pad,
726 			   u32 flags,
727 			   const bool allow_both_undefined)
728 {
729 	struct media_entity *entity;
730 	unsigned function;
731 	int ret;
732 
733 	/* Trivial case: 1:1 relation */
734 	if (source && sink)
735 		return media_create_pad_link(source, source_pad,
736 					     sink, sink_pad, flags);
737 
738 	/* Worse case scenario: n:n relation */
739 	if (!source && !sink) {
740 		if (!allow_both_undefined)
741 			return 0;
742 		media_device_for_each_entity(source, mdev) {
743 			if (source->function != source_function)
744 				continue;
745 			media_device_for_each_entity(sink, mdev) {
746 				if (sink->function != sink_function)
747 					continue;
748 				ret = media_create_pad_link(source, source_pad,
749 							    sink, sink_pad,
750 							    flags);
751 				if (ret)
752 					return ret;
753 				flags &= ~(MEDIA_LNK_FL_ENABLED |
754 					   MEDIA_LNK_FL_IMMUTABLE);
755 			}
756 		}
757 		return 0;
758 	}
759 
760 	/* Handle 1:n and n:1 cases */
761 	if (source)
762 		function = sink_function;
763 	else
764 		function = source_function;
765 
766 	media_device_for_each_entity(entity, mdev) {
767 		if (entity->function != function)
768 			continue;
769 
770 		if (source)
771 			ret = media_create_pad_link(source, source_pad,
772 						    entity, sink_pad, flags);
773 		else
774 			ret = media_create_pad_link(entity, source_pad,
775 						    sink, sink_pad, flags);
776 		if (ret)
777 			return ret;
778 		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
779 	}
780 	return 0;
781 }
782 EXPORT_SYMBOL_GPL(media_create_pad_links);
783 
784 void __media_entity_remove_links(struct media_entity *entity)
785 {
786 	struct media_link *link, *tmp;
787 
788 	list_for_each_entry_safe(link, tmp, &entity->links, list)
789 		__media_entity_remove_link(entity, link);
790 
791 	entity->num_links = 0;
792 	entity->num_backlinks = 0;
793 }
794 EXPORT_SYMBOL_GPL(__media_entity_remove_links);
795 
796 void media_entity_remove_links(struct media_entity *entity)
797 {
798 	struct media_device *mdev = entity->graph_obj.mdev;
799 
800 	/* Do nothing if the entity is not registered. */
801 	if (mdev == NULL)
802 		return;
803 
804 	mutex_lock(&mdev->graph_mutex);
805 	__media_entity_remove_links(entity);
806 	mutex_unlock(&mdev->graph_mutex);
807 }
808 EXPORT_SYMBOL_GPL(media_entity_remove_links);
809 
810 static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
811 {
812 	int ret;
813 
814 	/* Notify both entities. */
815 	ret = media_entity_call(link->source->entity, link_setup,
816 				link->source, link->sink, flags);
817 	if (ret < 0 && ret != -ENOIOCTLCMD)
818 		return ret;
819 
820 	ret = media_entity_call(link->sink->entity, link_setup,
821 				link->sink, link->source, flags);
822 	if (ret < 0 && ret != -ENOIOCTLCMD) {
823 		media_entity_call(link->source->entity, link_setup,
824 				  link->source, link->sink, link->flags);
825 		return ret;
826 	}
827 
828 	link->flags = flags;
829 	link->reverse->flags = link->flags;
830 
831 	return 0;
832 }
833 
834 int __media_entity_setup_link(struct media_link *link, u32 flags)
835 {
836 	const u32 mask = MEDIA_LNK_FL_ENABLED;
837 	struct media_device *mdev;
838 	struct media_entity *source, *sink;
839 	int ret = -EBUSY;
840 
841 	if (link == NULL)
842 		return -EINVAL;
843 
844 	/* The non-modifiable link flags must not be modified. */
845 	if ((link->flags & ~mask) != (flags & ~mask))
846 		return -EINVAL;
847 
848 	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
849 		return link->flags == flags ? 0 : -EINVAL;
850 
851 	if (link->flags == flags)
852 		return 0;
853 
854 	source = link->source->entity;
855 	sink = link->sink->entity;
856 
857 	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
858 	    (media_entity_is_streaming(source) ||
859 	     media_entity_is_streaming(sink)))
860 		return -EBUSY;
861 
862 	mdev = source->graph_obj.mdev;
863 
864 	if (mdev->ops && mdev->ops->link_notify) {
865 		ret = mdev->ops->link_notify(link, flags,
866 					     MEDIA_DEV_NOTIFY_PRE_LINK_CH);
867 		if (ret < 0)
868 			return ret;
869 	}
870 
871 	ret = __media_entity_setup_link_notify(link, flags);
872 
873 	if (mdev->ops && mdev->ops->link_notify)
874 		mdev->ops->link_notify(link, flags,
875 				       MEDIA_DEV_NOTIFY_POST_LINK_CH);
876 
877 	return ret;
878 }
879 EXPORT_SYMBOL_GPL(__media_entity_setup_link);
880 
881 int media_entity_setup_link(struct media_link *link, u32 flags)
882 {
883 	int ret;
884 
885 	mutex_lock(&link->graph_obj.mdev->graph_mutex);
886 	ret = __media_entity_setup_link(link, flags);
887 	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
888 
889 	return ret;
890 }
891 EXPORT_SYMBOL_GPL(media_entity_setup_link);
892 
893 struct media_link *
894 media_entity_find_link(struct media_pad *source, struct media_pad *sink)
895 {
896 	struct media_link *link;
897 
898 	for_each_media_entity_data_link(source->entity, link) {
899 		if (link->source->entity == source->entity &&
900 		    link->source->index == source->index &&
901 		    link->sink->entity == sink->entity &&
902 		    link->sink->index == sink->index)
903 			return link;
904 	}
905 
906 	return NULL;
907 }
908 EXPORT_SYMBOL_GPL(media_entity_find_link);
909 
910 struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)
911 {
912 	struct media_link *link;
913 
914 	for_each_media_entity_data_link(pad->entity, link) {
915 		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
916 			continue;
917 
918 		if (link->source == pad)
919 			return link->sink;
920 
921 		if (link->sink == pad)
922 			return link->source;
923 	}
924 
925 	return NULL;
926 
927 }
928 EXPORT_SYMBOL_GPL(media_pad_remote_pad_first);
929 
930 struct media_pad *
931 media_entity_remote_pad_unique(const struct media_entity *entity,
932 			       unsigned int type)
933 {
934 	struct media_pad *pad = NULL;
935 	struct media_link *link;
936 
937 	list_for_each_entry(link, &entity->links, list) {
938 		struct media_pad *local_pad;
939 		struct media_pad *remote_pad;
940 
941 		if (((link->flags & MEDIA_LNK_FL_LINK_TYPE) !=
942 		     MEDIA_LNK_FL_DATA_LINK) ||
943 		    !(link->flags & MEDIA_LNK_FL_ENABLED))
944 			continue;
945 
946 		if (type == MEDIA_PAD_FL_SOURCE) {
947 			local_pad = link->sink;
948 			remote_pad = link->source;
949 		} else {
950 			local_pad = link->source;
951 			remote_pad = link->sink;
952 		}
953 
954 		if (local_pad->entity == entity) {
955 			if (pad)
956 				return ERR_PTR(-ENOTUNIQ);
957 
958 			pad = remote_pad;
959 		}
960 	}
961 
962 	if (!pad)
963 		return ERR_PTR(-ENOLINK);
964 
965 	return pad;
966 }
967 EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique);
968 
969 struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
970 {
971 	struct media_pad *found_pad = NULL;
972 	struct media_link *link;
973 
974 	list_for_each_entry(link, &pad->entity->links, list) {
975 		struct media_pad *remote_pad;
976 
977 		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
978 			continue;
979 
980 		if (link->sink == pad)
981 			remote_pad = link->source;
982 		else if (link->source == pad)
983 			remote_pad = link->sink;
984 		else
985 			continue;
986 
987 		if (found_pad)
988 			return ERR_PTR(-ENOTUNIQ);
989 
990 		found_pad = remote_pad;
991 	}
992 
993 	if (!found_pad)
994 		return ERR_PTR(-ENOLINK);
995 
996 	return found_pad;
997 }
998 EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
999 
1000 int media_entity_get_fwnode_pad(struct media_entity *entity,
1001 				struct fwnode_handle *fwnode,
1002 				unsigned long direction_flags)
1003 {
1004 	struct fwnode_endpoint endpoint;
1005 	unsigned int i;
1006 	int ret;
1007 
1008 	if (!entity->ops || !entity->ops->get_fwnode_pad) {
1009 		for (i = 0; i < entity->num_pads; i++) {
1010 			if (entity->pads[i].flags & direction_flags)
1011 				return i;
1012 		}
1013 
1014 		return -ENXIO;
1015 	}
1016 
1017 	ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
1018 	if (ret)
1019 		return ret;
1020 
1021 	ret = entity->ops->get_fwnode_pad(entity, &endpoint);
1022 	if (ret < 0)
1023 		return ret;
1024 
1025 	if (ret >= entity->num_pads)
1026 		return -ENXIO;
1027 
1028 	if (!(entity->pads[ret].flags & direction_flags))
1029 		return -ENXIO;
1030 
1031 	return ret;
1032 }
1033 EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
1034 
1035 struct media_pipeline *media_entity_pipeline(struct media_entity *entity)
1036 {
1037 	return entity->pipe;
1038 }
1039 EXPORT_SYMBOL_GPL(media_entity_pipeline);
1040 
1041 static void media_interface_init(struct media_device *mdev,
1042 				 struct media_interface *intf,
1043 				 u32 gobj_type,
1044 				 u32 intf_type, u32 flags)
1045 {
1046 	intf->type = intf_type;
1047 	intf->flags = flags;
1048 	INIT_LIST_HEAD(&intf->links);
1049 
1050 	media_gobj_create(mdev, gobj_type, &intf->graph_obj);
1051 }
1052 
1053 /* Functions related to the media interface via device nodes */
1054 
1055 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
1056 						u32 type, u32 flags,
1057 						u32 major, u32 minor)
1058 {
1059 	struct media_intf_devnode *devnode;
1060 
1061 	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
1062 	if (!devnode)
1063 		return NULL;
1064 
1065 	devnode->major = major;
1066 	devnode->minor = minor;
1067 
1068 	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
1069 			     type, flags);
1070 
1071 	return devnode;
1072 }
1073 EXPORT_SYMBOL_GPL(media_devnode_create);
1074 
1075 void media_devnode_remove(struct media_intf_devnode *devnode)
1076 {
1077 	media_remove_intf_links(&devnode->intf);
1078 	media_gobj_destroy(&devnode->intf.graph_obj);
1079 	kfree(devnode);
1080 }
1081 EXPORT_SYMBOL_GPL(media_devnode_remove);
1082 
1083 struct media_link *media_create_intf_link(struct media_entity *entity,
1084 					    struct media_interface *intf,
1085 					    u32 flags)
1086 {
1087 	struct media_link *link;
1088 
1089 	link = media_add_link(&intf->links);
1090 	if (link == NULL)
1091 		return NULL;
1092 
1093 	link->intf = intf;
1094 	link->entity = entity;
1095 	link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
1096 
1097 	/* Initialize graph object embedded at the new link */
1098 	media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
1099 			&link->graph_obj);
1100 
1101 	return link;
1102 }
1103 EXPORT_SYMBOL_GPL(media_create_intf_link);
1104 
1105 void __media_remove_intf_link(struct media_link *link)
1106 {
1107 	list_del(&link->list);
1108 	media_gobj_destroy(&link->graph_obj);
1109 	kfree(link);
1110 }
1111 EXPORT_SYMBOL_GPL(__media_remove_intf_link);
1112 
1113 void media_remove_intf_link(struct media_link *link)
1114 {
1115 	struct media_device *mdev = link->graph_obj.mdev;
1116 
1117 	/* Do nothing if the intf is not registered. */
1118 	if (mdev == NULL)
1119 		return;
1120 
1121 	mutex_lock(&mdev->graph_mutex);
1122 	__media_remove_intf_link(link);
1123 	mutex_unlock(&mdev->graph_mutex);
1124 }
1125 EXPORT_SYMBOL_GPL(media_remove_intf_link);
1126 
1127 void __media_remove_intf_links(struct media_interface *intf)
1128 {
1129 	struct media_link *link, *tmp;
1130 
1131 	list_for_each_entry_safe(link, tmp, &intf->links, list)
1132 		__media_remove_intf_link(link);
1133 
1134 }
1135 EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1136 
1137 void media_remove_intf_links(struct media_interface *intf)
1138 {
1139 	struct media_device *mdev = intf->graph_obj.mdev;
1140 
1141 	/* Do nothing if the intf is not registered. */
1142 	if (mdev == NULL)
1143 		return;
1144 
1145 	mutex_lock(&mdev->graph_mutex);
1146 	__media_remove_intf_links(intf);
1147 	mutex_unlock(&mdev->graph_mutex);
1148 }
1149 EXPORT_SYMBOL_GPL(media_remove_intf_links);
1150 
1151 struct media_link *media_create_ancillary_link(struct media_entity *primary,
1152 					       struct media_entity *ancillary)
1153 {
1154 	struct media_link *link;
1155 
1156 	link = media_add_link(&primary->links);
1157 	if (!link)
1158 		return ERR_PTR(-ENOMEM);
1159 
1160 	link->gobj0 = &primary->graph_obj;
1161 	link->gobj1 = &ancillary->graph_obj;
1162 	link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
1163 		      MEDIA_LNK_FL_ANCILLARY_LINK;
1164 
1165 	/* Initialize graph object embedded in the new link */
1166 	media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
1167 			  &link->graph_obj);
1168 
1169 	return link;
1170 }
1171 EXPORT_SYMBOL_GPL(media_create_ancillary_link);
1172 
1173 struct media_link *__media_entity_next_link(struct media_entity *entity,
1174 					    struct media_link *link,
1175 					    unsigned long link_type)
1176 {
1177 	link = link ? list_next_entry(link, list)
1178 		    : list_first_entry(&entity->links, typeof(*link), list);
1179 
1180 	list_for_each_entry_from(link, &entity->links, list)
1181 		if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == link_type)
1182 			return link;
1183 
1184 	return NULL;
1185 }
1186 EXPORT_SYMBOL_GPL(__media_entity_next_link);
1187