1 |
commit: f258dc76d3adedc729b5b395b42dbbd8a4cb6a71 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jul 11 14:42:03 2021 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jul 11 14:42:03 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=f258dc76 |
7 |
|
8 |
Linux patch 5.12.16 |
9 |
|
10 |
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> |
11 |
|
12 |
0000_README | 4 + |
13 |
1015_linux-5.12.16.patch | 1016 ++++++++++++++++++++++++++++++++++++++++++++++ |
14 |
2 files changed, 1020 insertions(+) |
15 |
|
16 |
diff --git a/0000_README b/0000_README |
17 |
index 7954680..279298d 100644 |
18 |
--- a/0000_README |
19 |
+++ b/0000_README |
20 |
@@ -103,6 +103,10 @@ Patch: 1014_linux-5.12.15.patch |
21 |
From: http://www.kernel.org |
22 |
Desc: Linux 5.12.15 |
23 |
|
24 |
+Patch: 1015_linux-5.12.16.patch |
25 |
+From: http://www.kernel.org |
26 |
+Desc: Linux 5.12.16 |
27 |
+ |
28 |
Patch: 1500_XATTR_USER_PREFIX.patch |
29 |
From: https://bugs.gentoo.org/show_bug.cgi?id=470644 |
30 |
Desc: Support for namespace user.pax.* on tmpfs. |
31 |
|
32 |
diff --git a/1015_linux-5.12.16.patch b/1015_linux-5.12.16.patch |
33 |
new file mode 100644 |
34 |
index 0000000..5f03442 |
35 |
--- /dev/null |
36 |
+++ b/1015_linux-5.12.16.patch |
37 |
@@ -0,0 +1,1016 @@ |
38 |
+diff --git a/Makefile b/Makefile |
39 |
+index 09e1a0967bab7..bf6accb2328c3 100644 |
40 |
+--- a/Makefile |
41 |
++++ b/Makefile |
42 |
+@@ -1,7 +1,7 @@ |
43 |
+ # SPDX-License-Identifier: GPL-2.0 |
44 |
+ VERSION = 5 |
45 |
+ PATCHLEVEL = 12 |
46 |
+-SUBLEVEL = 15 |
47 |
++SUBLEVEL = 16 |
48 |
+ EXTRAVERSION = |
49 |
+ NAME = Frozen Wasteland |
50 |
+ |
51 |
+diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile |
52 |
+index c168c6980d050..74b644ea8a00a 100644 |
53 |
+--- a/arch/hexagon/Makefile |
54 |
++++ b/arch/hexagon/Makefile |
55 |
+@@ -10,6 +10,9 @@ LDFLAGS_vmlinux += -G0 |
56 |
+ # Do not use single-byte enums; these will overflow. |
57 |
+ KBUILD_CFLAGS += -fno-short-enums |
58 |
+ |
59 |
++# We must use long-calls: |
60 |
++KBUILD_CFLAGS += -mlong-calls |
61 |
++ |
62 |
+ # Modules must use either long-calls, or use pic/plt. |
63 |
+ # Use long-calls for now, it's easier. And faster. |
64 |
+ # KBUILD_CFLAGS_MODULE += -fPIC |
65 |
+@@ -30,9 +33,6 @@ TIR_NAME := r19 |
66 |
+ KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__ |
67 |
+ KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME) |
68 |
+ |
69 |
+-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name 2>/dev/null) |
70 |
+-libs-y += $(LIBGCC) |
71 |
+- |
72 |
+ head-y := arch/hexagon/kernel/head.o |
73 |
+ |
74 |
+ core-y += arch/hexagon/kernel/ \ |
75 |
+diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h |
76 |
+index 6b9c554aee78e..9fb00a0ae89f7 100644 |
77 |
+--- a/arch/hexagon/include/asm/futex.h |
78 |
++++ b/arch/hexagon/include/asm/futex.h |
79 |
+@@ -21,7 +21,7 @@ |
80 |
+ "3:\n" \ |
81 |
+ ".section .fixup,\"ax\"\n" \ |
82 |
+ "4: %1 = #%5;\n" \ |
83 |
+- " jump 3b\n" \ |
84 |
++ " jump ##3b\n" \ |
85 |
+ ".previous\n" \ |
86 |
+ ".section __ex_table,\"a\"\n" \ |
87 |
+ ".long 1b,4b,2b,4b\n" \ |
88 |
+@@ -90,7 +90,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, |
89 |
+ "3:\n" |
90 |
+ ".section .fixup,\"ax\"\n" |
91 |
+ "4: %0 = #%6\n" |
92 |
+- " jump 3b\n" |
93 |
++ " jump ##3b\n" |
94 |
+ ".previous\n" |
95 |
+ ".section __ex_table,\"a\"\n" |
96 |
+ ".long 1b,4b,2b,4b\n" |
97 |
+diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h |
98 |
+index 78338d8ada83f..8d4ec76fceb45 100644 |
99 |
+--- a/arch/hexagon/include/asm/timex.h |
100 |
++++ b/arch/hexagon/include/asm/timex.h |
101 |
+@@ -8,6 +8,7 @@ |
102 |
+ |
103 |
+ #include <asm-generic/timex.h> |
104 |
+ #include <asm/timer-regs.h> |
105 |
++#include <asm/hexagon_vm.h> |
106 |
+ |
107 |
+ /* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */ |
108 |
+ #define CLOCK_TICK_RATE TCX0_CLK_RATE |
109 |
+@@ -16,7 +17,7 @@ |
110 |
+ |
111 |
+ static inline int read_current_timer(unsigned long *timer_val) |
112 |
+ { |
113 |
+- *timer_val = (unsigned long) __vmgettime(); |
114 |
++ *timer_val = __vmgettime(); |
115 |
+ return 0; |
116 |
+ } |
117 |
+ |
118 |
+diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c |
119 |
+index 6fb1aaab1c298..35545a7386a06 100644 |
120 |
+--- a/arch/hexagon/kernel/hexagon_ksyms.c |
121 |
++++ b/arch/hexagon/kernel/hexagon_ksyms.c |
122 |
+@@ -35,8 +35,8 @@ EXPORT_SYMBOL(_dflt_cache_att); |
123 |
+ DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes); |
124 |
+ |
125 |
+ /* Additional functions */ |
126 |
+-DECLARE_EXPORT(__divsi3); |
127 |
+-DECLARE_EXPORT(__modsi3); |
128 |
+-DECLARE_EXPORT(__udivsi3); |
129 |
+-DECLARE_EXPORT(__umodsi3); |
130 |
++DECLARE_EXPORT(__hexagon_divsi3); |
131 |
++DECLARE_EXPORT(__hexagon_modsi3); |
132 |
++DECLARE_EXPORT(__hexagon_udivsi3); |
133 |
++DECLARE_EXPORT(__hexagon_umodsi3); |
134 |
+ DECLARE_EXPORT(csum_tcpudp_magic); |
135 |
+diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c |
136 |
+index a5a89e944257c..8975f9b4cedf0 100644 |
137 |
+--- a/arch/hexagon/kernel/ptrace.c |
138 |
++++ b/arch/hexagon/kernel/ptrace.c |
139 |
+@@ -35,7 +35,7 @@ void user_disable_single_step(struct task_struct *child) |
140 |
+ |
141 |
+ static int genregs_get(struct task_struct *target, |
142 |
+ const struct user_regset *regset, |
143 |
+- srtuct membuf to) |
144 |
++ struct membuf to) |
145 |
+ { |
146 |
+ struct pt_regs *regs = task_pt_regs(target); |
147 |
+ |
148 |
+@@ -54,7 +54,7 @@ static int genregs_get(struct task_struct *target, |
149 |
+ membuf_store(&to, regs->m0); |
150 |
+ membuf_store(&to, regs->m1); |
151 |
+ membuf_store(&to, regs->usr); |
152 |
+- membuf_store(&to, regs->p3_0); |
153 |
++ membuf_store(&to, regs->preds); |
154 |
+ membuf_store(&to, regs->gp); |
155 |
+ membuf_store(&to, regs->ugp); |
156 |
+ membuf_store(&to, pt_elr(regs)); // pc |
157 |
+diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile |
158 |
+index 54be529d17a25..a64641e89d5fe 100644 |
159 |
+--- a/arch/hexagon/lib/Makefile |
160 |
++++ b/arch/hexagon/lib/Makefile |
161 |
+@@ -2,4 +2,5 @@ |
162 |
+ # |
163 |
+ # Makefile for hexagon-specific library files. |
164 |
+ # |
165 |
+-obj-y = checksum.o io.o memcpy.o memset.o |
166 |
++obj-y = checksum.o io.o memcpy.o memset.o memcpy_likely_aligned.o \ |
167 |
++ divsi3.o modsi3.o udivsi3.o umodsi3.o |
168 |
+diff --git a/arch/hexagon/lib/divsi3.S b/arch/hexagon/lib/divsi3.S |
169 |
+new file mode 100644 |
170 |
+index 0000000000000..783e09424c2c8 |
171 |
+--- /dev/null |
172 |
++++ b/arch/hexagon/lib/divsi3.S |
173 |
+@@ -0,0 +1,67 @@ |
174 |
++/* SPDX-License-Identifier: GPL-2.0-only */ |
175 |
++/* |
176 |
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
177 |
++ */ |
178 |
++ |
179 |
++#include <linux/linkage.h> |
180 |
++ |
181 |
++SYM_FUNC_START(__hexagon_divsi3) |
182 |
++ { |
183 |
++ p0 = cmp.gt(r0,#-1) |
184 |
++ p1 = cmp.gt(r1,#-1) |
185 |
++ r3:2 = vabsw(r1:0) |
186 |
++ } |
187 |
++ { |
188 |
++ p3 = xor(p0,p1) |
189 |
++ r4 = sub(r2,r3) |
190 |
++ r6 = cl0(r2) |
191 |
++ p0 = cmp.gtu(r3,r2) |
192 |
++ } |
193 |
++ { |
194 |
++ r0 = mux(p3,#-1,#1) |
195 |
++ r7 = cl0(r3) |
196 |
++ p1 = cmp.gtu(r3,r4) |
197 |
++ } |
198 |
++ { |
199 |
++ r0 = mux(p0,#0,r0) |
200 |
++ p0 = or(p0,p1) |
201 |
++ if (p0.new) jumpr:nt r31 |
202 |
++ r6 = sub(r7,r6) |
203 |
++ } |
204 |
++ { |
205 |
++ r7 = r6 |
206 |
++ r5:4 = combine(#1,r3) |
207 |
++ r6 = add(#1,lsr(r6,#1)) |
208 |
++ p0 = cmp.gtu(r6,#4) |
209 |
++ } |
210 |
++ { |
211 |
++ r5:4 = vaslw(r5:4,r7) |
212 |
++ if (!p0) r6 = #3 |
213 |
++ } |
214 |
++ { |
215 |
++ loop0(1f,r6) |
216 |
++ r7:6 = vlsrw(r5:4,#1) |
217 |
++ r1:0 = #0 |
218 |
++ } |
219 |
++ .falign |
220 |
++1: |
221 |
++ { |
222 |
++ r5:4 = vlsrw(r5:4,#2) |
223 |
++ if (!p0.new) r0 = add(r0,r5) |
224 |
++ if (!p0.new) r2 = sub(r2,r4) |
225 |
++ p0 = cmp.gtu(r4,r2) |
226 |
++ } |
227 |
++ { |
228 |
++ r7:6 = vlsrw(r7:6,#2) |
229 |
++ if (!p0.new) r0 = add(r0,r7) |
230 |
++ if (!p0.new) r2 = sub(r2,r6) |
231 |
++ p0 = cmp.gtu(r6,r2) |
232 |
++ }:endloop0 |
233 |
++ { |
234 |
++ if (!p0) r0 = add(r0,r7) |
235 |
++ } |
236 |
++ { |
237 |
++ if (p3) r0 = sub(r1,r0) |
238 |
++ jumpr r31 |
239 |
++ } |
240 |
++SYM_FUNC_END(__hexagon_divsi3) |
241 |
+diff --git a/arch/hexagon/lib/memcpy_likely_aligned.S b/arch/hexagon/lib/memcpy_likely_aligned.S |
242 |
+new file mode 100644 |
243 |
+index 0000000000000..6a541fb90a540 |
244 |
+--- /dev/null |
245 |
++++ b/arch/hexagon/lib/memcpy_likely_aligned.S |
246 |
+@@ -0,0 +1,56 @@ |
247 |
++/* SPDX-License-Identifier: GPL-2.0-only */ |
248 |
++/* |
249 |
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
250 |
++ */ |
251 |
++ |
252 |
++#include <linux/linkage.h> |
253 |
++ |
254 |
++SYM_FUNC_START(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes) |
255 |
++ { |
256 |
++ p0 = bitsclr(r1,#7) |
257 |
++ p0 = bitsclr(r0,#7) |
258 |
++ if (p0.new) r5:4 = memd(r1) |
259 |
++ if (p0.new) r7:6 = memd(r1+#8) |
260 |
++ } |
261 |
++ { |
262 |
++ if (!p0) jump:nt .Lmemcpy_call |
263 |
++ if (p0) r9:8 = memd(r1+#16) |
264 |
++ if (p0) r11:10 = memd(r1+#24) |
265 |
++ p0 = cmp.gtu(r2,#64) |
266 |
++ } |
267 |
++ { |
268 |
++ if (p0) jump:nt .Lmemcpy_call |
269 |
++ if (!p0) memd(r0) = r5:4 |
270 |
++ if (!p0) memd(r0+#8) = r7:6 |
271 |
++ p0 = cmp.gtu(r2,#32) |
272 |
++ } |
273 |
++ { |
274 |
++ p1 = cmp.gtu(r2,#40) |
275 |
++ p2 = cmp.gtu(r2,#48) |
276 |
++ if (p0) r13:12 = memd(r1+#32) |
277 |
++ if (p1.new) r15:14 = memd(r1+#40) |
278 |
++ } |
279 |
++ { |
280 |
++ memd(r0+#16) = r9:8 |
281 |
++ memd(r0+#24) = r11:10 |
282 |
++ } |
283 |
++ { |
284 |
++ if (p0) memd(r0+#32) = r13:12 |
285 |
++ if (p1) memd(r0+#40) = r15:14 |
286 |
++ if (!p2) jumpr:t r31 |
287 |
++ } |
288 |
++ { |
289 |
++ p0 = cmp.gtu(r2,#56) |
290 |
++ r5:4 = memd(r1+#48) |
291 |
++ if (p0.new) r7:6 = memd(r1+#56) |
292 |
++ } |
293 |
++ { |
294 |
++ memd(r0+#48) = r5:4 |
295 |
++ if (p0) memd(r0+#56) = r7:6 |
296 |
++ jumpr r31 |
297 |
++ } |
298 |
++ |
299 |
++.Lmemcpy_call: |
300 |
++ jump memcpy |
301 |
++ |
302 |
++SYM_FUNC_END(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes) |
303 |
+diff --git a/arch/hexagon/lib/modsi3.S b/arch/hexagon/lib/modsi3.S |
304 |
+new file mode 100644 |
305 |
+index 0000000000000..9ea1c86efac2b |
306 |
+--- /dev/null |
307 |
++++ b/arch/hexagon/lib/modsi3.S |
308 |
+@@ -0,0 +1,46 @@ |
309 |
++/* SPDX-License-Identifier: GPL-2.0-only */ |
310 |
++/* |
311 |
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
312 |
++ */ |
313 |
++ |
314 |
++#include <linux/linkage.h> |
315 |
++ |
316 |
++SYM_FUNC_START(__hexagon_modsi3) |
317 |
++ { |
318 |
++ p2 = cmp.ge(r0,#0) |
319 |
++ r2 = abs(r0) |
320 |
++ r1 = abs(r1) |
321 |
++ } |
322 |
++ { |
323 |
++ r3 = cl0(r2) |
324 |
++ r4 = cl0(r1) |
325 |
++ p0 = cmp.gtu(r1,r2) |
326 |
++ } |
327 |
++ { |
328 |
++ r3 = sub(r4,r3) |
329 |
++ if (p0) jumpr r31 |
330 |
++ } |
331 |
++ { |
332 |
++ p1 = cmp.eq(r3,#0) |
333 |
++ loop0(1f,r3) |
334 |
++ r0 = r2 |
335 |
++ r2 = lsl(r1,r3) |
336 |
++ } |
337 |
++ .falign |
338 |
++1: |
339 |
++ { |
340 |
++ p0 = cmp.gtu(r2,r0) |
341 |
++ if (!p0.new) r0 = sub(r0,r2) |
342 |
++ r2 = lsr(r2,#1) |
343 |
++ if (p1) r1 = #0 |
344 |
++ }:endloop0 |
345 |
++ { |
346 |
++ p0 = cmp.gtu(r2,r0) |
347 |
++ if (!p0.new) r0 = sub(r0,r1) |
348 |
++ if (p2) jumpr r31 |
349 |
++ } |
350 |
++ { |
351 |
++ r0 = neg(r0) |
352 |
++ jumpr r31 |
353 |
++ } |
354 |
++SYM_FUNC_END(__hexagon_modsi3) |
355 |
+diff --git a/arch/hexagon/lib/udivsi3.S b/arch/hexagon/lib/udivsi3.S |
356 |
+new file mode 100644 |
357 |
+index 0000000000000..477f27b9311cd |
358 |
+--- /dev/null |
359 |
++++ b/arch/hexagon/lib/udivsi3.S |
360 |
+@@ -0,0 +1,38 @@ |
361 |
++/* SPDX-License-Identifier: GPL-2.0-only */ |
362 |
++/* |
363 |
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
364 |
++ */ |
365 |
++ |
366 |
++#include <linux/linkage.h> |
367 |
++ |
368 |
++SYM_FUNC_START(__hexagon_udivsi3) |
369 |
++ { |
370 |
++ r2 = cl0(r0) |
371 |
++ r3 = cl0(r1) |
372 |
++ r5:4 = combine(#1,#0) |
373 |
++ p0 = cmp.gtu(r1,r0) |
374 |
++ } |
375 |
++ { |
376 |
++ r6 = sub(r3,r2) |
377 |
++ r4 = r1 |
378 |
++ r1:0 = combine(r0,r4) |
379 |
++ if (p0) jumpr r31 |
380 |
++ } |
381 |
++ { |
382 |
++ r3:2 = vlslw(r5:4,r6) |
383 |
++ loop0(1f,r6) |
384 |
++ } |
385 |
++ .falign |
386 |
++1: |
387 |
++ { |
388 |
++ p0 = cmp.gtu(r2,r1) |
389 |
++ if (!p0.new) r1 = sub(r1,r2) |
390 |
++ if (!p0.new) r0 = add(r0,r3) |
391 |
++ r3:2 = vlsrw(r3:2,#1) |
392 |
++ }:endloop0 |
393 |
++ { |
394 |
++ p0 = cmp.gtu(r2,r1) |
395 |
++ if (!p0.new) r0 = add(r0,r3) |
396 |
++ jumpr r31 |
397 |
++ } |
398 |
++SYM_FUNC_END(__hexagon_udivsi3) |
399 |
+diff --git a/arch/hexagon/lib/umodsi3.S b/arch/hexagon/lib/umodsi3.S |
400 |
+new file mode 100644 |
401 |
+index 0000000000000..280bf06a55e7d |
402 |
+--- /dev/null |
403 |
++++ b/arch/hexagon/lib/umodsi3.S |
404 |
+@@ -0,0 +1,36 @@ |
405 |
++/* SPDX-License-Identifier: GPL-2.0-only */ |
406 |
++/* |
407 |
++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. |
408 |
++ */ |
409 |
++ |
410 |
++#include <linux/linkage.h> |
411 |
++ |
412 |
++SYM_FUNC_START(__hexagon_umodsi3) |
413 |
++ { |
414 |
++ r2 = cl0(r0) |
415 |
++ r3 = cl0(r1) |
416 |
++ p0 = cmp.gtu(r1,r0) |
417 |
++ } |
418 |
++ { |
419 |
++ r2 = sub(r3,r2) |
420 |
++ if (p0) jumpr r31 |
421 |
++ } |
422 |
++ { |
423 |
++ loop0(1f,r2) |
424 |
++ p1 = cmp.eq(r2,#0) |
425 |
++ r2 = lsl(r1,r2) |
426 |
++ } |
427 |
++ .falign |
428 |
++1: |
429 |
++ { |
430 |
++ p0 = cmp.gtu(r2,r0) |
431 |
++ if (!p0.new) r0 = sub(r0,r2) |
432 |
++ r2 = lsr(r2,#1) |
433 |
++ if (p1) r1 = #0 |
434 |
++ }:endloop0 |
435 |
++ { |
436 |
++ p0 = cmp.gtu(r2,r0) |
437 |
++ if (!p0.new) r0 = sub(r0,r1) |
438 |
++ jumpr r31 |
439 |
++ } |
440 |
++SYM_FUNC_END(__hexagon_umodsi3) |
441 |
+diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c |
442 |
+index 7196fa9047e6d..426787f4b2ae4 100644 |
443 |
+--- a/drivers/net/wireless/mediatek/mt76/dma.c |
444 |
++++ b/drivers/net/wireless/mediatek/mt76/dma.c |
445 |
+@@ -79,13 +79,38 @@ mt76_free_pending_txwi(struct mt76_dev *dev) |
446 |
+ local_bh_enable(); |
447 |
+ } |
448 |
+ |
449 |
++static void |
450 |
++mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) |
451 |
++{ |
452 |
++ writel(q->desc_dma, &q->regs->desc_base); |
453 |
++ writel(q->ndesc, &q->regs->ring_size); |
454 |
++ q->head = readl(&q->regs->dma_idx); |
455 |
++ q->tail = q->head; |
456 |
++} |
457 |
++ |
458 |
++static void |
459 |
++mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) |
460 |
++{ |
461 |
++ int i; |
462 |
++ |
463 |
++ if (!q) |
464 |
++ return; |
465 |
++ |
466 |
++ /* clear descriptors */ |
467 |
++ for (i = 0; i < q->ndesc; i++) |
468 |
++ q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); |
469 |
++ |
470 |
++ writel(0, &q->regs->cpu_idx); |
471 |
++ writel(0, &q->regs->dma_idx); |
472 |
++ mt76_dma_sync_idx(dev, q); |
473 |
++} |
474 |
++ |
475 |
+ static int |
476 |
+ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, |
477 |
+ int idx, int n_desc, int bufsize, |
478 |
+ u32 ring_base) |
479 |
+ { |
480 |
+ int size; |
481 |
+- int i; |
482 |
+ |
483 |
+ spin_lock_init(&q->lock); |
484 |
+ spin_lock_init(&q->cleanup_lock); |
485 |
+@@ -105,14 +130,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, |
486 |
+ if (!q->entry) |
487 |
+ return -ENOMEM; |
488 |
+ |
489 |
+- /* clear descriptors */ |
490 |
+- for (i = 0; i < q->ndesc; i++) |
491 |
+- q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); |
492 |
+- |
493 |
+- writel(q->desc_dma, &q->regs->desc_base); |
494 |
+- writel(0, &q->regs->cpu_idx); |
495 |
+- writel(0, &q->regs->dma_idx); |
496 |
+- writel(q->ndesc, &q->regs->ring_size); |
497 |
++ mt76_dma_queue_reset(dev, q); |
498 |
+ |
499 |
+ return 0; |
500 |
+ } |
501 |
+@@ -201,15 +219,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, |
502 |
+ memset(e, 0, sizeof(*e)); |
503 |
+ } |
504 |
+ |
505 |
+-static void |
506 |
+-mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) |
507 |
+-{ |
508 |
+- writel(q->desc_dma, &q->regs->desc_base); |
509 |
+- writel(q->ndesc, &q->regs->ring_size); |
510 |
+- q->head = readl(&q->regs->dma_idx); |
511 |
+- q->tail = q->head; |
512 |
+-} |
513 |
+- |
514 |
+ static void |
515 |
+ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) |
516 |
+ { |
517 |
+@@ -640,9 +649,11 @@ mt76_dma_init(struct mt76_dev *dev) |
518 |
+ static const struct mt76_queue_ops mt76_dma_ops = { |
519 |
+ .init = mt76_dma_init, |
520 |
+ .alloc = mt76_dma_alloc_queue, |
521 |
++ .reset_q = mt76_dma_queue_reset, |
522 |
+ .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, |
523 |
+ .tx_queue_skb = mt76_dma_tx_queue_skb, |
524 |
+ .tx_cleanup = mt76_dma_tx_cleanup, |
525 |
++ .rx_cleanup = mt76_dma_rx_cleanup, |
526 |
+ .rx_reset = mt76_dma_rx_reset, |
527 |
+ .kick = mt76_dma_kick_queue, |
528 |
+ }; |
529 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h |
530 |
+index 36a430f09f64c..967fe3e11d94e 100644 |
531 |
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h |
532 |
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h |
533 |
+@@ -190,7 +190,11 @@ struct mt76_queue_ops { |
534 |
+ void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q, |
535 |
+ bool flush); |
536 |
+ |
537 |
++ void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q); |
538 |
++ |
539 |
+ void (*kick)(struct mt76_dev *dev, struct mt76_queue *q); |
540 |
++ |
541 |
++ void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q); |
542 |
+ }; |
543 |
+ |
544 |
+ enum mt76_wcid_flags { |
545 |
+@@ -784,8 +788,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev) |
546 |
+ #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) |
547 |
+ #define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__) |
548 |
+ #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) |
549 |
+-#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) |
550 |
++#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) |
551 |
++#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__) |
552 |
+ #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) |
553 |
++#define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__) |
554 |
+ |
555 |
+ #define mt76_for_each_q_rx(dev, i) \ |
556 |
+ for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \ |
557 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c |
558 |
+index c0001e38fcce9..a0797cec136e9 100644 |
559 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c |
560 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c |
561 |
+@@ -142,7 +142,7 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) |
562 |
+ mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); |
563 |
+ } |
564 |
+ |
565 |
+-static void mt7921_mac_init(struct mt7921_dev *dev) |
566 |
++void mt7921_mac_init(struct mt7921_dev *dev) |
567 |
+ { |
568 |
+ int i; |
569 |
+ |
570 |
+@@ -232,7 +232,6 @@ int mt7921_register_device(struct mt7921_dev *dev) |
571 |
+ INIT_LIST_HEAD(&dev->sta_poll_list); |
572 |
+ spin_lock_init(&dev->sta_poll_lock); |
573 |
+ |
574 |
+- init_waitqueue_head(&dev->reset_wait); |
575 |
+ INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); |
576 |
+ |
577 |
+ ret = mt7921_init_hardware(dev); |
578 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c |
579 |
+index a6d2a25b3495f..ce4eae7f1e448 100644 |
580 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c |
581 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c |
582 |
+@@ -1184,43 +1184,77 @@ void mt7921_update_channel(struct mt76_dev *mdev) |
583 |
+ mt76_connac_power_save_sched(&dev->mphy, &dev->pm); |
584 |
+ } |
585 |
+ |
586 |
+-static bool |
587 |
+-mt7921_wait_reset_state(struct mt7921_dev *dev, u32 state) |
588 |
++static int |
589 |
++mt7921_wfsys_reset(struct mt7921_dev *dev) |
590 |
+ { |
591 |
+- bool ret; |
592 |
++ mt76_set(dev, 0x70002600, BIT(0)); |
593 |
++ msleep(200); |
594 |
++ mt76_clear(dev, 0x70002600, BIT(0)); |
595 |
+ |
596 |
+- ret = wait_event_timeout(dev->reset_wait, |
597 |
+- (READ_ONCE(dev->reset_state) & state), |
598 |
+- MT7921_RESET_TIMEOUT); |
599 |
+- |
600 |
+- WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); |
601 |
+- return ret; |
602 |
++ return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B, |
603 |
++ WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500); |
604 |
+ } |
605 |
+ |
606 |
+ static void |
607 |
+-mt7921_dma_reset(struct mt7921_phy *phy) |
608 |
++mt7921_dma_reset(struct mt7921_dev *dev) |
609 |
+ { |
610 |
+- struct mt7921_dev *dev = phy->dev; |
611 |
+ int i; |
612 |
+ |
613 |
++ /* reset */ |
614 |
++ mt76_clear(dev, MT_WFDMA0_RST, |
615 |
++ MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); |
616 |
++ |
617 |
++ mt76_set(dev, MT_WFDMA0_RST, |
618 |
++ MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); |
619 |
++ |
620 |
++ /* disable WFDMA0 */ |
621 |
+ mt76_clear(dev, MT_WFDMA0_GLO_CFG, |
622 |
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); |
623 |
++ MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | |
624 |
++ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | |
625 |
++ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | |
626 |
++ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | |
627 |
++ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); |
628 |
+ |
629 |
+- usleep_range(1000, 2000); |
630 |
++ mt76_poll(dev, MT_WFDMA0_GLO_CFG, |
631 |
++ MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | |
632 |
++ MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000); |
633 |
+ |
634 |
+- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); |
635 |
++ /* reset hw queues */ |
636 |
+ for (i = 0; i < __MT_TXQ_MAX; i++) |
637 |
+- mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); |
638 |
++ mt76_queue_reset(dev, dev->mphy.q_tx[i]); |
639 |
+ |
640 |
+- mt76_for_each_q_rx(&dev->mt76, i) { |
641 |
+- mt76_queue_rx_reset(dev, i); |
642 |
+- } |
643 |
++ for (i = 0; i < __MT_MCUQ_MAX; i++) |
644 |
++ mt76_queue_reset(dev, dev->mt76.q_mcu[i]); |
645 |
+ |
646 |
+- /* re-init prefetch settings after reset */ |
647 |
++ mt76_for_each_q_rx(&dev->mt76, i) |
648 |
++ mt76_queue_reset(dev, &dev->mt76.q_rx[i]); |
649 |
++ |
650 |
++ /* configure perfetch settings */ |
651 |
+ mt7921_dma_prefetch(dev); |
652 |
+ |
653 |
++ /* reset dma idx */ |
654 |
++ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); |
655 |
++ |
656 |
++ /* configure delay interrupt */ |
657 |
++ mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); |
658 |
++ |
659 |
++ mt76_set(dev, MT_WFDMA0_GLO_CFG, |
660 |
++ MT_WFDMA0_GLO_CFG_TX_WB_DDONE | |
661 |
++ MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | |
662 |
++ MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | |
663 |
++ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | |
664 |
++ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | |
665 |
++ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); |
666 |
++ |
667 |
+ mt76_set(dev, MT_WFDMA0_GLO_CFG, |
668 |
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); |
669 |
++ |
670 |
++ mt76_set(dev, 0x54000120, BIT(1)); |
671 |
++ |
672 |
++ /* enable interrupts for TX/RX rings */ |
673 |
++ mt7921_irq_enable(dev, |
674 |
++ MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | |
675 |
++ MT_INT_MCU_CMD); |
676 |
+ } |
677 |
+ |
678 |
+ void mt7921_tx_token_put(struct mt7921_dev *dev) |
679 |
+@@ -1244,71 +1278,133 @@ void mt7921_tx_token_put(struct mt7921_dev *dev) |
680 |
+ idr_destroy(&dev->token); |
681 |
+ } |
682 |
+ |
683 |
+-/* system error recovery */ |
684 |
+-void mt7921_mac_reset_work(struct work_struct *work) |
685 |
++static void |
686 |
++mt7921_vif_connect_iter(void *priv, u8 *mac, |
687 |
++ struct ieee80211_vif *vif) |
688 |
+ { |
689 |
+- struct mt7921_dev *dev; |
690 |
++ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; |
691 |
++ struct mt7921_dev *dev = mvif->phy->dev; |
692 |
+ |
693 |
+- dev = container_of(work, struct mt7921_dev, reset_work); |
694 |
++ ieee80211_disconnect(vif, true); |
695 |
+ |
696 |
+- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) |
697 |
+- return; |
698 |
++ mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); |
699 |
++ mt7921_mcu_set_tx(dev, vif); |
700 |
++} |
701 |
+ |
702 |
+- ieee80211_stop_queues(mt76_hw(dev)); |
703 |
++static int |
704 |
++mt7921_mac_reset(struct mt7921_dev *dev) |
705 |
++{ |
706 |
++ int i, err; |
707 |
++ |
708 |
++ mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); |
709 |
++ |
710 |
++ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); |
711 |
++ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); |
712 |
+ |
713 |
+- set_bit(MT76_RESET, &dev->mphy.state); |
714 |
+ set_bit(MT76_MCU_RESET, &dev->mphy.state); |
715 |
+ wake_up(&dev->mt76.mcu.wait); |
716 |
+- cancel_delayed_work_sync(&dev->mphy.mac_work); |
717 |
++ skb_queue_purge(&dev->mt76.mcu.res_q); |
718 |
+ |
719 |
+- /* lock/unlock all queues to ensure that no tx is pending */ |
720 |
+ mt76_txq_schedule_all(&dev->mphy); |
721 |
+ |
722 |
+ mt76_worker_disable(&dev->mt76.tx_worker); |
723 |
+- napi_disable(&dev->mt76.napi[0]); |
724 |
+- napi_disable(&dev->mt76.napi[1]); |
725 |
+- napi_disable(&dev->mt76.napi[2]); |
726 |
++ napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]); |
727 |
++ napi_disable(&dev->mt76.napi[MT_RXQ_MCU]); |
728 |
++ napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); |
729 |
+ napi_disable(&dev->mt76.tx_napi); |
730 |
+ |
731 |
+- mt7921_mutex_acquire(dev); |
732 |
+- |
733 |
+- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); |
734 |
+- |
735 |
+ mt7921_tx_token_put(dev); |
736 |
+ idr_init(&dev->token); |
737 |
+ |
738 |
+- if (mt7921_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { |
739 |
+- mt7921_dma_reset(&dev->phy); |
740 |
++ /* clean up hw queues */ |
741 |
++ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) |
742 |
++ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); |
743 |
+ |
744 |
+- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); |
745 |
+- mt7921_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); |
746 |
+- } |
747 |
++ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++) |
748 |
++ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); |
749 |
+ |
750 |
+- clear_bit(MT76_MCU_RESET, &dev->mphy.state); |
751 |
+- clear_bit(MT76_RESET, &dev->mphy.state); |
752 |
++ mt76_for_each_q_rx(&dev->mt76, i) |
753 |
++ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); |
754 |
++ |
755 |
++ mt7921_wfsys_reset(dev); |
756 |
++ mt7921_dma_reset(dev); |
757 |
++ |
758 |
++ mt76_for_each_q_rx(&dev->mt76, i) { |
759 |
++ mt76_queue_rx_reset(dev, i); |
760 |
++ napi_enable(&dev->mt76.napi[i]); |
761 |
++ napi_schedule(&dev->mt76.napi[i]); |
762 |
++ } |
763 |
+ |
764 |
+- mt76_worker_enable(&dev->mt76.tx_worker); |
765 |
+ napi_enable(&dev->mt76.tx_napi); |
766 |
+ napi_schedule(&dev->mt76.tx_napi); |
767 |
++ mt76_worker_enable(&dev->mt76.tx_worker); |
768 |
+ |
769 |
+- napi_enable(&dev->mt76.napi[0]); |
770 |
+- napi_schedule(&dev->mt76.napi[0]); |
771 |
++ clear_bit(MT76_MCU_RESET, &dev->mphy.state); |
772 |
+ |
773 |
+- napi_enable(&dev->mt76.napi[1]); |
774 |
+- napi_schedule(&dev->mt76.napi[1]); |
775 |
++ mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); |
776 |
++ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); |
777 |
++ mt7921_irq_enable(dev, |
778 |
++ MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | |
779 |
++ MT_INT_MCU_CMD); |
780 |
+ |
781 |
+- napi_enable(&dev->mt76.napi[2]); |
782 |
+- napi_schedule(&dev->mt76.napi[2]); |
783 |
++ err = mt7921_run_firmware(dev); |
784 |
++ if (err) |
785 |
++ return err; |
786 |
+ |
787 |
+- ieee80211_wake_queues(mt76_hw(dev)); |
788 |
++ err = mt7921_mcu_set_eeprom(dev); |
789 |
++ if (err) |
790 |
++ return err; |
791 |
+ |
792 |
+- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); |
793 |
+- mt7921_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); |
794 |
++ mt7921_mac_init(dev); |
795 |
++ return __mt7921_start(&dev->phy); |
796 |
++} |
797 |
+ |
798 |
+- mt7921_mutex_release(dev); |
799 |
++/* system error recovery */ |
800 |
++void mt7921_mac_reset_work(struct work_struct *work) |
801 |
++{ |
802 |
++ struct ieee80211_hw *hw; |
803 |
++ struct mt7921_dev *dev; |
804 |
++ int i; |
805 |
+ |
806 |
+- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, |
807 |
+- MT7921_WATCHDOG_TIME); |
808 |
++ dev = container_of(work, struct mt7921_dev, reset_work); |
809 |
++ hw = mt76_hw(dev); |
810 |
++ |
811 |
++ dev_err(dev->mt76.dev, "chip reset\n"); |
812 |
++ ieee80211_stop_queues(hw); |
813 |
++ |
814 |
++ cancel_delayed_work_sync(&dev->mphy.mac_work); |
815 |
++ cancel_delayed_work_sync(&dev->pm.ps_work); |
816 |
++ cancel_work_sync(&dev->pm.wake_work); |
817 |
++ |
818 |
++ mutex_lock(&dev->mt76.mutex); |
819 |
++ for (i = 0; i < 10; i++) { |
820 |
++ if (!mt7921_mac_reset(dev)) |
821 |
++ break; |
822 |
++ } |
823 |
++ mutex_unlock(&dev->mt76.mutex); |
824 |
++ |
825 |
++ if (i == 10) |
826 |
++ dev_err(dev->mt76.dev, "chip reset failed\n"); |
827 |
++ |
828 |
++ if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state)) { |
829 |
++ struct cfg80211_scan_info info = { |
830 |
++ .aborted = true, |
831 |
++ }; |
832 |
++ |
833 |
++ ieee80211_scan_completed(dev->mphy.hw, &info); |
834 |
++ } |
835 |
++ |
836 |
++ ieee80211_wake_queues(hw); |
837 |
++ ieee80211_iterate_active_interfaces(hw, |
838 |
++ IEEE80211_IFACE_ITER_RESUME_ALL, |
839 |
++ mt7921_vif_connect_iter, 0); |
840 |
++} |
841 |
++ |
842 |
++void mt7921_reset(struct mt76_dev *mdev) |
843 |
++{ |
844 |
++ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); |
845 |
++ |
846 |
++ queue_work(dev->mt76.wq, &dev->reset_work); |
847 |
+ } |
848 |
+ |
849 |
+ static void |
850 |
+@@ -1505,4 +1601,5 @@ void mt7921_coredump_work(struct work_struct *work) |
851 |
+ } |
852 |
+ dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, |
853 |
+ GFP_KERNEL); |
854 |
++ mt7921_reset(&dev->mt76); |
855 |
+ } |
856 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c |
857 |
+index 2c781b6f89e53..c6e8857067a3a 100644 |
858 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c |
859 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c |
860 |
+@@ -168,28 +168,44 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy) |
861 |
+ } |
862 |
+ } |
863 |
+ |
864 |
+-static int mt7921_start(struct ieee80211_hw *hw) |
865 |
++int __mt7921_start(struct mt7921_phy *phy) |
866 |
+ { |
867 |
+- struct mt7921_dev *dev = mt7921_hw_dev(hw); |
868 |
+- struct mt7921_phy *phy = mt7921_hw_phy(hw); |
869 |
++ struct mt76_phy *mphy = phy->mt76; |
870 |
++ int err; |
871 |
+ |
872 |
+- mt7921_mutex_acquire(dev); |
873 |
++ err = mt76_connac_mcu_set_mac_enable(mphy->dev, 0, true, false); |
874 |
++ if (err) |
875 |
++ return err; |
876 |
+ |
877 |
+- mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); |
878 |
+- mt76_connac_mcu_set_channel_domain(phy->mt76); |
879 |
++ err = mt76_connac_mcu_set_channel_domain(mphy); |
880 |
++ if (err) |
881 |
++ return err; |
882 |
++ |
883 |
++ err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); |
884 |
++ if (err) |
885 |
++ return err; |
886 |
+ |
887 |
+- mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); |
888 |
+ mt7921_mac_reset_counters(phy); |
889 |
+- set_bit(MT76_STATE_RUNNING, &phy->mt76->state); |
890 |
++ set_bit(MT76_STATE_RUNNING, &mphy->state); |
891 |
+ |
892 |
+- ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, |
893 |
++ ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, |
894 |
+ MT7921_WATCHDOG_TIME); |
895 |
+ |
896 |
+- mt7921_mutex_release(dev); |
897 |
+- |
898 |
+ return 0; |
899 |
+ } |
900 |
+ |
901 |
++static int mt7921_start(struct ieee80211_hw *hw) |
902 |
++{ |
903 |
++ struct mt7921_phy *phy = mt7921_hw_phy(hw); |
904 |
++ int err; |
905 |
++ |
906 |
++ mt7921_mutex_acquire(phy->dev); |
907 |
++ err = __mt7921_start(phy); |
908 |
++ mt7921_mutex_release(phy->dev); |
909 |
++ |
910 |
++ return err; |
911 |
++} |
912 |
++ |
913 |
+ static void mt7921_stop(struct ieee80211_hw *hw) |
914 |
+ { |
915 |
+ struct mt7921_dev *dev = mt7921_hw_dev(hw); |
916 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c |
917 |
+index be88c9f5637a5..a4f070cd78fda 100644 |
918 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c |
919 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c |
920 |
+@@ -161,6 +161,8 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, |
921 |
+ if (!skb) { |
922 |
+ dev_err(mdev->dev, "Message %d (seq %d) timeout\n", |
923 |
+ cmd, seq); |
924 |
++ mt7921_reset(mdev); |
925 |
++ |
926 |
+ return -ETIMEDOUT; |
927 |
+ } |
928 |
+ |
929 |
+@@ -927,6 +929,24 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) |
930 |
+ sizeof(data), false); |
931 |
+ } |
932 |
+ |
933 |
++int mt7921_run_firmware(struct mt7921_dev *dev) |
934 |
++{ |
935 |
++ int err; |
936 |
++ |
937 |
++ err = mt7921_driver_own(dev); |
938 |
++ if (err) |
939 |
++ return err; |
940 |
++ |
941 |
++ err = mt7921_load_firmware(dev); |
942 |
++ if (err) |
943 |
++ return err; |
944 |
++ |
945 |
++ set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); |
946 |
++ mt7921_mcu_fw_log_2_host(dev, 1); |
947 |
++ |
948 |
++ return 0; |
949 |
++} |
950 |
++ |
951 |
+ int mt7921_mcu_init(struct mt7921_dev *dev) |
952 |
+ { |
953 |
+ static const struct mt76_mcu_ops mt7921_mcu_ops = { |
954 |
+@@ -935,22 +955,10 @@ int mt7921_mcu_init(struct mt7921_dev *dev) |
955 |
+ .mcu_parse_response = mt7921_mcu_parse_response, |
956 |
+ .mcu_restart = mt7921_mcu_restart, |
957 |
+ }; |
958 |
+- int ret; |
959 |
+ |
960 |
+ dev->mt76.mcu_ops = &mt7921_mcu_ops; |
961 |
+ |
962 |
+- ret = mt7921_driver_own(dev); |
963 |
+- if (ret) |
964 |
+- return ret; |
965 |
+- |
966 |
+- ret = mt7921_load_firmware(dev); |
967 |
+- if (ret) |
968 |
+- return ret; |
969 |
+- |
970 |
+- set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); |
971 |
+- mt7921_mcu_fw_log_2_host(dev, 1); |
972 |
+- |
973 |
+- return 0; |
974 |
++ return mt7921_run_firmware(dev); |
975 |
+ } |
976 |
+ |
977 |
+ void mt7921_mcu_exit(struct mt7921_dev *dev) |
978 |
+@@ -1263,6 +1271,7 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) |
979 |
+ |
980 |
+ if (i == MT7921_DRV_OWN_RETRY_COUNT) { |
981 |
+ dev_err(dev->mt76.dev, "driver own failed\n"); |
982 |
++ mt7921_reset(&dev->mt76); |
983 |
+ return -EIO; |
984 |
+ } |
985 |
+ |
986 |
+@@ -1289,6 +1298,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev) |
987 |
+ |
988 |
+ if (i == MT7921_DRV_OWN_RETRY_COUNT) { |
989 |
+ dev_err(dev->mt76.dev, "firmware own failed\n"); |
990 |
++ mt7921_reset(&dev->mt76); |
991 |
+ return -EIO; |
992 |
+ } |
993 |
+ |
994 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |
995 |
+index 25a1a6acb6baf..bc26639695bd4 100644 |
996 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |
997 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |
998 |
+@@ -151,8 +151,6 @@ struct mt7921_dev { |
999 |
+ |
1000 |
+ struct work_struct init_work; |
1001 |
+ struct work_struct reset_work; |
1002 |
+- wait_queue_head_t reset_wait; |
1003 |
+- u32 reset_state; |
1004 |
+ |
1005 |
+ struct list_head sta_poll_list; |
1006 |
+ spinlock_t sta_poll_lock; |
1007 |
+@@ -209,6 +207,7 @@ extern struct pci_driver mt7921_pci_driver; |
1008 |
+ |
1009 |
+ u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); |
1010 |
+ |
1011 |
++int __mt7921_start(struct mt7921_phy *phy); |
1012 |
+ int mt7921_register_device(struct mt7921_dev *dev); |
1013 |
+ void mt7921_unregister_device(struct mt7921_dev *dev); |
1014 |
+ int mt7921_eeprom_init(struct mt7921_dev *dev); |
1015 |
+@@ -220,6 +219,7 @@ void mt7921_eeprom_init_sku(struct mt7921_dev *dev); |
1016 |
+ int mt7921_dma_init(struct mt7921_dev *dev); |
1017 |
+ void mt7921_dma_prefetch(struct mt7921_dev *dev); |
1018 |
+ void mt7921_dma_cleanup(struct mt7921_dev *dev); |
1019 |
++int mt7921_run_firmware(struct mt7921_dev *dev); |
1020 |
+ int mt7921_mcu_init(struct mt7921_dev *dev); |
1021 |
+ int mt7921_mcu_add_bss_info(struct mt7921_phy *phy, |
1022 |
+ struct ieee80211_vif *vif, int enable); |
1023 |
+@@ -281,6 +281,7 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) |
1024 |
+ #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) |
1025 |
+ #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) |
1026 |
+ |
1027 |
++void mt7921_mac_init(struct mt7921_dev *dev); |
1028 |
+ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); |
1029 |
+ void mt7921_mac_reset_counters(struct mt7921_phy *phy); |
1030 |
+ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, |
1031 |
+@@ -296,6 +297,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, |
1032 |
+ struct ieee80211_sta *sta); |
1033 |
+ void mt7921_mac_work(struct work_struct *work); |
1034 |
+ void mt7921_mac_reset_work(struct work_struct *work); |
1035 |
++void mt7921_reset(struct mt76_dev *mdev); |
1036 |
+ int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, |
1037 |
+ enum mt76_txq_id qid, struct mt76_wcid *wcid, |
1038 |
+ struct ieee80211_sta *sta, |
1039 |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h |
1040 |
+index 73878d3e24951..50249e9571a66 100644 |
1041 |
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h |
1042 |
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h |
1043 |
+@@ -418,6 +418,10 @@ |
1044 |
+ #define PCIE_LPCR_HOST_CLR_OWN BIT(1) |
1045 |
+ #define PCIE_LPCR_HOST_SET_OWN BIT(0) |
1046 |
+ |
1047 |
++#define MT_WFSYS_SW_RST_B 0x18000140 |
1048 |
++#define WFSYS_SW_RST_B BIT(0) |
1049 |
++#define WFSYS_SW_INIT_DONE BIT(4) |
1050 |
++ |
1051 |
+ #define MT_CONN_ON_MISC 0x7c0600f0 |
1052 |
+ #define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) |
1053 |
+ |