Add irq safe Media Controller start/stop pipeline API media_entity_pipeline_start_irq() media_entity_pipeline_stop_irq() to be used from inside interrupt context. Signed-off-by: Shuah Khan <shuahkh@xxxxxxxxxxxxxxx> --- drivers/media/media-entity.c | 80 +++++++++++++++++++++++++++++++++++++------- include/media/media-entity.h | 3 ++ 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 31132573..293cf25 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -210,6 +210,8 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); /** * media_entity_pipeline_start - Mark a pipeline as streaming + * media_entity_pipeline_start_irq - Mark a pipeline as streaming + * (safe to be used from inside interrupt context) * @entity: Starting entity * @pipe: Media pipeline to be assigned to all entities in the pipeline. * @@ -222,16 +224,18 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); * pipeline pointer must be identical for all nested calls to * media_entity_pipeline_start(). */ -__must_check int media_entity_pipeline_start(struct media_entity *entity, - struct media_pipeline *pipe) +/* + * __media_entity_pipeline_start() + * Should be called with graph_lock held +*/ +static __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; - spin_lock(&mdev->graph_lock); - media_entity_graph_walk_start(&graph, entity); while ((entity = media_entity_graph_walk_next(&graph))) { @@ -303,8 +307,6 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, } } - spin_unlock(&mdev->graph_lock); - return 0; error: @@ -327,14 +329,46 @@ error: break; } - spin_unlock(&mdev->graph_lock); + return ret; +} +/* + * media_entity_pipeline_start - Mark a pipeline as streaming + * (unsafe to be used from inside interrupt context) +*/ +__must_check int media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe) +{ + int ret; + + spin_lock(&entity->parent->graph_lock); + ret = __media_entity_pipeline_start(entity, pipe); + spin_unlock(&entity->parent->graph_lock); return ret; } EXPORT_SYMBOL_GPL(media_entity_pipeline_start); +/* + * media_entity_pipeline_start_irq - Mark a pipeline as streaming + * (safe to be used from inside interrupt context) +*/ +__must_check int media_entity_pipeline_start_irq(struct media_entity *entity, + struct media_pipeline *pipe) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&entity->parent->graph_lock, flags); + ret = __media_entity_pipeline_start(entity, pipe); + spin_unlock_irqrestore(&entity->parent->graph_lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(media_entity_pipeline_start_irq); + /** * media_entity_pipeline_stop - Mark a pipeline as not streaming + * media_entity_pipeline_stop_irq - Mark a pipeline as not streaming + * (safe to be used from inside interrupt context) * @entity: Starting entity * * Mark all entities connected to a given entity through enabled links, either @@ -345,13 +379,10 @@ EXPORT_SYMBOL_GPL(media_entity_pipeline_start); * number of calls to this function are required to mark the pipeline as not * streaming. */ -void media_entity_pipeline_stop(struct media_entity *entity) +static void __media_entity_pipeline_stop(struct media_entity *entity) { - struct media_device *mdev = entity->parent; struct media_entity_graph graph; - spin_lock(&mdev->graph_lock); - media_entity_graph_walk_start(&graph, entity); while ((entity = media_entity_graph_walk_next(&graph))) { @@ -359,11 +390,34 @@ void media_entity_pipeline_stop(struct media_entity *entity) if (entity->stream_count == 0) entity->pipe = NULL; } +} - spin_unlock(&mdev->graph_lock); +/* + * media_entity_pipeline_stop - Mark a pipeline as not streaming + * (unsafe to be used from inside interrupt context) +*/ +void media_entity_pipeline_stop(struct media_entity *entity) +{ + spin_lock(&entity->parent->graph_lock); + __media_entity_pipeline_stop(entity); + spin_unlock(&entity->parent->graph_lock); } EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); +/* + * media_entity_pipeline_stop_irq - Mark a pipeline as not streaming + * (safe to be used from inside interrupt context) +*/ +void media_entity_pipeline_stop_irq(struct media_entity *entity) +{ + unsigned long flags; + + spin_lock_irqsave(&entity->parent->graph_lock, flags); + __media_entity_pipeline_stop(entity); + spin_unlock_irqrestore(&entity->parent->graph_lock, flags); +} +EXPORT_SYMBOL_GPL(media_entity_pipeline_stop_irq); + /* ----------------------------------------------------------------------------- * Module use count */ diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 0c003d8..a4be306 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -151,6 +151,9 @@ media_entity_graph_walk_next(struct media_entity_graph *graph); __must_check int media_entity_pipeline_start(struct media_entity *entity, struct media_pipeline *pipe); void media_entity_pipeline_stop(struct media_entity *entity); +__must_check int media_entity_pipeline_start_irq(struct media_entity *entity, + struct media_pipeline *pipe); +void media_entity_pipeline_stop_irq(struct media_entity *entity); #define media_entity_call(entity, operation, args...) \ (((entity)->ops && (entity)->ops->operation) ? \ -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html