aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/main.c21
-rw-r--r--drivers/net/wireless/wl12xx/tx.c8
-rw-r--r--drivers/net/wireless/wl12xx/tx.h2
3 files changed, 22 insertions, 9 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 = {
352 .hci_io_ds = HCI_IO_DS_6MA, 352 .hci_io_ds = HCI_IO_DS_6MA,
353}; 353};
354 354
355static void __wl1271_op_remove_interface(struct wl1271 *wl); 355static void __wl1271_op_remove_interface(struct wl1271 *wl,
356 bool reset_tx_queues);
356static void wl1271_free_ap_keys(struct wl1271 *wl); 357static void wl1271_free_ap_keys(struct wl1271 *wl);
357 358
358 359
@@ -972,10 +973,19 @@ static void wl1271_recovery_work(struct work_struct *work)
972 if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) 973 if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
973 ieee80211_connection_loss(wl->vif); 974 ieee80211_connection_loss(wl->vif);
974 975
976 /* Prevent spurious TX during FW restart */
977 ieee80211_stop_queues(wl->hw);
978
975 /* reboot the chipset */ 979 /* reboot the chipset */
976 __wl1271_op_remove_interface(wl); 980 __wl1271_op_remove_interface(wl, false);
977 ieee80211_restart_hw(wl->hw); 981 ieee80211_restart_hw(wl->hw);
978 982
983 /*
984 * Its safe to enable TX now - the queues are stopped after a request
985 * to restart the HW.
986 */
987 ieee80211_wake_queues(wl->hw);
988
979out: 989out:
980 mutex_unlock(&wl->mutex); 990 mutex_unlock(&wl->mutex);
981} 991}
@@ -1479,7 +1489,8 @@ out:
1479 return ret; 1489 return ret;
1480} 1490}
1481 1491
1482static void __wl1271_op_remove_interface(struct wl1271 *wl) 1492static void __wl1271_op_remove_interface(struct wl1271 *wl,
1493 bool reset_tx_queues)
1483{ 1494{
1484 int i; 1495 int i;
1485 1496
@@ -1525,7 +1536,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
1525 mutex_lock(&wl->mutex); 1536 mutex_lock(&wl->mutex);
1526 1537
1527 /* let's notify MAC80211 about the remaining pending TX frames */ 1538 /* let's notify MAC80211 about the remaining pending TX frames */
1528 wl1271_tx_reset(wl); 1539 wl1271_tx_reset(wl, reset_tx_queues);
1529 wl1271_power_off(wl); 1540 wl1271_power_off(wl);
1530 1541
1531 memset(wl->bssid, 0, ETH_ALEN); 1542 memset(wl->bssid, 0, ETH_ALEN);
@@ -1586,7 +1597,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1586 */ 1597 */
1587 if (wl->vif) { 1598 if (wl->vif) {
1588 WARN_ON(wl->vif != vif); 1599 WARN_ON(wl->vif != vif);
1589 __wl1271_op_remove_interface(wl); 1600 __wl1271_op_remove_interface(wl, true);
1590 } 1601 }
1591 1602
1592 mutex_unlock(&wl->mutex); 1603 mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index cc837bba5468..ca3ab1c1acef 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -769,8 +769,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
769 wl1271_handle_tx_low_watermark(wl); 769 wl1271_handle_tx_low_watermark(wl);
770} 770}
771 771
772/* caller must hold wl->mutex */ 772/* caller must hold wl->mutex and TX must be stopped */
773void wl1271_tx_reset(struct wl1271 *wl) 773void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
774{ 774{
775 int i; 775 int i;
776 struct sk_buff *skb; 776 struct sk_buff *skb;
@@ -806,8 +806,10 @@ void wl1271_tx_reset(struct wl1271 *wl)
806 /* 806 /*
807 * Make sure the driver is at a consistent state, in case this 807 * Make sure the driver is at a consistent state, in case this
808 * function is called from a context other than interface removal. 808 * function is called from a context other than interface removal.
809 * This call will always wake the TX queues.
809 */ 810 */
810 wl1271_handle_tx_low_watermark(wl); 811 if (reset_tx_queues)
812 wl1271_handle_tx_low_watermark(wl);
811 813
812 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { 814 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
813 if (wl->tx_frames[i] == NULL) 815 if (wl->tx_frames[i] == NULL)
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index fc7835c4cf63..832f9258d675 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -185,7 +185,7 @@ static inline int wl1271_tx_get_queue(int queue)
185void wl1271_tx_work(struct work_struct *work); 185void wl1271_tx_work(struct work_struct *work);
186void wl1271_tx_work_locked(struct wl1271 *wl); 186void wl1271_tx_work_locked(struct wl1271 *wl);
187void wl1271_tx_complete(struct wl1271 *wl); 187void wl1271_tx_complete(struct wl1271 *wl);
188void wl1271_tx_reset(struct wl1271 *wl); 188void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
189void wl1271_tx_flush(struct wl1271 *wl); 189void wl1271_tx_flush(struct wl1271 *wl);
190u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); 190u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
191u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); 191u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);