In current sf-pdma implementation, the channel resources's alloc and free
operations are controlled by sf_pdma_alloc_chan_resources() and
sf_pdma_free_chan_resources() functions respectively, while the channel related
done_tasklet and err_tasklet are controlled by sf_pdma_setup_chans() and
sf_pdma_remove(). And this design will cause the following issue, especially
in rt kernel:
Unable to handle kernel NULL pointer dereference at virtual address
0000000000000088
Oops [#1]
Modules linked in: openvswitch nsh nf_conncount nf_nat fuse nfnetlink
CPU: 0 PID: 64 Comm: irq/19-3000000. Not tainted
6.6.116-rt31-yocto-preempt-rt #1
Hardware name: Microchip PolarFire-SoC Icicle Kit (DT)
epc : sf_pdma_donebh_tasklet+0x52/0xe8
ra : sf_pdma_donebh_tasklet+0x48/0xe8
epc : ffffffff806ab8be ra : ffffffff806ab8b4 sp : ffffffc8002c3c40
gp : ffffffff81e120c8 tp : ffffffe7a2ab4980 t0 : 0000000001329be0
t1 : 0000000000000006 t2 : 0000000000004c08 s0 : ffffffc8002c3c60
s1 : ffffffe7a207b390 a0 : ffffffff8121da90 a1 : 0000000000000030
a2 : 0000000000000200 a3 : 0000000000000000 a4 : dead000000000000
a5 : 0000000000000003 a6 : ffffffff81305bd0 a7 : ffffffff81c08080
s2 : ffffffe7a207b298 s3 : 0000000000000001 s4 : ffffffff80e32640
s5 : ffffffff81dd7b20 s6 : ffffffff81e522b8 s7 : fffffffffffffffd
s8 : ffffffe7a207b398 s9 : 0000000000000000 s10: ffffffe7fef574d0
s11: ffffffff81dd7b20 t3 : 000000000000031f t4 : 0000000000000000
t5 : 00000000e0ccdeeb t6 : 0000000001329491
status: 0000000200000120 badaddr: 0000000000000088 cause: 000000000000000d
[<ffffffff806ab8be>] sf_pdma_donebh_tasklet+0x52/0xe8
[<ffffffff800216c6>] tasklet_action_common.isra.0+0x168/0x352
[<ffffffff8002190c>] tasklet_hi_action+0x2a/0x32
[<ffffffff80021140>] handle_softirqs.isra.0+0x148/0x2fc
[<ffffffff800214c0>] __local_bh_enable_ip+0x72/0xbc
[<ffffffff800791ac>] irq_forced_thread_fn+0x6a/0x7a
[<ffffffff80079028>] irq_thread+0x160/0x220
[<ffffffff8003dde2>] kthread+0xda/0xf6
[<ffffffff80bca256>] ret_from_fork+0xe/0x18
Code: 854a c097 0051 80e7 d2a0 b683 f984 d737 fdea 1712 (66d0) 62cc
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Fatal exception in interrupt
SMP: stopping secondary CPUs
---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
So this patch updates the following tasklet related items:
1. move the setup/kill operations of done_tasklet and err_tasklet
to sf_pdma_alloc/free_chan_resources()
2. update sf_pdma_disable_request() by adding PDMA_ENABLE_DONE_INT_MASK and
PDMA_ENABLE_ERR_INT_MASK bits setting to make it consistent with
sf_pdma_enable_request()
3. put sf_pdma_alloc/free_chan_resources() to a proper location to after the
definitions of the done_tasklet and err_tasklet
Then the issue can be fixed.
Signed-off-by: Zhantao Tang <[email protected]>
---
drivers/dma/sf-pdma/sf-pdma.c | 68 ++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 32 deletions(-)
diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
index 4f982f65aeb16..b0dc5e0727063 100644
--- a/drivers/dma/sf-pdma/sf-pdma.c
+++ b/drivers/dma/sf-pdma/sf-pdma.c
@@ -118,38 +118,15 @@ static int sf_pdma_slave_config(struct dma_chan *dchan,
return 0;
}
-static int sf_pdma_alloc_chan_resources(struct dma_chan *dchan)
-{
- struct sf_pdma_chan *chan = to_sf_pdma_chan(dchan);
- struct pdma_regs *regs = &chan->regs;
-
- dma_cookie_init(dchan);
- writel(PDMA_CLAIM_MASK, regs->ctrl);
-
- return 0;
-}
-
static void sf_pdma_disable_request(struct sf_pdma_chan *chan)
{
struct pdma_regs *regs = &chan->regs;
- writel(readl(regs->ctrl) & ~PDMA_RUN_MASK, regs->ctrl);
-}
-
-static void sf_pdma_free_chan_resources(struct dma_chan *dchan)
-{
- struct sf_pdma_chan *chan = to_sf_pdma_chan(dchan);
- unsigned long flags;
- LIST_HEAD(head);
+ writel(readl(regs->ctrl) & ~(PDMA_RUN_MASK |
+ PDMA_ENABLE_DONE_INT_MASK |
+ PDMA_ENABLE_ERR_INT_MASK),
+ regs->ctrl);
- spin_lock_irqsave(&chan->vchan.lock, flags);
- sf_pdma_disable_request(chan);
- kfree(chan->desc);
- chan->desc = NULL;
- vchan_get_all_descriptors(&chan->vchan, &head);
- sf_pdma_disclaim_chan(chan);
- spin_unlock_irqrestore(&chan->vchan.lock, flags);
- vchan_dma_desc_free_list(&chan->vchan, &head);
}
static size_t sf_pdma_desc_residue(struct sf_pdma_chan *chan,
@@ -486,12 +463,41 @@ static void sf_pdma_setup_chans(struct sf_pdma *pdma)
vchan_init(&chan->vchan, &pdma->dma_dev);
writel(PDMA_CLEAR_CTRL, chan->regs.ctrl);
-
- tasklet_setup(&chan->done_tasklet, sf_pdma_donebh_tasklet);
- tasklet_setup(&chan->err_tasklet, sf_pdma_errbh_tasklet);
}
}
+static int sf_pdma_alloc_chan_resources(struct dma_chan *dchan)
+{
+ struct sf_pdma_chan *chan = to_sf_pdma_chan(dchan);
+ struct pdma_regs *regs = &chan->regs;
+
+ dma_cookie_init(dchan);
+ writel(PDMA_CLAIM_MASK, regs->ctrl);
+
+ tasklet_setup(&chan->done_tasklet, sf_pdma_donebh_tasklet);
+ tasklet_setup(&chan->err_tasklet, sf_pdma_errbh_tasklet);
+
+ return 0;
+}
+
+static void sf_pdma_free_chan_resources(struct dma_chan *dchan)
+{
+ struct sf_pdma_chan *chan = to_sf_pdma_chan(dchan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+ sf_pdma_disable_request(chan);
+ tasklet_kill(&chan->done_tasklet);
+ tasklet_kill(&chan->err_tasklet);
+ kfree(chan->desc);
+ chan->desc = NULL;
+ vchan_get_all_descriptors(&chan->vchan, &head);
+ sf_pdma_disclaim_chan(chan);
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+ vchan_dma_desc_free_list(&chan->vchan, &head);
+}
+
static struct dma_chan *sf_pdma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
@@ -630,8 +636,6 @@ static int sf_pdma_remove(struct platform_device *pdev)
devm_free_irq(&pdev->dev, ch->errirq, ch);
list_del(&ch->vchan.chan.device_node);
tasklet_kill(&ch->vchan.task);
- tasklet_kill(&ch->done_tasklet);
- tasklet_kill(&ch->err_tasklet);
}
dma_async_device_unregister(&pdma->dma_dev);
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#16184):
https://lists.yoctoproject.org/g/linux-yocto/message/16184
Mute This Topic: https://lists.yoctoproject.org/mt/117277205/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-