From: Pierre-Louis Bossart <pierre-louis.boss...@linux.intel.com>

The current memory allocation is somewhat strange: the dma_data is
allocated in set_sdw_stream, but released in the intel DAI
shutdown. This no longer works with the multi-cpu implementation,
since the dma_data is released in the dai shutdown which takes place
before the dailink shutdown.

Move to a more symmetric allocation where the dma_data is allocated
with non-NULL SoundWire stream, and conversely released when a NULL
stream is provided - for consistency with the stream startup and
shutdown operations.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.boss...@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.l...@linux.intel.com>
---
 drivers/soundwire/cadence_master.c | 52 ++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 9ea87538b9ef..613dbd415b91 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1437,25 +1437,49 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
        struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
        struct sdw_cdns_dma_data *dma;
 
-       dma = kzalloc(sizeof(*dma), GFP_KERNEL);
-       if (!dma)
-               return -ENOMEM;
+       if (stream) {
+               /* first paranoia check */
+               if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+                       dma = dai->playback_dma_data;
+               else
+                       dma = dai->capture_dma_data;
 
-       if (pcm)
-               dma->stream_type = SDW_STREAM_PCM;
-       else
-               dma->stream_type = SDW_STREAM_PDM;
+               if (dma) {
+                       dev_err(dai->dev,
+                               "dma_data already allocated for dai %s\n",
+                               dai->name);
+                       return -EINVAL;
+               }
 
-       dma->bus = &cdns->bus;
-       dma->link_id = cdns->instance;
+               /* allocate and set dma info */
+               dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+               if (!dma)
+                       return -ENOMEM;
 
-       dma->stream = stream;
+               if (pcm)
+                       dma->stream_type = SDW_STREAM_PCM;
+               else
+                       dma->stream_type = SDW_STREAM_PDM;
 
-       if (direction == SNDRV_PCM_STREAM_PLAYBACK)
-               dai->playback_dma_data = dma;
-       else
-               dai->capture_dma_data = dma;
+               dma->bus = &cdns->bus;
+               dma->link_id = cdns->instance;
 
+               dma->stream = stream;
+
+               if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+                       dai->playback_dma_data = dma;
+               else
+                       dai->capture_dma_data = dma;
+       } else {
+               /* for NULL stream we release allocated dma_data */
+               if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+                       kfree(dai->playback_dma_data);
+                       dai->playback_dma_data = NULL;
+               } else {
+                       kfree(dai->capture_dma_data);
+                       dai->capture_dma_data = NULL;
+               }
+       }
        return 0;
 }
 EXPORT_SYMBOL(cdns_set_sdw_stream);
-- 
2.17.1

Reply via email to