diff options
Diffstat (limited to 'package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch')
-rw-r--r-- | package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch b/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch new file mode 100644 index 0000000000..497227d474 --- /dev/null +++ b/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch @@ -0,0 +1,73 @@ +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> + +--- +drivers/net/wireless/ti/wlcore/main.c | 13 +++++++++++++ + drivers/net/wireless/ti/wlcore/tx.c | 9 +++++++-- + drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 + + 3 files changed, 21 insertions(+), 2 deletions(-) + +--- 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 ieee + 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 ieee8 + + 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; +--- 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 wl1 + 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)); +--- 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 { |