diff options
35 files changed, 314 insertions, 109 deletions
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index bca9c80056fe..8bffa5c9818c 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { | |||
84 | { BCMA_CORE_I2S, "I2S" }, | 84 | { BCMA_CORE_I2S, "I2S" }, |
85 | { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, | 85 | { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, |
86 | { BCMA_CORE_SHIM, "SHIM" }, | 86 | { BCMA_CORE_SHIM, "SHIM" }, |
87 | { BCMA_CORE_PCIE2, "PCIe Gen2" }, | ||
88 | { BCMA_CORE_ARM_CR4, "ARM CR4" }, | ||
87 | { BCMA_CORE_DEFAULT, "Default" }, | 89 | { BCMA_CORE_DEFAULT, "Default" }, |
88 | }; | 90 | }; |
89 | 91 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 639ba7d18ea4..6988e1d081f2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -965,7 +965,7 @@ static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, | |||
965 | { | 965 | { |
966 | int i; | 966 | int i; |
967 | 967 | ||
968 | if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah)) | 968 | if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah)) |
969 | return; | 969 | return; |
970 | 970 | ||
971 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 971 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 712f415b8c08..88ff1d7b53ab 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h | |||
@@ -1020,7 +1020,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { | |||
1020 | {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, | 1020 | {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, |
1021 | {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1021 | {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1022 | {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1022 | {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1023 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 1023 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, |
1024 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, | 1024 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, |
1025 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | 1025 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, |
1026 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1026 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8a1888d02070..366002f266f8 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -254,6 +254,7 @@ struct ath_atx_tid { | |||
254 | int sched; | 254 | int sched; |
255 | int paused; | 255 | int paused; |
256 | u8 state; | 256 | u8 state; |
257 | bool stop_cb; | ||
257 | }; | 258 | }; |
258 | 259 | ||
259 | struct ath_node { | 260 | struct ath_node { |
@@ -351,7 +352,8 @@ void ath_tx_tasklet(struct ath_softc *sc); | |||
351 | void ath_tx_edma_tasklet(struct ath_softc *sc); | 352 | void ath_tx_edma_tasklet(struct ath_softc *sc); |
352 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 353 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
353 | u16 tid, u16 *ssn); | 354 | u16 tid, u16 *ssn); |
354 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 355 | bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, |
356 | bool flush); | ||
355 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 357 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
356 | 358 | ||
357 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); | 359 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index e6307b86363a..b37eb8d38811 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -2008,6 +2008,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, | |||
2008 | WARN_ON(i != ATH9K_SSTATS_LEN); | 2008 | WARN_ON(i != ATH9K_SSTATS_LEN); |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | void ath9k_deinit_debug(struct ath_softc *sc) | ||
2012 | { | ||
2013 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { | ||
2014 | relay_close(sc->rfs_chan_spec_scan); | ||
2015 | sc->rfs_chan_spec_scan = NULL; | ||
2016 | } | ||
2017 | } | ||
2018 | |||
2011 | int ath9k_init_debug(struct ath_hw *ah) | 2019 | int ath9k_init_debug(struct ath_hw *ah) |
2012 | { | 2020 | { |
2013 | struct ath_common *common = ath9k_hw_common(ah); | 2021 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 794a7ec83a24..9d49aab8b989 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -304,6 +304,7 @@ struct ath9k_debug { | |||
304 | }; | 304 | }; |
305 | 305 | ||
306 | int ath9k_init_debug(struct ath_hw *ah); | 306 | int ath9k_init_debug(struct ath_hw *ah); |
307 | void ath9k_deinit_debug(struct ath_softc *sc); | ||
307 | 308 | ||
308 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 309 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
309 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | 310 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, |
@@ -339,6 +340,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah) | |||
339 | return 0; | 340 | return 0; |
340 | } | 341 | } |
341 | 342 | ||
343 | static inline void ath9k_deinit_debug(struct ath_softc *sc) | ||
344 | { | ||
345 | } | ||
346 | |||
342 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | 347 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, |
343 | enum ath9k_int status) | 348 | enum ath9k_int status) |
344 | { | 349 | { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0237b2868961..aba415103f94 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -906,7 +906,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
906 | if (!ath_is_world_regd(reg)) { | 906 | if (!ath_is_world_regd(reg)) { |
907 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 907 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
908 | if (error) | 908 | if (error) |
909 | goto unregister; | 909 | goto debug_cleanup; |
910 | } | 910 | } |
911 | 911 | ||
912 | ath_init_leds(sc); | 912 | ath_init_leds(sc); |
@@ -914,6 +914,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
914 | 914 | ||
915 | return 0; | 915 | return 0; |
916 | 916 | ||
917 | debug_cleanup: | ||
918 | ath9k_deinit_debug(sc); | ||
917 | unregister: | 919 | unregister: |
918 | ieee80211_unregister_hw(hw); | 920 | ieee80211_unregister_hw(hw); |
919 | rx_cleanup: | 921 | rx_cleanup: |
@@ -942,11 +944,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
942 | sc->dfs_detector->exit(sc->dfs_detector); | 944 | sc->dfs_detector->exit(sc->dfs_detector); |
943 | 945 | ||
944 | ath9k_eeprom_release(sc); | 946 | ath9k_eeprom_release(sc); |
945 | |||
946 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { | ||
947 | relay_close(sc->rfs_chan_spec_scan); | ||
948 | sc->rfs_chan_spec_scan = NULL; | ||
949 | } | ||
950 | } | 947 | } |
951 | 948 | ||
952 | void ath9k_deinit_device(struct ath_softc *sc) | 949 | void ath9k_deinit_device(struct ath_softc *sc) |
@@ -960,6 +957,7 @@ void ath9k_deinit_device(struct ath_softc *sc) | |||
960 | 957 | ||
961 | ath9k_ps_restore(sc); | 958 | ath9k_ps_restore(sc); |
962 | 959 | ||
960 | ath9k_deinit_debug(sc); | ||
963 | ieee80211_unregister_hw(hw); | 961 | ieee80211_unregister_hw(hw); |
964 | ath_rx_cleanup(sc); | 962 | ath_rx_cleanup(sc); |
965 | ath9k_deinit_softc(sc); | 963 | ath9k_deinit_softc(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a18414b5948b..2382d1262e7f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1687,6 +1687,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1687 | u16 tid, u16 *ssn, u8 buf_size) | 1687 | u16 tid, u16 *ssn, u8 buf_size) |
1688 | { | 1688 | { |
1689 | struct ath_softc *sc = hw->priv; | 1689 | struct ath_softc *sc = hw->priv; |
1690 | bool flush = false; | ||
1690 | int ret = 0; | 1691 | int ret = 0; |
1691 | 1692 | ||
1692 | local_bh_disable(); | 1693 | local_bh_disable(); |
@@ -1703,12 +1704,13 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1703 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1704 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1704 | ath9k_ps_restore(sc); | 1705 | ath9k_ps_restore(sc); |
1705 | break; | 1706 | break; |
1706 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
1707 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 1707 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
1708 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 1708 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
1709 | flush = true; | ||
1710 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
1709 | ath9k_ps_wakeup(sc); | 1711 | ath9k_ps_wakeup(sc); |
1710 | ath_tx_aggr_stop(sc, sta, tid); | 1712 | if (ath_tx_aggr_stop(sc, sta, tid, flush)) |
1711 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1713 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1712 | ath9k_ps_restore(sc); | 1714 | ath9k_ps_restore(sc); |
1713 | break; | 1715 | break; |
1714 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1716 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index eab0fcb7ded6..14bb3354ea64 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -164,7 +164,20 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, | |||
164 | ARRAY_SIZE(bf->rates)); | 164 | ARRAY_SIZE(bf->rates)); |
165 | } | 165 | } |
166 | 166 | ||
167 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 167 | static void ath_tx_clear_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
168 | { | ||
169 | tid->state &= ~AGGR_ADDBA_COMPLETE; | ||
170 | tid->state &= ~AGGR_CLEANUP; | ||
171 | if (!tid->stop_cb) | ||
172 | return; | ||
173 | |||
174 | ieee80211_start_tx_ba_cb_irqsafe(tid->an->vif, tid->an->sta->addr, | ||
175 | tid->tidno); | ||
176 | tid->stop_cb = false; | ||
177 | } | ||
178 | |||
179 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid, | ||
180 | bool flush_packets) | ||
168 | { | 181 | { |
169 | struct ath_txq *txq = tid->ac->txq; | 182 | struct ath_txq *txq = tid->ac->txq; |
170 | struct sk_buff *skb; | 183 | struct sk_buff *skb; |
@@ -181,16 +194,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
181 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 194 | while ((skb = __skb_dequeue(&tid->buf_q))) { |
182 | fi = get_frame_info(skb); | 195 | fi = get_frame_info(skb); |
183 | bf = fi->bf; | 196 | bf = fi->bf; |
197 | if (!bf && !flush_packets) | ||
198 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | ||
184 | 199 | ||
185 | if (!bf) { | 200 | if (!bf) { |
186 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 201 | ieee80211_free_txskb(sc->hw, skb); |
187 | if (!bf) { | 202 | continue; |
188 | ieee80211_free_txskb(sc->hw, skb); | ||
189 | continue; | ||
190 | } | ||
191 | } | 203 | } |
192 | 204 | ||
193 | if (fi->retries) { | 205 | if (fi->retries || flush_packets) { |
194 | list_add_tail(&bf->list, &bf_head); | 206 | list_add_tail(&bf->list, &bf_head); |
195 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 207 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
196 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 208 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
@@ -201,12 +213,10 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
201 | } | 213 | } |
202 | } | 214 | } |
203 | 215 | ||
204 | if (tid->baw_head == tid->baw_tail) { | 216 | if (tid->baw_head == tid->baw_tail) |
205 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 217 | ath_tx_clear_tid(sc, tid); |
206 | tid->state &= ~AGGR_CLEANUP; | ||
207 | } | ||
208 | 218 | ||
209 | if (sendbar) { | 219 | if (sendbar && !flush_packets) { |
210 | ath_txq_unlock(sc, txq); | 220 | ath_txq_unlock(sc, txq); |
211 | ath_send_bar(tid, tid->seq_start); | 221 | ath_send_bar(tid, tid->seq_start); |
212 | ath_txq_lock(sc, txq); | 222 | ath_txq_lock(sc, txq); |
@@ -277,9 +287,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
277 | 287 | ||
278 | list_add_tail(&bf->list, &bf_head); | 288 | list_add_tail(&bf->list, &bf_head); |
279 | 289 | ||
280 | if (fi->retries) | 290 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
281 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | ||
282 | |||
283 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 291 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
284 | } | 292 | } |
285 | 293 | ||
@@ -602,7 +610,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
602 | } | 610 | } |
603 | 611 | ||
604 | if (tid->state & AGGR_CLEANUP) | 612 | if (tid->state & AGGR_CLEANUP) |
605 | ath_tx_flush_tid(sc, tid); | 613 | ath_tx_flush_tid(sc, tid, false); |
606 | 614 | ||
607 | rcu_read_unlock(); | 615 | rcu_read_unlock(); |
608 | 616 | ||
@@ -620,6 +628,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
620 | struct ath_tx_status *ts, struct ath_buf *bf, | 628 | struct ath_tx_status *ts, struct ath_buf *bf, |
621 | struct list_head *bf_head) | 629 | struct list_head *bf_head) |
622 | { | 630 | { |
631 | struct ieee80211_tx_info *info; | ||
623 | bool txok, flush; | 632 | bool txok, flush; |
624 | 633 | ||
625 | txok = !(ts->ts_status & ATH9K_TXERR_MASK); | 634 | txok = !(ts->ts_status & ATH9K_TXERR_MASK); |
@@ -631,8 +640,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
631 | txq->axq_ampdu_depth--; | 640 | txq->axq_ampdu_depth--; |
632 | 641 | ||
633 | if (!bf_isampdu(bf)) { | 642 | if (!bf_isampdu(bf)) { |
634 | if (!flush) | 643 | if (!flush) { |
644 | info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
645 | memcpy(info->control.rates, bf->rates, | ||
646 | sizeof(info->control.rates)); | ||
635 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); | 647 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); |
648 | } | ||
636 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); | 649 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); |
637 | } else | 650 | } else |
638 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); | 651 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); |
@@ -676,7 +689,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
676 | 689 | ||
677 | skb = bf->bf_mpdu; | 690 | skb = bf->bf_mpdu; |
678 | tx_info = IEEE80211_SKB_CB(skb); | 691 | tx_info = IEEE80211_SKB_CB(skb); |
679 | rates = tx_info->control.rates; | 692 | rates = bf->rates; |
680 | 693 | ||
681 | /* | 694 | /* |
682 | * Find the lowest frame length among the rate series that will have a | 695 | * Find the lowest frame length among the rate series that will have a |
@@ -1256,18 +1269,23 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1256 | return 0; | 1269 | return 0; |
1257 | } | 1270 | } |
1258 | 1271 | ||
1259 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 1272 | bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, |
1273 | bool flush) | ||
1260 | { | 1274 | { |
1261 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 1275 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
1262 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 1276 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
1263 | struct ath_txq *txq = txtid->ac->txq; | 1277 | struct ath_txq *txq = txtid->ac->txq; |
1278 | bool ret = !flush; | ||
1279 | |||
1280 | if (flush) | ||
1281 | txtid->stop_cb = false; | ||
1264 | 1282 | ||
1265 | if (txtid->state & AGGR_CLEANUP) | 1283 | if (txtid->state & AGGR_CLEANUP) |
1266 | return; | 1284 | return false; |
1267 | 1285 | ||
1268 | if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { | 1286 | if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { |
1269 | txtid->state &= ~AGGR_ADDBA_PROGRESS; | 1287 | txtid->state &= ~AGGR_ADDBA_PROGRESS; |
1270 | return; | 1288 | return ret; |
1271 | } | 1289 | } |
1272 | 1290 | ||
1273 | ath_txq_lock(sc, txq); | 1291 | ath_txq_lock(sc, txq); |
@@ -1279,13 +1297,17 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1279 | * TID can only be reused after all in-progress subframes have been | 1297 | * TID can only be reused after all in-progress subframes have been |
1280 | * completed. | 1298 | * completed. |
1281 | */ | 1299 | */ |
1282 | if (txtid->baw_head != txtid->baw_tail) | 1300 | if (txtid->baw_head != txtid->baw_tail) { |
1283 | txtid->state |= AGGR_CLEANUP; | 1301 | txtid->state |= AGGR_CLEANUP; |
1284 | else | 1302 | ret = false; |
1303 | txtid->stop_cb = !flush; | ||
1304 | } else { | ||
1285 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 1305 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
1306 | } | ||
1286 | 1307 | ||
1287 | ath_tx_flush_tid(sc, txtid); | 1308 | ath_tx_flush_tid(sc, txtid, flush); |
1288 | ath_txq_unlock_complete(sc, txq); | 1309 | ath_txq_unlock_complete(sc, txq); |
1310 | return ret; | ||
1289 | } | 1311 | } |
1290 | 1312 | ||
1291 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | 1313 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
@@ -2415,6 +2437,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2415 | tid->ac = &an->ac[acno]; | 2437 | tid->ac = &an->ac[acno]; |
2416 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 2438 | tid->state &= ~AGGR_ADDBA_COMPLETE; |
2417 | tid->state &= ~AGGR_ADDBA_PROGRESS; | 2439 | tid->state &= ~AGGR_ADDBA_PROGRESS; |
2440 | tid->stop_cb = false; | ||
2418 | } | 2441 | } |
2419 | 2442 | ||
2420 | for (acno = 0, ac = &an->ac[acno]; | 2443 | for (acno = 0, ac = &an->ac[acno]; |
@@ -2451,8 +2474,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2451 | } | 2474 | } |
2452 | 2475 | ||
2453 | ath_tid_drain(sc, txq, tid); | 2476 | ath_tid_drain(sc, txq, tid); |
2454 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 2477 | ath_tx_clear_tid(sc, tid); |
2455 | tid->state &= ~AGGR_CLEANUP; | ||
2456 | 2478 | ||
2457 | ath_txq_unlock(sc, txq); | 2479 | ath_txq_unlock(sc, txq); |
2458 | } | 2480 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 6d758f285352..761f501959a9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -4140,6 +4140,10 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | |||
4140 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4140 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | |
4141 | BIT(NL80211_IFTYPE_P2P_GO) | 4141 | BIT(NL80211_IFTYPE_P2P_GO) |
4142 | }, | 4142 | }, |
4143 | { | ||
4144 | .max = 1, | ||
4145 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
4146 | } | ||
4143 | }; | 4147 | }; |
4144 | static const struct ieee80211_iface_combination brcmf_iface_combos[] = { | 4148 | static const struct ieee80211_iface_combination brcmf_iface_combos[] = { |
4145 | { | 4149 | { |
@@ -4197,7 +4201,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4197 | BIT(NL80211_IFTYPE_ADHOC) | | 4201 | BIT(NL80211_IFTYPE_ADHOC) | |
4198 | BIT(NL80211_IFTYPE_AP) | | 4202 | BIT(NL80211_IFTYPE_AP) | |
4199 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4203 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
4200 | BIT(NL80211_IFTYPE_P2P_GO); | 4204 | BIT(NL80211_IFTYPE_P2P_GO) | |
4205 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
4201 | wiphy->iface_combinations = brcmf_iface_combos; | 4206 | wiphy->iface_combinations = brcmf_iface_combos; |
4202 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | 4207 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); |
4203 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | 4208 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 592d0aa634a8..e9a3cbc409ae 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -1423,7 +1423,7 @@ il_setup_rx_scan_handlers(struct il_priv *il) | |||
1423 | } | 1423 | } |
1424 | EXPORT_SYMBOL(il_setup_rx_scan_handlers); | 1424 | EXPORT_SYMBOL(il_setup_rx_scan_handlers); |
1425 | 1425 | ||
1426 | inline u16 | 1426 | u16 |
1427 | il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, | 1427 | il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, |
1428 | u8 n_probes) | 1428 | u8 n_probes) |
1429 | { | 1429 | { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 191dcae8ba47..c6384555aab4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -173,6 +173,8 @@ enum { | |||
173 | REPLY_DEBUG_CMD = 0xf0, | 173 | REPLY_DEBUG_CMD = 0xf0, |
174 | DEBUG_LOG_MSG = 0xf7, | 174 | DEBUG_LOG_MSG = 0xf7, |
175 | 175 | ||
176 | MCAST_FILTER_CMD = 0xd0, | ||
177 | |||
176 | /* D3 commands/notifications */ | 178 | /* D3 commands/notifications */ |
177 | D3_CONFIG_CMD = 0xd3, | 179 | D3_CONFIG_CMD = 0xd3, |
178 | PROT_OFFLOAD_CONFIG_CMD = 0xd4, | 180 | PROT_OFFLOAD_CONFIG_CMD = 0xd4, |
@@ -948,4 +950,29 @@ struct iwl_set_calib_default_cmd { | |||
948 | u8 data[0]; | 950 | u8 data[0]; |
949 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ | 951 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ |
950 | 952 | ||
953 | #define MAX_PORT_ID_NUM 2 | ||
954 | |||
955 | /** | ||
956 | * struct iwl_mcast_filter_cmd - configure multicast filter. | ||
957 | * @filter_own: Set 1 to filter out multicast packets sent by station itself | ||
958 | * @port_id: Multicast MAC addresses array specifier. This is a strange way | ||
959 | * to identify network interface adopted in host-device IF. | ||
960 | * It is used by FW as index in array of addresses. This array has | ||
961 | * MAX_PORT_ID_NUM members. | ||
962 | * @count: Number of MAC addresses in the array | ||
963 | * @pass_all: Set 1 to pass all multicast packets. | ||
964 | * @bssid: current association BSSID. | ||
965 | * @addr_list: Place holder for array of MAC addresses. | ||
966 | * IMPORTANT: add padding if necessary to ensure DWORD alignment. | ||
967 | */ | ||
968 | struct iwl_mcast_filter_cmd { | ||
969 | u8 filter_own; | ||
970 | u8 port_id; | ||
971 | u8 count; | ||
972 | u8 pass_all; | ||
973 | u8 bssid[6]; | ||
974 | u8 reserved[2]; | ||
975 | u8 addr_list[0]; | ||
976 | } __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */ | ||
977 | |||
951 | #endif /* __fw_api_h__ */ | 978 | #endif /* __fw_api_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index e6eca4d66f6c..b2cc3d98e0f7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -586,10 +586,12 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm, | |||
586 | */ | 586 | */ |
587 | static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, | 587 | static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, |
588 | struct ieee80211_vif *vif, | 588 | struct ieee80211_vif *vif, |
589 | struct iwl_mac_data_sta *ctxt_sta) | 589 | struct iwl_mac_data_sta *ctxt_sta, |
590 | bool force_assoc_off) | ||
590 | { | 591 | { |
591 | /* We need the dtim_period to set the MAC as associated */ | 592 | /* We need the dtim_period to set the MAC as associated */ |
592 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) { | 593 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && |
594 | !force_assoc_off) { | ||
593 | u32 dtim_offs; | 595 | u32 dtim_offs; |
594 | 596 | ||
595 | /* | 597 | /* |
@@ -659,7 +661,8 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm, | |||
659 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); | 661 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); |
660 | 662 | ||
661 | /* Fill the data specific for station mode */ | 663 | /* Fill the data specific for station mode */ |
662 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); | 664 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta, |
665 | action == FW_CTXT_ACTION_ADD); | ||
663 | 666 | ||
664 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 667 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
665 | } | 668 | } |
@@ -677,7 +680,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm, | |||
677 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 680 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
678 | 681 | ||
679 | /* Fill the data specific for station mode */ | 682 | /* Fill the data specific for station mode */ |
680 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta); | 683 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta, |
684 | action == FW_CTXT_ACTION_ADD); | ||
681 | 685 | ||
682 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & | 686 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & |
683 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); | 687 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index dd158ec571fb..a5eb8c82f16a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -701,6 +701,20 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, | |||
701 | *total_flags = 0; | 701 | *total_flags = 0; |
702 | } | 702 | } |
703 | 703 | ||
704 | static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm, | ||
705 | struct ieee80211_vif *vif) | ||
706 | { | ||
707 | struct iwl_mcast_filter_cmd mcast_filter_cmd = { | ||
708 | .pass_all = 1, | ||
709 | }; | ||
710 | |||
711 | memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
712 | |||
713 | return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, | ||
714 | sizeof(mcast_filter_cmd), | ||
715 | &mcast_filter_cmd); | ||
716 | } | ||
717 | |||
704 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | 718 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, |
705 | struct ieee80211_vif *vif, | 719 | struct ieee80211_vif *vif, |
706 | struct ieee80211_bss_conf *bss_conf, | 720 | struct ieee80211_bss_conf *bss_conf, |
@@ -722,6 +736,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
722 | return; | 736 | return; |
723 | } | 737 | } |
724 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | 738 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); |
739 | iwl_mvm_configure_mcast_filter(mvm, vif); | ||
725 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 740 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
726 | /* remove AP station now that the MAC is unassoc */ | 741 | /* remove AP station now that the MAC is unassoc */ |
727 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 742 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); |
@@ -931,7 +946,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
931 | 946 | ||
932 | switch (cmd) { | 947 | switch (cmd) { |
933 | case STA_NOTIFY_SLEEP: | 948 | case STA_NOTIFY_SLEEP: |
934 | if (atomic_read(&mvmsta->pending_frames) > 0) | 949 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) |
935 | ieee80211_sta_block_awake(hw, sta, true); | 950 | ieee80211_sta_block_awake(hw, sta, true); |
936 | /* | 951 | /* |
937 | * The fw updates the STA to be asleep. Tx packets on the Tx | 952 | * The fw updates the STA to be asleep. Tx packets on the Tx |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 8269bc562951..9f46b23801bc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -292,6 +292,7 @@ struct iwl_mvm { | |||
292 | struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; | 292 | struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; |
293 | struct work_struct sta_drained_wk; | 293 | struct work_struct sta_drained_wk; |
294 | unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; | 294 | unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; |
295 | atomic_t pending_frames[IWL_MVM_STATION_COUNT]; | ||
295 | 296 | ||
296 | /* configured by mac80211 */ | 297 | /* configured by mac80211 */ |
297 | u32 rts_threshold; | 298 | u32 rts_threshold; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index fe031d304d1e..b29c31a41594 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -292,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
292 | CMD(BT_COEX_PROT_ENV), | 292 | CMD(BT_COEX_PROT_ENV), |
293 | CMD(BT_PROFILE_NOTIFICATION), | 293 | CMD(BT_PROFILE_NOTIFICATION), |
294 | CMD(BT_CONFIG), | 294 | CMD(BT_CONFIG), |
295 | CMD(MCAST_FILTER_CMD), | ||
295 | }; | 296 | }; |
296 | #undef CMD | 297 | #undef CMD |
297 | 298 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 2157b0f8ced5..2476e43799d5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -298,6 +298,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
298 | else | 298 | else |
299 | cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); | 299 | cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); |
300 | 300 | ||
301 | /* | ||
302 | * TODO: This is a WA due to a bug in the FW AUX framework that does not | ||
303 | * properly handle time events that fail to be scheduled | ||
304 | */ | ||
305 | cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); | ||
306 | |||
301 | cmd->repeats = cpu_to_le32(1); | 307 | cmd->repeats = cpu_to_le32(1); |
302 | 308 | ||
303 | /* | 309 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 0fd96e4da461..5c664ed54400 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -219,7 +219,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
219 | mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 219 | mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
220 | 220 | ||
221 | /* HW restart, don't assume the memory has been zeroed */ | 221 | /* HW restart, don't assume the memory has been zeroed */ |
222 | atomic_set(&mvm_sta->pending_frames, 0); | 222 | atomic_set(&mvm->pending_frames[sta_id], 0); |
223 | mvm_sta->tid_disable_agg = 0; | 223 | mvm_sta->tid_disable_agg = 0; |
224 | mvm_sta->tfd_queue_msk = 0; | 224 | mvm_sta->tfd_queue_msk = 0; |
225 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | 225 | for (i = 0; i < IEEE80211_NUM_ACS; i++) |
@@ -407,14 +407,21 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
407 | } | 407 | } |
408 | 408 | ||
409 | /* | 409 | /* |
410 | * Make sure that the tx response code sees the station as -EBUSY and | ||
411 | * calls the drain worker. | ||
412 | */ | ||
413 | spin_lock_bh(&mvm_sta->lock); | ||
414 | /* | ||
410 | * There are frames pending on the AC queues for this station. | 415 | * There are frames pending on the AC queues for this station. |
411 | * We need to wait until all the frames are drained... | 416 | * We need to wait until all the frames are drained... |
412 | */ | 417 | */ |
413 | if (atomic_read(&mvm_sta->pending_frames)) { | 418 | if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) { |
414 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); | ||
415 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | 419 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], |
416 | ERR_PTR(-EBUSY)); | 420 | ERR_PTR(-EBUSY)); |
421 | spin_unlock_bh(&mvm_sta->lock); | ||
422 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); | ||
417 | } else { | 423 | } else { |
424 | spin_unlock_bh(&mvm_sta->lock); | ||
418 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); | 425 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); |
419 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); | 426 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); |
420 | } | 427 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 12abd2d71835..a4ddce77aaae 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -274,7 +274,6 @@ struct iwl_mvm_tid_data { | |||
274 | * @bt_reduced_txpower: is reduced tx power enabled for this station | 274 | * @bt_reduced_txpower: is reduced tx power enabled for this station |
275 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx | 275 | * @lock: lock to protect the whole struct. Since %tid_data is access from Tx |
276 | * and from Tx response flow, it needs a spinlock. | 276 | * and from Tx response flow, it needs a spinlock. |
277 | * @pending_frames: number of frames for this STA on the shared Tx queues. | ||
278 | * @tid_data: per tid data. Look at %iwl_mvm_tid_data. | 277 | * @tid_data: per tid data. Look at %iwl_mvm_tid_data. |
279 | * | 278 | * |
280 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | 279 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) |
@@ -290,7 +289,6 @@ struct iwl_mvm_sta { | |||
290 | u8 max_agg_bufsize; | 289 | u8 max_agg_bufsize; |
291 | bool bt_reduced_txpower; | 290 | bool bt_reduced_txpower; |
292 | spinlock_t lock; | 291 | spinlock_t lock; |
293 | atomic_t pending_frames; | ||
294 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; | 292 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; |
295 | struct iwl_lq_sta lq_sta; | 293 | struct iwl_lq_sta lq_sta; |
296 | struct ieee80211_vif *vif; | 294 | struct ieee80211_vif *vif; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 479074303bd7..f212f16502ff 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -416,9 +416,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
416 | 416 | ||
417 | spin_unlock(&mvmsta->lock); | 417 | spin_unlock(&mvmsta->lock); |
418 | 418 | ||
419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && | 419 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE) |
420 | txq_id < IWL_MVM_FIRST_AGG_QUEUE) | 420 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); |
421 | atomic_inc(&mvmsta->pending_frames); | ||
422 | 421 | ||
423 | return 0; | 422 | return 0; |
424 | 423 | ||
@@ -680,16 +679,41 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
680 | /* | 679 | /* |
681 | * If the txq is not an AMPDU queue, there is no chance we freed | 680 | * If the txq is not an AMPDU queue, there is no chance we freed |
682 | * several skbs. Check that out... | 681 | * several skbs. Check that out... |
683 | * If there are no pending frames for this STA, notify mac80211 that | ||
684 | * this station can go to sleep in its STA table. | ||
685 | */ | 682 | */ |
686 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta && | 683 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) && |
687 | !WARN_ON(skb_freed > 1) && | 684 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { |
688 | mvmsta->vif->type == NL80211_IFTYPE_AP && | 685 | if (mvmsta) { |
689 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { | 686 | /* |
690 | ieee80211_sta_block_awake(mvm->hw, sta, false); | 687 | * If there are no pending frames for this STA, notify |
691 | set_bit(sta_id, mvm->sta_drained); | 688 | * mac80211 that this station can go to sleep in its |
692 | schedule_work(&mvm->sta_drained_wk); | 689 | * STA table. |
690 | */ | ||
691 | if (mvmsta->vif->type == NL80211_IFTYPE_AP) | ||
692 | ieee80211_sta_block_awake(mvm->hw, sta, false); | ||
693 | /* | ||
694 | * We might very well have taken mvmsta pointer while | ||
695 | * the station was being removed. The remove flow might | ||
696 | * have seen a pending_frame (because we didn't take | ||
697 | * the lock) even if now the queues are drained. So make | ||
698 | * really sure now that this the station is not being | ||
699 | * removed. If it is, run the drain worker to remove it. | ||
700 | */ | ||
701 | spin_lock_bh(&mvmsta->lock); | ||
702 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
703 | if (IS_ERR_OR_NULL(sta)) { | ||
704 | /* | ||
705 | * Station disappeared in the meantime: | ||
706 | * so we are draining. | ||
707 | */ | ||
708 | set_bit(sta_id, mvm->sta_drained); | ||
709 | schedule_work(&mvm->sta_drained_wk); | ||
710 | } | ||
711 | spin_unlock_bh(&mvmsta->lock); | ||
712 | } else if (!mvmsta) { | ||
713 | /* Tx response without STA, so we are draining */ | ||
714 | set_bit(sta_id, mvm->sta_drained); | ||
715 | schedule_work(&mvm->sta_drained_wk); | ||
716 | } | ||
693 | } | 717 | } |
694 | 718 | ||
695 | rcu_read_unlock(); | 719 | rcu_read_unlock(); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index b878a32e7a98..cb34c7895f2a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void) | |||
1723 | class_destroy(hwsim_class); | 1723 | class_destroy(hwsim_class); |
1724 | } | 1724 | } |
1725 | 1725 | ||
1726 | 1726 | static struct platform_driver mac80211_hwsim_driver = { | |
1727 | static struct device_driver mac80211_hwsim_driver = { | 1727 | .driver = { |
1728 | .name = "mac80211_hwsim", | 1728 | .name = "mac80211_hwsim", |
1729 | .bus = &platform_bus_type, | 1729 | .owner = THIS_MODULE, |
1730 | .owner = THIS_MODULE, | 1730 | }, |
1731 | }; | 1731 | }; |
1732 | 1732 | ||
1733 | static const struct net_device_ops hwsim_netdev_ops = { | 1733 | static const struct net_device_ops hwsim_netdev_ops = { |
@@ -2219,7 +2219,7 @@ static int __init init_mac80211_hwsim(void) | |||
2219 | spin_lock_init(&hwsim_radio_lock); | 2219 | spin_lock_init(&hwsim_radio_lock); |
2220 | INIT_LIST_HEAD(&hwsim_radios); | 2220 | INIT_LIST_HEAD(&hwsim_radios); |
2221 | 2221 | ||
2222 | err = driver_register(&mac80211_hwsim_driver); | 2222 | err = platform_driver_register(&mac80211_hwsim_driver); |
2223 | if (err) | 2223 | if (err) |
2224 | return err; | 2224 | return err; |
2225 | 2225 | ||
@@ -2254,7 +2254,7 @@ static int __init init_mac80211_hwsim(void) | |||
2254 | err = -ENOMEM; | 2254 | err = -ENOMEM; |
2255 | goto failed_drvdata; | 2255 | goto failed_drvdata; |
2256 | } | 2256 | } |
2257 | data->dev->driver = &mac80211_hwsim_driver; | 2257 | data->dev->driver = &mac80211_hwsim_driver.driver; |
2258 | err = device_bind_driver(data->dev); | 2258 | err = device_bind_driver(data->dev); |
2259 | if (err != 0) { | 2259 | if (err != 0) { |
2260 | printk(KERN_DEBUG | 2260 | printk(KERN_DEBUG |
@@ -2564,7 +2564,7 @@ failed_drvdata: | |||
2564 | failed: | 2564 | failed: |
2565 | mac80211_hwsim_free(); | 2565 | mac80211_hwsim_free(); |
2566 | failed_unregister_driver: | 2566 | failed_unregister_driver: |
2567 | driver_unregister(&mac80211_hwsim_driver); | 2567 | platform_driver_unregister(&mac80211_hwsim_driver); |
2568 | return err; | 2568 | return err; |
2569 | } | 2569 | } |
2570 | module_init(init_mac80211_hwsim); | 2570 | module_init(init_mac80211_hwsim); |
@@ -2577,6 +2577,6 @@ static void __exit exit_mac80211_hwsim(void) | |||
2577 | 2577 | ||
2578 | mac80211_hwsim_free(); | 2578 | mac80211_hwsim_free(); |
2579 | unregister_netdev(hwsim_mon); | 2579 | unregister_netdev(hwsim_mon); |
2580 | driver_unregister(&mac80211_hwsim_driver); | 2580 | platform_driver_unregister(&mac80211_hwsim_driver); |
2581 | } | 2581 | } |
2582 | module_exit(exit_mac80211_hwsim); | 2582 | module_exit(exit_mac80211_hwsim); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h index d3a02e73f53a..21ca33a7c770 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h | |||
@@ -550,7 +550,7 @@ do { \ | |||
550 | rxmcs == DESC92C_RATE11M) | 550 | rxmcs == DESC92C_RATE11M) |
551 | 551 | ||
552 | struct phy_rx_agc_info_t { | 552 | struct phy_rx_agc_info_t { |
553 | #if __LITTLE_ENDIAN | 553 | #ifdef __LITTLE_ENDIAN |
554 | u8 gain:7, trsw:1; | 554 | u8 gain:7, trsw:1; |
555 | #else | 555 | #else |
556 | u8 trsw:1, gain:7; | 556 | u8 trsw:1, gain:7; |
@@ -574,7 +574,7 @@ struct phy_status_rpt { | |||
574 | u8 stream_target_csi[2]; | 574 | u8 stream_target_csi[2]; |
575 | u8 sig_evm; | 575 | u8 sig_evm; |
576 | u8 rsvd_3; | 576 | u8 rsvd_3; |
577 | #if __LITTLE_ENDIAN | 577 | #ifdef __LITTLE_ENDIAN |
578 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ | 578 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ |
579 | u8 sgi_en:1; | 579 | u8 sgi_en:1; |
580 | u8 rxsc:2; | 580 | u8 rxsc:2; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 23d640a4debd..938b1e670b93 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -349,6 +349,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { | |||
349 | {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/ | 349 | {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/ |
350 | {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ | 350 | {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ |
351 | {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ | 351 | {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ |
352 | {RTL_USB_DEVICE(0x0846, 0xf001, rtl92cu_hal_cfg)}, /*On Netwrks N300MA*/ | ||
352 | {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ | 353 | {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ |
353 | {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ | 354 | {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ |
354 | {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ | 355 | {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index f14a98a79c9d..2e34db82a643 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -134,7 +134,10 @@ struct bcma_host_ops { | |||
134 | #define BCMA_CORE_I2S 0x834 | 134 | #define BCMA_CORE_I2S 0x834 |
135 | #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ | 135 | #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ |
136 | #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ | 136 | #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ |
137 | #define BCMA_CORE_ARM_CR4 0x83e | 137 | #define BCMA_CORE_PHY_AC 0x83B |
138 | #define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */ | ||
139 | #define BCMA_CORE_USB30_DEV 0x83D | ||
140 | #define BCMA_CORE_ARM_CR4 0x83E | ||
138 | #define BCMA_CORE_DEFAULT 0xFFF | 141 | #define BCMA_CORE_DEFAULT 0xFFF |
139 | 142 | ||
140 | #define BCMA_MAX_NR_CORES 16 | 143 | #define BCMA_MAX_NR_CORES 16 |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 04c2d4670dc6..885898a40d13 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -3043,7 +3043,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw); | |||
3043 | * This function may not be called in IRQ context. Calls to this function | 3043 | * This function may not be called in IRQ context. Calls to this function |
3044 | * for a single hardware must be synchronized against each other. Calls to | 3044 | * for a single hardware must be synchronized against each other. Calls to |
3045 | * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be | 3045 | * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be |
3046 | * mixed for a single hardware. | 3046 | * mixed for a single hardware. Must not run concurrently with |
3047 | * ieee80211_tx_status() or ieee80211_tx_status_ni(). | ||
3047 | * | 3048 | * |
3048 | * In process context use instead ieee80211_rx_ni(). | 3049 | * In process context use instead ieee80211_rx_ni(). |
3049 | * | 3050 | * |
@@ -3059,7 +3060,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
3059 | * (internally defers to a tasklet.) | 3060 | * (internally defers to a tasklet.) |
3060 | * | 3061 | * |
3061 | * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not | 3062 | * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not |
3062 | * be mixed for a single hardware. | 3063 | * be mixed for a single hardware.Must not run concurrently with |
3064 | * ieee80211_tx_status() or ieee80211_tx_status_ni(). | ||
3063 | * | 3065 | * |
3064 | * @hw: the hardware this frame came in on | 3066 | * @hw: the hardware this frame came in on |
3065 | * @skb: the buffer to receive, owned by mac80211 after this call | 3067 | * @skb: the buffer to receive, owned by mac80211 after this call |
@@ -3073,7 +3075,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
3073 | * (internally disables bottom halves). | 3075 | * (internally disables bottom halves). |
3074 | * | 3076 | * |
3075 | * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may | 3077 | * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may |
3076 | * not be mixed for a single hardware. | 3078 | * not be mixed for a single hardware. Must not run concurrently with |
3079 | * ieee80211_tx_status() or ieee80211_tx_status_ni(). | ||
3077 | * | 3080 | * |
3078 | * @hw: the hardware this frame came in on | 3081 | * @hw: the hardware this frame came in on |
3079 | * @skb: the buffer to receive, owned by mac80211 after this call | 3082 | * @skb: the buffer to receive, owned by mac80211 after this call |
@@ -3196,7 +3199,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, | |||
3196 | * This function may not be called in IRQ context. Calls to this function | 3199 | * This function may not be called in IRQ context. Calls to this function |
3197 | * for a single hardware must be synchronized against each other. Calls | 3200 | * for a single hardware must be synchronized against each other. Calls |
3198 | * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe() | 3201 | * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe() |
3199 | * may not be mixed for a single hardware. | 3202 | * may not be mixed for a single hardware. Must not run concurrently with |
3203 | * ieee80211_rx() or ieee80211_rx_ni(). | ||
3200 | * | 3204 | * |
3201 | * @hw: the hardware the frame was transmitted by | 3205 | * @hw: the hardware the frame was transmitted by |
3202 | * @skb: the frame that was transmitted, owned by mac80211 after this call | 3206 | * @skb: the frame that was transmitted, owned by mac80211 after this call |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 158e6eb188d3..44be28cfc6c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1267,6 +1267,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
1269 | __le16 fc, bool acked); | 1269 | __le16 fc, bool acked); |
1270 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | ||
1270 | 1271 | ||
1271 | /* IBSS code */ | 1272 | /* IBSS code */ |
1272 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1273 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 29620bfc7a69..a46e490f20dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
1015 | 1015 | ||
1016 | static void | 1016 | static void |
1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
1018 | u64 timestamp, struct ieee802_11_elems *elems) | 1018 | u64 timestamp, struct ieee802_11_elems *elems, |
1019 | bool beacon) | ||
1019 | { | 1020 | { |
1020 | struct ieee80211_local *local = sdata->local; | 1021 | struct ieee80211_local *local = sdata->local; |
1021 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1022 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1032 | struct cfg80211_chan_def new_vht_chandef = {}; | 1033 | struct cfg80211_chan_def new_vht_chandef = {}; |
1033 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | 1034 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; |
1034 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; | 1035 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; |
1036 | const struct ieee80211_ht_operation *ht_oper; | ||
1035 | int secondary_channel_offset = -1; | 1037 | int secondary_channel_offset = -1; |
1036 | 1038 | ||
1037 | ASSERT_MGD_MTX(ifmgd); | 1039 | ASSERT_MGD_MTX(ifmgd); |
@@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1048 | 1050 | ||
1049 | sec_chan_offs = elems->sec_chan_offs; | 1051 | sec_chan_offs = elems->sec_chan_offs; |
1050 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; | 1052 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; |
1053 | ht_oper = elems->ht_operation; | ||
1051 | 1054 | ||
1052 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | | 1055 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | |
1053 | IEEE80211_STA_DISABLE_40MHZ)) { | 1056 | IEEE80211_STA_DISABLE_40MHZ)) { |
1054 | sec_chan_offs = NULL; | 1057 | sec_chan_offs = NULL; |
1055 | wide_bw_chansw_ie = NULL; | 1058 | wide_bw_chansw_ie = NULL; |
1059 | /* only used for bandwidth here */ | ||
1060 | ht_oper = NULL; | ||
1056 | } | 1061 | } |
1057 | 1062 | ||
1058 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | 1063 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) |
@@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1094 | return; | 1099 | return; |
1095 | } | 1100 | } |
1096 | 1101 | ||
1097 | if (sec_chan_offs) { | 1102 | if (!beacon && sec_chan_offs) { |
1098 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; | 1103 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; |
1104 | } else if (beacon && ht_oper) { | ||
1105 | secondary_channel_offset = | ||
1106 | ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
1099 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | 1107 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { |
1100 | /* if HT is enabled and the IE not present, it's still HT */ | 1108 | /* |
1109 | * If it's not a beacon, HT is enabled and the IE not present, | ||
1110 | * it's 20 MHz, 802.11-2012 8.5.2.6: | ||
1111 | * This element [the Secondary Channel Offset Element] is | ||
1112 | * present when switching to a 40 MHz channel. It may be | ||
1113 | * present when switching to a 20 MHz channel (in which | ||
1114 | * case the secondary channel offset is set to SCN). | ||
1115 | */ | ||
1101 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1116 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1102 | } | 1117 | } |
1103 | 1118 | ||
@@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2796 | mutex_unlock(&local->iflist_mtx); | 2811 | mutex_unlock(&local->iflist_mtx); |
2797 | } | 2812 | } |
2798 | 2813 | ||
2799 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); | 2814 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
2815 | elems, true); | ||
2800 | 2816 | ||
2801 | } | 2817 | } |
2802 | 2818 | ||
@@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3210 | 3226 | ||
3211 | ieee80211_sta_process_chanswitch(sdata, | 3227 | ieee80211_sta_process_chanswitch(sdata, |
3212 | rx_status->mactime, | 3228 | rx_status->mactime, |
3213 | &elems); | 3229 | &elems, false); |
3214 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { | 3230 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { |
3215 | ies_len = skb->len - | 3231 | ies_len = skb->len - |
3216 | offsetof(struct ieee80211_mgmt, | 3232 | offsetof(struct ieee80211_mgmt, |
@@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3232 | 3248 | ||
3233 | ieee80211_sta_process_chanswitch(sdata, | 3249 | ieee80211_sta_process_chanswitch(sdata, |
3234 | rx_status->mactime, | 3250 | rx_status->mactime, |
3235 | &elems); | 3251 | &elems, false); |
3236 | } | 3252 | } |
3237 | break; | 3253 | break; |
3238 | } | 3254 | } |
@@ -3623,6 +3639,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3623 | } | 3639 | } |
3624 | } | 3640 | } |
3625 | 3641 | ||
3642 | #ifdef CONFIG_PM | ||
3643 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | ||
3644 | { | ||
3645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3646 | |||
3647 | mutex_lock(&ifmgd->mtx); | ||
3648 | if (!ifmgd->associated) { | ||
3649 | mutex_unlock(&ifmgd->mtx); | ||
3650 | return; | ||
3651 | } | ||
3652 | |||
3653 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
3654 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
3655 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); | ||
3656 | ieee80211_sta_connection_lost(sdata, | ||
3657 | ifmgd->associated->bssid, | ||
3658 | WLAN_REASON_UNSPECIFIED, | ||
3659 | true); | ||
3660 | mutex_unlock(&ifmgd->mtx); | ||
3661 | return; | ||
3662 | } | ||
3663 | mutex_unlock(&ifmgd->mtx); | ||
3664 | } | ||
3665 | #endif | ||
3666 | |||
3626 | /* interface setup */ | 3667 | /* interface setup */ |
3627 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 3668 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
3628 | { | 3669 | { |
@@ -4329,7 +4370,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4329 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4370 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4330 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 4371 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
4331 | bool tx = !req->local_state_change; | 4372 | bool tx = !req->local_state_change; |
4332 | bool sent_frame = false; | 4373 | bool report_frame = false; |
4333 | 4374 | ||
4334 | mutex_lock(&ifmgd->mtx); | 4375 | mutex_lock(&ifmgd->mtx); |
4335 | 4376 | ||
@@ -4346,7 +4387,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4346 | ieee80211_destroy_auth_data(sdata, false); | 4387 | ieee80211_destroy_auth_data(sdata, false); |
4347 | mutex_unlock(&ifmgd->mtx); | 4388 | mutex_unlock(&ifmgd->mtx); |
4348 | 4389 | ||
4349 | sent_frame = tx; | 4390 | report_frame = true; |
4350 | goto out; | 4391 | goto out; |
4351 | } | 4392 | } |
4352 | 4393 | ||
@@ -4354,12 +4395,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4354 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 4395 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
4355 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 4396 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
4356 | req->reason_code, tx, frame_buf); | 4397 | req->reason_code, tx, frame_buf); |
4357 | sent_frame = tx; | 4398 | report_frame = true; |
4358 | } | 4399 | } |
4359 | mutex_unlock(&ifmgd->mtx); | 4400 | mutex_unlock(&ifmgd->mtx); |
4360 | 4401 | ||
4361 | out: | 4402 | out: |
4362 | if (sent_frame) | 4403 | if (report_frame) |
4363 | __cfg80211_send_deauth(sdata->dev, frame_buf, | 4404 | __cfg80211_send_deauth(sdata->dev, frame_buf, |
4364 | IEEE80211_DEAUTH_FRAME_LEN); | 4405 | IEEE80211_DEAUTH_FRAME_LEN); |
4365 | 4406 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0d51877efdb7..d3f414fe67e0 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw, | |||
688 | struct ieee80211_sta *pubsta, | 688 | struct ieee80211_sta *pubsta, |
689 | struct ieee80211_sta_rates *rates) | 689 | struct ieee80211_sta_rates *rates) |
690 | { | 690 | { |
691 | struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates); | 691 | struct ieee80211_sta_rates *old; |
692 | 692 | ||
693 | /* | ||
694 | * mac80211 guarantees that this function will not be called | ||
695 | * concurrently, so the following RCU access is safe, even without | ||
696 | * extra locking. This can not be checked easily, so we just set | ||
697 | * the condition to true. | ||
698 | */ | ||
699 | old = rcu_dereference_protected(pubsta->rates, true); | ||
693 | rcu_assign_pointer(pubsta->rates, rates); | 700 | rcu_assign_pointer(pubsta->rates, rates); |
694 | if (old) | 701 | if (old) |
695 | kfree_rcu(old, rcu_head); | 702 | kfree_rcu(old, rcu_head); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c8447af76ead..8e2952620256 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -3036,6 +3036,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3036 | * and location updates. Note that mac80211 | 3036 | * and location updates. Note that mac80211 |
3037 | * itself never looks at these frames. | 3037 | * itself never looks at these frames. |
3038 | */ | 3038 | */ |
3039 | if (!multicast && | ||
3040 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
3041 | return 0; | ||
3039 | if (ieee80211_is_public_action(hdr, skb->len)) | 3042 | if (ieee80211_is_public_action(hdr, skb->len)) |
3040 | return 1; | 3043 | return 1; |
3041 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3044 | if (!ieee80211_is_beacon(hdr->frame_control)) |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 3ed801d90f1e..124b1fdc20d0 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, | |||
208 | u32 iv32 = get_unaligned_le32(&data[4]); | 208 | u32 iv32 = get_unaligned_le32(&data[4]); |
209 | u16 iv16 = data[2] | (data[0] << 8); | 209 | u16 iv16 = data[2] | (data[0] << 8); |
210 | 210 | ||
211 | spin_lock_bh(&key->u.tkip.txlock); | 211 | spin_lock(&key->u.tkip.txlock); |
212 | ieee80211_compute_tkip_p1k(key, iv32); | 212 | ieee80211_compute_tkip_p1k(key, iv32); |
213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); | 213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); |
214 | spin_unlock_bh(&key->u.tkip.txlock); | 214 | spin_unlock(&key->u.tkip.txlock); |
215 | } | 215 | } |
216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); | 216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); |
217 | 217 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f87fa468b1f..27e07150eb46 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1740,6 +1740,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1740 | mb(); | 1740 | mb(); |
1741 | local->resuming = false; | 1741 | local->resuming = false; |
1742 | 1742 | ||
1743 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1744 | if (!ieee80211_sdata_running(sdata)) | ||
1745 | continue; | ||
1746 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
1747 | ieee80211_sta_restart(sdata); | ||
1748 | } | ||
1749 | |||
1743 | mod_timer(&local->sta_cleanup, jiffies + 1); | 1750 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1744 | #else | 1751 | #else |
1745 | WARN_ON(1); | 1752 | WARN_ON(1); |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 84c9ad7e1dca..73405e00c800 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -638,17 +638,21 @@ int wiphy_register(struct wiphy *wiphy) | |||
638 | * cfg80211_mutex lock | 638 | * cfg80211_mutex lock |
639 | */ | 639 | */ |
640 | res = rfkill_register(rdev->rfkill); | 640 | res = rfkill_register(rdev->rfkill); |
641 | if (res) | 641 | if (res) { |
642 | goto out_rm_dev; | 642 | device_del(&rdev->wiphy.dev); |
643 | |||
644 | mutex_lock(&cfg80211_mutex); | ||
645 | debugfs_remove_recursive(rdev->wiphy.debugfsdir); | ||
646 | list_del_rcu(&rdev->list); | ||
647 | wiphy_regulatory_deregister(wiphy); | ||
648 | mutex_unlock(&cfg80211_mutex); | ||
649 | return res; | ||
650 | } | ||
643 | 651 | ||
644 | rtnl_lock(); | 652 | rtnl_lock(); |
645 | rdev->wiphy.registered = true; | 653 | rdev->wiphy.registered = true; |
646 | rtnl_unlock(); | 654 | rtnl_unlock(); |
647 | return 0; | 655 | return 0; |
648 | |||
649 | out_rm_dev: | ||
650 | device_del(&rdev->wiphy.dev); | ||
651 | return res; | ||
652 | } | 656 | } |
653 | EXPORT_SYMBOL(wiphy_register); | 657 | EXPORT_SYMBOL(wiphy_register); |
654 | 658 | ||
@@ -866,7 +870,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
866 | #endif | 870 | #endif |
867 | __cfg80211_disconnect(rdev, dev, | 871 | __cfg80211_disconnect(rdev, dev, |
868 | WLAN_REASON_DEAUTH_LEAVING, true); | 872 | WLAN_REASON_DEAUTH_LEAVING, true); |
869 | cfg80211_mlme_down(rdev, dev); | ||
870 | wdev_unlock(wdev); | 873 | wdev_unlock(wdev); |
871 | break; | 874 | break; |
872 | case NL80211_IFTYPE_MESH_POINT: | 875 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afa283841e8c..dfdb5e643211 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -7577,6 +7577,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg, | |||
7577 | &tcp->payload_tok)) | 7577 | &tcp->payload_tok)) |
7578 | return -ENOBUFS; | 7578 | return -ENOBUFS; |
7579 | 7579 | ||
7580 | nla_nest_end(msg, nl_tcp); | ||
7581 | |||
7580 | return 0; | 7582 | return 0; |
7581 | } | 7583 | } |
7582 | 7584 | ||
@@ -9970,6 +9972,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
9970 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9972 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9971 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 9973 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, |
9972 | netdev->ifindex)) || | 9974 | netdev->ifindex)) || |
9975 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | ||
9973 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | 9976 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || |
9974 | (sig_dbm && | 9977 | (sig_dbm && |
9975 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | 9978 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || |
@@ -10010,6 +10013,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | |||
10010 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10013 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
10011 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 10014 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, |
10012 | netdev->ifindex)) || | 10015 | netdev->ifindex)) || |
10016 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | ||
10013 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || | 10017 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || |
10014 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || | 10018 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || |
10015 | (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) | 10019 | (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a9dc5c736df0..8b5eddfba1e5 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -961,7 +961,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
961 | /* was it connected by userspace SME? */ | 961 | /* was it connected by userspace SME? */ |
962 | if (!wdev->conn) { | 962 | if (!wdev->conn) { |
963 | cfg80211_mlme_down(rdev, dev); | 963 | cfg80211_mlme_down(rdev, dev); |
964 | return 0; | 964 | goto disconnect; |
965 | } | 965 | } |
966 | 966 | ||
967 | if (wdev->sme_state == CFG80211_SME_CONNECTING && | 967 | if (wdev->sme_state == CFG80211_SME_CONNECTING && |
@@ -987,6 +987,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
987 | return err; | 987 | return err; |
988 | } | 988 | } |
989 | 989 | ||
990 | disconnect: | ||
990 | if (wdev->sme_state == CFG80211_SME_CONNECTED) | 991 | if (wdev->sme_state == CFG80211_SME_CONNECTED) |
991 | __cfg80211_disconnected(dev, NULL, 0, 0, false); | 992 | __cfg80211_disconnected(dev, NULL, 0, 0, false); |
992 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) | 993 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ecd4fcec3c94..5755bc14abbd 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2441,6 +2441,7 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2441 | TP_STRUCT__entry( | 2441 | TP_STRUCT__entry( |
2442 | WIPHY_ENTRY | 2442 | WIPHY_ENTRY |
2443 | WDEV_ENTRY | 2443 | WDEV_ENTRY |
2444 | __field(bool, non_wireless) | ||
2444 | __field(bool, disconnect) | 2445 | __field(bool, disconnect) |
2445 | __field(bool, magic_pkt) | 2446 | __field(bool, magic_pkt) |
2446 | __field(bool, gtk_rekey_failure) | 2447 | __field(bool, gtk_rekey_failure) |
@@ -2449,20 +2450,22 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2449 | __field(bool, rfkill_release) | 2450 | __field(bool, rfkill_release) |
2450 | __field(s32, pattern_idx) | 2451 | __field(s32, pattern_idx) |
2451 | __field(u32, packet_len) | 2452 | __field(u32, packet_len) |
2452 | __dynamic_array(u8, packet, wakeup->packet_present_len) | 2453 | __dynamic_array(u8, packet, |
2454 | wakeup ? wakeup->packet_present_len : 0) | ||
2453 | ), | 2455 | ), |
2454 | TP_fast_assign( | 2456 | TP_fast_assign( |
2455 | WIPHY_ASSIGN; | 2457 | WIPHY_ASSIGN; |
2456 | WDEV_ASSIGN; | 2458 | WDEV_ASSIGN; |
2457 | __entry->disconnect = wakeup->disconnect; | 2459 | __entry->non_wireless = !wakeup; |
2458 | __entry->magic_pkt = wakeup->magic_pkt; | 2460 | __entry->disconnect = wakeup ? wakeup->disconnect : false; |
2459 | __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure; | 2461 | __entry->magic_pkt = wakeup ? wakeup->magic_pkt : false; |
2460 | __entry->eap_identity_req = wakeup->eap_identity_req; | 2462 | __entry->gtk_rekey_failure = wakeup ? wakeup->gtk_rekey_failure : false; |
2461 | __entry->four_way_handshake = wakeup->four_way_handshake; | 2463 | __entry->eap_identity_req = wakeup ? wakeup->eap_identity_req : false; |
2462 | __entry->rfkill_release = wakeup->rfkill_release; | 2464 | __entry->four_way_handshake = wakeup ? wakeup->four_way_handshake : false; |
2463 | __entry->pattern_idx = wakeup->pattern_idx; | 2465 | __entry->rfkill_release = wakeup ? wakeup->rfkill_release : false; |
2464 | __entry->packet_len = wakeup->packet_len; | 2466 | __entry->pattern_idx = wakeup ? wakeup->pattern_idx : false; |
2465 | if (wakeup->packet && wakeup->packet_present_len) | 2467 | __entry->packet_len = wakeup ? wakeup->packet_len : false; |
2468 | if (wakeup && wakeup->packet && wakeup->packet_present_len) | ||
2466 | memcpy(__get_dynamic_array(packet), wakeup->packet, | 2469 | memcpy(__get_dynamic_array(packet), wakeup->packet, |
2467 | wakeup->packet_present_len); | 2470 | wakeup->packet_present_len); |
2468 | ), | 2471 | ), |