pxa2xx_pcm_hw_free frees dma channel and sets prtd->dma_ch to -1, but does not set prtd->params to NULL, so if pxa2xx_pcm_hw_params will be called immediately, it leaves prtd->dma_ch initialized with -1, and it results in oops in __pxa2xx_pcm_prepare. This bug is triggered via SDL.
This patch adds check for prtd->dma_ch to __pxa2xx_pcm_prepare and cleans prtd->params, so now it works properly.
Signed-off-by: Vasily Khoruzhick anarsoul@gmail.com --- v2: use -EINVAL as error in __pxa2xx_pcm_prepare if dma_ch is invalid.
sound/arm/pxa2xx-pcm-lib.c | 3 +++ sound/soc/pxa/pxa2xx-pcm.c | 1 + 2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c index 8808b82..76e0d56 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/arm/pxa2xx-pcm-lib.c @@ -140,6 +140,9 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) if (!prtd || !prtd->params) return 0;
+ if (prtd->dma_ch == -1) + return -EINVAL; + DCSR(prtd->dma_ch) &= ~DCSR_RUN; DCSR(prtd->dma_ch) = 0; DCMD(prtd->dma_ch) = 0; diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 02fb664..2ce0b2d 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -65,6 +65,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) if (prtd->dma_ch >= 0) { pxa_free_dma(prtd->dma_ch); prtd->dma_ch = -1; + prtd->params = NULL; }
return 0;