diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 2 |
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 | ||
355 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 355 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
356 | bool reset_tx_queues); | ||
356 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 357 | static 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 | |||
979 | out: | 989 | out: |
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 | ||
1482 | static void __wl1271_op_remove_interface(struct wl1271 *wl) | 1492 | static 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 */ |
773 | void wl1271_tx_reset(struct wl1271 *wl) | 773 | void 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) | |||
185 | void wl1271_tx_work(struct work_struct *work); | 185 | void wl1271_tx_work(struct work_struct *work); |
186 | void wl1271_tx_work_locked(struct wl1271 *wl); | 186 | void wl1271_tx_work_locked(struct wl1271 *wl); |
187 | void wl1271_tx_complete(struct wl1271 *wl); | 187 | void wl1271_tx_complete(struct wl1271 *wl); |
188 | void wl1271_tx_reset(struct wl1271 *wl); | 188 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); |
189 | void wl1271_tx_flush(struct wl1271 *wl); | 189 | void wl1271_tx_flush(struct wl1271 *wl); |
190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |