summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-toradex-rt-4.1-2.0.x/0003-Work-around-CPU-stalls-in-the-imx-sdma-driver.patch
blob: 93200c623971d43d1c3eacb18681c40504678de5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
From f7cba8d49a980909cea48c5b9dcfefc6e13fef0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominic=20Sacr=C3=A9?= <dominic.sacre@gmx.de>
Date: Fri, 29 Apr 2016 15:48:40 +0200
Subject: [PATCH] Work around CPU stalls in the imx-sdma driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace spinlocks with raw spinlocks. This prevents preemption during
the spinlock's critical section, as is the case on non PREEMPT_RT kernels.

Without this patch, the following error can occur, for example when
using the audio codec on an i.MX6Q SabreSD board:

INFO: rcu_preempt self-detected stall on CPU { 0}  (t=2100 jiffies g=106 c=105 q=93)
CPU: 0 PID: 120 Comm: irq/34-sdma Not tainted 3.14.28-rt25-1.0.0_ga+g91cf351 #1
[<80014a8c>] (unwind_backtrace) from [<8001173c>] (show_stack+0x10/0x14)
[<8001173c>] (show_stack) from [<806ee750>] (dump_stack+0x7c/0xc8)
[<806ee750>] (dump_stack) from [<800771c8>] (rcu_check_callbacks+0x454/0x888)
[<800771c8>] (rcu_check_callbacks) from [<80037f28>] (update_process_times+0x40/0x5c)
[<80037f28>] (update_process_times) from [<80082230>] (tick_sched_timer+0x4c/0x78)
[<80082230>] (tick_sched_timer) from [<8004bf30>] (__run_hrtimer.isra.34+0x74/0x124)
[<8004bf30>] (__run_hrtimer.isra.34) from [<8004cbb0>] (hrtimer_interrupt+0x154/0x3ac)
[<8004cbb0>] (hrtimer_interrupt) from [<80014464>] (twd_handler+0x30/0x38)
[<80014464>] (twd_handler) from [<8006fa2c>] (handle_percpu_devid_irq+0x6c/0x84)
[<8006fa2c>] (handle_percpu_devid_irq) from [<8006bc64>] (generic_handle_irq+0x2c/0x3c)
[<8006bc64>] (generic_handle_irq) from [<8000ed8c>] (handle_IRQ+0x40/0x90)
[<8000ed8c>] (handle_IRQ) from [<8000856c>] (gic_handle_irq+0x2c/0x5c)
[<8000856c>] (gic_handle_irq) from [<80012240>] (__irq_svc+0x40/0x84)
Exception stack(0xa840feb8 to 0xa840ff00)
fea0:                                                       a8007a28 00000002
fec0: 00000001 0000a6a6 a80079c0 a8007a28 a83ea080 00000000 a80079c0 a83ea080
fee0: 285190f0 00000000 00000000 a840ff00 8006d04c 806f3070 20030113 ffffffff
[<80012240>] (__irq_svc) from [<806f3070>] (_raw_spin_unlock_irq+0x20/0x60)
[<806f3070>] (_raw_spin_unlock_irq) from [<8006d04c>] (irq_finalize_oneshot.part.37+0x70/0xcc)
[<8006d04c>] (irq_finalize_oneshot.part.37) from [<8006d148>] (irq_forced_thread_fn+0x60/0x64)
[<8006d148>] (irq_forced_thread_fn) from [<8006d3dc>] (irq_thread+0x138/0x1a4)
[<8006d3dc>] (irq_thread) from [<8004913c>] (kthread+0xbc/0xd4)
[<8004913c>] (kthread) from [<8000e538>] (ret_from_fork+0x14/0x3c)

Upstream-Status: Pending

Signed-off-by: Dominic Sacré <dominic.sacre@gmx.de>
---
 drivers/dma/imx-sdma.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 31b7fed..bb7d6aa 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -408,7 +408,7 @@ struct sdma_engine {
 	struct dma_device		dma_device;
 	struct clk			*clk_ipg;
 	struct clk			*clk_ahb;
-	spinlock_t			channel_0_lock;
+	raw_spinlock_t			channel_0_lock;
 	u32				script_number;
 	struct sdma_script_start_addrs	*script_addrs;
 	const struct sdma_driver_data	*drvdata;
@@ -700,7 +700,7 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
 			return -ENOMEM;
 	}
 
-	spin_lock_irqsave(&sdma->channel_0_lock, flags);
+	raw_spin_lock_irqsave(&sdma->channel_0_lock, flags);
 
 	bd0->mode.command = C0_SETPM;
 	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -712,7 +712,7 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
 
 	ret = sdma_run_channel0(sdma);
 
-	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
+	raw_spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
 
 	if (use_iram)
 		gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size);
@@ -979,7 +979,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 	dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", (u32)sdmac->event_mask[0]);
 	dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", (u32)sdmac->event_mask[1]);
 
-	spin_lock_irqsave(&sdma->channel_0_lock, flags);
+	raw_spin_lock_irqsave(&sdma->channel_0_lock, flags);
 
 	memset(context, 0, sizeof(*context));
 	context->channel_state.pc = load_address;
@@ -1005,7 +1005,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 	bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel;
 	ret = sdma_run_channel0(sdma);
 
-	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
+	raw_spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
 
 	sdmac->context_loaded = true;
 
@@ -1019,7 +1019,7 @@ static int sdma_save_restore_context(struct sdma_engine *sdma, bool save)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&sdma->channel_0_lock, flags);
+	raw_spin_lock_irqsave(&sdma->channel_0_lock, flags);
 
 	if (save)
 		bd0->mode.command = C0_GETDM;
@@ -1032,7 +1032,7 @@ static int sdma_save_restore_context(struct sdma_engine *sdma, bool save)
 	bd0->ext_buffer_addr = 2048;
 	ret = sdma_run_channel0(sdma);
 
-	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
+	raw_spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
 
 	return ret;
 }
@@ -2152,7 +2152,7 @@ static int sdma_probe(struct platform_device *pdev)
 	if (!sdma)
 		return -ENOMEM;
 
-	spin_lock_init(&sdma->channel_0_lock);
+	raw_spin_lock_init(&sdma->channel_0_lock);
 
 	sdma->dev = &pdev->dev;
 	sdma->drvdata = drvdata;
-- 
2.8.1