]>
Commit | Line | Data |
---|---|---|
ba172962 SL |
1 | From efc5aa57f3bc5a93a3cc20b2489d8cb121539a6b Mon Sep 17 00:00:00 2001 |
2 | From: Shunyong Yang <shunyong.yang@hxt-semitech.com> | |
3 | Date: Mon, 7 Jan 2019 09:34:02 +0800 | |
4 | Subject: dmaengine: qcom_hidma: assign channel cookie correctly | |
5 | ||
6 | [ Upstream commit 546c0547555efca8ba8c120716c325435e29df1b ] | |
7 | ||
8 | When dma_cookie_complete() is called in hidma_process_completed(), | |
9 | dma_cookie_status() will return DMA_COMPLETE in hidma_tx_status(). Then, | |
10 | hidma_txn_is_success() will be called to use channel cookie | |
11 | mchan->last_success to do additional DMA status check. Current code | |
12 | assigns mchan->last_success after dma_cookie_complete(). This causes | |
13 | a race condition of dma_cookie_status() returns DMA_COMPLETE before | |
14 | mchan->last_success is assigned correctly. The race will cause | |
15 | hidma_tx_status() return DMA_ERROR but the transaction is actually a | |
16 | success. Moreover, in async_tx case, it will cause a timeout panic | |
17 | in async_tx_quiesce(). | |
18 | ||
19 | Kernel panic - not syncing: async_tx_quiesce: DMA error waiting for | |
20 | transaction | |
21 | ... | |
22 | Call trace: | |
23 | [<ffff000008089994>] dump_backtrace+0x0/0x1f4 | |
24 | [<ffff000008089bac>] show_stack+0x24/0x2c | |
25 | [<ffff00000891e198>] dump_stack+0x84/0xa8 | |
26 | [<ffff0000080da544>] panic+0x12c/0x29c | |
27 | [<ffff0000045d0334>] async_tx_quiesce+0xa4/0xc8 [async_tx] | |
28 | [<ffff0000045d03c8>] async_trigger_callback+0x70/0x1c0 [async_tx] | |
29 | [<ffff0000048b7d74>] raid_run_ops+0x86c/0x1540 [raid456] | |
30 | [<ffff0000048bd084>] handle_stripe+0x5e8/0x1c7c [raid456] | |
31 | [<ffff0000048be9ec>] handle_active_stripes.isra.45+0x2d4/0x550 [raid456] | |
32 | [<ffff0000048beff4>] raid5d+0x38c/0x5d0 [raid456] | |
33 | [<ffff000008736538>] md_thread+0x108/0x168 | |
34 | [<ffff0000080fb1cc>] kthread+0x10c/0x138 | |
35 | [<ffff000008084d34>] ret_from_fork+0x10/0x18 | |
36 | ||
37 | Cc: Joey Zheng <yu.zheng@hxt-semitech.com> | |
38 | Reviewed-by: Sinan Kaya <okaya@kernel.org> | |
39 | Signed-off-by: Shunyong Yang <shunyong.yang@hxt-semitech.com> | |
40 | Signed-off-by: Vinod Koul <vkoul@kernel.org> | |
41 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
42 | --- | |
43 | drivers/dma/qcom/hidma.c | 17 +++++++++-------- | |
44 | 1 file changed, 9 insertions(+), 8 deletions(-) | |
45 | ||
46 | diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c | |
47 | index 43d4b00b8138..ea219bca116d 100644 | |
48 | --- a/drivers/dma/qcom/hidma.c | |
49 | +++ b/drivers/dma/qcom/hidma.c | |
50 | @@ -138,24 +138,25 @@ static void hidma_process_completed(struct hidma_chan *mchan) | |
51 | desc = &mdesc->desc; | |
52 | last_cookie = desc->cookie; | |
53 | ||
54 | + llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); | |
55 | + | |
56 | spin_lock_irqsave(&mchan->lock, irqflags); | |
57 | + if (llstat == DMA_COMPLETE) { | |
58 | + mchan->last_success = last_cookie; | |
59 | + result.result = DMA_TRANS_NOERROR; | |
60 | + } else { | |
61 | + result.result = DMA_TRANS_ABORTED; | |
62 | + } | |
63 | + | |
64 | dma_cookie_complete(desc); | |
65 | spin_unlock_irqrestore(&mchan->lock, irqflags); | |
66 | ||
67 | - llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); | |
68 | dmaengine_desc_get_callback(desc, &cb); | |
69 | ||
70 | dma_run_dependencies(desc); | |
71 | ||
72 | spin_lock_irqsave(&mchan->lock, irqflags); | |
73 | list_move(&mdesc->node, &mchan->free); | |
74 | - | |
75 | - if (llstat == DMA_COMPLETE) { | |
76 | - mchan->last_success = last_cookie; | |
77 | - result.result = DMA_TRANS_NOERROR; | |
78 | - } else | |
79 | - result.result = DMA_TRANS_ABORTED; | |
80 | - | |
81 | spin_unlock_irqrestore(&mchan->lock, irqflags); | |
82 | ||
83 | dmaengine_desc_callback_invoke(&cb, &result); | |
84 | -- | |
85 | 2.19.1 | |
86 |