Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
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);