Commit 9be86cf0 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by John W. Linville

wlcore: cancel Tx watchdog on suspend and rearm on first Tx after

Sometimes a tx_flush during suspend fails, but the FW manages to flush
out the packets during the time when the host is supsended. Cancel
the Tx-watchdog on suspend to not cause a spurious recovery on resume
for that case. Set a flag to reinit the watchdog on the first Tx after
resume, so we'll still recover if the FW is not empty and there's
indeed a problem.
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 02d0727c
...@@ -1767,6 +1767,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, ...@@ -1767,6 +1767,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
flush_work(&wl->tx_work); flush_work(&wl->tx_work);
flush_delayed_work(&wl->elp_work); flush_delayed_work(&wl->elp_work);
/*
* Cancel the watchdog even if above tx_flush failed. We will detect
* it on resume anyway.
*/
cancel_delayed_work(&wl->tx_watchdog_work);
return 0; return 0;
} }
...@@ -1824,6 +1830,13 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) ...@@ -1824,6 +1830,13 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
out: out:
wl->wow_enabled = false; wl->wow_enabled = false;
/*
* Set a flag to re-init the watchdog on the first Tx after resume.
* That way we avoid possible conditions where Tx-complete interrupts
* fail to arrive and we perform a spurious recovery.
*/
set_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags);
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
return 0; return 0;
......
...@@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl->tx_blocks_available -= total_blocks; wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks; wl->tx_allocated_blocks += total_blocks;
/* If the FW was empty before, arm the Tx watchdog */ /*
if (wl->tx_allocated_blocks == total_blocks) * If the FW was empty before, arm the Tx watchdog. Also do
* this on the first Tx after resume, as we always cancel the
* watchdog on suspend.
*/
if (wl->tx_allocated_blocks == total_blocks ||
test_and_clear_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags))
wl12xx_rearm_tx_watchdog_locked(wl); wl12xx_rearm_tx_watchdog_locked(wl);
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
......
...@@ -240,6 +240,7 @@ enum wl12xx_flags { ...@@ -240,6 +240,7 @@ enum wl12xx_flags {
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
WL1271_FLAG_INTENDED_FW_RECOVERY, WL1271_FLAG_INTENDED_FW_RECOVERY,
WL1271_FLAG_IO_FAILED, WL1271_FLAG_IO_FAILED,
WL1271_FLAG_REINIT_TX_WDOG,
}; };
enum wl12xx_vif_flags { enum wl12xx_vif_flags {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment