mac80211: ath10k: Allow to enable the thermal code of ath10k
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 320-v4.17-mac80211-support-A-MSDU-in-fast-rx.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Mon, 26 Feb 2018 22:09:29 +0100
3 Subject: [PATCH] mac80211: support A-MSDU in fast-rx
4
5 Only works if the IV was stripped from packets. Create a smaller
6 variant of ieee80211_rx_h_amsdu, which bypasses checks already done
7 within the fast-rx context.
8
9 Signed-off-by: Felix Fietkau <nbd@nbd.name>
10 ---
11
12 --- a/net/mac80211/rx.c
13 +++ b/net/mac80211/rx.c
14 @@ -2358,39 +2358,17 @@ ieee80211_deliver_skb(struct ieee80211_r
15 }
16
17 static ieee80211_rx_result debug_noinline
18 -ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
19 +__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
20 {
21 struct net_device *dev = rx->sdata->dev;
22 struct sk_buff *skb = rx->skb;
23 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
24 __le16 fc = hdr->frame_control;
25 struct sk_buff_head frame_list;
26 - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
27 struct ethhdr ethhdr;
28 const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
29
30 - if (unlikely(!ieee80211_is_data(fc)))
31 - return RX_CONTINUE;
32 -
33 - if (unlikely(!ieee80211_is_data_present(fc)))
34 - return RX_DROP_MONITOR;
35 -
36 - if (!(status->rx_flags & IEEE80211_RX_AMSDU))
37 - return RX_CONTINUE;
38 -
39 if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
40 - switch (rx->sdata->vif.type) {
41 - case NL80211_IFTYPE_AP_VLAN:
42 - if (!rx->sdata->u.vlan.sta)
43 - return RX_DROP_UNUSABLE;
44 - break;
45 - case NL80211_IFTYPE_STATION:
46 - if (!rx->sdata->u.mgd.use_4addr)
47 - return RX_DROP_UNUSABLE;
48 - break;
49 - default:
50 - return RX_DROP_UNUSABLE;
51 - }
52 check_da = NULL;
53 check_sa = NULL;
54 } else switch (rx->sdata->vif.type) {
55 @@ -2410,15 +2388,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
56 break;
57 }
58
59 - if (is_multicast_ether_addr(hdr->addr1))
60 - return RX_DROP_UNUSABLE;
61 -
62 skb->dev = dev;
63 __skb_queue_head_init(&frame_list);
64
65 if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
66 rx->sdata->vif.addr,
67 - rx->sdata->vif.type))
68 + rx->sdata->vif.type,
69 + data_offset))
70 return RX_DROP_UNUSABLE;
71
72 ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
73 @@ -2440,6 +2416,44 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
74 return RX_QUEUED;
75 }
76
77 +static ieee80211_rx_result debug_noinline
78 +ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
79 +{
80 + struct sk_buff *skb = rx->skb;
81 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
82 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
83 + __le16 fc = hdr->frame_control;
84 +
85 + if (!(status->rx_flags & IEEE80211_RX_AMSDU))
86 + return RX_CONTINUE;
87 +
88 + if (unlikely(!ieee80211_is_data(fc)))
89 + return RX_CONTINUE;
90 +
91 + if (unlikely(!ieee80211_is_data_present(fc)))
92 + return RX_DROP_MONITOR;
93 +
94 + if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
95 + switch (rx->sdata->vif.type) {
96 + case NL80211_IFTYPE_AP_VLAN:
97 + if (!rx->sdata->u.vlan.sta)
98 + return RX_DROP_UNUSABLE;
99 + break;
100 + case NL80211_IFTYPE_STATION:
101 + if (!rx->sdata->u.mgd.use_4addr)
102 + return RX_DROP_UNUSABLE;
103 + break;
104 + default:
105 + return RX_DROP_UNUSABLE;
106 + }
107 + }
108 +
109 + if (is_multicast_ether_addr(hdr->addr1))
110 + return RX_DROP_UNUSABLE;
111 +
112 + return __ieee80211_rx_h_amsdu(rx, 0);
113 +}
114 +
115 #ifdef CPTCFG_MAC80211_MESH
116 static ieee80211_rx_result
117 ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
118 @@ -3889,7 +3903,8 @@ static bool ieee80211_invoke_fast_rx(str
119 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
120 struct sta_info *sta = rx->sta;
121 int orig_len = skb->len;
122 - int snap_offs = ieee80211_hdrlen(hdr->frame_control);
123 + int hdrlen = ieee80211_hdrlen(hdr->frame_control);
124 + int snap_offs = hdrlen;
125 struct {
126 u8 snap[sizeof(rfc1042_header)];
127 __be16 proto;
128 @@ -3920,10 +3935,6 @@ static bool ieee80211_invoke_fast_rx(str
129 (status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS)
130 return false;
131
132 - /* we don't deal with A-MSDU deaggregation here */
133 - if (status->rx_flags & IEEE80211_RX_AMSDU)
134 - return false;
135 -
136 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
137 return false;
138
139 @@ -3955,21 +3966,24 @@ static bool ieee80211_invoke_fast_rx(str
140 snap_offs += IEEE80211_CCMP_HDR_LEN;
141 }
142
143 - if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
144 - goto drop;
145 - payload = (void *)(skb->data + snap_offs);
146 + if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
147 + if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
148 + goto drop;
149
150 - if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
151 - return false;
152 + payload = (void *)(skb->data + snap_offs);
153
154 - /* Don't handle these here since they require special code.
155 - * Accept AARP and IPX even though they should come with a
156 - * bridge-tunnel header - but if we get them this way then
157 - * there's little point in discarding them.
158 - */
159 - if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
160 - payload->proto == fast_rx->control_port_protocol))
161 - return false;
162 + if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
163 + return false;
164 +
165 + /* Don't handle these here since they require special code.
166 + * Accept AARP and IPX even though they should come with a
167 + * bridge-tunnel header - but if we get them this way then
168 + * there's little point in discarding them.
169 + */
170 + if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
171 + payload->proto == fast_rx->control_port_protocol))
172 + return false;
173 + }
174
175 /* after this point, don't punt to the slowpath! */
176
177 @@ -3983,12 +3997,6 @@ static bool ieee80211_invoke_fast_rx(str
178 }
179
180 /* statistics part of ieee80211_rx_h_sta_process() */
181 - stats->last_rx = jiffies;
182 - stats->last_rate = sta_stats_encode_rate(status);
183 -
184 - stats->fragments++;
185 - stats->packets++;
186 -
187 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
188 stats->last_signal = status->signal;
189 if (!fast_rx->uses_rss)
190 @@ -4017,6 +4025,20 @@ static bool ieee80211_invoke_fast_rx(str
191 if (rx->key && !ieee80211_has_protected(hdr->frame_control))
192 goto drop;
193
194 + if (status->rx_flags & IEEE80211_RX_AMSDU) {
195 + if (__ieee80211_rx_h_amsdu(rx, snap_offs - hdrlen) !=
196 + RX_QUEUED)
197 + goto drop;
198 +
199 + return true;
200 + }
201 +
202 + stats->last_rx = jiffies;
203 + stats->last_rate = sta_stats_encode_rate(status);
204 +
205 + stats->fragments++;
206 + stats->packets++;
207 +
208 /* do the header conversion - first grab the addresses */
209 ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
210 ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
211 --- a/include/net/cfg80211.h
212 +++ b/include/net/cfg80211.h
213 @@ -4331,10 +4331,12 @@ unsigned int ieee80211_get_mesh_hdrlen(s
214 * of it being pushed into the SKB
215 * @addr: the device MAC address
216 * @iftype: the virtual interface type
217 + * @data_offset: offset of payload after the 802.11 header
218 * Return: 0 on success. Non-zero on error.
219 */
220 int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
221 - const u8 *addr, enum nl80211_iftype iftype);
222 + const u8 *addr, enum nl80211_iftype iftype,
223 + u8 data_offset);
224
225 /**
226 * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
227 @@ -4346,7 +4348,7 @@ int ieee80211_data_to_8023_exthdr(struct
228 static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
229 enum nl80211_iftype iftype)
230 {
231 - return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
232 + return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
233 }
234
235 /**
236 --- a/net/wireless/util.c
237 +++ b/net/wireless/util.c
238 @@ -419,7 +419,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s
239 EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
240
241 int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
242 - const u8 *addr, enum nl80211_iftype iftype)
243 + const u8 *addr, enum nl80211_iftype iftype,
244 + u8 data_offset)
245 {
246 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
247 struct {
248 @@ -433,7 +434,7 @@ int ieee80211_data_to_8023_exthdr(struct
249 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
250 return -1;
251
252 - hdrlen = ieee80211_hdrlen(hdr->frame_control);
253 + hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
254 if (skb->len < hdrlen + 8)
255 return -1;
256