summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorKai Vehmanen <kai.vehmanen@linux.intel.com>2019-09-27 16:05:30 -0400
committerMark Brown <broonie@kernel.org>2019-10-01 13:31:06 -0400
commite66e52c5b7422824cedf0084c0766602dea7e8a7 (patch)
treed7f5ab4eee5f8a3364650eba36312a0aea2463a4 /sound/soc/sof
parent2e305a074061121220a2828f97a57d315cf8efba (diff)
ASoC: SOF: pcm: fix resource leak in hw_free
Fix a bug in sof_pcm_hw_free() where some cleanup actions were skipped if STREAM_PCM_FREE IPC was already successfully sent to DSP when the stream was stopped or suspended. This is incorrect as hw_free should clean up also other resources, including pcm lib page allocations, period elapsed work queue and call to platform hw_free. Fixes: c29d96c3b9b4 ("ASoC: SOF: reset DMA state in prepare") Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20190927200538.660-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/pcm.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index e3f6a6dc0f36..fa7769dd825c 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -244,7 +244,7 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
244 snd_soc_rtdcom_lookup(rtd, DRV_NAME); 244 snd_soc_rtdcom_lookup(rtd, DRV_NAME);
245 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 245 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
246 struct snd_sof_pcm *spcm; 246 struct snd_sof_pcm *spcm;
247 int ret; 247 int ret, err = 0;
248 248
249 /* nothing to do for BE */ 249 /* nothing to do for BE */
250 if (rtd->dai_link->no_pcm) 250 if (rtd->dai_link->no_pcm)
@@ -254,26 +254,26 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
254 if (!spcm) 254 if (!spcm)
255 return -EINVAL; 255 return -EINVAL;
256 256
257 if (!spcm->prepared[substream->stream])
258 return 0;
259
260 dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, 257 dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
261 substream->stream); 258 substream->stream);
262 259
263 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); 260 if (spcm->prepared[substream->stream]) {
261 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
262 if (ret < 0)
263 err = ret;
264 }
264 265
265 snd_pcm_lib_free_pages(substream); 266 snd_pcm_lib_free_pages(substream);
266 267
267 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); 268 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
268 269
269 if (ret < 0)
270 return ret;
271
272 ret = snd_sof_pcm_platform_hw_free(sdev, substream); 270 ret = snd_sof_pcm_platform_hw_free(sdev, substream);
273 if (ret < 0) 271 if (ret < 0) {
274 dev_err(sdev->dev, "error: platform hw free failed\n"); 272 dev_err(sdev->dev, "error: platform hw free failed\n");
273 err = ret;
274 }
275 275
276 return ret; 276 return err;
277} 277}
278 278
279static int sof_pcm_prepare(struct snd_pcm_substream *substream) 279static int sof_pcm_prepare(struct snd_pcm_substream *substream)