mac80211: rebase ontop of v4.18.5
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 358-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch
1 From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
2 Date: Fri, 19 Feb 2016 11:01:50 +0100
3 Subject: [PATCH] mac80211: add NEED_ALIGNED4_SKBS hw flag
4
5 HW/driver should set NEED_ALIGNED4_SKBS flag in case
6 require aligned skbs to four-byte boundaries.
7 This affect only TX direction.
8
9 Padding is added after ieee80211_hdr, before IV/LLC.
10
11 Before we have to do memmove(hdrlen) twice in the
12 dirver. Once before we pass this to HW and next
13 in tx completion (to be sure monitor will report
14 this tx frame correctly).
15
16 With this patch we can skip this memmove() and save CPU.
17
18 Currently this was tested with ath9k, both hw/sw crypt for
19 wep/tkip/ccmp.
20
21 Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
22 ---
23
24 Index: backports-v4.18-rc7/include/net/mac80211.h
25 ===================================================================
26 --- backports-v4.18-rc7.orig/include/net/mac80211.h
27 +++ backports-v4.18-rc7/include/net/mac80211.h
28 @@ -2084,6 +2084,9 @@ struct ieee80211_txq {
29 * @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
30 * support QoS NDP for AP probing - that's most likely a driver bug.
31 *
32 + * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
33 + * Padding will be added after ieee80211_hdr, before IV/LLC.
34 + *
35 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
36 */
37 enum ieee80211_hw_flags {
38 @@ -2129,6 +2132,7 @@ enum ieee80211_hw_flags {
39 IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
40 IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
41 IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
42 + IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
43
44 /* keep last, obviously */
45 NUM_IEEE80211_HW_FLAGS
46 Index: backports-v4.18-rc7/net/mac80211/debugfs.c
47 ===================================================================
48 --- backports-v4.18-rc7.orig/net/mac80211/debugfs.c
49 +++ backports-v4.18-rc7/net/mac80211/debugfs.c
50 @@ -214,6 +214,7 @@ static const char *hw_flag_names[] = {
51 FLAG(SUPPORTS_TDLS_BUFFER_STA),
52 FLAG(DEAUTH_NEED_MGD_TX_PREP),
53 FLAG(DOESNT_SUPPORT_QOS_NDP),
54 + FLAG(NEEDS_ALIGNED4_SKBS),
55 #undef FLAG
56 };
57
58 Index: backports-v4.18-rc7/net/mac80211/ieee80211_i.h
59 ===================================================================
60 --- backports-v4.18-rc7.orig/net/mac80211/ieee80211_i.h
61 +++ backports-v4.18-rc7/net/mac80211/ieee80211_i.h
62 @@ -1550,6 +1550,29 @@ ieee80211_vif_get_num_mcast_if(struct ie
63 return -1;
64 }
65
66 +static inline unsigned int
67 +ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen)
68 +{
69 + /*
70 + * While hdrlen is already aligned to two-byte boundaries,
71 + * simple check with & 2 will return correct padsize.
72 + */
73 + if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS))
74 + return hdrlen & 2;
75 + return 0;
76 +}
77 +
78 +static inline unsigned int
79 +ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc)
80 +{
81 + unsigned int hdrlen;
82 +
83 + hdrlen = ieee80211_hdrlen(fc);
84 + hdrlen += ieee80211_hdr_padsize(hw, hdrlen);
85 +
86 + return hdrlen;
87 +}
88 +
89 u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
90 struct ieee80211_rx_status *status,
91 unsigned int mpdu_len,
92 Index: backports-v4.18-rc7/net/mac80211/sta_info.h
93 ===================================================================
94 --- backports-v4.18-rc7.orig/net/mac80211/sta_info.h
95 +++ backports-v4.18-rc7/net/mac80211/sta_info.h
96 @@ -301,7 +301,7 @@ struct ieee80211_fast_tx {
97 u8 hdr_len;
98 u8 sa_offs, da_offs, pn_offs;
99 u8 band;
100 - u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
101 + u8 hdr[30 + 2 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
102 sizeof(rfc1042_header)] __aligned(2);
103
104 struct rcu_head rcu_head;
105 Index: backports-v4.18-rc7/net/mac80211/status.c
106 ===================================================================
107 --- backports-v4.18-rc7.orig/net/mac80211/status.c
108 +++ backports-v4.18-rc7/net/mac80211/status.c
109 @@ -653,9 +653,22 @@ void ieee80211_tx_monitor(struct ieee802
110 struct sk_buff *skb2;
111 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
112 struct ieee80211_sub_if_data *sdata;
113 + struct ieee80211_hdr *hdr = (void *)skb->data;
114 struct net_device *prev_dev = NULL;
115 + unsigned int hdrlen, padsize;
116 int rtap_len;
117
118 + /* Remove padding if was added */
119 + if (ieee80211_hw_check(&local->hw, NEEDS_ALIGNED4_SKBS)) {
120 + hdrlen = ieee80211_hdrlen(hdr->frame_control);
121 + padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
122 +
123 + if (padsize && skb->len > hdrlen + padsize) {
124 + memmove(skb->data + padsize, skb->data, hdrlen);
125 + skb_pull(skb, padsize);
126 + }
127 + }
128 +
129 /* send frame to monitor interfaces now */
130 rtap_len = ieee80211_tx_radiotap_len(info);
131 if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
132 Index: backports-v4.18-rc7/net/mac80211/tkip.c
133 ===================================================================
134 --- backports-v4.18-rc7.orig/net/mac80211/tkip.c
135 +++ backports-v4.18-rc7/net/mac80211/tkip.c
136 @@ -201,10 +201,12 @@ void ieee80211_get_tkip_p2k(struct ieee8
137 {
138 struct ieee80211_key *key = (struct ieee80211_key *)
139 container_of(keyconf, struct ieee80211_key, conf);
140 + struct ieee80211_hw *hw = &key->local->hw;
141 const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
142 struct tkip_ctx *ctx = &key->u.tkip.tx;
143 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
144 - const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
145 + const u8 *data = (u8 *)hdr + ieee80211_padded_hdrlen(hw,
146 + hdr->frame_control);
147 u32 iv32 = get_unaligned_le32(&data[4]);
148 u16 iv16 = data[2] | (data[0] << 8);
149
150 Index: backports-v4.18-rc7/net/mac80211/tx.c
151 ===================================================================
152 --- backports-v4.18-rc7.orig/net/mac80211/tx.c
153 +++ backports-v4.18-rc7/net/mac80211/tx.c
154 @@ -1169,8 +1169,7 @@ ieee80211_tx_prepare(struct ieee80211_su
155 info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
156
157 hdr = (struct ieee80211_hdr *) skb->data;
158 -
159 - tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
160 + tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
161
162 if (likely(sta)) {
163 if (!IS_ERR(sta))
164 @@ -2200,7 +2199,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
165 goto fail;
166
167 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
168 - hdrlen = ieee80211_hdrlen(hdr->frame_control);
169 + hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
170
171 if (skb->len < len_rthdr + hdrlen)
172 goto fail;
173 @@ -2418,7 +2417,7 @@ static struct sk_buff *ieee80211_build_h
174 struct ieee80211_chanctx_conf *chanctx_conf;
175 struct ieee80211_sub_if_data *ap_sdata;
176 enum nl80211_band band;
177 - int ret;
178 + int padsize, ret;
179
180 if (IS_ERR(sta))
181 sta = NULL;
182 @@ -2638,6 +2637,9 @@ static struct sk_buff *ieee80211_build_h
183 hdrlen += 2;
184 }
185
186 + /* Check aligned4 skb required */
187 + padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen);
188 +
189 /*
190 * Drop unicast frames to unauthorised stations unless they are
191 * EAPOL frames from the local station.
192 @@ -2718,6 +2720,7 @@ static struct sk_buff *ieee80211_build_h
193
194 skb_pull(skb, skip_header_bytes);
195 head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
196 + head_need += padsize;
197
198 /*
199 * So we need to modify the skb header and hence need a copy of
200 @@ -2750,6 +2753,9 @@ static struct sk_buff *ieee80211_build_h
201 memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
202 #endif
203
204 + if (padsize)
205 + memset(skb_push(skb, padsize), 0, padsize);
206 +
207 if (ieee80211_is_data_qos(fc)) {
208 __le16 *qos_control;
209
210 @@ -2925,6 +2931,9 @@ void ieee80211_check_fast_xmit(struct st
211 fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
212 }
213
214 + /* Check aligned4 skb required */
215 + build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len);
216 +
217 /* We store the key here so there's no point in using rcu_dereference()
218 * but that's fine because the code that changes the pointers will call
219 * this function after doing so. For a single CPU that would be enough,
220 @@ -3513,7 +3522,7 @@ begin:
221
222 if (tx.key &&
223 (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
224 - pn_offs = ieee80211_hdrlen(hdr->frame_control);
225 + pn_offs = tx.hdrlen;
226
227 ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
228 tx.key, skb);
229 Index: backports-v4.18-rc7/net/mac80211/util.c
230 ===================================================================
231 --- backports-v4.18-rc7.orig/net/mac80211/util.c
232 +++ backports-v4.18-rc7/net/mac80211/util.c
233 @@ -1274,6 +1274,7 @@ void ieee80211_send_auth(struct ieee8021
234 u32 tx_flags)
235 {
236 struct ieee80211_local *local = sdata->local;
237 + struct ieee80211_hw *hw = &local->hw;
238 struct sk_buff *skb;
239 struct ieee80211_mgmt *mgmt;
240 unsigned int hdrlen;
241 @@ -1300,7 +1301,7 @@ void ieee80211_send_auth(struct ieee8021
242 skb_put_data(skb, extra, extra_len);
243
244 if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
245 - hdrlen = ieee80211_hdrlen(mgmt->frame_control);
246 + hdrlen = ieee80211_padded_hdrlen(hw, mgmt->frame_control);
247 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
248 err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
249 key_len, key_idx);