1 commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc
2 Author: Stanislaw Gruszka <sgruszka@redhat.com>
3 Date: Thu Jun 5 13:52:27 2014 +0200
5 rt2x00: do not initialize BCN_OFFSET registers
7 We setup BCN_OFFSET{0,1} registers dynamically, don't have to
10 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
12 commit e5c58ca7a48d4c82f282749a978052c47fd95998
13 Author: Stanislaw Gruszka <sgruszka@redhat.com>
14 Date: Thu Jun 5 13:52:26 2014 +0200
16 rt2x00: change order when stop beaconing
18 When no beaconing is needed, first stop beacon queue (disable beaconing
19 globally) to avoid possible sending of not prepared beacon on short
20 period after clearing beacon and before stop of BCN queue.
22 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
24 commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744
25 Author: Stanislaw Gruszka <sgruszka@redhat.com>
26 Date: Thu Jun 5 13:52:25 2014 +0200
28 rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM
30 We setup MAC_BSSID_DW1_BSS_BCN_NUM dynamically when numbers of active
31 beacons increase. Change default to 0 to tell hardware that we want to
32 send only one beacon as default.
34 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
36 commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9
37 Author: Stanislaw Gruszka <sgruszka@redhat.com>
38 Date: Thu Jun 5 13:52:24 2014 +0200
40 rt2x00: change beaconing setup on RT2800
42 As reported by Matthias, on 5572 chip, even if we clear up TXWI
43 of corresponding beacon, hardware still try to send it or do other
44 action that increase power consumption peak up to 1A.
46 To avoid the issue, setup beaconing dynamically by configuring offsets
47 of currently active beacons and MAC_BSSID_DW1_BSS_BCN_NUM variable,
48 which limit number of beacons that hardware will try to send.
50 Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
51 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
53 commit 916e591b2cc41f7e572992175ca56d866d7bc958
54 Author: Stanislaw Gruszka <sgruszka@redhat.com>
55 Date: Thu Jun 5 13:52:23 2014 +0200
57 rt2x00: change beaconing locking
59 This patch is needed for further changes to keep global variables
60 consistent when changing beaconing on diffrent vif's.
62 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
64 commit 930b0dffd1731f3f418f9132faea720a23b7af61
65 Author: Johannes Berg <johannes.berg@intel.com>
66 Date: Tue Jun 3 11:18:47 2014 +0200
68 mac80211: fix station/driver powersave race
70 It is currently possible to have a race due to the station PS
71 unblock work like this:
72 * station goes to sleep with frames buffered in the driver
73 * driver blocks wakeup
74 * station wakes up again
75 * driver flushes/returns frames, and unblocks, which schedules
77 * unblock work starts to run, and checks that the station is
78 awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
79 * we process a received frame with PM=1, setting the flag again
80 * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
81 to the driver, and then clearing the WLAN_STA_PS_DRIVER and
84 In this scenario, mac80211 will think that the station is awake,
85 while it really is asleep, and any TX'ed frames should be filtered
86 by the device (it will know that the station is sleeping) but then
87 passed to mac80211 again, which will not buffer it either as it
88 thinks the station is awake, and eventually the packets will be
91 Fix this by moving the clearing of the flags to exactly where we
92 learn about the situation. This creates a problem of reordering,
93 so introduce another flag indicating that delivery is being done,
94 this new flag also queues frames and is cleared only while the
95 spinlock is held (which the queuing code also holds) so that any
96 concurrent delivery/TX is handled correctly.
98 Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
99 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
101 commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
102 Author: Felix Fietkau <nbd@openwrt.org>
103 Date: Fri May 23 19:58:14 2014 +0200
105 mac80211: reduce packet loss notifications under load
107 During strong signal fluctuations under high throughput, few consecutive
108 failed A-MPDU transmissions can easily trigger packet loss notification,
109 and thus (in AP mode) client disconnection.
111 Reduce the number of false positives by checking the A-MPDU status flag
112 and treating a failed A-MPDU as a single packet.
114 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
116 commit 7b7843a36fbcc568834404c7430ff895d8502131
117 Author: Felix Fietkau <nbd@openwrt.org>
118 Date: Fri May 23 19:26:32 2014 +0200
120 mac80211: fix a memory leak on sta rate selection table
122 Cc: stable@vger.kernel.org
123 Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
124 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
126 commit 96892d6aa0a153423070addf3070bc79578b3897
127 Author: Felix Fietkau <nbd@openwrt.org>
128 Date: Mon May 19 21:20:49 2014 +0200
130 ath9k: avoid passing buffers to the hardware during flush
132 The commit "ath9k: fix possible hang on flush" changed the receive code
133 to always link rx descriptors of processed frames, even when flushing.
134 In some cases, this leads to flushed rx buffers being passed to the
135 hardware while rx is already stopped.
137 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
139 --- a/drivers/net/wireless/ath/ath9k/recv.c
140 +++ b/drivers/net/wireless/ath/ath9k/recv.c
141 @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
142 * buffer (or rx fifo). This can incorrectly acknowledge packets
143 * to a sender if last desc is self-linked.
145 -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
146 +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
149 struct ath_hw *ah = sc->sc_ah;
150 struct ath_common *common = ath9k_hw_common(ah);
151 @@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
155 - if (sc->rx.rxlink == NULL)
156 - ath9k_hw_putrxbuf(ah, bf->bf_daddr);
159 *sc->rx.rxlink = bf->bf_daddr;
161 + ath9k_hw_putrxbuf(ah, bf->bf_daddr);
163 sc->rx.rxlink = &ds->ds_link;
166 -static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
167 +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
171 - ath_rx_buf_link(sc, sc->rx.buf_hold);
172 + ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
174 sc->rx.buf_hold = bf;
176 @@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
177 sc->rx.buf_hold = NULL;
178 sc->rx.rxlink = NULL;
179 list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
180 - ath_rx_buf_link(sc, bf);
181 + ath_rx_buf_link(sc, bf, false);
184 /* We could have deleted elements so the list may be empty now */
185 @@ -1118,12 +1120,12 @@ requeue_drop_frag:
187 list_add_tail(&bf->list, &sc->rx.rxbuf);
190 - ath_rx_edma_buf_link(sc, qtype);
192 - ath_rx_buf_relink(sc, bf);
194 + ath_rx_buf_relink(sc, bf, flush);
197 + } else if (!flush) {
198 + ath_rx_edma_buf_link(sc, qtype);
202 --- a/net/mac80211/sta_info.c
203 +++ b/net/mac80211/sta_info.c
204 @@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct
207 if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
208 - test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
209 + test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
210 + test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
211 if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
212 sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
213 ps = &sdata->bss->ps;
214 @@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct
216 clear_sta_flag(sta, WLAN_STA_PS_STA);
217 clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
218 + clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
220 atomic_dec(&ps->num_sta_ps);
221 sta_info_recalc_tim(sta);
222 @@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct
223 if (ieee80211_vif_is_mesh(&sdata->vif))
224 mesh_sta_cleanup(sta);
226 - cancel_work_sync(&sta->drv_unblock_wk);
227 + cancel_work_sync(&sta->drv_deliver_wk);
230 * Destroy aggregation state here. It would be nice to wait for the
231 @@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
233 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
235 + struct ieee80211_sta_rates *rates;
239 @@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
243 + rates = rcu_dereference_protected(sta->sta.rates, true);
247 sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
250 @@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
251 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
254 -static void sta_unblock(struct work_struct *wk)
255 +static void sta_deliver_ps_frames(struct work_struct *wk)
257 struct sta_info *sta;
259 - sta = container_of(wk, struct sta_info, drv_unblock_wk);
260 + sta = container_of(wk, struct sta_info, drv_deliver_wk);
265 - if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
266 - local_bh_disable();
267 + local_bh_disable();
268 + if (!test_sta_flag(sta, WLAN_STA_PS_STA))
269 ieee80211_sta_ps_deliver_wakeup(sta);
271 - } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
272 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
274 - local_bh_disable();
275 + else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
276 ieee80211_sta_ps_deliver_poll_response(sta);
278 - } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
279 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
281 - local_bh_disable();
282 + else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
283 ieee80211_sta_ps_deliver_uapsd(sta);
286 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
290 static int sta_prepare_rate_control(struct ieee80211_local *local,
291 @@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
293 spin_lock_init(&sta->lock);
294 spin_lock_init(&sta->ps_lock);
295 - INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
296 + INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
297 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
298 mutex_init(&sta->ampdu_mlme.mtx);
299 #ifdef CPTCFG_MAC80211_MESH
300 @@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
303 ieee80211_add_pending_skbs(local, &pending);
304 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
305 - clear_sta_flag(sta, WLAN_STA_PS_STA);
307 + /* now we're no longer in the deliver code */
308 + clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
310 + /* The station might have polled and then woken up before we responded,
311 + * so clear these flags now to avoid them sticking around.
313 + clear_sta_flag(sta, WLAN_STA_PSPOLL);
314 + clear_sta_flag(sta, WLAN_STA_UAPSD);
315 spin_unlock(&sta->ps_lock);
317 atomic_dec(&ps->num_sta_ps);
318 @@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
320 trace_api_sta_block_awake(sta->local, pubsta, block);
324 set_sta_flag(sta, WLAN_STA_PS_DRIVER);
325 - else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
326 - ieee80211_queue_work(hw, &sta->drv_unblock_wk);
330 + if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
333 + if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
334 + set_sta_flag(sta, WLAN_STA_PS_DELIVER);
335 + clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
336 + ieee80211_queue_work(hw, &sta->drv_deliver_wk);
337 + } else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
338 + test_sta_flag(sta, WLAN_STA_UAPSD)) {
339 + /* must be asleep in this case */
340 + clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
341 + ieee80211_queue_work(hw, &sta->drv_deliver_wk);
343 + clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
346 EXPORT_SYMBOL(ieee80211_sta_block_awake);
348 --- a/net/mac80211/status.c
349 +++ b/net/mac80211/status.c
350 @@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
352 #define STA_LOST_PKT_THRESHOLD 50
354 +static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
356 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
358 + /* This packet was aggregated but doesn't carry status info */
359 + if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
360 + !(info->flags & IEEE80211_TX_STAT_AMPDU))
363 + if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
366 + cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
367 + sta->lost_packets, GFP_ATOMIC);
368 + sta->lost_packets = 0;
371 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
373 struct sk_buff *skb2;
374 @@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
375 if (info->flags & IEEE80211_TX_STAT_ACK) {
376 if (sta->lost_packets)
377 sta->lost_packets = 0;
378 - } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
379 - cfg80211_cqm_pktloss_notify(sta->sdata->dev,
383 - sta->lost_packets = 0;
385 + ieee80211_lost_packet(sta, skb);
389 --- a/net/mac80211/rx.c
390 +++ b/net/mac80211/rx.c
391 @@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
395 + set_sta_flag(sta, WLAN_STA_PS_DELIVER);
396 + clear_sta_flag(sta, WLAN_STA_PS_STA);
397 ieee80211_sta_ps_deliver_wakeup(sta);
400 --- a/net/mac80211/sta_info.h
401 +++ b/net/mac80211/sta_info.h
402 @@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
403 WLAN_STA_TOFFSET_KNOWN,
405 WLAN_STA_MPSP_RECIPIENT,
406 + WLAN_STA_PS_DELIVER,
409 #define ADDBA_RESP_INTERVAL HZ
410 @@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
411 * @last_rx_rate_vht_nss: rx status nss of last data packet
412 * @lock: used for locking all fields that require locking, see comments
413 * in the header file.
414 - * @drv_unblock_wk: used for driver PS unblocking
415 + * @drv_deliver_wk: used for delivering frames after driver PS unblocking
416 * @listen_interval: listen interval of this station, when we're acting as AP
417 * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
418 * @ps_lock: used for powersave (when mac80211 is the AP) related locking
419 @@ -345,7 +346,7 @@ struct sta_info {
420 void *rate_ctrl_priv;
423 - struct work_struct drv_unblock_wk;
424 + struct work_struct drv_deliver_wk;
428 --- a/net/mac80211/tx.c
429 +++ b/net/mac80211/tx.c
430 @@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
433 if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
434 - test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
435 + test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
436 + test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
437 !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
438 int ac = skb_get_queue_mapping(tx->skb);
440 @@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
441 * ahead and Tx the packet.
443 if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
444 - !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
445 + !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
446 + !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
447 spin_unlock(&sta->ps_lock);
450 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
451 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
452 @@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offse
453 return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
456 +static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
458 + struct data_queue *queue = rt2x00dev->bcn;
459 + struct queue_entry *entry;
460 + int i, bcn_num = 0;
465 + * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
467 + for (i = 0; i < queue->limit; i++) {
468 + entry = &queue->entries[i];
469 + if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
471 + off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
472 + reg |= off << (8 * bcn_num);
476 + WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
478 + rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
479 + rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
482 + * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
484 + rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
485 + rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
486 + bcn_num > 0 ? bcn_num - 1 : 0);
487 + rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
490 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
492 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
493 @@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
495 rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
496 entry->skb->len + padding_len);
497 + __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
500 + * Change global beacons settings.
502 + rt2800_update_beacons_setup(rt2x00dev);
505 * Restore beaconing state.
506 @@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
509 rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
510 + __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
513 + * Change global beacons settings.
515 + rt2800_update_beacons_setup(rt2x00dev);
517 * Restore beaconing state.
519 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
520 @@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_de
521 if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
522 reg = le32_to_cpu(conf->bssid[1]);
523 rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3);
524 - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
525 + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
526 conf->bssid[1] = cpu_to_le32(reg);
529 @@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct
533 - rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®);
534 - rt2x00_set_field32(®, BCN_OFFSET0_BCN0,
535 - rt2800_get_beacon_offset(rt2x00dev, 0));
536 - rt2x00_set_field32(®, BCN_OFFSET0_BCN1,
537 - rt2800_get_beacon_offset(rt2x00dev, 1));
538 - rt2x00_set_field32(®, BCN_OFFSET0_BCN2,
539 - rt2800_get_beacon_offset(rt2x00dev, 2));
540 - rt2x00_set_field32(®, BCN_OFFSET0_BCN3,
541 - rt2800_get_beacon_offset(rt2x00dev, 3));
542 - rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
544 - rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®);
545 - rt2x00_set_field32(®, BCN_OFFSET1_BCN4,
546 - rt2800_get_beacon_offset(rt2x00dev, 4));
547 - rt2x00_set_field32(®, BCN_OFFSET1_BCN5,
548 - rt2800_get_beacon_offset(rt2x00dev, 5));
549 - rt2x00_set_field32(®, BCN_OFFSET1_BCN6,
550 - rt2800_get_beacon_offset(rt2x00dev, 6));
551 - rt2x00_set_field32(®, BCN_OFFSET1_BCN7,
552 - rt2800_get_beacon_offset(rt2x00dev, 7));
553 - rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
555 rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
556 rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
558 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
559 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
560 @@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_ite
561 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
564 - if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
565 + if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
566 + mutex_lock(&intf->beacon_skb_mutex);
567 rt2x00queue_update_beacon(rt2x00dev, vif);
568 + mutex_unlock(&intf->beacon_skb_mutex);
572 static void rt2x00lib_intf_scheduled(struct work_struct *work)
573 @@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(
574 * never be called for USB devices.
576 WARN_ON(rt2x00_is_usb(rt2x00dev));
577 - rt2x00queue_update_beacon_locked(rt2x00dev, vif);
578 + rt2x00queue_update_beacon(rt2x00dev, vif);
581 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
582 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c
583 +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
584 @@ -624,25 +624,24 @@ void rt2x00mac_bss_info_changed(struct i
585 * Start/stop beaconing.
587 if (changes & BSS_CHANGED_BEACON_ENABLED) {
588 + mutex_lock(&intf->beacon_skb_mutex);
589 if (!bss_conf->enable_beacon && intf->enable_beacon) {
590 rt2x00dev->intf_beaconing--;
591 intf->enable_beacon = false;
593 - * Clear beacon in the H/W for this vif. This is needed
594 - * to disable beaconing on this particular interface
595 - * and keep it running on other interfaces.
597 - rt2x00queue_clear_beacon(rt2x00dev, vif);
599 if (rt2x00dev->intf_beaconing == 0) {
601 * Last beaconing interface disabled
602 * -> stop beacon queue.
604 - mutex_lock(&intf->beacon_skb_mutex);
605 rt2x00queue_stop_queue(rt2x00dev->bcn);
606 - mutex_unlock(&intf->beacon_skb_mutex);
609 + * Clear beacon in the H/W for this vif. This is needed
610 + * to disable beaconing on this particular interface
611 + * and keep it running on other interfaces.
613 + rt2x00queue_clear_beacon(rt2x00dev, vif);
614 } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
615 rt2x00dev->intf_beaconing++;
616 intf->enable_beacon = true;
617 @@ -658,11 +657,10 @@ void rt2x00mac_bss_info_changed(struct i
618 * First beaconing interface enabled
619 * -> start beacon queue.
621 - mutex_lock(&intf->beacon_skb_mutex);
622 rt2x00queue_start_queue(rt2x00dev->bcn);
623 - mutex_unlock(&intf->beacon_skb_mutex);
626 + mutex_unlock(&intf->beacon_skb_mutex);
630 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
631 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
632 @@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x
633 if (unlikely(!intf->beacon))
636 - mutex_lock(&intf->beacon_skb_mutex);
639 * Clean up the beacon skb.
641 @@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x
642 if (rt2x00dev->ops->lib->clear_beacon)
643 rt2x00dev->ops->lib->clear_beacon(intf->beacon);
645 - mutex_unlock(&intf->beacon_skb_mutex);
650 -int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
651 - struct ieee80211_vif *vif)
652 +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
653 + struct ieee80211_vif *vif)
655 struct rt2x00_intf *intf = vif_to_intf(vif);
656 struct skb_frame_desc *skbdesc;
657 @@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str
661 -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
662 - struct ieee80211_vif *vif)
664 - struct rt2x00_intf *intf = vif_to_intf(vif);
667 - mutex_lock(&intf->beacon_skb_mutex);
668 - ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
669 - mutex_unlock(&intf->beacon_skb_mutex);
674 bool rt2x00queue_for_each_entry(struct data_queue *queue,
675 enum queue_index start,
676 enum queue_index end,
677 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h
678 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
679 @@ -353,6 +353,7 @@ struct txentry_desc {
681 enum queue_entry_flags {
684 ENTRY_OWNER_DEVICE_DATA,
686 ENTRY_DATA_IO_FAILED,