summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/wl12xx/main.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-04-18 14:15:28 +0300
committerLuciano Coelho <coelho@ti.com>2011-05-02 10:31:28 +0300
commit7dece1c8e1044287287d44ac183a946333b55fc3 (patch)
tree82330386e96e8292bdea78301af98c047eb8a51c /drivers/net/wireless/wl12xx/main.c
parent2dc5a5c2c656b9029a0e635bb3a1cbcfbcb4ca5c (diff)
wl12xx: fix race condition during recovery in AP mode
When operating as AP, the TX queues are not stopped when we start recovery. mac80211 is notified only after the fact. When there is pending TX, it will be queued even after the FW is down. This leads to situations where the TX queues are stopped (because of the TX-watermark mechanism), and are never woken up when we return from recovery. Fix this by explicitly stopping the TX queues when before initiating recovery. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r--drivers/net/wireless/wl12xx/main.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 433bc035741a..6dd42c987663 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -352,7 +352,8 @@ static struct conf_drv_settings default_conf = {
.hci_io_ds = HCI_IO_DS_6MA,
};
-static void __wl1271_op_remove_interface(struct wl1271 *wl);
+static void __wl1271_op_remove_interface(struct wl1271 *wl,
+ bool reset_tx_queues);
static void wl1271_free_ap_keys(struct wl1271 *wl);
@@ -972,10 +973,19 @@ static void wl1271_recovery_work(struct work_struct *work)
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
ieee80211_connection_loss(wl->vif);
+ /* Prevent spurious TX during FW restart */
+ ieee80211_stop_queues(wl->hw);
+
/* reboot the chipset */
- __wl1271_op_remove_interface(wl);
+ __wl1271_op_remove_interface(wl, false);
ieee80211_restart_hw(wl->hw);
+ /*
+ * Its safe to enable TX now - the queues are stopped after a request
+ * to restart the HW.
+ */
+ ieee80211_wake_queues(wl->hw);
+
out:
mutex_unlock(&wl->mutex);
}
@@ -1479,7 +1489,8 @@ out:
return ret;
}
-static void __wl1271_op_remove_interface(struct wl1271 *wl)
+static void __wl1271_op_remove_interface(struct wl1271 *wl,
+ bool reset_tx_queues)
{
int i;
@@ -1525,7 +1536,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
mutex_lock(&wl->mutex);
/* let's notify MAC80211 about the remaining pending TX frames */
- wl1271_tx_reset(wl);
+ wl1271_tx_reset(wl, reset_tx_queues);
wl1271_power_off(wl);
memset(wl->bssid, 0, ETH_ALEN);
@@ -1586,7 +1597,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
*/
if (wl->vif) {
WARN_ON(wl->vif != vif);
- __wl1271_op_remove_interface(wl);
+ __wl1271_op_remove_interface(wl, true);
}
mutex_unlock(&wl->mutex);