diff options
author | Arik Nemtsov <arik@wizery.com> | 2014-02-10 15:47:18 +0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-14 00:20:14 +0400 |
commit | 9be86cf067f43c3a43a538189d773afc812e4017 (patch) | |
tree | 8677c171bdd00c83f525f4e1e2cfb2093ed25cd8 /drivers/net | |
parent | 02d0727ca3b0bc8194bd69cd52ddf9e4e2910890 (diff) | |
download | linux-9be86cf067f43c3a43a538189d773afc812e4017.tar.xz |
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: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/tx.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 |
3 files changed, 21 insertions, 2 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index da268e85c3a6..1e191967aa26 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1767,6 +1767,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, flush_work(&wl->tx_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; } @@ -1824,6 +1830,13 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) out: 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); return 0; diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 87cd707affa2..ca886efb0a57 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl->tx_blocks_available -= 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); ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index ce7261ce8b59..38153323a36b 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -240,6 +240,7 @@ enum wl12xx_flags { WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, WL1271_FLAG_INTENDED_FW_RECOVERY, WL1271_FLAG_IO_FAILED, + WL1271_FLAG_REINIT_TX_WDOG, }; enum wl12xx_vif_flags { |