Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Arik Nemtsov and committed by
John W. Linville
9be86cf0 02d0727c

+21 -2
+13
drivers/net/wireless/ti/wlcore/main.c
··· 1767 1767 flush_work(&wl->tx_work); 1768 1768 flush_delayed_work(&wl->elp_work); 1769 1769 1770 + /* 1771 + * Cancel the watchdog even if above tx_flush failed. We will detect 1772 + * it on resume anyway. 1773 + */ 1774 + cancel_delayed_work(&wl->tx_watchdog_work); 1775 + 1770 1776 return 0; 1771 1777 } 1772 1778 ··· 1830 1824 1831 1825 out: 1832 1826 wl->wow_enabled = false; 1827 + 1828 + /* 1829 + * Set a flag to re-init the watchdog on the first Tx after resume. 1830 + * That way we avoid possible conditions where Tx-complete interrupts 1831 + * fail to arrive and we perform a spurious recovery. 1832 + */ 1833 + set_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags); 1833 1834 mutex_unlock(&wl->mutex); 1834 1835 1835 1836 return 0;
+7 -2
drivers/net/wireless/ti/wlcore/tx.c
··· 234 234 wl->tx_blocks_available -= total_blocks; 235 235 wl->tx_allocated_blocks += total_blocks; 236 236 237 - /* If the FW was empty before, arm the Tx watchdog */ 238 - if (wl->tx_allocated_blocks == total_blocks) 237 + /* 238 + * If the FW was empty before, arm the Tx watchdog. Also do 239 + * this on the first Tx after resume, as we always cancel the 240 + * watchdog on suspend. 241 + */ 242 + if (wl->tx_allocated_blocks == total_blocks || 243 + test_and_clear_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags)) 239 244 wl12xx_rearm_tx_watchdog_locked(wl); 240 245 241 246 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+1
drivers/net/wireless/ti/wlcore/wlcore_i.h
··· 240 240 WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, 241 241 WL1271_FLAG_INTENDED_FW_RECOVERY, 242 242 WL1271_FLAG_IO_FAILED, 243 + WL1271_FLAG_REINIT_TX_WDOG, 243 244 }; 244 245 245 246 enum wl12xx_vif_flags {