[PATCH 4/7] ASoC: soc-component: add mark for snd_soc_pcm_component_pm_runtime_get/put()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

soc_pcm_open() does rollback when failed (A),
but, it is almost same as soc_pcm_close().

	static int soc_pcm_open(xxx)
	{
		...
		if (ret < 0)
			goto xxx_err;
		...
		return 0;

 ^	config_err:
 |		...
 |	rtd_startup_err:
(A)		...
 |	component_err:
 |		...
 v		return ret;
	}

The difference is
soc_pcm_close() is for all dai/component/substream,
rollback        is for succeeded part only.

This kind of duplicated code can be a hotbed of bugs,
thus, we want to share soc_pcm_close() and rollback.

Now, soc_pcm_open/close() are handling
	1) snd_soc_dai_startup/shutdown()
	2) snd_soc_link_startup/shutdown()
	3) snd_soc_component_module_get/put()
	4) snd_soc_component_open/close()
=>	5) pm_runtime_put/get()

This patch is for 5) pm_runtime_put/get(),
and adds new substream mark.
It will mark substream when get() was suceeded.
If rollback happen *after* that, it will check rollback flag
and marked substream.

It cares *previous* get() only now,
but we might want to check *whole* marked substream in the future.
This patch is using macro so that it can be easily adjust to it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
---
 include/sound/soc-component.h |  5 +++++
 sound/soc/soc-component.c     | 38 +++++++++++++++++++++++++++++++++++
 sound/soc/soc-compress.c      | 30 ++++++++-------------------
 sound/soc/soc-pcm.c           | 17 ++++++----------
 4 files changed, 57 insertions(+), 33 deletions(-)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 8aabadfbdebc..ae112f53143a 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -220,6 +220,7 @@ struct snd_soc_component {
 	/* function mark */
 	struct snd_pcm_substream *mark_module;
 	struct snd_pcm_substream *mark_open;
+	void *mark_pm;
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_root;
@@ -467,5 +468,9 @@ void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
 				   struct snd_soc_component *last);
 int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
 				  int cmd);
+int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
+					 void *stream);
+void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
+					  void *stream, int rollback);
 
 #endif /* __SOC_COMPONENT_H */
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 6544e74cf7f7..30e5599b24d4 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -9,6 +9,7 @@
 // Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
 //
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <sound/soc.h>
 
 #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret)
@@ -852,3 +853,40 @@ int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
 
 	return 0;
 }
+
+int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
+					 void *stream)
+{
+	struct snd_soc_component *component;
+	int i, ret;
+
+	for_each_rtd_components(rtd, i, component) {
+		ret = pm_runtime_get_sync(component->dev);
+		if (ret < 0 && ret != -EACCES) {
+			pm_runtime_put_noidle(component->dev);
+			return soc_component_ret(component, ret);
+		}
+		/* mark stream if succeeded */
+		soc_component_mark_push(component, stream, pm);
+	}
+
+	return 0;
+}
+
+void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
+					  void *stream, int rollback)
+{
+	struct snd_soc_component *component;
+	int i;
+
+	for_each_rtd_components(rtd, i, component) {
+		if (rollback && !soc_component_mark_match(component, stream, pm))
+			continue;
+
+		pm_runtime_mark_last_busy(component->dev);
+		pm_runtime_put_autosuspend(component->dev);
+
+		/* remove marked stream */
+		soc_component_mark_pop(component, stream, pm);
+	}
+}
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 415510909a82..3a6a60215e81 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -73,18 +73,13 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream,
 static int soc_compr_open(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_component *component = NULL, *save = NULL;
+	struct snd_soc_component *component = NULL;
 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
-	int ret, i;
+	int ret;
 
-	for_each_rtd_components(rtd, i, component) {
-		ret = pm_runtime_get_sync(component->dev);
-		if (ret < 0 && ret != -EACCES) {
-			pm_runtime_put_noidle(component->dev);
-			save = component;
-			goto pm_err;
-		}
-	}
+	ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
+	if (ret < 0)
+		goto pm_err;
 
 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 
@@ -113,12 +108,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
 out:
 	mutex_unlock(&rtd->card->pcm_mutex);
 pm_err:
-	for_each_rtd_components(rtd, i, component) {
-		if (component == save)
-			break;
-		pm_runtime_mark_last_busy(component->dev);
-		pm_runtime_put_autosuspend(component->dev);
-	}
+	snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 1);
 
 	return ret;
 }
@@ -205,10 +195,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 static int soc_compr_free(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
-	int stream, i;
+	int stream;
 
 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 
@@ -237,10 +226,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
 
 	mutex_unlock(&rtd->card->pcm_mutex);
 
-	for_each_rtd_components(rtd, i, component) {
-		pm_runtime_mark_last_busy(component->dev);
-		pm_runtime_put_autosuspend(component->dev);
-	}
+	snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 0);
 
 	return 0;
 }
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index c034b8a1e6f9..6243e1a0561c 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -678,10 +678,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 
 	mutex_unlock(&rtd->card->pcm_mutex);
 
-	for_each_rtd_components(rtd, i, component) {
-		pm_runtime_mark_last_busy(component->dev);
-		pm_runtime_put_autosuspend(component->dev);
-	}
+	snd_soc_pcm_component_pm_runtime_put(rtd, substream, 0);
 
 	for_each_rtd_components(rtd, i, component)
 		if (!snd_soc_component_active(component))
@@ -708,8 +705,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	for_each_rtd_components(rtd, i, component)
 		pinctrl_pm_select_default_state(component->dev);
 
-	for_each_rtd_components(rtd, i, component)
-		pm_runtime_get_sync(component->dev);
+	ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
+	if (ret < 0)
+		goto pm_err;
 
 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 
@@ -806,11 +804,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	soc_pcm_components_close(substream, 1);
 component_err:
 	mutex_unlock(&rtd->card->pcm_mutex);
-
-	for_each_rtd_components(rtd, i, component) {
-		pm_runtime_mark_last_busy(component->dev);
-		pm_runtime_put_autosuspend(component->dev);
-	}
+pm_err:
+	snd_soc_pcm_component_pm_runtime_put(rtd, substream, 1);
 
 	for_each_rtd_components(rtd, i, component)
 		if (!snd_soc_component_active(component))
-- 
2.25.1




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux