wlcore: cancel Tx watchdog on suspend and rearm on first Tx after
authorArik Nemtsov <arik@wizery.com>
Mon, 10 Feb 2014 11:47:18 +0000 (13:47 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 13 Feb 2014 20:20:14 +0000 (15:20 -0500)
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>
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/tx.c
drivers/net/wireless/ti/wlcore/wlcore_i.h

index da268e8..1e19196 100644 (file)
@@ -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;
index 87cd707..ca886ef 100644 (file)
@@ -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));
index ce7261c..3815332 100644 (file)
@@ -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 {