1 Sometimes a tx_flush during suspend fails, but the FW manages to flush
2 out the packets during the time when the host is supsended. Cancel
3 the Tx-watchdog on suspend to not cause a spurious recovery on resume
4 for that case. Set a flag to reinit the watchdog on the first Tx after
5 resume, so we'll still recover if the FW is not empty and there's
8 Signed-off-by: Arik Nemtsov <arik@wizery.com>
9 Signed-off-by: Eliad Peller <eliad@wizery.com>
12 drivers/net/wireless/ti/wlcore/main.c | 13 +++++++++++++
13 drivers/net/wireless/ti/wlcore/tx.c | 9 +++++++--
14 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 +
15 3 files changed, 21 insertions(+), 2 deletions(-)
17 --- a/drivers/net/wireless/ti/wlcore/main.c
18 +++ b/drivers/net/wireless/ti/wlcore/main.c
19 @@ -1767,6 +1767,12 @@ static int wl1271_op_suspend(struct ieee
20 flush_work(&wl->tx_work);
21 flush_delayed_work(&wl->elp_work);
24 + * Cancel the watchdog even if above tx_flush failed. We will detect
25 + * it on resume anyway.
27 + cancel_delayed_work(&wl->tx_watchdog_work);
32 @@ -1824,6 +1830,13 @@ static int wl1271_op_resume(struct ieee8
35 wl->wow_enabled = false;
38 + * Set a flag to re-init the watchdog on the first Tx after resume.
39 + * That way we avoid possible conditions where Tx-complete interrupts
40 + * fail to arrive and we perform a spurious recovery.
42 + set_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags);
43 mutex_unlock(&wl->mutex);
46 --- a/drivers/net/wireless/ti/wlcore/tx.c
47 +++ b/drivers/net/wireless/ti/wlcore/tx.c
48 @@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1
49 wl->tx_blocks_available -= total_blocks;
50 wl->tx_allocated_blocks += total_blocks;
52 - /* If the FW was empty before, arm the Tx watchdog */
53 - if (wl->tx_allocated_blocks == total_blocks)
55 + * If the FW was empty before, arm the Tx watchdog. Also do
56 + * this on the first Tx after resume, as we always cancel the
57 + * watchdog on suspend.
59 + if (wl->tx_allocated_blocks == total_blocks ||
60 + test_and_clear_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags))
61 wl12xx_rearm_tx_watchdog_locked(wl);
63 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
64 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
65 +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
66 @@ -240,6 +240,7 @@ enum wl12xx_flags {
67 WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
68 WL1271_FLAG_INTENDED_FW_RECOVERY,
69 WL1271_FLAG_IO_FAILED,
70 + WL1271_FLAG_REINIT_TX_WDOG,
73 enum wl12xx_vif_flags {