]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/media/media-entity.c
[media] media: Add link_validate() op to check links to the sink pad
[karo-tx-linux.git] / drivers / media / media-entity.c
index 056138f63c7dc26d8d8b9757f2beb8b234b6209c..e1cd13283407ce65b0c64345c9732be8e75aaf96 100644 (file)
@@ -214,23 +214,76 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
  * pipeline pointer must be identical for all nested calls to
  * media_entity_pipeline_start().
  */
-void media_entity_pipeline_start(struct media_entity *entity,
-                                struct media_pipeline *pipe)
+__must_check int media_entity_pipeline_start(struct media_entity *entity,
+                                            struct media_pipeline *pipe)
 {
        struct media_device *mdev = entity->parent;
        struct media_entity_graph graph;
+       struct media_entity *entity_err = entity;
+       int ret;
 
        mutex_lock(&mdev->graph_mutex);
 
        media_entity_graph_walk_start(&graph, entity);
 
        while ((entity = media_entity_graph_walk_next(&graph))) {
+               unsigned int i;
+
                entity->stream_count++;
                WARN_ON(entity->pipe && entity->pipe != pipe);
                entity->pipe = pipe;
+
+               /* Already streaming --- no need to check. */
+               if (entity->stream_count > 1)
+                       continue;
+
+               if (!entity->ops || !entity->ops->link_validate)
+                       continue;
+
+               for (i = 0; i < entity->num_links; i++) {
+                       struct media_link *link = &entity->links[i];
+
+                       /* Is this pad part of an enabled link? */
+                       if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+                               continue;
+
+                       /* Are we the sink or not? */
+                       if (link->sink->entity != entity)
+                               continue;
+
+                       ret = entity->ops->link_validate(link);
+                       if (ret < 0 && ret != -ENOIOCTLCMD)
+                               goto error;
+               }
        }
 
        mutex_unlock(&mdev->graph_mutex);
+
+       return 0;
+
+error:
+       /*
+        * Link validation on graph failed. We revert what we did and
+        * return the error.
+        */
+       media_entity_graph_walk_start(&graph, entity_err);
+
+       while ((entity_err = media_entity_graph_walk_next(&graph))) {
+               entity_err->stream_count--;
+               if (entity_err->stream_count == 0)
+                       entity_err->pipe = NULL;
+
+               /*
+                * We haven't increased stream_count further than this
+                * so we quit here.
+                */
+               if (entity_err == entity)
+                       break;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_start);