Commit ae219872 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

media: mc: entity: Rewrite media_pipeline_start()

[Note: the code is mostly from Laurent but the patch description is from Tomi]

The media_pipeline_start() and media_pipeline_stop() functions use the
media graph walk API to traverse the graph and validate the pipeline.
The graph walk traverses the media graph following links between the
entities.

Also, while the pipeline can't change between the start and stop calls,
the graph is walked again from scratch at stop time, or any time a
driver needs to inspect the pipeline.

With the upcoming multiplexed streams support we will need a bit more
intelligent pipeline construction, as e.g. two independent streams may
be passing through a single entity via separate pads in which case
those pads should not be part of the same pipeline.

This patch essentially rewrites the media_pipeline_start/stop so that
a pipeline is defined as a set of pads instead of entities and the media
graph traversal considers the pad interdependencies when choosing which
links to follow.

Currently all the entity's pads are considered as interdependent. This
means that the behavior with all the current drivers stays the same, but
in the future we can define a more fine-grained pipeline construction.

Additionally the media pipeline's pads are cached at
media_pipeline_start() time, and re-used at media_pipeline_stop() which
avoid the need to re-walk the whole graph as the previous implementation
did.

Also, caching pads in the pipeline can serve in the future as the
foundation to provide a better API than the media graph walk to drivers
to iterate over pads and entities in the pipeline.

Note that the old media_pipeline_start/stop used the media graph walk
API. The new version does not use the media graph walk API, but instead
a new implementation.

There are two reasons for not changing the graph walk: it proved to be
rather difficult to change the graph walk to have the features
implemented in this patch, and second, this keeps the backward
compatibility of the graph walk as there are users of the graph walk API

