7593c41da068a5476af97f3c198d60ef736dfd14
[openwrt/staging/thess.git] / package / kernel / mac80211 / patches / subsys / 318-mac80211-rework-tx-encapsulation-offload-API.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Thu, 13 Aug 2020 15:37:11 +0200
3 Subject: [PATCH] mac80211: rework tx encapsulation offload API
4
5 The current API (which lets the driver turn on/off per vif directly) has a
6 number of limitations:
7 - it does not deal with AP_VLAN
8 - conditions for enabling (no tkip, no monitor) are only checked at
9 add_interface time
10 - no way to indicate 4-addr support
11
12 In order to address this, store offload flags in struct ieee80211_vif
13 (easy to extend for decap offload later). mac80211 initially sets the enable
14 flag, but gives the driver a chance to modify it before its settings are
15 applied. In addition to the .add_interface op, a .update_vif_offload op is
16 introduced, which can be used for runtime changes.
17
18 If a driver can't disable encap offload at runtime, or if it has some extra
19 limitations, it can simply override the flags within those ops.
20
21 Support for encap offload with 4-address mode interfaces can be enabled
22 by setting a flag from .add_interface or .update_vif_offload.
23
24 Signed-off-by: Felix Fietkau <nbd@nbd.name>
25 ---
26
27 --- a/drivers/net/wireless/ath/ath11k/mac.c
28 +++ b/drivers/net/wireless/ath/ath11k/mac.c
29 @@ -4150,6 +4150,35 @@ static int ath11k_set_he_mu_sounding_mod
30 return ret;
31 }
32
33 +static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
34 + struct ieee80211_vif *vif)
35 +{
36 + struct ath11k *ar = hw->priv;
37 + struct ath11k_base *ab = ar->ab;
38 + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
39 + u32 param_id, param_value;
40 + int ret;
41 +
42 + param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
43 + if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
44 + (vif->type != NL80211_IFTYPE_STATION &&
45 + vif->type != NL80211_IFTYPE_AP))
46 + vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
47 +
48 + if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
49 + param_value = ATH11K_HW_TXRX_ETHERNET;
50 + else
51 + param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
52 +
53 + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
54 + param_id, param_value);
55 + if (ret) {
56 + ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
57 + arvif->vdev_id, ret);
58 + vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
59 + }
60 +}
61 +
62 static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
63 struct ieee80211_vif *vif)
64 {
65 @@ -4159,7 +4188,6 @@ static int ath11k_mac_op_add_interface(s
66 struct vdev_create_params vdev_param = {0};
67 struct peer_create_params peer_param;
68 u32 param_id, param_value;
69 - int hw_encap = 0;
70 u16 nss;
71 int i;
72 int ret;
73 @@ -4253,30 +4281,7 @@ static int ath11k_mac_op_add_interface(s
74 list_add(&arvif->list, &ar->arvifs);
75 spin_unlock_bh(&ar->data_lock);
76
77 - param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
78 - if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
79 - switch (vif->type) {
80 - case NL80211_IFTYPE_STATION:
81 - case NL80211_IFTYPE_AP_VLAN:
82 - case NL80211_IFTYPE_AP:
83 - hw_encap = 1;
84 - break;
85 - default:
86 - break;
87 - }
88 -
89 - if (ieee80211_set_hw_80211_encap(vif, hw_encap))
90 - param_value = ATH11K_HW_TXRX_ETHERNET;
91 - else
92 - param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
93 -
94 - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
95 - param_id, param_value);
96 - if (ret) {
97 - ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
98 - arvif->vdev_id, ret);
99 - goto err_vdev_del;
100 - }
101 + ath11k_mac_op_update_vif_offload(hw, vif);
102
103 nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
104 ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
105 @@ -5599,6 +5604,7 @@ static const struct ieee80211_ops ath11k
106 .reconfig_complete = ath11k_mac_op_reconfig_complete,
107 .add_interface = ath11k_mac_op_add_interface,
108 .remove_interface = ath11k_mac_op_remove_interface,
109 + .update_vif_offload = ath11k_mac_op_update_vif_offload,
110 .config = ath11k_mac_op_config,
111 .bss_info_changed = ath11k_mac_op_bss_info_changed,
112 .configure_filter = ath11k_mac_op_configure_filter,
113 @@ -5852,6 +5858,7 @@ static int __ath11k_mac_register(struct
114 ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
115 ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
116 ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
117 + ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
118 if (ht_cap & WMI_HT_CAP_ENABLED) {
119 ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
120 ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
121 --- a/include/net/mac80211.h
122 +++ b/include/net/mac80211.h
123 @@ -1603,6 +1603,21 @@ enum ieee80211_vif_flags {
124 IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
125 };
126
127 +
128 +/**
129 + * enum ieee80211_offload_flags - virtual interface offload flags
130 + *
131 + * @IEEE80211_OFFLOAD_ENCAP_ENABLED: tx encapsulation offload is enabled
132 + * The driver supports sending frames passed as 802.3 frames by mac80211.
133 + * It must also support sending 802.11 packets for the same interface.
134 + * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload
135 + */
136 +
137 +enum ieee80211_offload_flags {
138 + IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0),
139 + IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1),
140 +};
141 +
142 /**
143 * struct ieee80211_vif - per-interface data
144 *
145 @@ -1623,6 +1638,11 @@ enum ieee80211_vif_flags {
146 * these need to be set (or cleared) when the interface is added
147 * or, if supported by the driver, the interface type is changed
148 * at runtime, mac80211 will never touch this field
149 + * @offloaad_flags: hardware offload capabilities/flags for this interface.
150 + * These are initialized by mac80211 before calling .add_interface,
151 + * .change_interface or .update_vif_offload and updated by the driver
152 + * within these ops, based on supported features or runtime change
153 + * restrictions.
154 * @hw_queue: hardware queue for each AC
155 * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
156 * @chanctx_conf: The channel context this interface is assigned to, or %NULL
157 @@ -1659,6 +1679,7 @@ struct ieee80211_vif {
158 struct ieee80211_chanctx_conf __rcu *chanctx_conf;
159
160 u32 driver_flags;
161 + u32 offload_flags;
162
163 #ifdef CPTCFG_MAC80211_DEBUGFS
164 struct dentry *debugfs_dir;
165 @@ -2325,6 +2346,9 @@ struct ieee80211_txq {
166 * aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
167 * A-MPDU sessions active while rekeying with Extended Key ID.
168 *
169 + * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
170 + * offload
171 + *
172 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
173 */
174 enum ieee80211_hw_flags {
175 @@ -2377,6 +2401,7 @@ enum ieee80211_hw_flags {
176 IEEE80211_HW_SUPPORTS_MULTI_BSSID,
177 IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
178 IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
179 + IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
180
181 /* keep last, obviously */
182 NUM_IEEE80211_HW_FLAGS
183 @@ -3811,6 +3836,8 @@ enum ieee80211_reconfig_type {
184 * @set_tid_config: Apply TID specific configurations. This callback may sleep.
185 * @reset_tid_config: Reset TID specific configuration for the peer.
186 * This callback may sleep.
187 + * @update_vif_config: Update virtual interface offload flags
188 + * This callback may sleep.
189 */
190 struct ieee80211_ops {
191 void (*tx)(struct ieee80211_hw *hw,
192 @@ -4122,6 +4149,8 @@ struct ieee80211_ops {
193 int (*reset_tid_config)(struct ieee80211_hw *hw,
194 struct ieee80211_vif *vif,
195 struct ieee80211_sta *sta, u8 tids);
196 + void (*update_vif_offload)(struct ieee80211_hw *hw,
197 + struct ieee80211_vif *vif);
198 };
199
200 /**
201 --- a/net/mac80211/debugfs.c
202 +++ b/net/mac80211/debugfs.c
203 @@ -408,6 +408,7 @@ static const char *hw_flag_names[] = {
204 FLAG(SUPPORTS_MULTI_BSSID),
205 FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
206 FLAG(AMPDU_KEYBORDER_SUPPORT),
207 + FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
208 #undef FLAG
209 };
210
211 --- a/net/mac80211/driver-ops.h
212 +++ b/net/mac80211/driver-ops.h
213 @@ -1385,4 +1385,19 @@ static inline int drv_reset_tid_config(s
214
215 return ret;
216 }
217 +
218 +static inline void drv_update_vif_offload(struct ieee80211_local *local,
219 + struct ieee80211_sub_if_data *sdata)
220 +{
221 + might_sleep();
222 + check_sdata_in_driver(sdata);
223 +
224 + if (!local->ops->update_vif_offload)
225 + return;
226 +
227 + trace_drv_update_vif_offload(local, sdata);
228 + local->ops->update_vif_offload(&local->hw, &sdata->vif);
229 + trace_drv_return_void(local);
230 +}
231 +
232 #endif /* __MAC80211_DRIVER_OPS */
233 --- a/net/mac80211/ieee80211_i.h
234 +++ b/net/mac80211/ieee80211_i.h
235 @@ -990,8 +990,6 @@ struct ieee80211_sub_if_data {
236 } debugfs;
237 #endif
238
239 - bool hw_80211_encap;
240 -
241 /* must be last, dynamically sized area in this! */
242 struct ieee80211_vif vif;
243 };
244 @@ -1769,6 +1767,7 @@ void ieee80211_del_virtual_monitor(struc
245 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
246 void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
247 bool update_bss);
248 +void ieee80211_recalc_offload(struct ieee80211_local *local);
249
250 static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
251 {
252 --- a/net/mac80211/iface.c
253 +++ b/net/mac80211/iface.c
254 @@ -43,6 +43,7 @@
255 */
256
257 static void ieee80211_iface_work(struct work_struct *work);
258 +static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata);
259
260 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
261 {
262 @@ -348,6 +349,85 @@ static int ieee80211_check_queues(struct
263 return 0;
264 }
265
266 +static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
267 +{
268 + switch (iftype) {
269 + /* P2P GO and client are mapped to AP/STATION types */
270 + case NL80211_IFTYPE_AP:
271 + case NL80211_IFTYPE_STATION:
272 + return true;
273 + default:
274 + return false;
275 + }
276 +}
277 +
278 +static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata)
279 +{
280 + struct ieee80211_local *local = sdata->local;
281 + u32 flags;
282 +
283 + flags = sdata->vif.offload_flags;
284 +
285 + if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) &&
286 + ieee80211_iftype_supports_encap_offload(sdata->vif.type)) {
287 + flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED;
288 +
289 + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
290 + local->hw.wiphy->frag_threshold != (u32)-1)
291 + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
292 +
293 + if (local->monitors)
294 + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
295 + } else {
296 + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
297 + }
298 +
299 + if (sdata->vif.offload_flags == flags)
300 + return false;
301 +
302 + sdata->vif.offload_flags = flags;
303 + return true;
304 +}
305 +
306 +
307 +static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata)
308 +{
309 + struct ieee80211_local *local = sdata->local;
310 + struct ieee80211_sub_if_data *vsdata;
311 +
312 + if (ieee80211_set_sdata_offload_flags(sdata)) {
313 + drv_update_vif_offload(local, sdata);
314 + ieee80211_set_vif_encap_ops(sdata);
315 + }
316 +
317 + list_for_each_entry(vsdata, &local->interfaces, list) {
318 + if (vsdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
319 + vsdata->bss != &sdata->u.ap)
320 + continue;
321 +
322 + ieee80211_set_vif_encap_ops(vsdata);
323 + }
324 +}
325 +
326 +void ieee80211_recalc_offload(struct ieee80211_local *local)
327 +{
328 + struct ieee80211_sub_if_data *sdata;
329 +
330 + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD))
331 + return;
332 +
333 + mutex_lock(&local->iflist_mtx);
334 +
335 + list_for_each_entry(sdata, &local->interfaces, list) {
336 + if (!ieee80211_sdata_running(sdata))
337 + continue;
338 +
339 + ieee80211_recalc_sdata_offload(sdata);
340 + }
341 +
342 + mutex_unlock(&local->iflist_mtx);
343 +}
344 +
345 void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
346 const int offset)
347 {
348 @@ -587,6 +667,7 @@ int ieee80211_do_open(struct wireless_de
349 if (rtnl_dereference(sdata->bss->beacon)) {
350 ieee80211_vif_vlan_copy_chanctx(sdata);
351 netif_carrier_on(dev);
352 + ieee80211_set_vif_encap_ops(sdata);
353 } else {
354 netif_carrier_off(dev);
355 }
356 @@ -616,6 +697,7 @@ int ieee80211_do_open(struct wireless_de
357
358 ieee80211_adjust_monitor_flags(sdata, 1);
359 ieee80211_configure_filter(local);
360 + ieee80211_recalc_offload(local);
361 mutex_lock(&local->mtx);
362 ieee80211_recalc_idle(local);
363 mutex_unlock(&local->mtx);
364 @@ -625,10 +707,13 @@ int ieee80211_do_open(struct wireless_de
365 default:
366 if (coming_up) {
367 ieee80211_del_virtual_monitor(local);
368 + ieee80211_set_sdata_offload_flags(sdata);
369
370 res = drv_add_interface(local, sdata);
371 if (res)
372 goto err_stop;
373 +
374 + ieee80211_set_vif_encap_ops(sdata);
375 res = ieee80211_check_queues(sdata,
376 ieee80211_vif_type_p2p(&sdata->vif));
377 if (res)
378 @@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8
379
380 };
381
382 -static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata,
383 - bool enable)
384 -{
385 - sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops :
386 - &ieee80211_dataif_ops;
387 - sdata->hw_80211_encap = enable;
388 -}
389 -
390 -bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
391 -{
392 - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
393 - struct ieee80211_local *local = sdata->local;
394 - struct ieee80211_sub_if_data *iter;
395 - struct ieee80211_key *key;
396 -
397 - mutex_lock(&local->iflist_mtx);
398 - list_for_each_entry(iter, &local->interfaces, list) {
399 - struct ieee80211_sub_if_data *disable = NULL;
400 -
401 - if (vif->type == NL80211_IFTYPE_MONITOR) {
402 - disable = iter;
403 - __ieee80211_set_hw_80211_encap(iter, false);
404 - } else if (iter->vif.type == NL80211_IFTYPE_MONITOR) {
405 - disable = sdata;
406 - enable = false;
407 - }
408 - if (disable)
409 - sdata_dbg(disable,
410 - "disable hw 80211 encap due to mon co-exist\n");
411 - }
412 - mutex_unlock(&local->iflist_mtx);
413 -
414 - if (enable == sdata->hw_80211_encap)
415 - return enable;
416 -
417 - if (!sdata->dev)
418 - return false;
419 -
420 - if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
421 - (local->hw.wiphy->frag_threshold != (u32)-1))
422 - enable = false;
423 -
424 - mutex_lock(&sdata->local->key_mtx);
425 - list_for_each_entry(key, &sdata->key_list, list) {
426 - if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
427 - enable = false;
428 - }
429 - mutex_unlock(&sdata->local->key_mtx);
430 -
431 - __ieee80211_set_hw_80211_encap(sdata, enable);
432 -
433 - return enable;
434 -}
435 -EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
436 -
437 static void ieee80211_if_free(struct net_device *dev)
438 {
439 free_percpu(netdev_tstats(dev));
440 @@ -1371,6 +1401,32 @@ static void ieee80211_if_setup_no_queue(
441 #endif
442 }
443
444 +static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
445 +{
446 + struct ieee80211_local *local = sdata->local;
447 + struct ieee80211_sub_if_data *bss = sdata;
448 + bool enabled;
449 +
450 + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
451 + if (!sdata->bss)
452 + return;
453 +
454 + bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
455 + }
456 +
457 + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
458 + !ieee80211_iftype_supports_encap_offload(bss->vif.type))
459 + return;
460 +
461 + enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
462 + if (sdata->wdev.use_4addr &&
463 + !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR))
464 + enabled = false;
465 +
466 + sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops :
467 + &ieee80211_dataif_ops;
468 +}
469 +
470 static void ieee80211_iface_work(struct work_struct *work)
471 {
472 struct ieee80211_sub_if_data *sdata =
473 @@ -1553,7 +1609,6 @@ static void ieee80211_setup_sdata(struct
474 sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
475
476 sdata->noack_map = 0;
477 - sdata->hw_80211_encap = false;
478
479 /* only monitor/p2p-device differ */
480 if (sdata->dev) {
481 @@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty
482
483 ieee80211_teardown_sdata(sdata);
484
485 + ieee80211_set_sdata_offload_flags(sdata);
486 ret = drv_change_interface(local, sdata, internal_type, p2p);
487 if (ret)
488 type = ieee80211_vif_type_p2p(&sdata->vif);
489 @@ -1700,6 +1756,7 @@ static int ieee80211_runtime_change_ifty
490 ieee80211_check_queues(sdata, type);
491
492 ieee80211_setup_sdata(sdata, type);
493 + ieee80211_set_vif_encap_ops(sdata);
494
495 err = ieee80211_do_open(&sdata->wdev, false);
496 WARN(err, "type change: do_open returned %d", err);
497 --- a/net/mac80211/key.c
498 +++ b/net/mac80211/key.c
499 @@ -177,13 +177,6 @@ static int ieee80211_key_enable_hw_accel
500 }
501 }
502
503 - /* TKIP countermeasures don't work in encap offload mode */
504 - if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
505 - sdata->hw_80211_encap) {
506 - sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n");
507 - return -EINVAL;
508 - }
509 -
510 ret = drv_set_key(key->local, SET_KEY, sdata,
511 sta ? &sta->sta : NULL, &key->conf);
512
513 @@ -219,14 +212,6 @@ static int ieee80211_key_enable_hw_accel
514 case WLAN_CIPHER_SUITE_CCMP_256:
515 case WLAN_CIPHER_SUITE_GCMP:
516 case WLAN_CIPHER_SUITE_GCMP_256:
517 - /* We cannot do software crypto of data frames with
518 - * encapsulation offload enabled. However for 802.11w to
519 - * function properly we need cmac/gmac keys.
520 - */
521 - if (sdata->hw_80211_encap)
522 - return -EINVAL;
523 - /* Fall through */
524 -
525 case WLAN_CIPHER_SUITE_AES_CMAC:
526 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
527 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
528 --- a/net/mac80211/trace.h
529 +++ b/net/mac80211/trace.h
530 @@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
531 )
532 );
533
534 +DEFINE_EVENT(local_sdata_addr_evt, drv_update_vif_offload,
535 + TP_PROTO(struct ieee80211_local *local,
536 + struct ieee80211_sub_if_data *sdata),
537 + TP_ARGS(local, sdata)
538 +);
539 +
540 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
541
542 #undef TRACE_INCLUDE_PATH
543 --- a/net/mac80211/tx.c
544 +++ b/net/mac80211/tx.c
545 @@ -4181,11 +4181,10 @@ static bool ieee80211_tx_8023(struct iee
546
547 static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
548 struct net_device *dev, struct sta_info *sta,
549 - struct sk_buff *skb)
550 + struct ieee80211_key *key, struct sk_buff *skb)
551 {
552 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
553 struct ieee80211_local *local = sdata->local;
554 - struct ieee80211_key *key;
555 struct tid_ampdu_tx *tid_tx;
556 u8 tid;
557
558 @@ -4234,7 +4233,6 @@ static void ieee80211_8023_xmit(struct i
559 info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
560 info->control.vif = &sdata->vif;
561
562 - key = rcu_dereference(sta->ptk[sta->ptk_idx]);
563 if (key)
564 info->control.hw_key = &key->conf;
565
566 @@ -4251,12 +4249,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8
567 {
568 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
569 struct ethhdr *ehdr = (struct ethhdr *)skb->data;
570 + struct ieee80211_key *key;
571 struct sta_info *sta;
572 -
573 - if (WARN_ON(!sdata->hw_80211_encap)) {
574 - kfree_skb(skb);
575 - return NETDEV_TX_OK;
576 - }
577 + bool offload = true;
578
579 if (unlikely(skb->len < ETH_HLEN)) {
580 kfree_skb(skb);
581 @@ -4265,15 +4260,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8
582
583 rcu_read_lock();
584
585 - if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
586 + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
587 kfree_skb(skb);
588 - else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
589 - !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
590 - sdata->control_port_protocol == ehdr->h_proto))
591 - ieee80211_subif_start_xmit(skb, dev);
592 + goto out;
593 + }
594 +
595 + if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
596 + !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
597 + sdata->control_port_protocol == ehdr->h_proto))
598 + offload = false;
599 + else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) &&
600 + (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
601 + key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
602 + offload = false;
603 +
604 + if (offload)
605 + ieee80211_8023_xmit(sdata, dev, sta, key, skb);
606 else
607 - ieee80211_8023_xmit(sdata, dev, sta, skb);
608 + ieee80211_subif_start_xmit(skb, dev);
609
610 +out:
611 rcu_read_unlock();
612
613 return NETDEV_TX_OK;