@@ -273,8 +273,11 @@ struct wm_adsp_buffer {
__be32 words_written[2]; /* total words written (64 bit) */
};
+struct wm_adsp_compr;
+
struct wm_adsp_compr_buf {
struct wm_adsp *dsp;
+ struct wm_adsp_compr *compr;
struct wm_adsp_buffer_region *regions;
u32 host_buf_ptr;
@@ -2467,10 +2470,26 @@ static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
return -EINVAL;
compr->buf = compr->dsp->buffer;
+ compr->buf->compr = compr;
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)
{
struct wm_adsp_compr *compr;
@@ -2524,6 +2543,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream)
mutex_lock(&dsp->pwr_lock);
+ wm_adsp_compr_detach(compr);
dsp->compr = NULL;
kfree(compr->raw_buf);
@@ -2820,6 +2840,8 @@ err_buffer:
static int wm_adsp_buffer_free(struct wm_adsp *dsp)
{
if (dsp->buffer) {
+ wm_adsp_compr_detach(dsp->buffer->compr);
+
kfree(dsp->buffer->regions);
kfree(dsp->buffer);
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: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> --- sound/soc/codecs/wm_adsp.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)