The long term plan is that all the existing code would be converted to
use the new cached pipeline, thus allowing us to remove the graph walk.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 6eaff06a
...@@ -230,14 +230,13 @@ When starting streaming, drivers must notify all entities in the pipeline to ...@@ -230,14 +230,13 @@ When starting streaming, drivers must notify all entities in the pipeline to
prevent link states from being modified during streaming by calling prevent link states from being modified during streaming by calling
:c:func:`media_pipeline_start()`. :c:func:`media_pipeline_start()`.
The function will mark all entities connected to the given entity through The function will mark all the pads which are part of the pipeline as streaming.
enabled links, either directly or indirectly, as streaming.
The struct media_pipeline instance pointed to by The struct media_pipeline instance pointed to by
the pipe argument will be stored in every entity in the pipeline. the pipe argument will be stored in every pad in the pipeline.
Drivers should embed the struct media_pipeline Drivers should embed the struct media_pipeline
in higher-level pipeline structures and can then access the in higher-level pipeline structures and can then access the
pipeline through the struct media_entity pipeline through the struct media_pad
pipe field. pipe field.
Calls to :c:func:`media_pipeline_start()` can be nested. Calls to :c:func:`media_pipeline_start()` can be nested.
......
This diff is collapsed.
...@@ -101,13 +101,33 @@ struct media_graph { ...@@ -101,13 +101,33 @@ struct media_graph {
* struct media_pipeline - Media pipeline related information * struct media_pipeline - Media pipeline related information
* *
* @allocated: Media pipeline allocated and freed by the framework * @allocated: Media pipeline allocated and freed by the framework
* @mdev: The media device the pipeline is part of
* @pads: List of media_pipeline_pad
* @start_count: Media pipeline start - stop count * @start_count: Media pipeline start - stop count
* @graph: Media graph walk during pipeline start / stop
*/ */
struct media_pipeline { struct media_pipeline {
bool allocated; bool allocated;
struct media_device *mdev;
struct list_head pads;
int start_count; int start_count;
struct media_graph graph; };
/**
* struct media_pipeline_pad - A pad part of a media pipeline
*
* @list: Entry in the media_pad pads list
* @pipe: The media_pipeline that the pad is part of
* @pad: The media pad
*
* This structure associate a pad with a media pipeline. Instances of
* media_pipeline_pad are created by media_pipeline_start() when it builds the
* pipeline, and stored in the &media_pad.pads list. media_pipeline_stop()
* removes the entries from the list and deletes them.
*/
struct media_pipeline_pad {
struct list_head list;
struct media_pipeline *pipe;
struct media_pad *pad;
}; };
/** /**
...@@ -189,6 +209,8 @@ enum media_pad_signal_type { ...@@ -189,6 +209,8 @@ enum media_pad_signal_type {
* @flags: Pad flags, as defined in * @flags: Pad flags, as defined in
* :ref:`include/uapi/linux/media.h <media_header>` * :ref:`include/uapi/linux/media.h <media_header>`
* (seek for ``MEDIA_PAD_FL_*``) * (seek for ``MEDIA_PAD_FL_*``)
* @pipe: Pipeline this pad belongs to. Use media_entity_pipeline() to
* access this field.
*/ */
struct media_pad { struct media_pad {
struct media_gobj graph_obj; /* must be first field in struct */ struct media_gobj graph_obj; /* must be first field in struct */
...@@ -196,6 +218,12 @@ struct media_pad { ...@@ -196,6 +218,12 @@ struct media_pad {
u16 index; u16 index;
enum media_pad_signal_type sig_type; enum media_pad_signal_type sig_type;
unsigned long flags; unsigned long flags;
/*
* The fields below are private, and should only be accessed via
* appropriate functions.
*/
struct media_pipeline *pipe;
}; };
/** /**
...@@ -272,7 +300,6 @@ enum media_entity_type { ...@@ -272,7 +300,6 @@ enum media_entity_type {
* @links: List of data links. * @links: List of data links.
* @ops: Entity operations. * @ops: Entity operations.
* @use_count: Use count for the entity. * @use_count: Use count for the entity.
* @pipe: Pipeline this entity belongs to.
* @info: Union with devnode information. Kept just for backward * @info: Union with devnode information. Kept just for backward
* compatibility. * compatibility.
* @info.dev: Contains device major and minor info. * @info.dev: Contains device major and minor info.
...@@ -308,8 +335,6 @@ struct media_entity { ...@@ -308,8 +335,6 @@ struct media_entity {
int use_count; int use_count;
struct media_pipeline *pipe;
union { union {
struct { struct {
u32 major; u32 major;
...@@ -938,6 +963,18 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity) ...@@ -938,6 +963,18 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity)
return media_entity_remote_pad_unique(entity, MEDIA_PAD_FL_SOURCE); return media_entity_remote_pad_unique(entity, MEDIA_PAD_FL_SOURCE);
} }
/**
* media_pad_is_streaming - Test if a pad is part of a streaming pipeline
* @pad: The pad
*
* Return: True if the pad is part of a pipeline started with the
* media_pipeline_start() function, false otherwise.
*/
static inline bool media_pad_is_streaming(const struct media_pad *pad)
{
return pad->pipe;
}
/** /**
* media_entity_is_streaming - Test if an entity is part of a streaming pipeline * media_entity_is_streaming - Test if an entity is part of a streaming pipeline
* @entity: The entity * @entity: The entity
...@@ -947,13 +984,22 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity) ...@@ -947,13 +984,22 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity)
*/ */
static inline bool media_entity_is_streaming(const struct media_entity *entity) static inline bool media_entity_is_streaming(const struct media_entity *entity)
{ {
return entity->pipe; struct media_pad *pad;
media_entity_for_each_pad(entity, pad) {
if (media_pad_is_streaming(pad))
return true;
}
return false;
} }
/** /**
* media_entity_pipeline - Get the media pipeline an entity is part of * media_entity_pipeline - Get the media pipeline an entity is part of
* @entity: The entity * @entity: The entity
* *
* DEPRECATED: use media_pad_pipeline() instead.
*
* This function returns the media pipeline that an entity has been associated * This function returns the media pipeline that an entity has been associated
* with when constructing the pipeline with media_pipeline_start(). The pointer * with when constructing the pipeline with media_pipeline_start(). The pointer
* remains valid until media_pipeline_stop() is called. * remains valid until media_pipeline_stop() is called.
...@@ -968,6 +1014,19 @@ static inline bool media_entity_is_streaming(const struct media_entity *entity) ...@@ -968,6 +1014,19 @@ static inline bool media_entity_is_streaming(const struct media_entity *entity)
*/ */
struct media_pipeline *media_entity_pipeline(struct media_entity *entity); struct media_pipeline *media_entity_pipeline(struct media_entity *entity);
/**
* media_pad_pipeline - Get the media pipeline a pad is part of
* @pad: The pad
*
* This function returns the media pipeline that a pad has been associated
* with when constructing the pipeline with media_pipeline_start(). The pointer
* remains valid until media_pipeline_stop() is called.
*
* Return: The media_pipeline the pad is part of, or NULL if the pad is
* not part of any pipeline.
*/
struct media_pipeline *media_pad_pipeline(struct media_pad *pad);
/** /**
* media_entity_get_fwnode_pad - Get pad number from fwnode * media_entity_get_fwnode_pad - Get pad number from fwnode
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment