Patch "ASoC: dwc: move DMA init to snd_soc_dai_driver probe()" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ASoC: dwc: move DMA init to snd_soc_dai_driver probe()

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     asoc-dwc-move-dma-init-to-snd_soc_dai_driver-probe.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 143460b76c8afe1bd7dba28a5d72129885966a35
Author: Maxim Kochetkov <fido_max@xxxxxxxx>
Date:   Fri May 12 14:03:42 2023 +0300

    ASoC: dwc: move DMA init to snd_soc_dai_driver probe()
    
    [ Upstream commit 011a8719d6105dcb48077ea7a6a88ac019d4aa50 ]
    
    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 #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@xxxxxxxx>
    Link: https://lore.kernel.org/r/20230512110343.66664-1-fido_max@xxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
index 14ad8023fcdcb..feed7281ba215 100644
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
 	}
 }
 
-static int dw_i2s_startup(struct snd_pcm_substream *substream,
-		struct snd_soc_dai *cpu_dai)
-{
-	struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-	union dw_i2s_snd_dma_data *dma_data = NULL;
-
-	if (!(dev->capability & DWC_I2S_RECORD) &&
-			(substream->stream == SNDRV_PCM_STREAM_CAPTURE))
-		return -EINVAL;
-
-	if (!(dev->capability & DWC_I2S_PLAY) &&
-			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
-		return -EINVAL;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dma_data = &dev->play_dma_data;
-	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		dma_data = &dev->capture_dma_data;
-
-	snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
-
-	return 0;
-}
-
 static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
 {
 	u32 ch_reg;
@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
-		struct snd_soc_dai *dai)
-{
-	snd_soc_dai_set_dma_data(dai, substream, NULL);
-}
-
 static int dw_i2s_prepare(struct snd_pcm_substream *substream,
 			  struct snd_soc_dai *dai)
 {
@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
-	.startup	= dw_i2s_startup,
-	.shutdown	= dw_i2s_shutdown,
 	.hw_params	= dw_i2s_hw_params,
 	.prepare	= dw_i2s_prepare,
 	.trigger	= dw_i2s_trigger,
@@ -624,6 +592,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
 
 }
 
+static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+	struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+	snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
+	return 0;
+}
+
 static int dw_i2s_probe(struct platform_device *pdev)
 {
 	const struct i2s_platform_data *pdata = pdev->dev.platform_data;
@@ -642,6 +618,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
+	dw_i2s_dai->probe = dw_i2s_dai_probe;
 
 	dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(dev->i2s_base))



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux