Linux Audio

Check our new training course

Loading...
v6.13.7
   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	int ret = 0;
 201
 202	if (num_pads >= MEDIA_ENTITY_MAX_PADS)
 203		return -E2BIG;
 204
 205	entity->num_pads = num_pads;
 206	entity->pads = pads;
 207
 208	if (mdev)
 209		mutex_lock(&mdev->graph_mutex);
 210
 211	media_entity_for_each_pad(entity, iter) {
 212		iter->entity = entity;
 213		iter->index = i++;
 214
 215		if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK |
 216					     MEDIA_PAD_FL_SOURCE)) != 1) {
 217			ret = -EINVAL;
 218			break;
 219		}
 220
 221		if (mdev)
 222			media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 223					  &iter->graph_obj);
 224	}
 225
 226	if (ret && mdev) {
 227		media_entity_for_each_pad(entity, iter)
 228			media_gobj_destroy(&iter->graph_obj);
 229	}
 230
 231	if (mdev)
 232		mutex_unlock(&mdev->graph_mutex);
 233
 234	return ret;
 235}
 236EXPORT_SYMBOL_GPL(media_entity_pads_init);
 237
 238/* -----------------------------------------------------------------------------
 239 * Graph traversal
 240 */
 241
 242/**
 243 * media_entity_has_pad_interdep - Check interdependency between two pads
 244 *
 245 * @entity: The entity
 246 * @pad0: The first pad index
 247 * @pad1: The second pad index
 248 *
 249 * This function checks the interdependency inside the entity between @pad0
 250 * and @pad1. If two pads are interdependent they are part of the same pipeline
 251 * and enabling one of the pads means that the other pad will become "locked"
 252 * and doesn't allow configuration changes.
 253 *
 254 * This function uses the &media_entity_operations.has_pad_interdep() operation
 255 * to check the dependency inside the entity between @pad0 and @pad1. If the
 256 * has_pad_interdep operation is not implemented, all pads of the entity are
 257 * considered to be interdependent.
 258 *
 259 * One of @pad0 and @pad1 must be a sink pad and the other one a source pad.
 260 * The function returns false if both pads are sinks or sources.
 261 *
 262 * The caller must hold entity->graph_obj.mdev->mutex.
 263 *
 264 * Return: true if the pads are connected internally and false otherwise.
 265 */
 266static bool media_entity_has_pad_interdep(struct media_entity *entity,
 267					  unsigned int pad0, unsigned int pad1)
 268{
 269	if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
 270		return false;
 271
 272	if (entity->pads[pad0].flags & entity->pads[pad1].flags &
 273	    (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE))
 274		return false;
 275
 276	if (!entity->ops || !entity->ops->has_pad_interdep)
 277		return true;
 278
 279	return entity->ops->has_pad_interdep(entity, pad0, pad1);
 280}
 281
 282static struct media_entity *
 283media_entity_other(struct media_entity *entity, struct media_link *link)
 284{
 285	if (link->source->entity == entity)
 286		return link->sink->entity;
 287	else
 288		return link->source->entity;
 289}
 290
 291/* push an entity to traversal stack */
 292static void stack_push(struct media_graph *graph,
 293		       struct media_entity *entity)
 294{
 295	if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
 296		WARN_ON(1);
 297		return;
 298	}
 299	graph->top++;
 300	graph->stack[graph->top].link = entity->links.next;
 301	graph->stack[graph->top].entity = entity;
 302}
 303
 304static struct media_entity *stack_pop(struct media_graph *graph)
 305{
 306	struct media_entity *entity;
 307
 308	entity = graph->stack[graph->top].entity;
 309	graph->top--;
 310
 311	return entity;
 312}
 313
 314#define link_top(en)	((en)->stack[(en)->top].link)
 315#define stack_top(en)	((en)->stack[(en)->top].entity)
 316
 317/**
 318 * media_graph_walk_init - Allocate resources for graph walk
 319 * @graph: Media graph structure that will be used to walk the graph
 320 * @mdev: Media device
 321 *
 322 * Reserve resources for graph walk in media device's current
 323 * state. The memory must be released using
 324 * media_graph_walk_cleanup().
 325 *
 326 * Returns error on failure, zero on success.
 327 */
 328__must_check int media_graph_walk_init(
 329	struct media_graph *graph, struct media_device *mdev)
 330{
 331	return media_entity_enum_init(&graph->ent_enum, mdev);
 332}
 333EXPORT_SYMBOL_GPL(media_graph_walk_init);
 334
 335/**
 336 * media_graph_walk_cleanup - Release resources related to graph walking
 337 * @graph: Media graph structure that was used to walk the graph
 338 */
 339void media_graph_walk_cleanup(struct media_graph *graph)
 340{
 341	media_entity_enum_cleanup(&graph->ent_enum);
 342}
 343EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
 344
 345void media_graph_walk_start(struct media_graph *graph,
 346			    struct media_entity *entity)
 347{
 348	media_entity_enum_zero(&graph->ent_enum);
 349	media_entity_enum_set(&graph->ent_enum, entity);
 350
 351	graph->top = 0;
 352	graph->stack[graph->top].entity = NULL;
 353	stack_push(graph, entity);
 354	dev_dbg(entity->graph_obj.mdev->dev,
 355		"begin graph walk at '%s'\n", entity->name);
 356}
 357EXPORT_SYMBOL_GPL(media_graph_walk_start);
 358
 359static void media_graph_walk_iter(struct media_graph *graph)
 360{
 361	struct media_entity *entity = stack_top(graph);
 362	struct media_link *link;
 363	struct media_entity *next;
 364
 365	link = list_entry(link_top(graph), typeof(*link), list);
 366
 367	/* If the link is not a data link, don't follow it */
 368	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
 369		link_top(graph) = link_top(graph)->next;
 370		return;
 371	}
 372
 373	/* The link is not enabled so we do not follow. */
 374	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 375		link_top(graph) = link_top(graph)->next;
 376		dev_dbg(entity->graph_obj.mdev->dev,
 377			"walk: skipping disabled link '%s':%u -> '%s':%u\n",
 378			link->source->entity->name, link->source->index,
 379			link->sink->entity->name, link->sink->index);
 380		return;
 381	}
 382
 383	/* Get the entity at the other end of the link. */
 384	next = media_entity_other(entity, link);
 385
 386	/* Has the entity already been visited? */
 387	if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
 388		link_top(graph) = link_top(graph)->next;
 389		dev_dbg(entity->graph_obj.mdev->dev,
 390			"walk: skipping entity '%s' (already seen)\n",
 391			next->name);
 392		return;
 393	}
 394
 395	/* Push the new entity to stack and start over. */
 396	link_top(graph) = link_top(graph)->next;
 397	stack_push(graph, next);
 398	dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
 399		next->name);
 400	lockdep_assert_held(&entity->graph_obj.mdev->graph_mutex);
 401}
 402
 403struct media_entity *media_graph_walk_next(struct media_graph *graph)
 404{
 405	struct media_entity *entity;
 406
 407	if (stack_top(graph) == NULL)
 408		return NULL;
 409
 410	/*
 411	 * Depth first search. Push entity to stack and continue from
 412	 * top of the stack until no more entities on the level can be
 413	 * found.
 414	 */
 415	while (link_top(graph) != &stack_top(graph)->links)
 416		media_graph_walk_iter(graph);
 417
 418	entity = stack_pop(graph);
 419	dev_dbg(entity->graph_obj.mdev->dev,
 420		"walk: returning entity '%s'\n", entity->name);
 421
 422	return entity;
 423}
 424EXPORT_SYMBOL_GPL(media_graph_walk_next);
 425
 426/* -----------------------------------------------------------------------------
 427 * Pipeline management
 428 */
 429
 430/*
 431 * The pipeline traversal stack stores pads that are reached during graph
 432 * traversal, with a list of links to be visited to continue the traversal.
 433 * When a new pad is reached, an entry is pushed on the top of the stack and
 434 * points to the incoming pad and the first link of the entity.
 435 *
 436 * To find further pads in the pipeline, the traversal algorithm follows
 437 * internal pad dependencies in the entity, and then links in the graph. It
 438 * does so by iterating over all links of the entity, and following enabled
 439 * links that originate from a pad that is internally connected to the incoming
 440 * pad, as reported by the media_entity_has_pad_interdep() function.
 441 */
 442
 443/**
 444 * struct media_pipeline_walk_entry - Entry in the pipeline traversal stack
 445 *
 446 * @pad: The media pad being visited
 447 * @links: Links left to be visited
 448 */
 449struct media_pipeline_walk_entry {
 450	struct media_pad *pad;
 451	struct list_head *links;
 452};
 453
 454/**
 455 * struct media_pipeline_walk - State used by the media pipeline traversal
 456 *				algorithm
 457 *
 458 * @mdev: The media device
 459 * @stack: Depth-first search stack
 460 * @stack.size: Number of allocated entries in @stack.entries
 461 * @stack.top: Index of the top stack entry (-1 if the stack is empty)
 462 * @stack.entries: Stack entries
 463 */
 464struct media_pipeline_walk {
 465	struct media_device *mdev;
 466
 467	struct {
 468		unsigned int size;
 469		int top;
 470		struct media_pipeline_walk_entry *entries;
 471	} stack;
 472};
 473
 474#define MEDIA_PIPELINE_STACK_GROW_STEP		16
 475
 476static struct media_pipeline_walk_entry *
 477media_pipeline_walk_top(struct media_pipeline_walk *walk)
 478{
 479	return &walk->stack.entries[walk->stack.top];
 480}
 481
 482static bool media_pipeline_walk_empty(struct media_pipeline_walk *walk)
 483{
 484	return walk->stack.top == -1;
 485}
 486
 487/* Increase the stack size by MEDIA_PIPELINE_STACK_GROW_STEP elements. */
 488static int media_pipeline_walk_resize(struct media_pipeline_walk *walk)
 489{
 490	struct media_pipeline_walk_entry *entries;
 491	unsigned int new_size;
 492
 493	/* Safety check, to avoid stack overflows in case of bugs. */
 494	if (walk->stack.size >= 256)
 495		return -E2BIG;
 496
 497	new_size = walk->stack.size + MEDIA_PIPELINE_STACK_GROW_STEP;
 498
 499	entries = krealloc(walk->stack.entries,
 500			   new_size * sizeof(*walk->stack.entries),
 501			   GFP_KERNEL);
 502	if (!entries)
 503		return -ENOMEM;
 504
 505	walk->stack.entries = entries;
 506	walk->stack.size = new_size;
 507
 508	return 0;
 509}
 510
 511/* Push a new entry on the stack. */
 512static int media_pipeline_walk_push(struct media_pipeline_walk *walk,
 513				    struct media_pad *pad)
 514{
 515	struct media_pipeline_walk_entry *entry;
 
 516	int ret;
 517
 518	if (walk->stack.top + 1 >= walk->stack.size) {
 519		ret = media_pipeline_walk_resize(walk);
 520		if (ret)
 521			return ret;
 522	}
 523
 524	walk->stack.top++;
 525	entry = media_pipeline_walk_top(walk);
 526	entry->pad = pad;
 527	entry->links = pad->entity->links.next;
 528
 529	dev_dbg(walk->mdev->dev,
 530		"media pipeline: pushed entry %u: '%s':%u\n",
 531		walk->stack.top, pad->entity->name, pad->index);
 532
 533	return 0;
 534}
 535
 536/*
 537 * Move the top entry link cursor to the next link. If all links of the entry
 538 * have been visited, pop the entry itself. Return true if the entry has been
 539 * popped.
 540 */
 541static bool media_pipeline_walk_pop(struct media_pipeline_walk *walk)
 542{
 543	struct media_pipeline_walk_entry *entry;
 544
 545	if (WARN_ON(walk->stack.top < 0))
 546		return false;
 547
 548	entry = media_pipeline_walk_top(walk);
 549
 550	if (entry->links->next == &entry->pad->entity->links) {
 551		dev_dbg(walk->mdev->dev,
 552			"media pipeline: entry %u has no more links, popping\n",
 553			walk->stack.top);
 554
 555		walk->stack.top--;
 556		return true;
 557	}
 558
 559	entry->links = entry->links->next;
 560
 561	dev_dbg(walk->mdev->dev,
 562		"media pipeline: moved entry %u to next link\n",
 563		walk->stack.top);
 564
 565	return false;
 566}
 567
 568/* Free all memory allocated while walking the pipeline. */
 569static void media_pipeline_walk_destroy(struct media_pipeline_walk *walk)
 570{
 571	kfree(walk->stack.entries);
 572}
 573
 574/* Add a pad to the pipeline and push it to the stack. */
 575static int media_pipeline_add_pad(struct media_pipeline *pipe,
 576				  struct media_pipeline_walk *walk,
 577				  struct media_pad *pad)
 578{
 579	struct media_pipeline_pad *ppad;
 580
 581	list_for_each_entry(ppad, &pipe->pads, list) {
 582		if (ppad->pad == pad) {
 583			dev_dbg(pad->graph_obj.mdev->dev,
 584				"media pipeline: already contains pad '%s':%u\n",
 585				pad->entity->name, pad->index);
 586			return 0;
 587		}
 588	}
 589
 590	ppad = kzalloc(sizeof(*ppad), GFP_KERNEL);
 591	if (!ppad)
 592		return -ENOMEM;
 593
 594	ppad->pipe = pipe;
 595	ppad->pad = pad;
 596
 597	list_add_tail(&ppad->list, &pipe->pads);
 598
 599	dev_dbg(pad->graph_obj.mdev->dev,
 600		"media pipeline: added pad '%s':%u\n",
 601		pad->entity->name, pad->index);
 602
 603	return media_pipeline_walk_push(walk, pad);
 604}
 605
 606/* Explore the next link of the entity at the top of the stack. */
 607static int media_pipeline_explore_next_link(struct media_pipeline *pipe,
 608					    struct media_pipeline_walk *walk)
 609{
 610	struct media_pipeline_walk_entry *entry = media_pipeline_walk_top(walk);
 611	struct media_pad *origin;
 612	struct media_link *link;
 613	struct media_pad *local;
 614	struct media_pad *remote;
 615	bool last_link;
 616	int ret;
 617
 618	origin = entry->pad;
 619	link = list_entry(entry->links, typeof(*link), list);
 620	last_link = media_pipeline_walk_pop(walk);
 621
 622	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
 623		dev_dbg(walk->mdev->dev,
 624			"media pipeline: skipping link (not data-link)\n");
 625		return 0;
 626	}
 627
 628	dev_dbg(walk->mdev->dev,
 629		"media pipeline: exploring link '%s':%u -> '%s':%u\n",
 630		link->source->entity->name, link->source->index,
 631		link->sink->entity->name, link->sink->index);
 632
 633	/* Get the local pad and remote pad. */
 634	if (link->source->entity == origin->entity) {
 635		local = link->source;
 636		remote = link->sink;
 637	} else {
 638		local = link->sink;
 639		remote = link->source;
 640	}
 641
 642	/*
 643	 * Skip links that originate from a different pad than the incoming pad
 644	 * that is not connected internally in the entity to the incoming pad.
 645	 */
 646	if (origin != local &&
 647	    !media_entity_has_pad_interdep(origin->entity, origin->index,
 648					   local->index)) {
 649		dev_dbg(walk->mdev->dev,
 650			"media pipeline: skipping link (no route)\n");
 651		goto done;
 652	}
 653
 654	/*
 655	 * Add the local pad of the link to the pipeline and push it to the
 656	 * stack, if not already present.
 657	 */
 658	ret = media_pipeline_add_pad(pipe, walk, local);
 659	if (ret)
 660		return ret;
 661
 662	/* Similarly, add the remote pad, but only if the link is enabled. */
 663	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 664		dev_dbg(walk->mdev->dev,
 665			"media pipeline: skipping link (disabled)\n");
 666		goto done;
 667	}
 668
 669	ret = media_pipeline_add_pad(pipe, walk, remote);
 670	if (ret)
 671		return ret;
 672
 673done:
 674	/*
 675	 * If we're done iterating over links, iterate over pads of the entity.
 676	 * This is necessary to discover pads that are not connected with any
 677	 * link. Those are dead ends from a pipeline exploration point of view,
 678	 * but are still part of the pipeline and need to be added to enable
 679	 * proper validation.
 680	 */
 681	if (!last_link)
 682		return 0;
 683
 684	dev_dbg(walk->mdev->dev,
 685		"media pipeline: adding unconnected pads of '%s'\n",
 686		local->entity->name);
 687
 688	media_entity_for_each_pad(origin->entity, local) {
 689		/*
 690		 * Skip the origin pad (already handled), pad that have links
 691		 * (already discovered through iterating over links) and pads
 692		 * not internally connected.
 693		 */
 694		if (origin == local || !local->num_links ||
 695		    !media_entity_has_pad_interdep(origin->entity, origin->index,
 696						   local->index))
 697			continue;
 698
 699		ret = media_pipeline_add_pad(pipe, walk, local);
 700		if (ret)
 701			return ret;
 702	}
 703
 704	return 0;
 705}
 
 706
 707static void media_pipeline_cleanup(struct media_pipeline *pipe)
 708{
 709	while (!list_empty(&pipe->pads)) {
 710		struct media_pipeline_pad *ppad;
 711
 712		ppad = list_first_entry(&pipe->pads, typeof(*ppad), list);
 713		list_del(&ppad->list);
 714		kfree(ppad);
 715	}
 716}
 717
 718static int media_pipeline_populate(struct media_pipeline *pipe,
 719				   struct media_pad *pad)
 720{
 721	struct media_pipeline_walk walk = { };
 722	struct media_pipeline_pad *ppad;
 
 
 723	int ret;
 724
 725	/*
 726	 * Populate the media pipeline by walking the media graph, starting
 727	 * from @pad.
 728	 */
 729	INIT_LIST_HEAD(&pipe->pads);
 730	pipe->mdev = pad->graph_obj.mdev;
 731
 732	walk.mdev = pipe->mdev;
 733	walk.stack.top = -1;
 734	ret = media_pipeline_add_pad(pipe, &walk, pad);
 735	if (ret)
 736		goto done;
 737
 738	/*
 739	 * Use a depth-first search algorithm: as long as the stack is not
 740	 * empty, explore the next link of the top entry. The
 741	 * media_pipeline_explore_next_link() function will either move to the
 742	 * next link, pop the entry if fully visited, or add new entries on
 743	 * top.
 744	 */
 745	while (!media_pipeline_walk_empty(&walk)) {
 746		ret = media_pipeline_explore_next_link(pipe, &walk);
 747		if (ret)
 748			goto done;
 749	}
 750
 751	dev_dbg(pad->graph_obj.mdev->dev,
 752		"media pipeline populated, found pads:\n");
 753
 754	list_for_each_entry(ppad, &pipe->pads, list)
 755		dev_dbg(pad->graph_obj.mdev->dev, "- '%s':%u\n",
 756			ppad->pad->entity->name, ppad->pad->index);
 757
 758	WARN_ON(walk.stack.top != -1);
 759
 760	ret = 0;
 761
 762done:
 763	media_pipeline_walk_destroy(&walk);
 764
 765	if (ret)
 766		media_pipeline_cleanup(pipe);
 767
 768	return ret;
 769}
 770
 771__must_check int __media_pipeline_start(struct media_pad *origin,
 772					struct media_pipeline *pipe)
 773{
 774	struct media_device *mdev = origin->graph_obj.mdev;
 775	struct media_pipeline_pad *err_ppad;
 776	struct media_pipeline_pad *ppad;
 777	int ret;
 778
 779	lockdep_assert_held(&mdev->graph_mutex);
 
 
 780
 781	/*
 782	 * If the pad is already part of a pipeline, that pipeline must be the
 783	 * same as the pipe given to media_pipeline_start().
 784	 */
 785	if (WARN_ON(origin->pipe && origin->pipe != pipe))
 786		return -EINVAL;
 787
 788	/*
 789	 * If the pipeline has already been started, it is guaranteed to be
 790	 * valid, so just increase the start count.
 791	 */
 792	if (pipe->start_count) {
 793		pipe->start_count++;
 794		return 0;
 795	}
 796
 797	/*
 798	 * Populate the pipeline. This populates the media_pipeline pads list
 799	 * with media_pipeline_pad instances for each pad found during graph
 800	 * walk.
 801	 */
 802	ret = media_pipeline_populate(pipe, origin);
 803	if (ret)
 804		return ret;
 805
 806	/*
 807	 * Now that all the pads in the pipeline have been gathered, perform
 808	 * the validation steps.
 809	 */
 810
 811	list_for_each_entry(ppad, &pipe->pads, list) {
 812		struct media_pad *pad = ppad->pad;
 813		struct media_entity *entity = pad->entity;
 814		bool has_enabled_link = false;
 815		struct media_link *link;
 816
 817		dev_dbg(mdev->dev, "Validating pad '%s':%u\n", pad->entity->name,
 818			pad->index);
 819
 820		/*
 821		 * 1. Ensure that the pad doesn't already belong to a different
 822		 * pipeline.
 823		 */
 824		if (pad->pipe) {
 825			dev_dbg(mdev->dev, "Failed to start pipeline: pad '%s':%u busy\n",
 826				pad->entity->name, pad->index);
 827			ret = -EBUSY;
 828			goto error;
 829		}
 830
 831		/*
 832		 * 2. Validate all active links whose sink is the current pad.
 833		 * Validation of the source pads is performed in the context of
 834		 * the connected sink pad to avoid duplicating checks.
 835		 */
 836		for_each_media_entity_data_link(entity, link) {
 837			/* Skip links unrelated to the current pad. */
 838			if (link->sink != pad && link->source != pad)
 839				continue;
 840
 841			/* Record if the pad has links and enabled links. */
 842			if (link->flags & MEDIA_LNK_FL_ENABLED)
 843				has_enabled_link = true;
 844
 845			/*
 846			 * Validate the link if it's enabled and has the
 847			 * current pad as its sink.
 
 848			 */
 849			if (!(link->flags & MEDIA_LNK_FL_ENABLED))
 850				continue;
 851
 852			if (link->sink != pad)
 853				continue;
 854
 855			if (!entity->ops || !entity->ops->link_validate)
 
 
 
 
 
 856				continue;
 857
 858			ret = entity->ops->link_validate(link);
 859			if (ret) {
 860				dev_dbg(mdev->dev,
 861					"Link '%s':%u -> '%s':%u failed validation: %d\n",
 862					link->source->entity->name,
 863					link->source->index,
 864					link->sink->entity->name,
 865					link->sink->index, ret);
 866				goto error;
 867			}
 868
 869			dev_dbg(mdev->dev,
 870				"Link '%s':%u -> '%s':%u is valid\n",
 871				link->source->entity->name,
 872				link->source->index,
 873				link->sink->entity->name,
 874				link->sink->index);
 875		}
 876
 877		/*
 878		 * 3. If the pad has the MEDIA_PAD_FL_MUST_CONNECT flag set,
 879		 * ensure that it has either no link or an enabled link.
 880		 */
 881		if ((pad->flags & MEDIA_PAD_FL_MUST_CONNECT) &&
 882		    !has_enabled_link) {
 883			dev_dbg(mdev->dev,
 884				"Pad '%s':%u must be connected by an enabled link\n",
 885				pad->entity->name, pad->index);
 886			ret = -ENOLINK;
 
 
 
 
 
 887			goto error;
 888		}
 889
 890		/* Validation passed, store the pipe pointer in the pad. */
 891		pad->pipe = pipe;
 892	}
 893
 894	pipe->start_count++;
 895
 896	return 0;
 897
 898error:
 899	/*
 900	 * Link validation on graph failed. We revert what we did and
 901	 * return the error.
 902	 */
 
 903
 904	list_for_each_entry(err_ppad, &pipe->pads, list) {
 905		if (err_ppad == ppad)
 906			break;
 
 
 
 
 907
 908		err_ppad->pad->pipe = NULL;
 
 
 
 
 
 909	}
 910
 911	media_pipeline_cleanup(pipe);
 
 
 912
 913	return ret;
 914}
 915EXPORT_SYMBOL_GPL(__media_pipeline_start);
 916
 917__must_check int media_pipeline_start(struct media_pad *origin,
 918				      struct media_pipeline *pipe)
 919{
 920	struct media_device *mdev = origin->graph_obj.mdev;
 921	int ret;
 922
 923	mutex_lock(&mdev->graph_mutex);
 924	ret = __media_pipeline_start(origin, pipe);
 925	mutex_unlock(&mdev->graph_mutex);
 926	return ret;
 927}
 928EXPORT_SYMBOL_GPL(media_pipeline_start);
 929
 930void __media_pipeline_stop(struct media_pad *pad)
 931{
 932	struct media_pipeline *pipe = pad->pipe;
 933	struct media_pipeline_pad *ppad;
 934
 935	/*
 936	 * If the following check fails, the driver has performed an
 937	 * unbalanced call to media_pipeline_stop()
 938	 */
 939	if (WARN_ON(!pipe))
 940		return;
 941
 942	if (--pipe->start_count)
 943		return;
 944
 945	list_for_each_entry(ppad, &pipe->pads, list)
 946		ppad->pad->pipe = NULL;
 
 
 
 
 
 
 947
 948	media_pipeline_cleanup(pipe);
 
 949
 950	if (pipe->allocated)
 951		kfree(pipe);
 952}
 953EXPORT_SYMBOL_GPL(__media_pipeline_stop);
 954
 955void media_pipeline_stop(struct media_pad *pad)
 956{
 957	struct media_device *mdev = pad->graph_obj.mdev;
 958
 959	mutex_lock(&mdev->graph_mutex);
 960	__media_pipeline_stop(pad);
 961	mutex_unlock(&mdev->graph_mutex);
 962}
 963EXPORT_SYMBOL_GPL(media_pipeline_stop);
 964
 965__must_check int media_pipeline_alloc_start(struct media_pad *pad)
 966{
 967	struct media_device *mdev = pad->graph_obj.mdev;
 968	struct media_pipeline *new_pipe = NULL;
 969	struct media_pipeline *pipe;
 970	int ret;
 971
 972	mutex_lock(&mdev->graph_mutex);
 973
 974	/*
 975	 * Is the pad already part of a pipeline? If not, we need to allocate
 976	 * a pipe.
 977	 */
 978	pipe = media_pad_pipeline(pad);
 979	if (!pipe) {
 980		new_pipe = kzalloc(sizeof(*new_pipe), GFP_KERNEL);
 981		if (!new_pipe) {
 982			ret = -ENOMEM;
 983			goto out;
 984		}
 985
 986		pipe = new_pipe;
 987		pipe->allocated = true;
 988	}
 989
 990	ret = __media_pipeline_start(pad, pipe);
 991	if (ret)
 992		kfree(new_pipe);
 993
 994out:
 995	mutex_unlock(&mdev->graph_mutex);
 996
 997	return ret;
 998}
 999EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
