merged.
Bruce
In message: [linux-yocto][linux-yocto v6.6/standard/nxp-sdk-6.6/nxp-soc &
v6.6/standard/preempt-rt/nxp-sdk-6.6/nxp-soc][PATCH 1/2] dmaengine: imx-sdma:
Make runtime PM irq safe
on 12/12/2024 Xiaolei Wang wrote:
> Make runtime PM irq safe to avoid the following
> trace during the resume process, irq safe has told
> the runtime PM core to run with interrupts disabled.
> The dma_free_coherent() can't be invoked in interrupt
> context, otherwise it will also cause warnings. Therefore,
> in order to avoid these warnings, remove the allocation
> of bd0_phys in resume().
>
> BUG: sleeping function called from invalid context at
> drivers/base/power/runtime.c:1163
> in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 540, name: aplay
> preempt_count: 1, expected: 0
> RCU nest depth: 0, expected: 0
> 1 held lock by aplay/540:
> #0: ffffff80d5c96910 (&group->lock){....}-{2:2}, at:
> snd_pcm_stream_lock_irq+0x40/0x50
> irq event stamp: 10036
> hardirqs last enabled at (10035): [<ffffffc009174dc0>]
> _raw_spin_unlock_irq+0x40/0x80
> hardirqs last disabled at (10036): [<ffffffc009175354>]
> _raw_spin_lock_irq+0xf0/0xfc
> softirqs last enabled at (9620): [<ffffffc008018614>]
> fpsimd_restore_current_state+0x44/0xc0
> softirqs last disabled at (9618): [<ffffffc008017288>]
> get_cpu_fpsimd_context+0x8/0x70
> Preemption disabled at:
> [<ffffffc008dc6560>] snd_pcm_stream_lock_irq+0x40/0x50
> CPU: 2 PID: 540 Comm: aplay Tainted: G C 6.1.68-yocto-standard #1
> Hardware name: NXP i.MX8MPlus EVK board (DT)
> Call trace:
> dump_backtrace.part.0+0xcc/0xe0
> show_stack+0x20/0x30
> dump_stack_lvl+0x9c/0xd0
> dump_stack+0x18/0x34
> __might_resched+0x188/0x290
> __might_sleep+0x50/0xa0
> __pm_runtime_resume+0xa8/0xb0
> sdma_prep_dma_cyclic+0x60/0x2a0 [imx_sdma]
> snd_dmaengine_pcm_trigger+0xf8/0x190
> dmaengine_pcm_trigger+0x20/0x2c
> snd_soc_pcm_component_trigger+0x14c/0x224
> soc_pcm_trigger+0xc0/0x200
> snd_pcm_do_start+0x3c/0x4c
> snd_pcm_action_single+0x50/0xb0
> snd_pcm_action+0x84/0xa0
> snd_pcm_start+0x2c/0x40
> __snd_pcm_lib_xfer+0x594/0x7c0
> snd_pcm_common_ioctl+0x1370/0x1a3c
> snd_pcm_ioctl+0x38/0x50
> __arm64_sys_ioctl+0xb4/0x100
> invoke_syscall+0x5c/0x130
> el0_svc_common.constprop.0+0x68/0x124
> do_el0_svc+0x34/0xc0
> el0_svc+0x48/0xc0
> el0t_64_sync_handler+0xf4/0x120
> el0t_64_sync+0x18c/0x190
>
> Signed-off-by: Xiaolei Wang <[email protected]>
> Signed-off-by: Bruce Ashfield <[email protected]>
> ---
> drivers/dma/imx-sdma.c | 63 +++++++++++++++++++++---------------------
> 1 file changed, 32 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 647a3bc81ac1..16d54d97efbc 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -894,11 +894,16 @@ static int sdma_load_script(struct sdma_engine *sdma)
> ram_code = (void *)header + header->ram_code_start;
> sdma->ram_code_start = header->ram_code_start;
>
> - buf_virt = dma_alloc_coherent(sdma->dev, header->ram_code_size,
> - &buf_phys, GFP_KERNEL);
> + buf_virt = kzalloc(header->ram_code_size, GFP_NOWAIT);
> if (!buf_virt)
> return -ENOMEM;
>
> + buf_phys = dma_map_single(sdma->dev, buf_virt,
> + header->ram_code_size,
> + DMA_TO_DEVICE);
> + if (dma_mapping_error(sdma->dev, buf_phys))
> + return -ENOMEM;
> +
> spin_lock_irqsave(&sdma->channel_0_lock, flags);
>
> bd0->mode.command = C0_SETPM;
> @@ -913,7 +918,9 @@ static int sdma_load_script(struct sdma_engine *sdma)
>
> spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
>
> - dma_free_coherent(sdma->dev, header->ram_code_size, buf_virt, buf_phys);
> + dma_unmap_single(sdma->dev, buf_phys,
> + header->ram_code_size, DMA_TO_DEVICE);
> + kfree(buf_virt);
>
> sdma_add_scripts(sdma, addr);
>
> @@ -1570,14 +1577,6 @@ static int sdma_request_channel0(struct sdma_engine
> *sdma)
> {
> int ret = -EBUSY;
>
> - if (sdma->iram_pool)
> - sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool,
> - sizeof(struct sdma_buffer_descriptor),
> - &sdma->bd0_phys);
> - else
> - sdma->bd0 = dma_alloc_coherent(sdma->dev,
> - sizeof(struct sdma_buffer_descriptor),
> - &sdma->bd0_phys, GFP_NOWAIT);
> if (!sdma->bd0) {
> ret = -ENOMEM;
> goto out;
> @@ -1649,15 +1648,6 @@ static int sdma_runtime_suspend(struct device *dev)
> clk_disable(sdma->clk_ipg);
> clk_disable(sdma->clk_ahb);
>
> - /* free channel0 bd */
> - if (sdma->iram_pool)
> - gen_pool_free(sdma->iram_pool, (unsigned long)sdma->bd0,
> - sizeof(struct sdma_buffer_descriptor));
> - else
> - dma_free_coherent(sdma->dev,
> - sizeof(struct sdma_buffer_descriptor),
> - sdma->bd0, sdma->bd0_phys);
> -
> return 0;
> }
>
> @@ -1678,17 +1668,6 @@ static int sdma_runtime_resume(struct device *dev)
> * not off indeed.
> */
> if (readl_relaxed(sdma->regs + SDMA_H_C0PTR)) {
> - if (sdma->iram_pool)
> - sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool,
> - sizeof(struct sdma_buffer_descriptor),
> - &sdma->bd0_phys);
> - else
> - sdma->bd0 = dma_alloc_coherent(sdma->dev,
> - sizeof(struct sdma_buffer_descriptor),
> - &sdma->bd0_phys, GFP_NOWAIT);
> - if (!sdma->bd0)
> - ret = -ENOMEM;
> -
> sdma->channel_control[0].base_bd_ptr = sdma->bd0_phys;
> sdma->channel_control[0].current_bd_ptr = sdma->bd0_phys;
>
> @@ -2423,6 +2402,18 @@ static int sdma_init_sw(struct sdma_engine *sdma)
> return ret;
> }
>
> + if (sdma->iram_pool)
> + sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool,
> + sizeof(struct sdma_buffer_descriptor),
> + &sdma->bd0_phys);
> + else
> + sdma->bd0 = dma_alloc_coherent(sdma->dev,
> + sizeof(struct sdma_buffer_descriptor),
> + &sdma->bd0_phys, GFP_NOWAIT);
> + if (!sdma->bd0)
> + ret = -ENOMEM;
> +
> +
> sdma->context = (void *)sdma->channel_control +
> MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control);
> sdma->context_phys = sdma->ccb_phys +
> @@ -2663,6 +2654,7 @@ static int sdma_probe(struct platform_device *pdev)
> /* For the largest period size 64KB, the dma transfer time
> * is about 8 sec.
> */
> + pm_runtime_irq_safe(&pdev->dev);
> pm_runtime_set_autosuspend_delay(&pdev->dev, 8000);
> pm_runtime_use_autosuspend(&pdev->dev);
> pm_runtime_mark_last_busy(&pdev->dev);
> @@ -2709,6 +2701,15 @@ static int sdma_remove(struct platform_device *pdev)
> sdma_runtime_suspend(&pdev->dev);
> }
>
> + /* free channel0 bd */
> + if (sdma->iram_pool)
> + gen_pool_free(sdma->iram_pool, (unsigned long)sdma->bd0,
> + sizeof(struct sdma_buffer_descriptor));
> + else
> + dma_free_coherent(sdma->dev,
> + sizeof(struct sdma_buffer_descriptor),
> + sdma->bd0, sdma->bd0_phys);
> +
> platform_set_drvdata(pdev, NULL);
> return 0;
> }
> --
> 2.25.1
>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#14670):
https://lists.yoctoproject.org/g/linux-yocto/message/14670
Mute This Topic: https://lists.yoctoproject.org/mt/110076849/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-