1 |
From b2e8d37103e4d27ebd1bae13d30e79a6f77cd131 Mon Sep 17 00:00:00 2001 |
2 |
From: Tony Lindgren <tony@atomide.com> |
3 |
Date: Mon, 1 Oct 2018 14:38:05 -0700 |
4 |
Subject: [PATCH 031/145] wlcore: Fix BUG with clear completion on timeout |
5 |
|
6 |
[ Upstream commit 4e651bad848955d88b29a568bfbfb4b831270e16 ] |
7 |
|
8 |
We do not currently clear wl->elp_compl on ELP timeout and we have bogus |
9 |
lingering pointer that wlcore_irq then will try to access after recovery |
10 |
is done: |
11 |
|
12 |
BUG: spinlock bad magic on CPU#1, irq/255-wl12xx/580 |
13 |
... |
14 |
(spin_dump) from [<c01b9344>] (do_raw_spin_lock+0xc8/0x124) |
15 |
(do_raw_spin_lock) from [<c09b3970>] (_raw_spin_lock_irqsave+0x68/0x74) |
16 |
(_raw_spin_lock_irqsave) from [<c01a02f0>] (complete+0x24/0x58) |
17 |
(complete) from [<bf572610>] (wlcore_irq+0x48/0x17c [wlcore]) |
18 |
(wlcore_irq [wlcore]) from [<c01c5efc>] (irq_thread_fn+0x2c/0x64) |
19 |
(irq_thread_fn) from [<c01c623c>] (irq_thread+0x148/0x290) |
20 |
(irq_thread) from [<c016b4b0>] (kthread+0x160/0x17c) |
21 |
(kthread) from [<c01010b4>] (ret_from_fork+0x14/0x20) |
22 |
... |
23 |
|
24 |
After that the system will hang. Let's fix this by adding a flag for |
25 |
recovery and moving the recovery work call to to the error handling |
26 |
section. |
27 |
|
28 |
And we want to set WL1271_FLAG_INTENDED_FW_RECOVERY and actually clear |
29 |
it too in wl1271_recovery_work() and just downgrade the error to a |
30 |
warning to prevent overly verbose output. |
31 |
|
32 |
Cc: Eyal Reizer <eyalr@ti.com> |
33 |
Signed-off-by: Tony Lindgren <tony@atomide.com> |
34 |
Signed-off-by: Kalle Valo <kvalo@codeaurora.org> |
35 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
36 |
--- |
37 |
drivers/net/wireless/ti/wlcore/main.c | 18 ++++++++++++++---- |
38 |
1 file changed, 14 insertions(+), 4 deletions(-) |
39 |
|
40 |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c |
41 |
index 89b0d0fade9f..19e3c5a0b715 100644 |
42 |
--- a/drivers/net/wireless/ti/wlcore/main.c |
43 |
+++ b/drivers/net/wireless/ti/wlcore/main.c |
44 |
@@ -957,6 +957,8 @@ static void wl1271_recovery_work(struct work_struct *work) |
45 |
BUG_ON(wl->conf.recovery.bug_on_recovery && |
46 |
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
47 |
|
48 |
+ clear_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); |
49 |
+ |
50 |
if (wl->conf.recovery.no_recovery) { |
51 |
wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); |
52 |
goto out_unlock; |
53 |
@@ -6710,6 +6712,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) |
54 |
int ret; |
55 |
unsigned long start_time = jiffies; |
56 |
bool pending = false; |
57 |
+ bool recovery = false; |
58 |
|
59 |
/* Nothing to do if no ELP mode requested */ |
60 |
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
61 |
@@ -6726,7 +6729,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) |
62 |
|
63 |
ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
64 |
if (ret < 0) { |
65 |
- wl12xx_queue_recovery_work(wl); |
66 |
+ recovery = true; |
67 |
goto err; |
68 |
} |
69 |
|
70 |
@@ -6734,11 +6737,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) |
71 |
ret = wait_for_completion_timeout(&compl, |
72 |
msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); |
73 |
if (ret == 0) { |
74 |
- wl1271_error("ELP wakeup timeout!"); |
75 |
- wl12xx_queue_recovery_work(wl); |
76 |
+ wl1271_warning("ELP wakeup timeout!"); |
77 |
|
78 |
/* Return no error for runtime PM for recovery */ |
79 |
- return 0; |
80 |
+ ret = 0; |
81 |
+ recovery = true; |
82 |
+ goto err; |
83 |
} |
84 |
} |
85 |
|
86 |
@@ -6753,6 +6757,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) |
87 |
spin_lock_irqsave(&wl->wl_lock, flags); |
88 |
wl->elp_compl = NULL; |
89 |
spin_unlock_irqrestore(&wl->wl_lock, flags); |
90 |
+ |
91 |
+ if (recovery) { |
92 |
+ set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); |
93 |
+ wl12xx_queue_recovery_work(wl); |
94 |
+ } |
95 |
+ |
96 |
return ret; |
97 |
} |
98 |
|
99 |
-- |
100 |
2.19.1 |
101 |
|