]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.0.19/clk-sunxi-ng-nkmp-avoid-genmask-1-0.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 5.0.19 / clk-sunxi-ng-nkmp-avoid-genmask-1-0.patch
1 From 00437ac333d0524346793b5cdd834316f5bcfdf1 Mon Sep 17 00:00:00 2001
2 From: Jernej Skrabec <jernej.skrabec@siol.net>
3 Date: Tue, 2 Apr 2019 23:06:21 +0200
4 Subject: clk: sunxi-ng: nkmp: Avoid GENMASK(-1, 0)
5
6 [ Upstream commit 2abc330c514fe56c570bb1a6318b054b06a4f72e ]
7
8 Sometimes one of the nkmp factors is unused. This means that one of the
9 factors shift and width values are set to 0. Current nkmp clock code
10 generates a mask for each factor with GENMASK(width + shift - 1, shift).
11 For unused factor this translates to GENMASK(-1, 0). This code is
12 further expanded by C preprocessor to final version:
13 (((~0UL) - (1UL << (0)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (-1))))
14 or a bit simplified:
15 (~0UL & (~0UL >> BITS_PER_LONG))
16
17 It turns out that result of the second part (~0UL >> BITS_PER_LONG) is
18 actually undefined by C standard, which clearly specifies:
19
20 "If the value of the right operand is negative or is greater than or
21 equal to the width of the promoted left operand, the behavior is
22 undefined."
23
24 Additionally, compiling kernel with aarch64-linux-gnu-gcc 8.3.0 gave
25 different results whether literals or variables with same values as
26 literals were used. GENMASK with literals -1 and 0 gives zero and with
27 variables gives 0xFFFFFFFFFFFFFFF (~0UL). Because nkmp driver uses
28 GENMASK with variables as parameter, expression calculates mask as ~0UL
29 instead of 0. This has further consequences that LSB in register is
30 always set to 1 (1 is neutral value for a factor and shift is 0).
31
32 For example, H6 pll-de clock is set to 600 MHz by sun4i-drm driver, but
33 due to this bug ends up being 300 MHz. Additionally, 300 MHz seems to be
34 too low because following warning can be found in dmesg:
35
36 [ 1.752763] WARNING: CPU: 2 PID: 41 at drivers/clk/sunxi-ng/ccu_common.c:41 ccu_helper_wait_for_lock.part.0+0x6c/0x90
37 [ 1.763378] Modules linked in:
38 [ 1.766441] CPU: 2 PID: 41 Comm: kworker/2:1 Not tainted 5.1.0-rc2-next-20190401 #138
39 [ 1.774269] Hardware name: Pine H64 (DT)
40 [ 1.778200] Workqueue: events deferred_probe_work_func
41 [ 1.783341] pstate: 40000005 (nZcv daif -PAN -UAO)
42 [ 1.788135] pc : ccu_helper_wait_for_lock.part.0+0x6c/0x90
43 [ 1.793623] lr : ccu_helper_wait_for_lock.part.0+0x48/0x90
44 [ 1.799107] sp : ffff000010f93840
45 [ 1.802422] x29: ffff000010f93840 x28: 0000000000000000
46 [ 1.807735] x27: ffff800073ce9d80 x26: ffff000010afd1b8
47 [ 1.813049] x25: ffffffffffffffff x24: 00000000ffffffff
48 [ 1.818362] x23: 0000000000000001 x22: ffff000010abd5c8
49 [ 1.823675] x21: 0000000010000000 x20: 00000000685f367e
50 [ 1.828987] x19: 0000000000001801 x18: 0000000000000001
51 [ 1.834300] x17: 0000000000000001 x16: 0000000000000000
52 [ 1.839613] x15: 0000000000000000 x14: ffff000010789858
53 [ 1.844926] x13: 0000000000000000 x12: 0000000000000001
54 [ 1.850239] x11: 0000000000000000 x10: 0000000000000970
55 [ 1.855551] x9 : ffff000010f936c0 x8 : ffff800074cec0d0
56 [ 1.860864] x7 : 0000800067117000 x6 : 0000000115c30b41
57 [ 1.866177] x5 : 00ffffffffffffff x4 : 002c959300bfe500
58 [ 1.871490] x3 : 0000000000000018 x2 : 0000000029aaaaab
59 [ 1.876802] x1 : 00000000000002e6 x0 : 00000000686072bc
60 [ 1.882114] Call trace:
61 [ 1.884565] ccu_helper_wait_for_lock.part.0+0x6c/0x90
62 [ 1.889705] ccu_helper_wait_for_lock+0x10/0x20
63 [ 1.894236] ccu_nkmp_set_rate+0x244/0x2a8
64 [ 1.898334] clk_change_rate+0x144/0x290
65 [ 1.902258] clk_core_set_rate_nolock+0x180/0x1b8
66 [ 1.906963] clk_set_rate+0x34/0xa0
67 [ 1.910455] sun8i_mixer_bind+0x484/0x558
68 [ 1.914466] component_bind_all+0x10c/0x230
69 [ 1.918651] sun4i_drv_bind+0xc4/0x1a0
70 [ 1.922401] try_to_bring_up_master+0x164/0x1c0
71 [ 1.926932] __component_add+0xa0/0x168
72 [ 1.930769] component_add+0x10/0x18
73 [ 1.934346] sun8i_dw_hdmi_probe+0x18/0x20
74 [ 1.938443] platform_drv_probe+0x50/0xa0
75 [ 1.942455] really_probe+0xcc/0x280
76 [ 1.946032] driver_probe_device+0x54/0xe8
77 [ 1.950130] __device_attach_driver+0x80/0xb8
78 [ 1.954488] bus_for_each_drv+0x78/0xc8
79 [ 1.958326] __device_attach+0xd4/0x130
80 [ 1.962163] device_initial_probe+0x10/0x18
81 [ 1.966348] bus_probe_device+0x90/0x98
82 [ 1.970185] deferred_probe_work_func+0x6c/0xa0
83 [ 1.974720] process_one_work+0x1e0/0x320
84 [ 1.978732] worker_thread+0x228/0x428
85 [ 1.982484] kthread+0x120/0x128
86 [ 1.985714] ret_from_fork+0x10/0x18
87 [ 1.989290] ---[ end trace 9babd42e1ca4b84f ]---
88
89 This commit solves the issue by first checking value of the factor
90 width. If it is equal to 0 (unused factor), mask is set to 0, otherwise
91 GENMASK() macro is used as before.
92
93 Fixes: d897ef56faf9 ("clk: sunxi-ng: Mask nkmp factors when setting register")
94 Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
95 Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
96 Signed-off-by: Sasha Levin <sashal@kernel.org>
97 ---
98 drivers/clk/sunxi-ng/ccu_nkmp.c | 18 +++++++++++++-----
99 1 file changed, 13 insertions(+), 5 deletions(-)
100
101 diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
102 index 9b49adb20d07c..69dfc6de1c4e6 100644
103 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c
104 +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
105 @@ -167,7 +167,7 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
106 unsigned long parent_rate)
107 {
108 struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
109 - u32 n_mask, k_mask, m_mask, p_mask;
110 + u32 n_mask = 0, k_mask = 0, m_mask = 0, p_mask = 0;
111 struct _ccu_nkmp _nkmp;
112 unsigned long flags;
113 u32 reg;
114 @@ -186,10 +186,18 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
115
116 ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
117
118 - n_mask = GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift);
119 - k_mask = GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift);
120 - m_mask = GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift);
121 - p_mask = GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift);
122 + if (nkmp->n.width)
123 + n_mask = GENMASK(nkmp->n.width + nkmp->n.shift - 1,
124 + nkmp->n.shift);
125 + if (nkmp->k.width)
126 + k_mask = GENMASK(nkmp->k.width + nkmp->k.shift - 1,
127 + nkmp->k.shift);
128 + if (nkmp->m.width)
129 + m_mask = GENMASK(nkmp->m.width + nkmp->m.shift - 1,
130 + nkmp->m.shift);
131 + if (nkmp->p.width)
132 + p_mask = GENMASK(nkmp->p.width + nkmp->p.shift - 1,
133 + nkmp->p.shift);
134
135 spin_lock_irqsave(nkmp->common.lock, flags);
136
137 --
138 2.20.1
139