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