mac80211: backport a powersave related fix
[openwrt.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
1 commit 930b0dffd1731f3f418f9132faea720a23b7af61
2 Author: Johannes Berg <johannes.berg@intel.com>
3 Date:   Tue Jun 3 11:18:47 2014 +0200
4
5     mac80211: fix station/driver powersave race
6     
7     It is currently possible to have a race due to the station PS
8     unblock work like this:
9      * station goes to sleep with frames buffered in the driver
10      * driver blocks wakeup
11      * station wakes up again
12      * driver flushes/returns frames, and unblocks, which schedules
13        the unblock work
14      * unblock work starts to run, and checks that the station is
15        awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
16      * we process a received frame with PM=1, setting the flag again
17      * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
18        to the driver, and then clearing the WLAN_STA_PS_DRIVER and
19        WLAN_STA_PS_STA flags
20     
21     In this scenario, mac80211 will think that the station is awake,
22     while it really is asleep, and any TX'ed frames should be filtered
23     by the device (it will know that the station is sleeping) but then
24     passed to mac80211 again, which will not buffer it either as it
25     thinks the station is awake, and eventually the packets will be
26     dropped.
27     
28     Fix this by moving the clearing of the flags to exactly where we
29     learn about the situation. This creates a problem of reordering,
30     so introduce another flag indicating that delivery is being done,
31     this new flag also queues frames and is cleared only while the
32     spinlock is held (which the queuing code also holds) so that any
33     concurrent delivery/TX is handled correctly.
34     
35     Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
36     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
37
38 commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
39 Author: Felix Fietkau <nbd@openwrt.org>
40 Date:   Fri May 23 19:58:14 2014 +0200
41
42     mac80211: reduce packet loss notifications under load
43     
44     During strong signal fluctuations under high throughput, few consecutive
45     failed A-MPDU transmissions can easily trigger packet loss notification,
46     and thus (in AP mode) client disconnection.
47     
48     Reduce the number of false positives by checking the A-MPDU status flag
49     and treating a failed A-MPDU as a single packet.
50     
51     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
52
53 commit 7b7843a36fbcc568834404c7430ff895d8502131
54 Author: Felix Fietkau <nbd@openwrt.org>
55 Date:   Fri May 23 19:26:32 2014 +0200
56
57     mac80211: fix a memory leak on sta rate selection table
58     
59     Cc: stable@vger.kernel.org
60     Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
61     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
62
63 commit 96892d6aa0a153423070addf3070bc79578b3897
64 Author: Felix Fietkau <nbd@openwrt.org>
65 Date:   Mon May 19 21:20:49 2014 +0200
66
67     ath9k: avoid passing buffers to the hardware during flush
68     
69     The commit "ath9k: fix possible hang on flush" changed the receive code
70     to always link rx descriptors of processed frames, even when flushing.
71     In some cases, this leads to flushed rx buffers being passed to the
72     hardware while rx is already stopped.
73     
74     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
75
76 --- a/drivers/net/wireless/ath/ath9k/recv.c
77 +++ b/drivers/net/wireless/ath/ath9k/recv.c
78 @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
79   * buffer (or rx fifo). This can incorrectly acknowledge packets
80   * to a sender if last desc is self-linked.
81   */
82 -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
83 +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
84 +                           bool flush)
85  {
86         struct ath_hw *ah = sc->sc_ah;
87         struct ath_common *common = ath9k_hw_common(ah);
88 @@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
89                              common->rx_bufsize,
90                              0);
91  
92 -       if (sc->rx.rxlink == NULL)
93 -               ath9k_hw_putrxbuf(ah, bf->bf_daddr);
94 -       else
95 +       if (sc->rx.rxlink)
96                 *sc->rx.rxlink = bf->bf_daddr;
97 +       else if (!flush)
98 +               ath9k_hw_putrxbuf(ah, bf->bf_daddr);
99  
100         sc->rx.rxlink = &ds->ds_link;
101  }
102  
103 -static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
104 +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
105 +                             bool flush)
106  {
107         if (sc->rx.buf_hold)
108 -               ath_rx_buf_link(sc, sc->rx.buf_hold);
109 +               ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
110  
111         sc->rx.buf_hold = bf;
112  }
113 @@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
114         sc->rx.buf_hold = NULL;
115         sc->rx.rxlink = NULL;
116         list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
117 -               ath_rx_buf_link(sc, bf);
118 +               ath_rx_buf_link(sc, bf, false);
119         }
120  
121         /* We could have deleted elements so the list may be empty now */
122 @@ -1118,12 +1120,12 @@ requeue_drop_frag:
123  requeue:
124                 list_add_tail(&bf->list, &sc->rx.rxbuf);
125  
126 -               if (edma) {
127 -                       ath_rx_edma_buf_link(sc, qtype);
128 -               } else {
129 -                       ath_rx_buf_relink(sc, bf);
130 +               if (!edma) {
131 +                       ath_rx_buf_relink(sc, bf, flush);
132                         if (!flush)
133                                 ath9k_hw_rxena(ah);
134 +               } else if (!flush) {
135 +                       ath_rx_edma_buf_link(sc, qtype);
136                 }
137  
138                 if (!budget--)
139 --- a/net/mac80211/sta_info.c
140 +++ b/net/mac80211/sta_info.c
141 @@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct 
142         struct ps_data *ps;
143  
144         if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
145 -           test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
146 +           test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
147 +           test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
148                 if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
149                     sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
150                         ps = &sdata->bss->ps;
151 @@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct 
152  
153                 clear_sta_flag(sta, WLAN_STA_PS_STA);
154                 clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
155 +               clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
156  
157                 atomic_dec(&ps->num_sta_ps);
158                 sta_info_recalc_tim(sta);
159 @@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct 
160         if (ieee80211_vif_is_mesh(&sdata->vif))
161                 mesh_sta_cleanup(sta);
162  
163 -       cancel_work_sync(&sta->drv_unblock_wk);
164 +       cancel_work_sync(&sta->drv_deliver_wk);
165  
166         /*
167          * Destroy aggregation state here. It would be nice to wait for the
168 @@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
169   */
170  void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
171  {
172 +       struct ieee80211_sta_rates *rates;
173         int i;
174  
175         if (sta->rate_ctrl)
176 @@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
177                 kfree(sta->tx_lat);
178         }
179  
180 +       rates = rcu_dereference_protected(sta->sta.rates, true);
181 +       if (rates)
182 +               kfree(rates);
183 +
184         sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
185  
186         kfree(sta);
187 @@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
188         rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
189  }
190  
191 -static void sta_unblock(struct work_struct *wk)
192 +static void sta_deliver_ps_frames(struct work_struct *wk)
193  {
194         struct sta_info *sta;
195  
196 -       sta = container_of(wk, struct sta_info, drv_unblock_wk);
197 +       sta = container_of(wk, struct sta_info, drv_deliver_wk);
198  
199         if (sta->dead)
200                 return;
201  
202 -       if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
203 -               local_bh_disable();
204 +       local_bh_disable();
205 +       if (!test_sta_flag(sta, WLAN_STA_PS_STA))
206                 ieee80211_sta_ps_deliver_wakeup(sta);
207 -               local_bh_enable();
208 -       } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
209 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
210 -
211 -               local_bh_disable();
212 +       else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
213                 ieee80211_sta_ps_deliver_poll_response(sta);
214 -               local_bh_enable();
215 -       } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
216 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
217 -
218 -               local_bh_disable();
219 +       else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
220                 ieee80211_sta_ps_deliver_uapsd(sta);
221 -               local_bh_enable();
222 -       } else
223 -               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
224 +       local_bh_enable();
225  }
226  
227  static int sta_prepare_rate_control(struct ieee80211_local *local,
228 @@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
229  
230         spin_lock_init(&sta->lock);
231         spin_lock_init(&sta->ps_lock);
232 -       INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
233 +       INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
234         INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
235         mutex_init(&sta->ampdu_mlme.mtx);
236  #ifdef CPTCFG_MAC80211_MESH
237 @@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
238         }
239  
240         ieee80211_add_pending_skbs(local, &pending);
241 -       clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
242 -       clear_sta_flag(sta, WLAN_STA_PS_STA);
243 +
244 +       /* now we're no longer in the deliver code */
245 +       clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
246 +
247 +       /* The station might have polled and then woken up before we responded,
248 +        * so clear these flags now to avoid them sticking around.
249 +        */
250 +       clear_sta_flag(sta, WLAN_STA_PSPOLL);
251 +       clear_sta_flag(sta, WLAN_STA_UAPSD);
252         spin_unlock(&sta->ps_lock);
253  
254         atomic_dec(&ps->num_sta_ps);
255 @@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
256  
257         trace_api_sta_block_awake(sta->local, pubsta, block);
258  
259 -       if (block)
260 +       if (block) {
261                 set_sta_flag(sta, WLAN_STA_PS_DRIVER);
262 -       else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
263 -               ieee80211_queue_work(hw, &sta->drv_unblock_wk);
264 +               return;
265 +       }
266 +
267 +       if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
268 +               return;
269 +
270 +       if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
271 +               set_sta_flag(sta, WLAN_STA_PS_DELIVER);
272 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
273 +               ieee80211_queue_work(hw, &sta->drv_deliver_wk);
274 +       } else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
275 +                  test_sta_flag(sta, WLAN_STA_UAPSD)) {
276 +               /* must be asleep in this case */
277 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
278 +               ieee80211_queue_work(hw, &sta->drv_deliver_wk);
279 +       } else {
280 +               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
281 +       }
282  }
283  EXPORT_SYMBOL(ieee80211_sta_block_awake);
284  
285 --- a/net/mac80211/status.c
286 +++ b/net/mac80211/status.c
287 @@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
288   */
289  #define STA_LOST_PKT_THRESHOLD 50
290  
291 +static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
292 +{
293 +       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
294 +
295 +       /* This packet was aggregated but doesn't carry status info */
296 +       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
297 +           !(info->flags & IEEE80211_TX_STAT_AMPDU))
298 +               return;
299 +
300 +       if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
301 +               return;
302 +
303 +       cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
304 +                                   sta->lost_packets, GFP_ATOMIC);
305 +       sta->lost_packets = 0;
306 +}
307 +
308  void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
309  {
310         struct sk_buff *skb2;
311 @@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
312                         if (info->flags & IEEE80211_TX_STAT_ACK) {
313                                 if (sta->lost_packets)
314                                         sta->lost_packets = 0;
315 -                       } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
316 -                               cfg80211_cqm_pktloss_notify(sta->sdata->dev,
317 -                                                           sta->sta.addr,
318 -                                                           sta->lost_packets,
319 -                                                           GFP_ATOMIC);
320 -                               sta->lost_packets = 0;
321 +                       } else {
322 +                               ieee80211_lost_packet(sta, skb);
323                         }
324                 }
325  
326 --- a/net/mac80211/rx.c
327 +++ b/net/mac80211/rx.c
328 @@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
329                 return;
330         }
331  
332 +       set_sta_flag(sta, WLAN_STA_PS_DELIVER);
333 +       clear_sta_flag(sta, WLAN_STA_PS_STA);
334         ieee80211_sta_ps_deliver_wakeup(sta);
335  }
336  
337 --- a/net/mac80211/sta_info.h
338 +++ b/net/mac80211/sta_info.h
339 @@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
340         WLAN_STA_TOFFSET_KNOWN,
341         WLAN_STA_MPSP_OWNER,
342         WLAN_STA_MPSP_RECIPIENT,
343 +       WLAN_STA_PS_DELIVER,
344  };
345  
346  #define ADDBA_RESP_INTERVAL HZ
347 @@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
348   * @last_rx_rate_vht_nss: rx status nss of last data packet
349   * @lock: used for locking all fields that require locking, see comments
350   *     in the header file.
351 - * @drv_unblock_wk: used for driver PS unblocking
352 + * @drv_deliver_wk: used for delivering frames after driver PS unblocking
353   * @listen_interval: listen interval of this station, when we're acting as AP
354   * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
355   * @ps_lock: used for powersave (when mac80211 is the AP) related locking
356 @@ -345,7 +346,7 @@ struct sta_info {
357         void *rate_ctrl_priv;
358         spinlock_t lock;
359  
360 -       struct work_struct drv_unblock_wk;
361 +       struct work_struct drv_deliver_wk;
362  
363         u16 listen_interval;
364  
365 --- a/net/mac80211/tx.c
366 +++ b/net/mac80211/tx.c
367 @@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
368                 return TX_CONTINUE;
369  
370         if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
371 -                     test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
372 +                     test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
373 +                     test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
374                      !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
375                 int ac = skb_get_queue_mapping(tx->skb);
376  
377 @@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
378                  * ahead and Tx the packet.
379                  */
380                 if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
381 -                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
382 +                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
383 +                   !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
384                         spin_unlock(&sta->ps_lock);
385                         return TX_CONTINUE;
386                 }