1000
1001struct media_pad *
1002__media_pipeline_pad_iter_next(struct media_pipeline *pipe,
1003			       struct media_pipeline_pad_iter *iter,
1004			       struct media_pad *pad)
1005{
1006	if (!pad)
1007		iter->cursor = pipe->pads.next;
1008
1009	if (iter->cursor == &pipe->pads)
1010		return NULL;
1011
1012	pad = list_entry(iter->cursor, struct media_pipeline_pad, list)->pad;
1013	iter->cursor = iter->cursor->next;
1014
1015	return pad;
1016}
1017EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
1018
1019int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
1020				    struct media_pipeline_entity_iter *iter)
1021{
1022	return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
1023}
1024EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
1025
1026void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
1027{
1028	media_entity_enum_cleanup(&iter->ent_enum);
1029}
1030EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
1031
1032struct media_entity *
1033__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
1034				  struct media_pipeline_entity_iter *iter,
1035				  struct media_entity *entity)
1036{
1037	if (!entity)
1038		iter->cursor = pipe->pads.next;
1039
1040	while (iter->cursor != &pipe->pads) {
1041		struct media_pipeline_pad *ppad;
1042		struct media_entity *entity;
1043
1044		ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
1045		entity = ppad->pad->entity;
1046		iter->cursor = iter->cursor->next;
1047
1048		if (!media_entity_enum_test_and_set(&iter->ent_enum, entity))
1049			return entity;
1050	}
1051
1052	return NULL;
1053}
1054EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
1055
1056/* -----------------------------------------------------------------------------
1057 * Links management
1058 */
1059
1060static struct media_link *media_add_link(struct list_head *head)
1061{
1062	struct media_link *link;
1063
1064	link = kzalloc(sizeof(*link), GFP_KERNEL);
1065	if (link == NULL)
1066		return NULL;
1067
1068	list_add_tail(&link->list, head);
1069
1070	return link;
1071}
1072
1073static void __media_entity_remove_link(struct media_entity *entity,
1074				       struct media_link *link)
1075{
1076	struct media_link *rlink, *tmp;
1077	struct media_entity *remote;
1078
1079	/* Remove the reverse links for a data link. */
1080	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
1081		link->source->num_links--;
1082		link->sink->num_links--;
1083
1084		if (link->source->entity == entity)
1085			remote = link->sink->entity;
1086		else
1087			remote = link->source->entity;
1088
1089		list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
1090			if (rlink != link->reverse)
1091				continue;
1092
1093			if (link->source->entity == entity)
1094				remote->num_backlinks--;
1095
1096			/* Remove the remote link */
1097			list_del(&rlink->list);
1098			media_gobj_destroy(&rlink->graph_obj);
1099			kfree(rlink);
1100
1101			if (--remote->num_links == 0)
1102				break;
1103		}
1104	}
1105
1106	list_del(&link->list);
1107	media_gobj_destroy(&link->graph_obj);
1108	kfree(link);
1109}
1110
1111int media_get_pad_index(struct media_entity *entity, u32 pad_type,
1112			enum media_pad_signal_type sig_type)
1113{
1114	unsigned int i;
 
1115
1116	if (!entity)
1117		return -EINVAL;
1118
1119	for (i = 0; i < entity->num_pads; i++) {
1120		if ((entity->pads[i].flags &
1121		     (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type)
1122			continue;
 
 
 
1123
 
 
1124		if (entity->pads[i].sig_type == sig_type)
1125			return i;
1126	}
1127	return -EINVAL;
1128}
1129EXPORT_SYMBOL_GPL(media_get_pad_index);
1130
1131int
1132media_create_pad_link(struct media_entity *source, u16 source_pad,
1133			 struct media_entity *sink, u16 sink_pad, u32 flags)
1134{
1135	struct media_link *link;
1136	struct media_link *backlink;
1137
1138	if (flags & MEDIA_LNK_FL_LINK_TYPE)
1139		return -EINVAL;
1140
1141	flags |= MEDIA_LNK_FL_DATA_LINK;
1142
1143	if (WARN_ON(!source || !sink) ||
1144	    WARN_ON(source_pad >= source->num_pads) ||
1145	    WARN_ON(sink_pad >= sink->num_pads))
1146		return -EINVAL;
1147	if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE)))
1148		return -EINVAL;
1149	if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
1150		return -EINVAL;
1151
1152	link = media_add_link(&source->links);
1153	if (link == NULL)
1154		return -ENOMEM;
1155
1156	link->source = &source->pads[source_pad];
1157	link->sink = &sink->pads[sink_pad];
1158	link->flags = flags;
1159
1160	/* Initialize graph object embedded at the new link */
1161	media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
1162			&link->graph_obj);
1163
1164	/* Create the backlink. Backlinks are used to help graph traversal and
1165	 * are not reported to userspace.
1166	 */
1167	backlink = media_add_link(&sink->links);
1168	if (backlink == NULL) {
1169		__media_entity_remove_link(source, link);
1170		return -ENOMEM;
1171	}
1172
1173	backlink->source = &source->pads[source_pad];
1174	backlink->sink = &sink->pads[sink_pad];
1175	backlink->flags = flags;
1176	backlink->is_backlink = true;
1177
1178	/* Initialize graph object embedded at the new link */
1179	media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
1180			&backlink->graph_obj);
1181
1182	link->reverse = backlink;
1183	backlink->reverse = link;
1184
1185	sink->num_backlinks++;
1186	sink->num_links++;
1187	source->num_links++;
1188
1189	link->source->num_links++;
1190	link->sink->num_links++;
1191
1192	return 0;
1193}
1194EXPORT_SYMBOL_GPL(media_create_pad_link);
1195
1196int media_create_pad_links(const struct media_device *mdev,
1197			   const u32 source_function,
1198			   struct media_entity *source,
1199			   const u16 source_pad,
1200			   const u32 sink_function,
1201			   struct media_entity *sink,
1202			   const u16 sink_pad,
1203			   u32 flags,
1204			   const bool allow_both_undefined)
1205{
1206	struct media_entity *entity;
1207	unsigned function;
1208	int ret;
1209
1210	/* Trivial case: 1:1 relation */
1211	if (source && sink)
1212		return media_create_pad_link(source, source_pad,
1213					     sink, sink_pad, flags);
1214
1215	/* Worse case scenario: n:n relation */
1216	if (!source && !sink) {
1217		if (!allow_both_undefined)
1218			return 0;
1219		media_device_for_each_entity(source, mdev) {
1220			if (source->function != source_function)
1221				continue;
1222			media_device_for_each_entity(sink, mdev) {
1223				if (sink->function != sink_function)
1224					continue;
1225				ret = media_create_pad_link(source, source_pad,
1226							    sink, sink_pad,
1227							    flags);
1228				if (ret)
1229					return ret;
1230				flags &= ~(MEDIA_LNK_FL_ENABLED |
1231					   MEDIA_LNK_FL_IMMUTABLE);
1232			}
1233		}
1234		return 0;
1235	}
1236
1237	/* Handle 1:n and n:1 cases */
1238	if (source)
1239		function = sink_function;
1240	else
1241		function = source_function;
1242
1243	media_device_for_each_entity(entity, mdev) {
1244		if (entity->function != function)
1245			continue;
1246
1247		if (source)
1248			ret = media_create_pad_link(source, source_pad,
1249						    entity, sink_pad, flags);
1250		else
1251			ret = media_create_pad_link(entity, source_pad,
1252						    sink, sink_pad, flags);
1253		if (ret)
1254			return ret;
1255		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
1256	}
1257	return 0;
1258}
1259EXPORT_SYMBOL_GPL(media_create_pad_links);
1260
1261void __media_entity_remove_links(struct media_entity *entity)
1262{
1263	struct media_link *link, *tmp;
1264
1265	list_for_each_entry_safe(link, tmp, &entity->links, list)
1266		__media_entity_remove_link(entity, link);
1267
1268	entity->num_links = 0;
1269	entity->num_backlinks = 0;
1270}
1271EXPORT_SYMBOL_GPL(__media_entity_remove_links);
1272
1273void media_entity_remove_links(struct media_entity *entity)
1274{
1275	struct media_device *mdev = entity->graph_obj.mdev;
1276
1277	/* Do nothing if the entity is not registered. */
1278	if (mdev == NULL)
1279		return;
1280
1281	mutex_lock(&mdev->graph_mutex);
1282	__media_entity_remove_links(entity);
1283	mutex_unlock(&mdev->graph_mutex);
1284}
1285EXPORT_SYMBOL_GPL(media_entity_remove_links);
1286
1287static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
1288{
1289	int ret;
1290
1291	/* Notify both entities. */
1292	ret = media_entity_call(link->source->entity, link_setup,
1293				link->source, link->sink, flags);
1294	if (ret < 0 && ret != -ENOIOCTLCMD)
1295		return ret;
1296
1297	ret = media_entity_call(link->sink->entity, link_setup,
1298				link->sink, link->source, flags);
1299	if (ret < 0 && ret != -ENOIOCTLCMD) {
1300		media_entity_call(link->source->entity, link_setup,
1301				  link->source, link->sink, link->flags);
1302		return ret;
1303	}
1304
1305	link->flags = flags;
1306	link->reverse->flags = link->flags;
1307
1308	return 0;
1309}
1310
1311int __media_entity_setup_link(struct media_link *link, u32 flags)
1312{
1313	const u32 mask = MEDIA_LNK_FL_ENABLED;
1314	struct media_device *mdev;
1315	struct media_pad *source, *sink;
1316	int ret = -EBUSY;
1317
1318	if (link == NULL)
1319		return -EINVAL;
1320
1321	/* The non-modifiable link flags must not be modified. */
1322	if ((link->flags & ~mask) != (flags & ~mask))
1323		return -EINVAL;
1324
1325	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
1326		return link->flags == flags ? 0 : -EINVAL;
1327
1328	if (link->flags == flags)
1329		return 0;
1330
1331	source = link->source;
1332	sink = link->sink;
1333
1334	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
1335	    (media_pad_is_streaming(source) || media_pad_is_streaming(sink)))
1336		return -EBUSY;
1337
1338	mdev = source->graph_obj.mdev;
1339
1340	if (mdev->ops && mdev->ops->link_notify) {
1341		ret = mdev->ops->link_notify(link, flags,
1342					     MEDIA_DEV_NOTIFY_PRE_LINK_CH);
1343		if (ret < 0)
1344			return ret;
1345	}
1346
1347	ret = __media_entity_setup_link_notify(link, flags);
1348
1349	if (mdev->ops && mdev->ops->link_notify)
1350		mdev->ops->link_notify(link, flags,
1351				       MEDIA_DEV_NOTIFY_POST_LINK_CH);
1352
1353	return ret;
1354}
1355EXPORT_SYMBOL_GPL(__media_entity_setup_link);
1356
1357int media_entity_setup_link(struct media_link *link, u32 flags)
1358{
1359	int ret;
1360
1361	mutex_lock(&link->graph_obj.mdev->graph_mutex);
1362	ret = __media_entity_setup_link(link, flags);
1363	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
1364
1365	return ret;
1366}
1367EXPORT_SYMBOL_GPL(media_entity_setup_link);
1368
1369struct media_link *
1370media_entity_find_link(struct media_pad *source, struct media_pad *sink)
1371{
1372	struct media_link *link;
1373
1374	for_each_media_entity_data_link(source->entity, link) {
1375		if (link->source->entity == source->entity &&
1376		    link->source->index == source->index &&
1377		    link->sink->entity == sink->entity &&
1378		    link->sink->index == sink->index)
1379			return link;
1380	}
1381
1382	return NULL;
1383}
1384EXPORT_SYMBOL_GPL(media_entity_find_link);
1385
1386struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)
1387{
1388	struct media_link *link;
1389
1390	for_each_media_entity_data_link(pad->entity, link) {
1391		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
1392			continue;
1393
1394		if (link->source == pad)
1395			return link->sink;
1396
1397		if (link->sink == pad)
1398			return link->source;
1399	}
1400
1401	return NULL;
1402
1403}
1404EXPORT_SYMBOL_GPL(media_pad_remote_pad_first);
1405
1406struct media_pad *
1407media_entity_remote_pad_unique(const struct media_entity *entity,
1408			       unsigned int type)
1409{
1410	struct media_pad *pad = NULL;
1411	struct media_link *link;
1412
1413	list_for_each_entry(link, &entity->links, list) {
1414		struct media_pad *local_pad;
1415		struct media_pad *remote_pad;
1416
1417		if (((link->flags & MEDIA_LNK_FL_LINK_TYPE) !=
1418		     MEDIA_LNK_FL_DATA_LINK) ||
1419		    !(link->flags & MEDIA_LNK_FL_ENABLED))
1420			continue;
1421
1422		if (type == MEDIA_PAD_FL_SOURCE) {
1423			local_pad = link->sink;
1424			remote_pad = link->source;
1425		} else {
1426			local_pad = link->source;
1427			remote_pad = link->sink;
1428		}
1429
1430		if (local_pad->entity == entity) {
1431			if (pad)
1432				return ERR_PTR(-ENOTUNIQ);
1433
1434			pad = remote_pad;
1435		}
1436	}
1437
1438	if (!pad)
1439		return ERR_PTR(-ENOLINK);
1440
1441	return pad;
1442}
1443EXPORT_SYMBOL_GPL(media_entity_remote_pad_unique);
1444
1445struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
1446{
1447	struct media_pad *found_pad = NULL;
1448	struct media_link *link;
1449
1450	list_for_each_entry(link, &pad->entity->links, list) {
1451		struct media_pad *remote_pad;
1452
1453		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
1454			continue;
1455
1456		if (link->sink == pad)
1457			remote_pad = link->source;
1458		else if (link->source == pad)
1459			remote_pad = link->sink;
1460		else
1461			continue;
1462
1463		if (found_pad)
1464			return ERR_PTR(-ENOTUNIQ);
1465
1466		found_pad = remote_pad;
1467	}
1468
1469	if (!found_pad)
1470		return ERR_PTR(-ENOLINK);
1471
1472	return found_pad;
1473}
1474EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
1475
1476int media_entity_get_fwnode_pad(struct media_entity *entity,
1477				const struct fwnode_handle *fwnode,
1478				unsigned long direction_flags)
1479{
1480	struct fwnode_endpoint endpoint;
1481	unsigned int i;
1482	int ret;
1483
1484	if (!entity->ops || !entity->ops->get_fwnode_pad) {
1485		for (i = 0; i < entity->num_pads; i++) {
1486			if (entity->pads[i].flags & direction_flags)
1487				return i;
1488		}
1489
1490		return -ENXIO;
1491	}
1492
1493	ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
1494	if (ret)
1495		return ret;
1496
1497	ret = entity->ops->get_fwnode_pad(entity, &endpoint);
1498	if (ret < 0)
1499		return ret;
1500
1501	if (ret >= entity->num_pads)
1502		return -ENXIO;
1503
1504	if (!(entity->pads[ret].flags & direction_flags))
1505		return -ENXIO;
1506
1507	return ret;
1508}
1509EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
1510
1511struct media_pipeline *media_entity_pipeline(struct media_entity *entity)
1512{
1513	struct media_pad *pad;
1514
1515	media_entity_for_each_pad(entity, pad) {
1516		if (pad->pipe)
1517			return pad->pipe;
1518	}
1519
1520	return NULL;
1521}
1522EXPORT_SYMBOL_GPL(media_entity_pipeline);
1523
1524struct media_pipeline *media_pad_pipeline(struct media_pad *pad)
1525{
1526	return pad->pipe;
1527}
1528EXPORT_SYMBOL_GPL(media_pad_pipeline);
1529
1530static void media_interface_init(struct media_device *mdev,
1531				 struct media_interface *intf,
1532				 u32 gobj_type,
1533				 u32 intf_type, u32 flags)
1534{
1535	intf->type = intf_type;
1536	intf->flags = flags;
1537	INIT_LIST_HEAD(&intf->links);
1538
1539	media_gobj_create(mdev, gobj_type, &intf->graph_obj);
1540}
1541
1542/* Functions related to the media interface via device nodes */
1543
1544struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
1545						u32 type, u32 flags,
1546						u32 major, u32 minor)
1547{
1548	struct media_intf_devnode *devnode;
1549
1550	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
1551	if (!devnode)
1552		return NULL;
1553
1554	devnode->major = major;
1555	devnode->minor = minor;
1556
1557	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
1558			     type, flags);
1559
1560	return devnode;
1561}
1562EXPORT_SYMBOL_GPL(media_devnode_create);
1563
1564void media_devnode_remove(struct media_intf_devnode *devnode)
1565{
1566	media_remove_intf_links(&devnode->intf);
1567	media_gobj_destroy(&devnode->intf.graph_obj);
1568	kfree(devnode);
1569}
1570EXPORT_SYMBOL_GPL(media_devnode_remove);
1571
1572struct media_link *media_create_intf_link(struct media_entity *entity,
1573					    struct media_interface *intf,
1574					    u32 flags)
1575{
1576	struct media_link *link;
1577
1578	link = media_add_link(&intf->links);
1579	if (link == NULL)
1580		return NULL;
1581
1582	link->intf = intf;
1583	link->entity = entity;
1584	link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
1585
1586	/* Initialize graph object embedded at the new link */
1587	media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
1588			&link->graph_obj);
1589
1590	return link;
1591}
1592EXPORT_SYMBOL_GPL(media_create_intf_link);
1593
1594void __media_remove_intf_link(struct media_link *link)
1595{
1596	list_del(&link->list);
1597	media_gobj_destroy(&link->graph_obj);
1598	kfree(link);
1599}
1600EXPORT_SYMBOL_GPL(__media_remove_intf_link);
1601
1602void media_remove_intf_link(struct media_link *link)
1603{
1604	struct media_device *mdev = link->graph_obj.mdev;
1605
1606	/* Do nothing if the intf is not registered. */
1607	if (mdev == NULL)
1608		return;
1609
1610	mutex_lock(&mdev->graph_mutex);
1611	__media_remove_intf_link(link);
1612	mutex_unlock(&mdev->graph_mutex);
1613}
1614EXPORT_SYMBOL_GPL(media_remove_intf_link);
1615
1616void __media_remove_intf_links(struct media_interface *intf)
1617{
1618	struct media_link *link, *tmp;
1619
1620	list_for_each_entry_safe(link, tmp, &intf->links, list)
1621		__media_remove_intf_link(link);
1622
1623}
1624EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1625
1626void media_remove_intf_links(struct media_interface *intf)
1627{
1628	struct media_device *mdev = intf->graph_obj.mdev;
1629
1630	/* Do nothing if the intf is not registered. */
1631	if (mdev == NULL)
1632		return;
1633
1634	mutex_lock(&mdev->graph_mutex);
1635	__media_remove_intf_links(intf);
1636	mutex_unlock(&mdev->graph_mutex);
1637}
1638EXPORT_SYMBOL_GPL(media_remove_intf_links);
1639
1640struct media_link *media_create_ancillary_link(struct media_entity *primary,
1641					       struct media_entity *ancillary)
1642{
1643	struct media_link *link;
1644
1645	link = media_add_link(&primary->links);
1646	if (!link)
1647		return ERR_PTR(-ENOMEM);
1648
1649	link->gobj0 = &primary->graph_obj;
1650	link->gobj1 = &ancillary->graph_obj;
1651	link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
1652		      MEDIA_LNK_FL_ANCILLARY_LINK;
1653
1654	/* Initialize graph object embedded in the new link */
1655	media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
1656			  &link->graph_obj);
1657
1658	return link;
1659}
1660EXPORT_SYMBOL_GPL(media_create_ancillary_link);
1661
1662struct media_link *__media_entity_next_link(struct media_entity *entity,
1663					    struct media_link *link,
1664					    unsigned long link_type)
1665{
1666	link = link ? list_next_entry(link, list)
1667		    : list_first_entry(&entity->links, typeof(*link), list);
1668
1669	list_for_each_entry_from(link, &entity->links, list)
1670		if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == link_type)
1671			return link;
1672
1673	return NULL;
1674}
1675EXPORT_SYMBOL_GPL(__media_entity_next_link);
v5.4
   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
  17static inline const char *gobj_type(enum media_gobj_type type)
  18{
  19	switch (type) {
  20	case MEDIA_GRAPH_ENTITY:
  21		return "entity";
  22	case MEDIA_GRAPH_PAD:
  23		return "pad";
  24	case MEDIA_GRAPH_LINK:
  25		return "link";
  26	case MEDIA_GRAPH_INTF_DEVNODE:
  27		return "intf-devnode";
  28	default:
  29		return "unknown";
  30	}
  31}
  32
  33static inline const char *intf_type(struct media_interface *intf)
  34{
  35	switch (intf->type) {
  36	case MEDIA_INTF_T_DVB_FE:
  37		return "dvb-frontend";
  38	case MEDIA_INTF_T_DVB_DEMUX:
  39		return "dvb-demux";
  40	case MEDIA_INTF_T_DVB_DVR:
  41		return "dvb-dvr";
  42	case MEDIA_INTF_T_DVB_CA:
  43		return  "dvb-ca";
  44	case MEDIA_INTF_T_DVB_NET:
  45		return "dvb-net";
  46	case MEDIA_INTF_T_V4L_VIDEO:
  47		return "v4l-video";
  48	case MEDIA_INTF_T_V4L_VBI:
  49		return "v4l-vbi";
  50	case MEDIA_INTF_T_V4L_RADIO:
  51		return "v4l-radio";
  52	case MEDIA_INTF_T_V4L_SUBDEV:
  53		return "v4l-subdev";
  54	case MEDIA_INTF_T_V4L_SWRADIO:
  55		return "v4l-swradio";
  56	case MEDIA_INTF_T_V4L_TOUCH:
  57		return "v4l-touch";
  58	default:
  59		return "unknown-intf";
  60	}
  61};
  62
  63__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
  64					  int idx_max)
  65{
  66	idx_max = ALIGN(idx_max, BITS_PER_LONG);
  67	ent_enum->bmap = kcalloc(idx_max / BITS_PER_LONG, sizeof(long),
  68				 GFP_KERNEL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  69	if (!ent_enum->bmap)
  70		return -ENOMEM;
  71
  72	bitmap_zero(ent_enum->bmap, idx_max);
  73	ent_enum->idx_max = idx_max;
  74
  75	return 0;
  76}
  77EXPORT_SYMBOL_GPL(__media_entity_enum_init);
  78
  79void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
  80{
  81	kfree(ent_enum->bmap);
  82}
  83EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
  84
  85/**
  86 *  dev_dbg_obj - Prints in debug mode a change on some object
  87 *
  88 * @event_name:	Name of the event to report. Could be __func__
  89 * @gobj:	Pointer to the object
  90 *
  91 * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it
  92 * won't produce any code.
  93 */
  94static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
  95{
  96#if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
  97	switch (media_type(gobj)) {
  98	case MEDIA_GRAPH_ENTITY:
  99		dev_dbg(gobj->mdev->dev,
 100			"%s id %u: entity '%s'\n",
 101			event_name, media_id(gobj),
 102			gobj_to_entity(gobj)->name);
 103		break;
 104	case MEDIA_GRAPH_LINK:
 105	{
 106		struct media_link *link = gobj_to_link(gobj);
 107
 108		dev_dbg(gobj->mdev->dev,
 109			"%s id %u: %s link id %u ==> id %u\n",
 110			event_name, media_id(gobj),
 111			media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
 112				"data" : "interface",
 113			media_id(link->gobj0),
 114			media_id(link->gobj1));
 115		break;
 116	}
 117	case MEDIA_GRAPH_PAD:
 118	{
 119		struct media_pad *pad = gobj_to_pad(gobj);
 120
 121		dev_dbg(gobj->mdev->dev,
 122			"%s id %u: %s%spad '%s':%d\n",
 123			event_name, media_id(gobj),
 124			pad->flags & MEDIA_PAD_FL_SINK   ? "sink " : "",
 125			pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "",
 126			pad->entity->name, pad->index);
 127		break;
 128	}
 129	case MEDIA_GRAPH_INTF_DEVNODE:
 130	{
 131		struct media_interface *intf = gobj_to_intf(gobj);
 132		struct media_intf_devnode *devnode = intf_to_devnode(intf);
 133
 134		dev_dbg(gobj->mdev->dev,
 135			"%s id %u: intf_devnode %s - major: %d, minor: %d\n",
 136			event_name, media_id(gobj),
 137			intf_type(intf),
 138			devnode->major, devnode->minor);
 139		break;
 140	}
 141	}
 142#endif
 143}
 144
 145void media_gobj_create(struct media_device *mdev,
 146			   enum media_gobj_type type,
 147			   struct media_gobj *gobj)
 148{
 149	BUG_ON(!mdev);
 150
 151	gobj->mdev = mdev;
 152
 153	/* Create a per-type unique object ID */
 154	gobj->id = media_gobj_gen_id(type, ++mdev->id);
 155
 156	switch (type) {
 157	case MEDIA_GRAPH_ENTITY:
 158		list_add_tail(&gobj->list, &mdev->entities);
 159		break;
 160	case MEDIA_GRAPH_PAD:
 161		list_add_tail(&gobj->list, &mdev->pads);
 162		break;
 163	case MEDIA_GRAPH_LINK:
 164		list_add_tail(&gobj->list, &mdev->links);
 165		break;
 166	case MEDIA_GRAPH_INTF_DEVNODE:
 167		list_add_tail(&gobj->list, &mdev->interfaces);
 168		break;
 169	}
 170
 171	mdev->topology_version++;
 172
 173	dev_dbg_obj(__func__, gobj);
 174}
 175
 176void media_gobj_destroy(struct media_gobj *gobj)
 177{
 178	/* Do nothing if the object is not linked. */
 179	if (gobj->mdev == NULL)
 180		return;
 181
 182	dev_dbg_obj(__func__, gobj);
 183
 184	gobj->mdev->topology_version++;
 185
 186	/* Remove the object from mdev list */
 187	list_del(&gobj->list);
 188
 189	gobj->mdev = NULL;
 190}
 191
 192/*
 193 * TODO: Get rid of this.
 194 */
 195#define MEDIA_ENTITY_MAX_PADS		512
 196
 197int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
 198			   struct media_pad *pads)
 199{
 200	struct media_device *mdev = entity->graph_obj.mdev;
 201	unsigned int i;
 
 
 202
 203	if (num_pads >= MEDIA_ENTITY_MAX_PADS)
 204		return -E2BIG;
 205
 206	entity->num_pads = num_pads;
 207	entity->pads = pads;
 208
 209	if (mdev)
 210		mutex_lock(&mdev->graph_mutex);
 211
 212	for (i = 0; i < num_pads; i++) {
 213		pads[i].entity = entity;
 214		pads[i].index = i;
 
 
 
 
 
 
 
 215		if (mdev)
 216			media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 217					&entity->pads[i].graph_obj);
 
 
 
 
 
 218	}
 219
 220	if (mdev)
 221		mutex_unlock(&mdev->graph_mutex);
 222
 223	return 0;
 224}
 225EXPORT_SYMBOL_GPL(media_entity_pads_init);
 226
 227/* -----------------------------------------------------------------------------
 228 * Graph traversal
 229 */
 230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 231static struct media_entity *
 232media_entity_other(struct media_entity *entity, struct media_link *link)
 233{
 234	if (link->source->entity == entity)
 235		return link->sink->entity;
 236	else
 237		return link->source->entity;
 238}
 239
 240/* push an entity to traversal stack */
 241static void stack_push(struct media_graph *graph,
 242		       struct media_entity *entity)
 243{
 244	if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
 245		WARN_ON(1);
 246		return;
 247	}
 248	graph->top++;
 249	graph->stack[graph->top].link = entity->links.next;
 250	graph->stack[graph->top].entity = entity;
 251}
 252
 253static struct media_entity *stack_pop(struct media_graph *graph)
 254{
 255	struct media_entity *entity;
 256
 257	entity = graph->stack[graph->top].entity;
 258	graph->top--;
 259
 260	return entity;
 261}
 262
 263#define link_top(en)	((en)->stack[(en)->top].link)
 264#define stack_top(en)	((en)->stack[(en)->top].entity)
 265
 266/**
 267 * media_graph_walk_init - Allocate resources for graph walk
 268 * @graph: Media graph structure that will be used to walk the graph
 269 * @mdev: Media device
 270 *
 271 * Reserve resources for graph walk in media device's current
 272 * state. The memory must be released using
 273 * media_graph_walk_free().
 274 *
 275 * Returns error on failure, zero on success.
 276 */
 277__must_check int media_graph_walk_init(
 278	struct media_graph *graph, struct media_device *mdev)
 279{
 280	return media_entity_enum_init(&graph->ent_enum, mdev);
 281}
 282EXPORT_SYMBOL_GPL(media_graph_walk_init);
 283
 284/**
 285 * media_graph_walk_cleanup - Release resources related to graph walking
 286 * @graph: Media graph structure that was used to walk the graph
 287 */
 288void media_graph_walk_cleanup(struct media_graph *graph)
 289{
 290	media_entity_enum_cleanup(&graph->ent_enum);
 291}
 292EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
 293
 294void media_graph_walk_start(struct media_graph *graph,
 295			    struct media_entity *entity)
 296{
 297	media_entity_enum_zero(&graph->ent_enum);
 298	media_entity_enum_set(&graph->ent_enum, entity);
 299
 300	graph->top = 0;
 301	graph->stack[graph->top].entity = NULL;
 302	stack_push(graph, entity);
 303	dev_dbg(entity->graph_obj.mdev->dev,
 304		"begin graph walk at '%s'\n", entity->name);
 305}
 306EXPORT_SYMBOL_GPL(media_graph_walk_start);
 307
 308static void media_graph_walk_iter(struct media_graph *graph)
 309{
 310	struct media_entity *entity = stack_top(graph);
 311	struct media_link *link;
 312	struct media_entity *next;
 313
 314	link = list_entry(link_top(graph), typeof(*link), list);
 315
 
 
 
 
 
 
 316	/* The link is not enabled so we do not follow. */
 317	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
 318		link_top(graph) = link_top(graph)->next;
 319		dev_dbg(entity->graph_obj.mdev->dev,
 320			"walk: skipping disabled link '%s':%u -> '%s':%u\n",
 321			link->source->entity->name, link->source->index,
 322			link->sink->entity->name, link->sink->index);
 323		return;
 324	}
 325
 326	/* Get the entity in the other end of the link . */
 327	next = media_entity_other(entity, link);
 328
 329	/* Has the entity already been visited? */
 330	if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
 331		link_top(graph) = link_top(graph)->next;
 332		dev_dbg(entity->graph_obj.mdev->dev,
 333			"walk: skipping entity '%s' (already seen)\n",
 334			next->name);
 335		return;
 336	}
 337
 338	/* Push the new entity to stack and start over. */
 339	link_top(graph) = link_top(graph)->next;
 340	stack_push(graph, next);
 341	dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
 342		next->name);
 
 343}
 344
 345struct media_entity *media_graph_walk_next(struct media_graph *graph)
 346{
 347	struct media_entity *entity;
 348
 349	if (stack_top(graph) == NULL)
 350		return NULL;
 351
 352	/*
 353	 * Depth first search. Push entity to stack and continue from
 354	 * top of the stack until no more entities on the level can be
 355	 * found.
 356	 */
 357	while (link_top(graph) != &stack_top(graph)->links)
 358		media_graph_walk_iter(graph);
 359
 360	entity = stack_pop(graph);
 361	dev_dbg(entity->graph_obj.mdev->dev,
 362		"walk: returning entity '%s'\n", entity->name);
 363
 364	return entity;
 365}
 366EXPORT_SYMBOL_GPL(media_graph_walk_next);
 367
 368int media_entity_get_fwnode_pad(struct media_entity *entity,
 369				struct fwnode_handle *fwnode,
 370				unsigned long direction_flags)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 371{
 372	struct fwnode_endpoint endpoint;
 373	unsigned int i;
 374	int ret;
 375
 376	if (!entity->ops || !entity->ops->get_fwnode_pad) {
 377		for (i = 0; i < entity->num_pads; i++) {
 378			if (entity->pads[i].flags & direction_flags)
 379				return i;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 380		}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 381
 382		return -ENXIO;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 383	}
 384
 385	ret = fwnode_graph_parse_endpoint(fwnode, &endpoint);
 
 
 
 
 386	if (ret)
 387		return ret;
 388
 389	ret = entity->ops->get_fwnode_pad(&endpoint);
 390	if (ret < 0)
 
 
 
 
 
 
 
 391		return ret;
 392
 393	if (ret >= entity->num_pads)
 394		return -ENXIO;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 395
 396	if (!(entity->pads[ret].flags & direction_flags))
 397		return -ENXIO;
 
 
 398
 399	return ret;
 400}
 401EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
 402
 403/* -----------------------------------------------------------------------------
 404 * Pipeline management
 405 */
 
 
 
 
 
 
 
 406
 407__must_check int __media_pipeline_start(struct media_entity *entity,
 408					struct media_pipeline *pipe)
 409{
 410	struct media_device *mdev = entity->graph_obj.mdev;
 411	struct media_graph *graph = &pipe->graph;
 412	struct media_entity *entity_err = entity;
 413	struct media_link *link;
 414	int ret;
 415
 416	if (!pipe->streaming_count++) {
 417		ret = media_graph_walk_init(&pipe->graph, mdev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 418		if (ret)
 419			goto error_graph_walk_start;
 420	}
 421
 422	media_graph_walk_start(&pipe->graph, entity);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 423
 424	while ((entity = media_graph_walk_next(graph))) {
 425		DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
 426		DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
 427
 428		entity->stream_count++;
 
 
 
 
 
 429
 430		if (entity->pipe && entity->pipe != pipe) {
 431			pr_err("Pipe active for %s. Can't start for %s\n",
 432				entity->name,
 433				entity_err->name);
 434			ret = -EBUSY;
 435			goto error;
 436		}
 
 
 
 
 
 
 
 
 
 
 437
 438		entity->pipe = pipe;
 
 
 
 439
 440		/* Already streaming --- no need to check. */
 441		if (entity->stream_count > 1)
 442			continue;
 
 
 443
 444		if (!entity->ops || !entity->ops->link_validate)
 445			continue;
 446
 447		bitmap_zero(active, entity->num_pads);
 448		bitmap_fill(has_no_links, entity->num_pads);
 
 
 
 
 
 
 
 
 449
 450		list_for_each_entry(link, &entity->links, list) {
 451			struct media_pad *pad = link->sink->entity == entity
 452						? link->sink : link->source;
 
 
 
 
 
 
 453
 454			/* Mark that a pad is connected by a link. */
 455			bitmap_clear(has_no_links, pad->index, 1);
 
 456
 457			/*
 458			 * Pads that either do not need to connect or
 459			 * are connected through an enabled link are
 460			 * fine.
 461			 */
 462			if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
 463			    link->flags & MEDIA_LNK_FL_ENABLED)
 464				bitmap_set(active, pad->index, 1);
 
 
 465
 466			/*
 467			 * Link validation will only take place for
 468			 * sink ends of the link that are enabled.
 469			 */
 470			if (link->sink != pad ||
 471			    !(link->flags & MEDIA_LNK_FL_ENABLED))
 472				continue;
 473
 474			ret = entity->ops->link_validate(link);
 475			if (ret < 0 && ret != -ENOIOCTLCMD) {
 476				dev_dbg(entity->graph_obj.mdev->dev,
 477					"link validation failed for '%s':%u -> '%s':%u, error %d\n",
 478					link->source->entity->name,
 479					link->source->index,
 480					entity->name, link->sink->index, ret);
 
 481				goto error;
 482			}
 
 
 
 
 
 
 
 483		}
 484
 485		/* Either no links or validated links are fine. */
 486		bitmap_or(active, active, has_no_links, entity->num_pads);
 487
 488		if (!bitmap_full(active, entity->num_pads)) {
 
 
 
 
 
 489			ret = -ENOLINK;
 490			dev_dbg(entity->graph_obj.mdev->dev,
 491				"'%s':%u must be connected by an enabled link\n",
 492				entity->name,
 493				(unsigned)find_first_zero_bit(
 494					active, entity->num_pads));
 495			goto error;
 496		}
 
 
 
 497	}
 498
 
 
 499	return 0;
 500
 501error:
 502	/*
 503	 * Link validation on graph failed. We revert what we did and
 504	 * return the error.
 505	 */
 506	media_graph_walk_start(graph, entity_err);
 507
 508	while ((entity_err = media_graph_walk_next(graph))) {
 509		/* Sanity check for negative stream_count */
 510		if (!WARN_ON_ONCE(entity_err->stream_count <= 0)) {
 511			entity_err->stream_count--;
 512			if (entity_err->stream_count == 0)
 513				entity_err->pipe = NULL;
 514		}
 515
 516		/*
 517		 * We haven't increased stream_count further than this
 518		 * so we quit here.
 519		 */
 520		if (entity_err == entity)
 521			break;
 522	}
 523
 524error_graph_walk_start:
 525	if (!--pipe->streaming_count)
 526		media_graph_walk_cleanup(graph);
 527
 528	return ret;
 529}
 530EXPORT_SYMBOL_GPL(__media_pipeline_start);
 531
 532__must_check int media_pipeline_start(struct media_entity *entity,
 533				      struct media_pipeline *pipe)
 534{
 535	struct media_device *mdev = entity->graph_obj.mdev;
 536	int ret;
 537
 538	mutex_lock(&mdev->graph_mutex);
 539	ret = __media_pipeline_start(entity, pipe);
 540	mutex_unlock(&mdev->graph_mutex);
 541	return ret;
 542}
 543EXPORT_SYMBOL_GPL(media_pipeline_start);
 544
 545void __media_pipeline_stop(struct media_entity *entity)
 546{
 547	struct media_graph *graph = &entity->pipe->graph;
 548	struct media_pipeline *pipe = entity->pipe;
 549
 550	/*
 551	 * If the following check fails, the driver has performed an
 552	 * unbalanced call to media_pipeline_stop()
 553	 */
 554	if (WARN_ON(!pipe))
 555		return;
 556
 557	media_graph_walk_start(graph, entity);
 
 558
 559	while ((entity = media_graph_walk_next(graph))) {
 560		/* Sanity check for negative stream_count */
 561		if (!WARN_ON_ONCE(entity->stream_count <= 0)) {
 562			entity->stream_count--;
 563			if (entity->stream_count == 0)
 564				entity->pipe = NULL;
 565		}
 566	}
 567
 568	if (!--pipe->streaming_count)
 569		media_graph_walk_cleanup(graph);
 570
 
 
 571}
 572EXPORT_SYMBOL_GPL(__media_pipeline_stop);
 573
 574void media_pipeline_stop(struct media_entity *entity)
 575{
 576	struct media_device *mdev = entity->graph_obj.mdev;
 577
 578	mutex_lock(&mdev->graph_mutex);
 579	__media_pipeline_stop(entity);
 580	mutex_unlock(&mdev->graph_mutex);
 581}
 582EXPORT_SYMBOL_GPL(media_pipeline_stop);
 583
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 584/* -----------------------------------------------------------------------------
 585 * Links management
 586 */
 587
 588static struct media_link *media_add_link(struct list_head *head)
 589{
 590	struct media_link *link;
 591
 592	link = kzalloc(sizeof(*link), GFP_KERNEL);
 593	if (link == NULL)
 594		return NULL;
 595
 596	list_add_tail(&link->list, head);
 597
 598	return link;
 599}
 600
 601static void __media_entity_remove_link(struct media_entity *entity,
 602				       struct media_link *link)
 603{
 604	struct media_link *rlink, *tmp;
 605	struct media_entity *remote;
 606
 607	if (link->source->entity == entity)
 608		remote = link->sink->entity;
 609	else
 610		remote = link->source->entity;
 
 
 
 
 
 611
 612	list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
 613		if (rlink != link->reverse)
 614			continue;
 615
 616		if (link->source->entity == entity)
 617			remote->num_backlinks--;
 618
 619		/* Remove the remote link */
 620		list_del(&rlink->list);
 621		media_gobj_destroy(&rlink->graph_obj);
 622		kfree(rlink);
 623
 624		if (--remote->num_links == 0)
 625			break;
 
 626	}
 
 627	list_del(&link->list);
 628	media_gobj_destroy(&link->graph_obj);
 629	kfree(link);
 630}
 631
 632int media_get_pad_index(struct media_entity *entity, bool is_sink,
 633			enum media_pad_signal_type sig_type)
 634{
 635	int i;
 636	bool pad_is_sink;
 637
 638	if (!entity)
 639		return -EINVAL;
 640
 641	for (i = 0; i < entity->num_pads; i++) {
 642		if (entity->pads[i].flags == MEDIA_PAD_FL_SINK)
 643			pad_is_sink = true;
 644		else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE)
 645			pad_is_sink = false;
 646		else
 647			continue;	/* This is an error! */
 648
 649		if (pad_is_sink != is_sink)
 650			continue;
 651		if (entity->pads[i].sig_type == sig_type)
 652			return i;
 653	}
 654	return -EINVAL;
 655}
 656EXPORT_SYMBOL_GPL(media_get_pad_index);
 657
 658int
 659media_create_pad_link(struct media_entity *source, u16 source_pad,
 660			 struct media_entity *sink, u16 sink_pad, u32 flags)
 661{
 662	struct media_link *link;
 663	struct media_link *backlink;
 664
 665	BUG_ON(source == NULL || sink == NULL);
 666	BUG_ON(source_pad >= source->num_pads);
 667	BUG_ON(sink_pad >= sink->num_pads);
 
 
 
 
 
 
 
 
 
 
 668
 669	link = media_add_link(&source->links);
 670	if (link == NULL)
 671		return -ENOMEM;
 672
 673	link->source = &source->pads[source_pad];
 674	link->sink = &sink->pads[sink_pad];
 675	link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
 676
 677	/* Initialize graph object embedded at the new link */
 678	media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
 679			&link->graph_obj);
 680
 681	/* Create the backlink. Backlinks are used to help graph traversal and
 682	 * are not reported to userspace.
 683	 */
 684	backlink = media_add_link(&sink->links);
 685	if (backlink == NULL) {
 686		__media_entity_remove_link(source, link);
 687		return -ENOMEM;
 688	}
 689
 690	backlink->source = &source->pads[source_pad];
 691	backlink->sink = &sink->pads[sink_pad];
 692	backlink->flags = flags;
 693	backlink->is_backlink = true;
 694
 695	/* Initialize graph object embedded at the new link */
 696	media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK,
 697			&backlink->graph_obj);
 698
 699	link->reverse = backlink;
 700	backlink->reverse = link;
 701
 702	sink->num_backlinks++;
 703	sink->num_links++;
 704	source->num_links++;
 705
 
 
 
 706	return 0;
 707}
 708EXPORT_SYMBOL_GPL(media_create_pad_link);
 709
 710int media_create_pad_links(const struct media_device *mdev,
 711			   const u32 source_function,
 712			   struct media_entity *source,
 713			   const u16 source_pad,
 714			   const u32 sink_function,
 715			   struct media_entity *sink,
 716			   const u16 sink_pad,
 717			   u32 flags,
 718			   const bool allow_both_undefined)
 719{
 720	struct media_entity *entity;
 721	unsigned function;
 722	int ret;
 723
 724	/* Trivial case: 1:1 relation */
 725	if (source && sink)
 726		return media_create_pad_link(source, source_pad,
 727					     sink, sink_pad, flags);
 728
 729	/* Worse case scenario: n:n relation */
 730	if (!source && !sink) {
 731		if (!allow_both_undefined)
 732			return 0;
 733		media_device_for_each_entity(source, mdev) {
 734			if (source->function != source_function)
 735				continue;
 736			media_device_for_each_entity(sink, mdev) {
 737				if (sink->function != sink_function)
 738					continue;
 739				ret = media_create_pad_link(source, source_pad,
 740							    sink, sink_pad,
 741							    flags);
 742				if (ret)
 743					return ret;
 744				flags &= ~(MEDIA_LNK_FL_ENABLED |
 745					   MEDIA_LNK_FL_IMMUTABLE);
 746			}
 747		}
 748		return 0;
 749	}
 750
 751	/* Handle 1:n and n:1 cases */
 752	if (source)
 753		function = sink_function;
 754	else
 755		function = source_function;
 756
 757	media_device_for_each_entity(entity, mdev) {
 758		if (entity->function != function)
 759			continue;
 760
 761		if (source)
 762			ret = media_create_pad_link(source, source_pad,
 763						    entity, sink_pad, flags);
 764		else
 765			ret = media_create_pad_link(entity, source_pad,
 766						    sink, sink_pad, flags);
 767		if (ret)
 768			return ret;
 769		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
 770	}
 771	return 0;
 772}
 773EXPORT_SYMBOL_GPL(media_create_pad_links);
 774
 775void __media_entity_remove_links(struct media_entity *entity)
 776{
 777	struct media_link *link, *tmp;
 778
 779	list_for_each_entry_safe(link, tmp, &entity->links, list)
 780		__media_entity_remove_link(entity, link);
 781
 782	entity->num_links = 0;
 783	entity->num_backlinks = 0;
 784}
 785EXPORT_SYMBOL_GPL(__media_entity_remove_links);
 786
 787void media_entity_remove_links(struct media_entity *entity)
 788{
 789	struct media_device *mdev = entity->graph_obj.mdev;
 790
 791	/* Do nothing if the entity is not registered. */
 792	if (mdev == NULL)
 793		return;
 794
 795	mutex_lock(&mdev->graph_mutex);
 796	__media_entity_remove_links(entity);
 797	mutex_unlock(&mdev->graph_mutex);
 798}
 799EXPORT_SYMBOL_GPL(media_entity_remove_links);
 800
 801static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
 802{
 803	int ret;
 804
 805	/* Notify both entities. */
 806	ret = media_entity_call(link->source->entity, link_setup,
 807				link->source, link->sink, flags);
 808	if (ret < 0 && ret != -ENOIOCTLCMD)
 809		return ret;
 810
 811	ret = media_entity_call(link->sink->entity, link_setup,
 812				link->sink, link->source, flags);
 813	if (ret < 0 && ret != -ENOIOCTLCMD) {
 814		media_entity_call(link->source->entity, link_setup,
 815				  link->source, link->sink, link->flags);
 816		return ret;
 817	}
 818
 819	link->flags = flags;
 820	link->reverse->flags = link->flags;
 821
 822	return 0;
 823}
 824
 825int __media_entity_setup_link(struct media_link *link, u32 flags)
 826{
 827	const u32 mask = MEDIA_LNK_FL_ENABLED;
 828	struct media_device *mdev;
 829	struct media_entity *source, *sink;
 830	int ret = -EBUSY;
 831
 832	if (link == NULL)
 833		return -EINVAL;
 834
 835	/* The non-modifiable link flags must not be modified. */
 836	if ((link->flags & ~mask) != (flags & ~mask))
 837		return -EINVAL;
 838
 839	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
 840		return link->flags == flags ? 0 : -EINVAL;
 841
 842	if (link->flags == flags)
 843		return 0;
 844
 845	source = link->source->entity;
 846	sink = link->sink->entity;
 847
 848	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
 849	    (source->stream_count || sink->stream_count))
 850		return -EBUSY;
 851
 852	mdev = source->graph_obj.mdev;
 853
 854	if (mdev->ops && mdev->ops->link_notify) {
 855		ret = mdev->ops->link_notify(link, flags,
 856					     MEDIA_DEV_NOTIFY_PRE_LINK_CH);
 857		if (ret < 0)
 858			return ret;
 859	}
 860
 861	ret = __media_entity_setup_link_notify(link, flags);
 862
 863	if (mdev->ops && mdev->ops->link_notify)
 864		mdev->ops->link_notify(link, flags,
 865				       MEDIA_DEV_NOTIFY_POST_LINK_CH);
 866
 867	return ret;
 868}
 869EXPORT_SYMBOL_GPL(__media_entity_setup_link);
 870
 871int media_entity_setup_link(struct media_link *link, u32 flags)
 872{
 873	int ret;
 874
 875	mutex_lock(&link->graph_obj.mdev->graph_mutex);
 876	ret = __media_entity_setup_link(link, flags);
 877	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
 878
 879	return ret;
 880}
 881EXPORT_SYMBOL_GPL(media_entity_setup_link);
 882
 883struct media_link *
 884media_entity_find_link(struct media_pad *source, struct media_pad *sink)
 885{
 886	struct media_link *link;
 887
 888	list_for_each_entry(link, &source->entity->links, list) {
 889		if (link->source->entity == source->entity &&
 890		    link->source->index == source->index &&
 891		    link->sink->entity == sink->entity &&
 892		    link->sink->index == sink->index)
 893			return link;
 894	}
 895
 896	return NULL;
 897}
 898EXPORT_SYMBOL_GPL(media_entity_find_link);
 899
 900struct media_pad *media_entity_remote_pad(const struct media_pad *pad)
 901{
 902	struct media_link *link;
 903
 904	list_for_each_entry(link, &pad->entity->links, list) {
 905		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
 906			continue;
 907
 908		if (link->source == pad)
 909			return link->sink;
 910
 911		if (link->sink == pad)
 912			return link->source;
 913	}
 914
 915	return NULL;
 916
 917}
 918EXPORT_SYMBOL_GPL(media_entity_remote_pad);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 919
 920static void media_interface_init(struct media_device *mdev,
 921				 struct media_interface *intf,
 922				 u32 gobj_type,
 923				 u32 intf_type, u32 flags)
 924{
 925	intf->type = intf_type;
 926	intf->flags = flags;
 927	INIT_LIST_HEAD(&intf->links);
 928
 929	media_gobj_create(mdev, gobj_type, &intf->graph_obj);
 930}
 931
 932/* Functions related to the media interface via device nodes */
 933
 934struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 935						u32 type, u32 flags,
 936						u32 major, u32 minor)
 937{
 938	struct media_intf_devnode *devnode;
 939
 940	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
 941	if (!devnode)
 942		return NULL;
 943
 944	devnode->major = major;
 945	devnode->minor = minor;
 946
 947	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
 948			     type, flags);
 949
 950	return devnode;
 951}
 952EXPORT_SYMBOL_GPL(media_devnode_create);
 953
 954void media_devnode_remove(struct media_intf_devnode *devnode)
 955{
 956	media_remove_intf_links(&devnode->intf);
 957	media_gobj_destroy(&devnode->intf.graph_obj);
 958	kfree(devnode);
 959}
 960EXPORT_SYMBOL_GPL(media_devnode_remove);
 961
 962struct media_link *media_create_intf_link(struct media_entity *entity,
 963					    struct media_interface *intf,
 964					    u32 flags)
 965{
 966	struct media_link *link;
 967
 968	link = media_add_link(&intf->links);
 969	if (link == NULL)
 970		return NULL;
 971
 972	link->intf = intf;
 973	link->entity = entity;
 974	link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK;
 975
 976	/* Initialize graph object embedded at the new link */
 977	media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
 978			&link->graph_obj);
 979
 980	return link;
 981}
 982EXPORT_SYMBOL_GPL(media_create_intf_link);
 983
 984void __media_remove_intf_link(struct media_link *link)
 985{
 986	list_del(&link->list);
 987	media_gobj_destroy(&link->graph_obj);
 988	kfree(link);
 989}
 990EXPORT_SYMBOL_GPL(__media_remove_intf_link);
 991
 992void media_remove_intf_link(struct media_link *link)
 993{
 994	struct media_device *mdev = link->graph_obj.mdev;
 995
 996	/* Do nothing if the intf is not registered. */
 997	if (mdev == NULL)
 998		return;
 999
1000	mutex_lock(&mdev->graph_mutex);
1001	__media_remove_intf_link(link);
1002	mutex_unlock(&mdev->graph_mutex);
1003}
1004EXPORT_SYMBOL_GPL(media_remove_intf_link);
1005
1006void __media_remove_intf_links(struct media_interface *intf)
1007{
1008	struct media_link *link, *tmp;
1009
1010	list_for_each_entry_safe(link, tmp, &intf->links, list)
1011		__media_remove_intf_link(link);
1012
1013}
1014EXPORT_SYMBOL_GPL(__media_remove_intf_links);
1015
1016void media_remove_intf_links(struct media_interface *intf)
1017{
1018	struct media_device *mdev = intf->graph_obj.mdev;
1019
1020	/* Do nothing if the intf is not registered. */
1021	if (mdev == NULL)
1022		return;
1023
1024	mutex_lock(&mdev->graph_mutex);
1025	__media_remove_intf_links(intf);
1026	mutex_unlock(&mdev->graph_mutex);
1027}
1028EXPORT_SYMBOL_GPL(media_remove_intf_links);