a88229a3a0514996c693609f19dffd4a7440e752
[openwrt.git] / package / kernel / mac80211 / patches / 322-mac80211-add-A-MSDU-tx-support.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Fri, 5 Feb 2016 01:38:51 +0100
3 Subject: [PATCH] mac80211: add A-MSDU tx support
4
5 Requires software tx queueing support. frag_list support (for zero-copy)
6 is optional.
7
8 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
9 ---
10
11 --- a/include/net/mac80211.h
12 +++ b/include/net/mac80211.h
13 @@ -709,6 +709,7 @@ enum mac80211_tx_info_flags {
14   * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
15   *     frame (PS-Poll or uAPSD).
16   * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
17 + * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
18   *
19   * These flags are used in tx_info->control.flags.
20   */
21 @@ -716,6 +717,7 @@ enum mac80211_tx_control_flags {
22         IEEE80211_TX_CTRL_PORT_CTRL_PROTO       = BIT(0),
23         IEEE80211_TX_CTRL_PS_RESPONSE           = BIT(1),
24         IEEE80211_TX_CTRL_RATE_INJECT           = BIT(2),
25 +       IEEE80211_TX_CTRL_AMSDU                 = BIT(3),
26  };
27  
28  /*
29 @@ -1728,6 +1730,7 @@ struct ieee80211_sta_rates {
30   *               size is min(max_amsdu_len, 7935) bytes.
31   *     Both additional HT limits must be enforced by the low level driver.
32   *     This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2).
33 + * @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
34   * @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
35   */
36  struct ieee80211_sta {
37 @@ -1748,6 +1751,7 @@ struct ieee80211_sta {
38         bool mfp;
39         u8 max_amsdu_subframes;
40         u16 max_amsdu_len;
41 +       u16 max_rc_amsdu_len;
42  
43         struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
44  
45 @@ -1961,6 +1965,12 @@ struct ieee80211_txq {
46   *     order and does not need to manage its own reorder buffer or BA session
47   *     timeout.
48   *
49 + * @IEEE80211_HW_TX_AMSDU: Hardware (or driver) supports software aggregated
50 + *     A-MSDU frames. Requires software tx queueing support.
51 + *
52 + * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list
53 + *     skbs, needed for zero-copy software A-MSDU.
54 + *
55   * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
56   */
57  enum ieee80211_hw_flags {
58 @@ -1998,6 +2008,8 @@ enum ieee80211_hw_flags {
59         IEEE80211_HW_BEACON_TX_STATUS,
60         IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR,
61         IEEE80211_HW_SUPPORTS_REORDERING_BUFFER,
62 +       IEEE80211_HW_TX_AMSDU,
63 +       IEEE80211_HW_TX_FRAG_LIST,
64  
65         /* keep last, obviously */
66         NUM_IEEE80211_HW_FLAGS
67 @@ -2070,6 +2082,8 @@ enum ieee80211_hw_flags {
68   *     size is smaller (an example is LinkSys WRT120N with FW v1.0.07
69   *     build 002 Jun 18 2012).
70   *
71 + * @max_tx_fragments: maximum fragments per (A-)MSDU.
72 + *
73   * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX
74   *     (if %IEEE80211_HW_QUEUE_CONTROL is set)
75   *
76 @@ -2124,6 +2138,7 @@ struct ieee80211_hw {
77         u8 max_rate_tries;
78         u8 max_rx_aggregation_subframes;
79         u8 max_tx_aggregation_subframes;
80 +       u8 max_tx_fragments;
81         u8 offchannel_tx_hw_queue;
82         u8 radiotap_mcs_details;
83         u16 radiotap_vht_details;
84 --- a/net/mac80211/agg-tx.c
85 +++ b/net/mac80211/agg-tx.c
86 @@ -935,6 +935,7 @@ void ieee80211_process_addba_resp(struct
87                                   size_t len)
88  {
89         struct tid_ampdu_tx *tid_tx;
90 +       struct ieee80211_txq *txq;
91         u16 capab, tid;
92         u8 buf_size;
93         bool amsdu;
94 @@ -945,6 +946,10 @@ void ieee80211_process_addba_resp(struct
95         buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
96         buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
97  
98 +       txq = sta->sta.txq[tid];
99 +       if (!amsdu && txq)
100 +               set_bit(IEEE80211_TXQ_NO_AMSDU, &to_txq_info(txq)->flags);
101 +
102         mutex_lock(&sta->ampdu_mlme.mtx);
103  
104         tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
105 --- a/net/mac80211/debugfs.c
106 +++ b/net/mac80211/debugfs.c
107 @@ -127,6 +127,8 @@ static const char *hw_flag_names[NUM_IEE
108         FLAG(BEACON_TX_STATUS),
109         FLAG(NEEDS_UNIQUE_STA_ADDR),
110         FLAG(SUPPORTS_REORDERING_BUFFER),
111 +       FLAG(TX_AMSDU),
112 +       FLAG(TX_FRAG_LIST),
113  
114         /* keep last for the build bug below */
115         (void *)0x1
116 --- a/net/mac80211/ieee80211_i.h
117 +++ b/net/mac80211/ieee80211_i.h
118 @@ -799,6 +799,7 @@ struct mac80211_qos_map {
119  enum txq_info_flags {
120         IEEE80211_TXQ_STOP,
121         IEEE80211_TXQ_AMPDU,
122 +       IEEE80211_TXQ_NO_AMSDU,
123  };
124  
125  struct txq_info {
126 --- a/net/mac80211/tx.c
127 +++ b/net/mac80211/tx.c
128 @@ -1318,6 +1318,10 @@ struct sk_buff *ieee80211_tx_dequeue(str
129  out:
130         spin_unlock_bh(&txqi->queue.lock);
131  
132 +       if (skb && skb_has_frag_list(skb) &&
133 +           !ieee80211_hw_check(&local->hw, TX_FRAG_LIST))
134 +               skb_linearize(skb);
135 +
136         return skb;
137  }
138  EXPORT_SYMBOL(ieee80211_tx_dequeue);
139 @@ -2757,6 +2761,165 @@ void ieee80211_clear_fast_xmit(struct st
140                 kfree_rcu(fast_tx, rcu_head);
141  }
142  
143 +static int ieee80211_amsdu_pad(struct sk_buff *skb, int subframe_len)
144 +{
145 +       int amsdu_len = subframe_len + sizeof(struct ethhdr);
146 +       int padding = (4 - amsdu_len) & 3;
147 +
148 +       if (padding)
149 +               memset(skb_put(skb, padding), 0, padding);
150 +
151 +       return padding;
152 +}
153 +
154 +static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
155 +                                        struct ieee80211_fast_tx *fast_tx,
156 +                                        struct sk_buff *skb)
157 +{
158 +       struct ieee80211_local *local = sdata->local;
159 +       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
160 +       struct ieee80211_hdr *hdr;
161 +       struct ethhdr amsdu_hdr;
162 +       int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
163 +       int subframe_len = skb->len - hdr_len;
164 +       void *data;
165 +       u8 *qc;
166 +
167 +       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
168 +               return false;
169 +
170 +       if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
171 +               return true;
172 +
173 +       if (skb_headroom(skb) < sizeof(amsdu_hdr) || skb_tailroom(skb) < 3) {
174 +               I802_DEBUG_INC(local->tx_expand_skb_head);
175 +
176 +               if (pskb_expand_head(skb, sizeof(amsdu_hdr), 3, GFP_ATOMIC)) {
177 +                       wiphy_debug(local->hw.wiphy,
178 +                                   "failed to reallocate TX buffer\n");
179 +                       return false;
180 +               }
181 +       }
182 +
183 +       subframe_len += ieee80211_amsdu_pad(skb, subframe_len);
184 +
185 +       amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
186 +       memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
187 +       memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
188 +
189 +       data = skb_push(skb, sizeof(amsdu_hdr));
190 +       memmove(data, data + sizeof(amsdu_hdr), hdr_len);
191 +       memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
192 +
193 +       hdr = data;
194 +       qc = ieee80211_get_qos_ctl(hdr);
195 +       *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
196 +
197 +       info->control.flags |= IEEE80211_TX_CTRL_AMSDU;
198 +
199 +       return true;
200 +}
201 +
202 +static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
203 +                                     struct sta_info *sta,
204 +                                     struct ieee80211_fast_tx *fast_tx,
205 +                                     struct sk_buff *skb)
206 +{
207 +       struct ieee80211_local *local = sdata->local;
208 +       u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
209 +       struct ieee80211_txq *txq = sta->sta.txq[tid];
210 +       struct txq_info *txqi;
211 +       struct sk_buff **frag_tail, *head;
212 +       int subframe_len = skb->len - ETH_ALEN;
213 +       u8 max_subframes = sta->sta.max_amsdu_subframes;
214 +       int max_frags = local->hw.max_tx_fragments;
215 +       int max_amsdu_len = sta->sta.max_amsdu_len;
216 +       __be16 len;
217 +       void *data;
218 +       bool ret = false;
219 +       int n = 1, nfrags;
220 +
221 +       if (!ieee80211_hw_check(&local->hw, TX_AMSDU))
222 +               return false;
223 +
224 +       if (!txq)
225 +               return false;
226 +
227 +       txqi = to_txq_info(txq);
228 +       if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags))
229 +               return false;
230 +
231 +       if (sta->sta.max_rc_amsdu_len)
232 +               max_amsdu_len = min_t(int, max_amsdu_len,
233 +                                     sta->sta.max_rc_amsdu_len);
234 +
235 +       spin_lock_bh(&txqi->queue.lock);
236 +
237 +       head = skb_peek_tail(&txqi->queue);
238 +       if (!head)
239 +               goto out;
240 +
241 +       if (skb->len + head->len > max_amsdu_len)
242 +               goto out;
243 +
244 +       /*
245 +        * HT A-MPDU limits maximum MPDU size to 4095 bytes. Since aggregation
246 +        * sessions are started/stopped without txq flush, use the limit here
247 +        * to avoid having to de-aggregate later.
248 +        */
249 +       if (skb->len + head->len > 4095 &&
250 +           !sta->sta.vht_cap.vht_supported)
251 +               goto out;
252 +
253 +       if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
254 +               goto out;
255 +
256 +       nfrags = 1 + skb_shinfo(skb)->nr_frags;
257 +       nfrags += 1 + skb_shinfo(head)->nr_frags;
258 +       frag_tail = &skb_shinfo(head)->frag_list;
259 +       while (*frag_tail) {
260 +               nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags;
261 +               frag_tail = &(*frag_tail)->next;
262 +               n++;
263 +       }
264 +
265 +       if (max_subframes && n > max_subframes)
266 +               goto out;
267 +
268 +       if (max_frags && nfrags > max_frags)
269 +               goto out;
270 +
271 +       if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 3) {
272 +               I802_DEBUG_INC(local->tx_expand_skb_head);
273 +
274 +               if (pskb_expand_head(skb, 8, 3, GFP_ATOMIC)) {
275 +                       wiphy_debug(local->hw.wiphy,
276 +                                   "failed to reallocate TX buffer\n");
277 +                       goto out;
278 +               }
279 +       }
280 +
281 +       subframe_len += ieee80211_amsdu_pad(skb, subframe_len);
282 +
283 +       ret = true;
284 +       data = skb_push(skb, ETH_ALEN + 2);
285 +       memmove(data, data + ETH_ALEN + 2, 2 * ETH_ALEN);
286 +
287 +       data += 2 * ETH_ALEN;
288 +       len = cpu_to_be16(subframe_len);
289 +       memcpy(data, &len, 2);
290 +       memcpy(data + 2, rfc1042_header, ETH_ALEN);
291 +
292 +       head->len += skb->len;
293 +       head->data_len += skb->len;
294 +       *frag_tail = skb;
295 +
296 +out:
297 +       spin_unlock_bh(&txqi->queue.lock);
298 +
299 +       return ret;
300 +}
301 +
302  static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
303                                 struct net_device *dev, struct sta_info *sta,
304                                 struct ieee80211_fast_tx *fast_tx,
305 @@ -2811,6 +2974,10 @@ static bool ieee80211_xmit_fast(struct i
306  
307         ieee80211_tx_stats(dev, skb->len + extra_head);
308  
309 +       if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
310 +           ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
311 +               return true;
312 +
313         /* will not be crypto-handled beyond what we do here, so use false
314          * as the may-encrypt argument for the resize to not account for
315          * more room than we already have in 'extra_head'