Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   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
  18static 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
  48static 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}
  76EXPORT_SYMBOL_GPL(media_entity_enum_init);
  77
  78void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
  79{
  80	bitmap_free(ent_enum->bmap);
  81}
  82EXPORT_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 */
  93static 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
 142void 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
 173void 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
 194int 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}
 223EXPORT_SYMBOL_GPL(media_entity_pads_init);
 224
 225/* -----------------------------------------------------------------------------
 226 * Graph traversal
 227 */
 228
 229/*
 230 * This function checks the interdependency inside the entity between @pad0
 231 * and @pad1. If two pads are interdependent they are part of the same pipeline
 232 * and enabling one of the pads means that the other pad will become "locked"
 233 * and doesn't allow configuration changes.
 234 *
 235 * This function uses the &media_entity_operations.has_pad_interdep() operation
 236 * to check the dependency inside the entity between @pad0 and @pad1. If the
 237 * has_pad_interdep operation is not implemented, all pads of the entity are
 238 * considered to be interdependent.
 239 */
 240static bool media_entity_has_pad_interdep(struct media_entity *entity,
 241					  unsigned int pad0, unsigned int pad1)
 242{
 243	if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
 244		return false;
 245
 246	if (entity->pads[pad0].flags & entity->pads[pad1].flags &
 247	    (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE))
 248		return false;
 249
 250	if (!entity->ops || !entity->ops->has_pad_interdep)
 251		return true;
 252
 253	return entity->ops->has_pad_interdep(entity, pad0, pad1);
 254}
 255
 256static struct media_entity *
 257media_entity_other(struct media_entity *entity, struct media_link *link)
 258{
 259	if (link->source->entity == entity)
 260		return link->sink->entity;
 261	else
 262		return link->source->entity;
 263}
 264
 265/* push an entity to traversal stack */
 266static void stack_push(struct media_graph *graph,
 267		       struct media_entity *entity)
 268{
 269	if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
 270		WARN_ON(1);
 271		return;
 272	}
 273	graph->top++;
 274	graph->stack[graph->top].link = entity->links.next;
 275	graph->stack[graph->top].entity = entity;
 276}
 277
 278static struct media_entity *stack_pop(struct media_graph *graph)
 279{
 280	struct media_entity *entity;
 281
 282	entity = graph->stack[graph->top].entity;
 283	graph->top--;
 284
 285	return entity;
 286}
 287
 288#define link_top(en)	((en)->stack[(en)->top].link)
 289#define stack_top(en)	((en)->stack[(en)->top].entity)
 290
 291/**
 292 * media_graph_walk_init - Allocate resources for graph walk
 293 * @graph: Media graph structure that will be used to walk the graph
 294 * @mdev: Media device
 295 *
 296 * Reserve resources for graph walk in media device's current
 297 * state. The memory must be released using
 298 * media_graph_walk_free().
 299 *
 300 * Returns error on failure, zero on success.
 301 */
 302__must_check int media_graph_walk_init(
 303	struct media_graph *graph, struct media_device *mdev)
 304{
 305	return media_entity_enum_init(&graph->ent_enum, mdev);
 306}
 307EXPORT_SYMBOL_GPL(media_graph_walk_init);
 308
 309/**
 310 * media_graph_walk_cleanup - Release resources related to graph walking
 311 * @graph: Media graph structure that was used to walk the graph
 312 */
 313void media_graph_walk_cleanup(struct media_graph *graph)
 314{
 315	media_entity_enum_cleanup(&graph->ent_enum);
 316}
 317EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
 318
 319void media_graph_walk_start(struct media_graph *graph,
 320			    struct media_entity *entity)
 321{
 322	media_entity_enum_zero(&graph->ent_enum);
 323	media_entity_enum_set(&graph->ent_enum, entity);
 324
 325	graph->top = 0;
 326	graph->stack[graph->top].entity = NULL;
 327	stack_push(graph, entity);
 328	dev_dbg(entity->graph_obj.mdev->dev,
 329		"begin graph walk at '%s'\n", entity->name);
 330}
 331EXPORT_SYMBOL_GPL(media_graph_walk_start);
 332
 333static void media_graph_walk_iter(struct media_graph *graph)
 334{
 335	struct media_entity *entity = stack_top(graph);
 336	struct media_link *link;
 337	struct media_entity *next;
 338
 339	link = list_entry(link_top(graph), typeof(*link), list);
 340
 341	/* If the link is not a data link, don't follow it */
 342	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
 343		link_top(graph) = link_top(graph)->next;
 344		return;
 345	}
 346
 347	/* The link is not enabled so we do not follow. */
 348	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 349		link_top(graph) = link_top(graph)->next;
 350		dev_dbg(entity->graph_obj.mdev->dev,
 351			"walk: skipping disabled link '%s':%u -> '%s':%u\n",
 352			link->source->entity->name, link->source->index,
 353			link->sink->entity->name, link->sink->index);
 354		return;
 355	}
 356
 357	/* Get the entity at the other end of the link. */
 358	next = media_entity_other(entity, link);
 359
 360	/* Has the entity already been visited? */
 361	if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
 362		link_top(graph) = link_top(graph)->next;
 363		dev_dbg(entity->graph_obj.mdev->dev,
 364			"walk: skipping entity '%s' (already seen)\n",
 365			next->name);
 366		return;
 367	}
 368
 369	/* Push the new entity to stack and start over. */
 370	link_top(graph) = link_top(graph)->next;
 371	stack_push(graph, next);
 372	dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
 373		next->name);
 374	lockdep_assert_held(&entity->graph_obj.mdev->graph_mutex);
 375}
 376
 377struct media_entity *media_graph_walk_next(struct media_graph *graph)
 378{
 379	struct media_entity *entity;
 380
 381	if (stack_top(graph) == NULL)
 382		return NULL;
 383
 384	/*
 385	 * Depth first search. Push entity to stack and continue from
 386	 * top of the stack until no more entities on the level can be
 387	 * found.
 388	 */
 389	while (link_top(graph) != &stack_top(graph)->links)
 390		media_graph_walk_iter(graph);
 391
 392	entity = stack_pop(graph);
 393	dev_dbg(entity->graph_obj.mdev->dev,
 394		"walk: returning entity '%s'\n", entity->name);
 395
 396	return entity;
 397}
 398EXPORT_SYMBOL_GPL(media_graph_walk_next);
 399
 400/* -----------------------------------------------------------------------------
 401 * Pipeline management
 402 */
 403
 404/*
 405 * The pipeline traversal stack stores pads that are reached during graph
 406 * traversal, with a list of links to be visited to continue the traversal.
 407 * When a new pad is reached, an entry is pushed on the top of the stack and
 408 * points to the incoming pad and the first link of the entity.
 409 *
 410 * To find further pads in the pipeline, the traversal algorithm follows
 411 * internal pad dependencies in the entity, and then links in the graph. It
 412 * does so by iterating over all links of the entity, and following enabled
 413 * links that originate from a pad that is internally connected to the incoming
 414 * pad, as reported by the media_entity_has_pad_interdep() function.
 415 */
 416
 417/**
 418 * struct media_pipeline_walk_entry - Entry in the pipeline traversal stack
 419 *
 420 * @pad: The media pad being visited
 421 * @links: Links left to be visited
 422 */
 423struct media_pipeline_walk_entry {
 424	struct media_pad *pad;
 425	struct list_head *links;
 426};
 427
 428/**
 429 * struct media_pipeline_walk - State used by the media pipeline traversal
 430 *				algorithm
 431 *
 432 * @mdev: The media device
 433 * @stack: Depth-first search stack
 434 * @stack.size: Number of allocated entries in @stack.entries
 435 * @stack.top: Index of the top stack entry (-1 if the stack is empty)
 436 * @stack.entries: Stack entries
 437 */
 438struct media_pipeline_walk {
 439	struct media_device *mdev;
 440
 441	struct {
 442		unsigned int size;
 443		int top;
 444		struct media_pipeline_walk_entry *entries;
 445	} stack;
 446};
 447
 448#define MEDIA_PIPELINE_STACK_GROW_STEP		16
 449
 450static struct media_pipeline_walk_entry *
 451media_pipeline_walk_top(struct media_pipeline_walk *walk)
 452{
 453	return &walk->stack.entries[walk->stack.top];
 454}
 455
 456static bool media_pipeline_walk_empty(struct media_pipeline_walk *walk)
 457{
 458	return walk->stack.top == -1;
 459}
 460
 461/* Increase the stack size by MEDIA_PIPELINE_STACK_GROW_STEP elements. */
 462static int media_pipeline_walk_resize(struct media_pipeline_walk *walk)
 463{
 464	struct media_pipeline_walk_entry *entries;
 465	unsigned int new_size;
 466
 467	/* Safety check, to avoid stack overflows in case of bugs. */
 468	if (walk->stack.size >= 256)
 469		return -E2BIG;
 470
 471	new_size = walk->stack.size + MEDIA_PIPELINE_STACK_GROW_STEP;
 472
 473	entries = krealloc(walk->stack.entries,
 474			   new_size * sizeof(*walk->stack.entries),
 475			   GFP_KERNEL);
 476	if (!entries)
 477		return -ENOMEM;
 478
 479	walk->stack.entries = entries;
 480	walk->stack.size = new_size;
 481
 482	return 0;
 483}
 484
 485/* Push a new entry on the stack. */
 486static int media_pipeline_walk_push(struct media_pipeline_walk *walk,
 487				    struct media_pad *pad)
 488{
 489	struct media_pipeline_walk_entry *entry;
 490	int ret;
 491
 492	if (walk->stack.top + 1 >= walk->stack.size) {
 493		ret = media_pipeline_walk_resize(walk);
 494		if (ret)
 495			return ret;
 496	}
 497
 498	walk->stack.top++;
 499	entry = media_pipeline_walk_top(walk);
 500	entry->pad = pad;
 501	entry->links = pad->entity->links.next;
 502
 503	dev_dbg(walk->mdev->dev,
 504		"media pipeline: pushed entry %u: '%s':%u\n",
 505		walk->stack.top, pad->entity->name, pad->index);
 506
 507	return 0;
 508}
 509
 510/*
 511 * Move the top entry link cursor to the next link. If all links of the entry
 512 * have been visited, pop the entry itself.
 513 */
 514static void media_pipeline_walk_pop(struct media_pipeline_walk *walk)
 515{
 516	struct media_pipeline_walk_entry *entry;
 517
 518	if (WARN_ON(walk->stack.top < 0))
 519		return;
 520
 521	entry = media_pipeline_walk_top(walk);
 522
 523	if (entry->links->next == &entry->pad->entity->links) {
 524		dev_dbg(walk->mdev->dev,
 525			"media pipeline: entry %u has no more links, popping\n",
 526			walk->stack.top);
 527
 528		walk->stack.top--;
 529		return;
 530	}
 531
 532	entry->links = entry->links->next;
 533
 534	dev_dbg(walk->mdev->dev,
 535		"media pipeline: moved entry %u to next link\n",
 536		walk->stack.top);
 537}
 538
 539/* Free all memory allocated while walking the pipeline. */
 540static void media_pipeline_walk_destroy(struct media_pipeline_walk *walk)
 541{
 542	kfree(walk->stack.entries);
 543}
 544
 545/* Add a pad to the pipeline and push it to the stack. */
 546static int media_pipeline_add_pad(struct media_pipeline *pipe,
 547				  struct media_pipeline_walk *walk,
 548				  struct media_pad *pad)
 549{
 550	struct media_pipeline_pad *ppad;
 551
 552	list_for_each_entry(ppad, &pipe->pads, list) {
 553		if (ppad->pad == pad) {
 554			dev_dbg(pad->graph_obj.mdev->dev,
 555				"media pipeline: already contains pad '%s':%u\n",
 556				pad->entity->name, pad->index);
 557			return 0;
 558		}
 559	}
 560
 561	ppad = kzalloc(sizeof(*ppad), GFP_KERNEL);
 562	if (!ppad)
 563		return -ENOMEM;
 564
 565	ppad->pipe = pipe;
 566	ppad->pad = pad;
 567
 568	list_add_tail(&ppad->list, &pipe->pads);
 569
 570	dev_dbg(pad->graph_obj.mdev->dev,
 571		"media pipeline: added pad '%s':%u\n",
 572		pad->entity->name, pad->index);
 573
 574	return media_pipeline_walk_push(walk, pad);
 575}
 576
 577/* Explore the next link of the entity at the top of the stack. */
 578static int media_pipeline_explore_next_link(struct media_pipeline *pipe,
 579					    struct media_pipeline_walk *walk)
 580{
 581	struct media_pipeline_walk_entry *entry = media_pipeline_walk_top(walk);
 582	struct media_pad *pad;
 583	struct media_link *link;
 584	struct media_pad *local;
 585	struct media_pad *remote;
 586	int ret;
 587
 588	pad = entry->pad;
 589	link = list_entry(entry->links, typeof(*link), list);
 590	media_pipeline_walk_pop(walk);
 591
 592	dev_dbg(walk->mdev->dev,
 593		"media pipeline: exploring link '%s':%u -> '%s':%u\n",
 594		link->source->entity->name, link->source->index,
 595		link->sink->entity->name, link->sink->index);
 596
 597	/* Skip links that are not enabled. */
 598	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 599		dev_dbg(walk->mdev->dev,
 600			"media pipeline: skipping link (disabled)\n");
 601		return 0;
 602	}
 603
 604	/* Get the local pad and remote pad. */
 605	if (link->source->entity == pad->entity) {
 606		local = link->source;
 607		remote = link->sink;
 608	} else {
 609		local = link->sink;
 610		remote = link->source;
 611	}
 612
 613	/*
 614	 * Skip links that originate from a different pad than the incoming pad
 615	 * that is not connected internally in the entity to the incoming pad.
 616	 */
 617	if (pad != local &&
 618	    !media_entity_has_pad_interdep(pad->entity, pad->index, local->index)) {
 619		dev_dbg(walk->mdev->dev,
 620			"media pipeline: skipping link (no route)\n");
 621		return 0;
 622	}
 623
 624	/*
 625	 * Add the local and remote pads of the link to the pipeline and push
 626	 * them to the stack, if they're not already present.
 627	 */
 628	ret = media_pipeline_add_pad(pipe, walk, local);
 629	if (ret)
 630		return ret;
 631
 632	ret = media_pipeline_add_pad(pipe, walk, remote);
 633	if (ret)
 634		return ret;
 635
 636	return 0;
 637}
 638
 639static void media_pipeline_cleanup(struct media_pipeline *pipe)
 640{
 641	while (!list_empty(&pipe->pads)) {
 642		struct media_pipeline_pad *ppad;
 643
 644		ppad = list_first_entry(&pipe->pads, typeof(*ppad), list);
 645		list_del(&ppad->list);
 646		kfree(ppad);
 647	}
 648}
 649
 650static int media_pipeline_populate(struct media_pipeline *pipe,
 651				   struct media_pad *pad)
 652{
 653	struct media_pipeline_walk walk = { };
 654	struct media_pipeline_pad *ppad;
 655	int ret;
 656
 657	/*
 658	 * Populate the media pipeline by walking the media graph, starting
 659	 * from @pad.
 660	 */
 661	INIT_LIST_HEAD(&pipe->pads);
 662	pipe->mdev = pad->graph_obj.mdev;
 663
 664	walk.mdev = pipe->mdev;
 665	walk.stack.top = -1;
 666	ret = media_pipeline_add_pad(pipe, &walk, pad);
 667	if (ret)
 668		goto done;
 669
 670	/*
 671	 * Use a depth-first search algorithm: as long as the stack is not
 672	 * empty, explore the next link of the top entry. The
 673	 * media_pipeline_explore_next_link() function will either move to the
 674	 * next link, pop the entry if fully visited, or add new entries on
 675	 * top.
 676	 */
 677	while (!media_pipeline_walk_empty(&walk)) {
 678		ret = media_pipeline_explore_next_link(pipe, &walk);
 679		if (ret)
 680			goto done;
 681	}
 682
 683	dev_dbg(pad->graph_obj.mdev->dev,
 684		"media pipeline populated, found pads:\n");
 685
 686	list_for_each_entry(ppad, &pipe->pads, list)
 687		dev_dbg(pad->graph_obj.mdev->dev, "- '%s':%u\n",
 688			ppad->pad->entity->name, ppad->pad->index);
 689
 690	WARN_ON(walk.stack.top != -1);
 691
 692	ret = 0;
 693
 694done:
 695	media_pipeline_walk_destroy(&walk);
 696
 697	if (ret)
 698		media_pipeline_cleanup(pipe);
 699
 700	return ret;
 701}
 702
 703__must_check int __media_pipeline_start(struct media_pad *pad,
 704					struct media_pipeline *pipe)
 705{
 706	struct media_device *mdev = pad->entity->graph_obj.mdev;
 707	struct media_pipeline_pad *err_ppad;
 708	struct media_pipeline_pad *ppad;
 709	int ret;
 710
 711	lockdep_assert_held(&mdev->graph_mutex);
 712
 713	/*
 714	 * If the entity is already part of a pipeline, that pipeline must
 715	 * be the same as the pipe given to media_pipeline_start().
 716	 */
 717	if (WARN_ON(pad->pipe && pad->pipe != pipe))
 718		return -EINVAL;
 719
 720	/*
 721	 * If the pipeline has already been started, it is guaranteed to be
 722	 * valid, so just increase the start count.
 723	 */
 724	if (pipe->start_count) {
 725		pipe->start_count++;
 726		return 0;
 727	}
 728
 729	/*
 730	 * Populate the pipeline. This populates the media_pipeline pads list
 731	 * with media_pipeline_pad instances for each pad found during graph
 732	 * walk.
 733	 */
 734	ret = media_pipeline_populate(pipe, pad);
 735	if (ret)
 736		return ret;
 737
 738	/*
 739	 * Now that all the pads in the pipeline have been gathered, perform
 740	 * the validation steps.
 741	 */
 742
 743	list_for_each_entry(ppad, &pipe->pads, list) {
 744		struct media_pad *pad = ppad->pad;
 745		struct media_entity *entity = pad->entity;
 746		bool has_enabled_link = false;
 747		bool has_link = false;
 748		struct media_link *link;
 749
 750		dev_dbg(mdev->dev, "Validating pad '%s':%u\n", pad->entity->name,
 751			pad->index);
 752
 753		/*
 754		 * 1. Ensure that the pad doesn't already belong to a different
 755		 * pipeline.
 756		 */
 757		if (pad->pipe) {
 758			dev_dbg(mdev->dev, "Failed to start pipeline: pad '%s':%u busy\n",
 759				pad->entity->name, pad->index);
 760			ret = -EBUSY;
 761			goto error;
 762		}
 763
 764		/*
 765		 * 2. Validate all active links whose sink is the current pad.
 766		 * Validation of the source pads is performed in the context of
 767		 * the connected sink pad to avoid duplicating checks.
 768		 */
 769		for_each_media_entity_data_link(entity, link) {
 770			/* Skip links unrelated to the current pad. */
 771			if (link->sink != pad && link->source != pad)
 772				continue;
 773
 774			/* Record if the pad has links and enabled links. */
 775			if (link->flags & MEDIA_LNK_FL_ENABLED)
 776				has_enabled_link = true;
 777			has_link = true;
 778
 779			/*
 780			 * Validate the link if it's enabled and has the
 781			 * current pad as its sink.
 782			 */
 783			if (!(link->flags & MEDIA_LNK_FL_ENABLED))
 784				continue;
 785
 786			if (link->sink != pad)
 787				continue;
 788
 789			if (!entity->ops || !entity->ops->link_validate)
 790				continue;
 791
 792			ret = entity->ops->link_validate(link);
 793			if (ret) {
 794				dev_dbg(mdev->dev,
 795					"Link '%s':%u -> '%s':%u failed validation: %d\n",
 796					link->source->entity->name,
 797					link->source->index,
 798					link->sink->entity->name,
 799					link->sink->index, ret);
 800				goto error;
 801			}
 802
 803			dev_dbg(mdev->dev,
 804				"Link '%s':%u -> '%s':%u is valid\n",
 805				link->source->entity->name,
 806				link->source->index,
 807				link->sink->entity->name,
 808				link->sink->index);
 809		}
 810
 811		/*
 812		 * 3. If the pad has the MEDIA_PAD_FL_MUST_CONNECT flag set,
 813		 * ensure that it has either no link or an enabled link.
 814		 */
 815		if ((pad->flags & MEDIA_PAD_FL_MUST_CONNECT) && has_link &&
 816		    !has_enabled_link) {
 817			dev_dbg(mdev->dev,
 818				"Pad '%s':%u must be connected by an enabled link\n",
 819				pad->entity->name, pad->index);
 820			ret = -ENOLINK;
 821			goto error;
 822		}
 823
 824		/* Validation passed, store the pipe pointer in the pad. */
 825		pad->pipe = pipe;
 826	}
 827
 828	pipe->start_count++;
 829
 830	return 0;
 831
 832error:
 833	/*
 834	 * Link validation on graph failed. We revert what we did and
 835	 * return the error.
 836	 */
 837
 838	list_for_each_entry(err_ppad, &pipe->pads, list) {
 839		if (err_ppad == ppad)
 840			break;
 841
 842		err_ppad->pad->pipe = NULL;
 843	}
 844
 845	media_pipeline_cleanup(pipe);
 846
 847	return ret;
 848}
 849EXPORT_SYMBOL_GPL(__media_pipeline_start);
 850
 851__must_check int media_pipeline_start(struct media_pad *pad,
 852				      struct media_pipeline *pipe)
 853{
 854	struct media_device *mdev = pad->entity->graph_obj.mdev;
 855	int ret;
 856
 857	mutex_lock(&mdev->graph_mutex);
 858	ret = __media_pipeline_start(pad, pipe);
 859	mutex_unlock(&mdev->graph_mutex);
 860	return ret;
 861}
 862EXPORT_SYMBOL_GPL(media_pipeline_start);
 863
 864void __media_pipeline_stop(struct media_pad *pad)
 865{
 866	struct media_pipeline *pipe = pad->pipe;
 867	struct media_pipeline_pad *ppad;
 868
 869	/*
 870	 * If the following check fails, the driver has performed an
 871	 * unbalanced call to media_pipeline_stop()
 872	 */
 873	if (WARN_ON(!pipe))
 874		return;
 875
 876	if (--pipe->start_count)
 877		return;
 878
 879	list_for_each_entry(ppad, &pipe->pads, list)
 880		ppad->pad->pipe = NULL;
 881
 882	media_pipeline_cleanup(pipe);
 883
 884	if (pipe->allocated)
 885		kfree(pipe);
 886}
 887EXPORT_SYMBOL_GPL(__media_pipeline_stop);
 888
 889void media_pipeline_stop(struct media_pad *pad)
 890{
 891	struct media_device *mdev = pad->entity->graph_obj.mdev;
 892
 893	mutex_lock(&mdev->graph_mutex);
 894	__media_pipeline_stop(pad);
 895	mutex_unlock(&mdev->graph_mutex);
 896}
 897EXPORT_SYMBOL_GPL(media_pipeline_stop);
 898
 899__must_check int media_pipeline_alloc_start(struct media_pad *pad)
 900{
 901	struct media_device *mdev = pad->entity->graph_obj.mdev;
 902	struct media_pipeline *new_pipe = NULL;
 903	struct media_pipeline *pipe;
 904	int ret;
 905
 906	mutex_lock(&mdev->graph_mutex);
 907
 908	/*
 909	 * Is the entity already part of a pipeline? If not, we need to allocate
 910	 * a pipe.
 911	 */
 912	pipe = media_pad_pipeline(pad);
 913	if (!pipe) {
 914		new_pipe = kzalloc(sizeof(*new_pipe), GFP_KERNEL);
 915		if (!new_pipe) {
 916			ret = -ENOMEM;
 917			goto out;
 918		}
 919
 920		pipe = new_pipe;
 921		pipe->allocated = true;
 922	}
 923
 924	ret = __media_pipeline_start(pad, pipe);
 925	if (ret)
 926		kfree(new_pipe);
 927
 928out:
 929	mutex_unlock(&mdev->graph_mutex);
 930
 931	return ret;
 932}
 933EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
 934
 935/* -----------------------------------------------------------------------------
 936 * Links management
 937 */
 938
 939static struct media_link *media_add_link(struct list_head *head)
 940{
 941	struct media_link *link;
 942
 943	link = kzalloc(sizeof(*link), GFP_KERNEL);
 944	if (link == NULL)
 945		return NULL;
 946
 947	list_add_tail(&link->list, head);
 948
 949	return link;
 950}
 951
 952static void __media_entity_remove_link(struct media_entity *entity,
 953				       struct media_link *link)
 954{
 955	struct media_link *rlink, *tmp;
 956	struct media_entity *remote;
 957
 958	/* Remove the reverse links for a data link. */
 959	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
 960		if (link->source->entity == entity)
 961			remote = link->sink->entity;
 962		else
 963			remote = link->source->entity;
 964
 965		list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
 966			if (rlink != link->reverse)
 967				continue;
 968
 969			if (link->source->entity == entity)
 970				remote->num_backlinks--;
 971
 972			/* Remove the remote link */
 973			list_del(&rlink->list);
 974			media_gobj_destroy(&rlink->graph_obj);
 975			kfree(rlink);
 976
 977			if (--remote->num_links == 0)
 978				break;
 979		}
 980	}
 981
 982	list_del(&link->list);
 983	media_gobj_destroy(&link->graph_obj);
 984	kfree(link);
 985}
 986
 987int media_get_pad_index(struct media_entity *entity, bool is_sink,
 988			enum media_pad_signal_type sig_type)
 989{
 990	int i;
 991	bool pad_is_sink;
 992
 993	if (!entity)
 994		return -EINVAL;
 995
 996	for (i = 0; i < entity->num_pads; i++) {
 997		if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
 998			pad_is_sink = true;
 999		else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
1000			pad_is_sink = false;
1001		else
1002			continue;	/* This is an error! */
1003
1004		if (pad_is_sink != is_sink)
1005			continue;
1006		if (entity->pads[i].sig_type == sig_type)
1007			return i;
1008	}
1009	return -EINVAL;
1010}
1011EXPORT_SYMBOL_GPL(media_get_pad_index);
1012
1013int
1014media_create_pad_link(struct media_entity *source, u16 source_pad,
1015			 struct media_entity *sink, u16 sink_pad, u32 flags)
1016{
1017	struct media_link *link;
1018	struct media_link *backlink;
1019
1020	if (WARN_ON(!source || !sink) ||
1021	    WARN_ON(source_pad >= source->num_pads) ||
1022	    WARN_ON(sink_pad >= sink->num_pads))
1023		return -EINVAL;
1024	if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
1025		return -EINVAL;
1026	if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
1027		return -EINVAL;
1028
1029	link = media_add_link(&source->links);
1030	if (link == NULL)
1031		return -ENOMEM;
1032
1033	link->source = &source->pads[source_pad];
1034	link->sink = &sink->pads[sink_pad];
1035	link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
1036
1037	/* Initialize graph object embedded at the new link */
1038	media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
1039			&link->graph_obj);
1040
1041	/* Create the backlink. Backlinks are used to help graph traversal and
1042	 * are not reported to userspace.
1043	 */
1044	backlink = media_add_link(&sink->links);
1045	if (backlink == NULL) {
1046		__media_entity_remove_link(source, link);
1047		return -ENOMEM;
1048	}
1049
1050	backlink->source = &source->pads[source_pad];
1051	backlink->sink = &sink->pads[sink_pad];
1052	backlink->flags = flags;
1053	backlink->is_backlink = true;
1054
1055	/* Initialize graph object embedded at the new link */
1056	media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
1057			&backlink->graph_obj);
1058
1059	link->reverse = backlink;
1060	backlink->reverse = link;
1061
1062	sink->num_backlinks++;
1063	sink->num_links++;
1064	source->num_links++;
1065
1066	return 0;
1067}
1068EXPORT_SYMBOL_GPL(media_create_pad_link);
1069
1070int media_create_pad_links(const struct media_device *mdev,
1071			   const u32 source_function,
1072			   struct media_entity *source,
1073			   const u16 source_pad,
1074			   const u32 sink_function,
1075			   struct media_entity *sink,
1076			   const u16 sink_pad,
1077			   u32 flags,
1078			   const bool allow_both_undefined)
1079{
1080	struct media_entity *entity;
1081	unsigned function;
1082	int ret;
1083
1084	/* Trivial case: 1:1 relation */
1085	if (source && sink)
1086		return media_create_pad_link(source, source_pad,
1087					     sink, sink_pad, flags);
1088
1089	/* Worse case scenario: n:n relation */
1090	if (!source && !sink) {
1091		if (!allow_both_undefined)
1092			return 0;
1093		media_device_for_each_entity(source, mdev) {
1094			if (source->function != source_function)
1095				continue;
1096			media_device_for_each_entity(sink, mdev) {
1097				if (sink->function != sink_function)
1098					continue;
1099				ret = media_create_pad_link(source, source_pad,
1100							    sink, sink_pad,
1101							    flags);
1102				if (ret)
1103					return ret;
1104				flags &= ~(MEDIA_LNK_FL_ENABLED |
1105					   MEDIA_LNK_FL_IMMUTABLE);
1106			}
1107		}
1108		return 0;
1109	}
1110
1111	/* Handle 1:n and n:1 cases */
1112	if (source)
1113		function = sink_function;
1114	else
1115		function = source_function;
1116
1117	media_device_for_each_entity(entity, mdev) {
1118		if (entity->function != function)
1119			continue;
1120
1121		if (source)
1122			ret = media_create_pad_link(source, source_pad,
1123						    entity, sink_pad, flags);
1124		else
1125			ret = media_create_pad_link(entity, source_pad,
1126						    sink, sink_pad, flags);
1127		if (ret)
1128			return ret;
1129		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1130	}
1131	return 0;
1132}
1133EXPORT_SYMBOL_GPL(media_create_pad_links);
1134
1135void __media_entity_remove_links(struct media_entity *entity)
1136{
1137	struct media_link *link, *tmp;
1138
1139	list_for_each_entry_safe(link, tmp, &entity->links, list)
1140		__media_entity_remove_link(entity, link);
1141
1142	entity->num_links = 0;
1143	entity->num_backlinks = 0;
1144}
1145EXPORT_SYMBOL_GPL(__media_entity_remove_links);
1146
1147void media_entity_remove_links(struct media_entity *entity)
1148{
1149	struct media_device *mdev = entity->graph_obj.mdev;
1150
1151	/* Do nothing if the entity is not registered. */
1152	if (mdev == NULL)
1153		return;
1154
1155	mutex_lock(&mdev->graph_mutex);
1156	__media_entity_remove_links(entity);
1157	mutex_unlock(&mdev->graph_mutex);
1158}
1159EXPORT_SYMBOL_GPL(media_entity_remove_links);
1160
1161static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
1162{
1163	int ret;
1164
1165	/* Notify both entities. */
1166	ret = media_entity_call(link->source->entity, link_setup,
1167				link->source, link->sink, flags);
1168	if (ret < 0 && ret != -ENOIOCTLCMD)
1169		return ret;
1170
1171	ret = media_entity_call(link->sink->entity, link_setup,
1172				link->sink, link->source, flags);
1173	if (ret < 0 && ret != -ENOIOCTLCMD) {
1174		media_entity_call(link->source->entity, link_setup,
1175				  link->source, link->sink, link->flags);
1176		return ret;
1177	}
1178
1179	link->flags = flags;
1180	link->reverse->flags = link->flags;
1181
1182	return 0;
1183}
1184
1185int __media_entity_setup_link(struct media_link *link, u32 flags)
1186{
1187	const u32 mask = MEDIA_LNK_FL_ENABLED;
1188	struct media_device *mdev;
1189	struct media_pad *source, *sink;
1190	int ret = -EBUSY;
1191
1192	if (link == NULL)
1193		return -EINVAL;
1194
1195	/* The non-modifiable link flags must not be modified. */
1196	if ((link->flags & ~mask) != (flags & ~mask))
1197		return -EINVAL;
1198
1199	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
1200		return link->flags == flags ? 0 : -EINVAL;
1201
1202	if (link->flags == flags)
1203		return 0;
1204
1205	source = link->source;
1206	sink = link->sink;
1207
1208	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
1209	    (media_pad_is_streaming(source) || media_pad_is_streaming(sink)))
1210		return -EBUSY;
1211
1212	mdev = source->graph_obj.mdev;
1213
1214	if (mdev->ops && mdev->ops->link_notify) {
1215		ret = mdev->ops->link_notify(link, flags,
1216					     MEDIA_DEV_NOTIFY_PRE_LINK_CH);
1217		if (ret < 0)
1218			return ret;
1219	}
1220
1221	ret = __media_entity_setup_link_notify(link, flags);
1222
1223	if (mdev->ops && mdev->ops->link_notify)
1224		mdev->ops->link_notify(link, flags,
1225				       MEDIA_DEV_NOTIFY_POST_LINK_CH);
1226
1227	return ret;
1228}
1229EXPORT_SYMBOL_GPL(__media_entity_setup_link);
1230
1231int media_entity_setup_link(struct media_link *link, u32 flags)
1232{
1233	int ret;
1234
1235	mutex_lock(&link->graph_obj.mdev->graph_mutex);
1236	ret = __media_entity_setup_link(link, flags);
1237	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
1238
1239	return ret;
1240}
1241EXPORT_SYMBOL_GPL(media_entity_setup_link);
1242
1243struct media_link *
1244media_entity_find_link(struct media_pad *source, struct media_pad *sink)
1245{
1246	struct media_link *link;
1247
1248	for_each_media_entity_data_link(source->entity, link) {
1249		if (link->source->entity == source->entity &&
1250		    link->source->index == source->index &&
1251		    link->sink->entity == sink->entity &&
1252		    link->sink->index == sink->index)
1253			return link;
1254	}
1255
1256	return NULL;
1257}
1258EXPORT_SYMBOL_GPL(media_entity_find_link);
1259
1260struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)
1261{
1262	struct media_link *link;
1263
1264	for_each_media_entity_data_link(pad->entity, link) {
1265		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
1266			continue;
1267
1268		if (link->source == pad)
1269			return link->sink;
1270
1271		if (link->sink == pad)
1272			return link->source;
1273	}
1274
1275	return NULL;
1276
1277}
1278EXPORT_SYMBOL_GPL(media_pad_remote_pad_first);
1279
1280struct media_pad *
1281media_entity_remote_pad_unique(const struct media_entity *entity,
1282			       unsigned int type)
1283{
1284	struct media_pad *pad = NULL;
1285	struct media_link *link;
1286
1287	list_for_each_entry(link, &entity->links, list) {
1288		struct media_pad *local_pad;
1289		struct media_pad *remote_pad;
1290
1291		if (((link->flags & MEDIA_LNK_FL_LINK_TYPE) !=
1292		     MEDIA_LNK_FL_DATA_LINK) ||
1293		    !(link->flags & MEDIA_LNK_FL_ENABLED))
1294			continue;
1295
1296		if (type == MEDIA_PAD_FL_SOURCE) {
1297			local_pad = link->sink;
1298			remote_pad = link->source;
1299		} else {
1300			local_pad = link->source;
1301			remote_pad = link->sink;
1302		}
1303
1304		if (local_pad->entity == entity) {
1305			if (pad)
1306				return ERR_PTR(-ENOTUNIQ);
1307
1308			pad = remote_pad;
1309		}
1310	}
1311
1312	if (!pad)
1313		return ERR_PTR(-ENOLINK);
1314
1315	return pad;
1316}
1317EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique);
1318
1319struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
1320{
1321	struct media_pad *found_pad = NULL;
1322	struct media_link *link;
1323
1324	list_for_each_entry(link, &pad->entity->links, list) {
1325		struct media_pad *remote_pad;
1326
1327		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
1328			continue;
1329
1330		if (link->sink == pad)
1331			remote_pad = link->source;
1332		else if (link->source == pad)
1333			remote_pad = link->sink;
1334		else
1335			continue;
1336
1337		if (found_pad)
1338			return ERR_PTR(-ENOTUNIQ);
1339
1340		found_pad = remote_pad;
1341	}
1342
1343	if (!found_pad)
1344		return ERR_PTR(-ENOLINK);
1345
1346	return found_pad;
1347}
1348EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
1349
1350int media_entity_get_fwnode_pad(struct media_entity *entity,
1351				struct fwnode_handle *fwnode,
1352				unsigned long direction_flags)
1353{
1354	struct fwnode_endpoint endpoint;
1355	unsigned int i;
1356	int ret;
1357
1358	if (!entity->ops || !entity->ops->get_fwnode_pad) {
1359		for (i = 0; i < entity->num_pads; i++) {
1360			if (entity->pads[i].flags & direction_flags)
1361				return i;
1362		}
1363
1364		return -ENXIO;
1365	}
1366
1367	ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
1368	if (ret)
1369		return ret;
1370
1371	ret = entity->ops->get_fwnode_pad(entity, &endpoint);
1372	if (ret < 0)
1373		return ret;
1374
1375	if (ret >= entity->num_pads)
1376		return -ENXIO;
1377
1378	if (!(entity->pads[ret].flags & direction_flags))
1379		return -ENXIO;
1380
1381	return ret;
1382}
1383EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
1384
1385struct media_pipeline *media_entity_pipeline(struct media_entity *entity)
1386{
1387	struct media_pad *pad;
1388
1389	media_entity_for_each_pad(entity, pad) {
1390		if (pad->pipe)
1391			return pad->pipe;
1392	}
1393
1394	return NULL;
1395}
1396EXPORT_SYMBOL_GPL(media_entity_pipeline);
1397
1398struct media_pipeline *media_pad_pipeline(struct media_pad *pad)
1399{
1400	return pad->pipe;
1401}
1402EXPORT_SYMBOL_GPL(media_pad_pipeline);
1403
1404static void media_interface_init(struct media_device *mdev,
1405				 struct media_interface *intf,
1406				 u32 gobj_type,
1407				 u32 intf_type, u32 flags)
1408{
1409	intf->type = intf_type;
1410	intf->flags = flags;
1411	INIT_LIST_HEAD(&intf->links);
1412
1413	media_gobj_create(mdev, gobj_type, &intf->graph_obj);
1414}
1415
1416/* Functions related to the media interface via device nodes */
1417
1418struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
1419						u32 type, u32 flags,
1420						u32 major, u32 minor)
1421{
1422	struct media_intf_devnode *devnode;
1423
1424	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
1425	if (!devnode)
1426		return NULL;
1427
1428	devnode->major = major;
1429	devnode->minor = minor;
1430
1431	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
1432			     type, flags);
1433
1434	return devnode;
1435}
1436EXPORT_SYMBOL_GPL(media_devnode_create);
1437
1438void media_devnode_remove(struct media_intf_devnode *devnode)
1439{
1440	media_remove_intf_links(&devnode->intf);
1441	media_gobj_destroy(&devnode->intf.graph_obj);
1442	kfree(devnode);
1443}
1444EXPORT_SYMBOL_GPL(media_devnode_remove);
1445
1446struct media_link *media_create_intf_link(struct media_entity *entity,
1447					    struct media_interface *intf,
1448					    u32 flags)
1449{
1450	struct media_link *link;
1451
1452	link = media_add_link(&intf->links);
1453	if (link == NULL)
1454		return NULL;
1455
1456	link->intf = intf;
1457	link->entity = entity;
1458	link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
1459
1460	/* Initialize graph object embedded at the new link */
1461	media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
1462			&link->graph_obj);
1463
1464	return link;
1465}
1466EXPORT_SYMBOL_GPL(media_create_intf_link);
1467
1468void __media_remove_intf_link(struct media_link *link)
1469{
1470	list_del(&link->list);
1471	media_gobj_destroy(&link->graph_obj);
1472	kfree(link);
1473}
1474EXPORT_SYMBOL_GPL(__media_remove_intf_link);
1475
1476void media_remove_intf_link(struct media_link *link)
1477{
1478	struct media_device *mdev = link->graph_obj.mdev;
1479
1480	/* Do nothing if the intf is not registered. */
1481	if (mdev == NULL)
1482		return;
1483
1484	mutex_lock(&mdev->graph_mutex);
1485	__media_remove_intf_link(link);
1486	mutex_unlock(&mdev->graph_mutex);
1487}
1488EXPORT_SYMBOL_GPL(media_remove_intf_link);
1489
1490void __media_remove_intf_links(struct media_interface *intf)
1491{
1492	struct media_link *link, *tmp;
1493
1494	list_for_each_entry_safe(link, tmp, &intf->links, list)
1495		__media_remove_intf_link(link);
1496
1497}
1498EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1499
1500void media_remove_intf_links(struct media_interface *intf)
1501{
1502	struct media_device *mdev = intf->graph_obj.mdev;
1503
1504	/* Do nothing if the intf is not registered. */
1505	if (mdev == NULL)
1506		return;
1507
1508	mutex_lock(&mdev->graph_mutex);
1509	__media_remove_intf_links(intf);
1510	mutex_unlock(&mdev->graph_mutex);
1511}
1512EXPORT_SYMBOL_GPL(media_remove_intf_links);
1513
1514struct media_link *media_create_ancillary_link(struct media_entity *primary,
1515					       struct media_entity *ancillary)
1516{
1517	struct media_link *link;
1518
1519	link = media_add_link(&primary->links);
1520	if (!link)
1521		return ERR_PTR(-ENOMEM);
1522
1523	link->gobj0 = &primary->graph_obj;
1524	link->gobj1 = &ancillary->graph_obj;
1525	link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
1526		      MEDIA_LNK_FL_ANCILLARY_LINK;
1527
1528	/* Initialize graph object embedded in the new link */
1529	media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
1530			  &link->graph_obj);
1531
1532	return link;
1533}
1534EXPORT_SYMBOL_GPL(media_create_ancillary_link);
1535
1536struct media_link *__media_entity_next_link(struct media_entity *entity,
1537					    struct media_link *link,
1538					    unsigned long link_type)
1539{
1540	link = link ? list_next_entry(link, list)
1541		    : list_first_entry(&entity->links, typeof(*link), list);
1542
1543	list_for_each_entry_from(link, &entity->links, list)
1544		if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == link_type)
1545			return link;
1546
1547	return NULL;
1548}
1549EXPORT_SYMBOL_GPL(__media_entity_next_link);