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