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