soundwire: cadence: allocate/free dma_data in set_sdw_stream
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tue, 30 Jun 2020 18:43:55 +0000 (02:43 +0800)
committerVinod Koul <vkoul@kernel.org>
Wed, 15 Jul 2020 04:40:05 +0000 (10:10 +0530)
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.bossart@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20200630184356.24939-5-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/cadence_master.c

index 9ea8753..613dbd4 100644 (file)
@@ -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 (dma) {
+                       dev_err(dai->dev,
+                               "dma_data already allocated for dai %s\n",
+                               dai->name);
+                       return -EINVAL;
+               }
 
-       if (pcm)
-               dma->stream_type = SDW_STREAM_PCM;
-       else
-               dma->stream_type = SDW_STREAM_PDM;
+               /* allocate and set dma info */
+               dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+               if (!dma)
+                       return -ENOMEM;
 
-       dma->bus = &cdns->bus;
-       dma->link_id = cdns->instance;
+               if (pcm)
+                       dma->stream_type = SDW_STREAM_PCM;
+               else
+                       dma->stream_type = SDW_STREAM_PDM;
 
-       dma->stream = stream;
+               dma->bus = &cdns->bus;
+               dma->link_id = cdns->instance;
 
-       if (direction == SNDRV_PCM_STREAM_PLAYBACK)
-               dai->playback_dma_data = dma;
-       else
-               dai->capture_dma_data = dma;
+               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);