c621ddbdacdb398eb3c14d71ad73536b08407ea8
[openwrt/staging/mkresin.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 }