Skip to content

Commit 011a871

Browse files
fidomaxbroonie
authored andcommitted
ASoC: dwc: move DMA init to snd_soc_dai_driver probe()
When using DMA mode we are facing with Oops: [ 396.458157] Unable to handle kernel access to user memory without uaccess routines at virtual address 000000000000000c [ 396.469374] Oops [#1] [ 396.471839] Modules linked in: [ 396.475144] CPU: 0 PID: 114 Comm: arecord Not tainted 6.0.0-00164-g9a8eccdaf2be-dirty torvalds#68 [ 396.483619] Hardware name: YMP ELCT FPGA (DT) [ 396.488156] epc : dmaengine_pcm_open+0x1d2/0x342 [ 396.493227] ra : dmaengine_pcm_open+0x1d2/0x342 [ 396.498140] epc : ffffffff807fe346 ra : ffffffff807fe346 sp : ffffffc804e138f0 [ 396.505602] gp : ffffffff817bf730 tp : ffffffd8042c8ac0 t0 : 6500000000000000 [ 396.513045] t1 : 0000000000000064 t2 : 656e69676e65616d s0 : ffffffc804e13990 [ 396.520477] s1 : ffffffd801b86a18 a0 : 0000000000000026 a1 : ffffffff816920f8 [ 396.527897] a2 : 0000000000000010 a3 : fffffffffffffffe a4 : 0000000000000000 [ 396.535319] a5 : 0000000000000000 a6 : ffffffd801b87040 a7 : 0000000000000038 [ 396.542740] s2 : ffffffd801b94a00 s3 : 0000000000000000 s4 : ffffffd80427f5e8 [ 396.550153] s5 : ffffffd80427f5e8 s6 : ffffffd801b44410 s7 : fffffffffffffff5 [ 396.557569] s8 : 0000000000000800 s9 : 0000000000000001 s10: ffffffff8066d254 [ 396.564978] s11: ffffffd8059cf768 t3 : ffffffff817d5577 t4 : ffffffff817d5577 [ 396.572391] t5 : ffffffff817d5578 t6 : ffffffc804e136e8 [ 396.577876] status: 0000000200000120 badaddr: 000000000000000c cause: 000000000000000d [ 396.586007] [<ffffffff806839f4>] snd_soc_component_open+0x1a/0x68 [ 396.592439] [<ffffffff807fdd62>] __soc_pcm_open+0xf0/0x502 [ 396.598217] [<ffffffff80685d86>] soc_pcm_open+0x2e/0x4e [ 396.603741] [<ffffffff8066cea4>] snd_pcm_open_substream+0x442/0x68e [ 396.610313] [<ffffffff8066d1ea>] snd_pcm_open+0xfa/0x212 [ 396.615868] [<ffffffff8066d39c>] snd_pcm_capture_open+0x3a/0x60 [ 396.622048] [<ffffffff8065b35a>] snd_open+0xa8/0x17a [ 396.627421] [<ffffffff801ae036>] chrdev_open+0xa0/0x218 [ 396.632893] [<ffffffff801a5a28>] do_dentry_open+0x17c/0x2a6 [ 396.638713] [<ffffffff801a6d9a>] vfs_open+0x1e/0x26 [ 396.643850] [<ffffffff801b8544>] path_openat+0x96e/0xc96 [ 396.649518] [<ffffffff801b9390>] do_filp_open+0x7c/0xf6 [ 396.655034] [<ffffffff801a6ff2>] do_sys_openat2+0x8a/0x11e [ 396.660765] [<ffffffff801a735a>] sys_openat+0x50/0x7c [ 396.666068] [<ffffffff80003aca>] ret_from_syscall+0x0/0x2 [ 396.674964] ---[ end trace 0000000000000000 ]--- It happens because of play_dma_data/capture_dma_data pointers are NULL. Current implementation assigns these pointers at snd_soc_dai_driver startup() callback and reset them back to NULL at shutdown(). But soc_pcm_open() sequence uses DMA pointers in dmaengine_pcm_open() before snd_soc_dai_driver startup(). Most generic DMA capable I2S drivers use snd_soc_dai_driver probe() callback to init DMA pointers only once at probe. So move DMA init to dw_i2s_dai_probe and drop shutdown() and startup() callbacks. Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru> Link: https://lore.kernel.org/r/20230512110343.66664-1-fido_max@inbox.ru Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent e2d035f commit 011a871

File tree

1 file changed

+9
-32
lines changed

1 file changed

+9
-32
lines changed

sound/soc/dwc/dwc-i2s.c

+9-32
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
183183
}
184184
}
185185

186-
static int dw_i2s_startup(struct snd_pcm_substream *substream,
187-
struct snd_soc_dai *cpu_dai)
188-
{
189-
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
190-
union dw_i2s_snd_dma_data *dma_data = NULL;
191-
192-
if (!(dev->capability & DWC_I2S_RECORD) &&
193-
(substream->stream == SNDRV_PCM_STREAM_CAPTURE))
194-
return -EINVAL;
195-
196-
if (!(dev->capability & DWC_I2S_PLAY) &&
197-
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
198-
return -EINVAL;
199-
200-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
201-
dma_data = &dev->play_dma_data;
202-
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
203-
dma_data = &dev->capture_dma_data;
204-
205-
snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
206-
207-
return 0;
208-
}
209-
210186
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
211187
{
212188
u32 ch_reg;
@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
305281
return 0;
306282
}
307283

308-
static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
309-
struct snd_soc_dai *dai)
310-
{
311-
snd_soc_dai_set_dma_data(dai, substream, NULL);
312-
}
313-
314284
static int dw_i2s_prepare(struct snd_pcm_substream *substream,
315285
struct snd_soc_dai *dai)
316286
{
@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
382352
}
383353

384354
static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
385-
.startup = dw_i2s_startup,
386-
.shutdown = dw_i2s_shutdown,
387355
.hw_params = dw_i2s_hw_params,
388356
.prepare = dw_i2s_prepare,
389357
.trigger = dw_i2s_trigger,
@@ -625,6 +593,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
625593

626594
}
627595

596+
static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
597+
{
598+
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
599+
600+
snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
601+
return 0;
602+
}
603+
628604
static int dw_i2s_probe(struct platform_device *pdev)
629605
{
630606
const struct i2s_platform_data *pdata = pdev->dev.platform_data;
@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
643619
return -ENOMEM;
644620

645621
dw_i2s_dai->ops = &dw_i2s_dai_ops;
622+
dw_i2s_dai->probe = dw_i2s_dai_probe;
646623

647624
dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
648625
if (IS_ERR(dev->i2s_base))

0 commit comments

Comments
 (0)