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
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.
9 Padding is added after ieee80211_hdr, before IV/LLC.
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).
16 With this patch we can skip this memmove() and save CPU.
18 Currently this was tested with ath9k, both hw/sw crypt for
21 Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
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.
32 + * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
33 + * Padding will be added after ieee80211_hdr, before IV/LLC.
35 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
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,
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),
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
66 +static inline unsigned int
67 +ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen)
70 + * While hdrlen is already aligned to two-byte boundaries,
71 + * simple check with & 2 will return correct padsize.
73 + if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS))
78 +static inline unsigned int
79 +ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc)
81 + unsigned int hdrlen;
83 + hdrlen = ieee80211_hdrlen(fc);
84 + hdrlen += ieee80211_hdr_padsize(hw, hdrlen);
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 {
98 u8 sa_offs, da_offs, pn_offs;
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);
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;
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);
123 + if (padsize && skb->len > hdrlen + padsize) {
124 + memmove(skb->data + padsize, skb->data, hdrlen);
125 + skb_pull(skb, padsize);
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
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);
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;
157 hdr = (struct ieee80211_hdr *) skb->data;
159 - tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
160 + tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
164 @@ -2200,7 +2199,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
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);
171 if (skb->len < len_rthdr + hdrlen)
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;
182 @@ -2638,6 +2637,9 @@ static struct sk_buff *ieee80211_build_h
186 + /* Check aligned4 skb required */
187 + padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen);
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
194 skb_pull(skb, skip_header_bytes);
195 head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
196 + head_need += padsize;
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);
205 + memset(skb_push(skb, padsize), 0, padsize);
207 if (ieee80211_is_data_qos(fc)) {
210 @@ -2925,6 +2931,9 @@ void ieee80211_check_fast_xmit(struct st
211 fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
214 + /* Check aligned4 skb required */
215 + build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len);
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:
223 (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
224 - pn_offs = ieee80211_hdrlen(hdr->frame_control);
225 + pn_offs = tx.hdrlen;
227 ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
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
236 struct ieee80211_local *local = sdata->local;
237 + struct ieee80211_hw *hw = &local->hw;
239 struct ieee80211_mgmt *mgmt;
241 @@ -1300,7 +1301,7 @@ void ieee80211_send_auth(struct ieee8021
242 skb_put_data(skb, extra, extra_len);
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,