xref: /openbmc/linux/net/mac80211/tx.c (revision 34d6f206a88c2651d216bd3487ac956a40b2ba8e)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e2ebc74dSJohannes Berg /*
3e2ebc74dSJohannes Berg  * Copyright 2002-2005, Instant802 Networks, Inc.
4e2ebc74dSJohannes Berg  * Copyright 2005-2006, Devicescape Software, Inc.
5e2ebc74dSJohannes Berg  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
6e2ebc74dSJohannes Berg  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
7d98ad83eSJohannes Berg  * Copyright 2013-2014  Intel Mobile Communications GmbH
8e700e44fSJohannes Berg  * Copyright (C) 2018-2024 Intel Corporation
9e2ebc74dSJohannes Berg  *
10e2ebc74dSJohannes Berg  * Transmit and frame generation functions.
11e2ebc74dSJohannes Berg  */
12e2ebc74dSJohannes Berg 
13e2ebc74dSJohannes Berg #include <linux/kernel.h>
14e2ebc74dSJohannes Berg #include <linux/slab.h>
15e2ebc74dSJohannes Berg #include <linux/skbuff.h>
16ebceec86SMichael Braun #include <linux/if_vlan.h>
17e2ebc74dSJohannes Berg #include <linux/etherdevice.h>
18e2ebc74dSJohannes Berg #include <linux/bitmap.h>
19d4e46a3dSJohannes Berg #include <linux/rcupdate.h>
20bc3b2d7fSPaul Gortmaker #include <linux/export.h>
21881d966bSEric W. Biederman #include <net/net_namespace.h>
22e2ebc74dSJohannes Berg #include <net/ieee80211_radiotap.h>
23e2ebc74dSJohannes Berg #include <net/cfg80211.h>
24e2ebc74dSJohannes Berg #include <net/mac80211.h>
255caa328eSMichal Kazior #include <net/codel.h>
265caa328eSMichal Kazior #include <net/codel_impl.h>
27e2ebc74dSJohannes Berg #include <asm/unaligned.h>
28fa962b92SMichal Kazior #include <net/fq_impl.h>
29d457a0e3SEric Dumazet #include <net/gso.h>
30e2ebc74dSJohannes Berg 
31e2ebc74dSJohannes Berg #include "ieee80211_i.h"
3224487981SJohannes Berg #include "driver-ops.h"
332c8dccc7SJohannes Berg #include "led.h"
3433b64eb2SLuis Carlos Cobo #include "mesh.h"
35e2ebc74dSJohannes Berg #include "wep.h"
36e2ebc74dSJohannes Berg #include "wpa.h"
37e2ebc74dSJohannes Berg #include "wme.h"
382c8dccc7SJohannes Berg #include "rate.h"
39e2ebc74dSJohannes Berg 
40e2ebc74dSJohannes Berg /* misc utils */
41e2ebc74dSJohannes Berg 
ieee80211_duration(struct ieee80211_tx_data * tx,struct sk_buff * skb,int group_addr,int next_frag_len)42252b86c4SJohannes Berg static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
43252b86c4SJohannes Berg 				 struct sk_buff *skb, int group_addr,
44e2ebc74dSJohannes Berg 				 int next_frag_len)
45e2ebc74dSJohannes Berg {
462103dec1SSimon Wunderlich 	int rate, mrate, erp, dur, i, shift = 0;
472e92e6f2SJohannes Berg 	struct ieee80211_rate *txrate;
48e2ebc74dSJohannes Berg 	struct ieee80211_local *local = tx->local;
498318d78aSJohannes Berg 	struct ieee80211_supported_band *sband;
50358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr;
51252b86c4SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
522103dec1SSimon Wunderlich 	struct ieee80211_chanctx_conf *chanctx_conf;
532103dec1SSimon Wunderlich 	u32 rate_flags = 0;
542103dec1SSimon Wunderlich 
5595cd470cSFelix Fietkau 	/* assume HW handles this */
5695cd470cSFelix Fietkau 	if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
5795cd470cSFelix Fietkau 		return 0;
5895cd470cSFelix Fietkau 
592103dec1SSimon Wunderlich 	rcu_read_lock();
60d0a9123eSJohannes Berg 	chanctx_conf = rcu_dereference(tx->sdata->vif.bss_conf.chanctx_conf);
612103dec1SSimon Wunderlich 	if (chanctx_conf) {
622103dec1SSimon Wunderlich 		shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
632103dec1SSimon Wunderlich 		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
642103dec1SSimon Wunderlich 	}
652103dec1SSimon Wunderlich 	rcu_read_unlock();
66e6a9854bSJohannes Berg 
67e6a9854bSJohannes Berg 	/* uh huh? */
680d528d85SFelix Fietkau 	if (WARN_ON_ONCE(tx->rate.idx < 0))
69e6a9854bSJohannes Berg 		return 0;
70e2ebc74dSJohannes Berg 
712d56577bSJohannes Berg 	sband = local->hw.wiphy->bands[info->band];
720d528d85SFelix Fietkau 	txrate = &sband->bitrates[tx->rate.idx];
738318d78aSJohannes Berg 
748318d78aSJohannes Berg 	erp = txrate->flags & IEEE80211_RATE_ERP_G;
75e2ebc74dSJohannes Berg 
7689b8c02aSThomas Pedersen 	/* device is expected to do this */
7789b8c02aSThomas Pedersen 	if (sband->band == NL80211_BAND_S1GHZ)
7889b8c02aSThomas Pedersen 		return 0;
7989b8c02aSThomas Pedersen 
80e2ebc74dSJohannes Berg 	/*
81e2ebc74dSJohannes Berg 	 * data and mgmt (except PS Poll):
82e2ebc74dSJohannes Berg 	 * - during CFP: 32768
83e2ebc74dSJohannes Berg 	 * - during contention period:
84e2ebc74dSJohannes Berg 	 *   if addr1 is group address: 0
85e2ebc74dSJohannes Berg 	 *   if more fragments = 0 and addr1 is individual address: time to
86e2ebc74dSJohannes Berg 	 *      transmit one ACK plus SIFS
87e2ebc74dSJohannes Berg 	 *   if more fragments = 1 and addr1 is individual address: time to
88e2ebc74dSJohannes Berg 	 *      transmit next fragment plus 2 x ACK plus 3 x SIFS
89e2ebc74dSJohannes Berg 	 *
90e2ebc74dSJohannes Berg 	 * IEEE 802.11, 9.6:
91e2ebc74dSJohannes Berg 	 * - control response frame (CTS or ACK) shall be transmitted using the
92e2ebc74dSJohannes Berg 	 *   same rate as the immediately previous frame in the frame exchange
93e2ebc74dSJohannes Berg 	 *   sequence, if this rate belongs to the PHY mandatory rates, or else
94e2ebc74dSJohannes Berg 	 *   at the highest possible rate belonging to the PHY rates in the
95e2ebc74dSJohannes Berg 	 *   BSSBasicRateSet
96e2ebc74dSJohannes Berg 	 */
97252b86c4SJohannes Berg 	hdr = (struct ieee80211_hdr *)skb->data;
98358c8d9dSHarvey Harrison 	if (ieee80211_is_ctl(hdr->frame_control)) {
99e2ebc74dSJohannes Berg 		/* TODO: These control frames are not currently sent by
100ccd7b362SJohannes Berg 		 * mac80211, but should they be implemented, this function
101e2ebc74dSJohannes Berg 		 * needs to be updated to support duration field calculation.
102e2ebc74dSJohannes Berg 		 *
103e2ebc74dSJohannes Berg 		 * RTS: time needed to transmit pending data/mgmt frame plus
104e2ebc74dSJohannes Berg 		 *    one CTS frame plus one ACK frame plus 3 x SIFS
105e2ebc74dSJohannes Berg 		 * CTS: duration of immediately previous RTS minus time
106e2ebc74dSJohannes Berg 		 *    required to transmit CTS and its SIFS
107e2ebc74dSJohannes Berg 		 * ACK: 0 if immediately previous directed data/mgmt had
108e2ebc74dSJohannes Berg 		 *    more=0, with more=1 duration in ACK frame is duration
109e2ebc74dSJohannes Berg 		 *    from previous frame minus time needed to transmit ACK
110e2ebc74dSJohannes Berg 		 *    and its SIFS
111e2ebc74dSJohannes Berg 		 * PS Poll: BIT(15) | BIT(14) | aid
112e2ebc74dSJohannes Berg 		 */
113e2ebc74dSJohannes Berg 		return 0;
114e2ebc74dSJohannes Berg 	}
115e2ebc74dSJohannes Berg 
116e2ebc74dSJohannes Berg 	/* data/mgmt */
117e2ebc74dSJohannes Berg 	if (0 /* FIX: data/mgmt during CFP */)
11803f93c3dSJohannes Berg 		return cpu_to_le16(32768);
119e2ebc74dSJohannes Berg 
120e2ebc74dSJohannes Berg 	if (group_addr) /* Group address as the destination - no ACK */
121e2ebc74dSJohannes Berg 		return 0;
122e2ebc74dSJohannes Berg 
123e2ebc74dSJohannes Berg 	/* Individual destination address:
124e2ebc74dSJohannes Berg 	 * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
125e2ebc74dSJohannes Berg 	 * CTS and ACK frames shall be transmitted using the highest rate in
126e2ebc74dSJohannes Berg 	 * basic rate set that is less than or equal to the rate of the
127e2ebc74dSJohannes Berg 	 * immediately previous frame and that is using the same modulation
128e2ebc74dSJohannes Berg 	 * (CCK or OFDM). If no basic rate set matches with these requirements,
129e2ebc74dSJohannes Berg 	 * the highest mandatory rate of the PHY that is less than or equal to
130e2ebc74dSJohannes Berg 	 * the rate of the previous frame is used.
131e2ebc74dSJohannes Berg 	 * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
132e2ebc74dSJohannes Berg 	 */
133e2ebc74dSJohannes Berg 	rate = -1;
1348318d78aSJohannes Berg 	/* use lowest available if everything fails */
1358318d78aSJohannes Berg 	mrate = sband->bitrates[0].bitrate;
1368318d78aSJohannes Berg 	for (i = 0; i < sband->n_bitrates; i++) {
1378318d78aSJohannes Berg 		struct ieee80211_rate *r = &sband->bitrates[i];
1388318d78aSJohannes Berg 
1398318d78aSJohannes Berg 		if (r->bitrate > txrate->bitrate)
140e2ebc74dSJohannes Berg 			break;
141e2ebc74dSJohannes Berg 
1422103dec1SSimon Wunderlich 		if ((rate_flags & r->flags) != rate_flags)
1432103dec1SSimon Wunderlich 			continue;
1442103dec1SSimon Wunderlich 
145bda3933aSJohannes Berg 		if (tx->sdata->vif.bss_conf.basic_rates & BIT(i))
1462103dec1SSimon Wunderlich 			rate = DIV_ROUND_UP(r->bitrate, 1 << shift);
147e2ebc74dSJohannes Berg 
1488318d78aSJohannes Berg 		switch (sband->band) {
14963fa0426SSrinivasan Raju 		case NL80211_BAND_2GHZ:
15063fa0426SSrinivasan Raju 		case NL80211_BAND_LC: {
1518318d78aSJohannes Berg 			u32 flag;
15239eac2deSJohannes Berg 			if (tx->sdata->deflink.operating_11g_mode)
1538318d78aSJohannes Berg 				flag = IEEE80211_RATE_MANDATORY_G;
1548318d78aSJohannes Berg 			else
1558318d78aSJohannes Berg 				flag = IEEE80211_RATE_MANDATORY_B;
1568318d78aSJohannes Berg 			if (r->flags & flag)
1578318d78aSJohannes Berg 				mrate = r->bitrate;
1588318d78aSJohannes Berg 			break;
1598318d78aSJohannes Berg 		}
16057fbcce3SJohannes Berg 		case NL80211_BAND_5GHZ:
161c5b9a7f8SArend van Spriel 		case NL80211_BAND_6GHZ:
1628318d78aSJohannes Berg 			if (r->flags & IEEE80211_RATE_MANDATORY_A)
1638318d78aSJohannes Berg 				mrate = r->bitrate;
1648318d78aSJohannes Berg 			break;
165df78a0c0SThomas Pedersen 		case NL80211_BAND_S1GHZ:
16657fbcce3SJohannes Berg 		case NL80211_BAND_60GHZ:
1673a0c52a6SVladimir Kondratiev 			/* TODO, for now fall through */
16857fbcce3SJohannes Berg 		case NUM_NL80211_BANDS:
1698318d78aSJohannes Berg 			WARN_ON(1);
1708318d78aSJohannes Berg 			break;
1718318d78aSJohannes Berg 		}
172e2ebc74dSJohannes Berg 	}
173e2ebc74dSJohannes Berg 	if (rate == -1) {
174e2ebc74dSJohannes Berg 		/* No matching basic rate found; use highest suitable mandatory
175e2ebc74dSJohannes Berg 		 * PHY rate */
1762103dec1SSimon Wunderlich 		rate = DIV_ROUND_UP(mrate, 1 << shift);
177e2ebc74dSJohannes Berg 	}
178e2ebc74dSJohannes Berg 
1796674f210SSimon Wunderlich 	/* Don't calculate ACKs for QoS Frames with NoAck Policy set */
1806674f210SSimon Wunderlich 	if (ieee80211_is_data_qos(hdr->frame_control) &&
181c26a0e10SClaudio Pisa 	    *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
1826674f210SSimon Wunderlich 		dur = 0;
1836674f210SSimon Wunderlich 	else
184e2ebc74dSJohannes Berg 		/* Time needed to transmit ACK
185e2ebc74dSJohannes Berg 		 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
186e2ebc74dSJohannes Berg 		 * to closest integer */
1874ee73f33SMichal Kazior 		dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
188438b61b7SSimon Wunderlich 				tx->sdata->vif.bss_conf.use_short_preamble,
189438b61b7SSimon Wunderlich 				shift);
190e2ebc74dSJohannes Berg 
191e2ebc74dSJohannes Berg 	if (next_frag_len) {
192e2ebc74dSJohannes Berg 		/* Frame is fragmented: duration increases with time needed to
193e2ebc74dSJohannes Berg 		 * transmit next fragment plus ACK and 2 x SIFS. */
194e2ebc74dSJohannes Berg 		dur *= 2; /* ACK + SIFS */
195e2ebc74dSJohannes Berg 		/* next fragment */
1964ee73f33SMichal Kazior 		dur += ieee80211_frame_duration(sband->band, next_frag_len,
1978318d78aSJohannes Berg 				txrate->bitrate, erp,
198438b61b7SSimon Wunderlich 				tx->sdata->vif.bss_conf.use_short_preamble,
199438b61b7SSimon Wunderlich 				shift);
200e2ebc74dSJohannes Berg 	}
201e2ebc74dSJohannes Berg 
20203f93c3dSJohannes Berg 	return cpu_to_le16(dur);
203e2ebc74dSJohannes Berg }
204e2ebc74dSJohannes Berg 
205e2ebc74dSJohannes Berg /* tx handlers */
2065c1b98a5SKalle Valo static ieee80211_tx_result debug_noinline
ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data * tx)2075c1b98a5SKalle Valo ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
2085c1b98a5SKalle Valo {
2095c1b98a5SKalle Valo 	struct ieee80211_local *local = tx->local;
2100c74211dSKalle Valo 	struct ieee80211_if_managed *ifmgd;
21194a5b3acSAndrei Otcheretianski 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
2125c1b98a5SKalle Valo 
2135c1b98a5SKalle Valo 	/* driver doesn't support power save */
21430686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
2155c1b98a5SKalle Valo 		return TX_CONTINUE;
2165c1b98a5SKalle Valo 
2175c1b98a5SKalle Valo 	/* hardware does dynamic power save */
21830686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
2195c1b98a5SKalle Valo 		return TX_CONTINUE;
2205c1b98a5SKalle Valo 
2215c1b98a5SKalle Valo 	/* dynamic power save disabled */
2225c1b98a5SKalle Valo 	if (local->hw.conf.dynamic_ps_timeout <= 0)
2235c1b98a5SKalle Valo 		return TX_CONTINUE;
2245c1b98a5SKalle Valo 
2255c1b98a5SKalle Valo 	/* we are scanning, don't enable power save */
2265c1b98a5SKalle Valo 	if (local->scanning)
2275c1b98a5SKalle Valo 		return TX_CONTINUE;
2285c1b98a5SKalle Valo 
2295c1b98a5SKalle Valo 	if (!local->ps_sdata)
2305c1b98a5SKalle Valo 		return TX_CONTINUE;
2315c1b98a5SKalle Valo 
2325c1b98a5SKalle Valo 	/* No point if we're going to suspend */
2335c1b98a5SKalle Valo 	if (local->quiescing)
2345c1b98a5SKalle Valo 		return TX_CONTINUE;
2355c1b98a5SKalle Valo 
2360c74211dSKalle Valo 	/* dynamic ps is supported only in managed mode */
2370c74211dSKalle Valo 	if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
2380c74211dSKalle Valo 		return TX_CONTINUE;
2390c74211dSKalle Valo 
24094a5b3acSAndrei Otcheretianski 	if (unlikely(info->flags & IEEE80211_TX_INTFL_OFFCHAN_TX_OK))
24194a5b3acSAndrei Otcheretianski 		return TX_CONTINUE;
24294a5b3acSAndrei Otcheretianski 
2430c74211dSKalle Valo 	ifmgd = &tx->sdata->u.mgd;
2440c74211dSKalle Valo 
2450c74211dSKalle Valo 	/*
2460c74211dSKalle Valo 	 * Don't wakeup from power save if u-apsd is enabled, voip ac has
2470c74211dSKalle Valo 	 * u-apsd enabled and the frame is in voip class. This effectively
2480c74211dSKalle Valo 	 * means that even if all access categories have u-apsd enabled, in
2490c74211dSKalle Valo 	 * practise u-apsd is only used with the voip ac. This is a
2500c74211dSKalle Valo 	 * workaround for the case when received voip class packets do not
2510c74211dSKalle Valo 	 * have correct qos tag for some reason, due the network or the
2520c74211dSKalle Valo 	 * peer application.
2530c74211dSKalle Valo 	 *
254dc41e4d4SEliad Peller 	 * Note: ifmgd->uapsd_queues access is racy here. If the value is
2550c74211dSKalle Valo 	 * changed via debugfs, user needs to reassociate manually to have
2560c74211dSKalle Valo 	 * everything in sync.
2570c74211dSKalle Valo 	 */
2584875d30dSJohannes Berg 	if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) &&
2594875d30dSJohannes Berg 	    (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) &&
2604875d30dSJohannes Berg 	    skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO)
2610c74211dSKalle Valo 		return TX_CONTINUE;
2620c74211dSKalle Valo 
2635c1b98a5SKalle Valo 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
2645c1b98a5SKalle Valo 		ieee80211_stop_queues_by_reason(&local->hw,
265445ea4e8SJohannes Berg 						IEEE80211_MAX_QUEUE_MAP,
266cca07b00SLuciano Coelho 						IEEE80211_QUEUE_STOP_REASON_PS,
267cca07b00SLuciano Coelho 						false);
268db28569aSVivek Natarajan 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
2695c1b98a5SKalle Valo 		ieee80211_queue_work(&local->hw,
2705c1b98a5SKalle Valo 				     &local->dynamic_ps_disable_work);
2715c1b98a5SKalle Valo 	}
2725c1b98a5SKalle Valo 
2735db1c07cSLuciano Coelho 	/* Don't restart the timer if we're not disassociated */
2745db1c07cSLuciano Coelho 	if (!ifmgd->associated)
2755db1c07cSLuciano Coelho 		return TX_CONTINUE;
2765db1c07cSLuciano Coelho 
2775c1b98a5SKalle Valo 	mod_timer(&local->dynamic_ps_timer, jiffies +
2785c1b98a5SKalle Valo 		  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
2795c1b98a5SKalle Valo 
2805c1b98a5SKalle Valo 	return TX_CONTINUE;
2815c1b98a5SKalle Valo }
282e2ebc74dSJohannes Berg 
283d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data * tx)2845cf121c3SJohannes Berg ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
285e2ebc74dSJohannes Berg {
286358c8d9dSHarvey Harrison 
287e039fa4aSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
288e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
289c2c98fdeSJohannes Berg 	bool assoc = false;
290e2ebc74dSJohannes Berg 
291e039fa4aSJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
2929ae54c84SJohannes Berg 		return TX_CONTINUE;
29358d4185eSJohannes Berg 
294b23b025fSBen Greear 	if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
295b23b025fSBen Greear 	    test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
296a9a6ffffSKalle Valo 	    !ieee80211_is_probe_req(hdr->frame_control) &&
29730b2f0beSThomas Pedersen 	    !ieee80211_is_any_nullfunc(hdr->frame_control))
298a9a6ffffSKalle Valo 		/*
299a9a6ffffSKalle Valo 		 * When software scanning only nullfunc frames (to notify
300a9a6ffffSKalle Valo 		 * the sleep state to the AP) and probe requests (for the
301a9a6ffffSKalle Valo 		 * active scan) are allowed, all other frames should not be
302a9a6ffffSKalle Valo 		 * sent and we should not get here, but if we do
303a9a6ffffSKalle Valo 		 * nonetheless, drop them to avoid sending them
304a9a6ffffSKalle Valo 		 * off-channel. See the link below and
305a9a6ffffSKalle Valo 		 * ieee80211_start_scan() for more.
306a9a6ffffSKalle Valo 		 *
307a9a6ffffSKalle Valo 		 * http://article.gmane.org/gmane.linux.kernel.wireless.general/30089
308a9a6ffffSKalle Valo 		 */
3099ae54c84SJohannes Berg 		return TX_DROP;
310e2ebc74dSJohannes Berg 
311239281f8SRostislav Lisovy 	if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
312239281f8SRostislav Lisovy 		return TX_CONTINUE;
313239281f8SRostislav Lisovy 
3145cf121c3SJohannes Berg 	if (tx->flags & IEEE80211_TX_PS_BUFFERED)
3159ae54c84SJohannes Berg 		return TX_CONTINUE;
316e2ebc74dSJohannes Berg 
317c2c98fdeSJohannes Berg 	if (tx->sta)
318c2c98fdeSJohannes Berg 		assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
319e2ebc74dSJohannes Berg 
3205cf121c3SJohannes Berg 	if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
321c2c98fdeSJohannes Berg 		if (unlikely(!assoc &&
322358c8d9dSHarvey Harrison 			     ieee80211_is_data(hdr->frame_control))) {
323e2ebc74dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
324bdcbd8e0SJohannes Berg 			sdata_info(tx->sdata,
325bdcbd8e0SJohannes Berg 				   "dropped data frame to not associated station %pM\n",
326bdcbd8e0SJohannes Berg 				   hdr->addr1);
327bdcbd8e0SJohannes Berg #endif
328e2ebc74dSJohannes Berg 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
3299ae54c84SJohannes Berg 			return TX_DROP;
330e2ebc74dSJohannes Berg 		}
33172f15d53SMichael Braun 	} else if (unlikely(ieee80211_is_data(hdr->frame_control) &&
33272f15d53SMichael Braun 			    ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) {
333e2ebc74dSJohannes Berg 		/*
334e2ebc74dSJohannes Berg 		 * No associated STAs - no need to send multicast
335e2ebc74dSJohannes Berg 		 * frames.
336e2ebc74dSJohannes Berg 		 */
3379ae54c84SJohannes Berg 		return TX_DROP;
338e2ebc74dSJohannes Berg 	}
339e2ebc74dSJohannes Berg 
3409ae54c84SJohannes Berg 	return TX_CONTINUE;
341e2ebc74dSJohannes Berg }
342e2ebc74dSJohannes Berg 
343e2ebc74dSJohannes Berg /* This function is called whenever the AP is about to exceed the maximum limit
344e2ebc74dSJohannes Berg  * of buffered frames for power saving STAs. This situation should not really
345e2ebc74dSJohannes Berg  * happen often during normal operation, so dropping the oldest buffered packet
346e2ebc74dSJohannes Berg  * from each queue should be OK to make some room for new frames. */
purge_old_ps_buffers(struct ieee80211_local * local)347e2ebc74dSJohannes Berg static void purge_old_ps_buffers(struct ieee80211_local *local)
348e2ebc74dSJohannes Berg {
349e2ebc74dSJohannes Berg 	int total = 0, purged = 0;
350e2ebc74dSJohannes Berg 	struct sk_buff *skb;
351e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata;
352e2ebc74dSJohannes Berg 	struct sta_info *sta;
353e2ebc74dSJohannes Berg 
35479010420SJohannes Berg 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
355d012a605SMarco Porsch 		struct ps_data *ps;
356d012a605SMarco Porsch 
357d012a605SMarco Porsch 		if (sdata->vif.type == NL80211_IFTYPE_AP)
358d012a605SMarco Porsch 			ps = &sdata->u.ap.ps;
3593f52b7e3SMarco Porsch 		else if (ieee80211_vif_is_mesh(&sdata->vif))
3603f52b7e3SMarco Porsch 			ps = &sdata->u.mesh.ps;
361d012a605SMarco Porsch 		else
362e2ebc74dSJohannes Berg 			continue;
363d012a605SMarco Porsch 
364d012a605SMarco Porsch 		skb = skb_dequeue(&ps->bc_buf);
365e2ebc74dSJohannes Berg 		if (skb) {
366e2ebc74dSJohannes Berg 			purged++;
3676b07d9caSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
368e2ebc74dSJohannes Berg 		}
369d012a605SMarco Porsch 		total += skb_queue_len(&ps->bc_buf);
370e2ebc74dSJohannes Berg 	}
371e2ebc74dSJohannes Berg 
372948d887dSJohannes Berg 	/*
373948d887dSJohannes Berg 	 * Drop one frame from each station from the lowest-priority
374948d887dSJohannes Berg 	 * AC that has frames at all.
375948d887dSJohannes Berg 	 */
376d0709a65SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
377948d887dSJohannes Berg 		int ac;
378948d887dSJohannes Berg 
379948d887dSJohannes Berg 		for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) {
380948d887dSJohannes Berg 			skb = skb_dequeue(&sta->ps_tx_buf[ac]);
381948d887dSJohannes Berg 			total += skb_queue_len(&sta->ps_tx_buf[ac]);
382e2ebc74dSJohannes Berg 			if (skb) {
383e2ebc74dSJohannes Berg 				purged++;
384c3e7724bSFelix Fietkau 				ieee80211_free_txskb(&local->hw, skb);
385948d887dSJohannes Berg 				break;
386e2ebc74dSJohannes Berg 			}
387948d887dSJohannes Berg 		}
388e2ebc74dSJohannes Berg 	}
389d0709a65SJohannes Berg 
390e2ebc74dSJohannes Berg 	local->total_ps_buffered = total;
391bdcbd8e0SJohannes Berg 	ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
392e2ebc74dSJohannes Berg }
393e2ebc74dSJohannes Berg 
3949ae54c84SJohannes Berg static ieee80211_tx_result
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data * tx)3955cf121c3SJohannes Berg ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
396e2ebc74dSJohannes Berg {
397e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
398358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
399d012a605SMarco Porsch 	struct ps_data *ps;
400e039fa4aSJohannes Berg 
4017d54d0ddSJohannes Berg 	/*
4027d54d0ddSJohannes Berg 	 * broadcast/multicast frame
4037d54d0ddSJohannes Berg 	 *
4043f52b7e3SMarco Porsch 	 * If any of the associated/peer stations is in power save mode,
4057d54d0ddSJohannes Berg 	 * the frame is buffered to be sent after DTIM beacon frame.
4067d54d0ddSJohannes Berg 	 * This is done either by the hardware or us.
4077d54d0ddSJohannes Berg 	 */
4087d54d0ddSJohannes Berg 
4093f52b7e3SMarco Porsch 	/* powersaving STAs currently only in AP/VLAN/mesh mode */
410d012a605SMarco Porsch 	if (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
411d012a605SMarco Porsch 	    tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
4123e122be0SJohannes Berg 		if (!tx->sdata->bss)
4133e122be0SJohannes Berg 			return TX_CONTINUE;
4143e122be0SJohannes Berg 
415d012a605SMarco Porsch 		ps = &tx->sdata->bss->ps;
4163f52b7e3SMarco Porsch 	} else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) {
4173f52b7e3SMarco Porsch 		ps = &tx->sdata->u.mesh.ps;
418d012a605SMarco Porsch 	} else {
419d012a605SMarco Porsch 		return TX_CONTINUE;
420d012a605SMarco Porsch 	}
421d012a605SMarco Porsch 
422d012a605SMarco Porsch 
4233e122be0SJohannes Berg 	/* no buffering for ordered frames */
424358c8d9dSHarvey Harrison 	if (ieee80211_has_order(hdr->frame_control))
4259ae54c84SJohannes Berg 		return TX_CONTINUE;
4267d54d0ddSJohannes Berg 
42708b99399SJohannes Berg 	if (ieee80211_is_probe_req(hdr->frame_control))
42808b99399SJohannes Berg 		return TX_CONTINUE;
42908b99399SJohannes Berg 
43030686bf7SJohannes Berg 	if (ieee80211_hw_check(&tx->local->hw, QUEUE_CONTROL))
431f4d57941SJohannes Berg 		info->hw_queue = tx->sdata->vif.cab_queue;
432f4d57941SJohannes Berg 
4339ec1190dSFelix Fietkau 	/* no stations in PS mode and no buffered packets */
4349ec1190dSFelix Fietkau 	if (!atomic_read(&ps->num_sta_ps) && skb_queue_empty(&ps->bc_buf))
4359ae54c84SJohannes Berg 		return TX_CONTINUE;
4367d54d0ddSJohannes Berg 
43762b1208eSJohannes Berg 	info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
43862b1208eSJohannes Berg 
43962b517cbSJohannes Berg 	/* device releases frame after DTIM beacon */
44030686bf7SJohannes Berg 	if (!ieee80211_hw_check(&tx->local->hw, HOST_BROADCAST_PS_BUFFERING))
44162b1208eSJohannes Berg 		return TX_CONTINUE;
44262b1208eSJohannes Berg 
4437d54d0ddSJohannes Berg 	/* buffered in mac80211 */
444e2ebc74dSJohannes Berg 	if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
445e2ebc74dSJohannes Berg 		purge_old_ps_buffers(tx->local);
44662b1208eSJohannes Berg 
447d012a605SMarco Porsch 	if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
448bdcbd8e0SJohannes Berg 		ps_dbg(tx->sdata,
449bdcbd8e0SJohannes Berg 		       "BC TX buffer full - dropping the oldest frame\n");
4506b07d9caSFelix Fietkau 		ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf));
451e2ebc74dSJohannes Berg 	} else
452e2ebc74dSJohannes Berg 		tx->local->total_ps_buffered++;
45362b1208eSJohannes Berg 
454d012a605SMarco Porsch 	skb_queue_tail(&ps->bc_buf, tx->skb);
45562b1208eSJohannes Berg 
4569ae54c84SJohannes Berg 	return TX_QUEUED;
457e2ebc74dSJohannes Berg }
458e2ebc74dSJohannes Berg 
ieee80211_use_mfp(__le16 fc,struct sta_info * sta,struct sk_buff * skb)459fb733336SJouni Malinen static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
460fb733336SJouni Malinen 			     struct sk_buff *skb)
461fb733336SJouni Malinen {
462fb733336SJouni Malinen 	if (!ieee80211_is_mgmt(fc))
463fb733336SJouni Malinen 		return 0;
464fb733336SJouni Malinen 
465c2c98fdeSJohannes Berg 	if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
466fb733336SJouni Malinen 		return 0;
467fb733336SJouni Malinen 
468d8ca16dbSJohannes Berg 	if (!ieee80211_is_robust_mgmt_frame(skb))
469fb733336SJouni Malinen 		return 0;
470fb733336SJouni Malinen 
471fb733336SJouni Malinen 	return 1;
472fb733336SJouni Malinen }
473fb733336SJouni Malinen 
4749ae54c84SJohannes Berg static ieee80211_tx_result
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data * tx)4755cf121c3SJohannes Berg ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
476e2ebc74dSJohannes Berg {
477e2ebc74dSJohannes Berg 	struct sta_info *sta = tx->sta;
478e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
47908b99399SJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
4803393a608SJuuso Oikarinen 	struct ieee80211_local *local = tx->local;
481e2ebc74dSJohannes Berg 
48202f2f1a9SJohannes Berg 	if (unlikely(!sta))
4839ae54c84SJohannes Berg 		return TX_CONTINUE;
484e2ebc74dSJohannes Berg 
485c2c98fdeSJohannes Berg 	if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
4865ac2e350SJohannes Berg 		      test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
4875ac2e350SJohannes Berg 		      test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
48802f2f1a9SJohannes Berg 		     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
489948d887dSJohannes Berg 		int ac = skb_get_queue_mapping(tx->skb);
490948d887dSJohannes Berg 
49108b99399SJohannes Berg 		if (ieee80211_is_mgmt(hdr->frame_control) &&
4922c9abe65SJohannes Berg 		    !ieee80211_is_bufferable_mmpdu(tx->skb)) {
49308b99399SJohannes Berg 			info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
49408b99399SJohannes Berg 			return TX_CONTINUE;
49508b99399SJohannes Berg 		}
49608b99399SJohannes Berg 
497bdcbd8e0SJohannes Berg 		ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
498948d887dSJohannes Berg 		       sta->sta.addr, sta->sta.aid, ac);
499e2ebc74dSJohannes Berg 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
500e2ebc74dSJohannes Berg 			purge_old_ps_buffers(tx->local);
5011d147bfaSEmmanuel Grumbach 
5021d147bfaSEmmanuel Grumbach 		/* sync with ieee80211_sta_ps_deliver_wakeup */
5031d147bfaSEmmanuel Grumbach 		spin_lock(&sta->ps_lock);
5041d147bfaSEmmanuel Grumbach 		/*
5051d147bfaSEmmanuel Grumbach 		 * STA woke up the meantime and all the frames on ps_tx_buf have
5061d147bfaSEmmanuel Grumbach 		 * been queued to pending queue. No reordering can happen, go
5071d147bfaSEmmanuel Grumbach 		 * ahead and Tx the packet.
5081d147bfaSEmmanuel Grumbach 		 */
5091d147bfaSEmmanuel Grumbach 		if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
5105ac2e350SJohannes Berg 		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
5115ac2e350SJohannes Berg 		    !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
5121d147bfaSEmmanuel Grumbach 			spin_unlock(&sta->ps_lock);
5131d147bfaSEmmanuel Grumbach 			return TX_CONTINUE;
5141d147bfaSEmmanuel Grumbach 		}
5151d147bfaSEmmanuel Grumbach 
516948d887dSJohannes Berg 		if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
517948d887dSJohannes Berg 			struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
518bdcbd8e0SJohannes Berg 			ps_dbg(tx->sdata,
519bdcbd8e0SJohannes Berg 			       "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
520bdcbd8e0SJohannes Berg 			       sta->sta.addr, ac);
521c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, old);
522e2ebc74dSJohannes Berg 		} else
523e2ebc74dSJohannes Berg 			tx->local->total_ps_buffered++;
524004c872eSJohannes Berg 
525e039fa4aSJohannes Berg 		info->control.jiffies = jiffies;
5265061b0c2SJohannes Berg 		info->control.vif = &tx->sdata->vif;
527cc20ff2cSFelix Fietkau 		info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
52803c8c06fSJohannes Berg 		info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
529948d887dSJohannes Berg 		skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
5301d147bfaSEmmanuel Grumbach 		spin_unlock(&sta->ps_lock);
5313393a608SJuuso Oikarinen 
5323393a608SJuuso Oikarinen 		if (!timer_pending(&local->sta_cleanup))
5333393a608SJuuso Oikarinen 			mod_timer(&local->sta_cleanup,
5343393a608SJuuso Oikarinen 				  round_jiffies(jiffies +
5353393a608SJuuso Oikarinen 						STA_INFO_CLEANUP_INTERVAL));
5363393a608SJuuso Oikarinen 
537c868cb35SJohannes Berg 		/*
538c868cb35SJohannes Berg 		 * We queued up some frames, so the TIM bit might
539c868cb35SJohannes Berg 		 * need to be set, recalculate it.
540c868cb35SJohannes Berg 		 */
541c868cb35SJohannes Berg 		sta_info_recalc_tim(sta);
542c868cb35SJohannes Berg 
5439ae54c84SJohannes Berg 		return TX_QUEUED;
544bdcbd8e0SJohannes Berg 	} else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
545bdcbd8e0SJohannes Berg 		ps_dbg(tx->sdata,
546bdcbd8e0SJohannes Berg 		       "STA %pM in PS mode, but polling/in SP -> send frame\n",
547bdcbd8e0SJohannes Berg 		       sta->sta.addr);
548e2ebc74dSJohannes Berg 	}
549e2ebc74dSJohannes Berg 
5509ae54c84SJohannes Berg 	return TX_CONTINUE;
551e2ebc74dSJohannes Berg }
552e2ebc74dSJohannes Berg 
553d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_ps_buf(struct ieee80211_tx_data * tx)5545cf121c3SJohannes Berg ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
555e2ebc74dSJohannes Berg {
5565cf121c3SJohannes Berg 	if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
5579ae54c84SJohannes Berg 		return TX_CONTINUE;
558e2ebc74dSJohannes Berg 
5595cf121c3SJohannes Berg 	if (tx->flags & IEEE80211_TX_UNICAST)
560e2ebc74dSJohannes Berg 		return ieee80211_tx_h_unicast_ps_buf(tx);
561e2ebc74dSJohannes Berg 	else
562e2ebc74dSJohannes Berg 		return ieee80211_tx_h_multicast_ps_buf(tx);
563e2ebc74dSJohannes Berg }
564e2ebc74dSJohannes Berg 
565d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data * tx)566a621fa4dSJohannes Berg ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
567a621fa4dSJohannes Berg {
568a621fa4dSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
569a621fa4dSJohannes Berg 
570af61a165SJohannes Berg 	if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) {
571af61a165SJohannes Berg 		if (tx->sdata->control_port_no_encrypt)
572a621fa4dSJohannes Berg 			info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
573af61a165SJohannes Berg 		info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
5749c1c98a3SJouni Malinen 		info->flags |= IEEE80211_TX_CTL_USE_MINRATE;
575af61a165SJohannes Berg 	}
576a621fa4dSJohannes Berg 
577a621fa4dSJohannes Berg 	return TX_CONTINUE;
578a621fa4dSJohannes Berg }
579a621fa4dSJohannes Berg 
580ccdde7c7SJohannes Berg static struct ieee80211_key *
ieee80211_select_link_key(struct ieee80211_tx_data * tx)581ccdde7c7SJohannes Berg ieee80211_select_link_key(struct ieee80211_tx_data *tx)
582ccdde7c7SJohannes Berg {
583ccdde7c7SJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
584ccdde7c7SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
585ccdde7c7SJohannes Berg 	struct ieee80211_link_data *link;
586ccdde7c7SJohannes Berg 	unsigned int link_id;
587ccdde7c7SJohannes Berg 
588ccdde7c7SJohannes Berg 	link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
589ccdde7c7SJohannes Berg 	if (link_id == IEEE80211_LINK_UNSPECIFIED) {
590ccdde7c7SJohannes Berg 		link = &tx->sdata->deflink;
591ccdde7c7SJohannes Berg 	} else {
592ccdde7c7SJohannes Berg 		link = rcu_dereference(tx->sdata->link[link_id]);
593ccdde7c7SJohannes Berg 		if (!link)
594ccdde7c7SJohannes Berg 			return NULL;
595ccdde7c7SJohannes Berg 	}
596ccdde7c7SJohannes Berg 
5971d10575bSMukesh Sisodiya 	if (ieee80211_is_group_privacy_action(tx->skb))
598ccdde7c7SJohannes Berg 		return rcu_dereference(link->default_multicast_key);
5991d10575bSMukesh Sisodiya 	else if (ieee80211_is_mgmt(hdr->frame_control) &&
6001d10575bSMukesh Sisodiya 		 is_multicast_ether_addr(hdr->addr1) &&
6011d10575bSMukesh Sisodiya 		 ieee80211_is_robust_mgmt_frame(tx->skb))
6021d10575bSMukesh Sisodiya 		return rcu_dereference(link->default_mgmt_key);
6031d10575bSMukesh Sisodiya 	else if (is_multicast_ether_addr(hdr->addr1))
6041d10575bSMukesh Sisodiya 		return rcu_dereference(link->default_multicast_key);
605ccdde7c7SJohannes Berg 
606ccdde7c7SJohannes Berg 	return NULL;
607ccdde7c7SJohannes Berg }
608ccdde7c7SJohannes Berg 
609a621fa4dSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data * tx)6105cf121c3SJohannes Berg ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
611e2ebc74dSJohannes Berg {
61246e6de15SJohannes Berg 	struct ieee80211_key *key;
613e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
614358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
615d4e46a3dSJohannes Berg 
616a0761a30SJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
617e2ebc74dSJohannes Berg 		tx->key = NULL;
618a0761a30SJohannes Berg 		return TX_CONTINUE;
619a0761a30SJohannes Berg 	}
620a0761a30SJohannes Berg 
621a0761a30SJohannes Berg 	if (tx->sta &&
6222475b1ccSMax Stepanov 	    (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
623d4e46a3dSJohannes Berg 		tx->key = key;
624ccdde7c7SJohannes Berg 	else if ((key = ieee80211_select_link_key(tx)))
625f7e0104cSJohannes Berg 		tx->key = key;
626f7e0104cSJohannes Berg 	else if (!is_multicast_ether_addr(hdr->addr1) &&
627f7e0104cSJohannes Berg 		 (key = rcu_dereference(tx->sdata->default_unicast_key)))
628d4e46a3dSJohannes Berg 		tx->key = key;
629e8f4fb7cSJohannes Berg 	else
63046e6de15SJohannes Berg 		tx->key = NULL;
631e2ebc74dSJohannes Berg 
632e2ebc74dSJohannes Berg 	if (tx->key) {
633813d7669SJohannes Berg 		bool skip_hw = false;
634813d7669SJohannes Berg 
635011bfcc4SJohannes Berg 		/* TODO: add threshold stuff again */
636176e4f84SJohannes Berg 
63797359d12SJohannes Berg 		switch (tx->key->conf.cipher) {
63897359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP40:
63997359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP104:
64097359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_TKIP:
641358c8d9dSHarvey Harrison 			if (!ieee80211_is_data_present(hdr->frame_control))
642176e4f84SJohannes Berg 				tx->key = NULL;
643176e4f84SJohannes Berg 			break;
64497359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP:
6452b2ba0dbSJouni Malinen 		case WLAN_CIPHER_SUITE_CCMP_256:
64600b9cfa3SJouni Malinen 		case WLAN_CIPHER_SUITE_GCMP:
64700b9cfa3SJouni Malinen 		case WLAN_CIPHER_SUITE_GCMP_256:
648fb733336SJouni Malinen 			if (!ieee80211_is_data_present(hdr->frame_control) &&
649fb733336SJouni Malinen 			    !ieee80211_use_mfp(hdr->frame_control, tx->sta,
65046f6b060SMasashi Honma 					       tx->skb) &&
65146f6b060SMasashi Honma 			    !ieee80211_is_group_privacy_action(tx->skb))
652fb733336SJouni Malinen 				tx->key = NULL;
6533b43a187SKalle Valo 			else
654813d7669SJohannes Berg 				skip_hw = (tx->key->conf.flags &
655e548c49eSJohannes Berg 					   IEEE80211_KEY_FLAG_SW_MGMT_TX) &&
656813d7669SJohannes Berg 					ieee80211_is_mgmt(hdr->frame_control);
657fb733336SJouni Malinen 			break;
65897359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_AES_CMAC:
65956c52da2SJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
6608ade538bSJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
6618ade538bSJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
6623cfcf6acSJouni Malinen 			if (!ieee80211_is_mgmt(hdr->frame_control))
6633cfcf6acSJouni Malinen 				tx->key = NULL;
6643cfcf6acSJouni Malinen 			break;
665e2ebc74dSJohannes Berg 		}
666813d7669SJohannes Berg 
667e54faf29SJohannes Berg 		if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED &&
66861304336SWen Gong 			     !ieee80211_is_deauth(hdr->frame_control)) &&
66961304336SWen Gong 			     tx->skb->protocol != tx->sdata->control_port_protocol)
67095acac61SJohannes Berg 			return TX_DROP;
67195acac61SJohannes Berg 
672f12553ebSJohannes Berg 		if (!skip_hw && tx->key &&
673382b1655SJohannes Berg 		    tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
674813d7669SJohannes Berg 			info->control.hw_key = &tx->key->conf;
6752463ec86SFelix Fietkau 	} else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta &&
676a0761a30SJohannes Berg 		   test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) {
677a0761a30SJohannes Berg 		return TX_DROP;
678176e4f84SJohannes Berg 	}
679176e4f84SJohannes Berg 
6809ae54c84SJohannes Berg 	return TX_CONTINUE;
681e2ebc74dSJohannes Berg }
682e2ebc74dSJohannes Berg 
683d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data * tx)6845cf121c3SJohannes Berg ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
685e2ebc74dSJohannes Berg {
686e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
687e6a9854bSJohannes Berg 	struct ieee80211_hdr *hdr = (void *)tx->skb->data;
688e6a9854bSJohannes Berg 	struct ieee80211_supported_band *sband;
689a2c40249SShanyu Zhao 	u32 len;
690e6a9854bSJohannes Berg 	struct ieee80211_tx_rate_control txrc;
6910d528d85SFelix Fietkau 	struct ieee80211_sta_rates *ratetbl = NULL;
6923187ba0cSRyder Lee 	bool encap = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
693c2c98fdeSJohannes Berg 	bool assoc = false;
694e6a9854bSJohannes Berg 
695e6a9854bSJohannes Berg 	memset(&txrc, 0, sizeof(txrc));
6968318d78aSJohannes Berg 
6972d56577bSJohannes Berg 	sband = tx->local->hw.wiphy->bands[info->band];
698e2ebc74dSJohannes Berg 
699a2c40249SShanyu Zhao 	len = min_t(u32, tx->skb->len + FCS_LEN,
700b9a5f8caSJouni Malinen 			 tx->local->hw.wiphy->frag_threshold);
70158d4185eSJohannes Berg 
702e6a9854bSJohannes Berg 	/* set up the tx rate control struct we give the RC algo */
703005e472bSJohannes Berg 	txrc.hw = &tx->local->hw;
704e6a9854bSJohannes Berg 	txrc.sband = sband;
705e6a9854bSJohannes Berg 	txrc.bss_conf = &tx->sdata->vif.bss_conf;
706e6a9854bSJohannes Berg 	txrc.skb = tx->skb;
707e6a9854bSJohannes Berg 	txrc.reported_rate.idx = -1;
7080cfadb49SJohannes Berg 
709*d54455a3SPing-Ke Shih 	if (unlikely(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) {
7100cfadb49SJohannes Berg 		txrc.rate_idx_mask = ~0;
7110cfadb49SJohannes Berg 	} else {
7122d56577bSJohannes Berg 		txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
7132ffbe6d3SFelix Fietkau 
7142ffbe6d3SFelix Fietkau 		if (tx->sdata->rc_has_mcs_mask[info->band])
7152ffbe6d3SFelix Fietkau 			txrc.rate_idx_mcs_mask =
7162ffbe6d3SFelix Fietkau 				tx->sdata->rc_rateidx_mcs_mask[info->band];
7170cfadb49SJohannes Berg 	}
7182ffbe6d3SFelix Fietkau 
7198f0729b1SFelix Fietkau 	txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
7204bb62344SChun-Yeow Yeoh 		    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
7215765f9f6SBertold Van den Bergh 		    tx->sdata->vif.type == NL80211_IFTYPE_ADHOC ||
7225765f9f6SBertold Van den Bergh 		    tx->sdata->vif.type == NL80211_IFTYPE_OCB);
72358d4185eSJohannes Berg 
724e6a9854bSJohannes Berg 	/* set up RTS protection if desired */
725b9a5f8caSJouni Malinen 	if (len > tx->local->hw.wiphy->rts_threshold) {
7260d528d85SFelix Fietkau 		txrc.rts = true;
727e2ebc74dSJohannes Berg 	}
728e6a9854bSJohannes Berg 
7290d528d85SFelix Fietkau 	info->control.use_rts = txrc.rts;
730991fec09SFelix Fietkau 	info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot;
731991fec09SFelix Fietkau 
732e6a9854bSJohannes Berg 	/*
733e6a9854bSJohannes Berg 	 * Use short preamble if the BSS can handle it, but not for
734e6a9854bSJohannes Berg 	 * management frames unless we know the receiver can handle
735e6a9854bSJohannes Berg 	 * that -- the management frame might be to a station that
736e6a9854bSJohannes Berg 	 * just wants a probe response.
737e6a9854bSJohannes Berg 	 */
738e6a9854bSJohannes Berg 	if (tx->sdata->vif.bss_conf.use_short_preamble &&
7393187ba0cSRyder Lee 	    (ieee80211_is_tx_data(tx->skb) ||
740c2c98fdeSJohannes Berg 	     (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
7410d528d85SFelix Fietkau 		txrc.short_preamble = true;
7420d528d85SFelix Fietkau 
7430d528d85SFelix Fietkau 	info->control.short_preamble = txrc.short_preamble;
744e6a9854bSJohannes Berg 
745dfdfc2beSSven Eckelmann 	/* don't ask rate control when rate already injected via radiotap */
746dfdfc2beSSven Eckelmann 	if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
747dfdfc2beSSven Eckelmann 		return TX_CONTINUE;
748dfdfc2beSSven Eckelmann 
749c2c98fdeSJohannes Berg 	if (tx->sta)
750c2c98fdeSJohannes Berg 		assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
751e6a9854bSJohannes Berg 
752b770b43eSLuis R. Rodriguez 	/*
753b770b43eSLuis R. Rodriguez 	 * Lets not bother rate control if we're associated and cannot
754b770b43eSLuis R. Rodriguez 	 * talk to the sta. This should not happen.
755b770b43eSLuis R. Rodriguez 	 */
756c2c98fdeSJohannes Berg 	if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
757b770b43eSLuis R. Rodriguez 		 !rate_usable_index_exists(sband, &tx->sta->sta),
758b770b43eSLuis R. Rodriguez 		 "%s: Dropped data frame as no usable bitrate found while "
759b770b43eSLuis R. Rodriguez 		 "scanning and associated. Target station: "
760b770b43eSLuis R. Rodriguez 		 "%pM on %d GHz band\n",
7613187ba0cSRyder Lee 		 tx->sdata->name,
7623187ba0cSRyder Lee 		 encap ? ((struct ethhdr *)hdr)->h_dest : hdr->addr1,
7632d56577bSJohannes Berg 		 info->band ? 5 : 2))
764b770b43eSLuis R. Rodriguez 		return TX_DROP;
765b770b43eSLuis R. Rodriguez 
766b770b43eSLuis R. Rodriguez 	/*
767b770b43eSLuis R. Rodriguez 	 * If we're associated with the sta at this point we know we can at
768b770b43eSLuis R. Rodriguez 	 * least send the frame at the lowest bit rate.
769b770b43eSLuis R. Rodriguez 	 */
770e6a9854bSJohannes Berg 	rate_control_get_rate(tx->sdata, tx->sta, &txrc);
771e6a9854bSJohannes Berg 
7720d528d85SFelix Fietkau 	if (tx->sta && !info->control.skip_table)
7730d528d85SFelix Fietkau 		ratetbl = rcu_dereference(tx->sta->sta.rates);
7740d528d85SFelix Fietkau 
7750d528d85SFelix Fietkau 	if (unlikely(info->control.rates[0].idx < 0)) {
7760d528d85SFelix Fietkau 		if (ratetbl) {
7770d528d85SFelix Fietkau 			struct ieee80211_tx_rate rate = {
7780d528d85SFelix Fietkau 				.idx = ratetbl->rate[0].idx,
7790d528d85SFelix Fietkau 				.flags = ratetbl->rate[0].flags,
7800d528d85SFelix Fietkau 				.count = ratetbl->rate[0].count
7810d528d85SFelix Fietkau 			};
7820d528d85SFelix Fietkau 
7830d528d85SFelix Fietkau 			if (ratetbl->rate[0].idx < 0)
784e6a9854bSJohannes Berg 				return TX_DROP;
785e6a9854bSJohannes Berg 
7860d528d85SFelix Fietkau 			tx->rate = rate;
7870d528d85SFelix Fietkau 		} else {
7880d528d85SFelix Fietkau 			return TX_DROP;
7890d528d85SFelix Fietkau 		}
7900d528d85SFelix Fietkau 	} else {
7910d528d85SFelix Fietkau 		tx->rate = info->control.rates[0];
7920d528d85SFelix Fietkau 	}
7930d528d85SFelix Fietkau 
794c1ce5a74SHelmut Schaa 	if (txrc.reported_rate.idx < 0) {
7950d528d85SFelix Fietkau 		txrc.reported_rate = tx->rate;
7963187ba0cSRyder Lee 		if (tx->sta && ieee80211_is_tx_data(tx->skb))
797046d2e7cSSriram R 			tx->sta->deflink.tx_stats.last_rate = txrc.reported_rate;
798c1ce5a74SHelmut Schaa 	} else if (tx->sta)
799046d2e7cSSriram R 		tx->sta->deflink.tx_stats.last_rate = txrc.reported_rate;
800e6a9854bSJohannes Berg 
8010d528d85SFelix Fietkau 	if (ratetbl)
8020d528d85SFelix Fietkau 		return TX_CONTINUE;
8030d528d85SFelix Fietkau 
804e6a9854bSJohannes Berg 	if (unlikely(!info->control.rates[0].count))
805e6a9854bSJohannes Berg 		info->control.rates[0].count = 1;
806e6a9854bSJohannes Berg 
8079955151dSGábor Stefanik 	if (WARN_ON_ONCE((info->control.rates[0].count > 1) &&
8089955151dSGábor Stefanik 			 (info->flags & IEEE80211_TX_CTL_NO_ACK)))
8099955151dSGábor Stefanik 		info->control.rates[0].count = 1;
8109955151dSGábor Stefanik 
8119ae54c84SJohannes Berg 	return TX_CONTINUE;
812e2ebc74dSJohannes Berg }
813e2ebc74dSJohannes Berg 
ieee80211_tx_next_seq(struct sta_info * sta,int tid)814ba8c3d6fSFelix Fietkau static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
815ba8c3d6fSFelix Fietkau {
816ba8c3d6fSFelix Fietkau 	u16 *seq = &sta->tid_seq[tid];
817ba8c3d6fSFelix Fietkau 	__le16 ret = cpu_to_le16(*seq);
818ba8c3d6fSFelix Fietkau 
819ba8c3d6fSFelix Fietkau 	/* Increase the sequence number. */
820ba8c3d6fSFelix Fietkau 	*seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
821ba8c3d6fSFelix Fietkau 
822ba8c3d6fSFelix Fietkau 	return ret;
823ba8c3d6fSFelix Fietkau }
824ba8c3d6fSFelix Fietkau 
825d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data * tx)826f591fa5dSJohannes Berg ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
827f591fa5dSJohannes Berg {
828f591fa5dSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
829f591fa5dSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
830f591fa5dSJohannes Berg 	int tid;
831f591fa5dSJohannes Berg 
83225d834e1SJohannes Berg 	/*
83325d834e1SJohannes Berg 	 * Packet injection may want to control the sequence
83425d834e1SJohannes Berg 	 * number, if we have no matching interface then we
83525d834e1SJohannes Berg 	 * neither assign one ourselves nor ask the driver to.
83625d834e1SJohannes Berg 	 */
8375061b0c2SJohannes Berg 	if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
83825d834e1SJohannes Berg 		return TX_CONTINUE;
83925d834e1SJohannes Berg 
840f591fa5dSJohannes Berg 	if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
841f591fa5dSJohannes Berg 		return TX_CONTINUE;
842f591fa5dSJohannes Berg 
843f591fa5dSJohannes Berg 	if (ieee80211_hdrlen(hdr->frame_control) < 24)
844f591fa5dSJohannes Berg 		return TX_CONTINUE;
845f591fa5dSJohannes Berg 
84649a59543SJohannes Berg 	if (ieee80211_is_qos_nullfunc(hdr->frame_control))
84749a59543SJohannes Berg 		return TX_CONTINUE;
84849a59543SJohannes Berg 
84929c3e95fSMathy Vanhoef 	if (info->control.flags & IEEE80211_TX_CTRL_NO_SEQNO)
85029c3e95fSMathy Vanhoef 		return TX_CONTINUE;
85129c3e95fSMathy Vanhoef 
852963d0e8dSJohannes Berg 	/* SNS11 from 802.11be 10.3.2.14 */
853963d0e8dSJohannes Berg 	if (unlikely(is_multicast_ether_addr(hdr->addr1) &&
854f1871abdSIlan Peer 		     ieee80211_vif_is_mld(info->control.vif) &&
855963d0e8dSJohannes Berg 		     info->control.vif->type == NL80211_IFTYPE_AP)) {
856963d0e8dSJohannes Berg 		if (info->control.flags & IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX)
857963d0e8dSJohannes Berg 			tx->sdata->mld_mcast_seq += 0x10;
858963d0e8dSJohannes Berg 		hdr->seq_ctrl = cpu_to_le16(tx->sdata->mld_mcast_seq);
859963d0e8dSJohannes Berg 		return TX_CONTINUE;
860963d0e8dSJohannes Berg 	}
861963d0e8dSJohannes Berg 
86294778280SJohannes Berg 	/*
86394778280SJohannes Berg 	 * Anything but QoS data that has a sequence number field
86494778280SJohannes Berg 	 * (is long enough) gets a sequence number from the global
865c4c205f3SBob Copeland 	 * counter.  QoS data frames with a multicast destination
866c4c205f3SBob Copeland 	 * also use the global counter (802.11-2012 9.3.2.10).
86794778280SJohannes Berg 	 */
868c4c205f3SBob Copeland 	if (!ieee80211_is_data_qos(hdr->frame_control) ||
869c4c205f3SBob Copeland 	    is_multicast_ether_addr(hdr->addr1)) {
87094778280SJohannes Berg 		/* driver should assign sequence number */
871f591fa5dSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
87294778280SJohannes Berg 		/* for pure STA mode without beacons, we can do it */
87394778280SJohannes Berg 		hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
87494778280SJohannes Berg 		tx->sdata->sequence_number += 0x10;
87579c892b8SJohannes Berg 		if (tx->sta)
876046d2e7cSSriram R 			tx->sta->deflink.tx_stats.msdu[IEEE80211_NUM_TIDS]++;
877f591fa5dSJohannes Berg 		return TX_CONTINUE;
878f591fa5dSJohannes Berg 	}
879f591fa5dSJohannes Berg 
880f591fa5dSJohannes Berg 	/*
881f591fa5dSJohannes Berg 	 * This should be true for injected/management frames only, for
882f591fa5dSJohannes Berg 	 * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ
883f591fa5dSJohannes Berg 	 * above since they are not QoS-data frames.
884f591fa5dSJohannes Berg 	 */
885f591fa5dSJohannes Berg 	if (!tx->sta)
886f591fa5dSJohannes Berg 		return TX_CONTINUE;
887f591fa5dSJohannes Berg 
888f591fa5dSJohannes Berg 	/* include per-STA, per-TID sequence counter */
889a1f2ba04SSara Sharon 	tid = ieee80211_get_tid(hdr);
890046d2e7cSSriram R 	tx->sta->deflink.tx_stats.msdu[tid]++;
891f591fa5dSJohannes Berg 
892ba8c3d6fSFelix Fietkau 	hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
893f591fa5dSJohannes Berg 
894f591fa5dSJohannes Berg 	return TX_CONTINUE;
895f591fa5dSJohannes Berg }
896f591fa5dSJohannes Berg 
ieee80211_fragment(struct ieee80211_tx_data * tx,struct sk_buff * skb,int hdrlen,int frag_threshold)897252b86c4SJohannes Berg static int ieee80211_fragment(struct ieee80211_tx_data *tx,
8982de8e0d9SJohannes Berg 			      struct sk_buff *skb, int hdrlen,
8992de8e0d9SJohannes Berg 			      int frag_threshold)
9002de8e0d9SJohannes Berg {
901252b86c4SJohannes Berg 	struct ieee80211_local *local = tx->local;
902a1a3fcecSJohannes Berg 	struct ieee80211_tx_info *info;
903252b86c4SJohannes Berg 	struct sk_buff *tmp;
9042de8e0d9SJohannes Berg 	int per_fragm = frag_threshold - hdrlen - FCS_LEN;
9052de8e0d9SJohannes Berg 	int pos = hdrlen + per_fragm;
9062de8e0d9SJohannes Berg 	int rem = skb->len - hdrlen - per_fragm;
9072de8e0d9SJohannes Berg 
9082de8e0d9SJohannes Berg 	if (WARN_ON(rem < 0))
9092de8e0d9SJohannes Berg 		return -EINVAL;
9102de8e0d9SJohannes Berg 
911252b86c4SJohannes Berg 	/* first fragment was already added to queue by caller */
912252b86c4SJohannes Berg 
9132de8e0d9SJohannes Berg 	while (rem) {
9142de8e0d9SJohannes Berg 		int fraglen = per_fragm;
9152de8e0d9SJohannes Berg 
9162de8e0d9SJohannes Berg 		if (fraglen > rem)
9172de8e0d9SJohannes Berg 			fraglen = rem;
9182de8e0d9SJohannes Berg 		rem -= fraglen;
9192de8e0d9SJohannes Berg 		tmp = dev_alloc_skb(local->tx_headroom +
9202de8e0d9SJohannes Berg 				    frag_threshold +
92123a5f0afSJohannes Berg 				    IEEE80211_ENCRYPT_HEADROOM +
9222de8e0d9SJohannes Berg 				    IEEE80211_ENCRYPT_TAILROOM);
9232de8e0d9SJohannes Berg 		if (!tmp)
9242de8e0d9SJohannes Berg 			return -ENOMEM;
925252b86c4SJohannes Berg 
926252b86c4SJohannes Berg 		__skb_queue_tail(&tx->skbs, tmp);
927252b86c4SJohannes Berg 
9282475b1ccSMax Stepanov 		skb_reserve(tmp,
92923a5f0afSJohannes Berg 			    local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
9302475b1ccSMax Stepanov 
9312de8e0d9SJohannes Berg 		/* copy control information */
9322de8e0d9SJohannes Berg 		memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
933a1a3fcecSJohannes Berg 
934a1a3fcecSJohannes Berg 		info = IEEE80211_SKB_CB(tmp);
935a1a3fcecSJohannes Berg 		info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
936a1a3fcecSJohannes Berg 				 IEEE80211_TX_CTL_FIRST_FRAGMENT);
937a1a3fcecSJohannes Berg 
938a1a3fcecSJohannes Berg 		if (rem)
939a1a3fcecSJohannes Berg 			info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
940a1a3fcecSJohannes Berg 
9412de8e0d9SJohannes Berg 		skb_copy_queue_mapping(tmp, skb);
9422de8e0d9SJohannes Berg 		tmp->priority = skb->priority;
9432de8e0d9SJohannes Berg 		tmp->dev = skb->dev;
9442de8e0d9SJohannes Berg 
9452de8e0d9SJohannes Berg 		/* copy header and data */
94659ae1d12SJohannes Berg 		skb_put_data(tmp, skb->data, hdrlen);
94759ae1d12SJohannes Berg 		skb_put_data(tmp, skb->data + pos, fraglen);
9482de8e0d9SJohannes Berg 
9492de8e0d9SJohannes Berg 		pos += fraglen;
9502de8e0d9SJohannes Berg 	}
9512de8e0d9SJohannes Berg 
952252b86c4SJohannes Berg 	/* adjust first fragment's length */
953338f977fSJohannes Berg 	skb_trim(skb, hdrlen + per_fragm);
9542de8e0d9SJohannes Berg 	return 0;
9552de8e0d9SJohannes Berg }
9562de8e0d9SJohannes Berg 
957f591fa5dSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_fragment(struct ieee80211_tx_data * tx)958e2454948SJohannes Berg ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
959e2454948SJohannes Berg {
9602de8e0d9SJohannes Berg 	struct sk_buff *skb = tx->skb;
9612de8e0d9SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
9622de8e0d9SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)skb->data;
963b9a5f8caSJouni Malinen 	int frag_threshold = tx->local->hw.wiphy->frag_threshold;
9642de8e0d9SJohannes Berg 	int hdrlen;
9652de8e0d9SJohannes Berg 	int fragnum;
966e2454948SJohannes Berg 
967252b86c4SJohannes Berg 	/* no matter what happens, tx->skb moves to tx->skbs */
968252b86c4SJohannes Berg 	__skb_queue_tail(&tx->skbs, skb);
969252b86c4SJohannes Berg 	tx->skb = NULL;
970252b86c4SJohannes Berg 
971a26eb27aSJohannes Berg 	if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
972a26eb27aSJohannes Berg 		return TX_CONTINUE;
973a26eb27aSJohannes Berg 
974f3fe4e93SSara Sharon 	if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG))
975e2454948SJohannes Berg 		return TX_CONTINUE;
976e2454948SJohannes Berg 
977eefce91aSJohannes Berg 	/*
978eefce91aSJohannes Berg 	 * Warn when submitting a fragmented A-MPDU frame and drop it.
9793b8d81e0SJohannes Berg 	 * This scenario is handled in ieee80211_tx_prepare but extra
9808d5e0d58SRon Rindjunsky 	 * caution taken here as fragmented ampdu may cause Tx stop.
981eefce91aSJohannes Berg 	 */
9828b30b1feSSujith 	if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
983eefce91aSJohannes Berg 		return TX_DROP;
984eefce91aSJohannes Berg 
985065e9605SHarvey Harrison 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
986e2454948SJohannes Berg 
987a26eb27aSJohannes Berg 	/* internal error, why isn't DONTFRAG set? */
9888ccd8f21SJohannes Berg 	if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
9892de8e0d9SJohannes Berg 		return TX_DROP;
990e2454948SJohannes Berg 
9912de8e0d9SJohannes Berg 	/*
9922de8e0d9SJohannes Berg 	 * Now fragment the frame. This will allocate all the fragments and
9932de8e0d9SJohannes Berg 	 * chain them (using skb as the first fragment) to skb->next.
9942de8e0d9SJohannes Berg 	 * During transmission, we will remove the successfully transmitted
9952de8e0d9SJohannes Berg 	 * fragments from this list. When the low-level driver rejects one
9962de8e0d9SJohannes Berg 	 * of the fragments then we will simply pretend to accept the skb
9972de8e0d9SJohannes Berg 	 * but store it away as pending.
9982de8e0d9SJohannes Berg 	 */
999252b86c4SJohannes Berg 	if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold))
10002de8e0d9SJohannes Berg 		return TX_DROP;
1001e2454948SJohannes Berg 
10022de8e0d9SJohannes Berg 	/* update duration/seq/flags of fragments */
10032de8e0d9SJohannes Berg 	fragnum = 0;
1004252b86c4SJohannes Berg 
1005252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
10062de8e0d9SJohannes Berg 		const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
1007e2454948SJohannes Berg 
10082de8e0d9SJohannes Berg 		hdr = (void *)skb->data;
10092de8e0d9SJohannes Berg 		info = IEEE80211_SKB_CB(skb);
1010e6a9854bSJohannes Berg 
1011252b86c4SJohannes Berg 		if (!skb_queue_is_last(&tx->skbs, skb)) {
10122de8e0d9SJohannes Berg 			hdr->frame_control |= morefrags;
1013e6a9854bSJohannes Berg 			/*
1014e6a9854bSJohannes Berg 			 * No multi-rate retries for fragmented frames, that
1015e6a9854bSJohannes Berg 			 * would completely throw off the NAV at other STAs.
1016e6a9854bSJohannes Berg 			 */
1017e6a9854bSJohannes Berg 			info->control.rates[1].idx = -1;
1018e6a9854bSJohannes Berg 			info->control.rates[2].idx = -1;
1019e6a9854bSJohannes Berg 			info->control.rates[3].idx = -1;
1020e3e1a0bcSThomas Huehn 			BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4);
1021e6a9854bSJohannes Berg 			info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
10222de8e0d9SJohannes Berg 		} else {
10232de8e0d9SJohannes Berg 			hdr->frame_control &= ~morefrags;
1024e6a9854bSJohannes Berg 		}
10252de8e0d9SJohannes Berg 		hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
10262de8e0d9SJohannes Berg 		fragnum++;
1027252b86c4SJohannes Berg 	}
1028e2454948SJohannes Berg 
1029e2454948SJohannes Berg 	return TX_CONTINUE;
1030e2454948SJohannes Berg }
1031e2454948SJohannes Berg 
1032d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_stats(struct ieee80211_tx_data * tx)1033feff1f2fSJohannes Berg ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
1034feff1f2fSJohannes Berg {
1035252b86c4SJohannes Berg 	struct sk_buff *skb;
1036560d2682SJohannes Berg 	int ac = -1;
1037feff1f2fSJohannes Berg 
1038feff1f2fSJohannes Berg 	if (!tx->sta)
1039feff1f2fSJohannes Berg 		return TX_CONTINUE;
1040feff1f2fSJohannes Berg 
1041252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
1042560d2682SJohannes Berg 		ac = skb_get_queue_mapping(skb);
1043046d2e7cSSriram R 		tx->sta->deflink.tx_stats.bytes[ac] += skb->len;
1044252b86c4SJohannes Berg 	}
1045560d2682SJohannes Berg 	if (ac >= 0)
1046046d2e7cSSriram R 		tx->sta->deflink.tx_stats.packets[ac]++;
1047feff1f2fSJohannes Berg 
1048feff1f2fSJohannes Berg 	return TX_CONTINUE;
1049feff1f2fSJohannes Berg }
1050feff1f2fSJohannes Berg 
1051feff1f2fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_encrypt(struct ieee80211_tx_data * tx)1052e2454948SJohannes Berg ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1053e2454948SJohannes Berg {
1054e2454948SJohannes Berg 	if (!tx->key)
1055e2454948SJohannes Berg 		return TX_CONTINUE;
1056e2454948SJohannes Berg 
105797359d12SJohannes Berg 	switch (tx->key->conf.cipher) {
105897359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_WEP40:
105997359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_WEP104:
1060e2454948SJohannes Berg 		return ieee80211_crypto_wep_encrypt(tx);
106197359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_TKIP:
1062e2454948SJohannes Berg 		return ieee80211_crypto_tkip_encrypt(tx);
106397359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_CCMP:
10642b2ba0dbSJouni Malinen 		return ieee80211_crypto_ccmp_encrypt(
10652b2ba0dbSJouni Malinen 			tx, IEEE80211_CCMP_MIC_LEN);
10662b2ba0dbSJouni Malinen 	case WLAN_CIPHER_SUITE_CCMP_256:
10672b2ba0dbSJouni Malinen 		return ieee80211_crypto_ccmp_encrypt(
10682b2ba0dbSJouni Malinen 			tx, IEEE80211_CCMP_256_MIC_LEN);
106997359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_AES_CMAC:
10703cfcf6acSJouni Malinen 		return ieee80211_crypto_aes_cmac_encrypt(tx);
107156c52da2SJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
107256c52da2SJouni Malinen 		return ieee80211_crypto_aes_cmac_256_encrypt(tx);
10738ade538bSJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
10748ade538bSJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
10758ade538bSJouni Malinen 		return ieee80211_crypto_aes_gmac_encrypt(tx);
107600b9cfa3SJouni Malinen 	case WLAN_CIPHER_SUITE_GCMP:
107700b9cfa3SJouni Malinen 	case WLAN_CIPHER_SUITE_GCMP_256:
107800b9cfa3SJouni Malinen 		return ieee80211_crypto_gcmp_encrypt(tx);
1079e2454948SJohannes Berg 	}
1080e2454948SJohannes Berg 
1081e2454948SJohannes Berg 	return TX_DROP;
1082e2454948SJohannes Berg }
1083e2454948SJohannes Berg 
1084d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data * tx)108503f93c3dSJohannes Berg ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
108603f93c3dSJohannes Berg {
1087252b86c4SJohannes Berg 	struct sk_buff *skb;
10882de8e0d9SJohannes Berg 	struct ieee80211_hdr *hdr;
10892de8e0d9SJohannes Berg 	int next_len;
10902de8e0d9SJohannes Berg 	bool group_addr;
109103f93c3dSJohannes Berg 
1092252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
10932de8e0d9SJohannes Berg 		hdr = (void *) skb->data;
10947e0aae47SJouni Malinen 		if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
10957e0aae47SJouni Malinen 			break; /* must not overwrite AID */
1096252b86c4SJohannes Berg 		if (!skb_queue_is_last(&tx->skbs, skb)) {
1097252b86c4SJohannes Berg 			struct sk_buff *next = skb_queue_next(&tx->skbs, skb);
1098252b86c4SJohannes Berg 			next_len = next->len;
1099252b86c4SJohannes Berg 		} else
1100252b86c4SJohannes Berg 			next_len = 0;
11012de8e0d9SJohannes Berg 		group_addr = is_multicast_ether_addr(hdr->addr1);
110203f93c3dSJohannes Berg 
11032de8e0d9SJohannes Berg 		hdr->duration_id =
1104252b86c4SJohannes Berg 			ieee80211_duration(tx, skb, group_addr, next_len);
1105252b86c4SJohannes Berg 	}
110603f93c3dSJohannes Berg 
110703f93c3dSJohannes Berg 	return TX_CONTINUE;
110803f93c3dSJohannes Berg }
110903f93c3dSJohannes Berg 
1110e2ebc74dSJohannes Berg /* actual transmit path */
1111e2ebc74dSJohannes Berg 
ieee80211_tx_prep_agg(struct ieee80211_tx_data * tx,struct sk_buff * skb,struct ieee80211_tx_info * info,struct tid_ampdu_tx * tid_tx,int tid)1112a622ab72SJohannes Berg static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
1113a622ab72SJohannes Berg 				  struct sk_buff *skb,
1114a622ab72SJohannes Berg 				  struct ieee80211_tx_info *info,
1115a622ab72SJohannes Berg 				  struct tid_ampdu_tx *tid_tx,
1116a622ab72SJohannes Berg 				  int tid)
1117a622ab72SJohannes Berg {
1118a622ab72SJohannes Berg 	bool queued = false;
1119285fa695SNikolay Martynov 	bool reset_agg_timer = false;
1120aa454580SHelmut Schaa 	struct sk_buff *purge_skb = NULL;
1121a622ab72SJohannes Berg 
1122a622ab72SJohannes Berg 	if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
1123285fa695SNikolay Martynov 		reset_agg_timer = true;
11240ab33703SJohannes Berg 	} else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
11250ab33703SJohannes Berg 		/*
11260ab33703SJohannes Berg 		 * nothing -- this aggregation session is being started
11270ab33703SJohannes Berg 		 * but that might still fail with the driver
11280ab33703SJohannes Berg 		 */
1129ba8c3d6fSFelix Fietkau 	} else if (!tx->sta->sta.txq[tid]) {
1130a622ab72SJohannes Berg 		spin_lock(&tx->sta->lock);
1131a622ab72SJohannes Berg 		/*
1132a622ab72SJohannes Berg 		 * Need to re-check now, because we may get here
1133a622ab72SJohannes Berg 		 *
1134a622ab72SJohannes Berg 		 *  1) in the window during which the setup is actually
1135a622ab72SJohannes Berg 		 *     already done, but not marked yet because not all
1136a622ab72SJohannes Berg 		 *     packets are spliced over to the driver pending
1137a622ab72SJohannes Berg 		 *     queue yet -- if this happened we acquire the lock
1138a622ab72SJohannes Berg 		 *     either before or after the splice happens, but
1139a622ab72SJohannes Berg 		 *     need to recheck which of these cases happened.
1140a622ab72SJohannes Berg 		 *
1141a622ab72SJohannes Berg 		 *  2) during session teardown, if the OPERATIONAL bit
1142a622ab72SJohannes Berg 		 *     was cleared due to the teardown but the pointer
1143a622ab72SJohannes Berg 		 *     hasn't been assigned NULL yet (or we loaded it
1144a622ab72SJohannes Berg 		 *     before it was assigned) -- in this case it may
1145a622ab72SJohannes Berg 		 *     now be NULL which means we should just let the
1146a622ab72SJohannes Berg 		 *     packet pass through because splicing the frames
1147a622ab72SJohannes Berg 		 *     back is already done.
1148a622ab72SJohannes Berg 		 */
114940b275b6SJohannes Berg 		tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid);
1150a622ab72SJohannes Berg 
1151a622ab72SJohannes Berg 		if (!tid_tx) {
1152a622ab72SJohannes Berg 			/* do nothing, let packet pass through */
1153a622ab72SJohannes Berg 		} else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
1154285fa695SNikolay Martynov 			reset_agg_timer = true;
1155a622ab72SJohannes Berg 		} else {
1156a622ab72SJohannes Berg 			queued = true;
1157f6d4671aSEmmanuel Grumbach 			if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) {
1158f6d4671aSEmmanuel Grumbach 				clear_sta_flag(tx->sta, WLAN_STA_SP);
1159f6d4671aSEmmanuel Grumbach 				ps_dbg(tx->sta->sdata,
1160f6d4671aSEmmanuel Grumbach 				       "STA %pM aid %d: SP frame queued, close the SP w/o telling the peer\n",
1161f6d4671aSEmmanuel Grumbach 				       tx->sta->sta.addr, tx->sta->sta.aid);
1162f6d4671aSEmmanuel Grumbach 			}
1163a622ab72SJohannes Berg 			info->control.vif = &tx->sdata->vif;
1164cc20ff2cSFelix Fietkau 			info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
1165facde7f3SEmmanuel Grumbach 			info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
1166a622ab72SJohannes Berg 			__skb_queue_tail(&tid_tx->pending, skb);
1167aa454580SHelmut Schaa 			if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
1168aa454580SHelmut Schaa 				purge_skb = __skb_dequeue(&tid_tx->pending);
1169a622ab72SJohannes Berg 		}
1170a622ab72SJohannes Berg 		spin_unlock(&tx->sta->lock);
1171aa454580SHelmut Schaa 
1172aa454580SHelmut Schaa 		if (purge_skb)
1173c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&tx->local->hw, purge_skb);
1174a622ab72SJohannes Berg 	}
1175a622ab72SJohannes Berg 
1176285fa695SNikolay Martynov 	/* reset session timer */
1177914eac24SSara Sharon 	if (reset_agg_timer)
117812d3952fSFelix Fietkau 		tid_tx->last_tx = jiffies;
1179285fa695SNikolay Martynov 
1180a622ab72SJohannes Berg 	return queued;
1181a622ab72SJohannes Berg }
1182a622ab72SJohannes Berg 
ieee80211_aggr_check(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct sk_buff * skb)11838b0f5cb6SFelix Fietkau void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
11848b0f5cb6SFelix Fietkau 			  struct sta_info *sta, struct sk_buff *skb)
11851a791550SFelix Fietkau {
11861a791550SFelix Fietkau 	struct rate_control_ref *ref = sdata->local->rate_ctrl;
11871a791550SFelix Fietkau 	u16 tid;
11881a791550SFelix Fietkau 
11891a791550SFelix Fietkau 	if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
11901a791550SFelix Fietkau 		return;
11911a791550SFelix Fietkau 
1192046d2e7cSSriram R 	if (!sta || !sta->sta.deflink.ht_cap.ht_supported ||
11931a791550SFelix Fietkau 	    !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
11941a791550SFelix Fietkau 	    skb->protocol == sdata->control_port_protocol)
11951a791550SFelix Fietkau 		return;
11961a791550SFelix Fietkau 
11971a791550SFelix Fietkau 	tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
11981a791550SFelix Fietkau 	if (likely(sta->ampdu_mlme.tid_tx[tid]))
11991a791550SFelix Fietkau 		return;
12001a791550SFelix Fietkau 
12011a791550SFelix Fietkau 	ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
12021a791550SFelix Fietkau }
12031a791550SFelix Fietkau 
120458d4185eSJohannes Berg /*
120558d4185eSJohannes Berg  * initialises @tx
12067c10770fSJohannes Berg  * pass %NULL for the station if unknown, a valid pointer if known
12077c10770fSJohannes Berg  * or an ERR_PTR() if the station is known not to exist
120858d4185eSJohannes Berg  */
12099ae54c84SJohannes Berg static ieee80211_tx_result
ieee80211_tx_prepare(struct ieee80211_sub_if_data * sdata,struct ieee80211_tx_data * tx,struct sta_info * sta,struct sk_buff * skb)12103b8d81e0SJohannes Berg ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
12113b8d81e0SJohannes Berg 		     struct ieee80211_tx_data *tx,
12127c10770fSJohannes Berg 		     struct sta_info *sta, struct sk_buff *skb)
1213e2ebc74dSJohannes Berg {
12143b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
121558d4185eSJohannes Berg 	struct ieee80211_hdr *hdr;
1216e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
12171a791550SFelix Fietkau 	bool aggr_check = false;
121868f2b517SJohannes Berg 	int tid;
1219e2ebc74dSJohannes Berg 
1220e2ebc74dSJohannes Berg 	memset(tx, 0, sizeof(*tx));
1221e2ebc74dSJohannes Berg 	tx->skb = skb;
1222e2ebc74dSJohannes Berg 	tx->local = local;
12233b8d81e0SJohannes Berg 	tx->sdata = sdata;
1224252b86c4SJohannes Berg 	__skb_queue_head_init(&tx->skbs);
1225e2ebc74dSJohannes Berg 
1226cd8ffc80SJohannes Berg 	/*
1227cd8ffc80SJohannes Berg 	 * If this flag is set to true anywhere, and we get here,
1228cd8ffc80SJohannes Berg 	 * we are doing the needed processing, so remove the flag
1229cd8ffc80SJohannes Berg 	 * now.
1230cd8ffc80SJohannes Berg 	 */
1231cc20ff2cSFelix Fietkau 	info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
1232cd8ffc80SJohannes Berg 
123358d4185eSJohannes Berg 	hdr = (struct ieee80211_hdr *) skb->data;
123458d4185eSJohannes Berg 
12357c10770fSJohannes Berg 	if (likely(sta)) {
12367c10770fSJohannes Berg 		if (!IS_ERR(sta))
12377c10770fSJohannes Berg 			tx->sta = sta;
12387c10770fSJohannes Berg 	} else {
12393f0e0b22SFelix Fietkau 		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
1240f14543eeSFelix Fietkau 			tx->sta = rcu_dereference(sdata->u.vlan.sta);
12417c10770fSJohannes Berg 			if (!tx->sta && sdata->wdev.use_4addr)
12423f0e0b22SFelix Fietkau 				return TX_DROP;
124310cb8e61SMarkus Theil 		} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
1244b4d57adbSFelix Fietkau 			tx->sta = sta_info_get_bss(sdata, hdr->addr1);
12453f0e0b22SFelix Fietkau 		}
12461a791550SFelix Fietkau 		if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) {
1247abe60632SJohannes Berg 			tx->sta = sta_info_get(sdata, hdr->addr1);
12481a791550SFelix Fietkau 			aggr_check = true;
12491a791550SFelix Fietkau 		}
12507c10770fSJohannes Berg 	}
125158d4185eSJohannes Berg 
1252cd8ffc80SJohannes Berg 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
125349a59543SJohannes Berg 	    !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
125430686bf7SJohannes Berg 	    ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) &&
125530686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW)) {
1256cd8ffc80SJohannes Berg 		struct tid_ampdu_tx *tid_tx;
1257cd8ffc80SJohannes Berg 
1258a1f2ba04SSara Sharon 		tid = ieee80211_get_tid(hdr);
1259a622ab72SJohannes Berg 		tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
12601a791550SFelix Fietkau 		if (!tid_tx && aggr_check) {
12611a791550SFelix Fietkau 			ieee80211_aggr_check(sdata, tx->sta, skb);
12621a791550SFelix Fietkau 			tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
12631a791550SFelix Fietkau 		}
12641a791550SFelix Fietkau 
1265a622ab72SJohannes Berg 		if (tid_tx) {
1266a622ab72SJohannes Berg 			bool queued;
1267a622ab72SJohannes Berg 
1268a622ab72SJohannes Berg 			queued = ieee80211_tx_prep_agg(tx, skb, info,
1269a622ab72SJohannes Berg 						       tid_tx, tid);
1270cd8ffc80SJohannes Berg 
1271cd8ffc80SJohannes Berg 			if (unlikely(queued))
1272cd8ffc80SJohannes Berg 				return TX_QUEUED;
12738b30b1feSSujith 		}
1274a622ab72SJohannes Berg 	}
12758b30b1feSSujith 
1276badffb72SJiri Slaby 	if (is_multicast_ether_addr(hdr->addr1)) {
12775cf121c3SJohannes Berg 		tx->flags &= ~IEEE80211_TX_UNICAST;
1278e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_NO_ACK;
12796fd67e93SSimon Wunderlich 	} else
12805cf121c3SJohannes Berg 		tx->flags |= IEEE80211_TX_UNICAST;
128158d4185eSJohannes Berg 
1282a26eb27aSJohannes Berg 	if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) {
1283a26eb27aSJohannes Berg 		if (!(tx->flags & IEEE80211_TX_UNICAST) ||
1284a26eb27aSJohannes Berg 		    skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold ||
1285a26eb27aSJohannes Berg 		    info->flags & IEEE80211_TX_CTL_AMPDU)
1286a26eb27aSJohannes Berg 			info->flags |= IEEE80211_TX_CTL_DONTFRAG;
128758d4185eSJohannes Berg 	}
128858d4185eSJohannes Berg 
1289e2ebc74dSJohannes Berg 	if (!tx->sta)
1290e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1291f7418bc1SFelix Fietkau 	else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
1292e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1293f7418bc1SFelix Fietkau 		ieee80211_check_fast_xmit(tx->sta);
1294f7418bc1SFelix Fietkau 	}
129558d4185eSJohannes Berg 
1296e039fa4aSJohannes Berg 	info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
1297e2ebc74dSJohannes Berg 
12989ae54c84SJohannes Berg 	return TX_CONTINUE;
1299e2ebc74dSJohannes Berg }
1300e2ebc74dSJohannes Berg 
ieee80211_get_txq(struct ieee80211_local * local,struct ieee80211_vif * vif,struct sta_info * sta,struct sk_buff * skb)130180a83cfcSMichal Kazior static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
1302ba8c3d6fSFelix Fietkau 					  struct ieee80211_vif *vif,
1303dbef5362SMichal Kazior 					  struct sta_info *sta,
1304ba8c3d6fSFelix Fietkau 					  struct sk_buff *skb)
1305ba8c3d6fSFelix Fietkau {
1306ba8c3d6fSFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1307ba8c3d6fSFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1308ba8c3d6fSFelix Fietkau 	struct ieee80211_txq *txq = NULL;
1309ba8c3d6fSFelix Fietkau 
1310c3732a7bSFelix Fietkau 	if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) ||
1311c3732a7bSFelix Fietkau 	    (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
131280a83cfcSMichal Kazior 		return NULL;
1313ba8c3d6fSFelix Fietkau 
1314cc20ff2cSFelix Fietkau 	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
131550ff477aSJohn Crispin 	    unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
1316adf8ed01SJohannes Berg 		if ((!ieee80211_is_mgmt(hdr->frame_control) ||
13172c9abe65SJohannes Berg 		     ieee80211_is_bufferable_mmpdu(skb) ||
13180eeb2b67SSara Sharon 		     vif->type == NL80211_IFTYPE_STATION) &&
1319adf8ed01SJohannes Berg 		    sta && sta->uploaded) {
1320adf8ed01SJohannes Berg 			/*
1321adf8ed01SJohannes Berg 			 * This will be NULL if the driver didn't set the
1322adf8ed01SJohannes Berg 			 * opt-in hardware flag.
1323adf8ed01SJohannes Berg 			 */
1324adf8ed01SJohannes Berg 			txq = sta->sta.txq[IEEE80211_NUM_TIDS];
1325adf8ed01SJohannes Berg 		}
1326adf8ed01SJohannes Berg 	} else if (sta) {
1327ba8c3d6fSFelix Fietkau 		u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
1328ba8c3d6fSFelix Fietkau 
1329dbef5362SMichal Kazior 		if (!sta->uploaded)
1330dbef5362SMichal Kazior 			return NULL;
1331dbef5362SMichal Kazior 
1332dbef5362SMichal Kazior 		txq = sta->sta.txq[tid];
133394450963SAlexander Wetzel 	} else {
1334ba8c3d6fSFelix Fietkau 		txq = vif->txq;
1335ba8c3d6fSFelix Fietkau 	}
1336ba8c3d6fSFelix Fietkau 
1337ba8c3d6fSFelix Fietkau 	if (!txq)
133880a83cfcSMichal Kazior 		return NULL;
1339ba8c3d6fSFelix Fietkau 
134080a83cfcSMichal Kazior 	return to_txq_info(txq);
134180a83cfcSMichal Kazior }
1342ba8c3d6fSFelix Fietkau 
ieee80211_set_skb_enqueue_time(struct sk_buff * skb)13435caa328eSMichal Kazior static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
13445caa328eSMichal Kazior {
13457d360f60SFelix Fietkau 	struct sk_buff *next;
13467d360f60SFelix Fietkau 	codel_time_t now = codel_get_time();
13477d360f60SFelix Fietkau 
13487d360f60SFelix Fietkau 	skb_list_walk_safe(skb, skb, next)
13497d360f60SFelix Fietkau 		IEEE80211_SKB_CB(skb)->control.enqueue_time = now;
13505caa328eSMichal Kazior }
13515caa328eSMichal Kazior 
codel_skb_len_func(const struct sk_buff * skb)13525caa328eSMichal Kazior static u32 codel_skb_len_func(const struct sk_buff *skb)
13535caa328eSMichal Kazior {
13545caa328eSMichal Kazior 	return skb->len;
13555caa328eSMichal Kazior }
13565caa328eSMichal Kazior 
codel_skb_time_func(const struct sk_buff * skb)13575caa328eSMichal Kazior static codel_time_t codel_skb_time_func(const struct sk_buff *skb)
13585caa328eSMichal Kazior {
13595caa328eSMichal Kazior 	const struct ieee80211_tx_info *info;
13605caa328eSMichal Kazior 
13615caa328eSMichal Kazior 	info = (const struct ieee80211_tx_info *)skb->cb;
13625caa328eSMichal Kazior 	return info->control.enqueue_time;
13635caa328eSMichal Kazior }
13645caa328eSMichal Kazior 
codel_dequeue_func(struct codel_vars * cvars,void * ctx)13655caa328eSMichal Kazior static struct sk_buff *codel_dequeue_func(struct codel_vars *cvars,
13665caa328eSMichal Kazior 					  void *ctx)
13675caa328eSMichal Kazior {
13685caa328eSMichal Kazior 	struct ieee80211_local *local;
13695caa328eSMichal Kazior 	struct txq_info *txqi;
13705caa328eSMichal Kazior 	struct fq *fq;
13715caa328eSMichal Kazior 	struct fq_flow *flow;
13725caa328eSMichal Kazior 
13735caa328eSMichal Kazior 	txqi = ctx;
13745caa328eSMichal Kazior 	local = vif_to_sdata(txqi->txq.vif)->local;
13755caa328eSMichal Kazior 	fq = &local->fq;
13765caa328eSMichal Kazior 
13775caa328eSMichal Kazior 	if (cvars == &txqi->def_cvars)
1378bf9009bfSFelix Fietkau 		flow = &txqi->tin.default_flow;
13795caa328eSMichal Kazior 	else
13805caa328eSMichal Kazior 		flow = &fq->flows[cvars - local->cvars];
13815caa328eSMichal Kazior 
13825caa328eSMichal Kazior 	return fq_flow_dequeue(fq, flow);
13835caa328eSMichal Kazior }
13845caa328eSMichal Kazior 
codel_drop_func(struct sk_buff * skb,void * ctx)13855caa328eSMichal Kazior static void codel_drop_func(struct sk_buff *skb,
13865caa328eSMichal Kazior 			    void *ctx)
13875caa328eSMichal Kazior {
13885caa328eSMichal Kazior 	struct ieee80211_local *local;
13895caa328eSMichal Kazior 	struct ieee80211_hw *hw;
13905caa328eSMichal Kazior 	struct txq_info *txqi;
13915caa328eSMichal Kazior 
13925caa328eSMichal Kazior 	txqi = ctx;
13935caa328eSMichal Kazior 	local = vif_to_sdata(txqi->txq.vif)->local;
13945caa328eSMichal Kazior 	hw = &local->hw;
13955caa328eSMichal Kazior 
13965caa328eSMichal Kazior 	ieee80211_free_txskb(hw, skb);
13975caa328eSMichal Kazior }
13985caa328eSMichal Kazior 
fq_tin_dequeue_func(struct fq * fq,struct fq_tin * tin,struct fq_flow * flow)1399fa962b92SMichal Kazior static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
1400fa962b92SMichal Kazior 					   struct fq_tin *tin,
1401fa962b92SMichal Kazior 					   struct fq_flow *flow)
1402fa962b92SMichal Kazior {
14035caa328eSMichal Kazior 	struct ieee80211_local *local;
14045caa328eSMichal Kazior 	struct txq_info *txqi;
14055caa328eSMichal Kazior 	struct codel_vars *cvars;
14065caa328eSMichal Kazior 	struct codel_params *cparams;
14075caa328eSMichal Kazior 	struct codel_stats *cstats;
14085caa328eSMichal Kazior 
14095caa328eSMichal Kazior 	local = container_of(fq, struct ieee80211_local, fq);
14105caa328eSMichal Kazior 	txqi = container_of(tin, struct txq_info, tin);
14118d51dbb8SToke Høiland-Jørgensen 	cstats = &txqi->cstats;
14125caa328eSMichal Kazior 
1413484a54c2SToke Høiland-Jørgensen 	if (txqi->txq.sta) {
1414484a54c2SToke Høiland-Jørgensen 		struct sta_info *sta = container_of(txqi->txq.sta,
1415484a54c2SToke Høiland-Jørgensen 						    struct sta_info, sta);
1416484a54c2SToke Høiland-Jørgensen 		cparams = &sta->cparams;
1417484a54c2SToke Høiland-Jørgensen 	} else {
1418484a54c2SToke Høiland-Jørgensen 		cparams = &local->cparams;
1419484a54c2SToke Høiland-Jørgensen 	}
1420484a54c2SToke Høiland-Jørgensen 
1421bf9009bfSFelix Fietkau 	if (flow == &tin->default_flow)
14225caa328eSMichal Kazior 		cvars = &txqi->def_cvars;
14235caa328eSMichal Kazior 	else
14245caa328eSMichal Kazior 		cvars = &local->cvars[flow - fq->flows];
14255caa328eSMichal Kazior 
14265caa328eSMichal Kazior 	return codel_dequeue(txqi,
14275caa328eSMichal Kazior 			     &flow->backlog,
14285caa328eSMichal Kazior 			     cparams,
14295caa328eSMichal Kazior 			     cvars,
14305caa328eSMichal Kazior 			     cstats,
14315caa328eSMichal Kazior 			     codel_skb_len_func,
14325caa328eSMichal Kazior 			     codel_skb_time_func,
14335caa328eSMichal Kazior 			     codel_drop_func,
14345caa328eSMichal Kazior 			     codel_dequeue_func);
1435fa962b92SMichal Kazior }
1436fa962b92SMichal Kazior 
fq_skb_free_func(struct fq * fq,struct fq_tin * tin,struct fq_flow * flow,struct sk_buff * skb)1437fa962b92SMichal Kazior static void fq_skb_free_func(struct fq *fq,
1438fa962b92SMichal Kazior 			     struct fq_tin *tin,
1439fa962b92SMichal Kazior 			     struct fq_flow *flow,
1440fa962b92SMichal Kazior 			     struct sk_buff *skb)
1441fa962b92SMichal Kazior {
1442fa962b92SMichal Kazior 	struct ieee80211_local *local;
1443fa962b92SMichal Kazior 
1444fa962b92SMichal Kazior 	local = container_of(fq, struct ieee80211_local, fq);
1445fa962b92SMichal Kazior 	ieee80211_free_txskb(&local->hw, skb);
1446fa962b92SMichal Kazior }
1447fa962b92SMichal Kazior 
ieee80211_txq_enqueue(struct ieee80211_local * local,struct txq_info * txqi,struct sk_buff * skb)144880a83cfcSMichal Kazior static void ieee80211_txq_enqueue(struct ieee80211_local *local,
144980a83cfcSMichal Kazior 				  struct txq_info *txqi,
145080a83cfcSMichal Kazior 				  struct sk_buff *skb)
145180a83cfcSMichal Kazior {
1452fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1453fa962b92SMichal Kazior 	struct fq_tin *tin = &txqi->tin;
1454f2af2df8SFelix Fietkau 	u32 flow_idx = fq_flow_idx(fq, skb);
145580a83cfcSMichal Kazior 
14565caa328eSMichal Kazior 	ieee80211_set_skb_enqueue_time(skb);
1457f2af2df8SFelix Fietkau 
1458f2af2df8SFelix Fietkau 	spin_lock_bh(&fq->lock);
145973bc9e0aSJohannes Berg 	/*
146073bc9e0aSJohannes Berg 	 * For management frames, don't really apply codel etc.,
146173bc9e0aSJohannes Berg 	 * we don't want to apply any shaping or anything we just
146273bc9e0aSJohannes Berg 	 * want to simplify the driver API by having them on the
146373bc9e0aSJohannes Berg 	 * txqi.
146473bc9e0aSJohannes Berg 	 */
1465ca47b462SJohannes Berg 	if (unlikely(txqi->txq.tid == IEEE80211_NUM_TIDS)) {
1466ca47b462SJohannes Berg 		IEEE80211_SKB_CB(skb)->control.flags |=
1467ca47b462SJohannes Berg 			IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
146873bc9e0aSJohannes Berg 		__skb_queue_tail(&txqi->frags, skb);
1469ca47b462SJohannes Berg 	} else {
1470f2af2df8SFelix Fietkau 		fq_tin_enqueue(fq, tin, flow_idx, skb,
1471bf9009bfSFelix Fietkau 			       fq_skb_free_func);
1472ca47b462SJohannes Berg 	}
1473f2af2df8SFelix Fietkau 	spin_unlock_bh(&fq->lock);
147480a83cfcSMichal Kazior }
147580a83cfcSMichal Kazior 
fq_vlan_filter_func(struct fq * fq,struct fq_tin * tin,struct fq_flow * flow,struct sk_buff * skb,void * data)14762a9e2579SJohannes Berg static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin,
14772a9e2579SJohannes Berg 				struct fq_flow *flow, struct sk_buff *skb,
14782a9e2579SJohannes Berg 				void *data)
14792a9e2579SJohannes Berg {
14802a9e2579SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
14812a9e2579SJohannes Berg 
14822a9e2579SJohannes Berg 	return info->control.vif == data;
14832a9e2579SJohannes Berg }
14842a9e2579SJohannes Berg 
ieee80211_txq_remove_vlan(struct ieee80211_local * local,struct ieee80211_sub_if_data * sdata)14852a9e2579SJohannes Berg void ieee80211_txq_remove_vlan(struct ieee80211_local *local,
14862a9e2579SJohannes Berg 			       struct ieee80211_sub_if_data *sdata)
14872a9e2579SJohannes Berg {
14882a9e2579SJohannes Berg 	struct fq *fq = &local->fq;
14892a9e2579SJohannes Berg 	struct txq_info *txqi;
14902a9e2579SJohannes Berg 	struct fq_tin *tin;
14912a9e2579SJohannes Berg 	struct ieee80211_sub_if_data *ap;
14922a9e2579SJohannes Berg 
14932a9e2579SJohannes Berg 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
14942a9e2579SJohannes Berg 		return;
14952a9e2579SJohannes Berg 
14962a9e2579SJohannes Berg 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
14972a9e2579SJohannes Berg 
14982a9e2579SJohannes Berg 	if (!ap->vif.txq)
14992a9e2579SJohannes Berg 		return;
15002a9e2579SJohannes Berg 
15012a9e2579SJohannes Berg 	txqi = to_txq_info(ap->vif.txq);
15022a9e2579SJohannes Berg 	tin = &txqi->tin;
15032a9e2579SJohannes Berg 
15042a9e2579SJohannes Berg 	spin_lock_bh(&fq->lock);
15052a9e2579SJohannes Berg 	fq_tin_filter(fq, tin, fq_vlan_filter_func, &sdata->vif,
15062a9e2579SJohannes Berg 		      fq_skb_free_func);
15072a9e2579SJohannes Berg 	spin_unlock_bh(&fq->lock);
15082a9e2579SJohannes Berg }
15092a9e2579SJohannes Berg 
ieee80211_txq_init(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct txq_info * txqi,int tid)1510fa962b92SMichal Kazior void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
1511fa962b92SMichal Kazior 			struct sta_info *sta,
1512fa962b92SMichal Kazior 			struct txq_info *txqi, int tid)
1513fa962b92SMichal Kazior {
1514fa962b92SMichal Kazior 	fq_tin_init(&txqi->tin);
15155caa328eSMichal Kazior 	codel_vars_init(&txqi->def_cvars);
15168d51dbb8SToke Høiland-Jørgensen 	codel_stats_init(&txqi->cstats);
1517bb42f2d1SToke Høiland-Jørgensen 	__skb_queue_head_init(&txqi->frags);
1518942741daSFelix Fietkau 	INIT_LIST_HEAD(&txqi->schedule_order);
1519fa962b92SMichal Kazior 
1520fa962b92SMichal Kazior 	txqi->txq.vif = &sdata->vif;
1521fa962b92SMichal Kazior 
1522adf8ed01SJohannes Berg 	if (!sta) {
1523fa962b92SMichal Kazior 		sdata->vif.txq = &txqi->txq;
1524fa962b92SMichal Kazior 		txqi->txq.tid = 0;
1525fa962b92SMichal Kazior 		txqi->txq.ac = IEEE80211_AC_BE;
1526adf8ed01SJohannes Berg 
1527adf8ed01SJohannes Berg 		return;
1528fa962b92SMichal Kazior 	}
1529adf8ed01SJohannes Berg 
1530adf8ed01SJohannes Berg 	if (tid == IEEE80211_NUM_TIDS) {
15310eeb2b67SSara Sharon 		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
15320eeb2b67SSara Sharon 			/* Drivers need to opt in to the management MPDU TXQ */
15330eeb2b67SSara Sharon 			if (!ieee80211_hw_check(&sdata->local->hw,
15340eeb2b67SSara Sharon 						STA_MMPDU_TXQ))
1535adf8ed01SJohannes Berg 				return;
15360eeb2b67SSara Sharon 		} else if (!ieee80211_hw_check(&sdata->local->hw,
15370eeb2b67SSara Sharon 					       BUFF_MMPDU_TXQ)) {
15380eeb2b67SSara Sharon 			/* Drivers need to opt in to the bufferable MMPDU TXQ */
15390eeb2b67SSara Sharon 			return;
15400eeb2b67SSara Sharon 		}
1541adf8ed01SJohannes Berg 		txqi->txq.ac = IEEE80211_AC_VO;
1542adf8ed01SJohannes Berg 	} else {
1543adf8ed01SJohannes Berg 		txqi->txq.ac = ieee80211_ac_from_tid(tid);
1544adf8ed01SJohannes Berg 	}
1545adf8ed01SJohannes Berg 
1546adf8ed01SJohannes Berg 	txqi->txq.sta = &sta->sta;
1547adf8ed01SJohannes Berg 	txqi->txq.tid = tid;
1548adf8ed01SJohannes Berg 	sta->sta.txq[tid] = &txqi->txq;
1549fa962b92SMichal Kazior }
1550fa962b92SMichal Kazior 
ieee80211_txq_purge(struct ieee80211_local * local,struct txq_info * txqi)1551fa962b92SMichal Kazior void ieee80211_txq_purge(struct ieee80211_local *local,
1552fa962b92SMichal Kazior 			 struct txq_info *txqi)
1553fa962b92SMichal Kazior {
1554fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1555fa962b92SMichal Kazior 	struct fq_tin *tin = &txqi->tin;
1556fa962b92SMichal Kazior 
1557b4809e94SToke Høiland-Jørgensen 	spin_lock_bh(&fq->lock);
1558fa962b92SMichal Kazior 	fq_tin_reset(fq, tin, fq_skb_free_func);
1559bb42f2d1SToke Høiland-Jørgensen 	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
1560b4809e94SToke Høiland-Jørgensen 	spin_unlock_bh(&fq->lock);
1561b4809e94SToke Høiland-Jørgensen 
1562942741daSFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]);
1563942741daSFelix Fietkau 	list_del_init(&txqi->schedule_order);
1564942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]);
1565fa962b92SMichal Kazior }
1566fa962b92SMichal Kazior 
ieee80211_txq_set_params(struct ieee80211_local * local)15672fe4a29aSToke Høiland-Jørgensen void ieee80211_txq_set_params(struct ieee80211_local *local)
15682fe4a29aSToke Høiland-Jørgensen {
15692fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_limit)
15702fe4a29aSToke Høiland-Jørgensen 		local->fq.limit = local->hw.wiphy->txq_limit;
15712fe4a29aSToke Høiland-Jørgensen 	else
15722fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_limit = local->fq.limit;
15732fe4a29aSToke Høiland-Jørgensen 
15742fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_memory_limit)
15752fe4a29aSToke Høiland-Jørgensen 		local->fq.memory_limit = local->hw.wiphy->txq_memory_limit;
15762fe4a29aSToke Høiland-Jørgensen 	else
15772fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_memory_limit = local->fq.memory_limit;
15782fe4a29aSToke Høiland-Jørgensen 
15792fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_quantum)
15802fe4a29aSToke Høiland-Jørgensen 		local->fq.quantum = local->hw.wiphy->txq_quantum;
15812fe4a29aSToke Høiland-Jørgensen 	else
15822fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_quantum = local->fq.quantum;
15832fe4a29aSToke Høiland-Jørgensen }
15842fe4a29aSToke Høiland-Jørgensen 
ieee80211_txq_setup_flows(struct ieee80211_local * local)1585fa962b92SMichal Kazior int ieee80211_txq_setup_flows(struct ieee80211_local *local)
1586fa962b92SMichal Kazior {
1587fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1588fa962b92SMichal Kazior 	int ret;
15895caa328eSMichal Kazior 	int i;
15903ff23cd5SToke Høiland-Jørgensen 	bool supp_vht = false;
15913ff23cd5SToke Høiland-Jørgensen 	enum nl80211_band band;
1592fa962b92SMichal Kazior 
1593fa962b92SMichal Kazior 	ret = fq_init(fq, 4096);
1594fa962b92SMichal Kazior 	if (ret)
1595fa962b92SMichal Kazior 		return ret;
1596fa962b92SMichal Kazior 
15973ff23cd5SToke Høiland-Jørgensen 	/*
15983ff23cd5SToke Høiland-Jørgensen 	 * If the hardware doesn't support VHT, it is safe to limit the maximum
15993ff23cd5SToke Høiland-Jørgensen 	 * queue size. 4 Mbytes is 64 max-size aggregates in 802.11n.
16003ff23cd5SToke Høiland-Jørgensen 	 */
16013ff23cd5SToke Høiland-Jørgensen 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
16023ff23cd5SToke Høiland-Jørgensen 		struct ieee80211_supported_band *sband;
16033ff23cd5SToke Høiland-Jørgensen 
16043ff23cd5SToke Høiland-Jørgensen 		sband = local->hw.wiphy->bands[band];
16053ff23cd5SToke Høiland-Jørgensen 		if (!sband)
16063ff23cd5SToke Høiland-Jørgensen 			continue;
16073ff23cd5SToke Høiland-Jørgensen 
16083ff23cd5SToke Høiland-Jørgensen 		supp_vht = supp_vht || sband->vht_cap.vht_supported;
16093ff23cd5SToke Høiland-Jørgensen 	}
16103ff23cd5SToke Høiland-Jørgensen 
16113ff23cd5SToke Høiland-Jørgensen 	if (!supp_vht)
16123ff23cd5SToke Høiland-Jørgensen 		fq->memory_limit = 4 << 20; /* 4 Mbytes */
16133ff23cd5SToke Høiland-Jørgensen 
16145caa328eSMichal Kazior 	codel_params_init(&local->cparams);
16155caa328eSMichal Kazior 	local->cparams.interval = MS2TIME(100);
16165caa328eSMichal Kazior 	local->cparams.target = MS2TIME(20);
16175caa328eSMichal Kazior 	local->cparams.ecn = true;
16185caa328eSMichal Kazior 
16195caa328eSMichal Kazior 	local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
16205caa328eSMichal Kazior 			       GFP_KERNEL);
16215caa328eSMichal Kazior 	if (!local->cvars) {
162259a7c828SMichal Kazior 		spin_lock_bh(&fq->lock);
16235caa328eSMichal Kazior 		fq_reset(fq, fq_skb_free_func);
162459a7c828SMichal Kazior 		spin_unlock_bh(&fq->lock);
16255caa328eSMichal Kazior 		return -ENOMEM;
16265caa328eSMichal Kazior 	}
16275caa328eSMichal Kazior 
16285caa328eSMichal Kazior 	for (i = 0; i < fq->flows_cnt; i++)
16295caa328eSMichal Kazior 		codel_vars_init(&local->cvars[i]);
16305caa328eSMichal Kazior 
16312fe4a29aSToke Høiland-Jørgensen 	ieee80211_txq_set_params(local);
16322fe4a29aSToke Høiland-Jørgensen 
1633fa962b92SMichal Kazior 	return 0;
1634fa962b92SMichal Kazior }
1635fa962b92SMichal Kazior 
ieee80211_txq_teardown_flows(struct ieee80211_local * local)1636fa962b92SMichal Kazior void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
1637fa962b92SMichal Kazior {
1638fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1639fa962b92SMichal Kazior 
16405caa328eSMichal Kazior 	kfree(local->cvars);
16415caa328eSMichal Kazior 	local->cvars = NULL;
16425caa328eSMichal Kazior 
164359a7c828SMichal Kazior 	spin_lock_bh(&fq->lock);
1644fa962b92SMichal Kazior 	fq_reset(fq, fq_skb_free_func);
164559a7c828SMichal Kazior 	spin_unlock_bh(&fq->lock);
1646ba8c3d6fSFelix Fietkau }
1647ba8c3d6fSFelix Fietkau 
ieee80211_queue_skb(struct ieee80211_local * local,struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct sk_buff * skb)1648bb42f2d1SToke Høiland-Jørgensen static bool ieee80211_queue_skb(struct ieee80211_local *local,
1649bb42f2d1SToke Høiland-Jørgensen 				struct ieee80211_sub_if_data *sdata,
1650bb42f2d1SToke Høiland-Jørgensen 				struct sta_info *sta,
1651bb42f2d1SToke Høiland-Jørgensen 				struct sk_buff *skb)
1652bb42f2d1SToke Høiland-Jørgensen {
1653bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_vif *vif;
1654bb42f2d1SToke Høiland-Jørgensen 	struct txq_info *txqi;
1655bb42f2d1SToke Høiland-Jørgensen 
1656107395f9SAlexander Wetzel 	if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
1657bb42f2d1SToke Høiland-Jørgensen 		return false;
1658bb42f2d1SToke Høiland-Jørgensen 
1659bb42f2d1SToke Høiland-Jørgensen 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1660bb42f2d1SToke Høiland-Jørgensen 		sdata = container_of(sdata->bss,
1661bb42f2d1SToke Høiland-Jørgensen 				     struct ieee80211_sub_if_data, u.ap);
1662bb42f2d1SToke Høiland-Jørgensen 
1663bb42f2d1SToke Høiland-Jørgensen 	vif = &sdata->vif;
1664dbef5362SMichal Kazior 	txqi = ieee80211_get_txq(local, vif, sta, skb);
1665bb42f2d1SToke Høiland-Jørgensen 
1666bb42f2d1SToke Høiland-Jørgensen 	if (!txqi)
1667bb42f2d1SToke Høiland-Jørgensen 		return false;
1668bb42f2d1SToke Høiland-Jørgensen 
1669bb42f2d1SToke Høiland-Jørgensen 	ieee80211_txq_enqueue(local, txqi, skb);
1670bb42f2d1SToke Høiland-Jørgensen 
167118667600SToke Høiland-Jørgensen 	schedule_and_wake_txq(local, txqi);
1672bb42f2d1SToke Høiland-Jørgensen 
1673bb42f2d1SToke Høiland-Jørgensen 	return true;
1674bb42f2d1SToke Høiland-Jørgensen }
1675bb42f2d1SToke Høiland-Jørgensen 
ieee80211_tx_frags(struct ieee80211_local * local,struct ieee80211_vif * vif,struct sta_info * sta,struct sk_buff_head * skbs,bool txpending)167611127e91SJohannes Berg static bool ieee80211_tx_frags(struct ieee80211_local *local,
167711127e91SJohannes Berg 			       struct ieee80211_vif *vif,
16784fd0328dSJohannes Berg 			       struct sta_info *sta,
167911127e91SJohannes Berg 			       struct sk_buff_head *skbs,
168011127e91SJohannes Berg 			       bool txpending)
1681e2ebc74dSJohannes Berg {
168280a83cfcSMichal Kazior 	struct ieee80211_tx_control control = {};
1683252b86c4SJohannes Berg 	struct sk_buff *skb, *tmp;
16843b8d81e0SJohannes Berg 	unsigned long flags;
1685e2ebc74dSJohannes Berg 
1686252b86c4SJohannes Berg 	skb_queue_walk_safe(skbs, skb, tmp) {
16873a25a8c8SJohannes Berg 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
16883a25a8c8SJohannes Berg 		int q = info->hw_queue;
16893a25a8c8SJohannes Berg 
16903a25a8c8SJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
16913a25a8c8SJohannes Berg 		if (WARN_ON_ONCE(q >= local->hw.queues)) {
16923a25a8c8SJohannes Berg 			__skb_unlink(skb, skbs);
1693c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
16943a25a8c8SJohannes Berg 			continue;
16953a25a8c8SJohannes Berg 		}
16963a25a8c8SJohannes Berg #endif
16973b8d81e0SJohannes Berg 
16983b8d81e0SJohannes Berg 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
16993b8d81e0SJohannes Berg 		if (local->queue_stop_reasons[q] ||
17007bb45683SJohannes Berg 		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
17016c17b77bSSeth Forshee 			if (unlikely(info->flags &
1702a7679ed5SSeth Forshee 				     IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
1703a7679ed5SSeth Forshee 				if (local->queue_stop_reasons[q] &
1704a7679ed5SSeth Forshee 				    ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
17056c17b77bSSeth Forshee 					/*
1706a7679ed5SSeth Forshee 					 * Drop off-channel frames if queues
1707a7679ed5SSeth Forshee 					 * are stopped for any reason other
1708a7679ed5SSeth Forshee 					 * than off-channel operation. Never
1709a7679ed5SSeth Forshee 					 * queue them.
17106c17b77bSSeth Forshee 					 */
17116c17b77bSSeth Forshee 					spin_unlock_irqrestore(
1712a7679ed5SSeth Forshee 						&local->queue_stop_reason_lock,
1713a7679ed5SSeth Forshee 						flags);
1714a7679ed5SSeth Forshee 					ieee80211_purge_tx_queue(&local->hw,
1715a7679ed5SSeth Forshee 								 skbs);
17166c17b77bSSeth Forshee 					return true;
17176c17b77bSSeth Forshee 				}
1718a7679ed5SSeth Forshee 			} else {
17196c17b77bSSeth Forshee 
17207bb45683SJohannes Berg 				/*
1721a7679ed5SSeth Forshee 				 * Since queue is stopped, queue up frames for
1722a7679ed5SSeth Forshee 				 * later transmission from the tx-pending
1723a7679ed5SSeth Forshee 				 * tasklet when the queue is woken again.
17247bb45683SJohannes Berg 				 */
1725252b86c4SJohannes Berg 				if (txpending)
1726a7679ed5SSeth Forshee 					skb_queue_splice_init(skbs,
1727a7679ed5SSeth Forshee 							      &local->pending[q]);
17287bb45683SJohannes Berg 				else
17294db4e0a1SJohannes Berg 					skb_queue_splice_tail_init(skbs,
17304db4e0a1SJohannes Berg 								   &local->pending[q]);
17317bb45683SJohannes Berg 
17327bb45683SJohannes Berg 				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
17337bb45683SJohannes Berg 						       flags);
17347bb45683SJohannes Berg 				return false;
17357bb45683SJohannes Berg 			}
1736a7679ed5SSeth Forshee 		}
17373b8d81e0SJohannes Berg 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1738e2530083SJohannes Berg 
173911127e91SJohannes Berg 		info->control.vif = vif;
17404fd0328dSJohannes Berg 		control.sta = sta ? &sta->sta : NULL;
1741ec25acc4SJohannes Berg 
1742252b86c4SJohannes Berg 		__skb_unlink(skb, skbs);
174380a83cfcSMichal Kazior 		drv_tx(local, &control, skb);
1744e2ebc74dSJohannes Berg 	}
17452de8e0d9SJohannes Berg 
174611127e91SJohannes Berg 	return true;
174711127e91SJohannes Berg }
174811127e91SJohannes Berg 
174911127e91SJohannes Berg /*
175011127e91SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead.
175111127e91SJohannes Berg  */
__ieee80211_tx(struct ieee80211_local * local,struct sk_buff_head * skbs,struct sta_info * sta,bool txpending)175211127e91SJohannes Berg static bool __ieee80211_tx(struct ieee80211_local *local,
175330f6cf96SFelix Fietkau 			   struct sk_buff_head *skbs, struct sta_info *sta,
175430f6cf96SFelix Fietkau 			   bool txpending)
175511127e91SJohannes Berg {
175611127e91SJohannes Berg 	struct ieee80211_tx_info *info;
175711127e91SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
175811127e91SJohannes Berg 	struct ieee80211_vif *vif;
175911127e91SJohannes Berg 	struct sk_buff *skb;
1760958574cbSColin Ian King 	bool result;
176111127e91SJohannes Berg 
176211127e91SJohannes Berg 	if (WARN_ON(skb_queue_empty(skbs)))
176311127e91SJohannes Berg 		return true;
176411127e91SJohannes Berg 
176511127e91SJohannes Berg 	skb = skb_peek(skbs);
176611127e91SJohannes Berg 	info = IEEE80211_SKB_CB(skb);
176711127e91SJohannes Berg 	sdata = vif_to_sdata(info->control.vif);
176811127e91SJohannes Berg 	if (sta && !sta->uploaded)
176911127e91SJohannes Berg 		sta = NULL;
177011127e91SJohannes Berg 
177111127e91SJohannes Berg 	switch (sdata->vif.type) {
177211127e91SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
1773d8212184SAviya Erenfeld 		if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
1774c82b5a74SJohannes Berg 			vif = &sdata->vif;
1775c82b5a74SJohannes Berg 			break;
1776c82b5a74SJohannes Berg 		}
17774b6f1dd6SJohannes Berg 		sdata = rcu_dereference(local->monitor_sdata);
17783a25a8c8SJohannes Berg 		if (sdata) {
17794b6f1dd6SJohannes Berg 			vif = &sdata->vif;
17803a25a8c8SJohannes Berg 			info->hw_queue =
17813a25a8c8SJohannes Berg 				vif->hw_queue[skb_get_queue_mapping(skb)];
178230686bf7SJohannes Berg 		} else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
178363b4d8b3SJohannes Berg 			ieee80211_purge_tx_queue(&local->hw, skbs);
17843a25a8c8SJohannes Berg 			return true;
17853a25a8c8SJohannes Berg 		} else
178611127e91SJohannes Berg 			vif = NULL;
178711127e91SJohannes Berg 		break;
178811127e91SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
178911127e91SJohannes Berg 		sdata = container_of(sdata->bss,
179011127e91SJohannes Berg 				     struct ieee80211_sub_if_data, u.ap);
1791fc0561dcSGustavo A. R. Silva 		fallthrough;
179211127e91SJohannes Berg 	default:
179311127e91SJohannes Berg 		vif = &sdata->vif;
179411127e91SJohannes Berg 		break;
179511127e91SJohannes Berg 	}
179611127e91SJohannes Berg 
17974fd0328dSJohannes Berg 	result = ieee80211_tx_frags(local, vif, sta, skbs, txpending);
179811127e91SJohannes Berg 
17994db4e0a1SJohannes Berg 	WARN_ON_ONCE(!skb_queue_empty(skbs));
1800252b86c4SJohannes Berg 
180111127e91SJohannes Berg 	return result;
1802e2ebc74dSJohannes Berg }
1803e2ebc74dSJohannes Berg 
180497b045d6SJohannes Berg /*
180597b045d6SJohannes Berg  * Invoke TX handlers, return 0 on success and non-zero if the
180697b045d6SJohannes Berg  * frame was dropped or queued.
1807bb42f2d1SToke Høiland-Jørgensen  *
1808bb42f2d1SToke Høiland-Jørgensen  * The handlers are split into an early and late part. The latter is everything
1809bb42f2d1SToke Høiland-Jørgensen  * that can be sensitive to reordering, and will be deferred to after packets
1810bb42f2d1SToke Høiland-Jørgensen  * are dequeued from the intermediate queues (when they are enabled).
181197b045d6SJohannes Berg  */
invoke_tx_handlers_early(struct ieee80211_tx_data * tx)1812bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
181397b045d6SJohannes Berg {
181497b045d6SJohannes Berg 	ieee80211_tx_result res = TX_DROP;
181597b045d6SJohannes Berg 
1816d9e8a70fSJohannes Berg #define CALL_TXH(txh) \
18179aa4aee3SJohannes Berg 	do {				\
1818d9e8a70fSJohannes Berg 		res = txh(tx);		\
1819d9e8a70fSJohannes Berg 		if (res != TX_CONTINUE)	\
18209aa4aee3SJohannes Berg 			goto txh_done;	\
18219aa4aee3SJohannes Berg 	} while (0)
182297b045d6SJohannes Berg 
18235c1b98a5SKalle Valo 	CALL_TXH(ieee80211_tx_h_dynamic_ps);
18249aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_check_assoc);
18259aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_ps_buf);
1826a621fa4dSJohannes Berg 	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
18279aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_select_key);
1828c6fcf6bcSJohannes Berg 
1829bb42f2d1SToke Høiland-Jørgensen  txh_done:
1830bb42f2d1SToke Høiland-Jørgensen 	if (unlikely(res == TX_DROP)) {
1831bb42f2d1SToke Høiland-Jørgensen 		I802_DEBUG_INC(tx->local->tx_handlers_drop);
1832bb42f2d1SToke Høiland-Jørgensen 		if (tx->skb)
1833bb42f2d1SToke Høiland-Jørgensen 			ieee80211_free_txskb(&tx->local->hw, tx->skb);
1834bb42f2d1SToke Høiland-Jørgensen 		else
1835bb42f2d1SToke Høiland-Jørgensen 			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
1836bb42f2d1SToke Høiland-Jørgensen 		return -1;
1837bb42f2d1SToke Høiland-Jørgensen 	} else if (unlikely(res == TX_QUEUED)) {
1838bb42f2d1SToke Høiland-Jørgensen 		I802_DEBUG_INC(tx->local->tx_handlers_queued);
1839bb42f2d1SToke Høiland-Jørgensen 		return -1;
1840bb42f2d1SToke Høiland-Jørgensen 	}
1841bb42f2d1SToke Høiland-Jørgensen 
1842bb42f2d1SToke Høiland-Jørgensen 	return 0;
1843bb42f2d1SToke Høiland-Jørgensen }
1844bb42f2d1SToke Høiland-Jørgensen 
1845bb42f2d1SToke Høiland-Jørgensen /*
1846bb42f2d1SToke Høiland-Jørgensen  * Late handlers can be called while the sta lock is held. Handlers that can
1847bb42f2d1SToke Høiland-Jørgensen  * cause packets to be generated will cause deadlock!
1848bb42f2d1SToke Høiland-Jørgensen  */
invoke_tx_handlers_late(struct ieee80211_tx_data * tx)1849bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
1850bb42f2d1SToke Høiland-Jørgensen {
1851bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
1852bb42f2d1SToke Høiland-Jørgensen 	ieee80211_tx_result res = TX_CONTINUE;
1853bb42f2d1SToke Høiland-Jørgensen 
185418688c80SFelix Fietkau 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
185518688c80SFelix Fietkau 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
185618688c80SFelix Fietkau 
1857aa5b5492SJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
1858aa5b5492SJohannes Berg 		__skb_queue_tail(&tx->skbs, tx->skb);
1859aa5b5492SJohannes Berg 		tx->skb = NULL;
1860c6fcf6bcSJohannes Berg 		goto txh_done;
1861aa5b5492SJohannes Berg 	}
1862c6fcf6bcSJohannes Berg 
1863c6fcf6bcSJohannes Berg 	CALL_TXH(ieee80211_tx_h_michael_mic_add);
18649aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_sequence);
18659aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_fragment);
1866d9e8a70fSJohannes Berg 	/* handlers after fragment must be aware of tx info fragmentation! */
18679aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_stats);
18689aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_encrypt);
186930686bf7SJohannes Berg 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
18709aa4aee3SJohannes Berg 		CALL_TXH(ieee80211_tx_h_calculate_duration);
1871d9e8a70fSJohannes Berg #undef CALL_TXH
1872d9e8a70fSJohannes Berg 
1873d9e8a70fSJohannes Berg  txh_done:
187497b045d6SJohannes Berg 	if (unlikely(res == TX_DROP)) {
18755479d0e7STomas Winkler 		I802_DEBUG_INC(tx->local->tx_handlers_drop);
1876252b86c4SJohannes Berg 		if (tx->skb)
1877c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&tx->local->hw, tx->skb);
1878252b86c4SJohannes Berg 		else
18791f98ab7fSFelix Fietkau 			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
188097b045d6SJohannes Berg 		return -1;
188197b045d6SJohannes Berg 	} else if (unlikely(res == TX_QUEUED)) {
18825479d0e7STomas Winkler 		I802_DEBUG_INC(tx->local->tx_handlers_queued);
188397b045d6SJohannes Berg 		return -1;
188497b045d6SJohannes Berg 	}
188597b045d6SJohannes Berg 
188697b045d6SJohannes Berg 	return 0;
188797b045d6SJohannes Berg }
188897b045d6SJohannes Berg 
invoke_tx_handlers(struct ieee80211_tx_data * tx)1889bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1890bb42f2d1SToke Høiland-Jørgensen {
1891bb42f2d1SToke Høiland-Jørgensen 	int r = invoke_tx_handlers_early(tx);
1892bb42f2d1SToke Høiland-Jørgensen 
1893bb42f2d1SToke Høiland-Jørgensen 	if (r)
1894bb42f2d1SToke Høiland-Jørgensen 		return r;
1895bb42f2d1SToke Høiland-Jørgensen 	return invoke_tx_handlers_late(tx);
1896bb42f2d1SToke Høiland-Jørgensen }
1897bb42f2d1SToke Høiland-Jørgensen 
ieee80211_tx_prepare_skb(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct sk_buff * skb,int band,struct ieee80211_sta ** sta)189806be6b14SFelix Fietkau bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
189906be6b14SFelix Fietkau 			      struct ieee80211_vif *vif, struct sk_buff *skb,
190006be6b14SFelix Fietkau 			      int band, struct ieee80211_sta **sta)
190106be6b14SFelix Fietkau {
190206be6b14SFelix Fietkau 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
190306be6b14SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
190406be6b14SFelix Fietkau 	struct ieee80211_tx_data tx;
190588724a81SJohannes Berg 	struct sk_buff *skb2;
190606be6b14SFelix Fietkau 
19077c10770fSJohannes Berg 	if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
190806be6b14SFelix Fietkau 		return false;
190906be6b14SFelix Fietkau 
191006be6b14SFelix Fietkau 	info->band = band;
191106be6b14SFelix Fietkau 	info->control.vif = vif;
191206be6b14SFelix Fietkau 	info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)];
191306be6b14SFelix Fietkau 
191406be6b14SFelix Fietkau 	if (invoke_tx_handlers(&tx))
191506be6b14SFelix Fietkau 		return false;
191606be6b14SFelix Fietkau 
191706be6b14SFelix Fietkau 	if (sta) {
191806be6b14SFelix Fietkau 		if (tx.sta)
191906be6b14SFelix Fietkau 			*sta = &tx.sta->sta;
192006be6b14SFelix Fietkau 		else
192106be6b14SFelix Fietkau 			*sta = NULL;
192206be6b14SFelix Fietkau 	}
192306be6b14SFelix Fietkau 
192488724a81SJohannes Berg 	/* this function isn't suitable for fragmented data frames */
192588724a81SJohannes Berg 	skb2 = __skb_dequeue(&tx.skbs);
192688724a81SJohannes Berg 	if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) {
192788724a81SJohannes Berg 		ieee80211_free_txskb(hw, skb2);
192888724a81SJohannes Berg 		ieee80211_purge_tx_queue(hw, &tx.skbs);
192988724a81SJohannes Berg 		return false;
193088724a81SJohannes Berg 	}
193188724a81SJohannes Berg 
193206be6b14SFelix Fietkau 	return true;
193306be6b14SFelix Fietkau }
193406be6b14SFelix Fietkau EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
193506be6b14SFelix Fietkau 
19367bb45683SJohannes Berg /*
19377bb45683SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead.
19387bb45683SJohannes Berg  */
ieee80211_tx(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct sk_buff * skb,bool txpending)19397bb45683SJohannes Berg static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
19407c10770fSJohannes Berg 			 struct sta_info *sta, struct sk_buff *skb,
194108aca29aSMathy Vanhoef 			 bool txpending)
1942e2ebc74dSJohannes Berg {
19433b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
19445cf121c3SJohannes Berg 	struct ieee80211_tx_data tx;
194597b045d6SJohannes Berg 	ieee80211_tx_result res_prepare;
1946e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
19477bb45683SJohannes Berg 	bool result = true;
1948e2ebc74dSJohannes Berg 
1949e2ebc74dSJohannes Berg 	if (unlikely(skb->len < 10)) {
1950e2ebc74dSJohannes Berg 		dev_kfree_skb(skb);
19517bb45683SJohannes Berg 		return true;
1952e2ebc74dSJohannes Berg 	}
1953e2ebc74dSJohannes Berg 
195458d4185eSJohannes Berg 	/* initialises tx */
19557c10770fSJohannes Berg 	res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
1956e2ebc74dSJohannes Berg 
1957cd8ffc80SJohannes Berg 	if (unlikely(res_prepare == TX_DROP)) {
1958c3e7724bSFelix Fietkau 		ieee80211_free_txskb(&local->hw, skb);
195955de908aSJohannes Berg 		return true;
1960cd8ffc80SJohannes Berg 	} else if (unlikely(res_prepare == TX_QUEUED)) {
196155de908aSJohannes Berg 		return true;
1962e2ebc74dSJohannes Berg 	}
1963e2ebc74dSJohannes Berg 
19643a25a8c8SJohannes Berg 	/* set up hw_queue value early */
19653a25a8c8SJohannes Berg 	if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
196630686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
19673a25a8c8SJohannes Berg 		info->hw_queue =
19683a25a8c8SJohannes Berg 			sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
19693a25a8c8SJohannes Berg 
1970bb42f2d1SToke Høiland-Jørgensen 	if (invoke_tx_handlers_early(&tx))
19716eae4a6cSBob Copeland 		return true;
1972bb42f2d1SToke Høiland-Jørgensen 
1973bb42f2d1SToke Høiland-Jørgensen 	if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
1974bb42f2d1SToke Høiland-Jørgensen 		return true;
1975bb42f2d1SToke Høiland-Jørgensen 
1976bb42f2d1SToke Høiland-Jørgensen 	if (!invoke_tx_handlers_late(&tx))
197730f6cf96SFelix Fietkau 		result = __ieee80211_tx(local, &tx.skbs, tx.sta, txpending);
197855de908aSJohannes Berg 
19797bb45683SJohannes Berg 	return result;
1980e2ebc74dSJohannes Berg }
1981e2ebc74dSJohannes Berg 
1982e2ebc74dSJohannes Berg /* device xmit handlers */
1983e2ebc74dSJohannes Berg 
198414f46c1eSJohannes Berg enum ieee80211_encrypt {
198514f46c1eSJohannes Berg 	ENCRYPT_NO,
198614f46c1eSJohannes Berg 	ENCRYPT_MGMT,
198714f46c1eSJohannes Berg 	ENCRYPT_DATA,
198814f46c1eSJohannes Berg };
198914f46c1eSJohannes Berg 
ieee80211_skb_resize(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,int head_need,enum ieee80211_encrypt encrypt)19903bff1865SYogesh Ashok Powar static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
199123c0752aSJohannes Berg 				struct sk_buff *skb,
199214f46c1eSJohannes Berg 				int head_need,
199314f46c1eSJohannes Berg 				enum ieee80211_encrypt encrypt)
199423c0752aSJohannes Berg {
19953bff1865SYogesh Ashok Powar 	struct ieee80211_local *local = sdata->local;
19969d0f50b8SFelix Fietkau 	bool enc_tailroom;
199723c0752aSJohannes Berg 	int tail_need = 0;
199823c0752aSJohannes Berg 
199914f46c1eSJohannes Berg 	enc_tailroom = encrypt == ENCRYPT_MGMT ||
200014f46c1eSJohannes Berg 		       (encrypt == ENCRYPT_DATA &&
200114f46c1eSJohannes Berg 			sdata->crypto_tx_tailroom_needed_cnt);
20029d0f50b8SFelix Fietkau 
20039d0f50b8SFelix Fietkau 	if (enc_tailroom) {
200423c0752aSJohannes Berg 		tail_need = IEEE80211_ENCRYPT_TAILROOM;
200523c0752aSJohannes Berg 		tail_need -= skb_tailroom(skb);
200623c0752aSJohannes Berg 		tail_need = max_t(int, tail_need, 0);
200723c0752aSJohannes Berg 	}
200823c0752aSJohannes Berg 
2009c70f59a2SIdo Yariv 	if (skb_cloned(skb) &&
201030686bf7SJohannes Berg 	    (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
20119d0f50b8SFelix Fietkau 	     !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
201223c0752aSJohannes Berg 		I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
20134cd06a34SFelix Fietkau 	else if (head_need || tail_need)
201423c0752aSJohannes Berg 		I802_DEBUG_INC(local->tx_expand_skb_head);
20154cd06a34SFelix Fietkau 	else
20164cd06a34SFelix Fietkau 		return 0;
201723c0752aSJohannes Berg 
201823c0752aSJohannes Berg 	if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
20190fb9a9ecSJoe Perches 		wiphy_debug(local->hw.wiphy,
20200fb9a9ecSJoe Perches 			    "failed to reallocate TX buffer\n");
202123c0752aSJohannes Berg 		return -ENOMEM;
202223c0752aSJohannes Berg 	}
202323c0752aSJohannes Berg 
202423c0752aSJohannes Berg 	return 0;
202523c0752aSJohannes Berg }
202623c0752aSJohannes Berg 
ieee80211_xmit(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct sk_buff * skb)20277c10770fSJohannes Berg void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
202808aca29aSMathy Vanhoef 		    struct sta_info *sta, struct sk_buff *skb)
2029e2ebc74dSJohannes Berg {
20303b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
2031e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
203214f46c1eSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2033e2ebc74dSJohannes Berg 	int headroom;
203414f46c1eSJohannes Berg 	enum ieee80211_encrypt encrypt;
2035e2ebc74dSJohannes Berg 
203614f46c1eSJohannes Berg 	if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)
203714f46c1eSJohannes Berg 		encrypt = ENCRYPT_NO;
203814f46c1eSJohannes Berg 	else if (ieee80211_is_mgmt(hdr->frame_control))
203914f46c1eSJohannes Berg 		encrypt = ENCRYPT_MGMT;
204014f46c1eSJohannes Berg 	else
204114f46c1eSJohannes Berg 		encrypt = ENCRYPT_DATA;
204223c0752aSJohannes Berg 
20433b8d81e0SJohannes Berg 	headroom = local->tx_headroom;
204414f46c1eSJohannes Berg 	if (encrypt != ENCRYPT_NO)
204523a5f0afSJohannes Berg 		headroom += IEEE80211_ENCRYPT_HEADROOM;
204623c0752aSJohannes Berg 	headroom -= skb_headroom(skb);
204723c0752aSJohannes Berg 	headroom = max_t(int, 0, headroom);
204823c0752aSJohannes Berg 
204914f46c1eSJohannes Berg 	if (ieee80211_skb_resize(sdata, skb, headroom, encrypt)) {
2050c3e7724bSFelix Fietkau 		ieee80211_free_txskb(&local->hw, skb);
20513b8d81e0SJohannes Berg 		return;
2052e2ebc74dSJohannes Berg 	}
2053e2ebc74dSJohannes Berg 
205414f46c1eSJohannes Berg 	/* reload after potential resize */
2055740c1aa3SSteve deRosier 	hdr = (struct ieee80211_hdr *) skb->data;
20565061b0c2SJohannes Berg 	info->control.vif = &sdata->vif;
2057cd8ffc80SJohannes Berg 
20583f52b7e3SMarco Porsch 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
20593f52b7e3SMarco Porsch 		if (ieee80211_is_data(hdr->frame_control) &&
20603f52b7e3SMarco Porsch 		    is_unicast_ether_addr(hdr->addr1)) {
2061bf7cd94dSJohannes Berg 			if (mesh_nexthop_resolve(sdata, skb))
20623f52b7e3SMarco Porsch 				return; /* skb queued: don't free */
20633f52b7e3SMarco Porsch 		} else {
20643f52b7e3SMarco Porsch 			ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
20653f52b7e3SMarco Porsch 		}
2066cca89496SJavier Cardona 	}
2067cca89496SJavier Cardona 
20682154c81cSJavier Cardona 	ieee80211_set_qos_hdr(sdata, skb);
206908aca29aSMathy Vanhoef 	ieee80211_tx(sdata, sta, skb, false);
2070e2ebc74dSJohannes Berg }
2071e2ebc74dSJohannes Berg 
ieee80211_validate_radiotap_len(struct sk_buff * skb)2072bddc0c41SMathy Vanhoef static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
207373b9f03aSJohannes Berg {
207473b9f03aSJohannes Berg 	struct ieee80211_radiotap_header *rthdr =
207573b9f03aSJohannes Berg 		(struct ieee80211_radiotap_header *)skb->data;
207673b9f03aSJohannes Berg 
2077cb17ed29SMathy Vanhoef 	/* check for not even having the fixed radiotap header part */
2078cb17ed29SMathy Vanhoef 	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2079cb17ed29SMathy Vanhoef 		return false; /* too short to be possibly valid */
2080cb17ed29SMathy Vanhoef 
2081cb17ed29SMathy Vanhoef 	/* is it a header version we can trust to find length from? */
2082cb17ed29SMathy Vanhoef 	if (unlikely(rthdr->it_version))
2083cb17ed29SMathy Vanhoef 		return false; /* only version 0 is supported */
2084cb17ed29SMathy Vanhoef 
2085cb17ed29SMathy Vanhoef 	/* does the skb contain enough to deliver on the alleged length? */
2086cb17ed29SMathy Vanhoef 	if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data)))
2087cb17ed29SMathy Vanhoef 		return false; /* skb too short for claimed rt header extent */
2088cb17ed29SMathy Vanhoef 
2089bddc0c41SMathy Vanhoef 	return true;
2090bddc0c41SMathy Vanhoef }
2091bddc0c41SMathy Vanhoef 
ieee80211_parse_tx_radiotap(struct sk_buff * skb,struct net_device * dev)2092bddc0c41SMathy Vanhoef bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
2093bddc0c41SMathy Vanhoef 				 struct net_device *dev)
2094bddc0c41SMathy Vanhoef {
2095bddc0c41SMathy Vanhoef 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2096bddc0c41SMathy Vanhoef 	struct ieee80211_radiotap_iterator iterator;
2097bddc0c41SMathy Vanhoef 	struct ieee80211_radiotap_header *rthdr =
2098bddc0c41SMathy Vanhoef 		(struct ieee80211_radiotap_header *) skb->data;
2099bddc0c41SMathy Vanhoef 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2100bddc0c41SMathy Vanhoef 	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
2101bddc0c41SMathy Vanhoef 						   NULL);
2102bddc0c41SMathy Vanhoef 	u16 txflags;
2103bddc0c41SMathy Vanhoef 	u16 rate = 0;
2104bddc0c41SMathy Vanhoef 	bool rate_found = false;
2105bddc0c41SMathy Vanhoef 	u8 rate_retries = 0;
2106bddc0c41SMathy Vanhoef 	u16 rate_flags = 0;
2107bddc0c41SMathy Vanhoef 	u8 mcs_known, mcs_flags, mcs_bw;
2108bddc0c41SMathy Vanhoef 	u16 vht_known;
2109bddc0c41SMathy Vanhoef 	u8 vht_mcs = 0, vht_nss = 0;
2110bddc0c41SMathy Vanhoef 	int i;
2111bddc0c41SMathy Vanhoef 
2112bddc0c41SMathy Vanhoef 	if (!ieee80211_validate_radiotap_len(skb))
2113bddc0c41SMathy Vanhoef 		return false;
2114bddc0c41SMathy Vanhoef 
211573b9f03aSJohannes Berg 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
211673b9f03aSJohannes Berg 		       IEEE80211_TX_CTL_DONTFRAG;
211773b9f03aSJohannes Berg 
211873b9f03aSJohannes Berg 	/*
211973b9f03aSJohannes Berg 	 * for every radiotap entry that is present
212073b9f03aSJohannes Berg 	 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
212173b9f03aSJohannes Berg 	 * entries present, or -EINVAL on error)
212273b9f03aSJohannes Berg 	 */
212373b9f03aSJohannes Berg 
212473b9f03aSJohannes Berg 	while (!ret) {
212573b9f03aSJohannes Berg 		ret = ieee80211_radiotap_iterator_next(&iterator);
212673b9f03aSJohannes Berg 
212773b9f03aSJohannes Berg 		if (ret)
212873b9f03aSJohannes Berg 			continue;
212973b9f03aSJohannes Berg 
213073b9f03aSJohannes Berg 		/* see if this argument is something we can use */
213173b9f03aSJohannes Berg 		switch (iterator.this_arg_index) {
213273b9f03aSJohannes Berg 		/*
213373b9f03aSJohannes Berg 		 * You must take care when dereferencing iterator.this_arg
213473b9f03aSJohannes Berg 		 * for multibyte types... the pointer is not aligned.  Use
213573b9f03aSJohannes Berg 		 * get_unaligned((type *)iterator.this_arg) to dereference
213673b9f03aSJohannes Berg 		 * iterator.this_arg for type "type" safely on all arches.
213773b9f03aSJohannes Berg 		*/
213873b9f03aSJohannes Berg 		case IEEE80211_RADIOTAP_FLAGS:
213973b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
214073b9f03aSJohannes Berg 				/*
214173b9f03aSJohannes Berg 				 * this indicates that the skb we have been
214273b9f03aSJohannes Berg 				 * handed has the 32-bit FCS CRC at the end...
214373b9f03aSJohannes Berg 				 * we should react to that by snipping it off
214473b9f03aSJohannes Berg 				 * because it will be recomputed and added
214573b9f03aSJohannes Berg 				 * on transmission
214673b9f03aSJohannes Berg 				 */
214773b9f03aSJohannes Berg 				if (skb->len < (iterator._max_length + FCS_LEN))
214873b9f03aSJohannes Berg 					return false;
214973b9f03aSJohannes Berg 
215073b9f03aSJohannes Berg 				skb_trim(skb, skb->len - FCS_LEN);
215173b9f03aSJohannes Berg 			}
215273b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
215373b9f03aSJohannes Berg 				info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
215473b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
215573b9f03aSJohannes Berg 				info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
215673b9f03aSJohannes Berg 			break;
215773b9f03aSJohannes Berg 
215873b9f03aSJohannes Berg 		case IEEE80211_RADIOTAP_TX_FLAGS:
215973b9f03aSJohannes Berg 			txflags = get_unaligned_le16(iterator.this_arg);
216073b9f03aSJohannes Berg 			if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
216173b9f03aSJohannes Berg 				info->flags |= IEEE80211_TX_CTL_NO_ACK;
2162e02281e7SMathy Vanhoef 			if (txflags & IEEE80211_RADIOTAP_F_TX_NOSEQNO)
2163e02281e7SMathy Vanhoef 				info->control.flags |= IEEE80211_TX_CTRL_NO_SEQNO;
216430df8130SMathy Vanhoef 			if (txflags & IEEE80211_RADIOTAP_F_TX_ORDER)
216530df8130SMathy Vanhoef 				info->control.flags |=
216630df8130SMathy Vanhoef 					IEEE80211_TX_CTRL_DONT_REORDER;
216773b9f03aSJohannes Berg 			break;
216873b9f03aSJohannes Berg 
2169dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_RATE:
2170dfdfc2beSSven Eckelmann 			rate = *iterator.this_arg;
2171dfdfc2beSSven Eckelmann 			rate_flags = 0;
2172dfdfc2beSSven Eckelmann 			rate_found = true;
2173dfdfc2beSSven Eckelmann 			break;
2174dfdfc2beSSven Eckelmann 
2175dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_DATA_RETRIES:
2176dfdfc2beSSven Eckelmann 			rate_retries = *iterator.this_arg;
2177dfdfc2beSSven Eckelmann 			break;
2178dfdfc2beSSven Eckelmann 
2179dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_MCS:
2180dfdfc2beSSven Eckelmann 			mcs_known = iterator.this_arg[0];
2181dfdfc2beSSven Eckelmann 			mcs_flags = iterator.this_arg[1];
2182dfdfc2beSSven Eckelmann 			if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
2183dfdfc2beSSven Eckelmann 				break;
2184dfdfc2beSSven Eckelmann 
2185dfdfc2beSSven Eckelmann 			rate_found = true;
2186dfdfc2beSSven Eckelmann 			rate = iterator.this_arg[2];
2187dfdfc2beSSven Eckelmann 			rate_flags = IEEE80211_TX_RC_MCS;
2188dfdfc2beSSven Eckelmann 
2189dfdfc2beSSven Eckelmann 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
2190dfdfc2beSSven Eckelmann 			    mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
2191dfdfc2beSSven Eckelmann 				rate_flags |= IEEE80211_TX_RC_SHORT_GI;
2192dfdfc2beSSven Eckelmann 
2193f66b60f6SSven Eckelmann 			mcs_bw = mcs_flags & IEEE80211_RADIOTAP_MCS_BW_MASK;
2194dfdfc2beSSven Eckelmann 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
2195f66b60f6SSven Eckelmann 			    mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40)
2196dfdfc2beSSven Eckelmann 				rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2197f1864e19SPhilipp Borgers 
2198f1864e19SPhilipp Borgers 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC &&
2199f1864e19SPhilipp Borgers 			    mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC)
2200f1864e19SPhilipp Borgers 				info->flags |= IEEE80211_TX_CTL_LDPC;
2201549fdd34SPhilipp Borgers 
2202549fdd34SPhilipp Borgers 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_STBC) {
2203549fdd34SPhilipp Borgers 				u8 stbc = u8_get_bits(mcs_flags,
2204549fdd34SPhilipp Borgers 						      IEEE80211_RADIOTAP_MCS_STBC_MASK);
2205549fdd34SPhilipp Borgers 
2206549fdd34SPhilipp Borgers 				info->flags |=
2207549fdd34SPhilipp Borgers 					u32_encode_bits(stbc,
2208549fdd34SPhilipp Borgers 							IEEE80211_TX_CTL_STBC);
2209549fdd34SPhilipp Borgers 			}
2210dfdfc2beSSven Eckelmann 			break;
2211dfdfc2beSSven Eckelmann 
2212646e76bbSLorenzo Bianconi 		case IEEE80211_RADIOTAP_VHT:
2213646e76bbSLorenzo Bianconi 			vht_known = get_unaligned_le16(iterator.this_arg);
2214646e76bbSLorenzo Bianconi 			rate_found = true;
2215646e76bbSLorenzo Bianconi 
2216646e76bbSLorenzo Bianconi 			rate_flags = IEEE80211_TX_RC_VHT_MCS;
2217646e76bbSLorenzo Bianconi 			if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) &&
2218646e76bbSLorenzo Bianconi 			    (iterator.this_arg[2] &
2219646e76bbSLorenzo Bianconi 			     IEEE80211_RADIOTAP_VHT_FLAG_SGI))
2220646e76bbSLorenzo Bianconi 				rate_flags |= IEEE80211_TX_RC_SHORT_GI;
2221646e76bbSLorenzo Bianconi 			if (vht_known &
2222646e76bbSLorenzo Bianconi 			    IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) {
2223646e76bbSLorenzo Bianconi 				if (iterator.this_arg[3] == 1)
2224646e76bbSLorenzo Bianconi 					rate_flags |=
2225646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_40_MHZ_WIDTH;
2226646e76bbSLorenzo Bianconi 				else if (iterator.this_arg[3] == 4)
2227646e76bbSLorenzo Bianconi 					rate_flags |=
2228646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_80_MHZ_WIDTH;
2229646e76bbSLorenzo Bianconi 				else if (iterator.this_arg[3] == 11)
2230646e76bbSLorenzo Bianconi 					rate_flags |=
2231646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_160_MHZ_WIDTH;
2232646e76bbSLorenzo Bianconi 			}
2233646e76bbSLorenzo Bianconi 
2234646e76bbSLorenzo Bianconi 			vht_mcs = iterator.this_arg[4] >> 4;
223513cb6d82SLorenzo Bianconi 			if (vht_mcs > 11)
223613cb6d82SLorenzo Bianconi 				vht_mcs = 0;
2237646e76bbSLorenzo Bianconi 			vht_nss = iterator.this_arg[4] & 0xF;
223813cb6d82SLorenzo Bianconi 			if (!vht_nss || vht_nss > 8)
223913cb6d82SLorenzo Bianconi 				vht_nss = 1;
2240646e76bbSLorenzo Bianconi 			break;
2241646e76bbSLorenzo Bianconi 
224273b9f03aSJohannes Berg 		/*
224373b9f03aSJohannes Berg 		 * Please update the file
2244429ff87bSMauro Carvalho Chehab 		 * Documentation/networking/mac80211-injection.rst
224573b9f03aSJohannes Berg 		 * when parsing new fields here.
224673b9f03aSJohannes Berg 		 */
224773b9f03aSJohannes Berg 
224873b9f03aSJohannes Berg 		default:
224973b9f03aSJohannes Berg 			break;
225073b9f03aSJohannes Berg 		}
225173b9f03aSJohannes Berg 	}
225273b9f03aSJohannes Berg 
225373b9f03aSJohannes Berg 	if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
225473b9f03aSJohannes Berg 		return false;
225573b9f03aSJohannes Berg 
2256dfdfc2beSSven Eckelmann 	if (rate_found) {
2257bddc0c41SMathy Vanhoef 		struct ieee80211_supported_band *sband =
2258bddc0c41SMathy Vanhoef 			local->hw.wiphy->bands[info->band];
2259bddc0c41SMathy Vanhoef 
2260dfdfc2beSSven Eckelmann 		info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
2261dfdfc2beSSven Eckelmann 
2262dfdfc2beSSven Eckelmann 		for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
2263dfdfc2beSSven Eckelmann 			info->control.rates[i].idx = -1;
2264dfdfc2beSSven Eckelmann 			info->control.rates[i].flags = 0;
2265dfdfc2beSSven Eckelmann 			info->control.rates[i].count = 0;
2266dfdfc2beSSven Eckelmann 		}
2267dfdfc2beSSven Eckelmann 
2268dfdfc2beSSven Eckelmann 		if (rate_flags & IEEE80211_TX_RC_MCS) {
2269dfdfc2beSSven Eckelmann 			info->control.rates[0].idx = rate;
2270646e76bbSLorenzo Bianconi 		} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
2271646e76bbSLorenzo Bianconi 			ieee80211_rate_set_vht(info->control.rates, vht_mcs,
2272646e76bbSLorenzo Bianconi 					       vht_nss);
2273bddc0c41SMathy Vanhoef 		} else if (sband) {
2274dfdfc2beSSven Eckelmann 			for (i = 0; i < sband->n_bitrates; i++) {
2275dfdfc2beSSven Eckelmann 				if (rate * 5 != sband->bitrates[i].bitrate)
2276dfdfc2beSSven Eckelmann 					continue;
2277dfdfc2beSSven Eckelmann 
2278dfdfc2beSSven Eckelmann 				info->control.rates[0].idx = i;
2279dfdfc2beSSven Eckelmann 				break;
2280dfdfc2beSSven Eckelmann 			}
2281dfdfc2beSSven Eckelmann 		}
2282dfdfc2beSSven Eckelmann 
228307310a63SFelix Fietkau 		if (info->control.rates[0].idx < 0)
228407310a63SFelix Fietkau 			info->control.flags &= ~IEEE80211_TX_CTRL_RATE_INJECT;
228507310a63SFelix Fietkau 
2286dfdfc2beSSven Eckelmann 		info->control.rates[0].flags = rate_flags;
2287dfdfc2beSSven Eckelmann 		info->control.rates[0].count = min_t(u8, rate_retries + 1,
2288dfdfc2beSSven Eckelmann 						     local->hw.max_rate_tries);
2289dfdfc2beSSven Eckelmann 	}
2290dfdfc2beSSven Eckelmann 
229173b9f03aSJohannes Berg 	return true;
229273b9f03aSJohannes Berg }
229373b9f03aSJohannes Berg 
ieee80211_monitor_start_xmit(struct sk_buff * skb,struct net_device * dev)2294d0cf9c0dSStephen Hemminger netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
2295e2ebc74dSJohannes Berg 					 struct net_device *dev)
2296e2ebc74dSJohannes Berg {
2297e2ebc74dSJohannes Berg 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
229855de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
22993b8d81e0SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2300f75f5c6fSHelmut Schaa 	struct ieee80211_hdr *hdr;
23015d9cf4a5SJohannes Berg 	struct ieee80211_sub_if_data *tmp_sdata, *sdata;
2302b4932836SJanusz Dziedzic 	struct cfg80211_chan_def *chandef;
23039b8a74e3SAndy Green 	u16 len_rthdr;
23045d9cf4a5SJohannes Berg 	int hdrlen;
2305e2ebc74dSJohannes Berg 
2306c95014e1SAlexander Wetzel 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2307c95014e1SAlexander Wetzel 	if (unlikely(!ieee80211_sdata_running(sdata)))
2308c95014e1SAlexander Wetzel 		goto fail;
2309c95014e1SAlexander Wetzel 
2310cb17ed29SMathy Vanhoef 	memset(info, 0, sizeof(*info));
2311cb17ed29SMathy Vanhoef 	info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
2312cb17ed29SMathy Vanhoef 		      IEEE80211_TX_CTL_INJECTED;
23139b8a74e3SAndy Green 
2314bddc0c41SMathy Vanhoef 	/* Sanity-check the length of the radiotap header */
2315bddc0c41SMathy Vanhoef 	if (!ieee80211_validate_radiotap_len(skb))
2316cb17ed29SMathy Vanhoef 		goto fail;
23179b8a74e3SAndy Green 
2318cb17ed29SMathy Vanhoef 	/* we now know there is a radiotap header with a length we can use */
23199b8a74e3SAndy Green 	len_rthdr = ieee80211_get_radiotap_len(skb->data);
23209b8a74e3SAndy Green 
2321e2ebc74dSJohannes Berg 	/*
2322e2ebc74dSJohannes Berg 	 * fix up the pointers accounting for the radiotap
2323e2ebc74dSJohannes Berg 	 * header still being in there.  We are being given
2324e2ebc74dSJohannes Berg 	 * a precooked IEEE80211 header so no need for
2325e2ebc74dSJohannes Berg 	 * normal processing
2326e2ebc74dSJohannes Berg 	 */
23279b8a74e3SAndy Green 	skb_set_mac_header(skb, len_rthdr);
2328e2ebc74dSJohannes Berg 	/*
23299b8a74e3SAndy Green 	 * these are just fixed to the end of the rt area since we
23309b8a74e3SAndy Green 	 * don't have any better information and at this point, nobody cares
2331e2ebc74dSJohannes Berg 	 */
23329b8a74e3SAndy Green 	skb_set_network_header(skb, len_rthdr);
23339b8a74e3SAndy Green 	skb_set_transport_header(skb, len_rthdr);
2334e2ebc74dSJohannes Berg 
23355d9cf4a5SJohannes Berg 	if (skb->len < len_rthdr + 2)
23365d9cf4a5SJohannes Berg 		goto fail;
23375d9cf4a5SJohannes Berg 
23385d9cf4a5SJohannes Berg 	hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
23395d9cf4a5SJohannes Berg 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
23405d9cf4a5SJohannes Berg 
23415d9cf4a5SJohannes Berg 	if (skb->len < len_rthdr + hdrlen)
23425d9cf4a5SJohannes Berg 		goto fail;
23435d9cf4a5SJohannes Berg 
2344f75f5c6fSHelmut Schaa 	/*
2345f75f5c6fSHelmut Schaa 	 * Initialize skb->protocol if the injected frame is a data frame
2346f75f5c6fSHelmut Schaa 	 * carrying a rfc1042 header
2347f75f5c6fSHelmut Schaa 	 */
2348f75f5c6fSHelmut Schaa 	if (ieee80211_is_data(hdr->frame_control) &&
23495d9cf4a5SJohannes Berg 	    skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) {
23505d9cf4a5SJohannes Berg 		u8 *payload = (u8 *)hdr + hdrlen;
23515d9cf4a5SJohannes Berg 
2352b203ca39SJoe Perches 		if (ether_addr_equal(payload, rfc1042_header))
2353f75f5c6fSHelmut Schaa 			skb->protocol = cpu_to_be16((payload[6] << 8) |
2354f75f5c6fSHelmut Schaa 						    payload[7]);
2355f75f5c6fSHelmut Schaa 	}
2356f75f5c6fSHelmut Schaa 
23575d9cf4a5SJohannes Berg 	rcu_read_lock();
23585d9cf4a5SJohannes Berg 
23595d9cf4a5SJohannes Berg 	/*
23605d9cf4a5SJohannes Berg 	 * We process outgoing injected frames that have a local address
23615d9cf4a5SJohannes Berg 	 * we handle as though they are non-injected frames.
23625d9cf4a5SJohannes Berg 	 * This code here isn't entirely correct, the local MAC address
23635d9cf4a5SJohannes Berg 	 * isn't always enough to find the interface to use; for proper
236470d9c599SJohannes Berg 	 * VLAN support we have an nl80211-based mechanism.
2365b226a826SJohannes Berg 	 *
2366b226a826SJohannes Berg 	 * This is necessary, for example, for old hostapd versions that
2367b226a826SJohannes Berg 	 * don't use nl80211-based management TX/RX.
23685d9cf4a5SJohannes Berg 	 */
23695d9cf4a5SJohannes Berg 	list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) {
23705d9cf4a5SJohannes Berg 		if (!ieee80211_sdata_running(tmp_sdata))
23715d9cf4a5SJohannes Berg 			continue;
23725d9cf4a5SJohannes Berg 		if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
237370d9c599SJohannes Berg 		    tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
23745d9cf4a5SJohannes Berg 			continue;
2375b203ca39SJoe Perches 		if (ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) {
23765d9cf4a5SJohannes Berg 			sdata = tmp_sdata;
23775d9cf4a5SJohannes Berg 			break;
23785d9cf4a5SJohannes Berg 		}
23795d9cf4a5SJohannes Berg 	}
23807351c6bdSJohannes Berg 
2381d0a9123eSJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
238255de908aSJohannes Berg 	if (!chanctx_conf) {
238355de908aSJohannes Berg 		tmp_sdata = rcu_dereference(local->monitor_sdata);
238455de908aSJohannes Berg 		if (tmp_sdata)
238555de908aSJohannes Berg 			chanctx_conf =
2386d0a9123eSJohannes Berg 				rcu_dereference(tmp_sdata->vif.bss_conf.chanctx_conf);
238755de908aSJohannes Berg 	}
238855de908aSJohannes Berg 
2389b4a7ff75SFelix Fietkau 	if (chanctx_conf)
2390b4932836SJanusz Dziedzic 		chandef = &chanctx_conf->def;
2391b4a7ff75SFelix Fietkau 	else if (!local->use_chanctx)
2392b4932836SJanusz Dziedzic 		chandef = &local->_oper_chandef;
2393b4a7ff75SFelix Fietkau 	else
2394b4a7ff75SFelix Fietkau 		goto fail_rcu;
239555de908aSJohannes Berg 
239655de908aSJohannes Berg 	/*
239755de908aSJohannes Berg 	 * Frame injection is not allowed if beaconing is not allowed
239855de908aSJohannes Berg 	 * or if we need radar detection. Beaconing is usually not allowed when
239955de908aSJohannes Berg 	 * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
240055de908aSJohannes Berg 	 * Passive scan is also used in world regulatory domains where
240155de908aSJohannes Berg 	 * your country is not known and as such it should be treated as
240255de908aSJohannes Berg 	 * NO TX unless the channel is explicitly allowed in which case
240355de908aSJohannes Berg 	 * your current regulatory domain would not have the passive scan
240455de908aSJohannes Berg 	 * flag.
240555de908aSJohannes Berg 	 *
240655de908aSJohannes Berg 	 * Since AP mode uses monitor interfaces to inject/TX management
240755de908aSJohannes Berg 	 * frames we can make AP mode the exception to this rule once it
240855de908aSJohannes Berg 	 * supports radar detection as its implementation can deal with
240955de908aSJohannes Berg 	 * radar detection by itself. We can do that later by adding a
241055de908aSJohannes Berg 	 * monitor flag interfaces used for AP support.
241155de908aSJohannes Berg 	 */
2412b4932836SJanusz Dziedzic 	if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
2413b4932836SJanusz Dziedzic 				     sdata->vif.type))
241455de908aSJohannes Berg 		goto fail_rcu;
241555de908aSJohannes Berg 
241673c4e195SJohannes Berg 	info->band = chandef->chan->band;
2417109843b0SLorenzo Bianconi 
241896a7109aSJohan Almbladh 	/* Initialize skb->priority according to frame type and TID class,
241996a7109aSJohan Almbladh 	 * with respect to the sub interface that the frame will actually
242096a7109aSJohan Almbladh 	 * be transmitted on. If the DONT_REORDER flag is set, the original
242196a7109aSJohan Almbladh 	 * skb-priority is preserved to assure frames injected with this
242296a7109aSJohan Almbladh 	 * flag are not reordered relative to each other.
242396a7109aSJohan Almbladh 	 */
242496a7109aSJohan Almbladh 	ieee80211_select_queue_80211(sdata, skb, hdr);
242596a7109aSJohan Almbladh 	skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority));
242696a7109aSJohan Almbladh 
2427bddc0c41SMathy Vanhoef 	/*
2428bddc0c41SMathy Vanhoef 	 * Process the radiotap header. This will now take into account the
2429bddc0c41SMathy Vanhoef 	 * selected chandef above to accurately set injection rates and
2430bddc0c41SMathy Vanhoef 	 * retransmissions.
2431bddc0c41SMathy Vanhoef 	 */
2432bddc0c41SMathy Vanhoef 	if (!ieee80211_parse_tx_radiotap(skb, dev))
2433bddc0c41SMathy Vanhoef 		goto fail_rcu;
2434bddc0c41SMathy Vanhoef 
2435cb17ed29SMathy Vanhoef 	/* remove the injection radiotap header */
2436cb17ed29SMathy Vanhoef 	skb_pull(skb, len_rthdr);
2437109843b0SLorenzo Bianconi 
243808aca29aSMathy Vanhoef 	ieee80211_xmit(sdata, NULL, skb);
24395d9cf4a5SJohannes Berg 	rcu_read_unlock();
24405d9cf4a5SJohannes Berg 
2441e2ebc74dSJohannes Berg 	return NETDEV_TX_OK;
24429b8a74e3SAndy Green 
244355de908aSJohannes Berg fail_rcu:
244455de908aSJohannes Berg 	rcu_read_unlock();
24459b8a74e3SAndy Green fail:
24469b8a74e3SAndy Green 	dev_kfree_skb(skb);
24479b8a74e3SAndy Green 	return NETDEV_TX_OK; /* meaning, we dealt with the skb */
2448e2ebc74dSJohannes Berg }
2449e2ebc74dSJohannes Berg 
ieee80211_is_tdls_setup(struct sk_buff * skb)245097ffe757SJohannes Berg static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
2451ad38bfc9SMatti Gottlieb {
245297ffe757SJohannes Berg 	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
2453ad38bfc9SMatti Gottlieb 
245497ffe757SJohannes Berg 	return ethertype == ETH_P_TDLS &&
245597ffe757SJohannes Berg 	       skb->len > 14 &&
245697ffe757SJohannes Berg 	       skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
245797ffe757SJohannes Berg }
245897ffe757SJohannes Berg 
ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,struct sta_info ** sta_out)245950ff477aSJohn Crispin int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
246097ffe757SJohannes Berg 			    struct sk_buff *skb,
246197ffe757SJohannes Berg 			    struct sta_info **sta_out)
246297ffe757SJohannes Berg {
246397ffe757SJohannes Berg 	struct sta_info *sta;
246497ffe757SJohannes Berg 
246597ffe757SJohannes Berg 	switch (sdata->vif.type) {
246697ffe757SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
246797ffe757SJohannes Berg 		sta = rcu_dereference(sdata->u.vlan.sta);
246897ffe757SJohannes Berg 		if (sta) {
246997ffe757SJohannes Berg 			*sta_out = sta;
247097ffe757SJohannes Berg 			return 0;
247197ffe757SJohannes Berg 		} else if (sdata->wdev.use_4addr) {
247297ffe757SJohannes Berg 			return -ENOLINK;
247397ffe757SJohannes Berg 		}
2474fc0561dcSGustavo A. R. Silva 		fallthrough;
247597ffe757SJohannes Berg 	case NL80211_IFTYPE_AP:
247697ffe757SJohannes Berg 	case NL80211_IFTYPE_OCB:
247797ffe757SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
247897ffe757SJohannes Berg 		if (is_multicast_ether_addr(skb->data)) {
247997ffe757SJohannes Berg 			*sta_out = ERR_PTR(-ENOENT);
248097ffe757SJohannes Berg 			return 0;
248197ffe757SJohannes Berg 		}
248297ffe757SJohannes Berg 		sta = sta_info_get_bss(sdata, skb->data);
248397ffe757SJohannes Berg 		break;
248497ffe757SJohannes Berg #ifdef CONFIG_MAC80211_MESH
248597ffe757SJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
248697ffe757SJohannes Berg 		/* determined much later */
248797ffe757SJohannes Berg 		*sta_out = NULL;
248897ffe757SJohannes Berg 		return 0;
248997ffe757SJohannes Berg #endif
249097ffe757SJohannes Berg 	case NL80211_IFTYPE_STATION:
249197ffe757SJohannes Berg 		if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
249297ffe757SJohannes Berg 			sta = sta_info_get(sdata, skb->data);
249311d62cafSJohannes Berg 			if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
249411d62cafSJohannes Berg 				if (test_sta_flag(sta,
249511d62cafSJohannes Berg 						  WLAN_STA_TDLS_PEER_AUTH)) {
249697ffe757SJohannes Berg 					*sta_out = sta;
249797ffe757SJohannes Berg 					return 0;
249897ffe757SJohannes Berg 				}
249997ffe757SJohannes Berg 
250097ffe757SJohannes Berg 				/*
250197ffe757SJohannes Berg 				 * TDLS link during setup - throw out frames to
250297ffe757SJohannes Berg 				 * peer. Allow TDLS-setup frames to unauthorized
250397ffe757SJohannes Berg 				 * peers for the special case of a link teardown
250497ffe757SJohannes Berg 				 * after a TDLS sta is removed due to being
250597ffe757SJohannes Berg 				 * unreachable.
250697ffe757SJohannes Berg 				 */
250711d62cafSJohannes Berg 				if (!ieee80211_is_tdls_setup(skb))
250897ffe757SJohannes Berg 					return -EINVAL;
250997ffe757SJohannes Berg 			}
251097ffe757SJohannes Berg 
251197ffe757SJohannes Berg 		}
251297ffe757SJohannes Berg 
251381151ce4SJohannes Berg 		sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
251497ffe757SJohannes Berg 		if (!sta)
251597ffe757SJohannes Berg 			return -ENOLINK;
251697ffe757SJohannes Berg 		break;
251797ffe757SJohannes Berg 	default:
251897ffe757SJohannes Berg 		return -EINVAL;
251997ffe757SJohannes Berg 	}
252097ffe757SJohannes Berg 
252197ffe757SJohannes Berg 	*sta_out = sta ?: ERR_PTR(-ENOENT);
252297ffe757SJohannes Berg 	return 0;
2523ad38bfc9SMatti Gottlieb }
2524ad38bfc9SMatti Gottlieb 
ieee80211_store_ack_skb(struct ieee80211_local * local,struct sk_buff * skb,u32 * info_flags,u64 * cookie)2525a7528198SMarkus Theil static u16 ieee80211_store_ack_skb(struct ieee80211_local *local,
25265d8983c8SJohn Crispin 				   struct sk_buff *skb,
2527a7528198SMarkus Theil 				   u32 *info_flags,
2528a7528198SMarkus Theil 				   u64 *cookie)
25295d8983c8SJohn Crispin {
2530a7528198SMarkus Theil 	struct sk_buff *ack_skb;
25315d8983c8SJohn Crispin 	u16 info_id = 0;
25325d8983c8SJohn Crispin 
2533a7528198SMarkus Theil 	if (skb->sk)
2534a7528198SMarkus Theil 		ack_skb = skb_clone_sk(skb);
2535a7528198SMarkus Theil 	else
2536a7528198SMarkus Theil 		ack_skb = skb_clone(skb, GFP_ATOMIC);
2537a7528198SMarkus Theil 
25385d8983c8SJohn Crispin 	if (ack_skb) {
25395d8983c8SJohn Crispin 		unsigned long flags;
25405d8983c8SJohn Crispin 		int id;
25415d8983c8SJohn Crispin 
25425d8983c8SJohn Crispin 		spin_lock_irqsave(&local->ack_status_lock, flags);
25435d8983c8SJohn Crispin 		id = idr_alloc(&local->ack_status_frames, ack_skb,
2544f2b18bacSJohannes Berg 			       1, 0x2000, GFP_ATOMIC);
25455d8983c8SJohn Crispin 		spin_unlock_irqrestore(&local->ack_status_lock, flags);
25465d8983c8SJohn Crispin 
25475d8983c8SJohn Crispin 		if (id >= 0) {
25485d8983c8SJohn Crispin 			info_id = id;
25495d8983c8SJohn Crispin 			*info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
2550a7528198SMarkus Theil 			if (cookie) {
2551a7528198SMarkus Theil 				*cookie = ieee80211_mgmt_tx_cookie(local);
2552a7528198SMarkus Theil 				IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie;
2553a7528198SMarkus Theil 			}
25545d8983c8SJohn Crispin 		} else {
25555d8983c8SJohn Crispin 			kfree_skb(ack_skb);
25565d8983c8SJohn Crispin 		}
25575d8983c8SJohn Crispin 	}
25585d8983c8SJohn Crispin 
25595d8983c8SJohn Crispin 	return info_id;
25605d8983c8SJohn Crispin }
25615d8983c8SJohn Crispin 
2562e2ebc74dSJohannes Berg /**
25634c9451edSJohannes Berg  * ieee80211_build_hdr - build 802.11 header in the given frame
25644c9451edSJohannes Berg  * @sdata: virtual interface to build the header for
25654c9451edSJohannes Berg  * @skb: the skb to build the header in
256624d342c5SLiad Kaufman  * @info_flags: skb flags to set
2567f0daf54fSJohannes Berg  * @sta: the station pointer
256806016772SRajkumar Manoharan  * @ctrl_flags: info control flags to set
2569f0daf54fSJohannes Berg  * @cookie: cookie pointer to fill (if not %NULL)
2570e2ebc74dSJohannes Berg  *
25714c9451edSJohannes Berg  * This function takes the skb with 802.3 header and reformats the header to
25724c9451edSJohannes Berg  * the appropriate IEEE 802.11 header based on which interface the packet is
25734c9451edSJohannes Berg  * being transmitted on.
2574e2ebc74dSJohannes Berg  *
25754c9451edSJohannes Berg  * Note that this function also takes care of the TX status request and
25764c9451edSJohannes Berg  * potential unsharing of the SKB - this needs to be interleaved with the
25774c9451edSJohannes Berg  * header building.
25784c9451edSJohannes Berg  *
25794c9451edSJohannes Berg  * The function requires the read-side RCU lock held
25804c9451edSJohannes Berg  *
25814c9451edSJohannes Berg  * Returns: the (possibly reallocated) skb or an ERR_PTR() code
2582e2ebc74dSJohannes Berg  */
ieee80211_build_hdr(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,u32 info_flags,struct sta_info * sta,u32 ctrl_flags,u64 * cookie)25834c9451edSJohannes Berg static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
25847c10770fSJohannes Berg 					   struct sk_buff *skb, u32 info_flags,
2585a7528198SMarkus Theil 					   struct sta_info *sta, u32 ctrl_flags,
2586a7528198SMarkus Theil 					   u64 *cookie)
2587e2ebc74dSJohannes Berg {
2588133b8226SJohannes Berg 	struct ieee80211_local *local = sdata->local;
2589489ee919SFelix Fietkau 	struct ieee80211_tx_info *info;
2590dcf33963SJohannes Berg 	int head_need;
2591065e9605SHarvey Harrison 	u16 ethertype, hdrlen,  meshhdrlen = 0;
2592065e9605SHarvey Harrison 	__le16 fc;
2593e2ebc74dSJohannes Berg 	struct ieee80211_hdr hdr;
2594ff67bb86SWey-Yi Guy 	struct ieee80211s_hdr mesh_hdr __maybe_unused;
2595b8bacc18SChun-Yeow Yeoh 	struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
2596e2ebc74dSJohannes Berg 	const u8 *encaps_data;
2597e2ebc74dSJohannes Berg 	int encaps_len, skip_header_bytes;
259897ffe757SJohannes Berg 	bool wme_sta = false, authorized = false;
259997ffe757SJohannes Berg 	bool tdls_peer;
2600a729cff8SJohannes Berg 	bool multicast;
2601a729cff8SJohannes Berg 	u16 info_id = 0;
2602eef25a66SJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf = NULL;
260357fbcce3SJohannes Berg 	enum nl80211_band band;
26044c9451edSJohannes Berg 	int ret;
2605963d0e8dSJohannes Berg 	u8 link_id = u32_get_bits(ctrl_flags, IEEE80211_TX_CTRL_MLO_LINK);
2606e2ebc74dSJohannes Berg 
260797ffe757SJohannes Berg 	if (IS_ERR(sta))
260897ffe757SJohannes Berg 		sta = NULL;
260997ffe757SJohannes Berg 
2610276d9e82SJulius Niedworok #ifdef CONFIG_MAC80211_DEBUGFS
2611276d9e82SJulius Niedworok 	if (local->force_tx_status)
2612276d9e82SJulius Niedworok 		info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
2613276d9e82SJulius Niedworok #endif
2614276d9e82SJulius Niedworok 
2615e2ebc74dSJohannes Berg 	/* convert Ethernet header to proper 802.11 header (based on
2616e2ebc74dSJohannes Berg 	 * operation mode) */
2617e2ebc74dSJohannes Berg 	ethertype = (skb->data[12] << 8) | skb->data[13];
2618065e9605SHarvey Harrison 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
2619e2ebc74dSJohannes Berg 
2620f1871abdSIlan Peer 	if (!ieee80211_vif_is_mld(&sdata->vif))
2621eef25a66SJohannes Berg 		chanctx_conf =
2622eef25a66SJohannes Berg 			rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
262327f852deSJohannes Berg 
262451fb61e7SJohannes Berg 	switch (sdata->vif.type) {
262505c914feSJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
262697ffe757SJohannes Berg 		if (sdata->wdev.use_4addr) {
2627f14543eeSFelix Fietkau 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
2628f14543eeSFelix Fietkau 			/* RA TA DA SA */
2629f14543eeSFelix Fietkau 			memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
263047846c9bSJohannes Berg 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2631f14543eeSFelix Fietkau 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2632f14543eeSFelix Fietkau 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
2633f14543eeSFelix Fietkau 			hdrlen = 30;
2634c2c98fdeSJohannes Berg 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
2635a74a8c84SJohannes Berg 			wme_sta = sta->sta.wme;
2636f14543eeSFelix Fietkau 		}
2637f1871abdSIlan Peer 		if (!ieee80211_vif_is_mld(&sdata->vif)) {
2638eef25a66SJohannes Berg 			struct ieee80211_sub_if_data *ap_sdata;
2639eef25a66SJohannes Berg 
264027f852deSJohannes Berg 			/* override chanctx_conf from AP (we don't have one) */
2641eef25a66SJohannes Berg 			ap_sdata = container_of(sdata->bss,
2642eef25a66SJohannes Berg 						struct ieee80211_sub_if_data,
264355de908aSJohannes Berg 						u.ap);
2644eef25a66SJohannes Berg 			chanctx_conf =
2645eef25a66SJohannes Berg 				rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf);
2646eef25a66SJohannes Berg 		}
264797ffe757SJohannes Berg 		if (sdata->wdev.use_4addr)
2648f14543eeSFelix Fietkau 			break;
2649fc0561dcSGustavo A. R. Silva 		fallthrough;
2650f14543eeSFelix Fietkau 	case NL80211_IFTYPE_AP:
2651065e9605SHarvey Harrison 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
2652e2ebc74dSJohannes Berg 		/* DA BSSID SA */
2653e2ebc74dSJohannes Berg 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
26543e0278b7SAndrei Otcheretianski 
2655f1871abdSIlan Peer 		if (ieee80211_vif_is_mld(&sdata->vif) && sta && !sta->sta.mlo) {
26563e0278b7SAndrei Otcheretianski 			struct ieee80211_link_data *link;
26573e0278b7SAndrei Otcheretianski 
26583e0278b7SAndrei Otcheretianski 			link_id = sta->deflink.link_id;
26593e0278b7SAndrei Otcheretianski 			link = rcu_dereference(sdata->link[link_id]);
26603e0278b7SAndrei Otcheretianski 			if (WARN_ON(!link)) {
26613e0278b7SAndrei Otcheretianski 				ret = -ENOLINK;
26623e0278b7SAndrei Otcheretianski 				goto free;
26633e0278b7SAndrei Otcheretianski 			}
26643e0278b7SAndrei Otcheretianski 			memcpy(hdr.addr2, link->conf->addr, ETH_ALEN);
2665a6ba64d0SJohannes Berg 		} else if (link_id == IEEE80211_LINK_UNSPECIFIED ||
2666a6ba64d0SJohannes Berg 			   (sta && sta->sta.mlo)) {
266747846c9bSJohannes Berg 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2668963d0e8dSJohannes Berg 		} else {
2669963d0e8dSJohannes Berg 			struct ieee80211_bss_conf *conf;
2670963d0e8dSJohannes Berg 
2671963d0e8dSJohannes Berg 			conf = rcu_dereference(sdata->vif.link_conf[link_id]);
2672963d0e8dSJohannes Berg 			if (unlikely(!conf)) {
2673963d0e8dSJohannes Berg 				ret = -ENOLINK;
2674963d0e8dSJohannes Berg 				goto free;
2675963d0e8dSJohannes Berg 			}
2676963d0e8dSJohannes Berg 
2677963d0e8dSJohannes Berg 			memcpy(hdr.addr2, conf->addr, ETH_ALEN);
26783e0278b7SAndrei Otcheretianski 		}
26793e0278b7SAndrei Otcheretianski 
2680e2ebc74dSJohannes Berg 		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
2681e2ebc74dSJohannes Berg 		hdrlen = 24;
2682cf966838SJohannes Berg 		break;
268333b64eb2SLuis Carlos Cobo #ifdef CONFIG_MAC80211_MESH
268405c914feSJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
2685b8bacc18SChun-Yeow Yeoh 		if (!is_multicast_ether_addr(skb->data)) {
2686163df6cfSChun-Yeow Yeoh 			struct sta_info *next_hop;
2687163df6cfSChun-Yeow Yeoh 			bool mpp_lookup = true;
2688163df6cfSChun-Yeow Yeoh 
2689bf7cd94dSJohannes Berg 			mpath = mesh_path_lookup(sdata, skb->data);
2690163df6cfSChun-Yeow Yeoh 			if (mpath) {
2691163df6cfSChun-Yeow Yeoh 				mpp_lookup = false;
2692163df6cfSChun-Yeow Yeoh 				next_hop = rcu_dereference(mpath->next_hop);
2693163df6cfSChun-Yeow Yeoh 				if (!next_hop ||
2694163df6cfSChun-Yeow Yeoh 				    !(mpath->flags & (MESH_PATH_ACTIVE |
2695163df6cfSChun-Yeow Yeoh 						      MESH_PATH_RESOLVING)))
2696163df6cfSChun-Yeow Yeoh 					mpp_lookup = true;
2697163df6cfSChun-Yeow Yeoh 			}
2698163df6cfSChun-Yeow Yeoh 
2699ab1c7906SHenning Rogge 			if (mpp_lookup) {
2700bf7cd94dSJohannes Berg 				mppath = mpp_path_lookup(sdata, skb->data);
2701ab1c7906SHenning Rogge 				if (mppath)
2702ab1c7906SHenning Rogge 					mppath->exp_time = jiffies;
2703ab1c7906SHenning Rogge 			}
2704163df6cfSChun-Yeow Yeoh 
2705163df6cfSChun-Yeow Yeoh 			if (mppath && mpath)
27062bdaf386SBob Copeland 				mesh_path_del(sdata, mpath->dst);
2707b8bacc18SChun-Yeow Yeoh 		}
270879617deeSYanBo 
2709f76b57b4SJoel A Fernandes 		/*
27109d52501bSJoel A Fernandes 		 * Use address extension if it is a packet from
27119d52501bSJoel A Fernandes 		 * another interface or if we know the destination
27129d52501bSJoel A Fernandes 		 * is being proxied by a portal (i.e. portal address
27139d52501bSJoel A Fernandes 		 * differs from proxied address)
2714f76b57b4SJoel A Fernandes 		 */
2715b203ca39SJoe Perches 		if (ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN) &&
2716b203ca39SJoe Perches 		    !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
27173c5772a5SJavier Cardona 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
27183c5772a5SJavier Cardona 					skb->data, skb->data + ETH_ALEN);
2719bf7cd94dSJohannes Berg 			meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr,
2720bf7cd94dSJohannes Berg 							       NULL, NULL);
272179617deeSYanBo 		} else {
272227f01124SThomas Pedersen 			/* DS -> MBSS (802.11-2012 13.11.3.3).
272327f01124SThomas Pedersen 			 * For unicast with unknown forwarding information,
272427f01124SThomas Pedersen 			 * destination might be in the MBSS or if that fails
272527f01124SThomas Pedersen 			 * forwarded to another mesh gate. In either case
272627f01124SThomas Pedersen 			 * resolution will be handled in ieee80211_xmit(), so
272727f01124SThomas Pedersen 			 * leave the original DA. This also works for mcast */
272827f01124SThomas Pedersen 			const u8 *mesh_da = skb->data;
272979617deeSYanBo 
273027f01124SThomas Pedersen 			if (mppath)
27313c5772a5SJavier Cardona 				mesh_da = mppath->mpp;
273227f01124SThomas Pedersen 			else if (mpath)
27337c41f315SChun-Yeow Yeoh 				mesh_da = mpath->dst;
273427f01124SThomas Pedersen 
27353c5772a5SJavier Cardona 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
273647846c9bSJohannes Berg 					mesh_da, sdata->vif.addr);
273727f01124SThomas Pedersen 			if (is_multicast_ether_addr(mesh_da))
273827f01124SThomas Pedersen 				/* DA TA mSA AE:SA */
2739bf7cd94dSJohannes Berg 				meshhdrlen = ieee80211_new_mesh_header(
2740bf7cd94dSJohannes Berg 						sdata, &mesh_hdr,
2741bf7cd94dSJohannes Berg 						skb->data + ETH_ALEN, NULL);
27423c5772a5SJavier Cardona 			else
274327f01124SThomas Pedersen 				/* RA TA mDA mSA AE:DA SA */
2744bf7cd94dSJohannes Berg 				meshhdrlen = ieee80211_new_mesh_header(
2745bf7cd94dSJohannes Berg 						sdata, &mesh_hdr, skb->data,
27463c5772a5SJavier Cardona 						skb->data + ETH_ALEN);
274779617deeSYanBo 
274879617deeSYanBo 		}
27498828f81aSRajkumar Manoharan 
27508828f81aSRajkumar Manoharan 		/* For injected frames, fill RA right away as nexthop lookup
27518828f81aSRajkumar Manoharan 		 * will be skipped.
27528828f81aSRajkumar Manoharan 		 */
27538828f81aSRajkumar Manoharan 		if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) &&
27548828f81aSRajkumar Manoharan 		    is_zero_ether_addr(hdr.addr1))
27558828f81aSRajkumar Manoharan 			memcpy(hdr.addr1, skb->data, ETH_ALEN);
275633b64eb2SLuis Carlos Cobo 		break;
275733b64eb2SLuis Carlos Cobo #endif
275805c914feSJohannes Berg 	case NL80211_IFTYPE_STATION:
275997ffe757SJohannes Berg 		/* we already did checks when looking up the RA STA */
276097ffe757SJohannes Berg 		tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
2761941c93cdSArik Nemtsov 
276297ffe757SJohannes Berg 		if (tdls_peer) {
27638cc07265SAbhishek Naik 			/* For TDLS only one link can be valid with peer STA */
27648cc07265SAbhishek Naik 			int tdls_link_id = sta->sta.valid_links ?
27658cc07265SAbhishek Naik 					   __ffs(sta->sta.valid_links) : 0;
27668cc07265SAbhishek Naik 			struct ieee80211_link_data *link;
27678cc07265SAbhishek Naik 
2768941c93cdSArik Nemtsov 			/* DA SA BSSID */
2769941c93cdSArik Nemtsov 			memcpy(hdr.addr1, skb->data, ETH_ALEN);
2770941c93cdSArik Nemtsov 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
27718cc07265SAbhishek Naik 			link = rcu_dereference(sdata->link[tdls_link_id]);
27728cc07265SAbhishek Naik 			if (WARN_ON_ONCE(!link)) {
27738cc07265SAbhishek Naik 				ret = -EINVAL;
27748cc07265SAbhishek Naik 				goto free;
27758cc07265SAbhishek Naik 			}
27768cc07265SAbhishek Naik 			memcpy(hdr.addr3, link->u.mgd.bssid, ETH_ALEN);
2777941c93cdSArik Nemtsov 			hdrlen = 24;
2778941c93cdSArik Nemtsov 		}  else if (sdata->u.mgd.use_4addr &&
2779a621fa4dSJohannes Berg 			    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
2780941c93cdSArik Nemtsov 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
2781941c93cdSArik Nemtsov 					  IEEE80211_FCTL_TODS);
2782f14543eeSFelix Fietkau 			/* RA TA DA SA */
2783bfd8403aSJohannes Berg 			memcpy(hdr.addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
278447846c9bSJohannes Berg 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2785f14543eeSFelix Fietkau 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2786f14543eeSFelix Fietkau 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
2787f14543eeSFelix Fietkau 			hdrlen = 30;
2788f14543eeSFelix Fietkau 		} else {
2789065e9605SHarvey Harrison 			fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
2790e2ebc74dSJohannes Berg 			/* BSSID SA DA */
27918a9be422SJohannes Berg 			memcpy(hdr.addr1, sdata->vif.cfg.ap_addr, ETH_ALEN);
2792e2ebc74dSJohannes Berg 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
2793e2ebc74dSJohannes Berg 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2794e2ebc74dSJohannes Berg 			hdrlen = 24;
2795f14543eeSFelix Fietkau 		}
2796cf966838SJohannes Berg 		break;
2797239281f8SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
2798239281f8SRostislav Lisovy 		/* DA SA BSSID */
2799239281f8SRostislav Lisovy 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
2800239281f8SRostislav Lisovy 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
2801239281f8SRostislav Lisovy 		eth_broadcast_addr(hdr.addr3);
2802239281f8SRostislav Lisovy 		hdrlen = 24;
2803239281f8SRostislav Lisovy 		break;
280405c914feSJohannes Berg 	case NL80211_IFTYPE_ADHOC:
2805e2ebc74dSJohannes Berg 		/* DA SA BSSID */
2806e2ebc74dSJohannes Berg 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
2807e2ebc74dSJohannes Berg 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
280846900298SJohannes Berg 		memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
2809e2ebc74dSJohannes Berg 		hdrlen = 24;
2810cf966838SJohannes Berg 		break;
2811cf966838SJohannes Berg 	default:
28124c9451edSJohannes Berg 		ret = -EINVAL;
28134c9451edSJohannes Berg 		goto free;
2814e2ebc74dSJohannes Berg 	}
2815e2ebc74dSJohannes Berg 
281627f852deSJohannes Berg 	if (!chanctx_conf) {
2817f1871abdSIlan Peer 		if (!ieee80211_vif_is_mld(&sdata->vif)) {
281827f852deSJohannes Berg 			ret = -ENOTCONN;
281927f852deSJohannes Berg 			goto free;
282027f852deSJohannes Berg 		}
2821eef25a66SJohannes Berg 		/* MLD transmissions must not rely on the band */
2822eef25a66SJohannes Berg 		band = 0;
2823eef25a66SJohannes Berg 	} else {
282427f852deSJohannes Berg 		band = chanctx_conf->def.chan->band;
2825eef25a66SJohannes Berg 	}
282627f852deSJohannes Berg 
2827a729cff8SJohannes Berg 	multicast = is_multicast_ether_addr(hdr.addr1);
282897ffe757SJohannes Berg 
282997ffe757SJohannes Berg 	/* sta is always NULL for mesh */
2830c2c98fdeSJohannes Berg 	if (sta) {
2831c2c98fdeSJohannes Berg 		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
2832a74a8c84SJohannes Berg 		wme_sta = sta->sta.wme;
283397ffe757SJohannes Berg 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
28344777be41SJavier Cardona 		/* For mesh, the use of the QoS header is mandatory */
2835c2c98fdeSJohannes Berg 		wme_sta = true;
283697ffe757SJohannes Berg 	}
28374777be41SJavier Cardona 
2838527871d7SJohannes Berg 	/* receiver does QoS (which also means we do) use it */
2839527871d7SJohannes Berg 	if (wme_sta) {
2840065e9605SHarvey Harrison 		fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
2841e2ebc74dSJohannes Berg 		hdrlen += 2;
2842e2ebc74dSJohannes Berg 	}
2843ce3edf6dSJohannes Berg 
2844ce3edf6dSJohannes Berg 	/*
2845238814fdSJohannes Berg 	 * Drop unicast frames to unauthorised stations unless they are
2846238814fdSJohannes Berg 	 * EAPOL frames from the local station.
2847ce3edf6dSJohannes Berg 	 */
284855182e4aSJohannes Berg 	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
2849239281f8SRostislav Lisovy 		     (sdata->vif.type != NL80211_IFTYPE_OCB) &&
2850a6ececf4SSergey Ryazanov 		     !multicast && !authorized &&
285155182e4aSJohannes Berg 		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
28520d5891e3SAndrei Otcheretianski 		      !ieee80211_is_our_addr(sdata, skb->data + ETH_ALEN, NULL)))) {
2853ce3edf6dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2854bdcbd8e0SJohannes Berg 		net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
28554c9451edSJohannes Berg 				    sdata->name, hdr.addr1);
2856ce3edf6dSJohannes Berg #endif
2857ce3edf6dSJohannes Berg 
2858ce3edf6dSJohannes Berg 		I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
2859ce3edf6dSJohannes Berg 
28604c9451edSJohannes Berg 		ret = -EPERM;
28614c9451edSJohannes Berg 		goto free;
2862e2ebc74dSJohannes Berg 	}
2863e2ebc74dSJohannes Berg 
2864a7528198SMarkus Theil 	if (unlikely(!multicast && ((skb->sk &&
2865a7528198SMarkus Theil 		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) ||
2866a7528198SMarkus Theil 		     ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS)))
2867a7528198SMarkus Theil 		info_id = ieee80211_store_ack_skb(local, skb, &info_flags,
2868a7528198SMarkus Theil 						  cookie);
2869a729cff8SJohannes Berg 
28707e244707SHelmut Schaa 	/*
28717e244707SHelmut Schaa 	 * If the skb is shared we need to obtain our own copy.
28727e244707SHelmut Schaa 	 */
2873a4926abbSRyder Lee 	skb = skb_share_check(skb, GFP_ATOMIC);
2874a4926abbSRyder Lee 	if (unlikely(!skb)) {
28754c9451edSJohannes Berg 		ret = -ENOMEM;
28764c9451edSJohannes Berg 		goto free;
28774c9451edSJohannes Berg 	}
28787e244707SHelmut Schaa 
2879065e9605SHarvey Harrison 	hdr.frame_control = fc;
2880e2ebc74dSJohannes Berg 	hdr.duration_id = 0;
2881e2ebc74dSJohannes Berg 	hdr.seq_ctrl = 0;
2882e2ebc74dSJohannes Berg 
2883e2ebc74dSJohannes Berg 	skip_header_bytes = ETH_HLEN;
2884e2ebc74dSJohannes Berg 	if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
2885e2ebc74dSJohannes Berg 		encaps_data = bridge_tunnel_header;
2886e2ebc74dSJohannes Berg 		encaps_len = sizeof(bridge_tunnel_header);
2887e2ebc74dSJohannes Berg 		skip_header_bytes -= 2;
2888e5c5d22eSSimon Horman 	} else if (ethertype >= ETH_P_802_3_MIN) {
2889e2ebc74dSJohannes Berg 		encaps_data = rfc1042_header;
2890e2ebc74dSJohannes Berg 		encaps_len = sizeof(rfc1042_header);
2891e2ebc74dSJohannes Berg 		skip_header_bytes -= 2;
2892e2ebc74dSJohannes Berg 	} else {
2893e2ebc74dSJohannes Berg 		encaps_data = NULL;
2894e2ebc74dSJohannes Berg 		encaps_len = 0;
2895e2ebc74dSJohannes Berg 	}
2896e2ebc74dSJohannes Berg 
2897e2ebc74dSJohannes Berg 	skb_pull(skb, skip_header_bytes);
289823c0752aSJohannes Berg 	head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
2899e2ebc74dSJohannes Berg 
290023c0752aSJohannes Berg 	/*
290123c0752aSJohannes Berg 	 * So we need to modify the skb header and hence need a copy of
290223c0752aSJohannes Berg 	 * that. The head_need variable above doesn't, so far, include
290323c0752aSJohannes Berg 	 * the needed header space that we don't need right away. If we
290423c0752aSJohannes Berg 	 * can, then we don't reallocate right now but only after the
290523c0752aSJohannes Berg 	 * frame arrives at the master device (if it does...)
290623c0752aSJohannes Berg 	 *
290723c0752aSJohannes Berg 	 * If we cannot, however, then we will reallocate to include all
290823c0752aSJohannes Berg 	 * the ever needed space. Also, if we need to reallocate it anyway,
290923c0752aSJohannes Berg 	 * make it big enough for everything we may ever need.
291023c0752aSJohannes Berg 	 */
2911e2ebc74dSJohannes Berg 
29123a5be7d4SDavid S. Miller 	if (head_need > 0 || skb_cloned(skb)) {
291323a5f0afSJohannes Berg 		head_need += IEEE80211_ENCRYPT_HEADROOM;
291423c0752aSJohannes Berg 		head_need += local->tx_headroom;
291523c0752aSJohannes Berg 		head_need = max_t(int, 0, head_need);
291614f46c1eSJohannes Berg 		if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
2917c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
29181c963becSJohannes Berg 			skb = NULL;
29194c9451edSJohannes Berg 			return ERR_PTR(-ENOMEM);
2920c3e7724bSFelix Fietkau 		}
2921e2ebc74dSJohannes Berg 	}
2922e2ebc74dSJohannes Berg 
2923eae4430eSFelix Fietkau 	if (encaps_data)
2924e2ebc74dSJohannes Berg 		memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
2925c29b9b9bSJohannes Berg 
2926e4ab7eb0SYuri Ershov #ifdef CONFIG_MAC80211_MESH
2927eae4430eSFelix Fietkau 	if (meshhdrlen > 0)
292833b64eb2SLuis Carlos Cobo 		memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
2929e4ab7eb0SYuri Ershov #endif
293033b64eb2SLuis Carlos Cobo 
2931065e9605SHarvey Harrison 	if (ieee80211_is_data_qos(fc)) {
2932c29b9b9bSJohannes Berg 		__le16 *qos_control;
2933c29b9b9bSJohannes Berg 
2934d58ff351SJohannes Berg 		qos_control = skb_push(skb, 2);
2935c29b9b9bSJohannes Berg 		memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
2936c29b9b9bSJohannes Berg 		/*
2937c29b9b9bSJohannes Berg 		 * Maybe we could actually set some fields here, for now just
2938c29b9b9bSJohannes Berg 		 * initialise to zero to indicate no special operation.
2939c29b9b9bSJohannes Berg 		 */
2940c29b9b9bSJohannes Berg 		*qos_control = 0;
2941c29b9b9bSJohannes Berg 	} else
2942e2ebc74dSJohannes Berg 		memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
2943c29b9b9bSJohannes Berg 
2944d57a544dSZhang Shengju 	skb_reset_mac_header(skb);
2945e2ebc74dSJohannes Berg 
2946489ee919SFelix Fietkau 	info = IEEE80211_SKB_CB(skb);
29473b8d81e0SJohannes Berg 	memset(info, 0, sizeof(*info));
29483b8d81e0SJohannes Berg 
2949a729cff8SJohannes Berg 	info->flags = info_flags;
2950a729cff8SJohannes Berg 	info->ack_frame_id = info_id;
295173c4e195SJohannes Berg 	info->band = band;
29529dd19538SJohannes Berg 
29539dd19538SJohannes Berg 	if (likely(!cookie)) {
29549dd19538SJohannes Berg 		ctrl_flags |= u32_encode_bits(link_id,
295569d41b5aSJohannes Berg 					      IEEE80211_TX_CTRL_MLO_LINK);
29569dd19538SJohannes Berg 	} else {
29579dd19538SJohannes Berg 		unsigned int pre_conf_link_id;
29589dd19538SJohannes Berg 
29599dd19538SJohannes Berg 		/*
29609dd19538SJohannes Berg 		 * ctrl_flags already have been set by
29619dd19538SJohannes Berg 		 * ieee80211_tx_control_port(), here
29629dd19538SJohannes Berg 		 * we just sanity check that
29639dd19538SJohannes Berg 		 */
29649dd19538SJohannes Berg 
29659dd19538SJohannes Berg 		pre_conf_link_id = u32_get_bits(ctrl_flags,
29669dd19538SJohannes Berg 						IEEE80211_TX_CTRL_MLO_LINK);
29679dd19538SJohannes Berg 
29689dd19538SJohannes Berg 		if (pre_conf_link_id != link_id &&
29699dd19538SJohannes Berg 		    link_id != IEEE80211_LINK_UNSPECIFIED) {
29709d13aff9SJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
29719dd19538SJohannes Berg 			net_info_ratelimited("%s: dropped frame to %pM with bad link ID request (%d vs. %d)\n",
29729dd19538SJohannes Berg 					     sdata->name, hdr.addr1,
29739dd19538SJohannes Berg 					     pre_conf_link_id, link_id);
29749dd19538SJohannes Berg #endif
29759dd19538SJohannes Berg 			ret = -EINVAL;
29769dd19538SJohannes Berg 			goto free;
29779dd19538SJohannes Berg 		}
29789dd19538SJohannes Berg 	}
29799dd19538SJohannes Berg 
29809dd19538SJohannes Berg 	info->control.flags = ctrl_flags;
2981a729cff8SJohannes Berg 
29824c9451edSJohannes Berg 	return skb;
29834c9451edSJohannes Berg  free:
29844c9451edSJohannes Berg 	kfree_skb(skb);
29854c9451edSJohannes Berg 	return ERR_PTR(ret);
2986e2ebc74dSJohannes Berg }
2987e2ebc74dSJohannes Berg 
298817c18bf8SJohannes Berg /*
298917c18bf8SJohannes Berg  * fast-xmit overview
299017c18bf8SJohannes Berg  *
299117c18bf8SJohannes Berg  * The core idea of this fast-xmit is to remove per-packet checks by checking
299217c18bf8SJohannes Berg  * them out of band. ieee80211_check_fast_xmit() implements the out-of-band
299317c18bf8SJohannes Berg  * checks that are needed to get the sta->fast_tx pointer assigned, after which
299417c18bf8SJohannes Berg  * much less work can be done per packet. For example, fragmentation must be
299517c18bf8SJohannes Berg  * disabled or the fast_tx pointer will not be set. All the conditions are seen
299617c18bf8SJohannes Berg  * in the code here.
299717c18bf8SJohannes Berg  *
299817c18bf8SJohannes Berg  * Once assigned, the fast_tx data structure also caches the per-packet 802.11
299917c18bf8SJohannes Berg  * header and other data to aid packet processing in ieee80211_xmit_fast().
300017c18bf8SJohannes Berg  *
300117c18bf8SJohannes Berg  * The most difficult part of this is that when any of these assumptions
300217c18bf8SJohannes Berg  * change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(),
300317c18bf8SJohannes Berg  * ieee80211_check_fast_xmit() or friends) is required to reset the data,
300417c18bf8SJohannes Berg  * since the per-packet code no longer checks the conditions. This is reflected
300517c18bf8SJohannes Berg  * by the calls to these functions throughout the rest of the code, and must be
300617c18bf8SJohannes Berg  * maintained if any of the TX path checks change.
300717c18bf8SJohannes Berg  */
300817c18bf8SJohannes Berg 
ieee80211_check_fast_xmit(struct sta_info * sta)300917c18bf8SJohannes Berg void ieee80211_check_fast_xmit(struct sta_info *sta)
301017c18bf8SJohannes Berg {
301117c18bf8SJohannes Berg 	struct ieee80211_fast_tx build = {}, *fast_tx = NULL, *old;
301217c18bf8SJohannes Berg 	struct ieee80211_local *local = sta->local;
301317c18bf8SJohannes Berg 	struct ieee80211_sub_if_data *sdata = sta->sdata;
301417c18bf8SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)build.hdr;
301517c18bf8SJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
301617c18bf8SJohannes Berg 	__le16 fc;
301717c18bf8SJohannes Berg 
301830686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
301917c18bf8SJohannes Berg 		return;
302017c18bf8SJohannes Berg 
3021d5edb9aeSFelix Fietkau 	if (ieee80211_vif_is_mesh(&sdata->vif))
3022d5edb9aeSFelix Fietkau 		mesh_fast_tx_flush_sta(sdata, sta);
3023d5edb9aeSFelix Fietkau 
302417c18bf8SJohannes Berg 	/* Locking here protects both the pointer itself, and against concurrent
302517c18bf8SJohannes Berg 	 * invocations winning data access races to, e.g., the key pointer that
302617c18bf8SJohannes Berg 	 * is used.
302717c18bf8SJohannes Berg 	 * Without it, the invocation of this function right after the key
302817c18bf8SJohannes Berg 	 * pointer changes wouldn't be sufficient, as another CPU could access
302917c18bf8SJohannes Berg 	 * the pointer, then stall, and then do the cache update after the CPU
303017c18bf8SJohannes Berg 	 * that invalidated the key.
303117c18bf8SJohannes Berg 	 * With the locking, such scenarios cannot happen as the check for the
303217c18bf8SJohannes Berg 	 * key and the fast-tx assignment are done atomically, so the CPU that
303317c18bf8SJohannes Berg 	 * modifies the key will either wait or other one will see the key
303417c18bf8SJohannes Berg 	 * cleared/changed already.
303517c18bf8SJohannes Berg 	 */
303617c18bf8SJohannes Berg 	spin_lock_bh(&sta->lock);
303730686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
303830686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) &&
303917c18bf8SJohannes Berg 	    sdata->vif.type == NL80211_IFTYPE_STATION)
304017c18bf8SJohannes Berg 		goto out;
304117c18bf8SJohannes Berg 
304254b79d87SFelix Fietkau 	if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded)
304317c18bf8SJohannes Berg 		goto out;
304417c18bf8SJohannes Berg 
304517c18bf8SJohannes Berg 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
304617c18bf8SJohannes Berg 	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
3047f7418bc1SFelix Fietkau 	    test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
3048f7418bc1SFelix Fietkau 	    test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
304917c18bf8SJohannes Berg 		goto out;
305017c18bf8SJohannes Berg 
305117c18bf8SJohannes Berg 	if (sdata->noack_map)
305217c18bf8SJohannes Berg 		goto out;
305317c18bf8SJohannes Berg 
305417c18bf8SJohannes Berg 	/* fast-xmit doesn't handle fragmentation at all */
3055725b812cSJohannes Berg 	if (local->hw.wiphy->frag_threshold != (u32)-1 &&
3056f3fe4e93SSara Sharon 	    !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
305717c18bf8SJohannes Berg 		goto out;
305817c18bf8SJohannes Berg 
3059f1871abdSIlan Peer 	if (!ieee80211_vif_is_mld(&sdata->vif)) {
306017c18bf8SJohannes Berg 		rcu_read_lock();
3061eef25a66SJohannes Berg 		chanctx_conf =
3062eef25a66SJohannes Berg 			rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
306317c18bf8SJohannes Berg 		if (!chanctx_conf) {
306417c18bf8SJohannes Berg 			rcu_read_unlock();
306517c18bf8SJohannes Berg 			goto out;
306617c18bf8SJohannes Berg 		}
306717c18bf8SJohannes Berg 		build.band = chanctx_conf->def.chan->band;
306817c18bf8SJohannes Berg 		rcu_read_unlock();
3069eef25a66SJohannes Berg 	} else {
3070eef25a66SJohannes Berg 		/* MLD transmissions must not rely on the band */
3071eef25a66SJohannes Berg 		build.band = 0;
3072eef25a66SJohannes Berg 	}
307317c18bf8SJohannes Berg 
307417c18bf8SJohannes Berg 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
307517c18bf8SJohannes Berg 
307617c18bf8SJohannes Berg 	switch (sdata->vif.type) {
30773ffd8840SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
30783ffd8840SJohannes Berg 		/* DA SA BSSID */
30793ffd8840SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr1);
30803ffd8840SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
30813ffd8840SJohannes Berg 		memcpy(hdr->addr3, sdata->u.ibss.bssid, ETH_ALEN);
30823ffd8840SJohannes Berg 		build.hdr_len = 24;
30833ffd8840SJohannes Berg 		break;
308417c18bf8SJohannes Berg 	case NL80211_IFTYPE_STATION:
308517c18bf8SJohannes Berg 		if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
30868cc07265SAbhishek Naik 			/* For TDLS only one link can be valid with peer STA */
30878cc07265SAbhishek Naik 			int tdls_link_id = sta->sta.valid_links ?
30888cc07265SAbhishek Naik 					   __ffs(sta->sta.valid_links) : 0;
30898cc07265SAbhishek Naik 			struct ieee80211_link_data *link;
30908cc07265SAbhishek Naik 
309117c18bf8SJohannes Berg 			/* DA SA BSSID */
309217c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr1);
309317c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
3094fc3432aeSJohannes Berg 			rcu_read_lock();
30958cc07265SAbhishek Naik 			link = rcu_dereference(sdata->link[tdls_link_id]);
3096fc3432aeSJohannes Berg 			if (!WARN_ON_ONCE(!link))
30978cc07265SAbhishek Naik 				memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN);
3098fc3432aeSJohannes Berg 			rcu_read_unlock();
309917c18bf8SJohannes Berg 			build.hdr_len = 24;
310017c18bf8SJohannes Berg 			break;
310117c18bf8SJohannes Berg 		}
310217c18bf8SJohannes Berg 
310317c18bf8SJohannes Berg 		if (sdata->u.mgd.use_4addr) {
310417c18bf8SJohannes Berg 			/* non-regular ethertype cannot use the fastpath */
310517c18bf8SJohannes Berg 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
310617c18bf8SJohannes Berg 					  IEEE80211_FCTL_TODS);
310717c18bf8SJohannes Berg 			/* RA TA DA SA */
3108bfd8403aSJohannes Berg 			memcpy(hdr->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
310917c18bf8SJohannes Berg 			memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
311017c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr3);
311117c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
311217c18bf8SJohannes Berg 			build.hdr_len = 30;
311317c18bf8SJohannes Berg 			break;
311417c18bf8SJohannes Berg 		}
311517c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
311617c18bf8SJohannes Berg 		/* BSSID SA DA */
31178a9be422SJohannes Berg 		memcpy(hdr->addr1, sdata->vif.cfg.ap_addr, ETH_ALEN);
311817c18bf8SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr3);
311917c18bf8SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
312017c18bf8SJohannes Berg 		build.hdr_len = 24;
312117c18bf8SJohannes Berg 		break;
312217c18bf8SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
312317c18bf8SJohannes Berg 		if (sdata->wdev.use_4addr) {
312417c18bf8SJohannes Berg 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
312517c18bf8SJohannes Berg 					  IEEE80211_FCTL_TODS);
312617c18bf8SJohannes Berg 			/* RA TA DA SA */
312717c18bf8SJohannes Berg 			memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
312817c18bf8SJohannes Berg 			memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
312917c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr3);
313017c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
313117c18bf8SJohannes Berg 			build.hdr_len = 30;
313217c18bf8SJohannes Berg 			break;
313317c18bf8SJohannes Berg 		}
3134fc0561dcSGustavo A. R. Silva 		fallthrough;
313517c18bf8SJohannes Berg 	case NL80211_IFTYPE_AP:
313617c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
313717c18bf8SJohannes Berg 		/* DA BSSID SA */
313817c18bf8SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr1);
3139f1871abdSIlan Peer 		if (sta->sta.mlo || !ieee80211_vif_is_mld(&sdata->vif)) {
314017c18bf8SJohannes Berg 			memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
31410f13f3c3SJohannes Berg 		} else {
31420f13f3c3SJohannes Berg 			unsigned int link_id = sta->deflink.link_id;
31430f13f3c3SJohannes Berg 			struct ieee80211_link_data *link;
31440f13f3c3SJohannes Berg 
31450f13f3c3SJohannes Berg 			rcu_read_lock();
31460f13f3c3SJohannes Berg 			link = rcu_dereference(sdata->link[link_id]);
31470f13f3c3SJohannes Berg 			if (WARN_ON(!link)) {
31480f13f3c3SJohannes Berg 				rcu_read_unlock();
31490f13f3c3SJohannes Berg 				goto out;
31500f13f3c3SJohannes Berg 			}
31510f13f3c3SJohannes Berg 			memcpy(hdr->addr2, link->conf->addr, ETH_ALEN);
31520f13f3c3SJohannes Berg 			rcu_read_unlock();
31530f13f3c3SJohannes Berg 		}
315417c18bf8SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr3);
315517c18bf8SJohannes Berg 		build.hdr_len = 24;
315617c18bf8SJohannes Berg 		break;
315717c18bf8SJohannes Berg 	default:
315817c18bf8SJohannes Berg 		/* not handled on fast-xmit */
315917c18bf8SJohannes Berg 		goto out;
316017c18bf8SJohannes Berg 	}
316117c18bf8SJohannes Berg 
316217c18bf8SJohannes Berg 	if (sta->sta.wme) {
316317c18bf8SJohannes Berg 		build.hdr_len += 2;
316417c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
316517c18bf8SJohannes Berg 	}
316617c18bf8SJohannes Berg 
316717c18bf8SJohannes Berg 	/* We store the key here so there's no point in using rcu_dereference()
316817c18bf8SJohannes Berg 	 * but that's fine because the code that changes the pointers will call
316917c18bf8SJohannes Berg 	 * this function after doing so. For a single CPU that would be enough,
317017c18bf8SJohannes Berg 	 * for multiple see the comment above.
317117c18bf8SJohannes Berg 	 */
317217c18bf8SJohannes Berg 	build.key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
317317c18bf8SJohannes Berg 	if (!build.key)
317417c18bf8SJohannes Berg 		build.key = rcu_access_pointer(sdata->default_unicast_key);
317517c18bf8SJohannes Berg 	if (build.key) {
3176e495c247SJohannes Berg 		bool gen_iv, iv_spc, mmic;
317717c18bf8SJohannes Berg 
317817c18bf8SJohannes Berg 		gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
317917c18bf8SJohannes Berg 		iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
31809de18d81SDavid Spinadel 		mmic = build.key->conf.flags &
31819de18d81SDavid Spinadel 			(IEEE80211_KEY_FLAG_GENERATE_MMIC |
31829de18d81SDavid Spinadel 			 IEEE80211_KEY_FLAG_PUT_MIC_SPACE);
318317c18bf8SJohannes Berg 
318417c18bf8SJohannes Berg 		/* don't handle software crypto */
318517c18bf8SJohannes Berg 		if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
318617c18bf8SJohannes Berg 			goto out;
318717c18bf8SJohannes Berg 
318862872a9bSAlexander Wetzel 		/* Key is being removed */
318962872a9bSAlexander Wetzel 		if (build.key->flags & KEY_FLAG_TAINTED)
319062872a9bSAlexander Wetzel 			goto out;
319162872a9bSAlexander Wetzel 
319217c18bf8SJohannes Berg 		switch (build.key->conf.cipher) {
319317c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP:
319417c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP_256:
319596fc6efbSAlexander Wetzel 			if (gen_iv)
319617c18bf8SJohannes Berg 				build.pn_offs = build.hdr_len;
319717c18bf8SJohannes Berg 			if (gen_iv || iv_spc)
319817c18bf8SJohannes Berg 				build.hdr_len += IEEE80211_CCMP_HDR_LEN;
319917c18bf8SJohannes Berg 			break;
320017c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_GCMP:
320117c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_GCMP_256:
320296fc6efbSAlexander Wetzel 			if (gen_iv)
320317c18bf8SJohannes Berg 				build.pn_offs = build.hdr_len;
320417c18bf8SJohannes Berg 			if (gen_iv || iv_spc)
320517c18bf8SJohannes Berg 				build.hdr_len += IEEE80211_GCMP_HDR_LEN;
320617c18bf8SJohannes Berg 			break;
3207e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_TKIP:
3208e495c247SJohannes Berg 			/* cannot handle MMIC or IV generation in xmit-fast */
3209e495c247SJohannes Berg 			if (mmic || gen_iv)
321017c18bf8SJohannes Berg 				goto out;
3211e495c247SJohannes Berg 			if (iv_spc)
3212e495c247SJohannes Berg 				build.hdr_len += IEEE80211_TKIP_IV_LEN;
3213e495c247SJohannes Berg 			break;
3214e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP40:
3215e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP104:
3216e495c247SJohannes Berg 			/* cannot handle IV generation in fast-xmit */
3217e495c247SJohannes Berg 			if (gen_iv)
3218e495c247SJohannes Berg 				goto out;
3219e495c247SJohannes Berg 			if (iv_spc)
3220e495c247SJohannes Berg 				build.hdr_len += IEEE80211_WEP_IV_LEN;
3221e495c247SJohannes Berg 			break;
3222e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_AES_CMAC:
3223e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3224e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
3225e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
3226e495c247SJohannes Berg 			WARN(1,
3227e495c247SJohannes Berg 			     "management cipher suite 0x%x enabled for data\n",
3228e495c247SJohannes Berg 			     build.key->conf.cipher);
3229e495c247SJohannes Berg 			goto out;
3230e495c247SJohannes Berg 		default:
3231e495c247SJohannes Berg 			/* we don't know how to generate IVs for this at all */
3232e495c247SJohannes Berg 			if (WARN_ON(gen_iv))
3233e495c247SJohannes Berg 				goto out;
323417c18bf8SJohannes Berg 		}
323517c18bf8SJohannes Berg 
323617c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
323717c18bf8SJohannes Berg 	}
323817c18bf8SJohannes Berg 
323917c18bf8SJohannes Berg 	hdr->frame_control = fc;
324017c18bf8SJohannes Berg 
324117c18bf8SJohannes Berg 	memcpy(build.hdr + build.hdr_len,
324217c18bf8SJohannes Berg 	       rfc1042_header,  sizeof(rfc1042_header));
324317c18bf8SJohannes Berg 	build.hdr_len += sizeof(rfc1042_header);
324417c18bf8SJohannes Berg 
324517c18bf8SJohannes Berg 	fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC);
324617c18bf8SJohannes Berg 	/* if the kmemdup fails, continue w/o fast_tx */
324717c18bf8SJohannes Berg 
324817c18bf8SJohannes Berg  out:
324917c18bf8SJohannes Berg 	/* we might have raced against another call to this function */
325017c18bf8SJohannes Berg 	old = rcu_dereference_protected(sta->fast_tx,
325117c18bf8SJohannes Berg 					lockdep_is_held(&sta->lock));
325217c18bf8SJohannes Berg 	rcu_assign_pointer(sta->fast_tx, fast_tx);
325317c18bf8SJohannes Berg 	if (old)
325417c18bf8SJohannes Berg 		kfree_rcu(old, rcu_head);
325517c18bf8SJohannes Berg 	spin_unlock_bh(&sta->lock);
325617c18bf8SJohannes Berg }
325717c18bf8SJohannes Berg 
ieee80211_check_fast_xmit_all(struct ieee80211_local * local)325817c18bf8SJohannes Berg void ieee80211_check_fast_xmit_all(struct ieee80211_local *local)
325917c18bf8SJohannes Berg {
326017c18bf8SJohannes Berg 	struct sta_info *sta;
326117c18bf8SJohannes Berg 
326217c18bf8SJohannes Berg 	rcu_read_lock();
326317c18bf8SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list)
326417c18bf8SJohannes Berg 		ieee80211_check_fast_xmit(sta);
326517c18bf8SJohannes Berg 	rcu_read_unlock();
326617c18bf8SJohannes Berg }
326717c18bf8SJohannes Berg 
ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data * sdata)326817c18bf8SJohannes Berg void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata)
326917c18bf8SJohannes Berg {
327017c18bf8SJohannes Berg 	struct ieee80211_local *local = sdata->local;
327117c18bf8SJohannes Berg 	struct sta_info *sta;
327217c18bf8SJohannes Berg 
327317c18bf8SJohannes Berg 	rcu_read_lock();
327417c18bf8SJohannes Berg 
327517c18bf8SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
327617c18bf8SJohannes Berg 		if (sdata != sta->sdata &&
327717c18bf8SJohannes Berg 		    (!sta->sdata->bss || sta->sdata->bss != sdata->bss))
327817c18bf8SJohannes Berg 			continue;
327917c18bf8SJohannes Berg 		ieee80211_check_fast_xmit(sta);
328017c18bf8SJohannes Berg 	}
328117c18bf8SJohannes Berg 
328217c18bf8SJohannes Berg 	rcu_read_unlock();
328317c18bf8SJohannes Berg }
328417c18bf8SJohannes Berg 
ieee80211_clear_fast_xmit(struct sta_info * sta)328517c18bf8SJohannes Berg void ieee80211_clear_fast_xmit(struct sta_info *sta)
328617c18bf8SJohannes Berg {
328717c18bf8SJohannes Berg 	struct ieee80211_fast_tx *fast_tx;
328817c18bf8SJohannes Berg 
328917c18bf8SJohannes Berg 	spin_lock_bh(&sta->lock);
329017c18bf8SJohannes Berg 	fast_tx = rcu_dereference_protected(sta->fast_tx,
329117c18bf8SJohannes Berg 					    lockdep_is_held(&sta->lock));
329217c18bf8SJohannes Berg 	RCU_INIT_POINTER(sta->fast_tx, NULL);
329317c18bf8SJohannes Berg 	spin_unlock_bh(&sta->lock);
329417c18bf8SJohannes Berg 
329517c18bf8SJohannes Berg 	if (fast_tx)
329617c18bf8SJohannes Berg 		kfree_rcu(fast_tx, rcu_head);
329717c18bf8SJohannes Berg }
329817c18bf8SJohannes Berg 
ieee80211_amsdu_realloc_pad(struct ieee80211_local * local,struct sk_buff * skb,int headroom)32996e0456b5SFelix Fietkau static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local,
3300166ac9d5SSara Sharon 					struct sk_buff *skb, int headroom)
33016e0456b5SFelix Fietkau {
3302166ac9d5SSara Sharon 	if (skb_headroom(skb) < headroom) {
33036e0456b5SFelix Fietkau 		I802_DEBUG_INC(local->tx_expand_skb_head);
33046e0456b5SFelix Fietkau 
3305166ac9d5SSara Sharon 		if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
33066e0456b5SFelix Fietkau 			wiphy_debug(local->hw.wiphy,
33076e0456b5SFelix Fietkau 				    "failed to reallocate TX buffer\n");
33086e0456b5SFelix Fietkau 			return false;
33096e0456b5SFelix Fietkau 		}
33106e0456b5SFelix Fietkau 	}
33116e0456b5SFelix Fietkau 
33126e0456b5SFelix Fietkau 	return true;
33136e0456b5SFelix Fietkau }
33146e0456b5SFelix Fietkau 
ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data * sdata,struct ieee80211_fast_tx * fast_tx,struct sk_buff * skb)33156e0456b5SFelix Fietkau static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
33166e0456b5SFelix Fietkau 					 struct ieee80211_fast_tx *fast_tx,
33176e0456b5SFelix Fietkau 					 struct sk_buff *skb)
33186e0456b5SFelix Fietkau {
33196e0456b5SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
33206e0456b5SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
33216e0456b5SFelix Fietkau 	struct ieee80211_hdr *hdr;
332206f2bb1eSMichael Braun 	struct ethhdr *amsdu_hdr;
33236e0456b5SFelix Fietkau 	int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
33246e0456b5SFelix Fietkau 	int subframe_len = skb->len - hdr_len;
33256e0456b5SFelix Fietkau 	void *data;
332606f2bb1eSMichael Braun 	u8 *qc, *h_80211_src, *h_80211_dst;
3327a3e2f4b6SMichael Braun 	const u8 *bssid;
33286e0456b5SFelix Fietkau 
33296e0456b5SFelix Fietkau 	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
33306e0456b5SFelix Fietkau 		return false;
33316e0456b5SFelix Fietkau 
33326e0456b5SFelix Fietkau 	if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
33336e0456b5SFelix Fietkau 		return true;
33346e0456b5SFelix Fietkau 
3335f50d2ff8SChih-Kang Chang 	if (!ieee80211_amsdu_realloc_pad(local, skb,
3336f50d2ff8SChih-Kang Chang 					 sizeof(*amsdu_hdr) +
3337f50d2ff8SChih-Kang Chang 					 local->hw.extra_tx_headroom))
33386e0456b5SFelix Fietkau 		return false;
33396e0456b5SFelix Fietkau 
334006f2bb1eSMichael Braun 	data = skb_push(skb, sizeof(*amsdu_hdr));
334106f2bb1eSMichael Braun 	memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
33426e0456b5SFelix Fietkau 	hdr = data;
334306f2bb1eSMichael Braun 	amsdu_hdr = data + hdr_len;
334406f2bb1eSMichael Braun 	/* h_80211_src/dst is addr* field within hdr */
334506f2bb1eSMichael Braun 	h_80211_src = data + fast_tx->sa_offs;
334606f2bb1eSMichael Braun 	h_80211_dst = data + fast_tx->da_offs;
334706f2bb1eSMichael Braun 
334806f2bb1eSMichael Braun 	amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
334906f2bb1eSMichael Braun 	ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
335006f2bb1eSMichael Braun 	ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
335106f2bb1eSMichael Braun 
3352a3e2f4b6SMichael Braun 	/* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
3353a3e2f4b6SMichael Braun 	 * fields needs to be changed to BSSID for A-MSDU frames depending
3354a3e2f4b6SMichael Braun 	 * on FromDS/ToDS values.
3355a3e2f4b6SMichael Braun 	 */
3356a3e2f4b6SMichael Braun 	switch (sdata->vif.type) {
3357a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_STATION:
33588a9be422SJohannes Berg 		bssid = sdata->vif.cfg.ap_addr;
3359a3e2f4b6SMichael Braun 		break;
3360a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_AP:
3361a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_AP_VLAN:
3362a3e2f4b6SMichael Braun 		bssid = sdata->vif.addr;
3363a3e2f4b6SMichael Braun 		break;
3364a3e2f4b6SMichael Braun 	default:
3365a3e2f4b6SMichael Braun 		bssid = NULL;
3366a3e2f4b6SMichael Braun 	}
3367a3e2f4b6SMichael Braun 
3368a3e2f4b6SMichael Braun 	if (bssid && ieee80211_has_fromds(hdr->frame_control))
3369a3e2f4b6SMichael Braun 		ether_addr_copy(h_80211_src, bssid);
3370a3e2f4b6SMichael Braun 
3371a3e2f4b6SMichael Braun 	if (bssid && ieee80211_has_tods(hdr->frame_control))
3372a3e2f4b6SMichael Braun 		ether_addr_copy(h_80211_dst, bssid);
3373a3e2f4b6SMichael Braun 
33746e0456b5SFelix Fietkau 	qc = ieee80211_get_qos_ctl(hdr);
33756e0456b5SFelix Fietkau 	*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
33766e0456b5SFelix Fietkau 
33776e0456b5SFelix Fietkau 	info->control.flags |= IEEE80211_TX_CTRL_AMSDU;
33786e0456b5SFelix Fietkau 
33796e0456b5SFelix Fietkau 	return true;
33806e0456b5SFelix Fietkau }
33816e0456b5SFelix Fietkau 
ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct ieee80211_fast_tx * fast_tx,struct sk_buff * skb,const u8 * da,const u8 * sa)33826e0456b5SFelix Fietkau static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
33836e0456b5SFelix Fietkau 				      struct sta_info *sta,
33846e0456b5SFelix Fietkau 				      struct ieee80211_fast_tx *fast_tx,
3385d5edb9aeSFelix Fietkau 				      struct sk_buff *skb,
3386d5edb9aeSFelix Fietkau 				      const u8 *da, const u8 *sa)
33876e0456b5SFelix Fietkau {
33886e0456b5SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
3389fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
3390fa962b92SMichal Kazior 	struct fq_tin *tin;
3391fa962b92SMichal Kazior 	struct fq_flow *flow;
33926e0456b5SFelix Fietkau 	u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
33936e0456b5SFelix Fietkau 	struct ieee80211_txq *txq = sta->sta.txq[tid];
33946e0456b5SFelix Fietkau 	struct txq_info *txqi;
33956e0456b5SFelix Fietkau 	struct sk_buff **frag_tail, *head;
33966e0456b5SFelix Fietkau 	int subframe_len = skb->len - ETH_ALEN;
33976e0456b5SFelix Fietkau 	u8 max_subframes = sta->sta.max_amsdu_subframes;
33986e0456b5SFelix Fietkau 	int max_frags = local->hw.max_tx_fragments;
33994c51541dSBenjamin Berg 	int max_amsdu_len = sta->sta.cur->max_amsdu_len;
3400eb9b64e3SFelix Fietkau 	int orig_truesize;
3401f2af2df8SFelix Fietkau 	u32 flow_idx;
34026e0456b5SFelix Fietkau 	__be16 len;
34036e0456b5SFelix Fietkau 	void *data;
34046e0456b5SFelix Fietkau 	bool ret = false;
3405fa962b92SMichal Kazior 	unsigned int orig_len;
340666eb02d8SLorenzo Bianconi 	int n = 2, nfrags, pad = 0;
3407166ac9d5SSara Sharon 	u16 hdrlen;
34086e0456b5SFelix Fietkau 
34096e0456b5SFelix Fietkau 	if (!ieee80211_hw_check(&local->hw, TX_AMSDU))
34106e0456b5SFelix Fietkau 		return false;
34116e0456b5SFelix Fietkau 
34124f2e3eb6SRyder Lee 	if (sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
34134f2e3eb6SRyder Lee 		return false;
34144f2e3eb6SRyder Lee 
3415d5edb9aeSFelix Fietkau 	if (ieee80211_vif_is_mesh(&sdata->vif))
3416d5edb9aeSFelix Fietkau 		return false;
3417d5edb9aeSFelix Fietkau 
3418344f8e00SSara Sharon 	if (skb_is_gso(skb))
3419344f8e00SSara Sharon 		return false;
3420344f8e00SSara Sharon 
34216e0456b5SFelix Fietkau 	if (!txq)
34226e0456b5SFelix Fietkau 		return false;
34236e0456b5SFelix Fietkau 
34246e0456b5SFelix Fietkau 	txqi = to_txq_info(txq);
34256e0456b5SFelix Fietkau 	if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags))
34266e0456b5SFelix Fietkau 		return false;
34276e0456b5SFelix Fietkau 
34284c51541dSBenjamin Berg 	if (sta->sta.cur->max_rc_amsdu_len)
34296e0456b5SFelix Fietkau 		max_amsdu_len = min_t(int, max_amsdu_len,
34304c51541dSBenjamin Berg 				      sta->sta.cur->max_rc_amsdu_len);
34316e0456b5SFelix Fietkau 
34324c51541dSBenjamin Berg 	if (sta->sta.cur->max_tid_amsdu_len[tid])
3433edba6bdaSSara Sharon 		max_amsdu_len = min_t(int, max_amsdu_len,
34344c51541dSBenjamin Berg 				      sta->sta.cur->max_tid_amsdu_len[tid]);
3435edba6bdaSSara Sharon 
3436f2af2df8SFelix Fietkau 	flow_idx = fq_flow_idx(fq, skb);
3437f2af2df8SFelix Fietkau 
3438fa962b92SMichal Kazior 	spin_lock_bh(&fq->lock);
34396e0456b5SFelix Fietkau 
3440fa962b92SMichal Kazior 	/* TODO: Ideally aggregation should be done on dequeue to remain
3441fa962b92SMichal Kazior 	 * responsive to environment changes.
3442fa962b92SMichal Kazior 	 */
3443fa962b92SMichal Kazior 
3444fa962b92SMichal Kazior 	tin = &txqi->tin;
3445bf9009bfSFelix Fietkau 	flow = fq_flow_classify(fq, tin, flow_idx, skb);
3446fa962b92SMichal Kazior 	head = skb_peek_tail(&flow->queue);
3447344f8e00SSara Sharon 	if (!head || skb_is_gso(head))
34486e0456b5SFelix Fietkau 		goto out;
34496e0456b5SFelix Fietkau 
3450eb9b64e3SFelix Fietkau 	orig_truesize = head->truesize;
3451fa962b92SMichal Kazior 	orig_len = head->len;
3452fa962b92SMichal Kazior 
34536e0456b5SFelix Fietkau 	if (skb->len + head->len > max_amsdu_len)
34546e0456b5SFelix Fietkau 		goto out;
34556e0456b5SFelix Fietkau 
34566e0456b5SFelix Fietkau 	nfrags = 1 + skb_shinfo(skb)->nr_frags;
34576e0456b5SFelix Fietkau 	nfrags += 1 + skb_shinfo(head)->nr_frags;
34586e0456b5SFelix Fietkau 	frag_tail = &skb_shinfo(head)->frag_list;
34596e0456b5SFelix Fietkau 	while (*frag_tail) {
34606e0456b5SFelix Fietkau 		nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags;
34616e0456b5SFelix Fietkau 		frag_tail = &(*frag_tail)->next;
34626e0456b5SFelix Fietkau 		n++;
34636e0456b5SFelix Fietkau 	}
34646e0456b5SFelix Fietkau 
34656e0456b5SFelix Fietkau 	if (max_subframes && n > max_subframes)
34666e0456b5SFelix Fietkau 		goto out;
34676e0456b5SFelix Fietkau 
34686e0456b5SFelix Fietkau 	if (max_frags && nfrags > max_frags)
34696e0456b5SFelix Fietkau 		goto out;
34706e0456b5SFelix Fietkau 
34719739fe29SSara Sharon 	if (!drv_can_aggregate_in_amsdu(local, head, skb))
34729739fe29SSara Sharon 		goto out;
34739739fe29SSara Sharon 
34741eb50790SLorenzo Bianconi 	if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
34756e0456b5SFelix Fietkau 		goto out;
34766e0456b5SFelix Fietkau 
3477fe94bac6SChih-Kang Chang 	/* If n == 2, the "while (*frag_tail)" loop above didn't execute
3478fe94bac6SChih-Kang Chang 	 * and  frag_tail should be &skb_shinfo(head)->frag_list.
3479fe94bac6SChih-Kang Chang 	 * However, ieee80211_amsdu_prepare_head() can reallocate it.
3480fe94bac6SChih-Kang Chang 	 * Reload frag_tail to have it pointing to the correct place.
3481fe94bac6SChih-Kang Chang 	 */
3482fe94bac6SChih-Kang Chang 	if (n == 2)
3483fe94bac6SChih-Kang Chang 		frag_tail = &skb_shinfo(head)->frag_list;
3484fe94bac6SChih-Kang Chang 
3485166ac9d5SSara Sharon 	/*
3486166ac9d5SSara Sharon 	 * Pad out the previous subframe to a multiple of 4 by adding the
3487166ac9d5SSara Sharon 	 * padding to the next one, that's being added. Note that head->len
3488166ac9d5SSara Sharon 	 * is the length of the full A-MSDU, but that works since each time
3489166ac9d5SSara Sharon 	 * we add a new subframe we pad out the previous one to a multiple
3490166ac9d5SSara Sharon 	 * of 4 and thus it no longer matters in the next round.
3491166ac9d5SSara Sharon 	 */
3492166ac9d5SSara Sharon 	hdrlen = fast_tx->hdr_len - sizeof(rfc1042_header);
3493166ac9d5SSara Sharon 	if ((head->len - hdrlen) & 3)
3494166ac9d5SSara Sharon 		pad = 4 - ((head->len - hdrlen) & 3);
3495166ac9d5SSara Sharon 
3496166ac9d5SSara Sharon 	if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) +
3497166ac9d5SSara Sharon 						     2 + pad))
3498aa58acf3SJohannes Berg 		goto out_recalc;
34996e0456b5SFelix Fietkau 
35006e0456b5SFelix Fietkau 	ret = true;
35016e0456b5SFelix Fietkau 	data = skb_push(skb, ETH_ALEN + 2);
3502d5edb9aeSFelix Fietkau 	ether_addr_copy(data, da);
3503d5edb9aeSFelix Fietkau 	ether_addr_copy(data + ETH_ALEN, sa);
35046e0456b5SFelix Fietkau 
35056e0456b5SFelix Fietkau 	data += 2 * ETH_ALEN;
35066e0456b5SFelix Fietkau 	len = cpu_to_be16(subframe_len);
35076e0456b5SFelix Fietkau 	memcpy(data, &len, 2);
35086e0456b5SFelix Fietkau 	memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header));
35096e0456b5SFelix Fietkau 
3510166ac9d5SSara Sharon 	memset(skb_push(skb, pad), 0, pad);
3511166ac9d5SSara Sharon 
35126e0456b5SFelix Fietkau 	head->len += skb->len;
35136e0456b5SFelix Fietkau 	head->data_len += skb->len;
35146e0456b5SFelix Fietkau 	*frag_tail = skb;
35156e0456b5SFelix Fietkau 
3516aa58acf3SJohannes Berg out_recalc:
3517eb9b64e3SFelix Fietkau 	fq->memory_usage += head->truesize - orig_truesize;
3518aa58acf3SJohannes Berg 	if (head->len != orig_len) {
3519fa962b92SMichal Kazior 		flow->backlog += head->len - orig_len;
3520fa962b92SMichal Kazior 		tin->backlog_bytes += head->len - orig_len;
3521aa58acf3SJohannes Berg 	}
35226e0456b5SFelix Fietkau out:
3523fa962b92SMichal Kazior 	spin_unlock_bh(&fq->lock);
35246e0456b5SFelix Fietkau 
35256e0456b5SFelix Fietkau 	return ret;
35266e0456b5SFelix Fietkau }
35276e0456b5SFelix Fietkau 
3528bb42f2d1SToke Høiland-Jørgensen /*
3529bb42f2d1SToke Høiland-Jørgensen  * Can be called while the sta lock is held. Anything that can cause packets to
3530bb42f2d1SToke Høiland-Jørgensen  * be generated will cause deadlock!
3531bb42f2d1SToke Høiland-Jørgensen  */
353203c3911dSRyder Lee static ieee80211_tx_result
ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,u8 pn_offs,struct ieee80211_key * key,struct ieee80211_tx_data * tx)353303c3911dSRyder Lee ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
3534bb42f2d1SToke Høiland-Jørgensen 			   struct sta_info *sta, u8 pn_offs,
3535bb42f2d1SToke Høiland-Jørgensen 			   struct ieee80211_key *key,
353603c3911dSRyder Lee 			   struct ieee80211_tx_data *tx)
3537bb42f2d1SToke Høiland-Jørgensen {
353803c3911dSRyder Lee 	struct sk_buff *skb = tx->skb;
3539bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
3540bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_hdr *hdr = (void *)skb->data;
3541bb42f2d1SToke Høiland-Jørgensen 	u8 tid = IEEE80211_NUM_TIDS;
3542bb42f2d1SToke Høiland-Jørgensen 
354303c3911dSRyder Lee 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL) &&
354403c3911dSRyder Lee 	    ieee80211_tx_h_rate_ctrl(tx) != TX_CONTINUE)
354503c3911dSRyder Lee 		return TX_DROP;
354603c3911dSRyder Lee 
3547bb42f2d1SToke Høiland-Jørgensen 	if (key)
3548bb42f2d1SToke Høiland-Jørgensen 		info->control.hw_key = &key->conf;
3549bb42f2d1SToke Høiland-Jørgensen 
355036ec144fSLev Stipakov 	dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
3551bb42f2d1SToke Høiland-Jørgensen 
3552bb42f2d1SToke Høiland-Jørgensen 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
3553bb42f2d1SToke Høiland-Jørgensen 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
3554bb42f2d1SToke Høiland-Jørgensen 		hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
3555bb42f2d1SToke Høiland-Jørgensen 	} else {
3556bb42f2d1SToke Høiland-Jørgensen 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
3557bb42f2d1SToke Høiland-Jørgensen 		hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
3558bb42f2d1SToke Høiland-Jørgensen 		sdata->sequence_number += 0x10;
3559bb42f2d1SToke Høiland-Jørgensen 	}
3560bb42f2d1SToke Høiland-Jørgensen 
3561bb42f2d1SToke Høiland-Jørgensen 	if (skb_shinfo(skb)->gso_size)
3562046d2e7cSSriram R 		sta->deflink.tx_stats.msdu[tid] +=
3563bb42f2d1SToke Høiland-Jørgensen 			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
3564bb42f2d1SToke Høiland-Jørgensen 	else
3565046d2e7cSSriram R 		sta->deflink.tx_stats.msdu[tid]++;
3566bb42f2d1SToke Høiland-Jørgensen 
3567bb42f2d1SToke Høiland-Jørgensen 	info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
3568bb42f2d1SToke Høiland-Jørgensen 
3569bb42f2d1SToke Høiland-Jørgensen 	/* statistics normally done by ieee80211_tx_h_stats (but that
3570bb42f2d1SToke Høiland-Jørgensen 	 * has to consider fragmentation, so is more complex)
3571bb42f2d1SToke Høiland-Jørgensen 	 */
3572046d2e7cSSriram R 	sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
3573046d2e7cSSriram R 	sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++;
3574bb42f2d1SToke Høiland-Jørgensen 
3575bb42f2d1SToke Høiland-Jørgensen 	if (pn_offs) {
3576bb42f2d1SToke Høiland-Jørgensen 		u64 pn;
3577bb42f2d1SToke Høiland-Jørgensen 		u8 *crypto_hdr = skb->data + pn_offs;
3578bb42f2d1SToke Høiland-Jørgensen 
3579bb42f2d1SToke Høiland-Jørgensen 		switch (key->conf.cipher) {
3580bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_CCMP:
3581bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_CCMP_256:
3582bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_GCMP:
3583bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_GCMP_256:
3584bb42f2d1SToke Høiland-Jørgensen 			pn = atomic64_inc_return(&key->conf.tx_pn);
3585bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[0] = pn;
3586bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[1] = pn >> 8;
358796fc6efbSAlexander Wetzel 			crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6);
3588bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[4] = pn >> 16;
3589bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[5] = pn >> 24;
3590bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[6] = pn >> 32;
3591bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[7] = pn >> 40;
3592bb42f2d1SToke Høiland-Jørgensen 			break;
3593bb42f2d1SToke Høiland-Jørgensen 		}
3594bb42f2d1SToke Høiland-Jørgensen 	}
359503c3911dSRyder Lee 
359603c3911dSRyder Lee 	return TX_CONTINUE;
3597bb42f2d1SToke Høiland-Jørgensen }
3598bb42f2d1SToke Høiland-Jørgensen 
35997d360f60SFelix Fietkau static netdev_features_t
ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data * sdata)36007d360f60SFelix Fietkau ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data *sdata)
36017d360f60SFelix Fietkau {
36027d360f60SFelix Fietkau 	if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
36037d360f60SFelix Fietkau 		return sdata->vif.netdev_features;
36047d360f60SFelix Fietkau 
36057d360f60SFelix Fietkau 	if (!sdata->bss)
36067d360f60SFelix Fietkau 		return 0;
36077d360f60SFelix Fietkau 
36087d360f60SFelix Fietkau 	sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
36097d360f60SFelix Fietkau 	return sdata->vif.netdev_features;
36107d360f60SFelix Fietkau }
36117d360f60SFelix Fietkau 
36127d360f60SFelix Fietkau static struct sk_buff *
ieee80211_tx_skb_fixup(struct sk_buff * skb,netdev_features_t features)36137d360f60SFelix Fietkau ieee80211_tx_skb_fixup(struct sk_buff *skb, netdev_features_t features)
36147d360f60SFelix Fietkau {
36157d360f60SFelix Fietkau 	if (skb_is_gso(skb)) {
36167d360f60SFelix Fietkau 		struct sk_buff *segs;
36177d360f60SFelix Fietkau 
36187d360f60SFelix Fietkau 		segs = skb_gso_segment(skb, features);
36197d360f60SFelix Fietkau 		if (!segs)
36207d360f60SFelix Fietkau 			return skb;
36217d360f60SFelix Fietkau 		if (IS_ERR(segs))
36227d360f60SFelix Fietkau 			goto free;
36237d360f60SFelix Fietkau 
36247d360f60SFelix Fietkau 		consume_skb(skb);
36257d360f60SFelix Fietkau 		return segs;
36267d360f60SFelix Fietkau 	}
36277d360f60SFelix Fietkau 
36287d360f60SFelix Fietkau 	if (skb_needs_linearize(skb, features) && __skb_linearize(skb))
36297d360f60SFelix Fietkau 		goto free;
36307d360f60SFelix Fietkau 
36317d360f60SFelix Fietkau 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
36327d360f60SFelix Fietkau 		int ofs = skb_checksum_start_offset(skb);
36337d360f60SFelix Fietkau 
36347d360f60SFelix Fietkau 		if (skb->encapsulation)
36357d360f60SFelix Fietkau 			skb_set_inner_transport_header(skb, ofs);
36367d360f60SFelix Fietkau 		else
36377d360f60SFelix Fietkau 			skb_set_transport_header(skb, ofs);
36387d360f60SFelix Fietkau 
36397d360f60SFelix Fietkau 		if (skb_csum_hwoffload_help(skb, features))
36407d360f60SFelix Fietkau 			goto free;
36417d360f60SFelix Fietkau 	}
36427d360f60SFelix Fietkau 
36437d360f60SFelix Fietkau 	skb_mark_not_on_list(skb);
36447d360f60SFelix Fietkau 	return skb;
36457d360f60SFelix Fietkau 
36467d360f60SFelix Fietkau free:
36477d360f60SFelix Fietkau 	kfree_skb(skb);
36487d360f60SFelix Fietkau 	return NULL;
36497d360f60SFelix Fietkau }
36507d360f60SFelix Fietkau 
__ieee80211_xmit_fast(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct ieee80211_fast_tx * fast_tx,struct sk_buff * skb,bool ampdu,const u8 * da,const u8 * sa)3651d5edb9aeSFelix Fietkau void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
36527d360f60SFelix Fietkau 			   struct sta_info *sta,
36537d360f60SFelix Fietkau 			   struct ieee80211_fast_tx *fast_tx,
3654d5edb9aeSFelix Fietkau 			   struct sk_buff *skb, bool ampdu,
3655d5edb9aeSFelix Fietkau 			   const u8 *da, const u8 *sa)
36567d360f60SFelix Fietkau {
36577d360f60SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
36587d360f60SFelix Fietkau 	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
36597d360f60SFelix Fietkau 	struct ieee80211_tx_info *info;
36607d360f60SFelix Fietkau 	struct ieee80211_tx_data tx;
36617d360f60SFelix Fietkau 	ieee80211_tx_result r;
36627d360f60SFelix Fietkau 	int hw_headroom = sdata->local->hw.extra_tx_headroom;
36637d360f60SFelix Fietkau 	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
36647d360f60SFelix Fietkau 
36657d360f60SFelix Fietkau 	skb = skb_share_check(skb, GFP_ATOMIC);
36667d360f60SFelix Fietkau 	if (unlikely(!skb))
36677d360f60SFelix Fietkau 		return;
36687d360f60SFelix Fietkau 
36697d360f60SFelix Fietkau 	if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
3670d5edb9aeSFelix Fietkau 	    ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb, da, sa))
36717d360f60SFelix Fietkau 		return;
36727d360f60SFelix Fietkau 
36737d360f60SFelix Fietkau 	/* will not be crypto-handled beyond what we do here, so use false
36747d360f60SFelix Fietkau 	 * as the may-encrypt argument for the resize to not account for
36757d360f60SFelix Fietkau 	 * more room than we already have in 'extra_head'
36767d360f60SFelix Fietkau 	 */
36777d360f60SFelix Fietkau 	if (unlikely(ieee80211_skb_resize(sdata, skb,
36787d360f60SFelix Fietkau 					  max_t(int, extra_head + hw_headroom -
36797d360f60SFelix Fietkau 						     skb_headroom(skb), 0),
36807d360f60SFelix Fietkau 					  ENCRYPT_NO)))
36817d360f60SFelix Fietkau 		goto free;
36827d360f60SFelix Fietkau 
36837d360f60SFelix Fietkau 	hdr = skb_push(skb, extra_head);
36847d360f60SFelix Fietkau 	memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
3685d5edb9aeSFelix Fietkau 	memcpy(skb->data + fast_tx->da_offs, da, ETH_ALEN);
3686d5edb9aeSFelix Fietkau 	memcpy(skb->data + fast_tx->sa_offs, sa, ETH_ALEN);
36877d360f60SFelix Fietkau 
36887d360f60SFelix Fietkau 	info = IEEE80211_SKB_CB(skb);
36897d360f60SFelix Fietkau 	memset(info, 0, sizeof(*info));
36907d360f60SFelix Fietkau 	info->band = fast_tx->band;
36917d360f60SFelix Fietkau 	info->control.vif = &sdata->vif;
36927d360f60SFelix Fietkau 	info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
3693592234e9SAlexander Wetzel 		      IEEE80211_TX_CTL_DONTFRAG;
36947d360f60SFelix Fietkau 	info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
36957d360f60SFelix Fietkau 			      u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
36967d360f60SFelix Fietkau 					      IEEE80211_TX_CTRL_MLO_LINK);
36977d360f60SFelix Fietkau 
36987d360f60SFelix Fietkau #ifdef CONFIG_MAC80211_DEBUGFS
36997d360f60SFelix Fietkau 	if (local->force_tx_status)
37007d360f60SFelix Fietkau 		info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
37017d360f60SFelix Fietkau #endif
37027d360f60SFelix Fietkau 
37037d360f60SFelix Fietkau 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
3704d5edb9aeSFelix Fietkau 		u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
3705d5edb9aeSFelix Fietkau 
37067d360f60SFelix Fietkau 		*ieee80211_get_qos_ctl(hdr) = tid;
37077d360f60SFelix Fietkau 	}
37087d360f60SFelix Fietkau 
37097d360f60SFelix Fietkau 	__skb_queue_head_init(&tx.skbs);
37107d360f60SFelix Fietkau 
37117d360f60SFelix Fietkau 	tx.flags = IEEE80211_TX_UNICAST;
37127d360f60SFelix Fietkau 	tx.local = local;
37137d360f60SFelix Fietkau 	tx.sdata = sdata;
37147d360f60SFelix Fietkau 	tx.sta = sta;
37157d360f60SFelix Fietkau 	tx.key = fast_tx->key;
37167d360f60SFelix Fietkau 
37177d360f60SFelix Fietkau 	if (ieee80211_queue_skb(local, sdata, sta, skb))
37187d360f60SFelix Fietkau 		return;
37197d360f60SFelix Fietkau 
37207d360f60SFelix Fietkau 	tx.skb = skb;
37217d360f60SFelix Fietkau 	r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs,
37227d360f60SFelix Fietkau 				       fast_tx->key, &tx);
37237d360f60SFelix Fietkau 	tx.skb = NULL;
37247d360f60SFelix Fietkau 	if (r == TX_DROP)
37257d360f60SFelix Fietkau 		goto free;
37267d360f60SFelix Fietkau 
37277d360f60SFelix Fietkau 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
37287d360f60SFelix Fietkau 		sdata = container_of(sdata->bss,
37297d360f60SFelix Fietkau 				     struct ieee80211_sub_if_data, u.ap);
37307d360f60SFelix Fietkau 
37317d360f60SFelix Fietkau 	__skb_queue_tail(&tx.skbs, skb);
37327d360f60SFelix Fietkau 	ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
37337d360f60SFelix Fietkau 	return;
37347d360f60SFelix Fietkau 
37357d360f60SFelix Fietkau free:
37367d360f60SFelix Fietkau 	kfree_skb(skb);
37377d360f60SFelix Fietkau }
37387d360f60SFelix Fietkau 
ieee80211_xmit_fast(struct ieee80211_sub_if_data * sdata,struct sta_info * sta,struct ieee80211_fast_tx * fast_tx,struct sk_buff * skb)373917c18bf8SJohannes Berg static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
3740bb42f2d1SToke Høiland-Jørgensen 				struct sta_info *sta,
374117c18bf8SJohannes Berg 				struct ieee80211_fast_tx *fast_tx,
374217c18bf8SJohannes Berg 				struct sk_buff *skb)
374317c18bf8SJohannes Berg {
374417c18bf8SJohannes Berg 	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
374517c18bf8SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
374617c18bf8SJohannes Berg 	struct tid_ampdu_tx *tid_tx = NULL;
37477d360f60SFelix Fietkau 	struct sk_buff *next;
3748d5edb9aeSFelix Fietkau 	struct ethhdr eth;
374917c18bf8SJohannes Berg 	u8 tid = IEEE80211_NUM_TIDS;
375017c18bf8SJohannes Berg 
375117c18bf8SJohannes Berg 	/* control port protocol needs a lot of special handling */
375217c18bf8SJohannes Berg 	if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
375317c18bf8SJohannes Berg 		return false;
375417c18bf8SJohannes Berg 
375517c18bf8SJohannes Berg 	/* only RFC 1042 SNAP */
375617c18bf8SJohannes Berg 	if (ethertype < ETH_P_802_3_MIN)
375717c18bf8SJohannes Berg 		return false;
375817c18bf8SJohannes Berg 
375917c18bf8SJohannes Berg 	/* don't handle TX status request here either */
376017c18bf8SJohannes Berg 	if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
376117c18bf8SJohannes Berg 		return false;
376217c18bf8SJohannes Berg 
376317c18bf8SJohannes Berg 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
376417c18bf8SJohannes Berg 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
376517c18bf8SJohannes Berg 		tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
3766472be00dSJohannes Berg 		if (tid_tx) {
3767472be00dSJohannes Berg 			if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
376817c18bf8SJohannes Berg 				return false;
3769472be00dSJohannes Berg 			if (tid_tx->timeout)
3770472be00dSJohannes Berg 				tid_tx->last_tx = jiffies;
3771472be00dSJohannes Berg 		}
377217c18bf8SJohannes Berg 	}
377317c18bf8SJohannes Berg 
3774d5edb9aeSFelix Fietkau 	memcpy(&eth, skb->data, ETH_HLEN - 2);
3775d5edb9aeSFelix Fietkau 
377617c18bf8SJohannes Berg 	/* after this point (skb is modified) we cannot return false */
37777d360f60SFelix Fietkau 	skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
37787d360f60SFelix Fietkau 	if (!skb)
377917c18bf8SJohannes Berg 		return true;
378017c18bf8SJohannes Berg 
37817d360f60SFelix Fietkau 	skb_list_walk_safe(skb, skb, next) {
37827d360f60SFelix Fietkau 		skb_mark_not_on_list(skb);
3783d5edb9aeSFelix Fietkau 		__ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid_tx,
3784d5edb9aeSFelix Fietkau 				      eth.h_dest, eth.h_source);
378517c18bf8SJohannes Berg 	}
378617c18bf8SJohannes Berg 
378717c18bf8SJohannes Berg 	return true;
378817c18bf8SJohannes Berg }
378917c18bf8SJohannes Berg 
ieee80211_tx_dequeue(struct ieee80211_hw * hw,struct ieee80211_txq * txq)3790e0e2efffSToke Høiland-Jørgensen struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
3791e0e2efffSToke Høiland-Jørgensen 				     struct ieee80211_txq *txq)
3792e0e2efffSToke Høiland-Jørgensen {
3793e0e2efffSToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
3794e0e2efffSToke Høiland-Jørgensen 	struct txq_info *txqi = container_of(txq, struct txq_info, txq);
3795e0e2efffSToke Høiland-Jørgensen 	struct ieee80211_hdr *hdr;
3796e0e2efffSToke Høiland-Jørgensen 	struct sk_buff *skb = NULL;
3797e0e2efffSToke Høiland-Jørgensen 	struct fq *fq = &local->fq;
3798e0e2efffSToke Høiland-Jørgensen 	struct fq_tin *tin = &txqi->tin;
3799bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info;
3800bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_data tx;
3801bb42f2d1SToke Høiland-Jørgensen 	ieee80211_tx_result r;
380221a5d4c3SManikanta Pubbisetty 	struct ieee80211_vif *vif = txq->vif;
38034444bc21SAlexander Wetzel 	int q = vif->hw_queue[txq->ac];
3804ef6e1997SMirsad Goran Todorovac 	unsigned long flags;
38054444bc21SAlexander Wetzel 	bool q_stopped;
3806e0e2efffSToke Høiland-Jørgensen 
3807fb0e76abSErik Stromdahl 	WARN_ON_ONCE(softirq_count() == 0);
3808fb0e76abSErik Stromdahl 
38097a89233aSToke Høiland-Jørgensen 	if (!ieee80211_txq_airtime_check(hw, txq))
38107a89233aSToke Høiland-Jørgensen 		return NULL;
38117a89233aSToke Høiland-Jørgensen 
3812ded4698bSFelix Fietkau begin:
3813ef6e1997SMirsad Goran Todorovac 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
38144444bc21SAlexander Wetzel 	q_stopped = local->queue_stop_reasons[q];
3815ef6e1997SMirsad Goran Todorovac 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
38164444bc21SAlexander Wetzel 
38174444bc21SAlexander Wetzel 	if (unlikely(q_stopped)) {
38184444bc21SAlexander Wetzel 		/* mark for waking later */
38194444bc21SAlexander Wetzel 		set_bit(IEEE80211_TXQ_DIRTY, &txqi->flags);
38204444bc21SAlexander Wetzel 		return NULL;
38214444bc21SAlexander Wetzel 	}
38224444bc21SAlexander Wetzel 
3823e0e2efffSToke Høiland-Jørgensen 	spin_lock_bh(&fq->lock);
3824e0e2efffSToke Høiland-Jørgensen 
3825bb42f2d1SToke Høiland-Jørgensen 	/* Make sure fragments stay together. */
3826bb42f2d1SToke Høiland-Jørgensen 	skb = __skb_dequeue(&txqi->frags);
3827ca47b462SJohannes Berg 	if (unlikely(skb)) {
3828ca47b462SJohannes Berg 		if (!(IEEE80211_SKB_CB(skb)->control.flags &
3829ca47b462SJohannes Berg 				IEEE80211_TX_INTCFL_NEED_TXPROCESSING))
3830bb42f2d1SToke Høiland-Jørgensen 			goto out;
3831ca47b462SJohannes Berg 		IEEE80211_SKB_CB(skb)->control.flags &=
3832ca47b462SJohannes Berg 			~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
3833ca47b462SJohannes Berg 	} else {
3834592234e9SAlexander Wetzel 		if (unlikely(test_bit(IEEE80211_TXQ_STOP, &txqi->flags)))
3835592234e9SAlexander Wetzel 			goto out;
3836592234e9SAlexander Wetzel 
3837e0e2efffSToke Høiland-Jørgensen 		skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
3838ca47b462SJohannes Berg 	}
3839ca47b462SJohannes Berg 
3840e0e2efffSToke Høiland-Jørgensen 	if (!skb)
3841e0e2efffSToke Høiland-Jørgensen 		goto out;
3842e0e2efffSToke Høiland-Jørgensen 
3843ded4698bSFelix Fietkau 	spin_unlock_bh(&fq->lock);
3844ded4698bSFelix Fietkau 
3845e0e2efffSToke Høiland-Jørgensen 	hdr = (struct ieee80211_hdr *)skb->data;
3846bb42f2d1SToke Høiland-Jørgensen 	info = IEEE80211_SKB_CB(skb);
3847bb42f2d1SToke Høiland-Jørgensen 
3848bb42f2d1SToke Høiland-Jørgensen 	memset(&tx, 0, sizeof(tx));
3849bb42f2d1SToke Høiland-Jørgensen 	__skb_queue_head_init(&tx.skbs);
3850bb42f2d1SToke Høiland-Jørgensen 	tx.local = local;
3851bb42f2d1SToke Høiland-Jørgensen 	tx.skb = skb;
3852bb42f2d1SToke Høiland-Jørgensen 	tx.sdata = vif_to_sdata(info->control.vif);
3853bb42f2d1SToke Høiland-Jørgensen 
3854804fc6a2SMathy Vanhoef 	if (txq->sta) {
3855bb42f2d1SToke Høiland-Jørgensen 		tx.sta = container_of(txq->sta, struct sta_info, sta);
3856ce2e1ca7SJouni Malinen 		/*
3857ce2e1ca7SJouni Malinen 		 * Drop unicast frames to unauthorised stations unless they are
3858804fc6a2SMathy Vanhoef 		 * injected frames or EAPOL frames from the local station.
3859ce2e1ca7SJouni Malinen 		 */
3860804fc6a2SMathy Vanhoef 		if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
3861804fc6a2SMathy Vanhoef 			     ieee80211_is_data(hdr->frame_control) &&
3862be8c827fSJohannes Berg 			     !ieee80211_vif_is_mesh(&tx.sdata->vif) &&
3863ce2e1ca7SJouni Malinen 			     tx.sdata->vif.type != NL80211_IFTYPE_OCB &&
3864ce2e1ca7SJouni Malinen 			     !is_multicast_ether_addr(hdr->addr1) &&
3865ce2e1ca7SJouni Malinen 			     !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) &&
3866ce2e1ca7SJouni Malinen 			     (!(info->control.flags &
3867ce2e1ca7SJouni Malinen 				IEEE80211_TX_CTRL_PORT_CTRL_PROTO) ||
38683579f4c2SJohannes Berg 			      !ieee80211_is_our_addr(tx.sdata, hdr->addr2,
38693579f4c2SJohannes Berg 						     NULL)))) {
3870ce2e1ca7SJouni Malinen 			I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
3871ce2e1ca7SJouni Malinen 			ieee80211_free_txskb(&local->hw, skb);
3872ce2e1ca7SJouni Malinen 			goto begin;
3873ce2e1ca7SJouni Malinen 		}
3874ce2e1ca7SJouni Malinen 	}
3875bb42f2d1SToke Høiland-Jørgensen 
3876bb42f2d1SToke Høiland-Jørgensen 	/*
3877bb42f2d1SToke Høiland-Jørgensen 	 * The key can be removed while the packet was queued, so need to call
3878bb42f2d1SToke Høiland-Jørgensen 	 * this here to get the current key.
3879bb42f2d1SToke Høiland-Jørgensen 	 */
3880bb42f2d1SToke Høiland-Jørgensen 	r = ieee80211_tx_h_select_key(&tx);
3881bb42f2d1SToke Høiland-Jørgensen 	if (r != TX_CONTINUE) {
3882bb42f2d1SToke Høiland-Jørgensen 		ieee80211_free_txskb(&local->hw, skb);
3883bb42f2d1SToke Høiland-Jørgensen 		goto begin;
3884bb42f2d1SToke Høiland-Jørgensen 	}
3885bb42f2d1SToke Høiland-Jørgensen 
3886c1f4c9edSFelix Fietkau 	if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
3887592234e9SAlexander Wetzel 		info->flags |= (IEEE80211_TX_CTL_AMPDU |
3888592234e9SAlexander Wetzel 				IEEE80211_TX_CTL_DONTFRAG);
3889c1f4c9edSFelix Fietkau 
38903187ba0cSRyder Lee 	if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
38913187ba0cSRyder Lee 		if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
38923187ba0cSRyder Lee 			r = ieee80211_tx_h_rate_ctrl(&tx);
38933187ba0cSRyder Lee 			if (r != TX_CONTINUE) {
38943187ba0cSRyder Lee 				ieee80211_free_txskb(&local->hw, skb);
38953187ba0cSRyder Lee 				goto begin;
38963187ba0cSRyder Lee 			}
38973187ba0cSRyder Lee 		}
389850ff477aSJohn Crispin 		goto encap_out;
38993187ba0cSRyder Lee 	}
390050ff477aSJohn Crispin 
3901bb42f2d1SToke Høiland-Jørgensen 	if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
3902e0e2efffSToke Høiland-Jørgensen 		struct sta_info *sta = container_of(txq->sta, struct sta_info,
3903e0e2efffSToke Høiland-Jørgensen 						    sta);
3904bb42f2d1SToke Høiland-Jørgensen 		u8 pn_offs = 0;
3905e0e2efffSToke Høiland-Jørgensen 
3906bb42f2d1SToke Høiland-Jørgensen 		if (tx.key &&
3907bb42f2d1SToke Høiland-Jørgensen 		    (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
3908bb42f2d1SToke Høiland-Jørgensen 			pn_offs = ieee80211_hdrlen(hdr->frame_control);
3909bb42f2d1SToke Høiland-Jørgensen 
391003c3911dSRyder Lee 		r = ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
391103c3911dSRyder Lee 					       tx.key, &tx);
391203c3911dSRyder Lee 		if (r != TX_CONTINUE) {
391303c3911dSRyder Lee 			ieee80211_free_txskb(&local->hw, skb);
391403c3911dSRyder Lee 			goto begin;
391503c3911dSRyder Lee 		}
3916bb42f2d1SToke Høiland-Jørgensen 	} else {
3917bb42f2d1SToke Høiland-Jørgensen 		if (invoke_tx_handlers_late(&tx))
3918bb42f2d1SToke Høiland-Jørgensen 			goto begin;
3919bb42f2d1SToke Høiland-Jørgensen 
3920bb42f2d1SToke Høiland-Jørgensen 		skb = __skb_dequeue(&tx.skbs);
3921e700e44fSJohannes Berg 		info = IEEE80211_SKB_CB(skb);
3922bb42f2d1SToke Høiland-Jørgensen 
3923ded4698bSFelix Fietkau 		if (!skb_queue_empty(&tx.skbs)) {
3924ded4698bSFelix Fietkau 			spin_lock_bh(&fq->lock);
3925bb42f2d1SToke Høiland-Jørgensen 			skb_queue_splice_tail(&tx.skbs, &txqi->frags);
3926ded4698bSFelix Fietkau 			spin_unlock_bh(&fq->lock);
3927ded4698bSFelix Fietkau 		}
3928e0e2efffSToke Høiland-Jørgensen 	}
3929e0e2efffSToke Høiland-Jørgensen 
3930233e98dcSJohannes Berg 	if (skb_has_frag_list(skb) &&
39311e1430d5SJohannes Berg 	    !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) {
39321e1430d5SJohannes Berg 		if (skb_linearize(skb)) {
39331e1430d5SJohannes Berg 			ieee80211_free_txskb(&local->hw, skb);
39341e1430d5SJohannes Berg 			goto begin;
39351e1430d5SJohannes Berg 		}
39361e1430d5SJohannes Berg 	}
39371e1430d5SJohannes Berg 
393853168215SJohannes Berg 	switch (tx.sdata->vif.type) {
393953168215SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
394053168215SJohannes Berg 		if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
394153168215SJohannes Berg 			vif = &tx.sdata->vif;
394253168215SJohannes Berg 			break;
394353168215SJohannes Berg 		}
394453168215SJohannes Berg 		tx.sdata = rcu_dereference(local->monitor_sdata);
394553168215SJohannes Berg 		if (tx.sdata) {
394653168215SJohannes Berg 			vif = &tx.sdata->vif;
394753168215SJohannes Berg 			info->hw_queue =
394853168215SJohannes Berg 				vif->hw_queue[skb_get_queue_mapping(skb)];
394953168215SJohannes Berg 		} else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
395053168215SJohannes Berg 			ieee80211_free_txskb(&local->hw, skb);
395153168215SJohannes Berg 			goto begin;
395253168215SJohannes Berg 		} else {
395353168215SJohannes Berg 			vif = NULL;
395453168215SJohannes Berg 		}
395553168215SJohannes Berg 		break;
395653168215SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
395753168215SJohannes Berg 		tx.sdata = container_of(tx.sdata->bss,
395853168215SJohannes Berg 					struct ieee80211_sub_if_data, u.ap);
3959fc0561dcSGustavo A. R. Silva 		fallthrough;
396053168215SJohannes Berg 	default:
396153168215SJohannes Berg 		vif = &tx.sdata->vif;
396253168215SJohannes Berg 		break;
396353168215SJohannes Berg 	}
396453168215SJohannes Berg 
396550ff477aSJohn Crispin encap_out:
3966e700e44fSJohannes Berg 	info->control.vif = vif;
39677a89233aSToke Høiland-Jørgensen 
396851d3cfafSFelix Fietkau 	if (tx.sta &&
3969ca98c47dSJohannes Berg 	    wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
39703ff901cbSFelix Fietkau 		bool ampdu = txq->ac != IEEE80211_AC_VO;
39717a89233aSToke Høiland-Jørgensen 		u32 airtime;
39727a89233aSToke Høiland-Jørgensen 
39737a89233aSToke Høiland-Jørgensen 		airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
39743ff901cbSFelix Fietkau 							     skb->len, ampdu);
39757a89233aSToke Høiland-Jørgensen 		if (airtime) {
39767a89233aSToke Høiland-Jørgensen 			airtime = ieee80211_info_set_tx_time_est(info, airtime);
39777a89233aSToke Høiland-Jørgensen 			ieee80211_sta_update_pending_airtime(local, tx.sta,
39787a89233aSToke Høiland-Jørgensen 							     txq->ac,
39797a89233aSToke Høiland-Jørgensen 							     airtime,
39807a89233aSToke Høiland-Jørgensen 							     false);
39817a89233aSToke Høiland-Jørgensen 		}
39827a89233aSToke Høiland-Jørgensen 	}
39837a89233aSToke Høiland-Jørgensen 
3984ded4698bSFelix Fietkau 	return skb;
398521a5d4c3SManikanta Pubbisetty 
3986e0e2efffSToke Høiland-Jørgensen out:
3987e0e2efffSToke Høiland-Jørgensen 	spin_unlock_bh(&fq->lock);
3988e0e2efffSToke Høiland-Jørgensen 
3989e0e2efffSToke Høiland-Jørgensen 	return skb;
3990e0e2efffSToke Høiland-Jørgensen }
3991e0e2efffSToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_tx_dequeue);
3992e0e2efffSToke Høiland-Jørgensen 
ieee80211_sta_deficit(struct sta_info * sta,u8 ac)39939c1be3cdSFelix Fietkau static inline s32 ieee80211_sta_deficit(struct sta_info *sta, u8 ac)
39949c1be3cdSFelix Fietkau {
39959c1be3cdSFelix Fietkau 	struct airtime_info *air_info = &sta->airtime[ac];
39969c1be3cdSFelix Fietkau 
39979c1be3cdSFelix Fietkau 	return air_info->deficit - atomic_read(&air_info->aql_tx_pending);
39989c1be3cdSFelix Fietkau }
39999c1be3cdSFelix Fietkau 
40008ccc0702SFelix Fietkau static void
ieee80211_txq_set_active(struct txq_info * txqi)40018ccc0702SFelix Fietkau ieee80211_txq_set_active(struct txq_info *txqi)
40028ccc0702SFelix Fietkau {
40038ccc0702SFelix Fietkau 	struct sta_info *sta;
40048ccc0702SFelix Fietkau 
40058ccc0702SFelix Fietkau 	if (!txqi->txq.sta)
40068ccc0702SFelix Fietkau 		return;
40078ccc0702SFelix Fietkau 
40088ccc0702SFelix Fietkau 	sta = container_of(txqi->txq.sta, struct sta_info, sta);
40098ccc0702SFelix Fietkau 	sta->airtime[txqi->txq.ac].last_active = (u32)jiffies;
40108ccc0702SFelix Fietkau }
40118ccc0702SFelix Fietkau 
40128ccc0702SFelix Fietkau static bool
ieee80211_txq_keep_active(struct txq_info * txqi)40138ccc0702SFelix Fietkau ieee80211_txq_keep_active(struct txq_info *txqi)
40148ccc0702SFelix Fietkau {
40158ccc0702SFelix Fietkau 	struct sta_info *sta;
40168ccc0702SFelix Fietkau 	u32 diff;
40178ccc0702SFelix Fietkau 
40188ccc0702SFelix Fietkau 	if (!txqi->txq.sta)
40198ccc0702SFelix Fietkau 		return false;
40208ccc0702SFelix Fietkau 
40218ccc0702SFelix Fietkau 	sta = container_of(txqi->txq.sta, struct sta_info, sta);
40228ccc0702SFelix Fietkau 	if (ieee80211_sta_deficit(sta, txqi->txq.ac) >= 0)
40238ccc0702SFelix Fietkau 		return false;
40248ccc0702SFelix Fietkau 
40258ccc0702SFelix Fietkau 	diff = (u32)jiffies - sta->airtime[txqi->txq.ac].last_active;
40268ccc0702SFelix Fietkau 
40278ccc0702SFelix Fietkau 	return diff <= AIRTIME_ACTIVE_DURATION;
40288ccc0702SFelix Fietkau }
40298ccc0702SFelix Fietkau 
ieee80211_next_txq(struct ieee80211_hw * hw,u8 ac)403018667600SToke Høiland-Jørgensen struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
403118667600SToke Høiland-Jørgensen {
403218667600SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
40335b989c18SFelix Fietkau 	struct ieee80211_txq *ret = NULL;
4034942741daSFelix Fietkau 	struct txq_info *txqi = NULL, *head = NULL;
4035942741daSFelix Fietkau 	bool found_eligible_txq = false;
403618667600SToke Høiland-Jørgensen 
4037942741daSFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[ac]);
403818667600SToke Høiland-Jørgensen 
40398e4bac06SFelix Fietkau 	if (!local->schedule_round[ac])
40408e4bac06SFelix Fietkau 		goto out;
40418e4bac06SFelix Fietkau 
4042b4809e94SToke Høiland-Jørgensen  begin:
4043942741daSFelix Fietkau 	txqi = list_first_entry_or_null(&local->active_txqs[ac],
4044942741daSFelix Fietkau 					struct txq_info,
4045942741daSFelix Fietkau 					schedule_order);
4046942741daSFelix Fietkau 	if (!txqi)
4047942741daSFelix Fietkau 		goto out;
4048942741daSFelix Fietkau 
4049942741daSFelix Fietkau 	if (txqi == head) {
4050942741daSFelix Fietkau 		if (!found_eligible_txq)
4051942741daSFelix Fietkau 			goto out;
4052942741daSFelix Fietkau 		else
4053942741daSFelix Fietkau 			found_eligible_txq = false;
40543ace10f5SKan Yan 	}
40553ace10f5SKan Yan 
4056942741daSFelix Fietkau 	if (!head)
4057942741daSFelix Fietkau 		head = txqi;
40583ace10f5SKan Yan 
4059942741daSFelix Fietkau 	if (txqi->txq.sta) {
4060942741daSFelix Fietkau 		struct sta_info *sta = container_of(txqi->txq.sta,
4061942741daSFelix Fietkau 						    struct sta_info, sta);
4062942741daSFelix Fietkau 		bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
40639c1be3cdSFelix Fietkau 		s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac);
4064b4809e94SToke Høiland-Jørgensen 
4065942741daSFelix Fietkau 		if (aql_check)
4066942741daSFelix Fietkau 			found_eligible_txq = true;
40673ace10f5SKan Yan 
4068942741daSFelix Fietkau 		if (deficit < 0)
4069942741daSFelix Fietkau 			sta->airtime[txqi->txq.ac].deficit +=
4070942741daSFelix Fietkau 				sta->airtime_weight;
4071942741daSFelix Fietkau 
4072942741daSFelix Fietkau 		if (deficit < 0 || !aql_check) {
4073942741daSFelix Fietkau 			list_move_tail(&txqi->schedule_order,
4074942741daSFelix Fietkau 				       &local->active_txqs[txqi->txq.ac]);
4075b4809e94SToke Høiland-Jørgensen 			goto begin;
4076b4809e94SToke Høiland-Jørgensen 		}
4077942741daSFelix Fietkau 	}
4078b4809e94SToke Høiland-Jørgensen 
4079942741daSFelix Fietkau 	if (txqi->schedule_round == local->schedule_round[ac])
4080942741daSFelix Fietkau 		goto out;
4081942741daSFelix Fietkau 
4082942741daSFelix Fietkau 	list_del_init(&txqi->schedule_order);
4083942741daSFelix Fietkau 	txqi->schedule_round = local->schedule_round[ac];
40845b989c18SFelix Fietkau 	ret = &txqi->txq;
4085942741daSFelix Fietkau 
40865b989c18SFelix Fietkau out:
4087942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
40885b989c18SFelix Fietkau 	return ret;
408918667600SToke Høiland-Jørgensen }
409018667600SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_next_txq);
409118667600SToke Høiland-Jørgensen 
__ieee80211_schedule_txq(struct ieee80211_hw * hw,struct ieee80211_txq * txq,bool force)4092942741daSFelix Fietkau void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
4093942741daSFelix Fietkau 			      struct ieee80211_txq *txq,
4094942741daSFelix Fietkau 			      bool force)
40952433647bSToke Høiland-Jørgensen {
40962433647bSToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
40972433647bSToke Høiland-Jørgensen 	struct txq_info *txqi = to_txq_info(txq);
40988ccc0702SFelix Fietkau 	bool has_queue;
40992433647bSToke Høiland-Jørgensen 
4100942741daSFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[txq->ac]);
41012433647bSToke Høiland-Jørgensen 
41028ccc0702SFelix Fietkau 	has_queue = force || txq_has_queue(txq);
4103942741daSFelix Fietkau 	if (list_empty(&txqi->schedule_order) &&
41048ccc0702SFelix Fietkau 	    (has_queue || ieee80211_txq_keep_active(txqi))) {
4105942741daSFelix Fietkau 		/* If airtime accounting is active, always enqueue STAs at the
4106942741daSFelix Fietkau 		 * head of the list to ensure that they only get moved to the
4107942741daSFelix Fietkau 		 * back by the airtime DRR scheduler once they have a negative
4108942741daSFelix Fietkau 		 * deficit. A station that already has a negative deficit will
4109942741daSFelix Fietkau 		 * get immediately moved to the back of the list on the next
4110942741daSFelix Fietkau 		 * call to ieee80211_next_txq().
41112433647bSToke Høiland-Jørgensen 		 */
41128ccc0702SFelix Fietkau 		if (txqi->txq.sta && local->airtime_flags && has_queue &&
4113942741daSFelix Fietkau 		    wiphy_ext_feature_isset(local->hw.wiphy,
4114942741daSFelix Fietkau 					    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
4115942741daSFelix Fietkau 			list_add(&txqi->schedule_order,
4116942741daSFelix Fietkau 				 &local->active_txqs[txq->ac]);
41172433647bSToke Høiland-Jørgensen 		else
4118942741daSFelix Fietkau 			list_add_tail(&txqi->schedule_order,
4119942741daSFelix Fietkau 				      &local->active_txqs[txq->ac]);
41208ccc0702SFelix Fietkau 		if (has_queue)
41218ccc0702SFelix Fietkau 			ieee80211_txq_set_active(txqi);
41222433647bSToke Høiland-Jørgensen 	}
41232433647bSToke Høiland-Jørgensen 
4124942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[txq->ac]);
41252433647bSToke Høiland-Jørgensen }
4126942741daSFelix Fietkau EXPORT_SYMBOL(__ieee80211_schedule_txq);
4127390298e8SToke Høiland-Jørgensen 
4128e908435eSLorenzo Bianconi DEFINE_STATIC_KEY_FALSE(aql_disable);
4129e908435eSLorenzo Bianconi 
ieee80211_txq_airtime_check(struct ieee80211_hw * hw,struct ieee80211_txq * txq)41303ace10f5SKan Yan bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
41313ace10f5SKan Yan 				 struct ieee80211_txq *txq)
41323ace10f5SKan Yan {
4133942741daSFelix Fietkau 	struct sta_info *sta;
41343ace10f5SKan Yan 	struct ieee80211_local *local = hw_to_local(hw);
41353ace10f5SKan Yan 
4136911bde0fSToke Høiland-Jørgensen 	if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
41373ace10f5SKan Yan 		return true;
41383ace10f5SKan Yan 
4139e908435eSLorenzo Bianconi 	if (static_branch_unlikely(&aql_disable))
4140e908435eSLorenzo Bianconi 		return true;
4141e908435eSLorenzo Bianconi 
41423ace10f5SKan Yan 	if (!txq->sta)
41433ace10f5SKan Yan 		return true;
41443ace10f5SKan Yan 
414573bc9e0aSJohannes Berg 	if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
414673bc9e0aSJohannes Berg 		return true;
414773bc9e0aSJohannes Berg 
4148942741daSFelix Fietkau 	sta = container_of(txq->sta, struct sta_info, sta);
4149942741daSFelix Fietkau 	if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
4150942741daSFelix Fietkau 	    sta->airtime[txq->ac].aql_limit_low)
41513ace10f5SKan Yan 		return true;
41523ace10f5SKan Yan 
41533ace10f5SKan Yan 	if (atomic_read(&local->aql_total_pending_airtime) <
41543ace10f5SKan Yan 	    local->aql_threshold &&
4155942741daSFelix Fietkau 	    atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
4156942741daSFelix Fietkau 	    sta->airtime[txq->ac].aql_limit_high)
41573ace10f5SKan Yan 		return true;
41583ace10f5SKan Yan 
41593ace10f5SKan Yan 	return false;
41603ace10f5SKan Yan }
41613ace10f5SKan Yan EXPORT_SYMBOL(ieee80211_txq_airtime_check);
41623ace10f5SKan Yan 
41638e4bac06SFelix Fietkau static bool
ieee80211_txq_schedule_airtime_check(struct ieee80211_local * local,u8 ac)41648e4bac06SFelix Fietkau ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)
41658e4bac06SFelix Fietkau {
41668e4bac06SFelix Fietkau 	unsigned int num_txq = 0;
41678e4bac06SFelix Fietkau 	struct txq_info *txq;
41688e4bac06SFelix Fietkau 	u32 aql_limit;
41698e4bac06SFelix Fietkau 
41708e4bac06SFelix Fietkau 	if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
41718e4bac06SFelix Fietkau 		return true;
41728e4bac06SFelix Fietkau 
41738e4bac06SFelix Fietkau 	list_for_each_entry(txq, &local->active_txqs[ac], schedule_order)
41748e4bac06SFelix Fietkau 		num_txq++;
41758e4bac06SFelix Fietkau 
41768e4bac06SFelix Fietkau 	aql_limit = (num_txq - 1) * local->aql_txq_limit_low[ac] / 2 +
41778e4bac06SFelix Fietkau 		    local->aql_txq_limit_high[ac];
41788e4bac06SFelix Fietkau 
41798e4bac06SFelix Fietkau 	return atomic_read(&local->aql_ac_pending_airtime[ac]) < aql_limit;
41808e4bac06SFelix Fietkau }
41818e4bac06SFelix Fietkau 
ieee80211_txq_may_transmit(struct ieee80211_hw * hw,struct ieee80211_txq * txq)4182b4809e94SToke Høiland-Jørgensen bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
4183b4809e94SToke Høiland-Jørgensen 				struct ieee80211_txq *txq)
4184b4809e94SToke Høiland-Jørgensen {
4185b4809e94SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
4186942741daSFelix Fietkau 	struct txq_info *iter, *tmp, *txqi = to_txq_info(txq);
4187942741daSFelix Fietkau 	struct sta_info *sta;
4188942741daSFelix Fietkau 	u8 ac = txq->ac;
4189b4809e94SToke Høiland-Jørgensen 
4190942741daSFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[ac]);
4191b4809e94SToke Høiland-Jørgensen 
4192942741daSFelix Fietkau 	if (!txqi->txq.sta)
41932433647bSToke Høiland-Jørgensen 		goto out;
41942433647bSToke Høiland-Jørgensen 
4195942741daSFelix Fietkau 	if (list_empty(&txqi->schedule_order))
4196942741daSFelix Fietkau 		goto out;
41972433647bSToke Høiland-Jørgensen 
41988e4bac06SFelix Fietkau 	if (!ieee80211_txq_schedule_airtime_check(local, ac))
41998e4bac06SFelix Fietkau 		goto out;
42008e4bac06SFelix Fietkau 
4201942741daSFelix Fietkau 	list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
4202942741daSFelix Fietkau 				 schedule_order) {
4203942741daSFelix Fietkau 		if (iter == txqi)
4204942741daSFelix Fietkau 			break;
42052433647bSToke Høiland-Jørgensen 
4206942741daSFelix Fietkau 		if (!iter->txq.sta) {
4207942741daSFelix Fietkau 			list_move_tail(&iter->schedule_order,
4208942741daSFelix Fietkau 				       &local->active_txqs[ac]);
4209942741daSFelix Fietkau 			continue;
4210942741daSFelix Fietkau 		}
4211942741daSFelix Fietkau 		sta = container_of(iter->txq.sta, struct sta_info, sta);
42129c1be3cdSFelix Fietkau 		if (ieee80211_sta_deficit(sta, ac) < 0)
4213942741daSFelix Fietkau 			sta->airtime[ac].deficit += sta->airtime_weight;
4214942741daSFelix Fietkau 		list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
42152433647bSToke Høiland-Jørgensen 	}
42162433647bSToke Høiland-Jørgensen 
4217942741daSFelix Fietkau 	sta = container_of(txqi->txq.sta, struct sta_info, sta);
4218942741daSFelix Fietkau 	if (sta->airtime[ac].deficit >= 0)
4219942741daSFelix Fietkau 		goto out;
42202433647bSToke Høiland-Jørgensen 
4221942741daSFelix Fietkau 	sta->airtime[ac].deficit += sta->airtime_weight;
4222942741daSFelix Fietkau 	list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
4223942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
4224942741daSFelix Fietkau 
4225942741daSFelix Fietkau 	return false;
42262433647bSToke Høiland-Jørgensen out:
4227942741daSFelix Fietkau 	if (!list_empty(&txqi->schedule_order))
4228942741daSFelix Fietkau 		list_del_init(&txqi->schedule_order);
4229942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
4230942741daSFelix Fietkau 
4231942741daSFelix Fietkau 	return true;
4232b4809e94SToke Høiland-Jørgensen }
4233b4809e94SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_txq_may_transmit);
4234b4809e94SToke Høiland-Jørgensen 
ieee80211_txq_schedule_start(struct ieee80211_hw * hw,u8 ac)423518667600SToke Høiland-Jørgensen void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
423618667600SToke Høiland-Jørgensen {
423718667600SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
423818667600SToke Høiland-Jørgensen 
4239942741daSFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[ac]);
42408e4bac06SFelix Fietkau 
42418e4bac06SFelix Fietkau 	if (ieee80211_txq_schedule_airtime_check(local, ac)) {
4242942741daSFelix Fietkau 		local->schedule_round[ac]++;
42438e4bac06SFelix Fietkau 		if (!local->schedule_round[ac])
42448e4bac06SFelix Fietkau 			local->schedule_round[ac]++;
42458e4bac06SFelix Fietkau 	} else {
42468e4bac06SFelix Fietkau 		local->schedule_round[ac] = 0;
42478e4bac06SFelix Fietkau 	}
42488e4bac06SFelix Fietkau 
4249942741daSFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
425018667600SToke Høiland-Jørgensen }
42515b989c18SFelix Fietkau EXPORT_SYMBOL(ieee80211_txq_schedule_start);
425218667600SToke Høiland-Jørgensen 
__ieee80211_subif_start_xmit(struct sk_buff * skb,struct net_device * dev,u32 info_flags,u32 ctrl_flags,u64 * cookie)42534c9451edSJohannes Berg void __ieee80211_subif_start_xmit(struct sk_buff *skb,
42544c9451edSJohannes Berg 				  struct net_device *dev,
425506016772SRajkumar Manoharan 				  u32 info_flags,
4256a7528198SMarkus Theil 				  u32 ctrl_flags,
4257a7528198SMarkus Theil 				  u64 *cookie)
42584c9451edSJohannes Berg {
42594c9451edSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
42601974da8bSFelix Fietkau 	struct ieee80211_local *local = sdata->local;
426197ffe757SJohannes Berg 	struct sta_info *sta;
426280616c0dSJohannes Berg 	struct sk_buff *next;
426330f6cf96SFelix Fietkau 	int len = skb->len;
42644c9451edSJohannes Berg 
4265c95014e1SAlexander Wetzel 	if (unlikely(!ieee80211_sdata_running(sdata) || skb->len < ETH_HLEN)) {
42664c9451edSJohannes Berg 		kfree_skb(skb);
42674c9451edSJohannes Berg 		return;
42684c9451edSJohannes Berg 	}
42694c9451edSJohannes Berg 
4270d5edb9aeSFelix Fietkau 	sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
4271d5edb9aeSFelix Fietkau 
42724c9451edSJohannes Berg 	rcu_read_lock();
42734c9451edSJohannes Berg 
4274d5edb9aeSFelix Fietkau 	if (ieee80211_vif_is_mesh(&sdata->vif) &&
4275d5edb9aeSFelix Fietkau 	    ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) &&
4276d5edb9aeSFelix Fietkau 	    ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags))
4277d5edb9aeSFelix Fietkau 		goto out;
4278d5edb9aeSFelix Fietkau 
42792d981fddSJohannes Berg 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
42802d981fddSJohannes Berg 		goto out_free;
42814c9451edSJohannes Berg 
42821974da8bSFelix Fietkau 	if (IS_ERR(sta))
42831974da8bSFelix Fietkau 		sta = NULL;
42841974da8bSFelix Fietkau 
4285107395f9SAlexander Wetzel 	skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
428608a46c64SFelix Fietkau 	ieee80211_aggr_check(sdata, sta, skb);
428708a46c64SFelix Fietkau 
42881974da8bSFelix Fietkau 	if (sta) {
428917c18bf8SJohannes Berg 		struct ieee80211_fast_tx *fast_tx;
429017c18bf8SJohannes Berg 
429117c18bf8SJohannes Berg 		fast_tx = rcu_dereference(sta->fast_tx);
429217c18bf8SJohannes Berg 
429317c18bf8SJohannes Berg 		if (fast_tx &&
4294bb42f2d1SToke Høiland-Jørgensen 		    ieee80211_xmit_fast(sdata, sta, fast_tx, skb))
429517c18bf8SJohannes Berg 			goto out;
429617c18bf8SJohannes Berg 	}
429717c18bf8SJohannes Berg 
429880616c0dSJohannes Berg 	/* the frame could be fragmented, software-encrypted, and other
42997d360f60SFelix Fietkau 	 * things so we cannot really handle checksum or GSO offload.
430080616c0dSJohannes Berg 	 * fix it up in software before we handle anything else.
43012d981fddSJohannes Berg 	 */
43027d360f60SFelix Fietkau 	skb = ieee80211_tx_skb_fixup(skb, 0);
43037d360f60SFelix Fietkau 	if (!skb) {
43047d360f60SFelix Fietkau 		len = 0;
43057d360f60SFelix Fietkau 		goto out;
430680616c0dSJohannes Berg 	}
430780616c0dSJohannes Berg 
43089f3ef3d7SJason A. Donenfeld 	skb_list_walk_safe(skb, skb, next) {
43099f3ef3d7SJason A. Donenfeld 		skb_mark_not_on_list(skb);
43102d981fddSJohannes Berg 
43115af7fef3SMarkus Theil 		if (skb->protocol == sdata->control_port_protocol)
43125af7fef3SMarkus Theil 			ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
43135af7fef3SMarkus Theil 
431406016772SRajkumar Manoharan 		skb = ieee80211_build_hdr(sdata, skb, info_flags,
4315a7528198SMarkus Theil 					  sta, ctrl_flags, cookie);
43169f3ef3d7SJason A. Donenfeld 		if (IS_ERR(skb)) {
43179f3ef3d7SJason A. Donenfeld 			kfree_skb_list(next);
43184c9451edSJohannes Berg 			goto out;
43199f3ef3d7SJason A. Donenfeld 		}
43204c9451edSJohannes Berg 
432136ec144fSLev Stipakov 		dev_sw_netstats_tx_add(dev, 1, skb->len);
43224c9451edSJohannes Berg 
432308aca29aSMathy Vanhoef 		ieee80211_xmit(sdata, sta, skb);
432480616c0dSJohannes Berg 	}
43252d981fddSJohannes Berg 	goto out;
43262d981fddSJohannes Berg  out_free:
43272d981fddSJohannes Berg 	kfree_skb(skb);
432830f6cf96SFelix Fietkau 	len = 0;
43294c9451edSJohannes Berg  out:
433030f6cf96SFelix Fietkau 	if (len)
433130f6cf96SFelix Fietkau 		ieee80211_tpt_led_trig_tx(local, len);
43324c9451edSJohannes Berg 	rcu_read_unlock();
43334c9451edSJohannes Berg }
43344c9451edSJohannes Berg 
ieee80211_change_da(struct sk_buff * skb,struct sta_info * sta)4335ebceec86SMichael Braun static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta)
4336ebceec86SMichael Braun {
4337ebceec86SMichael Braun 	struct ethhdr *eth;
4338ebceec86SMichael Braun 	int err;
4339ebceec86SMichael Braun 
4340ebceec86SMichael Braun 	err = skb_ensure_writable(skb, ETH_HLEN);
4341ebceec86SMichael Braun 	if (unlikely(err))
4342ebceec86SMichael Braun 		return err;
4343ebceec86SMichael Braun 
4344ebceec86SMichael Braun 	eth = (void *)skb->data;
4345ebceec86SMichael Braun 	ether_addr_copy(eth->h_dest, sta->sta.addr);
4346ebceec86SMichael Braun 
4347ebceec86SMichael Braun 	return 0;
4348ebceec86SMichael Braun }
4349ebceec86SMichael Braun 
ieee80211_multicast_to_unicast(struct sk_buff * skb,struct net_device * dev)4350ebceec86SMichael Braun static bool ieee80211_multicast_to_unicast(struct sk_buff *skb,
4351ebceec86SMichael Braun 					   struct net_device *dev)
4352ebceec86SMichael Braun {
4353ebceec86SMichael Braun 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4354ebceec86SMichael Braun 	const struct ethhdr *eth = (void *)skb->data;
4355ebceec86SMichael Braun 	const struct vlan_ethhdr *ethvlan = (void *)skb->data;
4356ebceec86SMichael Braun 	__be16 ethertype;
4357ebceec86SMichael Braun 
4358ebceec86SMichael Braun 	switch (sdata->vif.type) {
4359ebceec86SMichael Braun 	case NL80211_IFTYPE_AP_VLAN:
4360ebceec86SMichael Braun 		if (sdata->u.vlan.sta)
4361ebceec86SMichael Braun 			return false;
4362ebceec86SMichael Braun 		if (sdata->wdev.use_4addr)
4363ebceec86SMichael Braun 			return false;
4364fc0561dcSGustavo A. R. Silva 		fallthrough;
4365ebceec86SMichael Braun 	case NL80211_IFTYPE_AP:
4366ebceec86SMichael Braun 		/* check runtime toggle for this bss */
4367ebceec86SMichael Braun 		if (!sdata->bss->multicast_to_unicast)
4368ebceec86SMichael Braun 			return false;
4369ebceec86SMichael Braun 		break;
4370ebceec86SMichael Braun 	default:
4371ebceec86SMichael Braun 		return false;
4372ebceec86SMichael Braun 	}
4373ebceec86SMichael Braun 
4374ebceec86SMichael Braun 	/* multicast to unicast conversion only for some payload */
4375ebceec86SMichael Braun 	ethertype = eth->h_proto;
4376ebceec86SMichael Braun 	if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN)
4377ebceec86SMichael Braun 		ethertype = ethvlan->h_vlan_encapsulated_proto;
4378ebceec86SMichael Braun 	switch (ethertype) {
4379ebceec86SMichael Braun 	case htons(ETH_P_ARP):
4380ebceec86SMichael Braun 	case htons(ETH_P_IP):
4381ebceec86SMichael Braun 	case htons(ETH_P_IPV6):
4382ebceec86SMichael Braun 		break;
4383ebceec86SMichael Braun 	default:
4384ebceec86SMichael Braun 		return false;
4385ebceec86SMichael Braun 	}
4386ebceec86SMichael Braun 
4387ebceec86SMichael Braun 	return true;
4388ebceec86SMichael Braun }
4389ebceec86SMichael Braun 
4390ebceec86SMichael Braun static void
ieee80211_convert_to_unicast(struct sk_buff * skb,struct net_device * dev,struct sk_buff_head * queue)4391ebceec86SMichael Braun ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev,
4392ebceec86SMichael Braun 			     struct sk_buff_head *queue)
4393ebceec86SMichael Braun {
4394ebceec86SMichael Braun 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4395ebceec86SMichael Braun 	struct ieee80211_local *local = sdata->local;
4396ebceec86SMichael Braun 	const struct ethhdr *eth = (struct ethhdr *)skb->data;
4397ebceec86SMichael Braun 	struct sta_info *sta, *first = NULL;
4398ebceec86SMichael Braun 	struct sk_buff *cloned_skb;
4399ebceec86SMichael Braun 
4400ebceec86SMichael Braun 	rcu_read_lock();
4401ebceec86SMichael Braun 
4402ebceec86SMichael Braun 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
4403ebceec86SMichael Braun 		if (sdata != sta->sdata)
4404ebceec86SMichael Braun 			/* AP-VLAN mismatch */
4405ebceec86SMichael Braun 			continue;
4406ebceec86SMichael Braun 		if (unlikely(ether_addr_equal(eth->h_source, sta->sta.addr)))
4407ebceec86SMichael Braun 			/* do not send back to source */
4408ebceec86SMichael Braun 			continue;
4409ebceec86SMichael Braun 		if (!first) {
4410ebceec86SMichael Braun 			first = sta;
4411ebceec86SMichael Braun 			continue;
4412ebceec86SMichael Braun 		}
4413ebceec86SMichael Braun 		cloned_skb = skb_clone(skb, GFP_ATOMIC);
4414ebceec86SMichael Braun 		if (!cloned_skb)
4415ebceec86SMichael Braun 			goto multicast;
4416ebceec86SMichael Braun 		if (unlikely(ieee80211_change_da(cloned_skb, sta))) {
4417ebceec86SMichael Braun 			dev_kfree_skb(cloned_skb);
4418ebceec86SMichael Braun 			goto multicast;
4419ebceec86SMichael Braun 		}
4420ebceec86SMichael Braun 		__skb_queue_tail(queue, cloned_skb);
4421ebceec86SMichael Braun 	}
4422ebceec86SMichael Braun 
4423ebceec86SMichael Braun 	if (likely(first)) {
4424ebceec86SMichael Braun 		if (unlikely(ieee80211_change_da(skb, first)))
4425ebceec86SMichael Braun 			goto multicast;
4426ebceec86SMichael Braun 		__skb_queue_tail(queue, skb);
4427ebceec86SMichael Braun 	} else {
4428ebceec86SMichael Braun 		/* no STA connected, drop */
4429ebceec86SMichael Braun 		kfree_skb(skb);
4430ebceec86SMichael Braun 		skb = NULL;
4431ebceec86SMichael Braun 	}
4432ebceec86SMichael Braun 
4433ebceec86SMichael Braun 	goto out;
4434ebceec86SMichael Braun multicast:
4435ebceec86SMichael Braun 	__skb_queue_purge(queue);
4436ebceec86SMichael Braun 	__skb_queue_tail(queue, skb);
4437ebceec86SMichael Braun out:
4438ebceec86SMichael Braun 	rcu_read_unlock();
4439ebceec86SMichael Braun }
4440ebceec86SMichael Braun 
ieee80211_mlo_multicast_tx_one(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,u32 ctrl_flags,unsigned int link_id)4441963d0e8dSJohannes Berg static void ieee80211_mlo_multicast_tx_one(struct ieee80211_sub_if_data *sdata,
4442963d0e8dSJohannes Berg 					   struct sk_buff *skb, u32 ctrl_flags,
4443963d0e8dSJohannes Berg 					   unsigned int link_id)
4444963d0e8dSJohannes Berg {
4445963d0e8dSJohannes Berg 	struct sk_buff *out;
4446963d0e8dSJohannes Berg 
4447963d0e8dSJohannes Berg 	out = skb_copy(skb, GFP_ATOMIC);
4448963d0e8dSJohannes Berg 	if (!out)
4449963d0e8dSJohannes Berg 		return;
4450963d0e8dSJohannes Berg 
4451963d0e8dSJohannes Berg 	ctrl_flags |= u32_encode_bits(link_id, IEEE80211_TX_CTRL_MLO_LINK);
4452963d0e8dSJohannes Berg 	__ieee80211_subif_start_xmit(out, sdata->dev, 0, ctrl_flags, NULL);
4453963d0e8dSJohannes Berg }
4454963d0e8dSJohannes Berg 
ieee80211_mlo_multicast_tx(struct net_device * dev,struct sk_buff * skb)4455963d0e8dSJohannes Berg static void ieee80211_mlo_multicast_tx(struct net_device *dev,
4456963d0e8dSJohannes Berg 				       struct sk_buff *skb)
4457963d0e8dSJohannes Berg {
4458963d0e8dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
44597b3b9ac8SIlan Peer 	unsigned long links = sdata->vif.active_links;
4460963d0e8dSJohannes Berg 	unsigned int link;
4461963d0e8dSJohannes Berg 	u32 ctrl_flags = IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX;
4462963d0e8dSJohannes Berg 
4463963d0e8dSJohannes Berg 	if (hweight16(links) == 1) {
4464cf08e29dSJohannes Berg 		ctrl_flags |= u32_encode_bits(__ffs(links),
4465963d0e8dSJohannes Berg 					      IEEE80211_TX_CTRL_MLO_LINK);
4466963d0e8dSJohannes Berg 
4467963d0e8dSJohannes Berg 		__ieee80211_subif_start_xmit(skb, sdata->dev, 0, ctrl_flags,
4468963d0e8dSJohannes Berg 					     NULL);
4469963d0e8dSJohannes Berg 		return;
4470963d0e8dSJohannes Berg 	}
4471963d0e8dSJohannes Berg 
4472963d0e8dSJohannes Berg 	for_each_set_bit(link, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
4473963d0e8dSJohannes Berg 		ieee80211_mlo_multicast_tx_one(sdata, skb, ctrl_flags, link);
4474963d0e8dSJohannes Berg 		ctrl_flags = 0;
4475963d0e8dSJohannes Berg 	}
4476963d0e8dSJohannes Berg 	kfree_skb(skb);
4477963d0e8dSJohannes Berg }
4478963d0e8dSJohannes Berg 
44794c9451edSJohannes Berg /**
44804c9451edSJohannes Berg  * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
44814c9451edSJohannes Berg  * @skb: packet to be sent
44824c9451edSJohannes Berg  * @dev: incoming interface
44834c9451edSJohannes Berg  *
44844c9451edSJohannes Berg  * On failure skb will be freed.
44854c9451edSJohannes Berg  */
ieee80211_subif_start_xmit(struct sk_buff * skb,struct net_device * dev)448624d342c5SLiad Kaufman netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
448724d342c5SLiad Kaufman 				       struct net_device *dev)
448824d342c5SLiad Kaufman {
4489963d0e8dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4490963d0e8dSJohannes Berg 	const struct ethhdr *eth = (void *)skb->data;
4491963d0e8dSJohannes Berg 
4492963d0e8dSJohannes Berg 	if (likely(!is_multicast_ether_addr(eth->h_dest)))
4493963d0e8dSJohannes Berg 		goto normal;
4494963d0e8dSJohannes Berg 
449578085418SZhengchao Shao 	if (unlikely(!ieee80211_sdata_running(sdata))) {
449678085418SZhengchao Shao 		kfree_skb(skb);
449778085418SZhengchao Shao 		return NETDEV_TX_OK;
449878085418SZhengchao Shao 	}
449978085418SZhengchao Shao 
4500ebceec86SMichael Braun 	if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
4501ebceec86SMichael Braun 		struct sk_buff_head queue;
4502ebceec86SMichael Braun 
4503ebceec86SMichael Braun 		__skb_queue_head_init(&queue);
4504ebceec86SMichael Braun 		ieee80211_convert_to_unicast(skb, dev, &queue);
4505ebceec86SMichael Braun 		while ((skb = __skb_dequeue(&queue)))
4506963d0e8dSJohannes Berg 			__ieee80211_subif_start_xmit(skb, dev, 0,
4507963d0e8dSJohannes Berg 						     IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
4508963d0e8dSJohannes Berg 						     NULL);
4509f1871abdSIlan Peer 	} else if (ieee80211_vif_is_mld(&sdata->vif) &&
4510963d0e8dSJohannes Berg 		   sdata->vif.type == NL80211_IFTYPE_AP &&
4511963d0e8dSJohannes Berg 		   !ieee80211_hw_check(&sdata->local->hw, MLO_MCAST_MULTI_LINK_TX)) {
4512963d0e8dSJohannes Berg 		ieee80211_mlo_multicast_tx(dev, skb);
4513ebceec86SMichael Braun 	} else {
4514963d0e8dSJohannes Berg normal:
4515963d0e8dSJohannes Berg 		__ieee80211_subif_start_xmit(skb, dev, 0,
4516963d0e8dSJohannes Berg 					     IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
4517963d0e8dSJohannes Berg 					     NULL);
4518ebceec86SMichael Braun 	}
4519ebceec86SMichael Braun 
452024d342c5SLiad Kaufman 	return NETDEV_TX_OK;
452124d342c5SLiad Kaufman }
4522e2ebc74dSJohannes Berg 
45237d360f60SFelix Fietkau 
45247d360f60SFelix Fietkau 
__ieee80211_tx_8023(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,struct sta_info * sta,bool txpending)45257d360f60SFelix Fietkau static bool __ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
452630f6cf96SFelix Fietkau 				struct sk_buff *skb, struct sta_info *sta,
452750ff477aSJohn Crispin 				bool txpending)
452850ff477aSJohn Crispin {
452950ff477aSJohn Crispin 	struct ieee80211_local *local = sdata->local;
453050ff477aSJohn Crispin 	struct ieee80211_tx_control control = {};
453150ff477aSJohn Crispin 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
453250ff477aSJohn Crispin 	struct ieee80211_sta *pubsta = NULL;
453350ff477aSJohn Crispin 	unsigned long flags;
453450ff477aSJohn Crispin 	int q = info->hw_queue;
453550ff477aSJohn Crispin 
453650ff477aSJohn Crispin 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
453750ff477aSJohn Crispin 
453850ff477aSJohn Crispin 	if (local->queue_stop_reasons[q] ||
453950ff477aSJohn Crispin 	    (!txpending && !skb_queue_empty(&local->pending[q]))) {
454050ff477aSJohn Crispin 		if (txpending)
454150ff477aSJohn Crispin 			skb_queue_head(&local->pending[q], skb);
454250ff477aSJohn Crispin 		else
454350ff477aSJohn Crispin 			skb_queue_tail(&local->pending[q], skb);
454450ff477aSJohn Crispin 
454550ff477aSJohn Crispin 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
454650ff477aSJohn Crispin 
454750ff477aSJohn Crispin 		return false;
454850ff477aSJohn Crispin 	}
454950ff477aSJohn Crispin 
455050ff477aSJohn Crispin 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
455150ff477aSJohn Crispin 
455250ff477aSJohn Crispin 	if (sta && sta->uploaded)
455350ff477aSJohn Crispin 		pubsta = &sta->sta;
455450ff477aSJohn Crispin 
455550ff477aSJohn Crispin 	control.sta = pubsta;
455650ff477aSJohn Crispin 
455750ff477aSJohn Crispin 	drv_tx(local, &control, skb);
455850ff477aSJohn Crispin 
455950ff477aSJohn Crispin 	return true;
456050ff477aSJohn Crispin }
456150ff477aSJohn Crispin 
ieee80211_tx_8023(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,struct sta_info * sta,bool txpending)45627d360f60SFelix Fietkau static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
45637d360f60SFelix Fietkau 			      struct sk_buff *skb, struct sta_info *sta,
45647d360f60SFelix Fietkau 			      bool txpending)
45657d360f60SFelix Fietkau {
45667d360f60SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
45677d360f60SFelix Fietkau 	struct sk_buff *next;
45687d360f60SFelix Fietkau 	bool ret = true;
45697d360f60SFelix Fietkau 
45707d360f60SFelix Fietkau 	if (ieee80211_queue_skb(local, sdata, sta, skb))
45717d360f60SFelix Fietkau 		return true;
45727d360f60SFelix Fietkau 
45737d360f60SFelix Fietkau 	skb_list_walk_safe(skb, skb, next) {
45747d360f60SFelix Fietkau 		skb_mark_not_on_list(skb);
45757d360f60SFelix Fietkau 		if (!__ieee80211_tx_8023(sdata, skb, sta, txpending))
45767d360f60SFelix Fietkau 			ret = false;
45777d360f60SFelix Fietkau 	}
45787d360f60SFelix Fietkau 
45797d360f60SFelix Fietkau 	return ret;
45807d360f60SFelix Fietkau }
45817d360f60SFelix Fietkau 
ieee80211_8023_xmit(struct ieee80211_sub_if_data * sdata,struct net_device * dev,struct sta_info * sta,struct ieee80211_key * key,struct sk_buff * skb)458250ff477aSJohn Crispin static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
458350ff477aSJohn Crispin 				struct net_device *dev, struct sta_info *sta,
45846aea26ceSFelix Fietkau 				struct ieee80211_key *key, struct sk_buff *skb)
458550ff477aSJohn Crispin {
4586a4926abbSRyder Lee 	struct ieee80211_tx_info *info;
458750ff477aSJohn Crispin 	struct ieee80211_local *local = sdata->local;
458896ae9cd0SFelix Fietkau 	struct tid_ampdu_tx *tid_tx;
45897d360f60SFelix Fietkau 	struct sk_buff *seg, *next;
45907d360f60SFelix Fietkau 	unsigned int skbs = 0, len = 0;
45917d360f60SFelix Fietkau 	u16 queue;
459296ae9cd0SFelix Fietkau 	u8 tid;
459350ff477aSJohn Crispin 
45947d360f60SFelix Fietkau 	queue = ieee80211_select_queue(sdata, sta, skb);
45957d360f60SFelix Fietkau 	skb_set_queue_mapping(skb, queue);
45965f8d69eaSFelix Fietkau 
459750ff477aSJohn Crispin 	if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
459850ff477aSJohn Crispin 	    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
459950ff477aSJohn Crispin 		goto out_free;
460050ff477aSJohn Crispin 
4601a4926abbSRyder Lee 	skb = skb_share_check(skb, GFP_ATOMIC);
4602a4926abbSRyder Lee 	if (unlikely(!skb))
4603a4926abbSRyder Lee 		return;
4604a4926abbSRyder Lee 
460508a46c64SFelix Fietkau 	ieee80211_aggr_check(sdata, sta, skb);
460608a46c64SFelix Fietkau 
460796ae9cd0SFelix Fietkau 	tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
460896ae9cd0SFelix Fietkau 	tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
460996ae9cd0SFelix Fietkau 	if (tid_tx) {
461096ae9cd0SFelix Fietkau 		if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
461196ae9cd0SFelix Fietkau 			/* fall back to non-offload slow path */
4612963d0e8dSJohannes Berg 			__ieee80211_subif_start_xmit(skb, dev, 0,
4613963d0e8dSJohannes Berg 						     IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
4614963d0e8dSJohannes Berg 						     NULL);
461596ae9cd0SFelix Fietkau 			return;
461696ae9cd0SFelix Fietkau 		}
461796ae9cd0SFelix Fietkau 
461896ae9cd0SFelix Fietkau 		if (tid_tx->timeout)
461996ae9cd0SFelix Fietkau 			tid_tx->last_tx = jiffies;
462096ae9cd0SFelix Fietkau 	}
462196ae9cd0SFelix Fietkau 
46227d360f60SFelix Fietkau 	skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
46237d360f60SFelix Fietkau 	if (!skb)
46247d360f60SFelix Fietkau 		return;
462550ff477aSJohn Crispin 
46267d360f60SFelix Fietkau 	info = IEEE80211_SKB_CB(skb);
46277d360f60SFelix Fietkau 	memset(info, 0, sizeof(*info));
462850ff477aSJohn Crispin 
46297d360f60SFelix Fietkau 	info->hw_queue = sdata->vif.hw_queue[queue];
463050ff477aSJohn Crispin 
463150ff477aSJohn Crispin 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
463250ff477aSJohn Crispin 		sdata = container_of(sdata->bss,
463350ff477aSJohn Crispin 				     struct ieee80211_sub_if_data, u.ap);
463450ff477aSJohn Crispin 
4635cc20ff2cSFelix Fietkau 	info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
463650ff477aSJohn Crispin 	info->control.vif = &sdata->vif;
463750ff477aSJohn Crispin 
4638ae045152SFelix Fietkau 	if (key)
4639ae045152SFelix Fietkau 		info->control.hw_key = &key->conf;
4640ae045152SFelix Fietkau 
46417d360f60SFelix Fietkau 	skb_list_walk_safe(skb, seg, next) {
46427d360f60SFelix Fietkau 		skbs++;
46437d360f60SFelix Fietkau 		len += seg->len;
46447d360f60SFelix Fietkau 		if (seg != skb)
46457d360f60SFelix Fietkau 			memcpy(IEEE80211_SKB_CB(seg), info, sizeof(*info));
46467d360f60SFelix Fietkau 	}
46477d360f60SFelix Fietkau 
46487d360f60SFelix Fietkau 	if (unlikely(skb->sk &&
46497d360f60SFelix Fietkau 		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
46507d360f60SFelix Fietkau 		info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
46517d360f60SFelix Fietkau 							     &info->flags, NULL);
46527d360f60SFelix Fietkau 
46537d360f60SFelix Fietkau 	dev_sw_netstats_tx_add(dev, skbs, len);
46547d360f60SFelix Fietkau 	sta->deflink.tx_stats.packets[queue] += skbs;
46557d360f60SFelix Fietkau 	sta->deflink.tx_stats.bytes[queue] += len;
46567d360f60SFelix Fietkau 
46577d360f60SFelix Fietkau 	ieee80211_tpt_led_trig_tx(local, len);
46587d360f60SFelix Fietkau 
465930f6cf96SFelix Fietkau 	ieee80211_tx_8023(sdata, skb, sta, false);
466050ff477aSJohn Crispin 
466150ff477aSJohn Crispin 	return;
466250ff477aSJohn Crispin 
466350ff477aSJohn Crispin out_free:
466450ff477aSJohn Crispin 	kfree_skb(skb);
466550ff477aSJohn Crispin }
466650ff477aSJohn Crispin 
ieee80211_subif_start_xmit_8023(struct sk_buff * skb,struct net_device * dev)466750ff477aSJohn Crispin netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
466850ff477aSJohn Crispin 					    struct net_device *dev)
466950ff477aSJohn Crispin {
467050ff477aSJohn Crispin 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4671aea6a3f0SFelix Fietkau 	struct ethhdr *ehdr = (struct ethhdr *)skb->data;
46726aea26ceSFelix Fietkau 	struct ieee80211_key *key;
467350ff477aSJohn Crispin 	struct sta_info *sta;
467450ff477aSJohn Crispin 
4675c95014e1SAlexander Wetzel 	if (unlikely(!ieee80211_sdata_running(sdata) || skb->len < ETH_HLEN)) {
467650ff477aSJohn Crispin 		kfree_skb(skb);
467750ff477aSJohn Crispin 		return NETDEV_TX_OK;
467850ff477aSJohn Crispin 	}
467950ff477aSJohn Crispin 
468050ff477aSJohn Crispin 	rcu_read_lock();
468150ff477aSJohn Crispin 
46826aea26ceSFelix Fietkau 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
468350ff477aSJohn Crispin 		kfree_skb(skb);
46846aea26ceSFelix Fietkau 		goto out;
46856aea26ceSFelix Fietkau 	}
46866aea26ceSFelix Fietkau 
46876aea26ceSFelix Fietkau 	if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
4688aea6a3f0SFelix Fietkau 	    !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
4689aea6a3f0SFelix Fietkau 	    sdata->control_port_protocol == ehdr->h_proto))
4690b101dd2dSFelix Fietkau 		goto skip_offload;
4691b101dd2dSFelix Fietkau 
4692b101dd2dSFelix Fietkau 	key = rcu_dereference(sta->ptk[sta->ptk_idx]);
4693b101dd2dSFelix Fietkau 	if (!key)
4694b101dd2dSFelix Fietkau 		key = rcu_dereference(sdata->default_unicast_key);
4695b101dd2dSFelix Fietkau 
4696b101dd2dSFelix Fietkau 	if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
46976aea26ceSFelix Fietkau 		    key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
4698b101dd2dSFelix Fietkau 		goto skip_offload;
469950ff477aSJohn Crispin 
47007d360f60SFelix Fietkau 	sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
47016aea26ceSFelix Fietkau 	ieee80211_8023_xmit(sdata, dev, sta, key, skb);
4702b101dd2dSFelix Fietkau 	goto out;
47036aea26ceSFelix Fietkau 
4704b101dd2dSFelix Fietkau skip_offload:
4705b101dd2dSFelix Fietkau 	ieee80211_subif_start_xmit(skb, dev);
47066aea26ceSFelix Fietkau out:
470750ff477aSJohn Crispin 	rcu_read_unlock();
470850ff477aSJohn Crispin 
470950ff477aSJohn Crispin 	return NETDEV_TX_OK;
471050ff477aSJohn Crispin }
471150ff477aSJohn Crispin 
47127528ec57SJohannes Berg struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,u32 info_flags)47137528ec57SJohannes Berg ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
47147528ec57SJohannes Berg 			      struct sk_buff *skb, u32 info_flags)
47157528ec57SJohannes Berg {
47167528ec57SJohannes Berg 	struct ieee80211_hdr *hdr;
47177528ec57SJohannes Berg 	struct ieee80211_tx_data tx = {
47187528ec57SJohannes Berg 		.local = sdata->local,
47197528ec57SJohannes Berg 		.sdata = sdata,
47207528ec57SJohannes Berg 	};
472197ffe757SJohannes Berg 	struct sta_info *sta;
47227528ec57SJohannes Berg 
47237528ec57SJohannes Berg 	rcu_read_lock();
47247528ec57SJohannes Berg 
472597ffe757SJohannes Berg 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
472697ffe757SJohannes Berg 		kfree_skb(skb);
472797ffe757SJohannes Berg 		skb = ERR_PTR(-EINVAL);
472897ffe757SJohannes Berg 		goto out;
472997ffe757SJohannes Berg 	}
473097ffe757SJohannes Berg 
4731963d0e8dSJohannes Berg 	skb = ieee80211_build_hdr(sdata, skb, info_flags, sta,
4732963d0e8dSJohannes Berg 				  IEEE80211_TX_CTRL_MLO_LINK_UNSPEC, NULL);
47337528ec57SJohannes Berg 	if (IS_ERR(skb))
47347528ec57SJohannes Berg 		goto out;
47357528ec57SJohannes Berg 
47367528ec57SJohannes Berg 	hdr = (void *)skb->data;
47377528ec57SJohannes Berg 	tx.sta = sta_info_get(sdata, hdr->addr1);
47387528ec57SJohannes Berg 	tx.skb = skb;
47397528ec57SJohannes Berg 
47407528ec57SJohannes Berg 	if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
47417528ec57SJohannes Berg 		rcu_read_unlock();
47427528ec57SJohannes Berg 		kfree_skb(skb);
47437528ec57SJohannes Berg 		return ERR_PTR(-EINVAL);
47447528ec57SJohannes Berg 	}
47457528ec57SJohannes Berg 
47467528ec57SJohannes Berg out:
47477528ec57SJohannes Berg 	rcu_read_unlock();
47487528ec57SJohannes Berg 	return skb;
47497528ec57SJohannes Berg }
47507528ec57SJohannes Berg 
4751e2530083SJohannes Berg /*
4752e2530083SJohannes Berg  * ieee80211_clear_tx_pending may not be called in a context where
4753e2530083SJohannes Berg  * it is possible that it packets could come in again.
4754e2530083SJohannes Berg  */
ieee80211_clear_tx_pending(struct ieee80211_local * local)4755e2ebc74dSJohannes Berg void ieee80211_clear_tx_pending(struct ieee80211_local *local)
4756e2ebc74dSJohannes Berg {
47571f98ab7fSFelix Fietkau 	struct sk_buff *skb;
47582de8e0d9SJohannes Berg 	int i;
4759e2ebc74dSJohannes Berg 
47601f98ab7fSFelix Fietkau 	for (i = 0; i < local->hw.queues; i++) {
47611f98ab7fSFelix Fietkau 		while ((skb = skb_dequeue(&local->pending[i])) != NULL)
47621f98ab7fSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
47631f98ab7fSFelix Fietkau 	}
4764e2ebc74dSJohannes Berg }
4765e2ebc74dSJohannes Berg 
47667bb45683SJohannes Berg /*
47677bb45683SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead,
47687bb45683SJohannes Berg  * which in this case means re-queued -- take as an indication to stop sending
47697bb45683SJohannes Berg  * more pending frames.
47707bb45683SJohannes Berg  */
ieee80211_tx_pending_skb(struct ieee80211_local * local,struct sk_buff * skb)4771cd8ffc80SJohannes Berg static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
4772cd8ffc80SJohannes Berg 				     struct sk_buff *skb)
4773cd8ffc80SJohannes Berg {
4774cd8ffc80SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4775cd8ffc80SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
4776cd8ffc80SJohannes Berg 	struct sta_info *sta;
4777cd8ffc80SJohannes Berg 	struct ieee80211_hdr *hdr;
47787bb45683SJohannes Berg 	bool result;
477955de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
4780cd8ffc80SJohannes Berg 
47815061b0c2SJohannes Berg 	sdata = vif_to_sdata(info->control.vif);
4782cd8ffc80SJohannes Berg 
4783cc20ff2cSFelix Fietkau 	if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
4784eef25a66SJohannes Berg 		/* update band only for non-MLD */
4785f1871abdSIlan Peer 		if (!ieee80211_vif_is_mld(&sdata->vif)) {
4786eef25a66SJohannes Berg 			chanctx_conf =
4787eef25a66SJohannes Berg 				rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
478855de908aSJohannes Berg 			if (unlikely(!chanctx_conf)) {
478955de908aSJohannes Berg 				dev_kfree_skb(skb);
479055de908aSJohannes Berg 				return true;
479155de908aSJohannes Berg 			}
479273c4e195SJohannes Berg 			info->band = chanctx_conf->def.chan->band;
4793eef25a66SJohannes Berg 		}
479408aca29aSMathy Vanhoef 		result = ieee80211_tx(sdata, NULL, skb, true);
4795cc20ff2cSFelix Fietkau 	} else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
479650ff477aSJohn Crispin 		if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
479750ff477aSJohn Crispin 			dev_kfree_skb(skb);
479850ff477aSJohn Crispin 			return true;
479950ff477aSJohn Crispin 		}
480050ff477aSJohn Crispin 
480150ff477aSJohn Crispin 		if (IS_ERR(sta) || (sta && !sta->uploaded))
480250ff477aSJohn Crispin 			sta = NULL;
480350ff477aSJohn Crispin 
480430f6cf96SFelix Fietkau 		result = ieee80211_tx_8023(sdata, skb, sta, true);
4805cd8ffc80SJohannes Berg 	} else {
4806252b86c4SJohannes Berg 		struct sk_buff_head skbs;
4807252b86c4SJohannes Berg 
4808252b86c4SJohannes Berg 		__skb_queue_head_init(&skbs);
4809252b86c4SJohannes Berg 		__skb_queue_tail(&skbs, skb);
4810252b86c4SJohannes Berg 
4811cd8ffc80SJohannes Berg 		hdr = (struct ieee80211_hdr *)skb->data;
4812abe60632SJohannes Berg 		sta = sta_info_get(sdata, hdr->addr1);
4813cd8ffc80SJohannes Berg 
481430f6cf96SFelix Fietkau 		result = __ieee80211_tx(local, &skbs, sta, true);
4815cd8ffc80SJohannes Berg 	}
4816cd8ffc80SJohannes Berg 
4817cd8ffc80SJohannes Berg 	return result;
4818cd8ffc80SJohannes Berg }
4819cd8ffc80SJohannes Berg 
4820e2530083SJohannes Berg /*
48213b8d81e0SJohannes Berg  * Transmit all pending packets. Called from tasklet.
4822e2530083SJohannes Berg  */
ieee80211_tx_pending(struct tasklet_struct * t)4823da1cad73SAllen Pais void ieee80211_tx_pending(struct tasklet_struct *t)
4824e2ebc74dSJohannes Berg {
4825da1cad73SAllen Pais 	struct ieee80211_local *local = from_tasklet(local, t,
4826da1cad73SAllen Pais 						     tx_pending_tasklet);
48272a577d98SJohannes Berg 	unsigned long flags;
4828cd8ffc80SJohannes Berg 	int i;
48293b8d81e0SJohannes Berg 	bool txok;
4830e2ebc74dSJohannes Berg 
4831f0e72851SJohannes Berg 	rcu_read_lock();
48322a577d98SJohannes Berg 
48333b8d81e0SJohannes Berg 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
4834176be728SJohannes Berg 	for (i = 0; i < local->hw.queues; i++) {
48352a577d98SJohannes Berg 		/*
48362a577d98SJohannes Berg 		 * If queue is stopped by something other than due to pending
48372a577d98SJohannes Berg 		 * frames, or we have no pending frames, proceed to next queue.
48382a577d98SJohannes Berg 		 */
48393b8d81e0SJohannes Berg 		if (local->queue_stop_reasons[i] ||
48402a577d98SJohannes Berg 		    skb_queue_empty(&local->pending[i]))
4841e2ebc74dSJohannes Berg 			continue;
4842e2530083SJohannes Berg 
48432a577d98SJohannes Berg 		while (!skb_queue_empty(&local->pending[i])) {
48443b8d81e0SJohannes Berg 			struct sk_buff *skb = __skb_dequeue(&local->pending[i]);
48455061b0c2SJohannes Berg 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
48465061b0c2SJohannes Berg 
4847a7bc376cSJohannes Berg 			if (WARN_ON(!info->control.vif)) {
4848c3e7724bSFelix Fietkau 				ieee80211_free_txskb(&local->hw, skb);
4849a7bc376cSJohannes Berg 				continue;
4850a7bc376cSJohannes Berg 			}
4851a7bc376cSJohannes Berg 
48523b8d81e0SJohannes Berg 			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
48533b8d81e0SJohannes Berg 						flags);
48542a577d98SJohannes Berg 
48553b8d81e0SJohannes Berg 			txok = ieee80211_tx_pending_skb(local, skb);
48563b8d81e0SJohannes Berg 			spin_lock_irqsave(&local->queue_stop_reason_lock,
48573b8d81e0SJohannes Berg 					  flags);
48583b8d81e0SJohannes Berg 			if (!txok)
48592a577d98SJohannes Berg 				break;
4860e2ebc74dSJohannes Berg 		}
4861e2ebc74dSJohannes Berg 	}
48623b8d81e0SJohannes Berg 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
48632a577d98SJohannes Berg 
4864f0e72851SJohannes Berg 	rcu_read_unlock();
4865e2ebc74dSJohannes Berg }
4866e2ebc74dSJohannes Berg 
4867e2ebc74dSJohannes Berg /* functions for drivers to get certain frames */
4868e2ebc74dSJohannes Berg 
__ieee80211_beacon_add_tim(struct ieee80211_sub_if_data * sdata,struct ieee80211_link_data * link,struct ps_data * ps,struct sk_buff * skb,bool is_template)4869eac70c13SMarco Porsch static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
4870d8675a63SJohannes Berg 				       struct ieee80211_link_data *link,
48716ec8c332SAndrei Otcheretianski 				       struct ps_data *ps, struct sk_buff *skb,
4872d8675a63SJohannes Berg 				       bool is_template)
4873e2ebc74dSJohannes Berg {
4874e2ebc74dSJohannes Berg 	u8 *pos, *tim;
4875e2ebc74dSJohannes Berg 	int aid0 = 0;
4876e2ebc74dSJohannes Berg 	int i, have_bits = 0, n1, n2;
4877d8675a63SJohannes Berg 	struct ieee80211_bss_conf *link_conf = link->conf;
4878e2ebc74dSJohannes Berg 
4879e2ebc74dSJohannes Berg 	/* Generate bitmap for TIM only if there are any STAs in power save
4880e2ebc74dSJohannes Berg 	 * mode. */
4881d012a605SMarco Porsch 	if (atomic_read(&ps->num_sta_ps) > 0)
4882e2ebc74dSJohannes Berg 		/* in the hope that this is faster than
4883e2ebc74dSJohannes Berg 		 * checking byte-for-byte */
4884d012a605SMarco Porsch 		have_bits = !bitmap_empty((unsigned long *)ps->tim,
4885e2ebc74dSJohannes Berg 					  IEEE80211_MAX_AID+1);
48866ec8c332SAndrei Otcheretianski 	if (!is_template) {
4887d012a605SMarco Porsch 		if (ps->dtim_count == 0)
48886e8912a5SShaul Triebitz 			ps->dtim_count = link_conf->dtim_period - 1;
4889e2ebc74dSJohannes Berg 		else
4890d012a605SMarco Porsch 			ps->dtim_count--;
48916ec8c332SAndrei Otcheretianski 	}
4892e2ebc74dSJohannes Berg 
4893209d70d3SKieran Frewen 	tim = pos = skb_put(skb, 5);
4894e2ebc74dSJohannes Berg 	*pos++ = WLAN_EID_TIM;
4895209d70d3SKieran Frewen 	*pos++ = 3;
4896d012a605SMarco Porsch 	*pos++ = ps->dtim_count;
48976e8912a5SShaul Triebitz 	*pos++ = link_conf->dtim_period;
4898e2ebc74dSJohannes Berg 
4899d012a605SMarco Porsch 	if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf))
4900e2ebc74dSJohannes Berg 		aid0 = 1;
4901e2ebc74dSJohannes Berg 
4902d012a605SMarco Porsch 	ps->dtim_bc_mc = aid0 == 1;
4903512119b3SChristian Lamparter 
4904e2ebc74dSJohannes Berg 	if (have_bits) {
4905e2ebc74dSJohannes Berg 		/* Find largest even number N1 so that bits numbered 1 through
4906e2ebc74dSJohannes Berg 		 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
4907e2ebc74dSJohannes Berg 		 * (N2 + 1) x 8 through 2007 are 0. */
4908e2ebc74dSJohannes Berg 		n1 = 0;
4909e2ebc74dSJohannes Berg 		for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
4910d012a605SMarco Porsch 			if (ps->tim[i]) {
4911e2ebc74dSJohannes Berg 				n1 = i & 0xfe;
4912e2ebc74dSJohannes Berg 				break;
4913e2ebc74dSJohannes Berg 			}
4914e2ebc74dSJohannes Berg 		}
4915e2ebc74dSJohannes Berg 		n2 = n1;
4916e2ebc74dSJohannes Berg 		for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
4917d012a605SMarco Porsch 			if (ps->tim[i]) {
4918e2ebc74dSJohannes Berg 				n2 = i;
4919e2ebc74dSJohannes Berg 				break;
4920e2ebc74dSJohannes Berg 			}
4921e2ebc74dSJohannes Berg 		}
4922e2ebc74dSJohannes Berg 
4923e2ebc74dSJohannes Berg 		/* Bitmap control */
4924e2ebc74dSJohannes Berg 		*pos++ = n1 | aid0;
4925e2ebc74dSJohannes Berg 		/* Part Virt Bitmap */
4926209d70d3SKieran Frewen 		skb_put_data(skb, ps->tim + n1, n2 - n1 + 1);
4927e2ebc74dSJohannes Berg 
4928e2ebc74dSJohannes Berg 		tim[1] = n2 - n1 + 4;
4929e2ebc74dSJohannes Berg 	} else {
4930e2ebc74dSJohannes Berg 		*pos++ = aid0; /* Bitmap control */
4931209d70d3SKieran Frewen 
4932209d70d3SKieran Frewen 		if (ieee80211_get_link_sband(link)->band != NL80211_BAND_S1GHZ) {
4933209d70d3SKieran Frewen 			tim[1] = 4;
4934209d70d3SKieran Frewen 			/* Part Virt Bitmap */
4935209d70d3SKieran Frewen 			skb_put_u8(skb, 0);
4936209d70d3SKieran Frewen 		}
4937e2ebc74dSJohannes Berg 	}
4938e2ebc74dSJohannes Berg }
4939e2ebc74dSJohannes Berg 
ieee80211_beacon_add_tim(struct ieee80211_sub_if_data * sdata,struct ieee80211_link_data * link,struct ps_data * ps,struct sk_buff * skb,bool is_template)4940eac70c13SMarco Porsch static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
4941d8675a63SJohannes Berg 				    struct ieee80211_link_data *link,
49426ec8c332SAndrei Otcheretianski 				    struct ps_data *ps, struct sk_buff *skb,
4943d8675a63SJohannes Berg 				    bool is_template)
4944eac70c13SMarco Porsch {
4945eac70c13SMarco Porsch 	struct ieee80211_local *local = sdata->local;
4946eac70c13SMarco Porsch 
4947eac70c13SMarco Porsch 	/*
4948eac70c13SMarco Porsch 	 * Not very nice, but we want to allow the driver to call
4949eac70c13SMarco Porsch 	 * ieee80211_beacon_get() as a response to the set_tim()
4950eac70c13SMarco Porsch 	 * callback. That, however, is already invoked under the
4951eac70c13SMarco Porsch 	 * sta_lock to guarantee consistent and race-free update
4952eac70c13SMarco Porsch 	 * of the tim bitmap in mac80211 and the driver.
4953eac70c13SMarco Porsch 	 */
4954eac70c13SMarco Porsch 	if (local->tim_in_locked_section) {
4955d8675a63SJohannes Berg 		__ieee80211_beacon_add_tim(sdata, link, ps, skb, is_template);
4956eac70c13SMarco Porsch 	} else {
49571b91731dSJohannes Berg 		spin_lock_bh(&local->tim_lock);
4958d8675a63SJohannes Berg 		__ieee80211_beacon_add_tim(sdata, link, ps, skb, is_template);
49591b91731dSJohannes Berg 		spin_unlock_bh(&local->tim_lock);
4960eac70c13SMarco Porsch 	}
4961eac70c13SMarco Porsch 
4962eac70c13SMarco Porsch 	return 0;
4963eac70c13SMarco Porsch }
4964eac70c13SMarco Porsch 
ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data * sdata,struct beacon_data * beacon,struct ieee80211_link_data * link)49658552a434SJohn Crispin static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
49666e8912a5SShaul Triebitz 					struct beacon_data *beacon,
4967d8675a63SJohannes Berg 					struct ieee80211_link_data *link)
496873da7d5bSSimon Wunderlich {
49695f9404abSJohn Crispin 	u8 *beacon_data, count, max_count = 1;
497073da7d5bSSimon Wunderlich 	struct probe_resp *resp;
4971cd7760e6SSimon Wunderlich 	size_t beacon_data_len;
49725f9404abSJohn Crispin 	u16 *bcn_offsets;
49730d06d9baSAndrei Otcheretianski 	int i;
497473da7d5bSSimon Wunderlich 
4975cd7760e6SSimon Wunderlich 	switch (sdata->vif.type) {
4976cd7760e6SSimon Wunderlich 	case NL80211_IFTYPE_AP:
4977cd7760e6SSimon Wunderlich 		beacon_data = beacon->tail;
4978cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->tail_len;
4979cd7760e6SSimon Wunderlich 		break;
4980cd7760e6SSimon Wunderlich 	case NL80211_IFTYPE_ADHOC:
4981cd7760e6SSimon Wunderlich 		beacon_data = beacon->head;
4982cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->head_len;
4983cd7760e6SSimon Wunderlich 		break;
4984b8456a14SChun-Yeow Yeoh 	case NL80211_IFTYPE_MESH_POINT:
4985b8456a14SChun-Yeow Yeoh 		beacon_data = beacon->head;
4986b8456a14SChun-Yeow Yeoh 		beacon_data_len = beacon->head_len;
4987b8456a14SChun-Yeow Yeoh 		break;
4988cd7760e6SSimon Wunderlich 	default:
4989cd7760e6SSimon Wunderlich 		return;
4990cd7760e6SSimon Wunderlich 	}
49910d06d9baSAndrei Otcheretianski 
4992d8675a63SJohannes Berg 	resp = rcu_dereference(link->u.ap.probe_resp);
499373da7d5bSSimon Wunderlich 
49945f9404abSJohn Crispin 	bcn_offsets = beacon->cntdwn_counter_offsets;
49955f9404abSJohn Crispin 	count = beacon->cntdwn_current_counter;
4996d8675a63SJohannes Berg 	if (link->conf->csa_active)
49975f9404abSJohn Crispin 		max_count = IEEE80211_MAX_CNTDWN_COUNTERS_NUM;
49985f9404abSJohn Crispin 
49995f9404abSJohn Crispin 	for (i = 0; i < max_count; ++i) {
50005f9404abSJohn Crispin 		if (bcn_offsets[i]) {
5001d8675a63SJohannes Berg 			if (WARN_ON_ONCE(bcn_offsets[i] >= beacon_data_len))
500273da7d5bSSimon Wunderlich 				return;
50035f9404abSJohn Crispin 			beacon_data[bcn_offsets[i]] = count;
5004af296bdbSMichal Kazior 		}
5005af296bdbSMichal Kazior 
50065f9404abSJohn Crispin 		if (sdata->vif.type == NL80211_IFTYPE_AP && resp) {
50075f9404abSJohn Crispin 			u16 *resp_offsets = resp->cntdwn_counter_offsets;
50085f9404abSJohn Crispin 
50095f9404abSJohn Crispin 			resp->data[resp_offsets[i]] = count;
50105f9404abSJohn Crispin 		}
5011af296bdbSMichal Kazior 	}
501273da7d5bSSimon Wunderlich }
50131af586c9SAndrei Otcheretianski 
__ieee80211_beacon_update_cntdwn(struct beacon_data * beacon)50148552a434SJohn Crispin static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)
5015e996ec2aSWojciech Dubowik {
50168552a434SJohn Crispin 	beacon->cntdwn_current_counter--;
5017e996ec2aSWojciech Dubowik 
5018e996ec2aSWojciech Dubowik 	/* the counter should never reach 0 */
50198552a434SJohn Crispin 	WARN_ON_ONCE(!beacon->cntdwn_current_counter);
5020e996ec2aSWojciech Dubowik 
50218552a434SJohn Crispin 	return beacon->cntdwn_current_counter;
5022e996ec2aSWojciech Dubowik }
5023e996ec2aSWojciech Dubowik 
ieee80211_beacon_update_cntdwn(struct ieee80211_vif * vif)50248552a434SJohn Crispin u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif)
50251af586c9SAndrei Otcheretianski {
50261af586c9SAndrei Otcheretianski 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5027af296bdbSMichal Kazior 	struct beacon_data *beacon = NULL;
5028af296bdbSMichal Kazior 	u8 count = 0;
502973da7d5bSSimon Wunderlich 
5030af296bdbSMichal Kazior 	rcu_read_lock();
5031af296bdbSMichal Kazior 
5032af296bdbSMichal Kazior 	if (sdata->vif.type == NL80211_IFTYPE_AP)
5033bfd8403aSJohannes Berg 		beacon = rcu_dereference(sdata->deflink.u.ap.beacon);
5034af296bdbSMichal Kazior 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
5035af296bdbSMichal Kazior 		beacon = rcu_dereference(sdata->u.ibss.presp);
5036af296bdbSMichal Kazior 	else if (ieee80211_vif_is_mesh(&sdata->vif))
5037af296bdbSMichal Kazior 		beacon = rcu_dereference(sdata->u.mesh.beacon);
5038af296bdbSMichal Kazior 
5039af296bdbSMichal Kazior 	if (!beacon)
5040af296bdbSMichal Kazior 		goto unlock;
5041af296bdbSMichal Kazior 
50428552a434SJohn Crispin 	count = __ieee80211_beacon_update_cntdwn(beacon);
50431af586c9SAndrei Otcheretianski 
5044af296bdbSMichal Kazior unlock:
5045af296bdbSMichal Kazior 	rcu_read_unlock();
5046af296bdbSMichal Kazior 	return count;
50470d06d9baSAndrei Otcheretianski }
50488552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_update_cntdwn);
50490d06d9baSAndrei Otcheretianski 
ieee80211_beacon_set_cntdwn(struct ieee80211_vif * vif,u8 counter)50508552a434SJohn Crispin void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter)
505103737001SGregory Greenman {
505203737001SGregory Greenman 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
505303737001SGregory Greenman 	struct beacon_data *beacon = NULL;
505403737001SGregory Greenman 
505503737001SGregory Greenman 	rcu_read_lock();
505603737001SGregory Greenman 
505703737001SGregory Greenman 	if (sdata->vif.type == NL80211_IFTYPE_AP)
5058bfd8403aSJohannes Berg 		beacon = rcu_dereference(sdata->deflink.u.ap.beacon);
505903737001SGregory Greenman 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
506003737001SGregory Greenman 		beacon = rcu_dereference(sdata->u.ibss.presp);
506103737001SGregory Greenman 	else if (ieee80211_vif_is_mesh(&sdata->vif))
506203737001SGregory Greenman 		beacon = rcu_dereference(sdata->u.mesh.beacon);
506303737001SGregory Greenman 
506403737001SGregory Greenman 	if (!beacon)
506503737001SGregory Greenman 		goto unlock;
506603737001SGregory Greenman 
50678552a434SJohn Crispin 	if (counter < beacon->cntdwn_current_counter)
50688552a434SJohn Crispin 		beacon->cntdwn_current_counter = counter;
506903737001SGregory Greenman 
507003737001SGregory Greenman unlock:
507103737001SGregory Greenman 	rcu_read_unlock();
507203737001SGregory Greenman }
50738552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn);
507403737001SGregory Greenman 
ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif * vif)50758552a434SJohn Crispin bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif)
507673da7d5bSSimon Wunderlich {
507773da7d5bSSimon Wunderlich 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
507873da7d5bSSimon Wunderlich 	struct beacon_data *beacon = NULL;
507973da7d5bSSimon Wunderlich 	u8 *beacon_data;
508073da7d5bSSimon Wunderlich 	size_t beacon_data_len;
508173da7d5bSSimon Wunderlich 	int ret = false;
508273da7d5bSSimon Wunderlich 
508373da7d5bSSimon Wunderlich 	if (!ieee80211_sdata_running(sdata))
508473da7d5bSSimon Wunderlich 		return false;
508573da7d5bSSimon Wunderlich 
508673da7d5bSSimon Wunderlich 	rcu_read_lock();
508773da7d5bSSimon Wunderlich 	if (vif->type == NL80211_IFTYPE_AP) {
5088bfd8403aSJohannes Berg 		beacon = rcu_dereference(sdata->deflink.u.ap.beacon);
508973da7d5bSSimon Wunderlich 		if (WARN_ON(!beacon || !beacon->tail))
509073da7d5bSSimon Wunderlich 			goto out;
509173da7d5bSSimon Wunderlich 		beacon_data = beacon->tail;
509273da7d5bSSimon Wunderlich 		beacon_data_len = beacon->tail_len;
5093cd7760e6SSimon Wunderlich 	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
5094cd7760e6SSimon Wunderlich 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
5095cd7760e6SSimon Wunderlich 
5096cd7760e6SSimon Wunderlich 		beacon = rcu_dereference(ifibss->presp);
5097cd7760e6SSimon Wunderlich 		if (!beacon)
5098cd7760e6SSimon Wunderlich 			goto out;
5099cd7760e6SSimon Wunderlich 
5100cd7760e6SSimon Wunderlich 		beacon_data = beacon->head;
5101cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->head_len;
5102b8456a14SChun-Yeow Yeoh 	} else if (vif->type == NL80211_IFTYPE_MESH_POINT) {
5103b8456a14SChun-Yeow Yeoh 		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
5104b8456a14SChun-Yeow Yeoh 
5105b8456a14SChun-Yeow Yeoh 		beacon = rcu_dereference(ifmsh->beacon);
5106b8456a14SChun-Yeow Yeoh 		if (!beacon)
5107b8456a14SChun-Yeow Yeoh 			goto out;
5108b8456a14SChun-Yeow Yeoh 
5109b8456a14SChun-Yeow Yeoh 		beacon_data = beacon->head;
5110b8456a14SChun-Yeow Yeoh 		beacon_data_len = beacon->head_len;
511173da7d5bSSimon Wunderlich 	} else {
511273da7d5bSSimon Wunderlich 		WARN_ON(1);
511373da7d5bSSimon Wunderlich 		goto out;
511473da7d5bSSimon Wunderlich 	}
511573da7d5bSSimon Wunderlich 
51168552a434SJohn Crispin 	if (!beacon->cntdwn_counter_offsets[0])
511710d78f27SMichal Kazior 		goto out;
511810d78f27SMichal Kazior 
51198552a434SJohn Crispin 	if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[0] > beacon_data_len))
512073da7d5bSSimon Wunderlich 		goto out;
512173da7d5bSSimon Wunderlich 
51228552a434SJohn Crispin 	if (beacon_data[beacon->cntdwn_counter_offsets[0]] == 1)
512373da7d5bSSimon Wunderlich 		ret = true;
51248552a434SJohn Crispin 
512573da7d5bSSimon Wunderlich  out:
512673da7d5bSSimon Wunderlich 	rcu_read_unlock();
512773da7d5bSSimon Wunderlich 
512873da7d5bSSimon Wunderlich 	return ret;
512973da7d5bSSimon Wunderlich }
51308552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_cntdwn_is_complete);
513173da7d5bSSimon Wunderlich 
ieee80211_beacon_protect(struct sk_buff * skb,struct ieee80211_local * local,struct ieee80211_sub_if_data * sdata,struct ieee80211_link_data * link)51320a3a8436SJouni Malinen static int ieee80211_beacon_protect(struct sk_buff *skb,
51330a3a8436SJouni Malinen 				    struct ieee80211_local *local,
51346e8912a5SShaul Triebitz 				    struct ieee80211_sub_if_data *sdata,
5135d8675a63SJohannes Berg 				    struct ieee80211_link_data *link)
51360a3a8436SJouni Malinen {
51370a3a8436SJouni Malinen 	ieee80211_tx_result res;
51380a3a8436SJouni Malinen 	struct ieee80211_tx_data tx;
513995247705SJohannes Berg 	struct sk_buff *check_skb;
51400a3a8436SJouni Malinen 
51410a3a8436SJouni Malinen 	memset(&tx, 0, sizeof(tx));
5142d8675a63SJohannes Berg 	tx.key = rcu_dereference(link->default_beacon_key);
51430a3a8436SJouni Malinen 	if (!tx.key)
51440a3a8436SJouni Malinen 		return 0;
51453ffcc659SJohannes Berg 
51463ffcc659SJohannes Berg 	if (unlikely(tx.key->flags & KEY_FLAG_TAINTED)) {
51473ffcc659SJohannes Berg 		tx.key = NULL;
51483ffcc659SJohannes Berg 		return -EINVAL;
51493ffcc659SJohannes Berg 	}
51503ffcc659SJohannes Berg 
5151d1b9bb65SJohannes Berg 	if (!(tx.key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT_TX) &&
5152d1b9bb65SJohannes Berg 	    tx.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
5153d1b9bb65SJohannes Berg 		IEEE80211_SKB_CB(skb)->control.hw_key = &tx.key->conf;
5154d1b9bb65SJohannes Berg 
51550a3a8436SJouni Malinen 	tx.local = local;
51560a3a8436SJouni Malinen 	tx.sdata = sdata;
51570a3a8436SJouni Malinen 	__skb_queue_head_init(&tx.skbs);
51580a3a8436SJouni Malinen 	__skb_queue_tail(&tx.skbs, skb);
51590a3a8436SJouni Malinen 	res = ieee80211_tx_h_encrypt(&tx);
516095247705SJohannes Berg 	check_skb = __skb_dequeue(&tx.skbs);
516195247705SJohannes Berg 	/* we may crash after this, but it'd be a bug in crypto */
516295247705SJohannes Berg 	WARN_ON(check_skb != skb);
51630a3a8436SJouni Malinen 	if (WARN_ON_ONCE(res != TX_CONTINUE))
516495247705SJohannes Berg 		return -EINVAL;
51650a3a8436SJouni Malinen 
51660a3a8436SJouni Malinen 	return 0;
51670a3a8436SJouni Malinen }
51680a3a8436SJouni Malinen 
5169a6e34fdeSAloka Dixit static void
ieee80211_beacon_get_finish(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_link_data * link,struct ieee80211_mutable_offsets * offs,struct beacon_data * beacon,struct sk_buff * skb,struct ieee80211_chanctx_conf * chanctx_conf,u16 csa_off_base)5170a6e34fdeSAloka Dixit ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
5171a6e34fdeSAloka Dixit 			    struct ieee80211_vif *vif,
5172d8675a63SJohannes Berg 			    struct ieee80211_link_data *link,
5173a6e34fdeSAloka Dixit 			    struct ieee80211_mutable_offsets *offs,
5174a6e34fdeSAloka Dixit 			    struct beacon_data *beacon,
5175a6e34fdeSAloka Dixit 			    struct sk_buff *skb,
5176a6e34fdeSAloka Dixit 			    struct ieee80211_chanctx_conf *chanctx_conf,
5177d8675a63SJohannes Berg 			    u16 csa_off_base)
5178a6e34fdeSAloka Dixit {
5179a6e34fdeSAloka Dixit 	struct ieee80211_local *local = hw_to_local(hw);
5180a6e34fdeSAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5181a6e34fdeSAloka Dixit 	struct ieee80211_tx_info *info;
5182a6e34fdeSAloka Dixit 	enum nl80211_band band;
5183a6e34fdeSAloka Dixit 	struct ieee80211_tx_rate_control txrc;
5184a6e34fdeSAloka Dixit 
5185a6e34fdeSAloka Dixit 	/* CSA offsets */
5186a6e34fdeSAloka Dixit 	if (offs && beacon) {
5187a6e34fdeSAloka Dixit 		u16 i;
5188a6e34fdeSAloka Dixit 
5189a6e34fdeSAloka Dixit 		for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
5190a6e34fdeSAloka Dixit 			u16 csa_off = beacon->cntdwn_counter_offsets[i];
5191a6e34fdeSAloka Dixit 
5192a6e34fdeSAloka Dixit 			if (!csa_off)
5193a6e34fdeSAloka Dixit 				continue;
5194a6e34fdeSAloka Dixit 
5195a6e34fdeSAloka Dixit 			offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
5196a6e34fdeSAloka Dixit 		}
5197a6e34fdeSAloka Dixit 	}
5198a6e34fdeSAloka Dixit 
5199a6e34fdeSAloka Dixit 	band = chanctx_conf->def.chan->band;
5200a6e34fdeSAloka Dixit 	info = IEEE80211_SKB_CB(skb);
5201a6e34fdeSAloka Dixit 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
5202a6e34fdeSAloka Dixit 	info->flags |= IEEE80211_TX_CTL_NO_ACK;
5203a6e34fdeSAloka Dixit 	info->band = band;
5204a6e34fdeSAloka Dixit 
5205a6e34fdeSAloka Dixit 	memset(&txrc, 0, sizeof(txrc));
5206a6e34fdeSAloka Dixit 	txrc.hw = hw;
5207a6e34fdeSAloka Dixit 	txrc.sband = local->hw.wiphy->bands[band];
5208d8675a63SJohannes Berg 	txrc.bss_conf = link->conf;
5209a6e34fdeSAloka Dixit 	txrc.skb = skb;
5210a6e34fdeSAloka Dixit 	txrc.reported_rate.idx = -1;
5211a6e34fdeSAloka Dixit 	if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
5212a6e34fdeSAloka Dixit 		txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
5213a6e34fdeSAloka Dixit 	else
5214a6e34fdeSAloka Dixit 		txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
5215a6e34fdeSAloka Dixit 	txrc.bss = true;
5216a6e34fdeSAloka Dixit 	rate_control_get_rate(sdata, NULL, &txrc);
5217a6e34fdeSAloka Dixit 
5218a6e34fdeSAloka Dixit 	info->control.vif = vif;
52198b06d13eSJohannes Berg 	info->control.flags |= u32_encode_bits(link->link_id,
52208b06d13eSJohannes Berg 					       IEEE80211_TX_CTRL_MLO_LINK);
5221a6e34fdeSAloka Dixit 	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
5222a6e34fdeSAloka Dixit 		       IEEE80211_TX_CTL_ASSIGN_SEQ |
5223a6e34fdeSAloka Dixit 		       IEEE80211_TX_CTL_FIRST_FRAGMENT;
5224a6e34fdeSAloka Dixit }
5225a6e34fdeSAloka Dixit 
52262b3171c6SLorenzo Bianconi static void
ieee80211_beacon_add_mbssid(struct sk_buff * skb,struct beacon_data * beacon,u8 i)5227bd54f3c2SAloka Dixit ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
5228bd54f3c2SAloka Dixit 			    u8 i)
52292b3171c6SLorenzo Bianconi {
5230bd54f3c2SAloka Dixit 	if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt ||
5231bd54f3c2SAloka Dixit 	    i > beacon->mbssid_ies->cnt)
52322b3171c6SLorenzo Bianconi 		return;
52332b3171c6SLorenzo Bianconi 
5234bd54f3c2SAloka Dixit 	if (i < beacon->mbssid_ies->cnt) {
5235bd54f3c2SAloka Dixit 		skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
5236bd54f3c2SAloka Dixit 			     beacon->mbssid_ies->elem[i].len);
523768b9bea2SAloka Dixit 
523868b9bea2SAloka Dixit 		if (beacon->rnr_ies && beacon->rnr_ies->cnt) {
523968b9bea2SAloka Dixit 			skb_put_data(skb, beacon->rnr_ies->elem[i].data,
524068b9bea2SAloka Dixit 				     beacon->rnr_ies->elem[i].len);
524168b9bea2SAloka Dixit 
524268b9bea2SAloka Dixit 			for (i = beacon->mbssid_ies->cnt; i < beacon->rnr_ies->cnt; i++)
524368b9bea2SAloka Dixit 				skb_put_data(skb, beacon->rnr_ies->elem[i].data,
524468b9bea2SAloka Dixit 					     beacon->rnr_ies->elem[i].len);
524568b9bea2SAloka Dixit 		}
5246bd54f3c2SAloka Dixit 		return;
5247bd54f3c2SAloka Dixit 	}
5248bd54f3c2SAloka Dixit 
5249bd54f3c2SAloka Dixit 	/* i == beacon->mbssid_ies->cnt, include all MBSSID elements */
52502b3171c6SLorenzo Bianconi 	for (i = 0; i < beacon->mbssid_ies->cnt; i++)
52512b3171c6SLorenzo Bianconi 		skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
52522b3171c6SLorenzo Bianconi 			     beacon->mbssid_ies->elem[i].len);
52532b3171c6SLorenzo Bianconi }
52542b3171c6SLorenzo Bianconi 
5255a6e34fdeSAloka Dixit static struct sk_buff *
ieee80211_beacon_get_ap(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_link_data * link,struct ieee80211_mutable_offsets * offs,bool is_template,struct beacon_data * beacon,struct ieee80211_chanctx_conf * chanctx_conf,u8 ema_index)5256a6e34fdeSAloka Dixit ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
5257a6e34fdeSAloka Dixit 			struct ieee80211_vif *vif,
5258d8675a63SJohannes Berg 			struct ieee80211_link_data *link,
5259a6e34fdeSAloka Dixit 			struct ieee80211_mutable_offsets *offs,
5260a6e34fdeSAloka Dixit 			bool is_template,
5261a6e34fdeSAloka Dixit 			struct beacon_data *beacon,
5262bd54f3c2SAloka Dixit 			struct ieee80211_chanctx_conf *chanctx_conf,
5263bd54f3c2SAloka Dixit 			u8 ema_index)
5264a6e34fdeSAloka Dixit {
5265a6e34fdeSAloka Dixit 	struct ieee80211_local *local = hw_to_local(hw);
5266a6e34fdeSAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5267a6e34fdeSAloka Dixit 	struct ieee80211_if_ap *ap = &sdata->u.ap;
5268a6e34fdeSAloka Dixit 	struct sk_buff *skb = NULL;
5269a6e34fdeSAloka Dixit 	u16 csa_off_base = 0;
52702b3171c6SLorenzo Bianconi 	int mbssid_len;
5271a6e34fdeSAloka Dixit 
5272a6e34fdeSAloka Dixit 	if (beacon->cntdwn_counter_offsets[0]) {
5273a6e34fdeSAloka Dixit 		if (!is_template)
5274a6e34fdeSAloka Dixit 			ieee80211_beacon_update_cntdwn(vif);
5275a6e34fdeSAloka Dixit 
5276d8675a63SJohannes Berg 		ieee80211_set_beacon_cntdwn(sdata, beacon, link);
5277a6e34fdeSAloka Dixit 	}
5278a6e34fdeSAloka Dixit 
5279a6e34fdeSAloka Dixit 	/* headroom, head length,
52802b3171c6SLorenzo Bianconi 	 * tail length, maximum TIM length and multiple BSSID length
5281a6e34fdeSAloka Dixit 	 */
5282bd54f3c2SAloka Dixit 	mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
528368b9bea2SAloka Dixit 						     beacon->rnr_ies,
5284bd54f3c2SAloka Dixit 						     ema_index);
5285bd54f3c2SAloka Dixit 
5286a6e34fdeSAloka Dixit 	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
5287a6e34fdeSAloka Dixit 			    beacon->tail_len + 256 +
52882b3171c6SLorenzo Bianconi 			    local->hw.extra_beacon_tailroom + mbssid_len);
5289a6e34fdeSAloka Dixit 	if (!skb)
5290a6e34fdeSAloka Dixit 		return NULL;
5291a6e34fdeSAloka Dixit 
5292a6e34fdeSAloka Dixit 	skb_reserve(skb, local->tx_headroom);
5293a6e34fdeSAloka Dixit 	skb_put_data(skb, beacon->head, beacon->head_len);
5294a6e34fdeSAloka Dixit 
5295d8675a63SJohannes Berg 	ieee80211_beacon_add_tim(sdata, link, &ap->ps, skb, is_template);
5296a6e34fdeSAloka Dixit 
5297a6e34fdeSAloka Dixit 	if (offs) {
5298a6e34fdeSAloka Dixit 		offs->tim_offset = beacon->head_len;
5299a6e34fdeSAloka Dixit 		offs->tim_length = skb->len - beacon->head_len;
5300a6e34fdeSAloka Dixit 		offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
5301a6e34fdeSAloka Dixit 
53022b3171c6SLorenzo Bianconi 		if (mbssid_len) {
5303bd54f3c2SAloka Dixit 			ieee80211_beacon_add_mbssid(skb, beacon, ema_index);
53042b3171c6SLorenzo Bianconi 			offs->mbssid_off = skb->len - mbssid_len;
53052b3171c6SLorenzo Bianconi 		}
53062b3171c6SLorenzo Bianconi 
5307a6e34fdeSAloka Dixit 		/* for AP the csa offsets are from tail */
5308a6e34fdeSAloka Dixit 		csa_off_base = skb->len;
5309a6e34fdeSAloka Dixit 	}
5310a6e34fdeSAloka Dixit 
5311a6e34fdeSAloka Dixit 	if (beacon->tail)
5312a6e34fdeSAloka Dixit 		skb_put_data(skb, beacon->tail, beacon->tail_len);
5313a6e34fdeSAloka Dixit 
53149902dacdSDmitry Antipov 	if (ieee80211_beacon_protect(skb, local, sdata, link) < 0) {
53159902dacdSDmitry Antipov 		dev_kfree_skb(skb);
5316a6e34fdeSAloka Dixit 		return NULL;
53179902dacdSDmitry Antipov 	}
5318a6e34fdeSAloka Dixit 
5319d8675a63SJohannes Berg 	ieee80211_beacon_get_finish(hw, vif, link, offs, beacon, skb,
5320d8675a63SJohannes Berg 				    chanctx_conf, csa_off_base);
5321a6e34fdeSAloka Dixit 	return skb;
5322a6e34fdeSAloka Dixit }
5323a6e34fdeSAloka Dixit 
5324bd54f3c2SAloka Dixit static struct ieee80211_ema_beacons *
ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_link_data * link,struct ieee80211_mutable_offsets * offs,bool is_template,struct beacon_data * beacon,struct ieee80211_chanctx_conf * chanctx_conf)5325bd54f3c2SAloka Dixit ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
5326bd54f3c2SAloka Dixit 				 struct ieee80211_vif *vif,
5327bd54f3c2SAloka Dixit 				 struct ieee80211_link_data *link,
5328bd54f3c2SAloka Dixit 				 struct ieee80211_mutable_offsets *offs,
5329bd54f3c2SAloka Dixit 				 bool is_template, struct beacon_data *beacon,
5330bd54f3c2SAloka Dixit 				 struct ieee80211_chanctx_conf *chanctx_conf)
5331bd54f3c2SAloka Dixit {
5332bd54f3c2SAloka Dixit 	struct ieee80211_ema_beacons *ema = NULL;
5333bd54f3c2SAloka Dixit 
5334bd54f3c2SAloka Dixit 	if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt)
5335bd54f3c2SAloka Dixit 		return NULL;
5336bd54f3c2SAloka Dixit 
5337bd54f3c2SAloka Dixit 	ema = kzalloc(struct_size(ema, bcn, beacon->mbssid_ies->cnt),
5338bd54f3c2SAloka Dixit 		      GFP_ATOMIC);
5339bd54f3c2SAloka Dixit 	if (!ema)
5340bd54f3c2SAloka Dixit 		return NULL;
5341bd54f3c2SAloka Dixit 
5342bd54f3c2SAloka Dixit 	for (ema->cnt = 0; ema->cnt < beacon->mbssid_ies->cnt; ema->cnt++) {
5343bd54f3c2SAloka Dixit 		ema->bcn[ema->cnt].skb =
5344bd54f3c2SAloka Dixit 			ieee80211_beacon_get_ap(hw, vif, link,
5345bd54f3c2SAloka Dixit 						&ema->bcn[ema->cnt].offs,
5346bd54f3c2SAloka Dixit 						is_template, beacon,
5347bd54f3c2SAloka Dixit 						chanctx_conf, ema->cnt);
5348bd54f3c2SAloka Dixit 		if (!ema->bcn[ema->cnt].skb)
5349bd54f3c2SAloka Dixit 			break;
5350bd54f3c2SAloka Dixit 	}
5351bd54f3c2SAloka Dixit 
5352bd54f3c2SAloka Dixit 	if (ema->cnt == beacon->mbssid_ies->cnt)
5353bd54f3c2SAloka Dixit 		return ema;
5354bd54f3c2SAloka Dixit 
5355bd54f3c2SAloka Dixit 	ieee80211_beacon_free_ema_list(ema);
5356bd54f3c2SAloka Dixit 	return NULL;
5357bd54f3c2SAloka Dixit }
5358bd54f3c2SAloka Dixit 
5359bd54f3c2SAloka Dixit #define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS -1
5360bd54f3c2SAloka Dixit 
53616ec8c332SAndrei Otcheretianski static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_mutable_offsets * offs,bool is_template,unsigned int link_id,int ema_index,struct ieee80211_ema_beacons ** ema_beacons)53626ec8c332SAndrei Otcheretianski __ieee80211_beacon_get(struct ieee80211_hw *hw,
5363eddcbb94SJohannes Berg 		       struct ieee80211_vif *vif,
53646ec8c332SAndrei Otcheretianski 		       struct ieee80211_mutable_offsets *offs,
53656e8912a5SShaul Triebitz 		       bool is_template,
5366bd54f3c2SAloka Dixit 		       unsigned int link_id,
5367bd54f3c2SAloka Dixit 		       int ema_index,
5368bd54f3c2SAloka Dixit 		       struct ieee80211_ema_beacons **ema_beacons)
5369e2ebc74dSJohannes Berg {
5370e2ebc74dSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
5371af296bdbSMichal Kazior 	struct beacon_data *beacon = NULL;
53729d139c81SJohannes Berg 	struct sk_buff *skb = NULL;
5373e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = NULL;
537455de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
5375d8675a63SJohannes Berg 	struct ieee80211_link_data *link;
53768318d78aSJohannes Berg 
53775dfdaf58SJohannes Berg 	rcu_read_lock();
5378e2ebc74dSJohannes Berg 
537932bfd35dSJohannes Berg 	sdata = vif_to_sdata(vif);
5380d8675a63SJohannes Berg 	link = rcu_dereference(sdata->link[link_id]);
5381d8675a63SJohannes Berg 	if (!link)
5382d8675a63SJohannes Berg 		goto out;
53836e8912a5SShaul Triebitz 	chanctx_conf =
5384d8675a63SJohannes Berg 		rcu_dereference(link->conf->chanctx_conf);
538533b64eb2SLuis Carlos Cobo 
538655de908aSJohannes Berg 	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
5387eb3e554bSFelix Fietkau 		goto out;
5388eb3e554bSFelix Fietkau 
53896ec8c332SAndrei Otcheretianski 	if (offs)
53906ec8c332SAndrei Otcheretianski 		memset(offs, 0, sizeof(*offs));
5391eddcbb94SJohannes Berg 
539205c914feSJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
5393d8675a63SJohannes Berg 		beacon = rcu_dereference(link->u.ap.beacon);
5394a6e34fdeSAloka Dixit 		if (!beacon)
53955dfdaf58SJohannes Berg 			goto out;
5396e2ebc74dSJohannes Berg 
5397bd54f3c2SAloka Dixit 		if (ema_beacons) {
5398bd54f3c2SAloka Dixit 			*ema_beacons =
5399bd54f3c2SAloka Dixit 				ieee80211_beacon_get_ap_ema_list(hw, vif, link,
5400bd54f3c2SAloka Dixit 								 offs,
5401bd54f3c2SAloka Dixit 								 is_template,
5402bd54f3c2SAloka Dixit 								 beacon,
5403bd54f3c2SAloka Dixit 								 chanctx_conf);
5404bd54f3c2SAloka Dixit 		} else {
5405bd54f3c2SAloka Dixit 			if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
5406bd54f3c2SAloka Dixit 				if (ema_index >= beacon->mbssid_ies->cnt)
5407bd54f3c2SAloka Dixit 					goto out; /* End of MBSSID elements */
5408bd54f3c2SAloka Dixit 
5409bd54f3c2SAloka Dixit 				if (ema_index <= IEEE80211_INCLUDE_ALL_MBSSID_ELEMS)
5410bd54f3c2SAloka Dixit 					ema_index = beacon->mbssid_ies->cnt;
5411bd54f3c2SAloka Dixit 			} else {
5412bd54f3c2SAloka Dixit 				ema_index = 0;
5413bd54f3c2SAloka Dixit 			}
5414bd54f3c2SAloka Dixit 
5415bd54f3c2SAloka Dixit 			skb = ieee80211_beacon_get_ap(hw, vif, link, offs,
5416bd54f3c2SAloka Dixit 						      is_template, beacon,
5417bd54f3c2SAloka Dixit 						      chanctx_conf,
5418bd54f3c2SAloka Dixit 						      ema_index);
5419bd54f3c2SAloka Dixit 		}
542005c914feSJohannes Berg 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
542146900298SJohannes Berg 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
54229d139c81SJohannes Berg 		struct ieee80211_hdr *hdr;
542333b64eb2SLuis Carlos Cobo 
5424af296bdbSMichal Kazior 		beacon = rcu_dereference(ifibss->presp);
5425af296bdbSMichal Kazior 		if (!beacon)
54269d139c81SJohannes Berg 			goto out;
54279d139c81SJohannes Berg 
54288552a434SJohn Crispin 		if (beacon->cntdwn_counter_offsets[0]) {
54291af586c9SAndrei Otcheretianski 			if (!is_template)
54308552a434SJohn Crispin 				__ieee80211_beacon_update_cntdwn(beacon);
5431cd7760e6SSimon Wunderlich 
5432d8675a63SJohannes Berg 			ieee80211_set_beacon_cntdwn(sdata, beacon, link);
54331af586c9SAndrei Otcheretianski 		}
5434cd7760e6SSimon Wunderlich 
5435af296bdbSMichal Kazior 		skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
543670dabeb7SFelix Fietkau 				    local->hw.extra_beacon_tailroom);
54379d139c81SJohannes Berg 		if (!skb)
54389d139c81SJohannes Berg 			goto out;
5439c3ffeab4SJohannes Berg 		skb_reserve(skb, local->tx_headroom);
544059ae1d12SJohannes Berg 		skb_put_data(skb, beacon->head, beacon->head_len);
54419d139c81SJohannes Berg 
54429d139c81SJohannes Berg 		hdr = (struct ieee80211_hdr *) skb->data;
5443e7827a70SHarvey Harrison 		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
54449d139c81SJohannes Berg 						 IEEE80211_STYPE_BEACON);
5445a6e34fdeSAloka Dixit 
5446d8675a63SJohannes Berg 		ieee80211_beacon_get_finish(hw, vif, link, offs, beacon, skb,
5447d8675a63SJohannes Berg 					    chanctx_conf, 0);
5448902acc78SJohannes Berg 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
5449dbf498fbSJavier Cardona 		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
5450472dbc45SJohannes Berg 
5451af296bdbSMichal Kazior 		beacon = rcu_dereference(ifmsh->beacon);
5452af296bdbSMichal Kazior 		if (!beacon)
5453ac1bd846SJohannes Berg 			goto out;
5454ac1bd846SJohannes Berg 
54558552a434SJohn Crispin 		if (beacon->cntdwn_counter_offsets[0]) {
54561af586c9SAndrei Otcheretianski 			if (!is_template)
54571af586c9SAndrei Otcheretianski 				/* TODO: For mesh csa_counter is in TU, so
54581af586c9SAndrei Otcheretianski 				 * decrementing it by one isn't correct, but
54591af586c9SAndrei Otcheretianski 				 * for now we leave it consistent with overall
54601af586c9SAndrei Otcheretianski 				 * mac80211's behavior.
54611af586c9SAndrei Otcheretianski 				 */
54628552a434SJohn Crispin 				__ieee80211_beacon_update_cntdwn(beacon);
54631af586c9SAndrei Otcheretianski 
5464d8675a63SJohannes Berg 			ieee80211_set_beacon_cntdwn(sdata, beacon, link);
54651af586c9SAndrei Otcheretianski 		}
5466b8456a14SChun-Yeow Yeoh 
5467dbf498fbSJavier Cardona 		if (ifmsh->sync_ops)
5468445cd452SMasashi Honma 			ifmsh->sync_ops->adjust_tsf(sdata, beacon);
5469dbf498fbSJavier Cardona 
54703b69a9c5SThomas Pedersen 		skb = dev_alloc_skb(local->tx_headroom +
5471af296bdbSMichal Kazior 				    beacon->head_len +
54723f52b7e3SMarco Porsch 				    256 + /* TIM IE */
5473af296bdbSMichal Kazior 				    beacon->tail_len +
547470dabeb7SFelix Fietkau 				    local->hw.extra_beacon_tailroom);
5475902acc78SJohannes Berg 		if (!skb)
5476902acc78SJohannes Berg 			goto out;
54772b5e1967SThomas Pedersen 		skb_reserve(skb, local->tx_headroom);
547859ae1d12SJohannes Berg 		skb_put_data(skb, beacon->head, beacon->head_len);
5479d8675a63SJohannes Berg 		ieee80211_beacon_add_tim(sdata, link, &ifmsh->ps, skb,
5480d8675a63SJohannes Berg 					 is_template);
54816ec8c332SAndrei Otcheretianski 
54826ec8c332SAndrei Otcheretianski 		if (offs) {
5483af296bdbSMichal Kazior 			offs->tim_offset = beacon->head_len;
5484af296bdbSMichal Kazior 			offs->tim_length = skb->len - beacon->head_len;
54856ec8c332SAndrei Otcheretianski 		}
54866ec8c332SAndrei Otcheretianski 
548759ae1d12SJohannes Berg 		skb_put_data(skb, beacon->tail, beacon->tail_len);
5488d8675a63SJohannes Berg 		ieee80211_beacon_get_finish(hw, vif, link, offs, beacon, skb,
5489d8675a63SJohannes Berg 					    chanctx_conf, 0);
54909d139c81SJohannes Berg 	} else {
54919d139c81SJohannes Berg 		WARN_ON(1);
549233b64eb2SLuis Carlos Cobo 		goto out;
549333b64eb2SLuis Carlos Cobo 	}
549433b64eb2SLuis Carlos Cobo 
54955dfdaf58SJohannes Berg  out:
54965dfdaf58SJohannes Berg 	rcu_read_unlock();
5497e2ebc74dSJohannes Berg 	return skb;
54986ec8c332SAndrei Otcheretianski 
54996ec8c332SAndrei Otcheretianski }
55006ec8c332SAndrei Otcheretianski 
55016ec8c332SAndrei Otcheretianski struct sk_buff *
ieee80211_beacon_get_template(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_mutable_offsets * offs,unsigned int link_id)55026ec8c332SAndrei Otcheretianski ieee80211_beacon_get_template(struct ieee80211_hw *hw,
55036ec8c332SAndrei Otcheretianski 			      struct ieee80211_vif *vif,
55046e8912a5SShaul Triebitz 			      struct ieee80211_mutable_offsets *offs,
55056e8912a5SShaul Triebitz 			      unsigned int link_id)
55066ec8c332SAndrei Otcheretianski {
5507bd54f3c2SAloka Dixit 	return __ieee80211_beacon_get(hw, vif, offs, true, link_id,
5508bd54f3c2SAloka Dixit 				      IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, NULL);
55096ec8c332SAndrei Otcheretianski }
55106ec8c332SAndrei Otcheretianski EXPORT_SYMBOL(ieee80211_beacon_get_template);
55116ec8c332SAndrei Otcheretianski 
5512bd54f3c2SAloka Dixit struct sk_buff *
ieee80211_beacon_get_template_ema_index(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_mutable_offsets * offs,unsigned int link_id,u8 ema_index)5513bd54f3c2SAloka Dixit ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
5514bd54f3c2SAloka Dixit 					struct ieee80211_vif *vif,
5515bd54f3c2SAloka Dixit 					struct ieee80211_mutable_offsets *offs,
5516bd54f3c2SAloka Dixit 					unsigned int link_id, u8 ema_index)
5517bd54f3c2SAloka Dixit {
5518bd54f3c2SAloka Dixit 	return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index,
5519bd54f3c2SAloka Dixit 				      NULL);
5520bd54f3c2SAloka Dixit }
5521bd54f3c2SAloka Dixit EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index);
5522bd54f3c2SAloka Dixit 
ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons * ema_beacons)5523bd54f3c2SAloka Dixit void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons)
5524bd54f3c2SAloka Dixit {
5525bd54f3c2SAloka Dixit 	u8 i;
5526bd54f3c2SAloka Dixit 
5527bd54f3c2SAloka Dixit 	if (!ema_beacons)
5528bd54f3c2SAloka Dixit 		return;
5529bd54f3c2SAloka Dixit 
5530bd54f3c2SAloka Dixit 	for (i = 0; i < ema_beacons->cnt; i++)
5531bd54f3c2SAloka Dixit 		kfree_skb(ema_beacons->bcn[i].skb);
5532bd54f3c2SAloka Dixit 
5533bd54f3c2SAloka Dixit 	kfree(ema_beacons);
5534bd54f3c2SAloka Dixit }
5535bd54f3c2SAloka Dixit EXPORT_SYMBOL(ieee80211_beacon_free_ema_list);
5536bd54f3c2SAloka Dixit 
5537bd54f3c2SAloka Dixit struct ieee80211_ema_beacons *
ieee80211_beacon_get_template_ema_list(struct ieee80211_hw * hw,struct ieee80211_vif * vif,unsigned int link_id)5538bd54f3c2SAloka Dixit ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
5539bd54f3c2SAloka Dixit 				       struct ieee80211_vif *vif,
5540bd54f3c2SAloka Dixit 				       unsigned int link_id)
5541bd54f3c2SAloka Dixit {
5542bd54f3c2SAloka Dixit 	struct ieee80211_ema_beacons *ema_beacons = NULL;
5543bd54f3c2SAloka Dixit 
55441afa18e9SAditya Kumar Singh 	WARN_ON(__ieee80211_beacon_get(hw, vif, NULL, true, link_id, 0,
5545bd54f3c2SAloka Dixit 				       &ema_beacons));
5546bd54f3c2SAloka Dixit 
5547bd54f3c2SAloka Dixit 	return ema_beacons;
5548bd54f3c2SAloka Dixit }
5549bd54f3c2SAloka Dixit EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list);
5550bd54f3c2SAloka Dixit 
ieee80211_beacon_get_tim(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u16 * tim_offset,u16 * tim_length,unsigned int link_id)55516ec8c332SAndrei Otcheretianski struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
55526ec8c332SAndrei Otcheretianski 					 struct ieee80211_vif *vif,
55536e8912a5SShaul Triebitz 					 u16 *tim_offset, u16 *tim_length,
55546e8912a5SShaul Triebitz 					 unsigned int link_id)
55556ec8c332SAndrei Otcheretianski {
55566ec8c332SAndrei Otcheretianski 	struct ieee80211_mutable_offsets offs = {};
55576e8912a5SShaul Triebitz 	struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false,
5558bd54f3c2SAloka Dixit 						     link_id,
5559bd54f3c2SAloka Dixit 						     IEEE80211_INCLUDE_ALL_MBSSID_ELEMS,
5560bd54f3c2SAloka Dixit 						     NULL);
556135afa588SHelmut Schaa 	struct sk_buff *copy;
556235afa588SHelmut Schaa 	int shift;
556335afa588SHelmut Schaa 
556435afa588SHelmut Schaa 	if (!bcn)
556535afa588SHelmut Schaa 		return bcn;
55666ec8c332SAndrei Otcheretianski 
55676ec8c332SAndrei Otcheretianski 	if (tim_offset)
55686ec8c332SAndrei Otcheretianski 		*tim_offset = offs.tim_offset;
55696ec8c332SAndrei Otcheretianski 
55706ec8c332SAndrei Otcheretianski 	if (tim_length)
55716ec8c332SAndrei Otcheretianski 		*tim_length = offs.tim_length;
55726ec8c332SAndrei Otcheretianski 
557335afa588SHelmut Schaa 	if (ieee80211_hw_check(hw, BEACON_TX_STATUS) ||
557435afa588SHelmut Schaa 	    !hw_to_local(hw)->monitors)
557535afa588SHelmut Schaa 		return bcn;
557635afa588SHelmut Schaa 
557735afa588SHelmut Schaa 	/* send a copy to monitor interfaces */
557835afa588SHelmut Schaa 	copy = skb_copy(bcn, GFP_ATOMIC);
557935afa588SHelmut Schaa 	if (!copy)
558035afa588SHelmut Schaa 		return bcn;
558135afa588SHelmut Schaa 
558235afa588SHelmut Schaa 	shift = ieee80211_vif_get_shift(vif);
5583e5c0ee01SJohannes Berg 	ieee80211_tx_monitor(hw_to_local(hw), copy, 1, shift, false, NULL);
558435afa588SHelmut Schaa 
55856ec8c332SAndrei Otcheretianski 	return bcn;
5586e2ebc74dSJohannes Berg }
5587eddcbb94SJohannes Berg EXPORT_SYMBOL(ieee80211_beacon_get_tim);
5588e2ebc74dSJohannes Berg 
ieee80211_proberesp_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif)558902945821SArik Nemtsov struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
559002945821SArik Nemtsov 					struct ieee80211_vif *vif)
559102945821SArik Nemtsov {
5592aa7a0080SEyal Shapira 	struct sk_buff *skb = NULL;
5593aa7a0080SEyal Shapira 	struct probe_resp *presp = NULL;
559402945821SArik Nemtsov 	struct ieee80211_hdr *hdr;
559502945821SArik Nemtsov 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
559602945821SArik Nemtsov 
559702945821SArik Nemtsov 	if (sdata->vif.type != NL80211_IFTYPE_AP)
559802945821SArik Nemtsov 		return NULL;
559902945821SArik Nemtsov 
560002945821SArik Nemtsov 	rcu_read_lock();
5601bfd8403aSJohannes Berg 	presp = rcu_dereference(sdata->deflink.u.ap.probe_resp);
560202945821SArik Nemtsov 	if (!presp)
560302945821SArik Nemtsov 		goto out;
560402945821SArik Nemtsov 
5605aa7a0080SEyal Shapira 	skb = dev_alloc_skb(presp->len);
560602945821SArik Nemtsov 	if (!skb)
560702945821SArik Nemtsov 		goto out;
560802945821SArik Nemtsov 
560959ae1d12SJohannes Berg 	skb_put_data(skb, presp->data, presp->len);
5610aa7a0080SEyal Shapira 
561102945821SArik Nemtsov 	hdr = (struct ieee80211_hdr *) skb->data;
561202945821SArik Nemtsov 	memset(hdr->addr1, 0, sizeof(hdr->addr1));
561302945821SArik Nemtsov 
561402945821SArik Nemtsov out:
561502945821SArik Nemtsov 	rcu_read_unlock();
561602945821SArik Nemtsov 	return skb;
561702945821SArik Nemtsov }
561802945821SArik Nemtsov EXPORT_SYMBOL(ieee80211_proberesp_get);
561902945821SArik Nemtsov 
ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw * hw,struct ieee80211_vif * vif)5620295b02c4SAloka Dixit struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw,
5621295b02c4SAloka Dixit 						  struct ieee80211_vif *vif)
5622295b02c4SAloka Dixit {
5623295b02c4SAloka Dixit 	struct sk_buff *skb = NULL;
5624295b02c4SAloka Dixit 	struct fils_discovery_data *tmpl = NULL;
5625295b02c4SAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5626295b02c4SAloka Dixit 
5627295b02c4SAloka Dixit 	if (sdata->vif.type != NL80211_IFTYPE_AP)
5628295b02c4SAloka Dixit 		return NULL;
5629295b02c4SAloka Dixit 
5630295b02c4SAloka Dixit 	rcu_read_lock();
5631bfd8403aSJohannes Berg 	tmpl = rcu_dereference(sdata->deflink.u.ap.fils_discovery);
5632295b02c4SAloka Dixit 	if (!tmpl) {
5633295b02c4SAloka Dixit 		rcu_read_unlock();
5634295b02c4SAloka Dixit 		return NULL;
5635295b02c4SAloka Dixit 	}
5636295b02c4SAloka Dixit 
5637295b02c4SAloka Dixit 	skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
5638295b02c4SAloka Dixit 	if (skb) {
5639295b02c4SAloka Dixit 		skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
5640295b02c4SAloka Dixit 		skb_put_data(skb, tmpl->data, tmpl->len);
5641295b02c4SAloka Dixit 	}
5642295b02c4SAloka Dixit 
5643295b02c4SAloka Dixit 	rcu_read_unlock();
5644295b02c4SAloka Dixit 	return skb;
5645295b02c4SAloka Dixit }
5646295b02c4SAloka Dixit EXPORT_SYMBOL(ieee80211_get_fils_discovery_tmpl);
5647295b02c4SAloka Dixit 
5648632189a0SAloka Dixit struct sk_buff *
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw * hw,struct ieee80211_vif * vif)5649632189a0SAloka Dixit ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
5650632189a0SAloka Dixit 					  struct ieee80211_vif *vif)
5651632189a0SAloka Dixit {
5652632189a0SAloka Dixit 	struct sk_buff *skb = NULL;
5653632189a0SAloka Dixit 	struct unsol_bcast_probe_resp_data *tmpl = NULL;
5654632189a0SAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5655632189a0SAloka Dixit 
5656632189a0SAloka Dixit 	if (sdata->vif.type != NL80211_IFTYPE_AP)
5657632189a0SAloka Dixit 		return NULL;
5658632189a0SAloka Dixit 
5659632189a0SAloka Dixit 	rcu_read_lock();
5660bfd8403aSJohannes Berg 	tmpl = rcu_dereference(sdata->deflink.u.ap.unsol_bcast_probe_resp);
5661632189a0SAloka Dixit 	if (!tmpl) {
5662632189a0SAloka Dixit 		rcu_read_unlock();
5663632189a0SAloka Dixit 		return NULL;
5664632189a0SAloka Dixit 	}
5665632189a0SAloka Dixit 
5666632189a0SAloka Dixit 	skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
5667632189a0SAloka Dixit 	if (skb) {
5668632189a0SAloka Dixit 		skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
5669632189a0SAloka Dixit 		skb_put_data(skb, tmpl->data, tmpl->len);
5670632189a0SAloka Dixit 	}
5671632189a0SAloka Dixit 
5672632189a0SAloka Dixit 	rcu_read_unlock();
5673632189a0SAloka Dixit 	return skb;
5674632189a0SAloka Dixit }
5675632189a0SAloka Dixit EXPORT_SYMBOL(ieee80211_get_unsol_bcast_probe_resp_tmpl);
5676632189a0SAloka Dixit 
ieee80211_pspoll_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif)56777044cc56SKalle Valo struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
56787044cc56SKalle Valo 				     struct ieee80211_vif *vif)
56797044cc56SKalle Valo {
56807044cc56SKalle Valo 	struct ieee80211_sub_if_data *sdata;
56817044cc56SKalle Valo 	struct ieee80211_pspoll *pspoll;
56827044cc56SKalle Valo 	struct ieee80211_local *local;
56837044cc56SKalle Valo 	struct sk_buff *skb;
56847044cc56SKalle Valo 
56857044cc56SKalle Valo 	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
56867044cc56SKalle Valo 		return NULL;
56877044cc56SKalle Valo 
56887044cc56SKalle Valo 	sdata = vif_to_sdata(vif);
56897044cc56SKalle Valo 	local = sdata->local;
56907044cc56SKalle Valo 
56917044cc56SKalle Valo 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
5692d15b8459SJoe Perches 	if (!skb)
56937044cc56SKalle Valo 		return NULL;
5694d15b8459SJoe Perches 
56957044cc56SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
56967044cc56SKalle Valo 
5697b080db58SJohannes Berg 	pspoll = skb_put_zero(skb, sizeof(*pspoll));
56987044cc56SKalle Valo 	pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
56997044cc56SKalle Valo 					    IEEE80211_STYPE_PSPOLL);
5700f276e20bSJohannes Berg 	pspoll->aid = cpu_to_le16(sdata->vif.cfg.aid);
57017044cc56SKalle Valo 
57027044cc56SKalle Valo 	/* aid in PS-Poll has its two MSBs each set to 1 */
57037044cc56SKalle Valo 	pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
57047044cc56SKalle Valo 
5705bfd8403aSJohannes Berg 	memcpy(pspoll->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
57067044cc56SKalle Valo 	memcpy(pspoll->ta, vif->addr, ETH_ALEN);
57077044cc56SKalle Valo 
57087044cc56SKalle Valo 	return skb;
57097044cc56SKalle Valo }
57107044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_pspoll_get);
57117044cc56SKalle Valo 
ieee80211_nullfunc_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif,int link_id,bool qos_ok)57127044cc56SKalle Valo struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
57137b6ddeafSJohannes Berg 				       struct ieee80211_vif *vif,
57140ab26380SJohannes Berg 				       int link_id, bool qos_ok)
57157044cc56SKalle Valo {
57160ab26380SJohannes Berg 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
57170ab26380SJohannes Berg 	struct ieee80211_local *local = sdata->local;
57180ab26380SJohannes Berg 	struct ieee80211_link_data *link = NULL;
57197044cc56SKalle Valo 	struct ieee80211_hdr_3addr *nullfunc;
57207044cc56SKalle Valo 	struct sk_buff *skb;
57217b6ddeafSJohannes Berg 	bool qos = false;
57227044cc56SKalle Valo 
57237044cc56SKalle Valo 	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
57247044cc56SKalle Valo 		return NULL;
57257044cc56SKalle Valo 
57267b6ddeafSJohannes Berg 	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
57277b6ddeafSJohannes Berg 			    sizeof(*nullfunc) + 2);
5728d15b8459SJoe Perches 	if (!skb)
57297044cc56SKalle Valo 		return NULL;
5730d15b8459SJoe Perches 
57310ab26380SJohannes Berg 	rcu_read_lock();
57320ab26380SJohannes Berg 	if (qos_ok) {
57330ab26380SJohannes Berg 		struct sta_info *sta;
57340ab26380SJohannes Berg 
57350ab26380SJohannes Berg 		sta = sta_info_get(sdata, vif->cfg.ap_addr);
57360ab26380SJohannes Berg 		qos = sta && sta->sta.wme;
57370ab26380SJohannes Berg 	}
57380ab26380SJohannes Berg 
57390ab26380SJohannes Berg 	if (link_id >= 0) {
57400ab26380SJohannes Berg 		link = rcu_dereference(sdata->link[link_id]);
57410ab26380SJohannes Berg 		if (WARN_ON_ONCE(!link)) {
57420ab26380SJohannes Berg 			rcu_read_unlock();
57430ab26380SJohannes Berg 			kfree_skb(skb);
57440ab26380SJohannes Berg 			return NULL;
57450ab26380SJohannes Berg 		}
57460ab26380SJohannes Berg 	}
57470ab26380SJohannes Berg 
57487044cc56SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
57497044cc56SKalle Valo 
5750b080db58SJohannes Berg 	nullfunc = skb_put_zero(skb, sizeof(*nullfunc));
57517044cc56SKalle Valo 	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
57527044cc56SKalle Valo 					      IEEE80211_STYPE_NULLFUNC |
57537044cc56SKalle Valo 					      IEEE80211_FCTL_TODS);
57547b6ddeafSJohannes Berg 	if (qos) {
5755e0ba7095SJohannes Berg 		__le16 qoshdr = cpu_to_le16(7);
57567b6ddeafSJohannes Berg 
57577b6ddeafSJohannes Berg 		BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC |
57587b6ddeafSJohannes Berg 			      IEEE80211_STYPE_NULLFUNC) !=
57597b6ddeafSJohannes Berg 			     IEEE80211_STYPE_QOS_NULLFUNC);
57607b6ddeafSJohannes Berg 		nullfunc->frame_control |=
57617b6ddeafSJohannes Berg 			cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC);
57627b6ddeafSJohannes Berg 		skb->priority = 7;
57637b6ddeafSJohannes Berg 		skb_set_queue_mapping(skb, IEEE80211_AC_VO);
5764e0ba7095SJohannes Berg 		skb_put_data(skb, &qoshdr, sizeof(qoshdr));
57657b6ddeafSJohannes Berg 	}
57667b6ddeafSJohannes Berg 
57670ab26380SJohannes Berg 	if (link) {
57680ab26380SJohannes Berg 		memcpy(nullfunc->addr1, link->conf->bssid, ETH_ALEN);
57690ab26380SJohannes Berg 		memcpy(nullfunc->addr2, link->conf->addr, ETH_ALEN);
57700ab26380SJohannes Berg 		memcpy(nullfunc->addr3, link->conf->bssid, ETH_ALEN);
57710ab26380SJohannes Berg 	} else {
57720ab26380SJohannes Berg 		memcpy(nullfunc->addr1, vif->cfg.ap_addr, ETH_ALEN);
57737044cc56SKalle Valo 		memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
57740ab26380SJohannes Berg 		memcpy(nullfunc->addr3, vif->cfg.ap_addr, ETH_ALEN);
57750ab26380SJohannes Berg 	}
57760ab26380SJohannes Berg 	rcu_read_unlock();
57777044cc56SKalle Valo 
57787044cc56SKalle Valo 	return skb;
57797044cc56SKalle Valo }
57807044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_nullfunc_get);
57817044cc56SKalle Valo 
ieee80211_probereq_get(struct ieee80211_hw * hw,const u8 * src_addr,const u8 * ssid,size_t ssid_len,size_t tailroom)578205e54ea6SKalle Valo struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
5783a344d677SJohannes Berg 				       const u8 *src_addr,
578405e54ea6SKalle Valo 				       const u8 *ssid, size_t ssid_len,
5785b9a9ada1SJohannes Berg 				       size_t tailroom)
578605e54ea6SKalle Valo {
5787a344d677SJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
578805e54ea6SKalle Valo 	struct ieee80211_hdr_3addr *hdr;
578905e54ea6SKalle Valo 	struct sk_buff *skb;
579005e54ea6SKalle Valo 	size_t ie_ssid_len;
579105e54ea6SKalle Valo 	u8 *pos;
579205e54ea6SKalle Valo 
579305e54ea6SKalle Valo 	ie_ssid_len = 2 + ssid_len;
579405e54ea6SKalle Valo 
579505e54ea6SKalle Valo 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
5796b9a9ada1SJohannes Berg 			    ie_ssid_len + tailroom);
5797d15b8459SJoe Perches 	if (!skb)
579805e54ea6SKalle Valo 		return NULL;
579905e54ea6SKalle Valo 
580005e54ea6SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
580105e54ea6SKalle Valo 
5802b080db58SJohannes Berg 	hdr = skb_put_zero(skb, sizeof(*hdr));
580305e54ea6SKalle Valo 	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
580405e54ea6SKalle Valo 					 IEEE80211_STYPE_PROBE_REQ);
5805e83e6541SJohannes Berg 	eth_broadcast_addr(hdr->addr1);
5806a344d677SJohannes Berg 	memcpy(hdr->addr2, src_addr, ETH_ALEN);
5807e83e6541SJohannes Berg 	eth_broadcast_addr(hdr->addr3);
580805e54ea6SKalle Valo 
580905e54ea6SKalle Valo 	pos = skb_put(skb, ie_ssid_len);
581005e54ea6SKalle Valo 	*pos++ = WLAN_EID_SSID;
581105e54ea6SKalle Valo 	*pos++ = ssid_len;
581288c868c4SStanislaw Gruszka 	if (ssid_len)
581305e54ea6SKalle Valo 		memcpy(pos, ssid, ssid_len);
581405e54ea6SKalle Valo 	pos += ssid_len;
581505e54ea6SKalle Valo 
581605e54ea6SKalle Valo 	return skb;
581705e54ea6SKalle Valo }
581805e54ea6SKalle Valo EXPORT_SYMBOL(ieee80211_probereq_get);
581905e54ea6SKalle Valo 
ieee80211_rts_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const void * frame,size_t frame_len,const struct ieee80211_tx_info * frame_txctl,struct ieee80211_rts * rts)582032bfd35dSJohannes Berg void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5821e2ebc74dSJohannes Berg 		       const void *frame, size_t frame_len,
5822e039fa4aSJohannes Berg 		       const struct ieee80211_tx_info *frame_txctl,
5823e2ebc74dSJohannes Berg 		       struct ieee80211_rts *rts)
5824e2ebc74dSJohannes Berg {
5825e2ebc74dSJohannes Berg 	const struct ieee80211_hdr *hdr = frame;
5826e2ebc74dSJohannes Berg 
5827065e9605SHarvey Harrison 	rts->frame_control =
5828065e9605SHarvey Harrison 	    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
582932bfd35dSJohannes Berg 	rts->duration = ieee80211_rts_duration(hw, vif, frame_len,
583032bfd35dSJohannes Berg 					       frame_txctl);
5831e2ebc74dSJohannes Berg 	memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
5832e2ebc74dSJohannes Berg 	memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
5833e2ebc74dSJohannes Berg }
5834e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_get);
5835e2ebc74dSJohannes Berg 
ieee80211_ctstoself_get(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const void * frame,size_t frame_len,const struct ieee80211_tx_info * frame_txctl,struct ieee80211_cts * cts)583632bfd35dSJohannes Berg void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5837e2ebc74dSJohannes Berg 			     const void *frame, size_t frame_len,
5838e039fa4aSJohannes Berg 			     const struct ieee80211_tx_info *frame_txctl,
5839e2ebc74dSJohannes Berg 			     struct ieee80211_cts *cts)
5840e2ebc74dSJohannes Berg {
5841e2ebc74dSJohannes Berg 	const struct ieee80211_hdr *hdr = frame;
5842e2ebc74dSJohannes Berg 
5843065e9605SHarvey Harrison 	cts->frame_control =
5844065e9605SHarvey Harrison 	    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
584532bfd35dSJohannes Berg 	cts->duration = ieee80211_ctstoself_duration(hw, vif,
584632bfd35dSJohannes Berg 						     frame_len, frame_txctl);
5847e2ebc74dSJohannes Berg 	memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
5848e2ebc74dSJohannes Berg }
5849e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_get);
5850e2ebc74dSJohannes Berg 
5851e2ebc74dSJohannes Berg struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw * hw,struct ieee80211_vif * vif)585232bfd35dSJohannes Berg ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
5853e039fa4aSJohannes Berg 			  struct ieee80211_vif *vif)
5854e2ebc74dSJohannes Berg {
5855e2ebc74dSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
5856747cf5e9STomas Winkler 	struct sk_buff *skb = NULL;
58575cf121c3SJohannes Berg 	struct ieee80211_tx_data tx;
5858e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata;
5859d012a605SMarco Porsch 	struct ps_data *ps;
5860e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info;
586155de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
5862e2ebc74dSJohannes Berg 
586332bfd35dSJohannes Berg 	sdata = vif_to_sdata(vif);
58645dfdaf58SJohannes Berg 
58655dfdaf58SJohannes Berg 	rcu_read_lock();
5866d0a9123eSJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
58675dfdaf58SJohannes Berg 
5868d012a605SMarco Porsch 	if (!chanctx_conf)
5869747cf5e9STomas Winkler 		goto out;
58705dfdaf58SJohannes Berg 
5871d012a605SMarco Porsch 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
5872d012a605SMarco Porsch 		struct beacon_data *beacon =
5873bfd8403aSJohannes Berg 				rcu_dereference(sdata->deflink.u.ap.beacon);
5874d012a605SMarco Porsch 
5875d012a605SMarco Porsch 		if (!beacon || !beacon->head)
5876d012a605SMarco Porsch 			goto out;
5877d012a605SMarco Porsch 
5878d012a605SMarco Porsch 		ps = &sdata->u.ap.ps;
58793f52b7e3SMarco Porsch 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
58803f52b7e3SMarco Porsch 		ps = &sdata->u.mesh.ps;
5881d012a605SMarco Porsch 	} else {
5882d012a605SMarco Porsch 		goto out;
5883d012a605SMarco Porsch 	}
5884d012a605SMarco Porsch 
5885d012a605SMarco Porsch 	if (ps->dtim_count != 0 || !ps->dtim_bc_mc)
5886747cf5e9STomas Winkler 		goto out; /* send buffered bc/mc only after DTIM beacon */
5887e039fa4aSJohannes Berg 
5888e2ebc74dSJohannes Berg 	while (1) {
5889d012a605SMarco Porsch 		skb = skb_dequeue(&ps->bc_buf);
5890e2ebc74dSJohannes Berg 		if (!skb)
5891747cf5e9STomas Winkler 			goto out;
5892e2ebc74dSJohannes Berg 		local->total_ps_buffered--;
5893e2ebc74dSJohannes Berg 
5894d012a605SMarco Porsch 		if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) {
5895e2ebc74dSJohannes Berg 			struct ieee80211_hdr *hdr =
5896e2ebc74dSJohannes Berg 				(struct ieee80211_hdr *) skb->data;
5897e2ebc74dSJohannes Berg 			/* more buffered multicast/broadcast frames ==> set
5898e2ebc74dSJohannes Berg 			 * MoreData flag in IEEE 802.11 header to inform PS
5899e2ebc74dSJohannes Berg 			 * STAs */
5900e2ebc74dSJohannes Berg 			hdr->frame_control |=
5901e2ebc74dSJohannes Berg 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5902e2ebc74dSJohannes Berg 		}
5903e2ebc74dSJohannes Berg 
5904112c44b2SMichael Braun 		if (sdata->vif.type == NL80211_IFTYPE_AP)
5905de74a1d9SMichael Braun 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
59067c10770fSJohannes Berg 		if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
5907e2ebc74dSJohannes Berg 			break;
59086b07d9caSFelix Fietkau 		ieee80211_free_txskb(hw, skb);
5909e2ebc74dSJohannes Berg 	}
5910e039fa4aSJohannes Berg 
5911e039fa4aSJohannes Berg 	info = IEEE80211_SKB_CB(skb);
5912e039fa4aSJohannes Berg 
59135cf121c3SJohannes Berg 	tx.flags |= IEEE80211_TX_PS_BUFFERED;
59144bf88530SJohannes Berg 	info->band = chanctx_conf->def.chan->band;
5915e2ebc74dSJohannes Berg 
591697b045d6SJohannes Berg 	if (invoke_tx_handlers(&tx))
5917e2ebc74dSJohannes Berg 		skb = NULL;
5918747cf5e9STomas Winkler  out:
5919d0709a65SJohannes Berg 	rcu_read_unlock();
5920e2ebc74dSJohannes Berg 
5921e2ebc74dSJohannes Berg 	return skb;
5922e2ebc74dSJohannes Berg }
5923e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_get_buffered_bc);
59243b8d81e0SJohannes Berg 
ieee80211_reserve_tid(struct ieee80211_sta * pubsta,u8 tid)5925b6da911bSLiad Kaufman int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
5926b6da911bSLiad Kaufman {
5927b6da911bSLiad Kaufman 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
5928b6da911bSLiad Kaufman 	struct ieee80211_sub_if_data *sdata = sta->sdata;
5929b6da911bSLiad Kaufman 	struct ieee80211_local *local = sdata->local;
5930b6da911bSLiad Kaufman 	int ret;
5931b6da911bSLiad Kaufman 	u32 queues;
5932b6da911bSLiad Kaufman 
5933b6da911bSLiad Kaufman 	lockdep_assert_held(&local->sta_mtx);
5934b6da911bSLiad Kaufman 
5935b6da911bSLiad Kaufman 	/* only some cases are supported right now */
5936b6da911bSLiad Kaufman 	switch (sdata->vif.type) {
5937b6da911bSLiad Kaufman 	case NL80211_IFTYPE_STATION:
5938b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP:
5939b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP_VLAN:
5940b6da911bSLiad Kaufman 		break;
5941b6da911bSLiad Kaufman 	default:
5942b6da911bSLiad Kaufman 		WARN_ON(1);
5943b6da911bSLiad Kaufman 		return -EINVAL;
5944b6da911bSLiad Kaufman 	}
5945b6da911bSLiad Kaufman 
5946b6da911bSLiad Kaufman 	if (WARN_ON(tid >= IEEE80211_NUM_UPS))
5947b6da911bSLiad Kaufman 		return -EINVAL;
5948b6da911bSLiad Kaufman 
5949b6da911bSLiad Kaufman 	if (sta->reserved_tid == tid) {
5950b6da911bSLiad Kaufman 		ret = 0;
5951b6da911bSLiad Kaufman 		goto out;
5952b6da911bSLiad Kaufman 	}
5953b6da911bSLiad Kaufman 
5954b6da911bSLiad Kaufman 	if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
5955b6da911bSLiad Kaufman 		sdata_err(sdata, "TID reservation already active\n");
5956b6da911bSLiad Kaufman 		ret = -EALREADY;
5957b6da911bSLiad Kaufman 		goto out;
5958b6da911bSLiad Kaufman 	}
5959b6da911bSLiad Kaufman 
5960b6da911bSLiad Kaufman 	ieee80211_stop_vif_queues(sdata->local, sdata,
5961b6da911bSLiad Kaufman 				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
5962b6da911bSLiad Kaufman 
5963b6da911bSLiad Kaufman 	synchronize_net();
5964b6da911bSLiad Kaufman 
5965b6da911bSLiad Kaufman 	/* Tear down BA sessions so we stop aggregating on this TID */
596630686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) {
5967b6da911bSLiad Kaufman 		set_sta_flag(sta, WLAN_STA_BLOCK_BA);
5968b6da911bSLiad Kaufman 		__ieee80211_stop_tx_ba_session(sta, tid,
5969b6da911bSLiad Kaufman 					       AGG_STOP_LOCAL_REQUEST);
5970b6da911bSLiad Kaufman 	}
5971b6da911bSLiad Kaufman 
5972b6da911bSLiad Kaufman 	queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
59733b24f4c6SEmmanuel Grumbach 	__ieee80211_flush_queues(local, sdata, queues, false);
5974b6da911bSLiad Kaufman 
5975b6da911bSLiad Kaufman 	sta->reserved_tid = tid;
5976b6da911bSLiad Kaufman 
5977b6da911bSLiad Kaufman 	ieee80211_wake_vif_queues(local, sdata,
5978b6da911bSLiad Kaufman 				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
5979b6da911bSLiad Kaufman 
598030686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION))
5981b6da911bSLiad Kaufman 		clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
5982b6da911bSLiad Kaufman 
5983b6da911bSLiad Kaufman 	ret = 0;
5984b6da911bSLiad Kaufman  out:
5985b6da911bSLiad Kaufman 	return ret;
5986b6da911bSLiad Kaufman }
5987b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_reserve_tid);
5988b6da911bSLiad Kaufman 
ieee80211_unreserve_tid(struct ieee80211_sta * pubsta,u8 tid)5989b6da911bSLiad Kaufman void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
5990b6da911bSLiad Kaufman {
5991b6da911bSLiad Kaufman 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
5992b6da911bSLiad Kaufman 	struct ieee80211_sub_if_data *sdata = sta->sdata;
5993b6da911bSLiad Kaufman 
5994b6da911bSLiad Kaufman 	lockdep_assert_held(&sdata->local->sta_mtx);
5995b6da911bSLiad Kaufman 
5996b6da911bSLiad Kaufman 	/* only some cases are supported right now */
5997b6da911bSLiad Kaufman 	switch (sdata->vif.type) {
5998b6da911bSLiad Kaufman 	case NL80211_IFTYPE_STATION:
5999b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP:
6000b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP_VLAN:
6001b6da911bSLiad Kaufman 		break;
6002b6da911bSLiad Kaufman 	default:
6003b6da911bSLiad Kaufman 		WARN_ON(1);
6004b6da911bSLiad Kaufman 		return;
6005b6da911bSLiad Kaufman 	}
6006b6da911bSLiad Kaufman 
6007b6da911bSLiad Kaufman 	if (tid != sta->reserved_tid) {
6008b6da911bSLiad Kaufman 		sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
6009b6da911bSLiad Kaufman 		return;
6010b6da911bSLiad Kaufman 	}
6011b6da911bSLiad Kaufman 
6012b6da911bSLiad Kaufman 	sta->reserved_tid = IEEE80211_TID_UNRESERVED;
6013b6da911bSLiad Kaufman }
6014b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_unreserve_tid);
6015b6da911bSLiad Kaufman 
__ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,int tid,int link_id,enum nl80211_band band)601655de908aSJohannes Berg void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
6017e1e68b14SJohannes Berg 				 struct sk_buff *skb, int tid, int link_id,
601808aca29aSMathy Vanhoef 				 enum nl80211_band band)
60193b8d81e0SJohannes Berg {
602069d41b5aSJohannes Berg 	const struct ieee80211_hdr *hdr = (void *)skb->data;
6021731977e9SAmadeusz Sławiński 	int ac = ieee80211_ac_from_tid(tid);
602269d41b5aSJohannes Berg 	unsigned int link;
60233a25a8c8SJohannes Berg 
6024d57a544dSZhang Shengju 	skb_reset_mac_header(skb);
60253a25a8c8SJohannes Berg 	skb_set_queue_mapping(skb, ac);
6026cf6bb79aSHelmut Schaa 	skb->priority = tid;
6027cf0277e7SJohannes Berg 
602889afe614SJohannes Berg 	skb->dev = sdata->dev;
602989afe614SJohannes Berg 
603069d41b5aSJohannes Berg 	BUILD_BUG_ON(IEEE80211_LINK_UNSPECIFIED < IEEE80211_MLD_MAX_NUM_LINKS);
603169d41b5aSJohannes Berg 	BUILD_BUG_ON(!FIELD_FIT(IEEE80211_TX_CTRL_MLO_LINK,
603269d41b5aSJohannes Berg 				IEEE80211_LINK_UNSPECIFIED));
603369d41b5aSJohannes Berg 
6034f1871abdSIlan Peer 	if (!ieee80211_vif_is_mld(&sdata->vif)) {
603569d41b5aSJohannes Berg 		link = 0;
6036e1e68b14SJohannes Berg 	} else if (link_id >= 0) {
6037e1e68b14SJohannes Berg 		link = link_id;
603869d41b5aSJohannes Berg 	} else if (memcmp(sdata->vif.addr, hdr->addr2, ETH_ALEN) == 0) {
603969d41b5aSJohannes Berg 		/* address from the MLD */
604069d41b5aSJohannes Berg 		link = IEEE80211_LINK_UNSPECIFIED;
604169d41b5aSJohannes Berg 	} else {
604269d41b5aSJohannes Berg 		/* otherwise must be addressed from a link */
6043d8675a63SJohannes Berg 		rcu_read_lock();
604469d41b5aSJohannes Berg 		for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
6045d8675a63SJohannes Berg 			struct ieee80211_bss_conf *link_conf;
6046d8675a63SJohannes Berg 
6047d8675a63SJohannes Berg 			link_conf = rcu_dereference(sdata->vif.link_conf[link]);
6048d8675a63SJohannes Berg 			if (!link_conf)
6049d8675a63SJohannes Berg 				continue;
6050d8675a63SJohannes Berg 			if (memcmp(link_conf->addr, hdr->addr2, ETH_ALEN) == 0)
605169d41b5aSJohannes Berg 				break;
605269d41b5aSJohannes Berg 		}
6053d8675a63SJohannes Berg 		rcu_read_unlock();
605469d41b5aSJohannes Berg 
605569d41b5aSJohannes Berg 		if (WARN_ON_ONCE(link == ARRAY_SIZE(sdata->vif.link_conf)))
60567b3b9ac8SIlan Peer 			link = ffs(sdata->vif.active_links) - 1;
605769d41b5aSJohannes Berg 	}
605869d41b5aSJohannes Berg 
605969d41b5aSJohannes Berg 	IEEE80211_SKB_CB(skb)->control.flags |=
606069d41b5aSJohannes Berg 		u32_encode_bits(link, IEEE80211_TX_CTRL_MLO_LINK);
606169d41b5aSJohannes Berg 
60623d34deb6SJohannes Berg 	/*
60633d34deb6SJohannes Berg 	 * The other path calling ieee80211_xmit is from the tasklet,
60643d34deb6SJohannes Berg 	 * and while we can handle concurrent transmissions locking
60653d34deb6SJohannes Berg 	 * requirements are that we do not come into tx with bhs on.
60663d34deb6SJohannes Berg 	 */
60673d34deb6SJohannes Berg 	local_bh_disable();
606873c4e195SJohannes Berg 	IEEE80211_SKB_CB(skb)->band = band;
606908aca29aSMathy Vanhoef 	ieee80211_xmit(sdata, NULL, skb);
60703d34deb6SJohannes Berg 	local_bh_enable();
60713b8d81e0SJohannes Berg }
607291180649SDenis Kenzior 
ieee80211_tx_skb_tid(struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,int tid,int link_id)6073eef25a66SJohannes Berg void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
6074e1e68b14SJohannes Berg 			  struct sk_buff *skb, int tid, int link_id)
6075eef25a66SJohannes Berg {
6076eef25a66SJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
6077eef25a66SJohannes Berg 	enum nl80211_band band;
6078eef25a66SJohannes Berg 
6079eef25a66SJohannes Berg 	rcu_read_lock();
6080f1871abdSIlan Peer 	if (!ieee80211_vif_is_mld(&sdata->vif)) {
6081e1e68b14SJohannes Berg 		WARN_ON(link_id >= 0);
6082eef25a66SJohannes Berg 		chanctx_conf =
6083eef25a66SJohannes Berg 			rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
6084eef25a66SJohannes Berg 		if (WARN_ON(!chanctx_conf)) {
6085eef25a66SJohannes Berg 			rcu_read_unlock();
6086eef25a66SJohannes Berg 			kfree_skb(skb);
6087eef25a66SJohannes Berg 			return;
6088eef25a66SJohannes Berg 		}
6089eef25a66SJohannes Berg 		band = chanctx_conf->def.chan->band;
6090eef25a66SJohannes Berg 	} else {
6091e1e68b14SJohannes Berg 		WARN_ON(link_id >= 0 &&
60927b3b9ac8SIlan Peer 			!(sdata->vif.active_links & BIT(link_id)));
6093eef25a66SJohannes Berg 		/* MLD transmissions must not rely on the band */
6094eef25a66SJohannes Berg 		band = 0;
6095eef25a66SJohannes Berg 	}
6096eef25a66SJohannes Berg 
6097e1e68b14SJohannes Berg 	__ieee80211_tx_skb_tid_band(sdata, skb, tid, link_id, band);
6098eef25a66SJohannes Berg 	rcu_read_unlock();
6099eef25a66SJohannes Berg }
6100eef25a66SJohannes Berg 
ieee80211_tx_control_port(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len,const u8 * dest,__be16 proto,bool unencrypted,int link_id,u64 * cookie)610191180649SDenis Kenzior int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
610291180649SDenis Kenzior 			      const u8 *buf, size_t len,
6103dca9ca2dSMarkus Theil 			      const u8 *dest, __be16 proto, bool unencrypted,
610467207babSAndrei Otcheretianski 			      int link_id, u64 *cookie)
610591180649SDenis Kenzior {
610691180649SDenis Kenzior 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
610791180649SDenis Kenzior 	struct ieee80211_local *local = sdata->local;
610810cb8e61SMarkus Theil 	struct sta_info *sta;
610991180649SDenis Kenzior 	struct sk_buff *skb;
611091180649SDenis Kenzior 	struct ethhdr *ehdr;
6111b95d2ccdSJohannes Berg 	u32 ctrl_flags = 0;
6112a7528198SMarkus Theil 	u32 flags = 0;
6113dd820ed6SJohannes Berg 	int err;
611491180649SDenis Kenzior 
611591180649SDenis Kenzior 	/* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE
611691180649SDenis Kenzior 	 * or Pre-Authentication
611791180649SDenis Kenzior 	 */
611891180649SDenis Kenzior 	if (proto != sdata->control_port_protocol &&
611991180649SDenis Kenzior 	    proto != cpu_to_be16(ETH_P_PREAUTH))
612091180649SDenis Kenzior 		return -EINVAL;
612191180649SDenis Kenzior 
6122b95d2ccdSJohannes Berg 	if (proto == sdata->control_port_protocol)
61235af7fef3SMarkus Theil 		ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO |
61245af7fef3SMarkus Theil 			      IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
6125b95d2ccdSJohannes Berg 
612691180649SDenis Kenzior 	if (unencrypted)
6127a7528198SMarkus Theil 		flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
6128a7528198SMarkus Theil 
6129a7528198SMarkus Theil 	if (cookie)
6130a7528198SMarkus Theil 		ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
6131a7528198SMarkus Theil 
613210cb8e61SMarkus Theil 	flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX;
613391180649SDenis Kenzior 
613491180649SDenis Kenzior 	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
613591180649SDenis Kenzior 			    sizeof(struct ethhdr) + len);
613691180649SDenis Kenzior 	if (!skb)
613791180649SDenis Kenzior 		return -ENOMEM;
613891180649SDenis Kenzior 
613991180649SDenis Kenzior 	skb_reserve(skb, local->hw.extra_tx_headroom + sizeof(struct ethhdr));
614091180649SDenis Kenzior 
614191180649SDenis Kenzior 	skb_put_data(skb, buf, len);
614291180649SDenis Kenzior 
614391180649SDenis Kenzior 	ehdr = skb_push(skb, sizeof(struct ethhdr));
614491180649SDenis Kenzior 	memcpy(ehdr->h_dest, dest, ETH_ALEN);
614567207babSAndrei Otcheretianski 
61469dd19538SJohannes Berg 	/* we may override the SA for MLO STA later */
614767207babSAndrei Otcheretianski 	if (link_id < 0) {
61489dd19538SJohannes Berg 		ctrl_flags |= u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
61499dd19538SJohannes Berg 					      IEEE80211_TX_CTRL_MLO_LINK);
61508079e4feSJohannes Berg 		memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
615167207babSAndrei Otcheretianski 	} else {
615267207babSAndrei Otcheretianski 		struct ieee80211_bss_conf *link_conf;
615367207babSAndrei Otcheretianski 
61549dd19538SJohannes Berg 		ctrl_flags |= u32_encode_bits(link_id,
61559dd19538SJohannes Berg 					      IEEE80211_TX_CTRL_MLO_LINK);
61569dd19538SJohannes Berg 
615767207babSAndrei Otcheretianski 		rcu_read_lock();
615867207babSAndrei Otcheretianski 		link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
615967207babSAndrei Otcheretianski 		if (!link_conf) {
616067207babSAndrei Otcheretianski 			dev_kfree_skb(skb);
616167207babSAndrei Otcheretianski 			rcu_read_unlock();
616267207babSAndrei Otcheretianski 			return -ENOLINK;
616367207babSAndrei Otcheretianski 		}
616467207babSAndrei Otcheretianski 		memcpy(ehdr->h_source, link_conf->addr, ETH_ALEN);
616567207babSAndrei Otcheretianski 		rcu_read_unlock();
616667207babSAndrei Otcheretianski 	}
616767207babSAndrei Otcheretianski 
616891180649SDenis Kenzior 	ehdr->h_proto = proto;
616991180649SDenis Kenzior 
617091180649SDenis Kenzior 	skb->dev = dev;
617110cb8e61SMarkus Theil 	skb->protocol = proto;
617291180649SDenis Kenzior 	skb_reset_network_header(skb);
617391180649SDenis Kenzior 	skb_reset_mac_header(skb);
617491180649SDenis Kenzior 
6175d873697eSHans de Goede 	if (local->hw.queues < IEEE80211_NUM_ACS)
6176d873697eSHans de Goede 		goto start_xmit;
6177d873697eSHans de Goede 
617810cb8e61SMarkus Theil 	/* update QoS header to prioritize control port frames if possible,
617910cb8e61SMarkus Theil 	 * priorization also happens for control port frames send over
618010cb8e61SMarkus Theil 	 * AF_PACKET
618110cb8e61SMarkus Theil 	 */
618210cb8e61SMarkus Theil 	rcu_read_lock();
6183dd820ed6SJohannes Berg 	err = ieee80211_lookup_ra_sta(sdata, skb, &sta);
6184dd820ed6SJohannes Berg 	if (err) {
618562b03f45SYang Yingliang 		dev_kfree_skb(skb);
6186dd820ed6SJohannes Berg 		rcu_read_unlock();
6187dd820ed6SJohannes Berg 		return err;
6188dd820ed6SJohannes Berg 	}
618910cb8e61SMarkus Theil 
6190dd820ed6SJohannes Berg 	if (!IS_ERR(sta)) {
6191107395f9SAlexander Wetzel 		u16 queue = ieee80211_select_queue(sdata, sta, skb);
619210cb8e61SMarkus Theil 
619310cb8e61SMarkus Theil 		skb_set_queue_mapping(skb, queue);
61949dd19538SJohannes Berg 
61959dd19538SJohannes Berg 		/*
61969dd19538SJohannes Berg 		 * for MLO STA, the SA should be the AP MLD address, but
61979dd19538SJohannes Berg 		 * the link ID has been selected already
61989dd19538SJohannes Berg 		 */
619955f0a489SDan Carpenter 		if (sta && sta->sta.mlo)
62009dd19538SJohannes Berg 			memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
620110cb8e61SMarkus Theil 	}
620210cb8e61SMarkus Theil 	rcu_read_unlock();
620310cb8e61SMarkus Theil 
6204d873697eSHans de Goede start_xmit:
6205a7528198SMarkus Theil 	/* mutex lock is only needed for incrementing the cookie counter */
6206a7528198SMarkus Theil 	mutex_lock(&local->mtx);
6207a7528198SMarkus Theil 
6208e7441c92SDenis Kenzior 	local_bh_disable();
6209a7528198SMarkus Theil 	__ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags, cookie);
6210e7441c92SDenis Kenzior 	local_bh_enable();
621191180649SDenis Kenzior 
6212a7528198SMarkus Theil 	mutex_unlock(&local->mtx);
6213a7528198SMarkus Theil 
621491180649SDenis Kenzior 	return 0;
621591180649SDenis Kenzior }
62168828f81aSRajkumar Manoharan 
ieee80211_probe_mesh_link(struct wiphy * wiphy,struct net_device * dev,const u8 * buf,size_t len)62178828f81aSRajkumar Manoharan int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
62188828f81aSRajkumar Manoharan 			      const u8 *buf, size_t len)
62198828f81aSRajkumar Manoharan {
62208828f81aSRajkumar Manoharan 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
62218828f81aSRajkumar Manoharan 	struct ieee80211_local *local = sdata->local;
62228828f81aSRajkumar Manoharan 	struct sk_buff *skb;
62238828f81aSRajkumar Manoharan 
62248828f81aSRajkumar Manoharan 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + len +
62258828f81aSRajkumar Manoharan 			    30 + /* header size */
62268828f81aSRajkumar Manoharan 			    18); /* 11s header size */
62278828f81aSRajkumar Manoharan 	if (!skb)
62288828f81aSRajkumar Manoharan 		return -ENOMEM;
62298828f81aSRajkumar Manoharan 
62308828f81aSRajkumar Manoharan 	skb_reserve(skb, local->hw.extra_tx_headroom);
62318828f81aSRajkumar Manoharan 	skb_put_data(skb, buf, len);
62328828f81aSRajkumar Manoharan 
62338828f81aSRajkumar Manoharan 	skb->dev = dev;
62348828f81aSRajkumar Manoharan 	skb->protocol = htons(ETH_P_802_3);
62358828f81aSRajkumar Manoharan 	skb_reset_network_header(skb);
62368828f81aSRajkumar Manoharan 	skb_reset_mac_header(skb);
62378828f81aSRajkumar Manoharan 
62388828f81aSRajkumar Manoharan 	local_bh_disable();
62398828f81aSRajkumar Manoharan 	__ieee80211_subif_start_xmit(skb, skb->dev, 0,
6240a7528198SMarkus Theil 				     IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP,
6241a7528198SMarkus Theil 				     NULL);
6242e2ebc74dSJohannes Berg 	local_bh_enable();
6243e2ebc74dSJohannes Berg 
6244e2ebc74dSJohannes Berg 	return 0;
6245e2ebc74dSJohannes Berg }
6246