rt2x00: merge beacon setup fixes, disable unused hw beacon slots
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
1 commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc
2 Author: Stanislaw Gruszka <sgruszka@redhat.com>
3 Date: Thu Jun 5 13:52:27 2014 +0200
4
5 rt2x00: do not initialize BCN_OFFSET registers
6
7 We setup BCN_OFFSET{0,1} registers dynamically, don't have to
8 initialize them.
9
10 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
11
12 commit e5c58ca7a48d4c82f282749a978052c47fd95998
13 Author: Stanislaw Gruszka <sgruszka@redhat.com>
14 Date: Thu Jun 5 13:52:26 2014 +0200
15
16 rt2x00: change order when stop beaconing
17
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.
21
22 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
23
24 commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744
25 Author: Stanislaw Gruszka <sgruszka@redhat.com>
26 Date: Thu Jun 5 13:52:25 2014 +0200
27
28 rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM
29
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.
33
34 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
35
36 commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9
37 Author: Stanislaw Gruszka <sgruszka@redhat.com>
38 Date: Thu Jun 5 13:52:24 2014 +0200
39
40 rt2x00: change beaconing setup on RT2800
41
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.
45
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.
49
50 Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
51 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
52
53 commit 916e591b2cc41f7e572992175ca56d866d7bc958
54 Author: Stanislaw Gruszka <sgruszka@redhat.com>
55 Date: Thu Jun 5 13:52:23 2014 +0200
56
57 rt2x00: change beaconing locking
58
59 This patch is needed for further changes to keep global variables
60 consistent when changing beaconing on diffrent vif's.
61
62 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
63
64 commit 930b0dffd1731f3f418f9132faea720a23b7af61
65 Author: Johannes Berg <johannes.berg@intel.com>
66 Date: Tue Jun 3 11:18:47 2014 +0200
67
68 mac80211: fix station/driver powersave race
69
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
76 the unblock work
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
82 WLAN_STA_PS_STA flags
83
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
89 dropped.
90
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.
97
98 Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
99 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
100
101 commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
102 Author: Felix Fietkau <nbd@openwrt.org>
103 Date: Fri May 23 19:58:14 2014 +0200
104
105 mac80211: reduce packet loss notifications under load
106
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.
110
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.
113
114 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
115
116 commit 7b7843a36fbcc568834404c7430ff895d8502131
117 Author: Felix Fietkau <nbd@openwrt.org>
118 Date: Fri May 23 19:26:32 2014 +0200
119
120 mac80211: fix a memory leak on sta rate selection table
121
122 Cc: stable@vger.kernel.org
123 Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
124 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
125
126 commit 96892d6aa0a153423070addf3070bc79578b3897
127 Author: Felix Fietkau <nbd@openwrt.org>
128 Date: Mon May 19 21:20:49 2014 +0200
129
130 ath9k: avoid passing buffers to the hardware during flush
131
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.
136
137 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
138
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.
144 */
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,
147 + bool flush)
148 {
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
152 common->rx_bufsize,
153 0);
154
155 - if (sc->rx.rxlink == NULL)
156 - ath9k_hw_putrxbuf(ah, bf->bf_daddr);
157 - else
158 + if (sc->rx.rxlink)
159 *sc->rx.rxlink = bf->bf_daddr;
160 + else if (!flush)
161 + ath9k_hw_putrxbuf(ah, bf->bf_daddr);
162
163 sc->rx.rxlink = &ds->ds_link;
164 }
165
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,
168 + bool flush)
169 {
170 if (sc->rx.buf_hold)
171 - ath_rx_buf_link(sc, sc->rx.buf_hold);
172 + ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
173
174 sc->rx.buf_hold = bf;
175 }
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);
182 }
183
184 /* We could have deleted elements so the list may be empty now */
185 @@ -1118,12 +1120,12 @@ requeue_drop_frag:
186 requeue:
187 list_add_tail(&bf->list, &sc->rx.rxbuf);
188
189 - if (edma) {
190 - ath_rx_edma_buf_link(sc, qtype);
191 - } else {
192 - ath_rx_buf_relink(sc, bf);
193 + if (!edma) {
194 + ath_rx_buf_relink(sc, bf, flush);
195 if (!flush)
196 ath9k_hw_rxena(ah);
197 + } else if (!flush) {
198 + ath_rx_edma_buf_link(sc, qtype);
199 }
200
201 if (!budget--)
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
205 struct ps_data *ps;
206
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
215
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);
219
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);
225
226 - cancel_work_sync(&sta->drv_unblock_wk);
227 + cancel_work_sync(&sta->drv_deliver_wk);
228
229 /*
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
232 */
233 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
234 {
235 + struct ieee80211_sta_rates *rates;
236 int i;
237
238 if (sta->rate_ctrl)
239 @@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
240 kfree(sta->tx_lat);
241 }
242
243 + rates = rcu_dereference_protected(sta->sta.rates, true);
244 + if (rates)
245 + kfree(rates);
246 +
247 sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
248
249 kfree(sta);
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);
252 }
253
254 -static void sta_unblock(struct work_struct *wk)
255 +static void sta_deliver_ps_frames(struct work_struct *wk)
256 {
257 struct sta_info *sta;
258
259 - sta = container_of(wk, struct sta_info, drv_unblock_wk);
260 + sta = container_of(wk, struct sta_info, drv_deliver_wk);
261
262 if (sta->dead)
263 return;
264
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);
270 - local_bh_enable();
271 - } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
272 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
273 -
274 - local_bh_disable();
275 + else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
276 ieee80211_sta_ps_deliver_poll_response(sta);
277 - local_bh_enable();
278 - } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
279 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
280 -
281 - local_bh_disable();
282 + else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
283 ieee80211_sta_ps_deliver_uapsd(sta);
284 - local_bh_enable();
285 - } else
286 - clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
287 + local_bh_enable();
288 }
289
290 static int sta_prepare_rate_control(struct ieee80211_local *local,
291 @@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
292
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
301 }
302
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);
306 +
307 + /* now we're no longer in the deliver code */
308 + clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
309 +
310 + /* The station might have polled and then woken up before we responded,
311 + * so clear these flags now to avoid them sticking around.
312 + */
313 + clear_sta_flag(sta, WLAN_STA_PSPOLL);
314 + clear_sta_flag(sta, WLAN_STA_UAPSD);
315 spin_unlock(&sta->ps_lock);
316
317 atomic_dec(&ps->num_sta_ps);
318 @@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
319
320 trace_api_sta_block_awake(sta->local, pubsta, block);
321
322 - if (block)
323 + if (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);
327 + return;
328 + }
329 +
330 + if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
331 + return;
332 +
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);
342 + } else {
343 + clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
344 + }
345 }
346 EXPORT_SYMBOL(ieee80211_sta_block_awake);
347
348 --- a/net/mac80211/status.c
349 +++ b/net/mac80211/status.c
350 @@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
351 */
352 #define STA_LOST_PKT_THRESHOLD 50
353
354 +static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
355 +{
356 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
357 +
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))
361 + return;
362 +
363 + if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
364 + return;
365 +
366 + cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
367 + sta->lost_packets, GFP_ATOMIC);
368 + sta->lost_packets = 0;
369 +}
370 +
371 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
372 {
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,
380 - sta->sta.addr,
381 - sta->lost_packets,
382 - GFP_ATOMIC);
383 - sta->lost_packets = 0;
384 + } else {
385 + ieee80211_lost_packet(sta, skb);
386 }
387 }
388
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 *
392 return;
393 }
394
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);
398 }
399
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,
404 WLAN_STA_MPSP_OWNER,
405 WLAN_STA_MPSP_RECIPIENT,
406 + WLAN_STA_PS_DELIVER,
407 };
408
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;
421 spinlock_t lock;
422
423 - struct work_struct drv_unblock_wk;
424 + struct work_struct drv_deliver_wk;
425
426 u16 listen_interval;
427
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
431 return TX_CONTINUE;
432
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);
439
440 @@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
441 * ahead and Tx the packet.
442 */
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);
448 return TX_CONTINUE;
449 }
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));
454 }
455
456 +static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
457 +{
458 + struct data_queue *queue = rt2x00dev->bcn;
459 + struct queue_entry *entry;
460 + int i, bcn_num = 0;
461 + u64 off, reg = 0;
462 + u32 bssid_dw1;
463 +
464 + /*
465 + * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
466 + */
467 + for (i = 0; i < queue->limit; i++) {
468 + entry = &queue->entries[i];
469 + if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
470 + continue;
471 + off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
472 + reg |= off << (8 * bcn_num);
473 + bcn_num++;
474 + }
475 +
476 + WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
477 +
478 + rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
479 + rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
480 +
481 + /*
482 + * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
483 + */
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);
488 +}
489 +
490 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
491 {
492 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
493 @@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
494
495 rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
496 entry->skb->len + padding_len);
497 + __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
498 +
499 + /*
500 + * Change global beacons settings.
501 + */
502 + rt2800_update_beacons_setup(rt2x00dev);
503
504 /*
505 * Restore beaconing state.
506 @@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
507 * Clear beacon.
508 */
509 rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
510 + __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
511
512 /*
513 + * Change global beacons settings.
514 + */
515 + rt2800_update_beacons_setup(rt2x00dev);
516 + /*
517 * Restore beaconing state.
518 */
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(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
524 - rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
525 + rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
526 conf->bssid[1] = cpu_to_le32(reg);
527 }
528
529 @@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct
530 if (ret)
531 return ret;
532
533 - rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
534 - rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
535 - rt2800_get_beacon_offset(rt2x00dev, 0));
536 - rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
537 - rt2800_get_beacon_offset(rt2x00dev, 1));
538 - rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
539 - rt2800_get_beacon_offset(rt2x00dev, 2));
540 - rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
541 - rt2800_get_beacon_offset(rt2x00dev, 3));
542 - rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
543 -
544 - rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
545 - rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
546 - rt2800_get_beacon_offset(rt2x00dev, 4));
547 - rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
548 - rt2800_get_beacon_offset(rt2x00dev, 5));
549 - rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
550 - rt2800_get_beacon_offset(rt2x00dev, 6));
551 - rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
552 - rt2800_get_beacon_offset(rt2x00dev, 7));
553 - rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
554 -
555 rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
556 rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
557
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))
562 return;
563
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);
569 + }
570 }
571
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.
575 */
576 WARN_ON(rt2x00_is_usb(rt2x00dev));
577 - rt2x00queue_update_beacon_locked(rt2x00dev, vif);
578 + rt2x00queue_update_beacon(rt2x00dev, vif);
579 }
580
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.
586 */
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;
592 - /*
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.
596 - */
597 - rt2x00queue_clear_beacon(rt2x00dev, vif);
598
599 if (rt2x00dev->intf_beaconing == 0) {
600 /*
601 * Last beaconing interface disabled
602 * -> stop beacon queue.
603 */
604 - mutex_lock(&intf->beacon_skb_mutex);
605 rt2x00queue_stop_queue(rt2x00dev->bcn);
606 - mutex_unlock(&intf->beacon_skb_mutex);
607 }
608 + /*
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.
612 + */
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.
620 */
621 - mutex_lock(&intf->beacon_skb_mutex);
622 rt2x00queue_start_queue(rt2x00dev->bcn);
623 - mutex_unlock(&intf->beacon_skb_mutex);
624 }
625 }
626 + mutex_unlock(&intf->beacon_skb_mutex);
627 }
628
629 /*
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))
634 return -ENOBUFS;
635
636 - mutex_lock(&intf->beacon_skb_mutex);
637 -
638 /*
639 * Clean up the beacon skb.
640 */
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);
644
645 - mutex_unlock(&intf->beacon_skb_mutex);
646 -
647 return 0;
648 }
649
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)
654 {
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
658
659 }
660
661 -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
662 - struct ieee80211_vif *vif)
663 -{
664 - struct rt2x00_intf *intf = vif_to_intf(vif);
665 - int ret;
666 -
667 - mutex_lock(&intf->beacon_skb_mutex);
668 - ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
669 - mutex_unlock(&intf->beacon_skb_mutex);
670 -
671 - return ret;
672 -}
673 -
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 {
680 */
681 enum queue_entry_flags {
682 ENTRY_BCN_ASSIGNED,
683 + ENTRY_BCN_ENABLED,
684 ENTRY_OWNER_DEVICE_DATA,
685 ENTRY_DATA_PENDING,
686 ENTRY_DATA_IO_FAILED,