@@ -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
*/
@@ -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) ? \
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@osg.samsung.com> --- drivers/media/media-entity.c | 80 +++++++++++++++++++++++++++++++++++++------- include/media/media-entity.h | 3 ++ 2 files changed, 70 insertions(+), 13 deletions(-)