xref: /openbmc/linux/drivers/media/mc/mc-entity.c (revision 84564481)
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 		ret = media_graph_walk_init(&pipe->graph, mdev);
401 		if (ret)
402 			goto error_graph_walk_start;
403 	}
404 
405 	media_graph_walk_start(&pipe->graph, entity);
406 
407 	while ((entity = media_graph_walk_next(graph))) {
408 		DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
409 		DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
410 
411 		entity->stream_count++;
412 
413 		if (entity->pipe && entity->pipe != pipe) {
414 			pr_err("Pipe active for %s. Can't start for %s\n",
415 				entity->name,
416 				entity_err->name);
417 			ret = -EBUSY;
418 			goto error;
419 		}
420 
421 		entity->pipe = pipe;
422 
423 		/* Already streaming --- no need to check. */
424 		if (entity->stream_count > 1)
425 			continue;
426 
427 		if (!entity->ops || !entity->ops->link_validate)
428 			continue;
429 
430 		bitmap_zero(active, entity->num_pads);
431 		bitmap_fill(has_no_links, entity->num_pads);
432 
433 		list_for_each_entry(link, &entity->links, list) {
434 			struct media_pad *pad = link->sink->entity == entity
435 						? link->sink : link->source;
436 
437 			/* Mark that a pad is connected by a link. */
438 			bitmap_clear(has_no_links, pad->index, 1);
439 
440 			/*
441 			 * Pads that either do not need to connect or
442 			 * are connected through an enabled link are
443 			 * fine.
444 			 */
445 			if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
446 			    link->flags & MEDIA_LNK_FL_ENABLED)
447 				bitmap_set(active, pad->index, 1);
448 
449 			/*
450 			 * Link validation will only take place for
451 			 * sink ends of the link that are enabled.
452 			 */
453 			if (link->sink != pad ||
454 			    !(link->flags & MEDIA_LNK_FL_ENABLED))
455 				continue;
456 
457 			ret = entity->ops->link_validate(link);
458 			if (ret < 0 && ret != -ENOIOCTLCMD) {
459 				dev_dbg(entity->graph_obj.mdev->dev,
460 					"link validation failed for '%s':%u -> '%s':%u, error %d\n",
461 					link->source->entity->name,
462 					link->source->index,
463 					entity->name, link->sink->index, ret);
464 				goto error;
465 			}
466 		}
467 
468 		/* Either no links or validated links are fine. */
469 		bitmap_or(active, active, has_no_links, entity->num_pads);
470 
471 		if (!bitmap_full(active, entity->num_pads)) {
472 			ret = -ENOLINK;
473 			dev_dbg(entity->graph_obj.mdev->dev,
474 				"'%s':%u must be connected by an enabled link\n",
475 				entity->name,
476 				(unsigned)find_first_zero_bit(
477 					active, entity->num_pads));
478 			goto error;
479 		}
480 	}
481 
482 	return 0;
483 
484 error:
485 	/*
486 	 * Link validation on graph failed. We revert what we did and
487 	 * return the error.
488 	 */
489 	media_graph_walk_start(graph, entity_err);
490 
491 	while ((entity_err = media_graph_walk_next(graph))) {
492 		/* Sanity check for negative stream_count */
493 		if (!WARN_ON_ONCE(entity_err->stream_count <= 0)) {
494 			entity_err->stream_count--;
495 			if (entity_err->stream_count == 0)
496 				entity_err->pipe = NULL;
497 		}
498 
499 		/*
500 		 * We haven't increased stream_count further than this
501 		 * so we quit here.
502 		 */
503 		if (entity_err == entity)
504 			break;
505 	}
506 
507 error_graph_walk_start:
508 	if (!--pipe->streaming_count)
509 		media_graph_walk_cleanup(graph);
510 
511 	return ret;
512 }
513 EXPORT_SYMBOL_GPL(__media_pipeline_start);
514 
515 __must_check int media_pipeline_start(struct media_entity *entity,
516 				      struct media_pipeline *pipe)
517 {
518 	struct media_device *mdev = entity->graph_obj.mdev;
519 	int ret;
520 
521 	mutex_lock(&mdev->graph_mutex);
522 	ret = __media_pipeline_start(entity, pipe);
523 	mutex_unlock(&mdev->graph_mutex);
524 	return ret;
525 }
526 EXPORT_SYMBOL_GPL(media_pipeline_start);
527 
528 void __media_pipeline_stop(struct media_entity *entity)
529 {
530 	struct media_graph *graph = &entity->pipe->graph;
531 	struct media_pipeline *pipe = entity->pipe;
532 
533 	/*
534 	 * If the following check fails, the driver has performed an
535 	 * unbalanced call to media_pipeline_stop()
536 	 */
537 	if (WARN_ON(!pipe))
538 		return;
539 
540 	media_graph_walk_start(graph, entity);
541 
542 	while ((entity = media_graph_walk_next(graph))) {
543 		/* Sanity check for negative stream_count */
544 		if (!WARN_ON_ONCE(entity->stream_count <= 0)) {
545 			entity->stream_count--;
546 			if (entity->stream_count == 0)
547 				entity->pipe = NULL;
548 		}
549 	}
550 
551 	if (!--pipe->streaming_count)
552 		media_graph_walk_cleanup(graph);
553 
554 }
555 EXPORT_SYMBOL_GPL(__media_pipeline_stop);
556 
557 void media_pipeline_stop(struct media_entity *entity)
558 {
559 	struct media_device *mdev = entity->graph_obj.mdev;
560 
561 	mutex_lock(&mdev->graph_mutex);
562 	__media_pipeline_stop(entity);
563 	mutex_unlock(&mdev->graph_mutex);
564 }
565 EXPORT_SYMBOL_GPL(media_pipeline_stop);
566 
567 /* -----------------------------------------------------------------------------
568  * Links management
569  */
570 
571 static struct media_link *media_add_link(struct list_head *head)
572 {
573 	struct media_link *link;
574 
575 	link = kzalloc(sizeof(*link), GFP_KERNEL);
576 	if (link == NULL)
577 		return NULL;
578 
579 	list_add_tail(&link->list, head);
580 
581 	return link;
582 }
583 
584 static void __media_entity_remove_link(struct media_entity *entity,
585 				       struct media_link *link)
586 {
587 	struct media_link *rlink, *tmp;
588 	struct media_entity *remote;
589 
590 	if (link->source->entity == entity)
591 		remote = link->sink->entity;
592 	else
593 		remote = link->source->entity;
594 
595 	list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
596 		if (rlink != link->reverse)
597 			continue;
598 
599 		if (link->source->entity == entity)
600 			remote->num_backlinks--;
601 
602 		/* Remove the remote link */
603 		list_del(&rlink->list);
604 		media_gobj_destroy(&rlink->graph_obj);
605 		kfree(rlink);
606 
607 		if (--remote->num_links == 0)
608 			break;
609 	}
610 	list_del(&link->list);
611 	media_gobj_destroy(&link->graph_obj);
612 	kfree(link);
613 }
614 
615 int media_get_pad_index(struct media_entity *entity, bool is_sink,
616 			enum media_pad_signal_type sig_type)
617 {
618 	int i;
619 	bool pad_is_sink;
620 
621 	if (!entity)
622 		return -EINVAL;
623 
624 	for (i = 0; i < entity->num_pads; i++) {
625 		if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
626 			pad_is_sink = true;
627 		else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
628 			pad_is_sink = false;
629 		else
630 			continue;	/* This is an error! */
631 
632 		if (pad_is_sink != is_sink)
633 			continue;
634 		if (entity->pads[i].sig_type == sig_type)
635 			return i;
636 	}
637 	return -EINVAL;
638 }
639 EXPORT_SYMBOL_GPL(media_get_pad_index);
640 
641 int
642 media_create_pad_link(struct media_entity *source, u16 source_pad,
643 			 struct media_entity *sink, u16 sink_pad, u32 flags)
644 {
645 	struct media_link *link;
646 	struct media_link *backlink;
647 
648 	if (WARN_ON(!source || !sink) ||
649 	    WARN_ON(source_pad >= source->num_pads) ||
650 	    WARN_ON(sink_pad >= sink->num_pads))
651 		return -EINVAL;
652 	if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
653 		return -EINVAL;
654 	if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
655 		return -EINVAL;
656 
657 	link = media_add_link(&source->links);
658 	if (link == NULL)
659 		return -ENOMEM;
660 
661 	link->source = &source->pads[source_pad];
662 	link->sink = &sink->pads[sink_pad];
663 	link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
664 
665 	/* Initialize graph object embedded at the new link */
666 	media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
667 			&link->graph_obj);
668 
669 	/* Create the backlink. Backlinks are used to help graph traversal and
670 	 * are not reported to userspace.
671 	 */
672 	backlink = media_add_link(&sink->links);
673 	if (backlink == NULL) {
674 		__media_entity_remove_link(source, link);
675 		return -ENOMEM;
676 	}
677 
678 	backlink->source = &source->pads[source_pad];
679 	backlink->sink = &sink->pads[sink_pad];
680 	backlink->flags = flags;
681 	backlink->is_backlink = true;
682 
683 	/* Initialize graph object embedded at the new link */
684 	media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
685 			&backlink->graph_obj);
686 
687 	link->reverse = backlink;
688 	backlink->reverse = link;
689 
690 	sink->num_backlinks++;
691 	sink->num_links++;
692 	source->num_links++;
693 
694 	return 0;
695 }
696 EXPORT_SYMBOL_GPL(media_create_pad_link);
697 
698 int media_create_pad_links(const struct media_device *mdev,
699 			   const u32 source_function,
700 			   struct media_entity *source,
701 			   const u16 source_pad,
702 			   const u32 sink_function,
703 			   struct media_entity *sink,
704 			   const u16 sink_pad,
705 			   u32 flags,
706 			   const bool allow_both_undefined)
707 {
708 	struct media_entity *entity;
709 	unsigned function;
710 	int ret;
711 
712 	/* Trivial case: 1:1 relation */
713 	if (source && sink)
714 		return media_create_pad_link(source, source_pad,
715 					     sink, sink_pad, flags);
716 
717 	/* Worse case scenario: n:n relation */
718 	if (!source && !sink) {
719 		if (!allow_both_undefined)
720 			return 0;
721 		media_device_for_each_entity(source, mdev) {
722 			if (source->function != source_function)
723 				continue;
724 			media_device_for_each_entity(sink, mdev) {
725 				if (sink->function != sink_function)
726 					continue;
727 				ret = media_create_pad_link(source, source_pad,
728 							    sink, sink_pad,
729 							    flags);
730 				if (ret)
731 					return ret;
732 				flags &= ~(MEDIA_LNK_FL_ENABLED |
733 					   MEDIA_LNK_FL_IMMUTABLE);
734 			}
735 		}
736 		return 0;
737 	}
738 
739 	/* Handle 1:n and n:1 cases */
740 	if (source)
741 		function = sink_function;
742 	else
743 		function = source_function;
744 
745 	media_device_for_each_entity(entity, mdev) {
746 		if (entity->function != function)
747 			continue;
748 
749 		if (source)
750 			ret = media_create_pad_link(source, source_pad,
751 						    entity, sink_pad, flags);
752 		else
753 			ret = media_create_pad_link(entity, source_pad,
754 						    sink, sink_pad, flags);
755 		if (ret)
756 			return ret;
757 		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
758 	}
759 	return 0;
760 }
761 EXPORT_SYMBOL_GPL(media_create_pad_links);
762 
763 void __media_entity_remove_links(struct media_entity *entity)
764 {
765 	struct media_link *link, *tmp;
766 
767 	list_for_each_entry_safe(link, tmp, &entity->links, list)
768 		__media_entity_remove_link(entity, link);
769 
770 	entity->num_links = 0;
771 	entity->num_backlinks = 0;
772 }
773 EXPORT_SYMBOL_GPL(__media_entity_remove_links);
774 
775 void media_entity_remove_links(struct media_entity *entity)
776 {
777 	struct media_device *mdev = entity->graph_obj.mdev;
778 
779 	/* Do nothing if the entity is not registered. */
780 	if (mdev == NULL)
781 		return;
782 
783 	mutex_lock(&mdev->graph_mutex);
784 	__media_entity_remove_links(entity);
785 	mutex_unlock(&mdev->graph_mutex);
786 }
787 EXPORT_SYMBOL_GPL(media_entity_remove_links);
788 
789 static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
790 {
791 	int ret;
792 
793 	/* Notify both entities. */
794 	ret = media_entity_call(link->source->entity, link_setup,
795 				link->source, link->sink, flags);
796 	if (ret < 0 && ret != -ENOIOCTLCMD)
797 		return ret;
798 
799 	ret = media_entity_call(link->sink->entity, link_setup,
800 				link->sink, link->source, flags);
801 	if (ret < 0 && ret != -ENOIOCTLCMD) {
802 		media_entity_call(link->source->entity, link_setup,
803 				  link->source, link->sink, link->flags);
804 		return ret;
805 	}
806 
807 	link->flags = flags;
808 	link->reverse->flags = link->flags;
809 
810 	return 0;
811 }
812 
813 int __media_entity_setup_link(struct media_link *link, u32 flags)
814 {
815 	const u32 mask = MEDIA_LNK_FL_ENABLED;
816 	struct media_device *mdev;
817 	struct media_entity *source, *sink;
818 	int ret = -EBUSY;
819 
820 	if (link == NULL)
821 		return -EINVAL;
822 
823 	/* The non-modifiable link flags must not be modified. */
824 	if ((link->flags & ~mask) != (flags & ~mask))
825 		return -EINVAL;
826 
827 	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
828 		return link->flags == flags ? 0 : -EINVAL;
829 
830 	if (link->flags == flags)
831 		return 0;
832 
833 	source = link->source->entity;
834 	sink = link->sink->entity;
835 
836 	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
837 	    (source->stream_count || sink->stream_count))
838 		return -EBUSY;
839 
840 	mdev = source->graph_obj.mdev;
841 
842 	if (mdev->ops && mdev->ops->link_notify) {
843 		ret = mdev->ops->link_notify(link, flags,
844 					     MEDIA_DEV_NOTIFY_PRE_LINK_CH);
845 		if (ret < 0)
846 			return ret;
847 	}
848 
849 	ret = __media_entity_setup_link_notify(link, flags);
850 
851 	if (mdev->ops && mdev->ops->link_notify)
852 		mdev->ops->link_notify(link, flags,
853 				       MEDIA_DEV_NOTIFY_POST_LINK_CH);
854 
855 	return ret;
856 }
857 EXPORT_SYMBOL_GPL(__media_entity_setup_link);
858 
859 int media_entity_setup_link(struct media_link *link, u32 flags)
860 {
861 	int ret;
862 
863 	mutex_lock(&link->graph_obj.mdev->graph_mutex);
864 	ret = __media_entity_setup_link(link, flags);
865 	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
866 
867 	return ret;
868 }
869 EXPORT_SYMBOL_GPL(media_entity_setup_link);
870 
871 struct media_link *
872 media_entity_find_link(struct media_pad *source, struct media_pad *sink)
873 {
874 	struct media_link *link;
875 
876 	list_for_each_entry(link, &source->entity->links, list) {
877 		if (link->source->entity == source->entity &&
878 		    link->source->index == source->index &&
879 		    link->sink->entity == sink->entity &&
880 		    link->sink->index == sink->index)
881 			return link;
882 	}
883 
884 	return NULL;
885 }
886 EXPORT_SYMBOL_GPL(media_entity_find_link);
887 
888 struct media_pad *media_entity_remote_pad(const struct media_pad *pad)
889 {
890 	struct media_link *link;
891 
892 	list_for_each_entry(link, &pad->entity->links, list) {
893 		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
894 			continue;
895 
896 		if (link->source == pad)
897 			return link->sink;
898 
899 		if (link->sink == pad)
900 			return link->source;
901 	}
902 
903 	return NULL;
904 
905 }
906 EXPORT_SYMBOL_GPL(media_entity_remote_pad);
907 
908 static void media_interface_init(struct media_device *mdev,
909 				 struct media_interface *intf,
910 				 u32 gobj_type,
911 				 u32 intf_type, u32 flags)
912 {
913 	intf->type = intf_type;
914 	intf->flags = flags;
915 	INIT_LIST_HEAD(&intf->links);
916 
917 	media_gobj_create(mdev, gobj_type, &intf->graph_obj);
918 }
919 
920 /* Functions related to the media interface via device nodes */
921 
922 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
923 						u32 type, u32 flags,
924 						u32 major, u32 minor)
925 {
926 	struct media_intf_devnode *devnode;
927 
928 	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
929 	if (!devnode)
930 		return NULL;
931 
932 	devnode->major = major;
933 	devnode->minor = minor;
934 
935 	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
936 			     type, flags);
937 
938 	return devnode;
939 }
940 EXPORT_SYMBOL_GPL(media_devnode_create);
941 
942 void media_devnode_remove(struct media_intf_devnode *devnode)
943 {
944 	media_remove_intf_links(&devnode->intf);
945 	media_gobj_destroy(&devnode->intf.graph_obj);
946 	kfree(devnode);
947 }
948 EXPORT_SYMBOL_GPL(media_devnode_remove);
949 
950 struct media_link *media_create_intf_link(struct media_entity *entity,
951 					    struct media_interface *intf,
952 					    u32 flags)
953 {
954 	struct media_link *link;
955 
956 	link = media_add_link(&intf->links);
957 	if (link == NULL)
958 		return NULL;
959 
960 	link->intf = intf;
961 	link->entity = entity;
962 	link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
963 
964 	/* Initialize graph object embedded at the new link */
965 	media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
966 			&link->graph_obj);
967 
968 	return link;
969 }
970 EXPORT_SYMBOL_GPL(media_create_intf_link);
971 
972 void __media_remove_intf_link(struct media_link *link)
973 {
974 	list_del(&link->list);
975 	media_gobj_destroy(&link->graph_obj);
976 	kfree(link);
977 }
978 EXPORT_SYMBOL_GPL(__media_remove_intf_link);
979 
980 void media_remove_intf_link(struct media_link *link)
981 {
982 	struct media_device *mdev = link->graph_obj.mdev;
983 
984 	/* Do nothing if the intf is not registered. */
985 	if (mdev == NULL)
986 		return;
987 
988 	mutex_lock(&mdev->graph_mutex);
989 	__media_remove_intf_link(link);
990 	mutex_unlock(&mdev->graph_mutex);
991 }
992 EXPORT_SYMBOL_GPL(media_remove_intf_link);
993 
994 void __media_remove_intf_links(struct media_interface *intf)
995 {
996 	struct media_link *link, *tmp;
997 
998 	list_for_each_entry_safe(link, tmp, &intf->links, list)
999 		__media_remove_intf_link(link);
1000 
1001 }
1002 EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1003 
1004 void media_remove_intf_links(struct media_interface *intf)
1005 {
1006 	struct media_device *mdev = intf->graph_obj.mdev;
1007 
1008 	/* Do nothing if the intf is not registered. */
1009 	if (mdev == NULL)
1010 		return;
1011 
1012 	mutex_lock(&mdev->graph_mutex);
1013 	__media_remove_intf_links(intf);
1014 	mutex_unlock(&mdev->graph_mutex);
1015 }
1016 EXPORT_SYMBOL_GPL(media_remove_intf_links);
1017