0a2e86b1d7bc2f539b84d4b4a23ec5a1eb413ec9
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
1 commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
2 Author: Felix Fietkau <nbd@openwrt.org>
3 Date: Fri May 23 19:58:14 2014 +0200
4
5 mac80211: reduce packet loss notifications under load
6
7 During strong signal fluctuations under high throughput, few consecutive
8 failed A-MPDU transmissions can easily trigger packet loss notification,
9 and thus (in AP mode) client disconnection.
10
11 Reduce the number of false positives by checking the A-MPDU status flag
12 and treating a failed A-MPDU as a single packet.
13
14 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
15
16 commit 7b7843a36fbcc568834404c7430ff895d8502131
17 Author: Felix Fietkau <nbd@openwrt.org>
18 Date: Fri May 23 19:26:32 2014 +0200
19
20 mac80211: fix a memory leak on sta rate selection table
21
22 Cc: stable@vger.kernel.org
23 Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
24 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
25
26 commit 96892d6aa0a153423070addf3070bc79578b3897
27 Author: Felix Fietkau <nbd@openwrt.org>
28 Date: Mon May 19 21:20:49 2014 +0200
29
30 ath9k: avoid passing buffers to the hardware during flush
31
32 The commit "ath9k: fix possible hang on flush" changed the receive code
33 to always link rx descriptors of processed frames, even when flushing.
34 In some cases, this leads to flushed rx buffers being passed to the
35 hardware while rx is already stopped.
36
37 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
38
39 --- a/drivers/net/wireless/ath/ath9k/recv.c
40 +++ b/drivers/net/wireless/ath/ath9k/recv.c
41 @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
42 * buffer (or rx fifo). This can incorrectly acknowledge packets
43 * to a sender if last desc is self-linked.
44 */
45 -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
46 +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
47 + bool flush)
48 {
49 struct ath_hw *ah = sc->sc_ah;
50 struct ath_common *common = ath9k_hw_common(ah);
51 @@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
52 common->rx_bufsize,
53 0);
54
55 - if (sc->rx.rxlink == NULL)
56 - ath9k_hw_putrxbuf(ah, bf->bf_daddr);
57 - else
58 + if (sc->rx.rxlink)
59 *sc->rx.rxlink = bf->bf_daddr;
60 + else if (!flush)
61 + ath9k_hw_putrxbuf(ah, bf->bf_daddr);
62
63 sc->rx.rxlink = &ds->ds_link;
64 }
65
66 -static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
67 +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
68 + bool flush)
69 {
70 if (sc->rx.buf_hold)
71 - ath_rx_buf_link(sc, sc->rx.buf_hold);
72 + ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
73
74 sc->rx.buf_hold = bf;
75 }
76 @@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
77 sc->rx.buf_hold = NULL;
78 sc->rx.rxlink = NULL;
79 list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
80 - ath_rx_buf_link(sc, bf);
81 + ath_rx_buf_link(sc, bf, false);
82 }
83
84 /* We could have deleted elements so the list may be empty now */
85 @@ -1118,12 +1120,12 @@ requeue_drop_frag:
86 requeue:
87 list_add_tail(&bf->list, &sc->rx.rxbuf);
88
89 - if (edma) {
90 - ath_rx_edma_buf_link(sc, qtype);
91 - } else {
92 - ath_rx_buf_relink(sc, bf);
93 + if (!edma) {
94 + ath_rx_buf_relink(sc, bf, flush);
95 if (!flush)
96 ath9k_hw_rxena(ah);
97 + } else if (!flush) {
98 + ath_rx_edma_buf_link(sc, qtype);
99 }
100
101 if (!budget--)
102 --- a/net/mac80211/sta_info.c
103 +++ b/net/mac80211/sta_info.c
104 @@ -227,6 +227,7 @@ struct sta_info *sta_info_get_by_idx(str
105 */
106 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
107 {
108 + struct ieee80211_sta_rates *rates;
109 int i;
110
111 if (sta->rate_ctrl)
112 @@ -238,6 +239,10 @@ void sta_info_free(struct ieee80211_loca
113 kfree(sta->tx_lat);
114 }
115
116 + rates = rcu_dereference_protected(sta->sta.rates, true);
117 + if (rates)
118 + kfree(rates);
119 +
120 sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
121
122 kfree(sta);
123 --- a/net/mac80211/status.c
124 +++ b/net/mac80211/status.c
125 @@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
126 */
127 #define STA_LOST_PKT_THRESHOLD 50
128
129 +static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
130 +{
131 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
132 +
133 + /* This packet was aggregated but doesn't carry status info */
134 + if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
135 + !(info->flags & IEEE80211_TX_STAT_AMPDU))
136 + return;
137 +
138 + if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
139 + return;
140 +
141 + cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
142 + sta->lost_packets, GFP_ATOMIC);
143 + sta->lost_packets = 0;
144 +}
145 +
146 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
147 {
148 struct sk_buff *skb2;
149 @@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
150 if (info->flags & IEEE80211_TX_STAT_ACK) {
151 if (sta->lost_packets)
152 sta->lost_packets = 0;
153 - } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
154 - cfg80211_cqm_pktloss_notify(sta->sdata->dev,
155 - sta->sta.addr,
156 - sta->lost_packets,
157 - GFP_ATOMIC);
158 - sta->lost_packets = 0;
159 + } else {
160 + ieee80211_lost_packet(sta, skb);
161 }
162 }
163