summaryrefslogtreecommitdiff
path: root/patches/collateral-evolutions/network/55-iwlwifi-msg-trace-fix.patch
blob: 6ccb5d19a2fb16b1e72a0d1fd0888dd4a023ef4a (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
In recent kernels, %pV will copy the va_list before using it.
This isn't true for all kernels, so copy the va_list for use
by the dev_*() functions, otherwise the kernel will crash if
the message is printed and traced.

--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -75,13 +75,16 @@ void __iwl_ ##fn(struct device *dev, con
 	struct va_format vaf = {				\
 		.fmt = fmt,					\
 	};							\
-	va_list args;						\
+	va_list args1, args2;					\
 								\
-	va_start(args, fmt);					\
-	vaf.va = &args;						\
+	va_start(args1, fmt);					\
+	va_copy(args2, args1);					\
+	vaf.va = &args2;					\
 	dev_ ##fn(dev, "%pV", &vaf);				\
+	va_end(args2);						\
+	vaf.va = &args1;					\
 	trace_iwlwifi_ ##fn(&vaf);				\
-	va_end(args);						\
+	va_end(args1);						\
 }
 
 __iwl_fn(warn)
@@ -100,13 +103,18 @@ void __iwl_err(struct device *dev, bool
 	va_list args;
 
 	va_start(args, fmt);
-	vaf.va = &args;
 	if (!trace_only) {
+		va_list args2;
+
+		va_copy(args2, args);
+		vaf.va = &args2;
 		if (rfkill_prefix)
 			dev_err(dev, "(RFKILL) %pV", &vaf);
 		else
 			dev_err(dev, "%pV", &vaf);
+		va_end(args2);
 	}
+	vaf.va = &args;
 	trace_iwlwifi_err(&vaf);
 	va_end(args);
 }
@@ -123,13 +131,19 @@ void __iwl_dbg(struct device *dev,
 	va_list args;
 
 	va_start(args, fmt);
-	vaf.va = &args;
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (iwl_have_debug_level(level) &&
-	    (!limit || net_ratelimit()))
+	    (!limit || net_ratelimit())) {
+		va_list args2;
+
+		va_copy(args2, args);
+		vaf.va = &args2;
 		dev_dbg(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
 			function, &vaf);
+		va_end(args2);
+	}
 #endif
+	vaf.va = &args;
 	trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
 	va_end(args);
 }