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