summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2019-08-13 06:45:32 -0400
committerMark Brown <broonie@kernel.org>2019-08-15 10:07:43 -0400
commit72b745e3ad65deac94ea4eb83262c52ba3ffdb5b (patch)
treea5850d63c1e97e8fc8d4a6e1f29b8d6e181b112a /sound/soc/soc-pcm.c
parent12f0bfadf69bb154052722e7e4e5cd1639044c76 (diff)
ASoC: core: Move pcm_mutex up to card level from snd_soc_pcm_runtime
The pcm_mutex is used to prevent concurrent execution of snd_pcm_ops callbacks. This works fine most of the cases but it can not handle setups when the same DAI is used by different rtd, for example: pcm3168a have two DAIs: one for Playback and one for Capture. If the codec is connected to a single CPU DAI we need to have two dai_link to support both playback and capture. In this case the snd_pcm_ops callbacks can be executed in parallel causing unexpected races in DAI drivers. By moving the pcm_mutex up to card level this can be solved while - hopefully - not breaking other setups. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Tested-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20190813104532.16669-1-peter.ujfalusi@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index da657c8179cc..e163dde5eab1 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -36,7 +36,7 @@
36 * Increments the active count for all the DAIs and components attached to a PCM 36 * Increments the active count for all the DAIs and components attached to a PCM
37 * runtime. Should typically be called when a stream is opened. 37 * runtime. Should typically be called when a stream is opened.
38 * 38 *
39 * Must be called with the rtd->pcm_mutex being held 39 * Must be called with the rtd->card->pcm_mutex being held
40 */ 40 */
41void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) 41void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
42{ 42{
@@ -44,7 +44,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
44 struct snd_soc_dai *codec_dai; 44 struct snd_soc_dai *codec_dai;
45 int i; 45 int i;
46 46
47 lockdep_assert_held(&rtd->pcm_mutex); 47 lockdep_assert_held(&rtd->card->pcm_mutex);
48 48
49 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 49 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
50 cpu_dai->playback_active++; 50 cpu_dai->playback_active++;
@@ -72,7 +72,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
72 * Decrements the active count for all the DAIs and components attached to a PCM 72 * Decrements the active count for all the DAIs and components attached to a PCM
73 * runtime. Should typically be called when a stream is closed. 73 * runtime. Should typically be called when a stream is closed.
74 * 74 *
75 * Must be called with the rtd->pcm_mutex being held 75 * Must be called with the rtd->card->pcm_mutex being held
76 */ 76 */
77void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) 77void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
78{ 78{
@@ -80,7 +80,7 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
80 struct snd_soc_dai *codec_dai; 80 struct snd_soc_dai *codec_dai;
81 int i; 81 int i;
82 82
83 lockdep_assert_held(&rtd->pcm_mutex); 83 lockdep_assert_held(&rtd->card->pcm_mutex);
84 84
85 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 85 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
86 cpu_dai->playback_active--; 86 cpu_dai->playback_active--;
@@ -506,7 +506,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
506 pm_runtime_get_sync(component->dev); 506 pm_runtime_get_sync(component->dev);
507 } 507 }
508 508
509 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 509 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
510 510
511 /* startup the audio subsystem */ 511 /* startup the audio subsystem */
512 ret = snd_soc_dai_startup(cpu_dai, substream); 512 ret = snd_soc_dai_startup(cpu_dai, substream);
@@ -604,7 +604,7 @@ dynamic:
604 604
605 snd_soc_runtime_activate(rtd, substream->stream); 605 snd_soc_runtime_activate(rtd, substream->stream);
606 606
607 mutex_unlock(&rtd->pcm_mutex); 607 mutex_unlock(&rtd->card->pcm_mutex);
608 return 0; 608 return 0;
609 609
610config_err: 610config_err:
@@ -623,7 +623,7 @@ component_err:
623 623
624 snd_soc_dai_shutdown(cpu_dai, substream); 624 snd_soc_dai_shutdown(cpu_dai, substream);
625out: 625out:
626 mutex_unlock(&rtd->pcm_mutex); 626 mutex_unlock(&rtd->card->pcm_mutex);
627 627
628 for_each_rtdcom(rtd, rtdcom) { 628 for_each_rtdcom(rtd, rtdcom) {
629 component = rtdcom->component; 629 component = rtdcom->component;
@@ -653,7 +653,7 @@ static void close_delayed_work(struct work_struct *work)
653 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); 653 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
654 struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; 654 struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
655 655
656 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 656 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
657 657
658 dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", 658 dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
659 codec_dai->driver->playback.stream_name, 659 codec_dai->driver->playback.stream_name,
@@ -667,7 +667,7 @@ static void close_delayed_work(struct work_struct *work)
667 SND_SOC_DAPM_STREAM_STOP); 667 SND_SOC_DAPM_STREAM_STOP);
668 } 668 }
669 669
670 mutex_unlock(&rtd->pcm_mutex); 670 mutex_unlock(&rtd->card->pcm_mutex);
671} 671}
672 672
673static void codec2codec_close_delayed_work(struct work_struct *work) 673static void codec2codec_close_delayed_work(struct work_struct *work)
@@ -694,7 +694,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
694 struct snd_soc_dai *codec_dai; 694 struct snd_soc_dai *codec_dai;
695 int i; 695 int i;
696 696
697 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 697 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
698 698
699 snd_soc_runtime_deactivate(rtd, substream->stream); 699 snd_soc_runtime_deactivate(rtd, substream->stream);
700 700
@@ -738,7 +738,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
738 SND_SOC_DAPM_STREAM_STOP); 738 SND_SOC_DAPM_STREAM_STOP);
739 } 739 }
740 740
741 mutex_unlock(&rtd->pcm_mutex); 741 mutex_unlock(&rtd->card->pcm_mutex);
742 742
743 for_each_rtdcom(rtd, rtdcom) { 743 for_each_rtdcom(rtd, rtdcom) {
744 component = rtdcom->component; 744 component = rtdcom->component;
@@ -771,7 +771,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
771 struct snd_soc_dai *codec_dai; 771 struct snd_soc_dai *codec_dai;
772 int i, ret = 0; 772 int i, ret = 0;
773 773
774 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 774 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
775 775
776 if (rtd->dai_link->ops->prepare) { 776 if (rtd->dai_link->ops->prepare) {
777 ret = rtd->dai_link->ops->prepare(substream); 777 ret = rtd->dai_link->ops->prepare(substream);
@@ -826,7 +826,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
826 snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); 826 snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream);
827 827
828out: 828out:
829 mutex_unlock(&rtd->pcm_mutex); 829 mutex_unlock(&rtd->card->pcm_mutex);
830 return ret; 830 return ret;
831} 831}
832 832
@@ -876,7 +876,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
876 struct snd_soc_dai *codec_dai; 876 struct snd_soc_dai *codec_dai;
877 int i, ret = 0; 877 int i, ret = 0;
878 878
879 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 879 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
880 if (rtd->dai_link->ops->hw_params) { 880 if (rtd->dai_link->ops->hw_params) {
881 ret = rtd->dai_link->ops->hw_params(substream, params); 881 ret = rtd->dai_link->ops->hw_params(substream, params);
882 if (ret < 0) { 882 if (ret < 0) {
@@ -962,7 +962,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
962 if (ret) 962 if (ret)
963 goto component_err; 963 goto component_err;
964out: 964out:
965 mutex_unlock(&rtd->pcm_mutex); 965 mutex_unlock(&rtd->card->pcm_mutex);
966 return ret; 966 return ret;
967 967
968component_err: 968component_err:
@@ -986,7 +986,7 @@ codec_err:
986 if (rtd->dai_link->ops->hw_free) 986 if (rtd->dai_link->ops->hw_free)
987 rtd->dai_link->ops->hw_free(substream); 987 rtd->dai_link->ops->hw_free(substream);
988 988
989 mutex_unlock(&rtd->pcm_mutex); 989 mutex_unlock(&rtd->card->pcm_mutex);
990 return ret; 990 return ret;
991} 991}
992 992
@@ -1001,7 +1001,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
1001 bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 1001 bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
1002 int i; 1002 int i;
1003 1003
1004 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 1004 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
1005 1005
1006 /* clear the corresponding DAIs parameters when going to be inactive */ 1006 /* clear the corresponding DAIs parameters when going to be inactive */
1007 if (cpu_dai->active == 1) { 1007 if (cpu_dai->active == 1) {
@@ -1043,7 +1043,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
1043 1043
1044 snd_soc_dai_hw_free(cpu_dai, substream); 1044 snd_soc_dai_hw_free(cpu_dai, substream);
1045 1045
1046 mutex_unlock(&rtd->pcm_mutex); 1046 mutex_unlock(&rtd->card->pcm_mutex);
1047 return 0; 1047 return 0;
1048} 1048}
1049 1049