Commit 721be3be authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown

ASoC: wm_adsp: Detach compressed stream on free

If someone powers down the DSP core (through routing changes
say) whilst a compressed record is in progress we can end up
using a freed pointer to the buffer object. When a compressed
audio stream is triggered we attach it to a buffer on a physical
DSP. This patch adds a detach of the buffer from the stream when
the stream is freed or when the DSP is powered down which avoids
the situation where we use a buffer when it is no longer valid.
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent edd71350
...@@ -273,8 +273,11 @@ struct wm_adsp_buffer { ...@@ -273,8 +273,11 @@ struct wm_adsp_buffer {
__be32 words_written[2]; /* total words written (64 bit) */ __be32 words_written[2]; /* total words written (64 bit) */
}; };
struct wm_adsp_compr;
struct wm_adsp_compr_buf { struct wm_adsp_compr_buf {
struct wm_adsp *dsp; struct wm_adsp *dsp;
struct wm_adsp_compr *compr;
struct wm_adsp_buffer_region *regions; struct wm_adsp_buffer_region *regions;
u32 host_buf_ptr; u32 host_buf_ptr;
...@@ -2467,10 +2470,26 @@ static int wm_adsp_compr_attach(struct wm_adsp_compr *compr) ...@@ -2467,10 +2470,26 @@ static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
return -EINVAL; return -EINVAL;
compr->buf = compr->dsp->buffer; compr->buf = compr->dsp->buffer;
compr->buf->compr = compr;
return 0; return 0;
} }
static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
{
if (!compr)
return;
/* Wake the poll so it can see buffer is no longer attached */
if (compr->stream)
snd_compr_fragment_elapsed(compr->stream);
if (wm_adsp_compr_attached(compr)) {
compr->buf->compr = NULL;
compr->buf = NULL;
}
}
int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream) int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
{ {
struct wm_adsp_compr *compr; struct wm_adsp_compr *compr;
...@@ -2524,6 +2543,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream) ...@@ -2524,6 +2543,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream)
mutex_lock(&dsp->pwr_lock); mutex_lock(&dsp->pwr_lock);
wm_adsp_compr_detach(compr);
dsp->compr = NULL; dsp->compr = NULL;
kfree(compr->raw_buf); kfree(compr->raw_buf);
...@@ -2820,6 +2840,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp) ...@@ -2820,6 +2840,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
static int wm_adsp_buffer_free(struct wm_adsp *dsp) static int wm_adsp_buffer_free(struct wm_adsp *dsp)
{ {
if (dsp->buffer) { if (dsp->buffer) {
wm_adsp_compr_detach(dsp->buffer->compr);
kfree(dsp->buffer->regions); kfree(dsp->buffer->regions);
kfree(dsp->buffer); kfree(dsp->buffer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment