df492bb81277fd4a3a6e7b3fd8690a4b7fb2dc1b
[librecmc/librecmc.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
1 commit 60ccc107c9b9fb732fdee1f76bb2dad44f0e1798
2 Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
3 Date:   Tue May 27 16:58:02 2014 +0530
4
5     ath9k: Fix deadlock while updating p2p beacon timer
6     
7     pm_lock is taken twice while syncing HW TSF of p2p vif.
8     Fix this by taking the lock at caller side.
9     
10     Cc: Felix Fietkau <nbd@openwrt.org>
11     Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
12     Signed-off-by: John W. Linville <linville@tuxdriver.com>
13
14 commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc
15 Author: Stanislaw Gruszka <sgruszka@redhat.com>
16 Date:   Thu Jun 5 13:52:27 2014 +0200
17
18     rt2x00: do not initialize BCN_OFFSET registers
19     
20     We setup BCN_OFFSET{0,1} registers dynamically, don't have to
21     initialize them.
22     
23     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
24
25 commit e5c58ca7a48d4c82f282749a978052c47fd95998
26 Author: Stanislaw Gruszka <sgruszka@redhat.com>
27 Date:   Thu Jun 5 13:52:26 2014 +0200
28
29     rt2x00: change order when stop beaconing
30     
31     When no beaconing is needed, first stop beacon queue (disable beaconing
32     globally) to avoid possible sending of not prepared beacon on short
33     period after clearing beacon and before stop of BCN queue.
34     
35     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
36
37 commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744
38 Author: Stanislaw Gruszka <sgruszka@redhat.com>
39 Date:   Thu Jun 5 13:52:25 2014 +0200
40
41     rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM
42     
43     We setup MAC_BSSID_DW1_BSS_BCN_NUM dynamically when numbers of active
44     beacons increase. Change default to 0 to tell hardware that we want to
45     send only one beacon as default.
46     
47     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
48
49 commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9
50 Author: Stanislaw Gruszka <sgruszka@redhat.com>
51 Date:   Thu Jun 5 13:52:24 2014 +0200
52
53     rt2x00: change beaconing setup on RT2800
54     
55     As reported by Matthias, on 5572 chip, even if we clear up TXWI
56     of corresponding beacon, hardware still try to send it or do other
57     action that increase power consumption peak up to 1A.
58     
59     To avoid the issue, setup beaconing dynamically by configuring offsets
60     of currently active beacons and MAC_BSSID_DW1_BSS_BCN_NUM variable,
61     which limit number of beacons that hardware will try to send.
62     
63     Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
64     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
65
66 commit 916e591b2cc41f7e572992175ca56d866d7bc958
67 Author: Stanislaw Gruszka <sgruszka@redhat.com>
68 Date:   Thu Jun 5 13:52:23 2014 +0200
69
70     rt2x00: change beaconing locking
71     
72     This patch is needed for further changes to keep global variables
73     consistent when changing beaconing on diffrent vif's.
74     
75     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
76
77 commit 930b0dffd1731f3f418f9132faea720a23b7af61
78 Author: Johannes Berg <johannes.berg@intel.com>
79 Date:   Tue Jun 3 11:18:47 2014 +0200
80
81     mac80211: fix station/driver powersave race
82     
83     It is currently possible to have a race due to the station PS
84     unblock work like this:
85      * station goes to sleep with frames buffered in the driver
86      * driver blocks wakeup
87      * station wakes up again
88      * driver flushes/returns frames, and unblocks, which schedules
89        the unblock work
90      * unblock work starts to run, and checks that the station is
91        awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
92      * we process a received frame with PM=1, setting the flag again
93      * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
94        to the driver, and then clearing the WLAN_STA_PS_DRIVER and
95        WLAN_STA_PS_STA flags
96     
97     In this scenario, mac80211 will think that the station is awake,
98     while it really is asleep, and any TX'ed frames should be filtered
99     by the device (it will know that the station is sleeping) but then
100     passed to mac80211 again, which will not buffer it either as it
101     thinks the station is awake, and eventually the packets will be
102     dropped.
103     
104     Fix this by moving the clearing of the flags to exactly where we
105     learn about the situation. This creates a problem of reordering,
106     so introduce another flag indicating that delivery is being done,
107     this new flag also queues frames and is cleared only while the
108     spinlock is held (which the queuing code also holds) so that any
109     concurrent delivery/TX is handled correctly.
110     
111     Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
112     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
113
114 commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
115 Author: Felix Fietkau <nbd@openwrt.org>
116 Date:   Fri May 23 19:58:14 2014 +0200
117
118     mac80211: reduce packet loss notifications under load
119     
120     During strong signal fluctuations under high throughput, few consecutive
121     failed A-MPDU transmissions can easily trigger packet loss notification,
122     and thus (in AP mode) client disconnection.
123     
124     Reduce the number of false positives by checking the A-MPDU status flag
125     and treating a failed A-MPDU as a single packet.
126     
127     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
128
129 commit 7b7843a36fbcc568834404c7430ff895d8502131
130 Author: Felix Fietkau <nbd@openwrt.org>
131 Date:   Fri May 23 19:26:32 2014 +0200
132
133     mac80211: fix a memory leak on sta rate selection table
134     
135     Cc: stable@vger.kernel.org
136     Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
137     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
138
139 commit 96892d6aa0a153423070addf3070bc79578b3897
140 Author: Felix Fietkau <nbd@openwrt.org>
141 Date:   Mon May 19 21:20:49 2014 +0200
142
143     ath9k: avoid passing buffers to the hardware during flush
144     
145     The commit "ath9k: fix possible hang on flush" changed the receive code
146     to always link rx descriptors of processed frames, even when flushing.
147     In some cases, this leads to flushed rx buffers being passed to the
148     hardware while rx is already stopped.
149     
150     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
151
152 --- a/drivers/net/wireless/ath/ath9k/recv.c
153 +++ b/drivers/net/wireless/ath/ath9k/recv.c
154 @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
155   * buffer (or rx fifo). This can incorrectly acknowledge packets
156   * to a sender if last desc is self-linked.
157   */
158 -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
159 +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
160 +                           bool flush)
161  {
162         struct ath_hw *ah = sc->sc_ah;
163         struct ath_common *common = ath9k_hw_common(ah);
164 @@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
165                              common->rx_bufsize,
166                              0);
167  
168 -       if (sc->rx.rxlink == NULL)
169 -               ath9k_hw_putrxbuf(ah, bf->bf_daddr);
170 -       else
171 +       if (sc->rx.rxlink)
172                 *sc->rx.rxlink = bf->bf_daddr;
173 +       else if (!flush)
174 +               ath9k_hw_putrxbuf(ah, bf->bf_daddr);
175  
176         sc->rx.rxlink = &ds->ds_link;
177  }
178  
179 -static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
180 +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
181 +                             bool flush)
182  {
183         if (sc->rx.buf_hold)
184 -               ath_rx_buf_link(sc, sc->rx.buf_hold);
185 +               ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
186  
187         sc->rx.buf_hold = bf;
188  }
189 @@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
190         sc->rx.buf_hold = NULL;
191         sc->rx.rxlink = NULL;
192         list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
193 -               ath_rx_buf_link(sc, bf);
194 +               ath_rx_buf_link(sc, bf, false);
195         }
196  
197         /* We could have deleted elements so the list may be empty now */
198 @@ -1118,12 +1120,12 @@ requeue_drop_frag:
199  requeue:
200                 list_add_tail(&bf->list, &sc->rx.rxbuf);
201  
202 -               if (edma) {
203 -                       ath_rx_edma_buf_link(sc, qtype);
204 -               } else {
205 -                       ath_rx_buf_relink(sc, bf);
206 +               if (!edma) {
207 +                       ath_rx_buf_relink(sc, bf, flush);
208                         if (!flush)
209                                 ath9k_hw_rxena(ah);
210 +               } else if (!flush) {
211 +                       ath_rx_edma_buf_link(sc, qtype);
212                 }
213  
214                 if (!budget--)
215 --- a/net/mac80211/sta_info.c
216 +++ b/net/mac80211/sta_info.c
217 @@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct 
218         struct ps_data *ps;
219  
220         if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
221 -           test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
222 +           test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
223 +           test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
224                 if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
225                     sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
226                         ps = &sdata->bss->ps;
227 @@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct 
228  
229                 clear_sta_flag(sta, WLAN_STA_PS_STA);
230                 clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
231 +               clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
232  
233                 atomic_dec(&ps->num_sta_ps);
234                 sta_info_recalc_tim(sta);
235 @@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct 
236         if (ieee80211_vif_is_mesh(&sdata->vif))
237                 mesh_sta_cleanup(sta);
238  
239 -       cancel_work_sync(&sta->drv_unblock_wk);
240 +       cancel_work_sync(&sta->drv_deliver_wk);
241  
242         /*
243          * Destroy aggregation state here. It would be nice to wait for the
244 @@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
245   */
246  void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
247  {
248 +       struct ieee80211_sta_rates *rates;
249         int i;
250  
251         if (sta->rate_ctrl)
252 @@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
253                 kfree(sta->tx_lat);
254         }
255  
256 +       rates = rcu_dereference_protected(sta->sta.rates, true);
257 +       if (rates)
258 +               kfree(rates);
259 +
260         sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
261  
262         kfree(sta);
263 @@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
264         rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
265  }
266  
267 -static void sta_unblock(struct work_struct *wk)
268 +static void sta_deliver_ps_frames(struct work_struct *wk)
269  {
270         struct sta_info *sta;
271  
272 -       sta = container_of(wk, struct sta_info, drv_unblock_wk);
273 +       sta = container_of(wk, struct sta_info, drv_deliver_wk);
274  
275         if (sta->dead)
276                 return;
277  
278 -       if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
279 -               local_bh_disable();
280 +       local_bh_disable();
281 +       if (!test_sta_flag(sta, WLAN_STA_PS_STA))
282                 ieee80211_sta_ps_deliver_wakeup(sta);
283 -               local_bh_enable();
284 -       } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
285 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
286 -
287 -               local_bh_disable();
288 +       else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
289                 ieee80211_sta_ps_deliver_poll_response(sta);
290 -               local_bh_enable();
291 -       } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
292 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
293 -
294 -               local_bh_disable();
295 +       else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
296                 ieee80211_sta_ps_deliver_uapsd(sta);
297 -               local_bh_enable();
298 -       } else
299 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
300 +       local_bh_enable();
301  }
302  
303  static int sta_prepare_rate_control(struct ieee80211_local *local,
304 @@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
305  
306         spin_lock_init(&sta->lock);
307         spin_lock_init(&sta->ps_lock);
308 -       INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
309 +       INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
310         INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
311         mutex_init(&sta->ampdu_mlme.mtx);
312  #ifdef CPTCFG_MAC80211_MESH
313 @@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
314         }
315  
316         ieee80211_add_pending_skbs(local, &pending);
317 -       clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
318 -       clear_sta_flag(sta, WLAN_STA_PS_STA);
319 +
320 +       /* now we're no longer in the deliver code */
321 +       clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
322 +
323 +       /* The station might have polled and then woken up before we responded,
324 +        * so clear these flags now to avoid them sticking around.
325 +        */
326 +       clear_sta_flag(sta, WLAN_STA_PSPOLL);
327 +       clear_sta_flag(sta, WLAN_STA_UAPSD);
328         spin_unlock(&sta->ps_lock);
329  
330         atomic_dec(&ps->num_sta_ps);
331 @@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
332  
333         trace_api_sta_block_awake(sta->local, pubsta, block);
334  
335 -       if (block)
336 +       if (block) {
337                 set_sta_flag(sta, WLAN_STA_PS_DRIVER);
338 -       else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
339 -               ieee80211_queue_work(hw, &sta->drv_unblock_wk);
340 +               return;
341 +       }
342 +
343 +       if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
344 +               return;
345 +
346 +       if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
347 +               set_sta_flag(sta, WLAN_STA_PS_DELIVER);
348 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
349 +               ieee80211_queue_work(hw, &sta->drv_deliver_wk);
350 +       } else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
351 +                  test_sta_flag(sta, WLAN_STA_UAPSD)) {
352 +               /* must be asleep in this case */
353 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
354 +               ieee80211_queue_work(hw, &sta->drv_deliver_wk);
355 +       } else {
356 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
357 +       }
358  }
359  EXPORT_SYMBOL(ieee80211_sta_block_awake);
360  
361 --- a/net/mac80211/status.c
362 +++ b/net/mac80211/status.c
363 @@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
364   */
365  #define STA_LOST_PKT_THRESHOLD 50
366  
367 +static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
368 +{
369 +       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
370 +
371 +       /* This packet was aggregated but doesn't carry status info */
372 +       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
373 +           !(info->flags & IEEE80211_TX_STAT_AMPDU))
374 +               return;
375 +
376 +       if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
377 +               return;
378 +
379 +       cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
380 +                                   sta->lost_packets, GFP_ATOMIC);
381 +       sta->lost_packets = 0;
382 +}
383 +
384  void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
385  {
386         struct sk_buff *skb2;
387 @@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
388                         if (info->flags & IEEE80211_TX_STAT_ACK) {
389                                 if (sta->lost_packets)
390                                         sta->lost_packets = 0;
391 -                       } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
392 -                               cfg80211_cqm_pktloss_notify(sta->sdata->dev,
393 -                                                           sta->sta.addr,
394 -                                                           sta->lost_packets,
395 -                                                           GFP_ATOMIC);
396 -                               sta->lost_packets = 0;
397 +                       } else {
398 +                               ieee80211_lost_packet(sta, skb);
399                         }
400                 }
401  
402 --- a/net/mac80211/rx.c
403 +++ b/net/mac80211/rx.c
404 @@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
405                 return;
406         }
407  
408 +       set_sta_flag(sta, WLAN_STA_PS_DELIVER);
409 +       clear_sta_flag(sta, WLAN_STA_PS_STA);
410         ieee80211_sta_ps_deliver_wakeup(sta);
411  }
412  
413 --- a/net/mac80211/sta_info.h
414 +++ b/net/mac80211/sta_info.h
415 @@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
416         WLAN_STA_TOFFSET_KNOWN,
417         WLAN_STA_MPSP_OWNER,
418         WLAN_STA_MPSP_RECIPIENT,
419 +       WLAN_STA_PS_DELIVER,
420  };
421  
422  #define ADDBA_RESP_INTERVAL HZ
423 @@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
424   * @last_rx_rate_vht_nss: rx status nss of last data packet
425   * @lock: used for locking all fields that require locking, see comments
426   *     in the header file.
427 - * @drv_unblock_wk: used for driver PS unblocking
428 + * @drv_deliver_wk: used for delivering frames after driver PS unblocking
429   * @listen_interval: listen interval of this station, when we're acting as AP
430   * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
431   * @ps_lock: used for powersave (when mac80211 is the AP) related locking
432 @@ -345,7 +346,7 @@ struct sta_info {
433         void *rate_ctrl_priv;
434         spinlock_t lock;
435  
436 -       struct work_struct drv_unblock_wk;
437 +       struct work_struct drv_deliver_wk;
438  
439         u16 listen_interval;
440  
441 --- a/net/mac80211/tx.c
442 +++ b/net/mac80211/tx.c
443 @@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
444                 return TX_CONTINUE;
445  
446         if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
447 -                     test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
448 +                     test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
449 +                     test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
450                      !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
451                 int ac = skb_get_queue_mapping(tx->skb);
452  
453 @@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
454                  * ahead and Tx the packet.
455                  */
456                 if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
457 -                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
458 +                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
459 +                   !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
460                         spin_unlock(&sta->ps_lock);
461                         return TX_CONTINUE;
462                 }
463 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
464 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
465 @@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offse
466         return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
467  }
468  
469 +static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
470 +{
471 +       struct data_queue *queue = rt2x00dev->bcn;
472 +       struct queue_entry *entry;
473 +       int i, bcn_num = 0;
474 +       u64 off, reg = 0;
475 +       u32 bssid_dw1;
476 +
477 +       /*
478 +        * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
479 +        */
480 +       for (i = 0; i < queue->limit; i++) {
481 +               entry = &queue->entries[i];
482 +               if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
483 +                       continue;
484 +               off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
485 +               reg |= off << (8 * bcn_num);
486 +               bcn_num++;
487 +       }
488 +
489 +       WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
490 +
491 +       rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
492 +       rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
493 +
494 +       /*
495 +        * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
496 +        */
497 +       rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
498 +       rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
499 +                          bcn_num > 0 ? bcn_num - 1 : 0);
500 +       rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
501 +}
502 +
503  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
504  {
505         struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
506 @@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
507  
508         rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
509                                    entry->skb->len + padding_len);
510 +       __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
511 +
512 +       /*
513 +        * Change global beacons settings.
514 +        */
515 +       rt2800_update_beacons_setup(rt2x00dev);
516  
517         /*
518          * Restore beaconing state.
519 @@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
520          * Clear beacon.
521          */
522         rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
523 +       __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
524  
525         /*
526 +        * Change global beacons settings.
527 +        */
528 +       rt2800_update_beacons_setup(rt2x00dev);
529 +       /*
530          * Restore beaconing state.
531          */
532         rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
533 @@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_de
534                 if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
535                         reg = le32_to_cpu(conf->bssid[1]);
536                         rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
537 -                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
538 +                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
539                         conf->bssid[1] = cpu_to_le32(reg);
540                 }
541  
542 @@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct 
543         if (ret)
544                 return ret;
545  
546 -       rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
547 -       rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
548 -                          rt2800_get_beacon_offset(rt2x00dev, 0));
549 -       rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
550 -                          rt2800_get_beacon_offset(rt2x00dev, 1));
551 -       rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
552 -                          rt2800_get_beacon_offset(rt2x00dev, 2));
553 -       rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
554 -                          rt2800_get_beacon_offset(rt2x00dev, 3));
555 -       rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
556 -
557 -       rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
558 -       rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
559 -                          rt2800_get_beacon_offset(rt2x00dev, 4));
560 -       rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
561 -                          rt2800_get_beacon_offset(rt2x00dev, 5));
562 -       rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
563 -                          rt2800_get_beacon_offset(rt2x00dev, 6));
564 -       rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
565 -                          rt2800_get_beacon_offset(rt2x00dev, 7));
566 -       rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
567 -
568         rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
569         rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
570  
571 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
572 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
573 @@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_ite
574         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
575                 return;
576  
577 -       if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
578 +       if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
579 +               mutex_lock(&intf->beacon_skb_mutex);
580                 rt2x00queue_update_beacon(rt2x00dev, vif);
581 +               mutex_unlock(&intf->beacon_skb_mutex);
582 +       }
583  }
584  
585  static void rt2x00lib_intf_scheduled(struct work_struct *work)
586 @@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(
587          * never be called for USB devices.
588          */
589         WARN_ON(rt2x00_is_usb(rt2x00dev));
590 -       rt2x00queue_update_beacon_locked(rt2x00dev, vif);
591 +       rt2x00queue_update_beacon(rt2x00dev, vif);
592  }
593  
594  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
595 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c
596 +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
597 @@ -624,25 +624,24 @@ void rt2x00mac_bss_info_changed(struct i
598          * Start/stop beaconing.
599          */
600         if (changes & BSS_CHANGED_BEACON_ENABLED) {
601 +               mutex_lock(&intf->beacon_skb_mutex);
602                 if (!bss_conf->enable_beacon && intf->enable_beacon) {
603                         rt2x00dev->intf_beaconing--;
604                         intf->enable_beacon = false;
605 -                       /*
606 -                        * Clear beacon in the H/W for this vif. This is needed
607 -                        * to disable beaconing on this particular interface
608 -                        * and keep it running on other interfaces.
609 -                        */
610 -                       rt2x00queue_clear_beacon(rt2x00dev, vif);
611  
612                         if (rt2x00dev->intf_beaconing == 0) {
613                                 /*
614                                  * Last beaconing interface disabled
615                                  * -> stop beacon queue.
616                                  */
617 -                               mutex_lock(&intf->beacon_skb_mutex);
618                                 rt2x00queue_stop_queue(rt2x00dev->bcn);
619 -                               mutex_unlock(&intf->beacon_skb_mutex);
620                         }
621 +                       /*
622 +                        * Clear beacon in the H/W for this vif. This is needed
623 +                        * to disable beaconing on this particular interface
624 +                        * and keep it running on other interfaces.
625 +                        */
626 +                       rt2x00queue_clear_beacon(rt2x00dev, vif);
627                 } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
628                         rt2x00dev->intf_beaconing++;
629                         intf->enable_beacon = true;
630 @@ -658,11 +657,10 @@ void rt2x00mac_bss_info_changed(struct i
631                                  * First beaconing interface enabled
632                                  * -> start beacon queue.
633                                  */
634 -                               mutex_lock(&intf->beacon_skb_mutex);
635                                 rt2x00queue_start_queue(rt2x00dev->bcn);
636 -                               mutex_unlock(&intf->beacon_skb_mutex);
637                         }
638                 }
639 +               mutex_unlock(&intf->beacon_skb_mutex);
640         }
641  
642         /*
643 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
644 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
645 @@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x
646         if (unlikely(!intf->beacon))
647                 return -ENOBUFS;
648  
649 -       mutex_lock(&intf->beacon_skb_mutex);
650 -
651         /*
652          * Clean up the beacon skb.
653          */
654 @@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x
655         if (rt2x00dev->ops->lib->clear_beacon)
656                 rt2x00dev->ops->lib->clear_beacon(intf->beacon);
657  
658 -       mutex_unlock(&intf->beacon_skb_mutex);
659 -
660         return 0;
661  }
662  
663 -int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
664 -                                    struct ieee80211_vif *vif)
665 +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
666 +                             struct ieee80211_vif *vif)
667  {
668         struct rt2x00_intf *intf = vif_to_intf(vif);
669         struct skb_frame_desc *skbdesc;
670 @@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str
671  
672  }
673  
674 -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
675 -                             struct ieee80211_vif *vif)
676 -{
677 -       struct rt2x00_intf *intf = vif_to_intf(vif);
678 -       int ret;
679 -
680 -       mutex_lock(&intf->beacon_skb_mutex);
681 -       ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
682 -       mutex_unlock(&intf->beacon_skb_mutex);
683 -
684 -       return ret;
685 -}
686 -
687  bool rt2x00queue_for_each_entry(struct data_queue *queue,
688                                 enum queue_index start,
689                                 enum queue_index end,
690 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h
691 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
692 @@ -353,6 +353,7 @@ struct txentry_desc {
693   */
694  enum queue_entry_flags {
695         ENTRY_BCN_ASSIGNED,
696 +       ENTRY_BCN_ENABLED,
697         ENTRY_OWNER_DEVICE_DATA,
698         ENTRY_DATA_PENDING,
699         ENTRY_DATA_IO_FAILED,
700 --- a/drivers/net/wireless/ath/ath9k/main.c
701 +++ b/drivers/net/wireless/ath/ath9k/main.c
702 @@ -1757,7 +1757,6 @@ out:
703  void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
704  {
705         struct ath_vif *avp = (void *)vif->drv_priv;
706 -       unsigned long flags;
707         u32 tsf;
708  
709         if (!sc->p2p_ps_timer)
710 @@ -1767,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_soft
711                 return;
712  
713         sc->p2p_ps_vif = avp;
714 -
715 -       spin_lock_irqsave(&sc->sc_pm_lock, flags);
716 -       if (!(sc->ps_flags & PS_BEACON_SYNC)) {
717 -               tsf = ath9k_hw_gettsf32(sc->sc_ah);
718 -               ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
719 -               ath9k_update_p2p_ps_timer(sc, avp);
720 -       }
721 -       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
722 +       tsf = ath9k_hw_gettsf32(sc->sc_ah);
723 +       ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
724 +       ath9k_update_p2p_ps_timer(sc, avp);
725  }
726  
727  static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
728 @@ -1791,6 +1785,7 @@ static void ath9k_bss_info_changed(struc
729         struct ath_hw *ah = sc->sc_ah;
730         struct ath_common *common = ath9k_hw_common(ah);
731         struct ath_vif *avp = (void *)vif->drv_priv;
732 +       unsigned long flags;
733         int slottime;
734  
735         ath9k_ps_wakeup(sc);
736 @@ -1853,7 +1848,10 @@ static void ath9k_bss_info_changed(struc
737  
738         if (changed & BSS_CHANGED_P2P_PS) {
739                 spin_lock_bh(&sc->sc_pcu_lock);
740 -               ath9k_update_p2p_ps(sc, vif);
741 +               spin_lock_irqsave(&sc->sc_pm_lock, flags);
742 +               if (!(sc->ps_flags & PS_BEACON_SYNC))
743 +                       ath9k_update_p2p_ps(sc, vif);
744 +               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
745                 spin_unlock_bh(&sc->sc_pcu_lock);
746         }
747