Skip to content

Commit 4e651ba

Browse files
tmlindKalle Valo
authored andcommitted
wlcore: Fix BUG with clear completion on timeout
We do not currently clear wl->elp_compl on ELP timeout and we have bogus lingering pointer that wlcore_irq then will try to access after recovery is done: BUG: spinlock bad magic on CPU#1, irq/255-wl12xx/580 ... (spin_dump) from [<c01b9344>] (do_raw_spin_lock+0xc8/0x124) (do_raw_spin_lock) from [<c09b3970>] (_raw_spin_lock_irqsave+0x68/0x74) (_raw_spin_lock_irqsave) from [<c01a02f0>] (complete+0x24/0x58) (complete) from [<bf572610>] (wlcore_irq+0x48/0x17c [wlcore]) (wlcore_irq [wlcore]) from [<c01c5efc>] (irq_thread_fn+0x2c/0x64) (irq_thread_fn) from [<c01c623c>] (irq_thread+0x148/0x290) (irq_thread) from [<c016b4b0>] (kthread+0x160/0x17c) (kthread) from [<c01010b4>] (ret_from_fork+0x14/0x20) ... After that the system will hang. Let's fix this by adding a flag for recovery and moving the recovery work call to to the error handling section. And we want to set WL1271_FLAG_INTENDED_FW_RECOVERY and actually clear it too in wl1271_recovery_work() and just downgrade the error to a warning to prevent overly verbose output. Cc: Eyal Reizer <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 9c22211 commit 4e651ba

File tree

1 file changed

+14
-4
lines changed
  • drivers/net/wireless/ti/wlcore

1 file changed

+14
-4
lines changed

drivers/net/wireless/ti/wlcore/main.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,8 @@ static void wl1271_recovery_work(struct work_struct *work)
957957
BUG_ON(wl->conf.recovery.bug_on_recovery &&
958958
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
959959

960+
clear_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
961+
960962
if (wl->conf.recovery.no_recovery) {
961963
wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
962964
goto out_unlock;
@@ -6710,6 +6712,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
67106712
int ret;
67116713
unsigned long start_time = jiffies;
67126714
bool pending = false;
6715+
bool recovery = false;
67136716

67146717
/* Nothing to do if no ELP mode requested */
67156718
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
@@ -6726,19 +6729,20 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
67266729

67276730
ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
67286731
if (ret < 0) {
6729-
wl12xx_queue_recovery_work(wl);
6732+
recovery = true;
67306733
goto err;
67316734
}
67326735

67336736
if (!pending) {
67346737
ret = wait_for_completion_timeout(&compl,
67356738
msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
67366739
if (ret == 0) {
6737-
wl1271_error("ELP wakeup timeout!");
6738-
wl12xx_queue_recovery_work(wl);
6740+
wl1271_warning("ELP wakeup timeout!");
67396741

67406742
/* Return no error for runtime PM for recovery */
6741-
return 0;
6743+
ret = 0;
6744+
recovery = true;
6745+
goto err;
67426746
}
67436747
}
67446748

@@ -6753,6 +6757,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev)
67536757
spin_lock_irqsave(&wl->wl_lock, flags);
67546758
wl->elp_compl = NULL;
67556759
spin_unlock_irqrestore(&wl->wl_lock, flags);
6760+
6761+
if (recovery) {
6762+
set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
6763+
wl12xx_queue_recovery_work(wl);
6764+
}
6765+
67566766
return ret;
67576767
}
67586768

0 commit comments

Comments
 (0)