]>
Commit | Line | Data |
---|---|---|
544566e1 GKH |
1 | From 0efa3334d65b7f421ba12382dfa58f6ff5bf83c4 Mon Sep 17 00:00:00 2001 |
2 | From: Ross Zwisler <zwisler@chromium.org> | |
3 | Date: Mon, 29 Apr 2019 12:25:17 -0600 | |
4 | Subject: ASoC: Intel: avoid Oops if DMA setup fails | |
5 | ||
6 | From: Ross Zwisler <zwisler@chromium.org> | |
7 | ||
8 | commit 0efa3334d65b7f421ba12382dfa58f6ff5bf83c4 upstream. | |
9 | ||
10 | Currently in sst_dsp_new() if we get an error return from sst_dma_new() | |
11 | we just print an error message and then still complete the function | |
12 | successfully. This means that we are trying to run without sst->dma | |
13 | properly set up, which will result in NULL pointer dereference when | |
14 | sst->dma is later used. This was happening for me in | |
15 | sst_dsp_dma_get_channel(): | |
16 | ||
17 | struct sst_dma *dma = dsp->dma; | |
18 | ... | |
19 | dma->ch = dma_request_channel(mask, dma_chan_filter, dsp); | |
20 | ||
21 | This resulted in: | |
22 | ||
23 | BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 | |
24 | IP: sst_dsp_dma_get_channel+0x4f/0x125 [snd_soc_sst_firmware] | |
25 | ||
26 | Fix this by adding proper error handling for the case where we fail to | |
27 | set up DMA. | |
28 | ||
29 | This change only affects Haswell and Broadwell systems. Baytrail | |
30 | systems explicilty opt-out of DMA via sst->pdata->resindex_dma_base | |
31 | being set to -1. | |
32 | ||
33 | Signed-off-by: Ross Zwisler <zwisler@google.com> | |
34 | Cc: stable@vger.kernel.org | |
35 | Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | |
36 | Signed-off-by: Mark Brown <broonie@kernel.org> | |
37 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
38 | ||
39 | --- | |
40 | sound/soc/intel/common/sst-dsp.c | 8 ++++++-- | |
41 | 1 file changed, 6 insertions(+), 2 deletions(-) | |
42 | ||
43 | --- a/sound/soc/intel/common/sst-dsp.c | |
44 | +++ b/sound/soc/intel/common/sst-dsp.c | |
45 | @@ -463,11 +463,15 @@ struct sst_dsp *sst_dsp_new(struct devic | |
46 | goto irq_err; | |
47 | ||
48 | err = sst_dma_new(sst); | |
49 | - if (err) | |
50 | - dev_warn(dev, "sst_dma_new failed %d\n", err); | |
51 | + if (err) { | |
52 | + dev_err(dev, "sst_dma_new failed %d\n", err); | |
53 | + goto dma_err; | |
54 | + } | |
55 | ||
56 | return sst; | |
57 | ||
58 | +dma_err: | |
59 | + free_irq(sst->irq, sst); | |
60 | irq_err: | |
61 | if (sst->ops->free) | |
62 | sst->ops->free(sst); |