From: Shengjiu Wang <[email protected]>

The shared dma_params_tx/rx fields in struct fsl_asrc were a single
instance written by every concurrent fsl_asrc_dma_hw_params() call.
With multiple DAIs registered (one per pair/context), parallel stream
open+hw_params races would corrupt addr and maxburst for all active
streams.

Fix by moving dma_params into struct fsl_asrc_pair so each pair owns
its own copy. Initialise them in fsl_asrc_dma_startup() where
the pair is allocated, which makes the per-DAI probe callbacks in
fsl_asrc.c and fsl_easrc.c redundant; remove those as well.

Signed-off-by: Shengjiu Wang <[email protected]>
---
 sound/soc/fsl/fsl_asrc.c        | 11 -----------
 sound/soc/fsl/fsl_asrc_common.h |  7 +++----
 sound/soc/fsl/fsl_asrc_dma.c    | 14 ++++++++++++++
 sound/soc/fsl/fsl_easrc.c       | 11 -----------
 4 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 0b28bcfa47fe..986a2e26819a 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -781,18 +781,7 @@ static int fsl_asrc_dai_trigger(struct snd_pcm_substream 
*substream, int cmd,
        return 0;
 }
 
-static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
-{
-       struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
-
-       snd_soc_dai_init_dma_data(dai, &asrc->dma_params_tx,
-                                 &asrc->dma_params_rx);
-
-       return 0;
-}
-
 static const struct snd_soc_dai_ops fsl_asrc_dai_ops = {
-       .probe          = fsl_asrc_dai_probe,
        .startup        = fsl_asrc_dai_startup,
        .hw_params      = fsl_asrc_dai_hw_params,
        .hw_free        = fsl_asrc_dai_hw_free,
diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h
index c8a1a2b5915d..4e6b00cb5d63 100644
--- a/sound/soc/fsl/fsl_asrc_common.h
+++ b/sound/soc/fsl/fsl_asrc_common.h
@@ -53,6 +53,7 @@ struct fsl_asrc_m2m_cap {
  * @dma_data: private dma data
  * @pos: hardware pointer position
  * @req_dma_chan: flag to release dev_to_dev chan
+ * @dma_params: DMA parameters for transmit/receive channel
  * @private: pair private area
  * @complete: dma task complete
  * @sample_format: format of m2m
@@ -76,6 +77,8 @@ struct fsl_asrc_pair {
        unsigned int pos;
        bool req_dma_chan;
 
+       struct snd_dmaengine_dai_dma_data dma_params;
+
        void *private;
 
        /* used for m2m */
@@ -92,8 +95,6 @@ struct fsl_asrc_pair {
 /**
  * fsl_asrc: ASRC common data
  *
- * @dma_params_rx: DMA parameters for receive channel
- * @dma_params_tx: DMA parameters for transmit channel
  * @pdev: platform device pointer
  * @regmap: regmap handler
  * @paddr: physical address to the base address of registers
@@ -128,8 +129,6 @@ struct fsl_asrc_pair {
  * @private: private data structure
  */
 struct fsl_asrc {
-       struct snd_dmaengine_dai_dma_data dma_params_rx;
-       struct snd_dmaengine_dai_dma_data dma_params_tx;
        struct platform_device *pdev;
        struct regmap *regmap;
        unsigned long paddr;
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index 38f2b7c63133..64d66420e7ad 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -390,6 +390,20 @@ static int fsl_asrc_dma_startup(struct snd_soc_component 
*component,
 
        runtime->private_data = pair;
 
+       /*
+        * Point the cpu DAI dma_data at the per-pair params so that
+        * concurrent hw_params calls on different pairs each write to
+        * their own struct and do not race on addr/maxburst.  Use the
+        * per-direction setters so that a concurrent open of the other
+        * direction on the same DAI does not NULL out its pointer.
+        */
+       if (tx)
+               snd_soc_dai_dma_data_set_playback(snd_soc_rtd_to_cpu(rtd, 0),
+                                                 &pair->dma_params);
+       else
+               snd_soc_dai_dma_data_set_capture(snd_soc_rtd_to_cpu(rtd, 0),
+                                                &pair->dma_params);
+
        /* Request a dummy pair, which will be released later.
         * Request pair function needs channel num as input, for this
         * dummy pair, we just request "1" channel temporarily.
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index edfd943197a0..e68f6cbdd653 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1582,18 +1582,7 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream 
*substream,
        return 0;
 }
 
-static int fsl_easrc_dai_probe(struct snd_soc_dai *cpu_dai)
-{
-       struct fsl_asrc *easrc = dev_get_drvdata(cpu_dai->dev);
-
-       snd_soc_dai_init_dma_data(cpu_dai,
-                                 &easrc->dma_params_tx,
-                                 &easrc->dma_params_rx);
-       return 0;
-}
-
 static const struct snd_soc_dai_ops fsl_easrc_dai_ops = {
-       .probe          = fsl_easrc_dai_probe,
        .startup        = fsl_easrc_startup,
        .trigger        = fsl_easrc_trigger,
        .hw_params      = fsl_easrc_hw_params,
-- 
2.34.1


Reply via email to