xref: /openbmc/linux/net/mac80211/tx.c (revision 03c3911d2d67a43ad4ffd15b534a5905d6ce5c59)
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
873bc9e0aSJohannes Berg  * Copyright (C) 2018-2021 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>
29e2ebc74dSJohannes Berg 
30e2ebc74dSJohannes Berg #include "ieee80211_i.h"
3124487981SJohannes Berg #include "driver-ops.h"
322c8dccc7SJohannes Berg #include "led.h"
3333b64eb2SLuis Carlos Cobo #include "mesh.h"
34e2ebc74dSJohannes Berg #include "wep.h"
35e2ebc74dSJohannes Berg #include "wpa.h"
36e2ebc74dSJohannes Berg #include "wme.h"
372c8dccc7SJohannes Berg #include "rate.h"
38e2ebc74dSJohannes Berg 
39e2ebc74dSJohannes Berg /* misc utils */
40e2ebc74dSJohannes Berg 
41252b86c4SJohannes Berg static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
42252b86c4SJohannes Berg 				 struct sk_buff *skb, int group_addr,
43e2ebc74dSJohannes Berg 				 int next_frag_len)
44e2ebc74dSJohannes Berg {
452103dec1SSimon Wunderlich 	int rate, mrate, erp, dur, i, shift = 0;
462e92e6f2SJohannes Berg 	struct ieee80211_rate *txrate;
47e2ebc74dSJohannes Berg 	struct ieee80211_local *local = tx->local;
488318d78aSJohannes Berg 	struct ieee80211_supported_band *sband;
49358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr;
50252b86c4SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
512103dec1SSimon Wunderlich 	struct ieee80211_chanctx_conf *chanctx_conf;
522103dec1SSimon Wunderlich 	u32 rate_flags = 0;
532103dec1SSimon Wunderlich 
5495cd470cSFelix Fietkau 	/* assume HW handles this */
5595cd470cSFelix Fietkau 	if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
5695cd470cSFelix Fietkau 		return 0;
5795cd470cSFelix Fietkau 
582103dec1SSimon Wunderlich 	rcu_read_lock();
592103dec1SSimon Wunderlich 	chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf);
602103dec1SSimon Wunderlich 	if (chanctx_conf) {
612103dec1SSimon Wunderlich 		shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
622103dec1SSimon Wunderlich 		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
632103dec1SSimon Wunderlich 	}
642103dec1SSimon Wunderlich 	rcu_read_unlock();
65e6a9854bSJohannes Berg 
66e6a9854bSJohannes Berg 	/* uh huh? */
670d528d85SFelix Fietkau 	if (WARN_ON_ONCE(tx->rate.idx < 0))
68e6a9854bSJohannes Berg 		return 0;
69e2ebc74dSJohannes Berg 
702d56577bSJohannes Berg 	sband = local->hw.wiphy->bands[info->band];
710d528d85SFelix Fietkau 	txrate = &sband->bitrates[tx->rate.idx];
728318d78aSJohannes Berg 
738318d78aSJohannes Berg 	erp = txrate->flags & IEEE80211_RATE_ERP_G;
74e2ebc74dSJohannes Berg 
7589b8c02aSThomas Pedersen 	/* device is expected to do this */
7689b8c02aSThomas Pedersen 	if (sband->band == NL80211_BAND_S1GHZ)
7789b8c02aSThomas Pedersen 		return 0;
7889b8c02aSThomas Pedersen 
79e2ebc74dSJohannes Berg 	/*
80e2ebc74dSJohannes Berg 	 * data and mgmt (except PS Poll):
81e2ebc74dSJohannes Berg 	 * - during CFP: 32768
82e2ebc74dSJohannes Berg 	 * - during contention period:
83e2ebc74dSJohannes Berg 	 *   if addr1 is group address: 0
84e2ebc74dSJohannes Berg 	 *   if more fragments = 0 and addr1 is individual address: time to
85e2ebc74dSJohannes Berg 	 *      transmit one ACK plus SIFS
86e2ebc74dSJohannes Berg 	 *   if more fragments = 1 and addr1 is individual address: time to
87e2ebc74dSJohannes Berg 	 *      transmit next fragment plus 2 x ACK plus 3 x SIFS
88e2ebc74dSJohannes Berg 	 *
89e2ebc74dSJohannes Berg 	 * IEEE 802.11, 9.6:
90e2ebc74dSJohannes Berg 	 * - control response frame (CTS or ACK) shall be transmitted using the
91e2ebc74dSJohannes Berg 	 *   same rate as the immediately previous frame in the frame exchange
92e2ebc74dSJohannes Berg 	 *   sequence, if this rate belongs to the PHY mandatory rates, or else
93e2ebc74dSJohannes Berg 	 *   at the highest possible rate belonging to the PHY rates in the
94e2ebc74dSJohannes Berg 	 *   BSSBasicRateSet
95e2ebc74dSJohannes Berg 	 */
96252b86c4SJohannes Berg 	hdr = (struct ieee80211_hdr *)skb->data;
97358c8d9dSHarvey Harrison 	if (ieee80211_is_ctl(hdr->frame_control)) {
98e2ebc74dSJohannes Berg 		/* TODO: These control frames are not currently sent by
99ccd7b362SJohannes Berg 		 * mac80211, but should they be implemented, this function
100e2ebc74dSJohannes Berg 		 * needs to be updated to support duration field calculation.
101e2ebc74dSJohannes Berg 		 *
102e2ebc74dSJohannes Berg 		 * RTS: time needed to transmit pending data/mgmt frame plus
103e2ebc74dSJohannes Berg 		 *    one CTS frame plus one ACK frame plus 3 x SIFS
104e2ebc74dSJohannes Berg 		 * CTS: duration of immediately previous RTS minus time
105e2ebc74dSJohannes Berg 		 *    required to transmit CTS and its SIFS
106e2ebc74dSJohannes Berg 		 * ACK: 0 if immediately previous directed data/mgmt had
107e2ebc74dSJohannes Berg 		 *    more=0, with more=1 duration in ACK frame is duration
108e2ebc74dSJohannes Berg 		 *    from previous frame minus time needed to transmit ACK
109e2ebc74dSJohannes Berg 		 *    and its SIFS
110e2ebc74dSJohannes Berg 		 * PS Poll: BIT(15) | BIT(14) | aid
111e2ebc74dSJohannes Berg 		 */
112e2ebc74dSJohannes Berg 		return 0;
113e2ebc74dSJohannes Berg 	}
114e2ebc74dSJohannes Berg 
115e2ebc74dSJohannes Berg 	/* data/mgmt */
116e2ebc74dSJohannes Berg 	if (0 /* FIX: data/mgmt during CFP */)
11703f93c3dSJohannes Berg 		return cpu_to_le16(32768);
118e2ebc74dSJohannes Berg 
119e2ebc74dSJohannes Berg 	if (group_addr) /* Group address as the destination - no ACK */
120e2ebc74dSJohannes Berg 		return 0;
121e2ebc74dSJohannes Berg 
122e2ebc74dSJohannes Berg 	/* Individual destination address:
123e2ebc74dSJohannes Berg 	 * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
124e2ebc74dSJohannes Berg 	 * CTS and ACK frames shall be transmitted using the highest rate in
125e2ebc74dSJohannes Berg 	 * basic rate set that is less than or equal to the rate of the
126e2ebc74dSJohannes Berg 	 * immediately previous frame and that is using the same modulation
127e2ebc74dSJohannes Berg 	 * (CCK or OFDM). If no basic rate set matches with these requirements,
128e2ebc74dSJohannes Berg 	 * the highest mandatory rate of the PHY that is less than or equal to
129e2ebc74dSJohannes Berg 	 * the rate of the previous frame is used.
130e2ebc74dSJohannes Berg 	 * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
131e2ebc74dSJohannes Berg 	 */
132e2ebc74dSJohannes Berg 	rate = -1;
1338318d78aSJohannes Berg 	/* use lowest available if everything fails */
1348318d78aSJohannes Berg 	mrate = sband->bitrates[0].bitrate;
1358318d78aSJohannes Berg 	for (i = 0; i < sband->n_bitrates; i++) {
1368318d78aSJohannes Berg 		struct ieee80211_rate *r = &sband->bitrates[i];
1378318d78aSJohannes Berg 
1388318d78aSJohannes Berg 		if (r->bitrate > txrate->bitrate)
139e2ebc74dSJohannes Berg 			break;
140e2ebc74dSJohannes Berg 
1412103dec1SSimon Wunderlich 		if ((rate_flags & r->flags) != rate_flags)
1422103dec1SSimon Wunderlich 			continue;
1432103dec1SSimon Wunderlich 
144bda3933aSJohannes Berg 		if (tx->sdata->vif.bss_conf.basic_rates & BIT(i))
1452103dec1SSimon Wunderlich 			rate = DIV_ROUND_UP(r->bitrate, 1 << shift);
146e2ebc74dSJohannes Berg 
1478318d78aSJohannes Berg 		switch (sband->band) {
14857fbcce3SJohannes Berg 		case NL80211_BAND_2GHZ: {
1498318d78aSJohannes Berg 			u32 flag;
1508318d78aSJohannes Berg 			if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
1518318d78aSJohannes Berg 				flag = IEEE80211_RATE_MANDATORY_G;
1528318d78aSJohannes Berg 			else
1538318d78aSJohannes Berg 				flag = IEEE80211_RATE_MANDATORY_B;
1548318d78aSJohannes Berg 			if (r->flags & flag)
1558318d78aSJohannes Berg 				mrate = r->bitrate;
1568318d78aSJohannes Berg 			break;
1578318d78aSJohannes Berg 		}
15857fbcce3SJohannes Berg 		case NL80211_BAND_5GHZ:
159c5b9a7f8SArend van Spriel 		case NL80211_BAND_6GHZ:
1608318d78aSJohannes Berg 			if (r->flags & IEEE80211_RATE_MANDATORY_A)
1618318d78aSJohannes Berg 				mrate = r->bitrate;
1628318d78aSJohannes Berg 			break;
163df78a0c0SThomas Pedersen 		case NL80211_BAND_S1GHZ:
16457fbcce3SJohannes Berg 		case NL80211_BAND_60GHZ:
1653a0c52a6SVladimir Kondratiev 			/* TODO, for now fall through */
16657fbcce3SJohannes Berg 		case NUM_NL80211_BANDS:
1678318d78aSJohannes Berg 			WARN_ON(1);
1688318d78aSJohannes Berg 			break;
1698318d78aSJohannes Berg 		}
170e2ebc74dSJohannes Berg 	}
171e2ebc74dSJohannes Berg 	if (rate == -1) {
172e2ebc74dSJohannes Berg 		/* No matching basic rate found; use highest suitable mandatory
173e2ebc74dSJohannes Berg 		 * PHY rate */
1742103dec1SSimon Wunderlich 		rate = DIV_ROUND_UP(mrate, 1 << shift);
175e2ebc74dSJohannes Berg 	}
176e2ebc74dSJohannes Berg 
1776674f210SSimon Wunderlich 	/* Don't calculate ACKs for QoS Frames with NoAck Policy set */
1786674f210SSimon Wunderlich 	if (ieee80211_is_data_qos(hdr->frame_control) &&
179c26a0e10SClaudio Pisa 	    *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
1806674f210SSimon Wunderlich 		dur = 0;
1816674f210SSimon Wunderlich 	else
182e2ebc74dSJohannes Berg 		/* Time needed to transmit ACK
183e2ebc74dSJohannes Berg 		 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
184e2ebc74dSJohannes Berg 		 * to closest integer */
1854ee73f33SMichal Kazior 		dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
186438b61b7SSimon Wunderlich 				tx->sdata->vif.bss_conf.use_short_preamble,
187438b61b7SSimon Wunderlich 				shift);
188e2ebc74dSJohannes Berg 
189e2ebc74dSJohannes Berg 	if (next_frag_len) {
190e2ebc74dSJohannes Berg 		/* Frame is fragmented: duration increases with time needed to
191e2ebc74dSJohannes Berg 		 * transmit next fragment plus ACK and 2 x SIFS. */
192e2ebc74dSJohannes Berg 		dur *= 2; /* ACK + SIFS */
193e2ebc74dSJohannes Berg 		/* next fragment */
1944ee73f33SMichal Kazior 		dur += ieee80211_frame_duration(sband->band, next_frag_len,
1958318d78aSJohannes Berg 				txrate->bitrate, erp,
196438b61b7SSimon Wunderlich 				tx->sdata->vif.bss_conf.use_short_preamble,
197438b61b7SSimon Wunderlich 				shift);
198e2ebc74dSJohannes Berg 	}
199e2ebc74dSJohannes Berg 
20003f93c3dSJohannes Berg 	return cpu_to_le16(dur);
201e2ebc74dSJohannes Berg }
202e2ebc74dSJohannes Berg 
203e2ebc74dSJohannes Berg /* tx handlers */
2045c1b98a5SKalle Valo static ieee80211_tx_result debug_noinline
2055c1b98a5SKalle Valo ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
2065c1b98a5SKalle Valo {
2075c1b98a5SKalle Valo 	struct ieee80211_local *local = tx->local;
2080c74211dSKalle Valo 	struct ieee80211_if_managed *ifmgd;
20994a5b3acSAndrei Otcheretianski 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
2105c1b98a5SKalle Valo 
2115c1b98a5SKalle Valo 	/* driver doesn't support power save */
21230686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
2135c1b98a5SKalle Valo 		return TX_CONTINUE;
2145c1b98a5SKalle Valo 
2155c1b98a5SKalle Valo 	/* hardware does dynamic power save */
21630686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
2175c1b98a5SKalle Valo 		return TX_CONTINUE;
2185c1b98a5SKalle Valo 
2195c1b98a5SKalle Valo 	/* dynamic power save disabled */
2205c1b98a5SKalle Valo 	if (local->hw.conf.dynamic_ps_timeout <= 0)
2215c1b98a5SKalle Valo 		return TX_CONTINUE;
2225c1b98a5SKalle Valo 
2235c1b98a5SKalle Valo 	/* we are scanning, don't enable power save */
2245c1b98a5SKalle Valo 	if (local->scanning)
2255c1b98a5SKalle Valo 		return TX_CONTINUE;
2265c1b98a5SKalle Valo 
2275c1b98a5SKalle Valo 	if (!local->ps_sdata)
2285c1b98a5SKalle Valo 		return TX_CONTINUE;
2295c1b98a5SKalle Valo 
2305c1b98a5SKalle Valo 	/* No point if we're going to suspend */
2315c1b98a5SKalle Valo 	if (local->quiescing)
2325c1b98a5SKalle Valo 		return TX_CONTINUE;
2335c1b98a5SKalle Valo 
2340c74211dSKalle Valo 	/* dynamic ps is supported only in managed mode */
2350c74211dSKalle Valo 	if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
2360c74211dSKalle Valo 		return TX_CONTINUE;
2370c74211dSKalle Valo 
23894a5b3acSAndrei Otcheretianski 	if (unlikely(info->flags & IEEE80211_TX_INTFL_OFFCHAN_TX_OK))
23994a5b3acSAndrei Otcheretianski 		return TX_CONTINUE;
24094a5b3acSAndrei Otcheretianski 
2410c74211dSKalle Valo 	ifmgd = &tx->sdata->u.mgd;
2420c74211dSKalle Valo 
2430c74211dSKalle Valo 	/*
2440c74211dSKalle Valo 	 * Don't wakeup from power save if u-apsd is enabled, voip ac has
2450c74211dSKalle Valo 	 * u-apsd enabled and the frame is in voip class. This effectively
2460c74211dSKalle Valo 	 * means that even if all access categories have u-apsd enabled, in
2470c74211dSKalle Valo 	 * practise u-apsd is only used with the voip ac. This is a
2480c74211dSKalle Valo 	 * workaround for the case when received voip class packets do not
2490c74211dSKalle Valo 	 * have correct qos tag for some reason, due the network or the
2500c74211dSKalle Valo 	 * peer application.
2510c74211dSKalle Valo 	 *
252dc41e4d4SEliad Peller 	 * Note: ifmgd->uapsd_queues access is racy here. If the value is
2530c74211dSKalle Valo 	 * changed via debugfs, user needs to reassociate manually to have
2540c74211dSKalle Valo 	 * everything in sync.
2550c74211dSKalle Valo 	 */
2564875d30dSJohannes Berg 	if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) &&
2574875d30dSJohannes Berg 	    (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) &&
2584875d30dSJohannes Berg 	    skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO)
2590c74211dSKalle Valo 		return TX_CONTINUE;
2600c74211dSKalle Valo 
2615c1b98a5SKalle Valo 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
2625c1b98a5SKalle Valo 		ieee80211_stop_queues_by_reason(&local->hw,
263445ea4e8SJohannes Berg 						IEEE80211_MAX_QUEUE_MAP,
264cca07b00SLuciano Coelho 						IEEE80211_QUEUE_STOP_REASON_PS,
265cca07b00SLuciano Coelho 						false);
266db28569aSVivek Natarajan 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
2675c1b98a5SKalle Valo 		ieee80211_queue_work(&local->hw,
2685c1b98a5SKalle Valo 				     &local->dynamic_ps_disable_work);
2695c1b98a5SKalle Valo 	}
2705c1b98a5SKalle Valo 
2715db1c07cSLuciano Coelho 	/* Don't restart the timer if we're not disassociated */
2725db1c07cSLuciano Coelho 	if (!ifmgd->associated)
2735db1c07cSLuciano Coelho 		return TX_CONTINUE;
2745db1c07cSLuciano Coelho 
2755c1b98a5SKalle Valo 	mod_timer(&local->dynamic_ps_timer, jiffies +
2765c1b98a5SKalle Valo 		  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
2775c1b98a5SKalle Valo 
2785c1b98a5SKalle Valo 	return TX_CONTINUE;
2795c1b98a5SKalle Valo }
280e2ebc74dSJohannes Berg 
281d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
2825cf121c3SJohannes Berg ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
283e2ebc74dSJohannes Berg {
284358c8d9dSHarvey Harrison 
285e039fa4aSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
286e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
287c2c98fdeSJohannes Berg 	bool assoc = false;
288e2ebc74dSJohannes Berg 
289e039fa4aSJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
2909ae54c84SJohannes Berg 		return TX_CONTINUE;
29158d4185eSJohannes Berg 
292b23b025fSBen Greear 	if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
293b23b025fSBen Greear 	    test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
294a9a6ffffSKalle Valo 	    !ieee80211_is_probe_req(hdr->frame_control) &&
29530b2f0beSThomas Pedersen 	    !ieee80211_is_any_nullfunc(hdr->frame_control))
296a9a6ffffSKalle Valo 		/*
297a9a6ffffSKalle Valo 		 * When software scanning only nullfunc frames (to notify
298a9a6ffffSKalle Valo 		 * the sleep state to the AP) and probe requests (for the
299a9a6ffffSKalle Valo 		 * active scan) are allowed, all other frames should not be
300a9a6ffffSKalle Valo 		 * sent and we should not get here, but if we do
301a9a6ffffSKalle Valo 		 * nonetheless, drop them to avoid sending them
302a9a6ffffSKalle Valo 		 * off-channel. See the link below and
303a9a6ffffSKalle Valo 		 * ieee80211_start_scan() for more.
304a9a6ffffSKalle Valo 		 *
305a9a6ffffSKalle Valo 		 * http://article.gmane.org/gmane.linux.kernel.wireless.general/30089
306a9a6ffffSKalle Valo 		 */
3079ae54c84SJohannes Berg 		return TX_DROP;
308e2ebc74dSJohannes Berg 
309239281f8SRostislav Lisovy 	if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
310239281f8SRostislav Lisovy 		return TX_CONTINUE;
311239281f8SRostislav Lisovy 
3125cf121c3SJohannes Berg 	if (tx->flags & IEEE80211_TX_PS_BUFFERED)
3139ae54c84SJohannes Berg 		return TX_CONTINUE;
314e2ebc74dSJohannes Berg 
315c2c98fdeSJohannes Berg 	if (tx->sta)
316c2c98fdeSJohannes Berg 		assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
317e2ebc74dSJohannes Berg 
3185cf121c3SJohannes Berg 	if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
319c2c98fdeSJohannes Berg 		if (unlikely(!assoc &&
320358c8d9dSHarvey Harrison 			     ieee80211_is_data(hdr->frame_control))) {
321e2ebc74dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
322bdcbd8e0SJohannes Berg 			sdata_info(tx->sdata,
323bdcbd8e0SJohannes Berg 				   "dropped data frame to not associated station %pM\n",
324bdcbd8e0SJohannes Berg 				   hdr->addr1);
325bdcbd8e0SJohannes Berg #endif
326e2ebc74dSJohannes Berg 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
3279ae54c84SJohannes Berg 			return TX_DROP;
328e2ebc74dSJohannes Berg 		}
32972f15d53SMichael Braun 	} else if (unlikely(ieee80211_is_data(hdr->frame_control) &&
33072f15d53SMichael Braun 			    ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) {
331e2ebc74dSJohannes Berg 		/*
332e2ebc74dSJohannes Berg 		 * No associated STAs - no need to send multicast
333e2ebc74dSJohannes Berg 		 * frames.
334e2ebc74dSJohannes Berg 		 */
3359ae54c84SJohannes Berg 		return TX_DROP;
336e2ebc74dSJohannes Berg 	}
337e2ebc74dSJohannes Berg 
3389ae54c84SJohannes Berg 	return TX_CONTINUE;
339e2ebc74dSJohannes Berg }
340e2ebc74dSJohannes Berg 
341e2ebc74dSJohannes Berg /* This function is called whenever the AP is about to exceed the maximum limit
342e2ebc74dSJohannes Berg  * of buffered frames for power saving STAs. This situation should not really
343e2ebc74dSJohannes Berg  * happen often during normal operation, so dropping the oldest buffered packet
344e2ebc74dSJohannes Berg  * from each queue should be OK to make some room for new frames. */
345e2ebc74dSJohannes Berg static void purge_old_ps_buffers(struct ieee80211_local *local)
346e2ebc74dSJohannes Berg {
347e2ebc74dSJohannes Berg 	int total = 0, purged = 0;
348e2ebc74dSJohannes Berg 	struct sk_buff *skb;
349e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata;
350e2ebc74dSJohannes Berg 	struct sta_info *sta;
351e2ebc74dSJohannes Berg 
35279010420SJohannes Berg 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
353d012a605SMarco Porsch 		struct ps_data *ps;
354d012a605SMarco Porsch 
355d012a605SMarco Porsch 		if (sdata->vif.type == NL80211_IFTYPE_AP)
356d012a605SMarco Porsch 			ps = &sdata->u.ap.ps;
3573f52b7e3SMarco Porsch 		else if (ieee80211_vif_is_mesh(&sdata->vif))
3583f52b7e3SMarco Porsch 			ps = &sdata->u.mesh.ps;
359d012a605SMarco Porsch 		else
360e2ebc74dSJohannes Berg 			continue;
361d012a605SMarco Porsch 
362d012a605SMarco Porsch 		skb = skb_dequeue(&ps->bc_buf);
363e2ebc74dSJohannes Berg 		if (skb) {
364e2ebc74dSJohannes Berg 			purged++;
3656b07d9caSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
366e2ebc74dSJohannes Berg 		}
367d012a605SMarco Porsch 		total += skb_queue_len(&ps->bc_buf);
368e2ebc74dSJohannes Berg 	}
369e2ebc74dSJohannes Berg 
370948d887dSJohannes Berg 	/*
371948d887dSJohannes Berg 	 * Drop one frame from each station from the lowest-priority
372948d887dSJohannes Berg 	 * AC that has frames at all.
373948d887dSJohannes Berg 	 */
374d0709a65SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
375948d887dSJohannes Berg 		int ac;
376948d887dSJohannes Berg 
377948d887dSJohannes Berg 		for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) {
378948d887dSJohannes Berg 			skb = skb_dequeue(&sta->ps_tx_buf[ac]);
379948d887dSJohannes Berg 			total += skb_queue_len(&sta->ps_tx_buf[ac]);
380e2ebc74dSJohannes Berg 			if (skb) {
381e2ebc74dSJohannes Berg 				purged++;
382c3e7724bSFelix Fietkau 				ieee80211_free_txskb(&local->hw, skb);
383948d887dSJohannes Berg 				break;
384e2ebc74dSJohannes Berg 			}
385948d887dSJohannes Berg 		}
386e2ebc74dSJohannes Berg 	}
387d0709a65SJohannes Berg 
388e2ebc74dSJohannes Berg 	local->total_ps_buffered = total;
389bdcbd8e0SJohannes Berg 	ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
390e2ebc74dSJohannes Berg }
391e2ebc74dSJohannes Berg 
3929ae54c84SJohannes Berg static ieee80211_tx_result
3935cf121c3SJohannes Berg ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
394e2ebc74dSJohannes Berg {
395e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
396358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
397d012a605SMarco Porsch 	struct ps_data *ps;
398e039fa4aSJohannes Berg 
3997d54d0ddSJohannes Berg 	/*
4007d54d0ddSJohannes Berg 	 * broadcast/multicast frame
4017d54d0ddSJohannes Berg 	 *
4023f52b7e3SMarco Porsch 	 * If any of the associated/peer stations is in power save mode,
4037d54d0ddSJohannes Berg 	 * the frame is buffered to be sent after DTIM beacon frame.
4047d54d0ddSJohannes Berg 	 * This is done either by the hardware or us.
4057d54d0ddSJohannes Berg 	 */
4067d54d0ddSJohannes Berg 
4073f52b7e3SMarco Porsch 	/* powersaving STAs currently only in AP/VLAN/mesh mode */
408d012a605SMarco Porsch 	if (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
409d012a605SMarco Porsch 	    tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
4103e122be0SJohannes Berg 		if (!tx->sdata->bss)
4113e122be0SJohannes Berg 			return TX_CONTINUE;
4123e122be0SJohannes Berg 
413d012a605SMarco Porsch 		ps = &tx->sdata->bss->ps;
4143f52b7e3SMarco Porsch 	} else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) {
4153f52b7e3SMarco Porsch 		ps = &tx->sdata->u.mesh.ps;
416d012a605SMarco Porsch 	} else {
417d012a605SMarco Porsch 		return TX_CONTINUE;
418d012a605SMarco Porsch 	}
419d012a605SMarco Porsch 
420d012a605SMarco Porsch 
4213e122be0SJohannes Berg 	/* no buffering for ordered frames */
422358c8d9dSHarvey Harrison 	if (ieee80211_has_order(hdr->frame_control))
4239ae54c84SJohannes Berg 		return TX_CONTINUE;
4247d54d0ddSJohannes Berg 
42508b99399SJohannes Berg 	if (ieee80211_is_probe_req(hdr->frame_control))
42608b99399SJohannes Berg 		return TX_CONTINUE;
42708b99399SJohannes Berg 
42830686bf7SJohannes Berg 	if (ieee80211_hw_check(&tx->local->hw, QUEUE_CONTROL))
429f4d57941SJohannes Berg 		info->hw_queue = tx->sdata->vif.cab_queue;
430f4d57941SJohannes Berg 
4319ec1190dSFelix Fietkau 	/* no stations in PS mode and no buffered packets */
4329ec1190dSFelix Fietkau 	if (!atomic_read(&ps->num_sta_ps) && skb_queue_empty(&ps->bc_buf))
4339ae54c84SJohannes Berg 		return TX_CONTINUE;
4347d54d0ddSJohannes Berg 
43562b1208eSJohannes Berg 	info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
43662b1208eSJohannes Berg 
43762b517cbSJohannes Berg 	/* device releases frame after DTIM beacon */
43830686bf7SJohannes Berg 	if (!ieee80211_hw_check(&tx->local->hw, HOST_BROADCAST_PS_BUFFERING))
43962b1208eSJohannes Berg 		return TX_CONTINUE;
44062b1208eSJohannes Berg 
4417d54d0ddSJohannes Berg 	/* buffered in mac80211 */
442e2ebc74dSJohannes Berg 	if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
443e2ebc74dSJohannes Berg 		purge_old_ps_buffers(tx->local);
44462b1208eSJohannes Berg 
445d012a605SMarco Porsch 	if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
446bdcbd8e0SJohannes Berg 		ps_dbg(tx->sdata,
447bdcbd8e0SJohannes Berg 		       "BC TX buffer full - dropping the oldest frame\n");
4486b07d9caSFelix Fietkau 		ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf));
449e2ebc74dSJohannes Berg 	} else
450e2ebc74dSJohannes Berg 		tx->local->total_ps_buffered++;
45162b1208eSJohannes Berg 
452d012a605SMarco Porsch 	skb_queue_tail(&ps->bc_buf, tx->skb);
45362b1208eSJohannes Berg 
4549ae54c84SJohannes Berg 	return TX_QUEUED;
455e2ebc74dSJohannes Berg }
456e2ebc74dSJohannes Berg 
457fb733336SJouni Malinen static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
458fb733336SJouni Malinen 			     struct sk_buff *skb)
459fb733336SJouni Malinen {
460fb733336SJouni Malinen 	if (!ieee80211_is_mgmt(fc))
461fb733336SJouni Malinen 		return 0;
462fb733336SJouni Malinen 
463c2c98fdeSJohannes Berg 	if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
464fb733336SJouni Malinen 		return 0;
465fb733336SJouni Malinen 
466d8ca16dbSJohannes Berg 	if (!ieee80211_is_robust_mgmt_frame(skb))
467fb733336SJouni Malinen 		return 0;
468fb733336SJouni Malinen 
469fb733336SJouni Malinen 	return 1;
470fb733336SJouni Malinen }
471fb733336SJouni Malinen 
4729ae54c84SJohannes Berg static ieee80211_tx_result
4735cf121c3SJohannes Berg ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
474e2ebc74dSJohannes Berg {
475e2ebc74dSJohannes Berg 	struct sta_info *sta = tx->sta;
476e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
47708b99399SJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
4783393a608SJuuso Oikarinen 	struct ieee80211_local *local = tx->local;
479e2ebc74dSJohannes Berg 
48002f2f1a9SJohannes Berg 	if (unlikely(!sta))
4819ae54c84SJohannes Berg 		return TX_CONTINUE;
482e2ebc74dSJohannes Berg 
483c2c98fdeSJohannes Berg 	if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
4845ac2e350SJohannes Berg 		      test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
4855ac2e350SJohannes Berg 		      test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
48602f2f1a9SJohannes Berg 		     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
487948d887dSJohannes Berg 		int ac = skb_get_queue_mapping(tx->skb);
488948d887dSJohannes Berg 
48908b99399SJohannes Berg 		if (ieee80211_is_mgmt(hdr->frame_control) &&
49008b99399SJohannes Berg 		    !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
49108b99399SJohannes Berg 			info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
49208b99399SJohannes Berg 			return TX_CONTINUE;
49308b99399SJohannes Berg 		}
49408b99399SJohannes Berg 
495bdcbd8e0SJohannes Berg 		ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
496948d887dSJohannes Berg 		       sta->sta.addr, sta->sta.aid, ac);
497e2ebc74dSJohannes Berg 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
498e2ebc74dSJohannes Berg 			purge_old_ps_buffers(tx->local);
4991d147bfaSEmmanuel Grumbach 
5001d147bfaSEmmanuel Grumbach 		/* sync with ieee80211_sta_ps_deliver_wakeup */
5011d147bfaSEmmanuel Grumbach 		spin_lock(&sta->ps_lock);
5021d147bfaSEmmanuel Grumbach 		/*
5031d147bfaSEmmanuel Grumbach 		 * STA woke up the meantime and all the frames on ps_tx_buf have
5041d147bfaSEmmanuel Grumbach 		 * been queued to pending queue. No reordering can happen, go
5051d147bfaSEmmanuel Grumbach 		 * ahead and Tx the packet.
5061d147bfaSEmmanuel Grumbach 		 */
5071d147bfaSEmmanuel Grumbach 		if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
5085ac2e350SJohannes Berg 		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
5095ac2e350SJohannes Berg 		    !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
5101d147bfaSEmmanuel Grumbach 			spin_unlock(&sta->ps_lock);
5111d147bfaSEmmanuel Grumbach 			return TX_CONTINUE;
5121d147bfaSEmmanuel Grumbach 		}
5131d147bfaSEmmanuel Grumbach 
514948d887dSJohannes Berg 		if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
515948d887dSJohannes Berg 			struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
516bdcbd8e0SJohannes Berg 			ps_dbg(tx->sdata,
517bdcbd8e0SJohannes Berg 			       "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
518bdcbd8e0SJohannes Berg 			       sta->sta.addr, ac);
519c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, old);
520e2ebc74dSJohannes Berg 		} else
521e2ebc74dSJohannes Berg 			tx->local->total_ps_buffered++;
522004c872eSJohannes Berg 
523e039fa4aSJohannes Berg 		info->control.jiffies = jiffies;
5245061b0c2SJohannes Berg 		info->control.vif = &tx->sdata->vif;
525cc20ff2cSFelix Fietkau 		info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
52603c8c06fSJohannes Berg 		info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
527948d887dSJohannes Berg 		skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
5281d147bfaSEmmanuel Grumbach 		spin_unlock(&sta->ps_lock);
5293393a608SJuuso Oikarinen 
5303393a608SJuuso Oikarinen 		if (!timer_pending(&local->sta_cleanup))
5313393a608SJuuso Oikarinen 			mod_timer(&local->sta_cleanup,
5323393a608SJuuso Oikarinen 				  round_jiffies(jiffies +
5333393a608SJuuso Oikarinen 						STA_INFO_CLEANUP_INTERVAL));
5343393a608SJuuso Oikarinen 
535c868cb35SJohannes Berg 		/*
536c868cb35SJohannes Berg 		 * We queued up some frames, so the TIM bit might
537c868cb35SJohannes Berg 		 * need to be set, recalculate it.
538c868cb35SJohannes Berg 		 */
539c868cb35SJohannes Berg 		sta_info_recalc_tim(sta);
540c868cb35SJohannes Berg 
5419ae54c84SJohannes Berg 		return TX_QUEUED;
542bdcbd8e0SJohannes Berg 	} else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
543bdcbd8e0SJohannes Berg 		ps_dbg(tx->sdata,
544bdcbd8e0SJohannes Berg 		       "STA %pM in PS mode, but polling/in SP -> send frame\n",
545bdcbd8e0SJohannes Berg 		       sta->sta.addr);
546e2ebc74dSJohannes Berg 	}
547e2ebc74dSJohannes Berg 
5489ae54c84SJohannes Berg 	return TX_CONTINUE;
549e2ebc74dSJohannes Berg }
550e2ebc74dSJohannes Berg 
551d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
5525cf121c3SJohannes Berg ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
553e2ebc74dSJohannes Berg {
5545cf121c3SJohannes Berg 	if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
5559ae54c84SJohannes Berg 		return TX_CONTINUE;
556e2ebc74dSJohannes Berg 
5575cf121c3SJohannes Berg 	if (tx->flags & IEEE80211_TX_UNICAST)
558e2ebc74dSJohannes Berg 		return ieee80211_tx_h_unicast_ps_buf(tx);
559e2ebc74dSJohannes Berg 	else
560e2ebc74dSJohannes Berg 		return ieee80211_tx_h_multicast_ps_buf(tx);
561e2ebc74dSJohannes Berg }
562e2ebc74dSJohannes Berg 
563d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
564a621fa4dSJohannes Berg ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
565a621fa4dSJohannes Berg {
566a621fa4dSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
567a621fa4dSJohannes Berg 
568af61a165SJohannes Berg 	if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) {
569af61a165SJohannes Berg 		if (tx->sdata->control_port_no_encrypt)
570a621fa4dSJohannes Berg 			info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
571af61a165SJohannes Berg 		info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
5729c1c98a3SJouni Malinen 		info->flags |= IEEE80211_TX_CTL_USE_MINRATE;
573af61a165SJohannes Berg 	}
574a621fa4dSJohannes Berg 
575a621fa4dSJohannes Berg 	return TX_CONTINUE;
576a621fa4dSJohannes Berg }
577a621fa4dSJohannes Berg 
578a621fa4dSJohannes Berg static ieee80211_tx_result debug_noinline
5795cf121c3SJohannes Berg ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
580e2ebc74dSJohannes Berg {
58146e6de15SJohannes Berg 	struct ieee80211_key *key;
582e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
583358c8d9dSHarvey Harrison 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
584d4e46a3dSJohannes Berg 
585a0761a30SJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
586e2ebc74dSJohannes Berg 		tx->key = NULL;
587a0761a30SJohannes Berg 		return TX_CONTINUE;
588a0761a30SJohannes Berg 	}
589a0761a30SJohannes Berg 
590a0761a30SJohannes Berg 	if (tx->sta &&
5912475b1ccSMax Stepanov 	    (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
592d4e46a3dSJohannes Berg 		tx->key = key;
59346f6b060SMasashi Honma 	else if (ieee80211_is_group_privacy_action(tx->skb) &&
59446f6b060SMasashi Honma 		(key = rcu_dereference(tx->sdata->default_multicast_key)))
59546f6b060SMasashi Honma 		tx->key = key;
5963cfcf6acSJouni Malinen 	else if (ieee80211_is_mgmt(hdr->frame_control) &&
597ecbcd324SJouni Malinen 		 is_multicast_ether_addr(hdr->addr1) &&
598d8ca16dbSJohannes Berg 		 ieee80211_is_robust_mgmt_frame(tx->skb) &&
5993cfcf6acSJouni Malinen 		 (key = rcu_dereference(tx->sdata->default_mgmt_key)))
6003cfcf6acSJouni Malinen 		tx->key = key;
601f7e0104cSJohannes Berg 	else if (is_multicast_ether_addr(hdr->addr1) &&
602f7e0104cSJohannes Berg 		 (key = rcu_dereference(tx->sdata->default_multicast_key)))
603f7e0104cSJohannes Berg 		tx->key = key;
604f7e0104cSJohannes Berg 	else if (!is_multicast_ether_addr(hdr->addr1) &&
605f7e0104cSJohannes Berg 		 (key = rcu_dereference(tx->sdata->default_unicast_key)))
606d4e46a3dSJohannes Berg 		tx->key = key;
607e8f4fb7cSJohannes Berg 	else
60846e6de15SJohannes Berg 		tx->key = NULL;
609e2ebc74dSJohannes Berg 
610e2ebc74dSJohannes Berg 	if (tx->key) {
611813d7669SJohannes Berg 		bool skip_hw = false;
612813d7669SJohannes Berg 
613011bfcc4SJohannes Berg 		/* TODO: add threshold stuff again */
614176e4f84SJohannes Berg 
61597359d12SJohannes Berg 		switch (tx->key->conf.cipher) {
61697359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP40:
61797359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP104:
61897359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_TKIP:
619358c8d9dSHarvey Harrison 			if (!ieee80211_is_data_present(hdr->frame_control))
620176e4f84SJohannes Berg 				tx->key = NULL;
621176e4f84SJohannes Berg 			break;
62297359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP:
6232b2ba0dbSJouni Malinen 		case WLAN_CIPHER_SUITE_CCMP_256:
62400b9cfa3SJouni Malinen 		case WLAN_CIPHER_SUITE_GCMP:
62500b9cfa3SJouni Malinen 		case WLAN_CIPHER_SUITE_GCMP_256:
626fb733336SJouni Malinen 			if (!ieee80211_is_data_present(hdr->frame_control) &&
627fb733336SJouni Malinen 			    !ieee80211_use_mfp(hdr->frame_control, tx->sta,
62846f6b060SMasashi Honma 					       tx->skb) &&
62946f6b060SMasashi Honma 			    !ieee80211_is_group_privacy_action(tx->skb))
630fb733336SJouni Malinen 				tx->key = NULL;
6313b43a187SKalle Valo 			else
632813d7669SJohannes Berg 				skip_hw = (tx->key->conf.flags &
633e548c49eSJohannes Berg 					   IEEE80211_KEY_FLAG_SW_MGMT_TX) &&
634813d7669SJohannes Berg 					ieee80211_is_mgmt(hdr->frame_control);
635fb733336SJouni Malinen 			break;
63697359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_AES_CMAC:
63756c52da2SJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
6388ade538bSJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
6398ade538bSJouni Malinen 		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
6403cfcf6acSJouni Malinen 			if (!ieee80211_is_mgmt(hdr->frame_control))
6413cfcf6acSJouni Malinen 				tx->key = NULL;
6423cfcf6acSJouni Malinen 			break;
643e2ebc74dSJohannes Berg 		}
644813d7669SJohannes Berg 
645e54faf29SJohannes Berg 		if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED &&
646e54faf29SJohannes Berg 			     !ieee80211_is_deauth(hdr->frame_control)))
64795acac61SJohannes Berg 			return TX_DROP;
64895acac61SJohannes Berg 
649f12553ebSJohannes Berg 		if (!skip_hw && tx->key &&
650382b1655SJohannes Berg 		    tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
651813d7669SJohannes Berg 			info->control.hw_key = &tx->key->conf;
6522463ec86SFelix Fietkau 	} else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta &&
653a0761a30SJohannes Berg 		   test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) {
654a0761a30SJohannes Berg 		return TX_DROP;
655176e4f84SJohannes Berg 	}
656176e4f84SJohannes Berg 
6579ae54c84SJohannes Berg 	return TX_CONTINUE;
658e2ebc74dSJohannes Berg }
659e2ebc74dSJohannes Berg 
660d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
6615cf121c3SJohannes Berg ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
662e2ebc74dSJohannes Berg {
663e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
664e6a9854bSJohannes Berg 	struct ieee80211_hdr *hdr = (void *)tx->skb->data;
665e6a9854bSJohannes Berg 	struct ieee80211_supported_band *sband;
666a2c40249SShanyu Zhao 	u32 len;
667e6a9854bSJohannes Berg 	struct ieee80211_tx_rate_control txrc;
6680d528d85SFelix Fietkau 	struct ieee80211_sta_rates *ratetbl = NULL;
669c2c98fdeSJohannes Berg 	bool assoc = false;
670e6a9854bSJohannes Berg 
671e6a9854bSJohannes Berg 	memset(&txrc, 0, sizeof(txrc));
6728318d78aSJohannes Berg 
6732d56577bSJohannes Berg 	sband = tx->local->hw.wiphy->bands[info->band];
674e2ebc74dSJohannes Berg 
675a2c40249SShanyu Zhao 	len = min_t(u32, tx->skb->len + FCS_LEN,
676b9a5f8caSJouni Malinen 			 tx->local->hw.wiphy->frag_threshold);
67758d4185eSJohannes Berg 
678e6a9854bSJohannes Berg 	/* set up the tx rate control struct we give the RC algo */
679005e472bSJohannes Berg 	txrc.hw = &tx->local->hw;
680e6a9854bSJohannes Berg 	txrc.sband = sband;
681e6a9854bSJohannes Berg 	txrc.bss_conf = &tx->sdata->vif.bss_conf;
682e6a9854bSJohannes Berg 	txrc.skb = tx->skb;
683e6a9854bSJohannes Berg 	txrc.reported_rate.idx = -1;
6842d56577bSJohannes Berg 	txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
6852ffbe6d3SFelix Fietkau 
6862ffbe6d3SFelix Fietkau 	if (tx->sdata->rc_has_mcs_mask[info->band])
6872ffbe6d3SFelix Fietkau 		txrc.rate_idx_mcs_mask =
6882ffbe6d3SFelix Fietkau 			tx->sdata->rc_rateidx_mcs_mask[info->band];
6892ffbe6d3SFelix Fietkau 
6908f0729b1SFelix Fietkau 	txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
6914bb62344SChun-Yeow Yeoh 		    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
6925765f9f6SBertold Van den Bergh 		    tx->sdata->vif.type == NL80211_IFTYPE_ADHOC ||
6935765f9f6SBertold Van den Bergh 		    tx->sdata->vif.type == NL80211_IFTYPE_OCB);
69458d4185eSJohannes Berg 
695e6a9854bSJohannes Berg 	/* set up RTS protection if desired */
696b9a5f8caSJouni Malinen 	if (len > tx->local->hw.wiphy->rts_threshold) {
6970d528d85SFelix Fietkau 		txrc.rts = true;
698e2ebc74dSJohannes Berg 	}
699e6a9854bSJohannes Berg 
7000d528d85SFelix Fietkau 	info->control.use_rts = txrc.rts;
701991fec09SFelix Fietkau 	info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot;
702991fec09SFelix Fietkau 
703e6a9854bSJohannes Berg 	/*
704e6a9854bSJohannes Berg 	 * Use short preamble if the BSS can handle it, but not for
705e6a9854bSJohannes Berg 	 * management frames unless we know the receiver can handle
706e6a9854bSJohannes Berg 	 * that -- the management frame might be to a station that
707e6a9854bSJohannes Berg 	 * just wants a probe response.
708e6a9854bSJohannes Berg 	 */
709e6a9854bSJohannes Berg 	if (tx->sdata->vif.bss_conf.use_short_preamble &&
710e6a9854bSJohannes Berg 	    (ieee80211_is_data(hdr->frame_control) ||
711c2c98fdeSJohannes Berg 	     (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
7120d528d85SFelix Fietkau 		txrc.short_preamble = true;
7130d528d85SFelix Fietkau 
7140d528d85SFelix Fietkau 	info->control.short_preamble = txrc.short_preamble;
715e6a9854bSJohannes Berg 
716dfdfc2beSSven Eckelmann 	/* don't ask rate control when rate already injected via radiotap */
717dfdfc2beSSven Eckelmann 	if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
718dfdfc2beSSven Eckelmann 		return TX_CONTINUE;
719dfdfc2beSSven Eckelmann 
720c2c98fdeSJohannes Berg 	if (tx->sta)
721c2c98fdeSJohannes Berg 		assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
722e6a9854bSJohannes Berg 
723b770b43eSLuis R. Rodriguez 	/*
724b770b43eSLuis R. Rodriguez 	 * Lets not bother rate control if we're associated and cannot
725b770b43eSLuis R. Rodriguez 	 * talk to the sta. This should not happen.
726b770b43eSLuis R. Rodriguez 	 */
727c2c98fdeSJohannes Berg 	if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
728b770b43eSLuis R. Rodriguez 		 !rate_usable_index_exists(sband, &tx->sta->sta),
729b770b43eSLuis R. Rodriguez 		 "%s: Dropped data frame as no usable bitrate found while "
730b770b43eSLuis R. Rodriguez 		 "scanning and associated. Target station: "
731b770b43eSLuis R. Rodriguez 		 "%pM on %d GHz band\n",
73247846c9bSJohannes Berg 		 tx->sdata->name, hdr->addr1,
7332d56577bSJohannes Berg 		 info->band ? 5 : 2))
734b770b43eSLuis R. Rodriguez 		return TX_DROP;
735b770b43eSLuis R. Rodriguez 
736b770b43eSLuis R. Rodriguez 	/*
737b770b43eSLuis R. Rodriguez 	 * If we're associated with the sta at this point we know we can at
738b770b43eSLuis R. Rodriguez 	 * least send the frame at the lowest bit rate.
739b770b43eSLuis R. Rodriguez 	 */
740e6a9854bSJohannes Berg 	rate_control_get_rate(tx->sdata, tx->sta, &txrc);
741e6a9854bSJohannes Berg 
7420d528d85SFelix Fietkau 	if (tx->sta && !info->control.skip_table)
7430d528d85SFelix Fietkau 		ratetbl = rcu_dereference(tx->sta->sta.rates);
7440d528d85SFelix Fietkau 
7450d528d85SFelix Fietkau 	if (unlikely(info->control.rates[0].idx < 0)) {
7460d528d85SFelix Fietkau 		if (ratetbl) {
7470d528d85SFelix Fietkau 			struct ieee80211_tx_rate rate = {
7480d528d85SFelix Fietkau 				.idx = ratetbl->rate[0].idx,
7490d528d85SFelix Fietkau 				.flags = ratetbl->rate[0].flags,
7500d528d85SFelix Fietkau 				.count = ratetbl->rate[0].count
7510d528d85SFelix Fietkau 			};
7520d528d85SFelix Fietkau 
7530d528d85SFelix Fietkau 			if (ratetbl->rate[0].idx < 0)
754e6a9854bSJohannes Berg 				return TX_DROP;
755e6a9854bSJohannes Berg 
7560d528d85SFelix Fietkau 			tx->rate = rate;
7570d528d85SFelix Fietkau 		} else {
7580d528d85SFelix Fietkau 			return TX_DROP;
7590d528d85SFelix Fietkau 		}
7600d528d85SFelix Fietkau 	} else {
7610d528d85SFelix Fietkau 		tx->rate = info->control.rates[0];
7620d528d85SFelix Fietkau 	}
7630d528d85SFelix Fietkau 
764c1ce5a74SHelmut Schaa 	if (txrc.reported_rate.idx < 0) {
7650d528d85SFelix Fietkau 		txrc.reported_rate = tx->rate;
766c1ce5a74SHelmut Schaa 		if (tx->sta && ieee80211_is_data(hdr->frame_control))
767e5a9f8d0SJohannes Berg 			tx->sta->tx_stats.last_rate = txrc.reported_rate;
768c1ce5a74SHelmut Schaa 	} else if (tx->sta)
769e5a9f8d0SJohannes Berg 		tx->sta->tx_stats.last_rate = txrc.reported_rate;
770e6a9854bSJohannes Berg 
7710d528d85SFelix Fietkau 	if (ratetbl)
7720d528d85SFelix Fietkau 		return TX_CONTINUE;
7730d528d85SFelix Fietkau 
774e6a9854bSJohannes Berg 	if (unlikely(!info->control.rates[0].count))
775e6a9854bSJohannes Berg 		info->control.rates[0].count = 1;
776e6a9854bSJohannes Berg 
7779955151dSGábor Stefanik 	if (WARN_ON_ONCE((info->control.rates[0].count > 1) &&
7789955151dSGábor Stefanik 			 (info->flags & IEEE80211_TX_CTL_NO_ACK)))
7799955151dSGábor Stefanik 		info->control.rates[0].count = 1;
7809955151dSGábor Stefanik 
7819ae54c84SJohannes Berg 	return TX_CONTINUE;
782e2ebc74dSJohannes Berg }
783e2ebc74dSJohannes Berg 
784ba8c3d6fSFelix Fietkau static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
785ba8c3d6fSFelix Fietkau {
786ba8c3d6fSFelix Fietkau 	u16 *seq = &sta->tid_seq[tid];
787ba8c3d6fSFelix Fietkau 	__le16 ret = cpu_to_le16(*seq);
788ba8c3d6fSFelix Fietkau 
789ba8c3d6fSFelix Fietkau 	/* Increase the sequence number. */
790ba8c3d6fSFelix Fietkau 	*seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
791ba8c3d6fSFelix Fietkau 
792ba8c3d6fSFelix Fietkau 	return ret;
793ba8c3d6fSFelix Fietkau }
794ba8c3d6fSFelix Fietkau 
795d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
796f591fa5dSJohannes Berg ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
797f591fa5dSJohannes Berg {
798f591fa5dSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
799f591fa5dSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
800f591fa5dSJohannes Berg 	int tid;
801f591fa5dSJohannes Berg 
80225d834e1SJohannes Berg 	/*
80325d834e1SJohannes Berg 	 * Packet injection may want to control the sequence
80425d834e1SJohannes Berg 	 * number, if we have no matching interface then we
80525d834e1SJohannes Berg 	 * neither assign one ourselves nor ask the driver to.
80625d834e1SJohannes Berg 	 */
8075061b0c2SJohannes Berg 	if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
80825d834e1SJohannes Berg 		return TX_CONTINUE;
80925d834e1SJohannes Berg 
810f591fa5dSJohannes Berg 	if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
811f591fa5dSJohannes Berg 		return TX_CONTINUE;
812f591fa5dSJohannes Berg 
813f591fa5dSJohannes Berg 	if (ieee80211_hdrlen(hdr->frame_control) < 24)
814f591fa5dSJohannes Berg 		return TX_CONTINUE;
815f591fa5dSJohannes Berg 
81649a59543SJohannes Berg 	if (ieee80211_is_qos_nullfunc(hdr->frame_control))
81749a59543SJohannes Berg 		return TX_CONTINUE;
81849a59543SJohannes Berg 
81929c3e95fSMathy Vanhoef 	if (info->control.flags & IEEE80211_TX_CTRL_NO_SEQNO)
82029c3e95fSMathy Vanhoef 		return TX_CONTINUE;
82129c3e95fSMathy Vanhoef 
82294778280SJohannes Berg 	/*
82394778280SJohannes Berg 	 * Anything but QoS data that has a sequence number field
82494778280SJohannes Berg 	 * (is long enough) gets a sequence number from the global
825c4c205f3SBob Copeland 	 * counter.  QoS data frames with a multicast destination
826c4c205f3SBob Copeland 	 * also use the global counter (802.11-2012 9.3.2.10).
82794778280SJohannes Berg 	 */
828c4c205f3SBob Copeland 	if (!ieee80211_is_data_qos(hdr->frame_control) ||
829c4c205f3SBob Copeland 	    is_multicast_ether_addr(hdr->addr1)) {
83094778280SJohannes Berg 		/* driver should assign sequence number */
831f591fa5dSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
83294778280SJohannes Berg 		/* for pure STA mode without beacons, we can do it */
83394778280SJohannes Berg 		hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
83494778280SJohannes Berg 		tx->sdata->sequence_number += 0x10;
83579c892b8SJohannes Berg 		if (tx->sta)
836e5a9f8d0SJohannes Berg 			tx->sta->tx_stats.msdu[IEEE80211_NUM_TIDS]++;
837f591fa5dSJohannes Berg 		return TX_CONTINUE;
838f591fa5dSJohannes Berg 	}
839f591fa5dSJohannes Berg 
840f591fa5dSJohannes Berg 	/*
841f591fa5dSJohannes Berg 	 * This should be true for injected/management frames only, for
842f591fa5dSJohannes Berg 	 * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ
843f591fa5dSJohannes Berg 	 * above since they are not QoS-data frames.
844f591fa5dSJohannes Berg 	 */
845f591fa5dSJohannes Berg 	if (!tx->sta)
846f591fa5dSJohannes Berg 		return TX_CONTINUE;
847f591fa5dSJohannes Berg 
848f591fa5dSJohannes Berg 	/* include per-STA, per-TID sequence counter */
849a1f2ba04SSara Sharon 	tid = ieee80211_get_tid(hdr);
850e5a9f8d0SJohannes Berg 	tx->sta->tx_stats.msdu[tid]++;
851f591fa5dSJohannes Berg 
852ba8c3d6fSFelix Fietkau 	hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
853f591fa5dSJohannes Berg 
854f591fa5dSJohannes Berg 	return TX_CONTINUE;
855f591fa5dSJohannes Berg }
856f591fa5dSJohannes Berg 
857252b86c4SJohannes Berg static int ieee80211_fragment(struct ieee80211_tx_data *tx,
8582de8e0d9SJohannes Berg 			      struct sk_buff *skb, int hdrlen,
8592de8e0d9SJohannes Berg 			      int frag_threshold)
8602de8e0d9SJohannes Berg {
861252b86c4SJohannes Berg 	struct ieee80211_local *local = tx->local;
862a1a3fcecSJohannes Berg 	struct ieee80211_tx_info *info;
863252b86c4SJohannes Berg 	struct sk_buff *tmp;
8642de8e0d9SJohannes Berg 	int per_fragm = frag_threshold - hdrlen - FCS_LEN;
8652de8e0d9SJohannes Berg 	int pos = hdrlen + per_fragm;
8662de8e0d9SJohannes Berg 	int rem = skb->len - hdrlen - per_fragm;
8672de8e0d9SJohannes Berg 
8682de8e0d9SJohannes Berg 	if (WARN_ON(rem < 0))
8692de8e0d9SJohannes Berg 		return -EINVAL;
8702de8e0d9SJohannes Berg 
871252b86c4SJohannes Berg 	/* first fragment was already added to queue by caller */
872252b86c4SJohannes Berg 
8732de8e0d9SJohannes Berg 	while (rem) {
8742de8e0d9SJohannes Berg 		int fraglen = per_fragm;
8752de8e0d9SJohannes Berg 
8762de8e0d9SJohannes Berg 		if (fraglen > rem)
8772de8e0d9SJohannes Berg 			fraglen = rem;
8782de8e0d9SJohannes Berg 		rem -= fraglen;
8792de8e0d9SJohannes Berg 		tmp = dev_alloc_skb(local->tx_headroom +
8802de8e0d9SJohannes Berg 				    frag_threshold +
8812475b1ccSMax Stepanov 				    tx->sdata->encrypt_headroom +
8822de8e0d9SJohannes Berg 				    IEEE80211_ENCRYPT_TAILROOM);
8832de8e0d9SJohannes Berg 		if (!tmp)
8842de8e0d9SJohannes Berg 			return -ENOMEM;
885252b86c4SJohannes Berg 
886252b86c4SJohannes Berg 		__skb_queue_tail(&tx->skbs, tmp);
887252b86c4SJohannes Berg 
8882475b1ccSMax Stepanov 		skb_reserve(tmp,
8892475b1ccSMax Stepanov 			    local->tx_headroom + tx->sdata->encrypt_headroom);
8902475b1ccSMax Stepanov 
8912de8e0d9SJohannes Berg 		/* copy control information */
8922de8e0d9SJohannes Berg 		memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
893a1a3fcecSJohannes Berg 
894a1a3fcecSJohannes Berg 		info = IEEE80211_SKB_CB(tmp);
895a1a3fcecSJohannes Berg 		info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
896a1a3fcecSJohannes Berg 				 IEEE80211_TX_CTL_FIRST_FRAGMENT);
897a1a3fcecSJohannes Berg 
898a1a3fcecSJohannes Berg 		if (rem)
899a1a3fcecSJohannes Berg 			info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
900a1a3fcecSJohannes Berg 
9012de8e0d9SJohannes Berg 		skb_copy_queue_mapping(tmp, skb);
9022de8e0d9SJohannes Berg 		tmp->priority = skb->priority;
9032de8e0d9SJohannes Berg 		tmp->dev = skb->dev;
9042de8e0d9SJohannes Berg 
9052de8e0d9SJohannes Berg 		/* copy header and data */
90659ae1d12SJohannes Berg 		skb_put_data(tmp, skb->data, hdrlen);
90759ae1d12SJohannes Berg 		skb_put_data(tmp, skb->data + pos, fraglen);
9082de8e0d9SJohannes Berg 
9092de8e0d9SJohannes Berg 		pos += fraglen;
9102de8e0d9SJohannes Berg 	}
9112de8e0d9SJohannes Berg 
912252b86c4SJohannes Berg 	/* adjust first fragment's length */
913338f977fSJohannes Berg 	skb_trim(skb, hdrlen + per_fragm);
9142de8e0d9SJohannes Berg 	return 0;
9152de8e0d9SJohannes Berg }
9162de8e0d9SJohannes Berg 
917f591fa5dSJohannes Berg static ieee80211_tx_result debug_noinline
918e2454948SJohannes Berg ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
919e2454948SJohannes Berg {
9202de8e0d9SJohannes Berg 	struct sk_buff *skb = tx->skb;
9212de8e0d9SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
9222de8e0d9SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)skb->data;
923b9a5f8caSJouni Malinen 	int frag_threshold = tx->local->hw.wiphy->frag_threshold;
9242de8e0d9SJohannes Berg 	int hdrlen;
9252de8e0d9SJohannes Berg 	int fragnum;
926e2454948SJohannes Berg 
927252b86c4SJohannes Berg 	/* no matter what happens, tx->skb moves to tx->skbs */
928252b86c4SJohannes Berg 	__skb_queue_tail(&tx->skbs, skb);
929252b86c4SJohannes Berg 	tx->skb = NULL;
930252b86c4SJohannes Berg 
931a26eb27aSJohannes Berg 	if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
932a26eb27aSJohannes Berg 		return TX_CONTINUE;
933a26eb27aSJohannes Berg 
934f3fe4e93SSara Sharon 	if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG))
935e2454948SJohannes Berg 		return TX_CONTINUE;
936e2454948SJohannes Berg 
937eefce91aSJohannes Berg 	/*
938eefce91aSJohannes Berg 	 * Warn when submitting a fragmented A-MPDU frame and drop it.
9393b8d81e0SJohannes Berg 	 * This scenario is handled in ieee80211_tx_prepare but extra
9408d5e0d58SRon Rindjunsky 	 * caution taken here as fragmented ampdu may cause Tx stop.
941eefce91aSJohannes Berg 	 */
9428b30b1feSSujith 	if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
943eefce91aSJohannes Berg 		return TX_DROP;
944eefce91aSJohannes Berg 
945065e9605SHarvey Harrison 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
946e2454948SJohannes Berg 
947a26eb27aSJohannes Berg 	/* internal error, why isn't DONTFRAG set? */
9488ccd8f21SJohannes Berg 	if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
9492de8e0d9SJohannes Berg 		return TX_DROP;
950e2454948SJohannes Berg 
9512de8e0d9SJohannes Berg 	/*
9522de8e0d9SJohannes Berg 	 * Now fragment the frame. This will allocate all the fragments and
9532de8e0d9SJohannes Berg 	 * chain them (using skb as the first fragment) to skb->next.
9542de8e0d9SJohannes Berg 	 * During transmission, we will remove the successfully transmitted
9552de8e0d9SJohannes Berg 	 * fragments from this list. When the low-level driver rejects one
9562de8e0d9SJohannes Berg 	 * of the fragments then we will simply pretend to accept the skb
9572de8e0d9SJohannes Berg 	 * but store it away as pending.
9582de8e0d9SJohannes Berg 	 */
959252b86c4SJohannes Berg 	if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold))
9602de8e0d9SJohannes Berg 		return TX_DROP;
961e2454948SJohannes Berg 
9622de8e0d9SJohannes Berg 	/* update duration/seq/flags of fragments */
9632de8e0d9SJohannes Berg 	fragnum = 0;
964252b86c4SJohannes Berg 
965252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
9662de8e0d9SJohannes Berg 		const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
967e2454948SJohannes Berg 
9682de8e0d9SJohannes Berg 		hdr = (void *)skb->data;
9692de8e0d9SJohannes Berg 		info = IEEE80211_SKB_CB(skb);
970e6a9854bSJohannes Berg 
971252b86c4SJohannes Berg 		if (!skb_queue_is_last(&tx->skbs, skb)) {
9722de8e0d9SJohannes Berg 			hdr->frame_control |= morefrags;
973e6a9854bSJohannes Berg 			/*
974e6a9854bSJohannes Berg 			 * No multi-rate retries for fragmented frames, that
975e6a9854bSJohannes Berg 			 * would completely throw off the NAV at other STAs.
976e6a9854bSJohannes Berg 			 */
977e6a9854bSJohannes Berg 			info->control.rates[1].idx = -1;
978e6a9854bSJohannes Berg 			info->control.rates[2].idx = -1;
979e6a9854bSJohannes Berg 			info->control.rates[3].idx = -1;
980e3e1a0bcSThomas Huehn 			BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4);
981e6a9854bSJohannes Berg 			info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
9822de8e0d9SJohannes Berg 		} else {
9832de8e0d9SJohannes Berg 			hdr->frame_control &= ~morefrags;
984e6a9854bSJohannes Berg 		}
9852de8e0d9SJohannes Berg 		hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
9862de8e0d9SJohannes Berg 		fragnum++;
987252b86c4SJohannes Berg 	}
988e2454948SJohannes Berg 
989e2454948SJohannes Berg 	return TX_CONTINUE;
990e2454948SJohannes Berg }
991e2454948SJohannes Berg 
992d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
993feff1f2fSJohannes Berg ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
994feff1f2fSJohannes Berg {
995252b86c4SJohannes Berg 	struct sk_buff *skb;
996560d2682SJohannes Berg 	int ac = -1;
997feff1f2fSJohannes Berg 
998feff1f2fSJohannes Berg 	if (!tx->sta)
999feff1f2fSJohannes Berg 		return TX_CONTINUE;
1000feff1f2fSJohannes Berg 
1001252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
1002560d2682SJohannes Berg 		ac = skb_get_queue_mapping(skb);
1003e5a9f8d0SJohannes Berg 		tx->sta->tx_stats.bytes[ac] += skb->len;
1004252b86c4SJohannes Berg 	}
1005560d2682SJohannes Berg 	if (ac >= 0)
1006e5a9f8d0SJohannes Berg 		tx->sta->tx_stats.packets[ac]++;
1007feff1f2fSJohannes Berg 
1008feff1f2fSJohannes Berg 	return TX_CONTINUE;
1009feff1f2fSJohannes Berg }
1010feff1f2fSJohannes Berg 
1011feff1f2fSJohannes Berg static ieee80211_tx_result debug_noinline
1012e2454948SJohannes Berg ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1013e2454948SJohannes Berg {
1014e2454948SJohannes Berg 	if (!tx->key)
1015e2454948SJohannes Berg 		return TX_CONTINUE;
1016e2454948SJohannes Berg 
101797359d12SJohannes Berg 	switch (tx->key->conf.cipher) {
101897359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_WEP40:
101997359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_WEP104:
1020e2454948SJohannes Berg 		return ieee80211_crypto_wep_encrypt(tx);
102197359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_TKIP:
1022e2454948SJohannes Berg 		return ieee80211_crypto_tkip_encrypt(tx);
102397359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_CCMP:
10242b2ba0dbSJouni Malinen 		return ieee80211_crypto_ccmp_encrypt(
10252b2ba0dbSJouni Malinen 			tx, IEEE80211_CCMP_MIC_LEN);
10262b2ba0dbSJouni Malinen 	case WLAN_CIPHER_SUITE_CCMP_256:
10272b2ba0dbSJouni Malinen 		return ieee80211_crypto_ccmp_encrypt(
10282b2ba0dbSJouni Malinen 			tx, IEEE80211_CCMP_256_MIC_LEN);
102997359d12SJohannes Berg 	case WLAN_CIPHER_SUITE_AES_CMAC:
10303cfcf6acSJouni Malinen 		return ieee80211_crypto_aes_cmac_encrypt(tx);
103156c52da2SJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
103256c52da2SJouni Malinen 		return ieee80211_crypto_aes_cmac_256_encrypt(tx);
10338ade538bSJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
10348ade538bSJouni Malinen 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
10358ade538bSJouni Malinen 		return ieee80211_crypto_aes_gmac_encrypt(tx);
103600b9cfa3SJouni Malinen 	case WLAN_CIPHER_SUITE_GCMP:
103700b9cfa3SJouni Malinen 	case WLAN_CIPHER_SUITE_GCMP_256:
103800b9cfa3SJouni Malinen 		return ieee80211_crypto_gcmp_encrypt(tx);
10393ffc2a90SJohannes Berg 	default:
1040d32a1028SYoni Divinsky 		return ieee80211_crypto_hw_encrypt(tx);
1041e2454948SJohannes Berg 	}
1042e2454948SJohannes Berg 
1043e2454948SJohannes Berg 	return TX_DROP;
1044e2454948SJohannes Berg }
1045e2454948SJohannes Berg 
1046d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline
104703f93c3dSJohannes Berg ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
104803f93c3dSJohannes Berg {
1049252b86c4SJohannes Berg 	struct sk_buff *skb;
10502de8e0d9SJohannes Berg 	struct ieee80211_hdr *hdr;
10512de8e0d9SJohannes Berg 	int next_len;
10522de8e0d9SJohannes Berg 	bool group_addr;
105303f93c3dSJohannes Berg 
1054252b86c4SJohannes Berg 	skb_queue_walk(&tx->skbs, skb) {
10552de8e0d9SJohannes Berg 		hdr = (void *) skb->data;
10567e0aae47SJouni Malinen 		if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
10577e0aae47SJouni Malinen 			break; /* must not overwrite AID */
1058252b86c4SJohannes Berg 		if (!skb_queue_is_last(&tx->skbs, skb)) {
1059252b86c4SJohannes Berg 			struct sk_buff *next = skb_queue_next(&tx->skbs, skb);
1060252b86c4SJohannes Berg 			next_len = next->len;
1061252b86c4SJohannes Berg 		} else
1062252b86c4SJohannes Berg 			next_len = 0;
10632de8e0d9SJohannes Berg 		group_addr = is_multicast_ether_addr(hdr->addr1);
106403f93c3dSJohannes Berg 
10652de8e0d9SJohannes Berg 		hdr->duration_id =
1066252b86c4SJohannes Berg 			ieee80211_duration(tx, skb, group_addr, next_len);
1067252b86c4SJohannes Berg 	}
106803f93c3dSJohannes Berg 
106903f93c3dSJohannes Berg 	return TX_CONTINUE;
107003f93c3dSJohannes Berg }
107103f93c3dSJohannes Berg 
1072e2ebc74dSJohannes Berg /* actual transmit path */
1073e2ebc74dSJohannes Berg 
1074a622ab72SJohannes Berg static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
1075a622ab72SJohannes Berg 				  struct sk_buff *skb,
1076a622ab72SJohannes Berg 				  struct ieee80211_tx_info *info,
1077a622ab72SJohannes Berg 				  struct tid_ampdu_tx *tid_tx,
1078a622ab72SJohannes Berg 				  int tid)
1079a622ab72SJohannes Berg {
1080a622ab72SJohannes Berg 	bool queued = false;
1081285fa695SNikolay Martynov 	bool reset_agg_timer = false;
1082aa454580SHelmut Schaa 	struct sk_buff *purge_skb = NULL;
1083a622ab72SJohannes Berg 
1084a622ab72SJohannes Berg 	if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
1085a622ab72SJohannes Berg 		info->flags |= IEEE80211_TX_CTL_AMPDU;
1086285fa695SNikolay Martynov 		reset_agg_timer = true;
10870ab33703SJohannes Berg 	} else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
10880ab33703SJohannes Berg 		/*
10890ab33703SJohannes Berg 		 * nothing -- this aggregation session is being started
10900ab33703SJohannes Berg 		 * but that might still fail with the driver
10910ab33703SJohannes Berg 		 */
1092ba8c3d6fSFelix Fietkau 	} else if (!tx->sta->sta.txq[tid]) {
1093a622ab72SJohannes Berg 		spin_lock(&tx->sta->lock);
1094a622ab72SJohannes Berg 		/*
1095a622ab72SJohannes Berg 		 * Need to re-check now, because we may get here
1096a622ab72SJohannes Berg 		 *
1097a622ab72SJohannes Berg 		 *  1) in the window during which the setup is actually
1098a622ab72SJohannes Berg 		 *     already done, but not marked yet because not all
1099a622ab72SJohannes Berg 		 *     packets are spliced over to the driver pending
1100a622ab72SJohannes Berg 		 *     queue yet -- if this happened we acquire the lock
1101a622ab72SJohannes Berg 		 *     either before or after the splice happens, but
1102a622ab72SJohannes Berg 		 *     need to recheck which of these cases happened.
1103a622ab72SJohannes Berg 		 *
1104a622ab72SJohannes Berg 		 *  2) during session teardown, if the OPERATIONAL bit
1105a622ab72SJohannes Berg 		 *     was cleared due to the teardown but the pointer
1106a622ab72SJohannes Berg 		 *     hasn't been assigned NULL yet (or we loaded it
1107a622ab72SJohannes Berg 		 *     before it was assigned) -- in this case it may
1108a622ab72SJohannes Berg 		 *     now be NULL which means we should just let the
1109a622ab72SJohannes Berg 		 *     packet pass through because splicing the frames
1110a622ab72SJohannes Berg 		 *     back is already done.
1111a622ab72SJohannes Berg 		 */
111240b275b6SJohannes Berg 		tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid);
1113a622ab72SJohannes Berg 
1114a622ab72SJohannes Berg 		if (!tid_tx) {
1115a622ab72SJohannes Berg 			/* do nothing, let packet pass through */
1116a622ab72SJohannes Berg 		} else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
1117a622ab72SJohannes Berg 			info->flags |= IEEE80211_TX_CTL_AMPDU;
1118285fa695SNikolay Martynov 			reset_agg_timer = true;
1119a622ab72SJohannes Berg 		} else {
1120a622ab72SJohannes Berg 			queued = true;
1121f6d4671aSEmmanuel Grumbach 			if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) {
1122f6d4671aSEmmanuel Grumbach 				clear_sta_flag(tx->sta, WLAN_STA_SP);
1123f6d4671aSEmmanuel Grumbach 				ps_dbg(tx->sta->sdata,
1124f6d4671aSEmmanuel Grumbach 				       "STA %pM aid %d: SP frame queued, close the SP w/o telling the peer\n",
1125f6d4671aSEmmanuel Grumbach 				       tx->sta->sta.addr, tx->sta->sta.aid);
1126f6d4671aSEmmanuel Grumbach 			}
1127a622ab72SJohannes Berg 			info->control.vif = &tx->sdata->vif;
1128cc20ff2cSFelix Fietkau 			info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
1129facde7f3SEmmanuel Grumbach 			info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
1130a622ab72SJohannes Berg 			__skb_queue_tail(&tid_tx->pending, skb);
1131aa454580SHelmut Schaa 			if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
1132aa454580SHelmut Schaa 				purge_skb = __skb_dequeue(&tid_tx->pending);
1133a622ab72SJohannes Berg 		}
1134a622ab72SJohannes Berg 		spin_unlock(&tx->sta->lock);
1135aa454580SHelmut Schaa 
1136aa454580SHelmut Schaa 		if (purge_skb)
1137c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&tx->local->hw, purge_skb);
1138a622ab72SJohannes Berg 	}
1139a622ab72SJohannes Berg 
1140285fa695SNikolay Martynov 	/* reset session timer */
1141914eac24SSara Sharon 	if (reset_agg_timer)
114212d3952fSFelix Fietkau 		tid_tx->last_tx = jiffies;
1143285fa695SNikolay Martynov 
1144a622ab72SJohannes Berg 	return queued;
1145a622ab72SJohannes Berg }
1146a622ab72SJohannes Berg 
114758d4185eSJohannes Berg /*
114858d4185eSJohannes Berg  * initialises @tx
11497c10770fSJohannes Berg  * pass %NULL for the station if unknown, a valid pointer if known
11507c10770fSJohannes Berg  * or an ERR_PTR() if the station is known not to exist
115158d4185eSJohannes Berg  */
11529ae54c84SJohannes Berg static ieee80211_tx_result
11533b8d81e0SJohannes Berg ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
11543b8d81e0SJohannes Berg 		     struct ieee80211_tx_data *tx,
11557c10770fSJohannes Berg 		     struct sta_info *sta, struct sk_buff *skb)
1156e2ebc74dSJohannes Berg {
11573b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
115858d4185eSJohannes Berg 	struct ieee80211_hdr *hdr;
1159e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
116068f2b517SJohannes Berg 	int tid;
1161e2ebc74dSJohannes Berg 
1162e2ebc74dSJohannes Berg 	memset(tx, 0, sizeof(*tx));
1163e2ebc74dSJohannes Berg 	tx->skb = skb;
1164e2ebc74dSJohannes Berg 	tx->local = local;
11653b8d81e0SJohannes Berg 	tx->sdata = sdata;
1166252b86c4SJohannes Berg 	__skb_queue_head_init(&tx->skbs);
1167e2ebc74dSJohannes Berg 
1168cd8ffc80SJohannes Berg 	/*
1169cd8ffc80SJohannes Berg 	 * If this flag is set to true anywhere, and we get here,
1170cd8ffc80SJohannes Berg 	 * we are doing the needed processing, so remove the flag
1171cd8ffc80SJohannes Berg 	 * now.
1172cd8ffc80SJohannes Berg 	 */
1173cc20ff2cSFelix Fietkau 	info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
1174cd8ffc80SJohannes Berg 
117558d4185eSJohannes Berg 	hdr = (struct ieee80211_hdr *) skb->data;
117658d4185eSJohannes Berg 
11777c10770fSJohannes Berg 	if (likely(sta)) {
11787c10770fSJohannes Berg 		if (!IS_ERR(sta))
11797c10770fSJohannes Berg 			tx->sta = sta;
11807c10770fSJohannes Berg 	} else {
11813f0e0b22SFelix Fietkau 		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
1182f14543eeSFelix Fietkau 			tx->sta = rcu_dereference(sdata->u.vlan.sta);
11837c10770fSJohannes Berg 			if (!tx->sta && sdata->wdev.use_4addr)
11843f0e0b22SFelix Fietkau 				return TX_DROP;
118510cb8e61SMarkus Theil 		} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
1186b4d57adbSFelix Fietkau 			tx->sta = sta_info_get_bss(sdata, hdr->addr1);
11873f0e0b22SFelix Fietkau 		}
11889d6b106bSJohannes Berg 		if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
1189abe60632SJohannes Berg 			tx->sta = sta_info_get(sdata, hdr->addr1);
11907c10770fSJohannes Berg 	}
119158d4185eSJohannes Berg 
1192cd8ffc80SJohannes Berg 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
119349a59543SJohannes Berg 	    !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
119430686bf7SJohannes Berg 	    ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) &&
119530686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW)) {
1196cd8ffc80SJohannes Berg 		struct tid_ampdu_tx *tid_tx;
1197cd8ffc80SJohannes Berg 
1198a1f2ba04SSara Sharon 		tid = ieee80211_get_tid(hdr);
11998b30b1feSSujith 
1200a622ab72SJohannes Berg 		tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
1201a622ab72SJohannes Berg 		if (tid_tx) {
1202a622ab72SJohannes Berg 			bool queued;
1203a622ab72SJohannes Berg 
1204a622ab72SJohannes Berg 			queued = ieee80211_tx_prep_agg(tx, skb, info,
1205a622ab72SJohannes Berg 						       tid_tx, tid);
1206cd8ffc80SJohannes Berg 
1207cd8ffc80SJohannes Berg 			if (unlikely(queued))
1208cd8ffc80SJohannes Berg 				return TX_QUEUED;
12098b30b1feSSujith 		}
1210a622ab72SJohannes Berg 	}
12118b30b1feSSujith 
1212badffb72SJiri Slaby 	if (is_multicast_ether_addr(hdr->addr1)) {
12135cf121c3SJohannes Berg 		tx->flags &= ~IEEE80211_TX_UNICAST;
1214e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_NO_ACK;
12156fd67e93SSimon Wunderlich 	} else
12165cf121c3SJohannes Berg 		tx->flags |= IEEE80211_TX_UNICAST;
121758d4185eSJohannes Berg 
1218a26eb27aSJohannes Berg 	if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) {
1219a26eb27aSJohannes Berg 		if (!(tx->flags & IEEE80211_TX_UNICAST) ||
1220a26eb27aSJohannes Berg 		    skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold ||
1221a26eb27aSJohannes Berg 		    info->flags & IEEE80211_TX_CTL_AMPDU)
1222a26eb27aSJohannes Berg 			info->flags |= IEEE80211_TX_CTL_DONTFRAG;
122358d4185eSJohannes Berg 	}
122458d4185eSJohannes Berg 
1225e2ebc74dSJohannes Berg 	if (!tx->sta)
1226e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1227f7418bc1SFelix Fietkau 	else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
1228e039fa4aSJohannes Berg 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1229f7418bc1SFelix Fietkau 		ieee80211_check_fast_xmit(tx->sta);
1230f7418bc1SFelix Fietkau 	}
123158d4185eSJohannes Berg 
1232e039fa4aSJohannes Berg 	info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
1233e2ebc74dSJohannes Berg 
12349ae54c84SJohannes Berg 	return TX_CONTINUE;
1235e2ebc74dSJohannes Berg }
1236e2ebc74dSJohannes Berg 
123780a83cfcSMichal Kazior static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
1238ba8c3d6fSFelix Fietkau 					  struct ieee80211_vif *vif,
1239dbef5362SMichal Kazior 					  struct sta_info *sta,
1240ba8c3d6fSFelix Fietkau 					  struct sk_buff *skb)
1241ba8c3d6fSFelix Fietkau {
1242ba8c3d6fSFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1243ba8c3d6fSFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1244ba8c3d6fSFelix Fietkau 	struct ieee80211_txq *txq = NULL;
1245ba8c3d6fSFelix Fietkau 
1246c3732a7bSFelix Fietkau 	if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) ||
1247c3732a7bSFelix Fietkau 	    (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
124880a83cfcSMichal Kazior 		return NULL;
1249ba8c3d6fSFelix Fietkau 
1250cc20ff2cSFelix Fietkau 	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
125150ff477aSJohn Crispin 	    unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
1252adf8ed01SJohannes Berg 		if ((!ieee80211_is_mgmt(hdr->frame_control) ||
12530eeb2b67SSara Sharon 		     ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
12540eeb2b67SSara Sharon 		     vif->type == NL80211_IFTYPE_STATION) &&
1255adf8ed01SJohannes Berg 		    sta && sta->uploaded) {
1256adf8ed01SJohannes Berg 			/*
1257adf8ed01SJohannes Berg 			 * This will be NULL if the driver didn't set the
1258adf8ed01SJohannes Berg 			 * opt-in hardware flag.
1259adf8ed01SJohannes Berg 			 */
1260adf8ed01SJohannes Berg 			txq = sta->sta.txq[IEEE80211_NUM_TIDS];
1261adf8ed01SJohannes Berg 		}
1262adf8ed01SJohannes Berg 	} else if (sta) {
1263ba8c3d6fSFelix Fietkau 		u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
1264ba8c3d6fSFelix Fietkau 
1265dbef5362SMichal Kazior 		if (!sta->uploaded)
1266dbef5362SMichal Kazior 			return NULL;
1267dbef5362SMichal Kazior 
1268dbef5362SMichal Kazior 		txq = sta->sta.txq[tid];
1269ba8c3d6fSFelix Fietkau 	} else if (vif) {
1270ba8c3d6fSFelix Fietkau 		txq = vif->txq;
1271ba8c3d6fSFelix Fietkau 	}
1272ba8c3d6fSFelix Fietkau 
1273ba8c3d6fSFelix Fietkau 	if (!txq)
127480a83cfcSMichal Kazior 		return NULL;
1275ba8c3d6fSFelix Fietkau 
127680a83cfcSMichal Kazior 	return to_txq_info(txq);
127780a83cfcSMichal Kazior }
1278ba8c3d6fSFelix Fietkau 
12795caa328eSMichal Kazior static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
12805caa328eSMichal Kazior {
12815caa328eSMichal Kazior 	IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
12825caa328eSMichal Kazior }
12835caa328eSMichal Kazior 
12845caa328eSMichal Kazior static u32 codel_skb_len_func(const struct sk_buff *skb)
12855caa328eSMichal Kazior {
12865caa328eSMichal Kazior 	return skb->len;
12875caa328eSMichal Kazior }
12885caa328eSMichal Kazior 
12895caa328eSMichal Kazior static codel_time_t codel_skb_time_func(const struct sk_buff *skb)
12905caa328eSMichal Kazior {
12915caa328eSMichal Kazior 	const struct ieee80211_tx_info *info;
12925caa328eSMichal Kazior 
12935caa328eSMichal Kazior 	info = (const struct ieee80211_tx_info *)skb->cb;
12945caa328eSMichal Kazior 	return info->control.enqueue_time;
12955caa328eSMichal Kazior }
12965caa328eSMichal Kazior 
12975caa328eSMichal Kazior static struct sk_buff *codel_dequeue_func(struct codel_vars *cvars,
12985caa328eSMichal Kazior 					  void *ctx)
12995caa328eSMichal Kazior {
13005caa328eSMichal Kazior 	struct ieee80211_local *local;
13015caa328eSMichal Kazior 	struct txq_info *txqi;
13025caa328eSMichal Kazior 	struct fq *fq;
13035caa328eSMichal Kazior 	struct fq_flow *flow;
13045caa328eSMichal Kazior 
13055caa328eSMichal Kazior 	txqi = ctx;
13065caa328eSMichal Kazior 	local = vif_to_sdata(txqi->txq.vif)->local;
13075caa328eSMichal Kazior 	fq = &local->fq;
13085caa328eSMichal Kazior 
13095caa328eSMichal Kazior 	if (cvars == &txqi->def_cvars)
1310bf9009bfSFelix Fietkau 		flow = &txqi->tin.default_flow;
13115caa328eSMichal Kazior 	else
13125caa328eSMichal Kazior 		flow = &fq->flows[cvars - local->cvars];
13135caa328eSMichal Kazior 
13145caa328eSMichal Kazior 	return fq_flow_dequeue(fq, flow);
13155caa328eSMichal Kazior }
13165caa328eSMichal Kazior 
13175caa328eSMichal Kazior static void codel_drop_func(struct sk_buff *skb,
13185caa328eSMichal Kazior 			    void *ctx)
13195caa328eSMichal Kazior {
13205caa328eSMichal Kazior 	struct ieee80211_local *local;
13215caa328eSMichal Kazior 	struct ieee80211_hw *hw;
13225caa328eSMichal Kazior 	struct txq_info *txqi;
13235caa328eSMichal Kazior 
13245caa328eSMichal Kazior 	txqi = ctx;
13255caa328eSMichal Kazior 	local = vif_to_sdata(txqi->txq.vif)->local;
13265caa328eSMichal Kazior 	hw = &local->hw;
13275caa328eSMichal Kazior 
13285caa328eSMichal Kazior 	ieee80211_free_txskb(hw, skb);
13295caa328eSMichal Kazior }
13305caa328eSMichal Kazior 
1331fa962b92SMichal Kazior static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
1332fa962b92SMichal Kazior 					   struct fq_tin *tin,
1333fa962b92SMichal Kazior 					   struct fq_flow *flow)
1334fa962b92SMichal Kazior {
13355caa328eSMichal Kazior 	struct ieee80211_local *local;
13365caa328eSMichal Kazior 	struct txq_info *txqi;
13375caa328eSMichal Kazior 	struct codel_vars *cvars;
13385caa328eSMichal Kazior 	struct codel_params *cparams;
13395caa328eSMichal Kazior 	struct codel_stats *cstats;
13405caa328eSMichal Kazior 
13415caa328eSMichal Kazior 	local = container_of(fq, struct ieee80211_local, fq);
13425caa328eSMichal Kazior 	txqi = container_of(tin, struct txq_info, tin);
13438d51dbb8SToke Høiland-Jørgensen 	cstats = &txqi->cstats;
13445caa328eSMichal Kazior 
1345484a54c2SToke Høiland-Jørgensen 	if (txqi->txq.sta) {
1346484a54c2SToke Høiland-Jørgensen 		struct sta_info *sta = container_of(txqi->txq.sta,
1347484a54c2SToke Høiland-Jørgensen 						    struct sta_info, sta);
1348484a54c2SToke Høiland-Jørgensen 		cparams = &sta->cparams;
1349484a54c2SToke Høiland-Jørgensen 	} else {
1350484a54c2SToke Høiland-Jørgensen 		cparams = &local->cparams;
1351484a54c2SToke Høiland-Jørgensen 	}
1352484a54c2SToke Høiland-Jørgensen 
1353bf9009bfSFelix Fietkau 	if (flow == &tin->default_flow)
13545caa328eSMichal Kazior 		cvars = &txqi->def_cvars;
13555caa328eSMichal Kazior 	else
13565caa328eSMichal Kazior 		cvars = &local->cvars[flow - fq->flows];
13575caa328eSMichal Kazior 
13585caa328eSMichal Kazior 	return codel_dequeue(txqi,
13595caa328eSMichal Kazior 			     &flow->backlog,
13605caa328eSMichal Kazior 			     cparams,
13615caa328eSMichal Kazior 			     cvars,
13625caa328eSMichal Kazior 			     cstats,
13635caa328eSMichal Kazior 			     codel_skb_len_func,
13645caa328eSMichal Kazior 			     codel_skb_time_func,
13655caa328eSMichal Kazior 			     codel_drop_func,
13665caa328eSMichal Kazior 			     codel_dequeue_func);
1367fa962b92SMichal Kazior }
1368fa962b92SMichal Kazior 
1369fa962b92SMichal Kazior static void fq_skb_free_func(struct fq *fq,
1370fa962b92SMichal Kazior 			     struct fq_tin *tin,
1371fa962b92SMichal Kazior 			     struct fq_flow *flow,
1372fa962b92SMichal Kazior 			     struct sk_buff *skb)
1373fa962b92SMichal Kazior {
1374fa962b92SMichal Kazior 	struct ieee80211_local *local;
1375fa962b92SMichal Kazior 
1376fa962b92SMichal Kazior 	local = container_of(fq, struct ieee80211_local, fq);
1377fa962b92SMichal Kazior 	ieee80211_free_txskb(&local->hw, skb);
1378fa962b92SMichal Kazior }
1379fa962b92SMichal Kazior 
138080a83cfcSMichal Kazior static void ieee80211_txq_enqueue(struct ieee80211_local *local,
138180a83cfcSMichal Kazior 				  struct txq_info *txqi,
138280a83cfcSMichal Kazior 				  struct sk_buff *skb)
138380a83cfcSMichal Kazior {
1384fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1385fa962b92SMichal Kazior 	struct fq_tin *tin = &txqi->tin;
1386f2af2df8SFelix Fietkau 	u32 flow_idx = fq_flow_idx(fq, skb);
138780a83cfcSMichal Kazior 
13885caa328eSMichal Kazior 	ieee80211_set_skb_enqueue_time(skb);
1389f2af2df8SFelix Fietkau 
1390f2af2df8SFelix Fietkau 	spin_lock_bh(&fq->lock);
139173bc9e0aSJohannes Berg 	/*
139273bc9e0aSJohannes Berg 	 * For management frames, don't really apply codel etc.,
139373bc9e0aSJohannes Berg 	 * we don't want to apply any shaping or anything we just
139473bc9e0aSJohannes Berg 	 * want to simplify the driver API by having them on the
139573bc9e0aSJohannes Berg 	 * txqi.
139673bc9e0aSJohannes Berg 	 */
1397ca47b462SJohannes Berg 	if (unlikely(txqi->txq.tid == IEEE80211_NUM_TIDS)) {
1398ca47b462SJohannes Berg 		IEEE80211_SKB_CB(skb)->control.flags |=
1399ca47b462SJohannes Berg 			IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
140073bc9e0aSJohannes Berg 		__skb_queue_tail(&txqi->frags, skb);
1401ca47b462SJohannes Berg 	} else {
1402f2af2df8SFelix Fietkau 		fq_tin_enqueue(fq, tin, flow_idx, skb,
1403bf9009bfSFelix Fietkau 			       fq_skb_free_func);
1404ca47b462SJohannes Berg 	}
1405f2af2df8SFelix Fietkau 	spin_unlock_bh(&fq->lock);
140680a83cfcSMichal Kazior }
140780a83cfcSMichal Kazior 
14082a9e2579SJohannes Berg static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin,
14092a9e2579SJohannes Berg 				struct fq_flow *flow, struct sk_buff *skb,
14102a9e2579SJohannes Berg 				void *data)
14112a9e2579SJohannes Berg {
14122a9e2579SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
14132a9e2579SJohannes Berg 
14142a9e2579SJohannes Berg 	return info->control.vif == data;
14152a9e2579SJohannes Berg }
14162a9e2579SJohannes Berg 
14172a9e2579SJohannes Berg void ieee80211_txq_remove_vlan(struct ieee80211_local *local,
14182a9e2579SJohannes Berg 			       struct ieee80211_sub_if_data *sdata)
14192a9e2579SJohannes Berg {
14202a9e2579SJohannes Berg 	struct fq *fq = &local->fq;
14212a9e2579SJohannes Berg 	struct txq_info *txqi;
14222a9e2579SJohannes Berg 	struct fq_tin *tin;
14232a9e2579SJohannes Berg 	struct ieee80211_sub_if_data *ap;
14242a9e2579SJohannes Berg 
14252a9e2579SJohannes Berg 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
14262a9e2579SJohannes Berg 		return;
14272a9e2579SJohannes Berg 
14282a9e2579SJohannes Berg 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
14292a9e2579SJohannes Berg 
14302a9e2579SJohannes Berg 	if (!ap->vif.txq)
14312a9e2579SJohannes Berg 		return;
14322a9e2579SJohannes Berg 
14332a9e2579SJohannes Berg 	txqi = to_txq_info(ap->vif.txq);
14342a9e2579SJohannes Berg 	tin = &txqi->tin;
14352a9e2579SJohannes Berg 
14362a9e2579SJohannes Berg 	spin_lock_bh(&fq->lock);
14372a9e2579SJohannes Berg 	fq_tin_filter(fq, tin, fq_vlan_filter_func, &sdata->vif,
14382a9e2579SJohannes Berg 		      fq_skb_free_func);
14392a9e2579SJohannes Berg 	spin_unlock_bh(&fq->lock);
14402a9e2579SJohannes Berg }
14412a9e2579SJohannes Berg 
1442fa962b92SMichal Kazior void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
1443fa962b92SMichal Kazior 			struct sta_info *sta,
1444fa962b92SMichal Kazior 			struct txq_info *txqi, int tid)
1445fa962b92SMichal Kazior {
1446fa962b92SMichal Kazior 	fq_tin_init(&txqi->tin);
14475caa328eSMichal Kazior 	codel_vars_init(&txqi->def_cvars);
14488d51dbb8SToke Høiland-Jørgensen 	codel_stats_init(&txqi->cstats);
1449bb42f2d1SToke Høiland-Jørgensen 	__skb_queue_head_init(&txqi->frags);
145018667600SToke Høiland-Jørgensen 	INIT_LIST_HEAD(&txqi->schedule_order);
1451fa962b92SMichal Kazior 
1452fa962b92SMichal Kazior 	txqi->txq.vif = &sdata->vif;
1453fa962b92SMichal Kazior 
1454adf8ed01SJohannes Berg 	if (!sta) {
1455fa962b92SMichal Kazior 		sdata->vif.txq = &txqi->txq;
1456fa962b92SMichal Kazior 		txqi->txq.tid = 0;
1457fa962b92SMichal Kazior 		txqi->txq.ac = IEEE80211_AC_BE;
1458adf8ed01SJohannes Berg 
1459adf8ed01SJohannes Berg 		return;
1460fa962b92SMichal Kazior 	}
1461adf8ed01SJohannes Berg 
1462adf8ed01SJohannes Berg 	if (tid == IEEE80211_NUM_TIDS) {
14630eeb2b67SSara Sharon 		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
14640eeb2b67SSara Sharon 			/* Drivers need to opt in to the management MPDU TXQ */
14650eeb2b67SSara Sharon 			if (!ieee80211_hw_check(&sdata->local->hw,
14660eeb2b67SSara Sharon 						STA_MMPDU_TXQ))
1467adf8ed01SJohannes Berg 				return;
14680eeb2b67SSara Sharon 		} else if (!ieee80211_hw_check(&sdata->local->hw,
14690eeb2b67SSara Sharon 					       BUFF_MMPDU_TXQ)) {
14700eeb2b67SSara Sharon 			/* Drivers need to opt in to the bufferable MMPDU TXQ */
14710eeb2b67SSara Sharon 			return;
14720eeb2b67SSara Sharon 		}
1473adf8ed01SJohannes Berg 		txqi->txq.ac = IEEE80211_AC_VO;
1474adf8ed01SJohannes Berg 	} else {
1475adf8ed01SJohannes Berg 		txqi->txq.ac = ieee80211_ac_from_tid(tid);
1476adf8ed01SJohannes Berg 	}
1477adf8ed01SJohannes Berg 
1478adf8ed01SJohannes Berg 	txqi->txq.sta = &sta->sta;
1479adf8ed01SJohannes Berg 	txqi->txq.tid = tid;
1480adf8ed01SJohannes Berg 	sta->sta.txq[tid] = &txqi->txq;
1481fa962b92SMichal Kazior }
1482fa962b92SMichal Kazior 
1483fa962b92SMichal Kazior void ieee80211_txq_purge(struct ieee80211_local *local,
1484fa962b92SMichal Kazior 			 struct txq_info *txqi)
1485fa962b92SMichal Kazior {
1486fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1487fa962b92SMichal Kazior 	struct fq_tin *tin = &txqi->tin;
1488fa962b92SMichal Kazior 
1489b4809e94SToke Høiland-Jørgensen 	spin_lock_bh(&fq->lock);
1490fa962b92SMichal Kazior 	fq_tin_reset(fq, tin, fq_skb_free_func);
1491bb42f2d1SToke Høiland-Jørgensen 	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
1492b4809e94SToke Høiland-Jørgensen 	spin_unlock_bh(&fq->lock);
1493b4809e94SToke Høiland-Jørgensen 
149418667600SToke Høiland-Jørgensen 	spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]);
149518667600SToke Høiland-Jørgensen 	list_del_init(&txqi->schedule_order);
149618667600SToke Høiland-Jørgensen 	spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]);
1497fa962b92SMichal Kazior }
1498fa962b92SMichal Kazior 
14992fe4a29aSToke Høiland-Jørgensen void ieee80211_txq_set_params(struct ieee80211_local *local)
15002fe4a29aSToke Høiland-Jørgensen {
15012fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_limit)
15022fe4a29aSToke Høiland-Jørgensen 		local->fq.limit = local->hw.wiphy->txq_limit;
15032fe4a29aSToke Høiland-Jørgensen 	else
15042fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_limit = local->fq.limit;
15052fe4a29aSToke Høiland-Jørgensen 
15062fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_memory_limit)
15072fe4a29aSToke Høiland-Jørgensen 		local->fq.memory_limit = local->hw.wiphy->txq_memory_limit;
15082fe4a29aSToke Høiland-Jørgensen 	else
15092fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_memory_limit = local->fq.memory_limit;
15102fe4a29aSToke Høiland-Jørgensen 
15112fe4a29aSToke Høiland-Jørgensen 	if (local->hw.wiphy->txq_quantum)
15122fe4a29aSToke Høiland-Jørgensen 		local->fq.quantum = local->hw.wiphy->txq_quantum;
15132fe4a29aSToke Høiland-Jørgensen 	else
15142fe4a29aSToke Høiland-Jørgensen 		local->hw.wiphy->txq_quantum = local->fq.quantum;
15152fe4a29aSToke Høiland-Jørgensen }
15162fe4a29aSToke Høiland-Jørgensen 
1517fa962b92SMichal Kazior int ieee80211_txq_setup_flows(struct ieee80211_local *local)
1518fa962b92SMichal Kazior {
1519fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1520fa962b92SMichal Kazior 	int ret;
15215caa328eSMichal Kazior 	int i;
15223ff23cd5SToke Høiland-Jørgensen 	bool supp_vht = false;
15233ff23cd5SToke Høiland-Jørgensen 	enum nl80211_band band;
1524fa962b92SMichal Kazior 
1525fa962b92SMichal Kazior 	if (!local->ops->wake_tx_queue)
1526fa962b92SMichal Kazior 		return 0;
1527fa962b92SMichal Kazior 
1528fa962b92SMichal Kazior 	ret = fq_init(fq, 4096);
1529fa962b92SMichal Kazior 	if (ret)
1530fa962b92SMichal Kazior 		return ret;
1531fa962b92SMichal Kazior 
15323ff23cd5SToke Høiland-Jørgensen 	/*
15333ff23cd5SToke Høiland-Jørgensen 	 * If the hardware doesn't support VHT, it is safe to limit the maximum
15343ff23cd5SToke Høiland-Jørgensen 	 * queue size. 4 Mbytes is 64 max-size aggregates in 802.11n.
15353ff23cd5SToke Høiland-Jørgensen 	 */
15363ff23cd5SToke Høiland-Jørgensen 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
15373ff23cd5SToke Høiland-Jørgensen 		struct ieee80211_supported_band *sband;
15383ff23cd5SToke Høiland-Jørgensen 
15393ff23cd5SToke Høiland-Jørgensen 		sband = local->hw.wiphy->bands[band];
15403ff23cd5SToke Høiland-Jørgensen 		if (!sband)
15413ff23cd5SToke Høiland-Jørgensen 			continue;
15423ff23cd5SToke Høiland-Jørgensen 
15433ff23cd5SToke Høiland-Jørgensen 		supp_vht = supp_vht || sband->vht_cap.vht_supported;
15443ff23cd5SToke Høiland-Jørgensen 	}
15453ff23cd5SToke Høiland-Jørgensen 
15463ff23cd5SToke Høiland-Jørgensen 	if (!supp_vht)
15473ff23cd5SToke Høiland-Jørgensen 		fq->memory_limit = 4 << 20; /* 4 Mbytes */
15483ff23cd5SToke Høiland-Jørgensen 
15495caa328eSMichal Kazior 	codel_params_init(&local->cparams);
15505caa328eSMichal Kazior 	local->cparams.interval = MS2TIME(100);
15515caa328eSMichal Kazior 	local->cparams.target = MS2TIME(20);
15525caa328eSMichal Kazior 	local->cparams.ecn = true;
15535caa328eSMichal Kazior 
15545caa328eSMichal Kazior 	local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
15555caa328eSMichal Kazior 			       GFP_KERNEL);
15565caa328eSMichal Kazior 	if (!local->cvars) {
155759a7c828SMichal Kazior 		spin_lock_bh(&fq->lock);
15585caa328eSMichal Kazior 		fq_reset(fq, fq_skb_free_func);
155959a7c828SMichal Kazior 		spin_unlock_bh(&fq->lock);
15605caa328eSMichal Kazior 		return -ENOMEM;
15615caa328eSMichal Kazior 	}
15625caa328eSMichal Kazior 
15635caa328eSMichal Kazior 	for (i = 0; i < fq->flows_cnt; i++)
15645caa328eSMichal Kazior 		codel_vars_init(&local->cvars[i]);
15655caa328eSMichal Kazior 
15662fe4a29aSToke Høiland-Jørgensen 	ieee80211_txq_set_params(local);
15672fe4a29aSToke Høiland-Jørgensen 
1568fa962b92SMichal Kazior 	return 0;
1569fa962b92SMichal Kazior }
1570fa962b92SMichal Kazior 
1571fa962b92SMichal Kazior void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
1572fa962b92SMichal Kazior {
1573fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
1574fa962b92SMichal Kazior 
1575fa962b92SMichal Kazior 	if (!local->ops->wake_tx_queue)
1576fa962b92SMichal Kazior 		return;
1577fa962b92SMichal Kazior 
15785caa328eSMichal Kazior 	kfree(local->cvars);
15795caa328eSMichal Kazior 	local->cvars = NULL;
15805caa328eSMichal Kazior 
158159a7c828SMichal Kazior 	spin_lock_bh(&fq->lock);
1582fa962b92SMichal Kazior 	fq_reset(fq, fq_skb_free_func);
158359a7c828SMichal Kazior 	spin_unlock_bh(&fq->lock);
1584ba8c3d6fSFelix Fietkau }
1585ba8c3d6fSFelix Fietkau 
1586bb42f2d1SToke Høiland-Jørgensen static bool ieee80211_queue_skb(struct ieee80211_local *local,
1587bb42f2d1SToke Høiland-Jørgensen 				struct ieee80211_sub_if_data *sdata,
1588bb42f2d1SToke Høiland-Jørgensen 				struct sta_info *sta,
1589bb42f2d1SToke Høiland-Jørgensen 				struct sk_buff *skb)
1590bb42f2d1SToke Høiland-Jørgensen {
1591bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_vif *vif;
1592bb42f2d1SToke Høiland-Jørgensen 	struct txq_info *txqi;
1593bb42f2d1SToke Høiland-Jørgensen 
1594bb42f2d1SToke Høiland-Jørgensen 	if (!local->ops->wake_tx_queue ||
1595bb42f2d1SToke Høiland-Jørgensen 	    sdata->vif.type == NL80211_IFTYPE_MONITOR)
1596bb42f2d1SToke Høiland-Jørgensen 		return false;
1597bb42f2d1SToke Høiland-Jørgensen 
1598bb42f2d1SToke Høiland-Jørgensen 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1599bb42f2d1SToke Høiland-Jørgensen 		sdata = container_of(sdata->bss,
1600bb42f2d1SToke Høiland-Jørgensen 				     struct ieee80211_sub_if_data, u.ap);
1601bb42f2d1SToke Høiland-Jørgensen 
1602bb42f2d1SToke Høiland-Jørgensen 	vif = &sdata->vif;
1603dbef5362SMichal Kazior 	txqi = ieee80211_get_txq(local, vif, sta, skb);
1604bb42f2d1SToke Høiland-Jørgensen 
1605bb42f2d1SToke Høiland-Jørgensen 	if (!txqi)
1606bb42f2d1SToke Høiland-Jørgensen 		return false;
1607bb42f2d1SToke Høiland-Jørgensen 
1608bb42f2d1SToke Høiland-Jørgensen 	ieee80211_txq_enqueue(local, txqi, skb);
1609bb42f2d1SToke Høiland-Jørgensen 
161018667600SToke Høiland-Jørgensen 	schedule_and_wake_txq(local, txqi);
1611bb42f2d1SToke Høiland-Jørgensen 
1612bb42f2d1SToke Høiland-Jørgensen 	return true;
1613bb42f2d1SToke Høiland-Jørgensen }
1614bb42f2d1SToke Høiland-Jørgensen 
161511127e91SJohannes Berg static bool ieee80211_tx_frags(struct ieee80211_local *local,
161611127e91SJohannes Berg 			       struct ieee80211_vif *vif,
16174fd0328dSJohannes Berg 			       struct sta_info *sta,
161811127e91SJohannes Berg 			       struct sk_buff_head *skbs,
161911127e91SJohannes Berg 			       bool txpending)
1620e2ebc74dSJohannes Berg {
162180a83cfcSMichal Kazior 	struct ieee80211_tx_control control = {};
1622252b86c4SJohannes Berg 	struct sk_buff *skb, *tmp;
16233b8d81e0SJohannes Berg 	unsigned long flags;
1624e2ebc74dSJohannes Berg 
1625252b86c4SJohannes Berg 	skb_queue_walk_safe(skbs, skb, tmp) {
16263a25a8c8SJohannes Berg 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
16273a25a8c8SJohannes Berg 		int q = info->hw_queue;
16283a25a8c8SJohannes Berg 
16293a25a8c8SJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
16303a25a8c8SJohannes Berg 		if (WARN_ON_ONCE(q >= local->hw.queues)) {
16313a25a8c8SJohannes Berg 			__skb_unlink(skb, skbs);
1632c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
16333a25a8c8SJohannes Berg 			continue;
16343a25a8c8SJohannes Berg 		}
16353a25a8c8SJohannes Berg #endif
16363b8d81e0SJohannes Berg 
16373b8d81e0SJohannes Berg 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
16383b8d81e0SJohannes Berg 		if (local->queue_stop_reasons[q] ||
16397bb45683SJohannes Berg 		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
16406c17b77bSSeth Forshee 			if (unlikely(info->flags &
1641a7679ed5SSeth Forshee 				     IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
1642a7679ed5SSeth Forshee 				if (local->queue_stop_reasons[q] &
1643a7679ed5SSeth Forshee 				    ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
16446c17b77bSSeth Forshee 					/*
1645a7679ed5SSeth Forshee 					 * Drop off-channel frames if queues
1646a7679ed5SSeth Forshee 					 * are stopped for any reason other
1647a7679ed5SSeth Forshee 					 * than off-channel operation. Never
1648a7679ed5SSeth Forshee 					 * queue them.
16496c17b77bSSeth Forshee 					 */
16506c17b77bSSeth Forshee 					spin_unlock_irqrestore(
1651a7679ed5SSeth Forshee 						&local->queue_stop_reason_lock,
1652a7679ed5SSeth Forshee 						flags);
1653a7679ed5SSeth Forshee 					ieee80211_purge_tx_queue(&local->hw,
1654a7679ed5SSeth Forshee 								 skbs);
16556c17b77bSSeth Forshee 					return true;
16566c17b77bSSeth Forshee 				}
1657a7679ed5SSeth Forshee 			} else {
16586c17b77bSSeth Forshee 
16597bb45683SJohannes Berg 				/*
1660a7679ed5SSeth Forshee 				 * Since queue is stopped, queue up frames for
1661a7679ed5SSeth Forshee 				 * later transmission from the tx-pending
1662a7679ed5SSeth Forshee 				 * tasklet when the queue is woken again.
16637bb45683SJohannes Berg 				 */
1664252b86c4SJohannes Berg 				if (txpending)
1665a7679ed5SSeth Forshee 					skb_queue_splice_init(skbs,
1666a7679ed5SSeth Forshee 							      &local->pending[q]);
16677bb45683SJohannes Berg 				else
16684db4e0a1SJohannes Berg 					skb_queue_splice_tail_init(skbs,
16694db4e0a1SJohannes Berg 								   &local->pending[q]);
16707bb45683SJohannes Berg 
16717bb45683SJohannes Berg 				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
16727bb45683SJohannes Berg 						       flags);
16737bb45683SJohannes Berg 				return false;
16747bb45683SJohannes Berg 			}
1675a7679ed5SSeth Forshee 		}
16763b8d81e0SJohannes Berg 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1677e2530083SJohannes Berg 
167811127e91SJohannes Berg 		info->control.vif = vif;
16794fd0328dSJohannes Berg 		control.sta = sta ? &sta->sta : NULL;
1680ec25acc4SJohannes Berg 
1681252b86c4SJohannes Berg 		__skb_unlink(skb, skbs);
168280a83cfcSMichal Kazior 		drv_tx(local, &control, skb);
1683e2ebc74dSJohannes Berg 	}
16842de8e0d9SJohannes Berg 
168511127e91SJohannes Berg 	return true;
168611127e91SJohannes Berg }
168711127e91SJohannes Berg 
168811127e91SJohannes Berg /*
168911127e91SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead.
169011127e91SJohannes Berg  */
169111127e91SJohannes Berg static bool __ieee80211_tx(struct ieee80211_local *local,
169211127e91SJohannes Berg 			   struct sk_buff_head *skbs, int led_len,
169311127e91SJohannes Berg 			   struct sta_info *sta, bool txpending)
169411127e91SJohannes Berg {
169511127e91SJohannes Berg 	struct ieee80211_tx_info *info;
169611127e91SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
169711127e91SJohannes Berg 	struct ieee80211_vif *vif;
169811127e91SJohannes Berg 	struct sk_buff *skb;
1699958574cbSColin Ian King 	bool result;
170011127e91SJohannes Berg 	__le16 fc;
170111127e91SJohannes Berg 
170211127e91SJohannes Berg 	if (WARN_ON(skb_queue_empty(skbs)))
170311127e91SJohannes Berg 		return true;
170411127e91SJohannes Berg 
170511127e91SJohannes Berg 	skb = skb_peek(skbs);
170611127e91SJohannes Berg 	fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
170711127e91SJohannes Berg 	info = IEEE80211_SKB_CB(skb);
170811127e91SJohannes Berg 	sdata = vif_to_sdata(info->control.vif);
170911127e91SJohannes Berg 	if (sta && !sta->uploaded)
171011127e91SJohannes Berg 		sta = NULL;
171111127e91SJohannes Berg 
171211127e91SJohannes Berg 	switch (sdata->vif.type) {
171311127e91SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
1714d8212184SAviya Erenfeld 		if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
1715c82b5a74SJohannes Berg 			vif = &sdata->vif;
1716c82b5a74SJohannes Berg 			break;
1717c82b5a74SJohannes Berg 		}
17184b6f1dd6SJohannes Berg 		sdata = rcu_dereference(local->monitor_sdata);
17193a25a8c8SJohannes Berg 		if (sdata) {
17204b6f1dd6SJohannes Berg 			vif = &sdata->vif;
17213a25a8c8SJohannes Berg 			info->hw_queue =
17223a25a8c8SJohannes Berg 				vif->hw_queue[skb_get_queue_mapping(skb)];
172330686bf7SJohannes Berg 		} else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
172463b4d8b3SJohannes Berg 			ieee80211_purge_tx_queue(&local->hw, skbs);
17253a25a8c8SJohannes Berg 			return true;
17263a25a8c8SJohannes Berg 		} else
172711127e91SJohannes Berg 			vif = NULL;
172811127e91SJohannes Berg 		break;
172911127e91SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
173011127e91SJohannes Berg 		sdata = container_of(sdata->bss,
173111127e91SJohannes Berg 				     struct ieee80211_sub_if_data, u.ap);
1732fc0561dcSGustavo A. R. Silva 		fallthrough;
173311127e91SJohannes Berg 	default:
173411127e91SJohannes Berg 		vif = &sdata->vif;
173511127e91SJohannes Berg 		break;
173611127e91SJohannes Berg 	}
173711127e91SJohannes Berg 
17384fd0328dSJohannes Berg 	result = ieee80211_tx_frags(local, vif, sta, skbs, txpending);
173911127e91SJohannes Berg 
174074e4dbfdSJohannes Berg 	ieee80211_tpt_led_trig_tx(local, fc, led_len);
174174e4dbfdSJohannes Berg 
17424db4e0a1SJohannes Berg 	WARN_ON_ONCE(!skb_queue_empty(skbs));
1743252b86c4SJohannes Berg 
174411127e91SJohannes Berg 	return result;
1745e2ebc74dSJohannes Berg }
1746e2ebc74dSJohannes Berg 
174797b045d6SJohannes Berg /*
174897b045d6SJohannes Berg  * Invoke TX handlers, return 0 on success and non-zero if the
174997b045d6SJohannes Berg  * frame was dropped or queued.
1750bb42f2d1SToke Høiland-Jørgensen  *
1751bb42f2d1SToke Høiland-Jørgensen  * The handlers are split into an early and late part. The latter is everything
1752bb42f2d1SToke Høiland-Jørgensen  * that can be sensitive to reordering, and will be deferred to after packets
1753bb42f2d1SToke Høiland-Jørgensen  * are dequeued from the intermediate queues (when they are enabled).
175497b045d6SJohannes Berg  */
1755bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
175697b045d6SJohannes Berg {
175797b045d6SJohannes Berg 	ieee80211_tx_result res = TX_DROP;
175897b045d6SJohannes Berg 
1759d9e8a70fSJohannes Berg #define CALL_TXH(txh) \
17609aa4aee3SJohannes Berg 	do {				\
1761d9e8a70fSJohannes Berg 		res = txh(tx);		\
1762d9e8a70fSJohannes Berg 		if (res != TX_CONTINUE)	\
17639aa4aee3SJohannes Berg 			goto txh_done;	\
17649aa4aee3SJohannes Berg 	} while (0)
176597b045d6SJohannes Berg 
17665c1b98a5SKalle Valo 	CALL_TXH(ieee80211_tx_h_dynamic_ps);
17679aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_check_assoc);
17689aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_ps_buf);
1769a621fa4dSJohannes Berg 	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
17709aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_select_key);
1771c6fcf6bcSJohannes Berg 
1772bb42f2d1SToke Høiland-Jørgensen  txh_done:
1773bb42f2d1SToke Høiland-Jørgensen 	if (unlikely(res == TX_DROP)) {
1774bb42f2d1SToke Høiland-Jørgensen 		I802_DEBUG_INC(tx->local->tx_handlers_drop);
1775bb42f2d1SToke Høiland-Jørgensen 		if (tx->skb)
1776bb42f2d1SToke Høiland-Jørgensen 			ieee80211_free_txskb(&tx->local->hw, tx->skb);
1777bb42f2d1SToke Høiland-Jørgensen 		else
1778bb42f2d1SToke Høiland-Jørgensen 			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
1779bb42f2d1SToke Høiland-Jørgensen 		return -1;
1780bb42f2d1SToke Høiland-Jørgensen 	} else if (unlikely(res == TX_QUEUED)) {
1781bb42f2d1SToke Høiland-Jørgensen 		I802_DEBUG_INC(tx->local->tx_handlers_queued);
1782bb42f2d1SToke Høiland-Jørgensen 		return -1;
1783bb42f2d1SToke Høiland-Jørgensen 	}
1784bb42f2d1SToke Høiland-Jørgensen 
1785bb42f2d1SToke Høiland-Jørgensen 	return 0;
1786bb42f2d1SToke Høiland-Jørgensen }
1787bb42f2d1SToke Høiland-Jørgensen 
1788bb42f2d1SToke Høiland-Jørgensen /*
1789bb42f2d1SToke Høiland-Jørgensen  * Late handlers can be called while the sta lock is held. Handlers that can
1790bb42f2d1SToke Høiland-Jørgensen  * cause packets to be generated will cause deadlock!
1791bb42f2d1SToke Høiland-Jørgensen  */
1792bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
1793bb42f2d1SToke Høiland-Jørgensen {
1794bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
1795bb42f2d1SToke Høiland-Jørgensen 	ieee80211_tx_result res = TX_CONTINUE;
1796bb42f2d1SToke Høiland-Jørgensen 
1797aa5b5492SJohannes Berg 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
1798aa5b5492SJohannes Berg 		__skb_queue_tail(&tx->skbs, tx->skb);
1799aa5b5492SJohannes Berg 		tx->skb = NULL;
1800c6fcf6bcSJohannes Berg 		goto txh_done;
1801aa5b5492SJohannes Berg 	}
1802c6fcf6bcSJohannes Berg 
1803*03c3911dSRyder Lee 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
1804*03c3911dSRyder Lee 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
1805*03c3911dSRyder Lee 
1806c6fcf6bcSJohannes Berg 	CALL_TXH(ieee80211_tx_h_michael_mic_add);
18079aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_sequence);
18089aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_fragment);
1809d9e8a70fSJohannes Berg 	/* handlers after fragment must be aware of tx info fragmentation! */
18109aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_stats);
18119aa4aee3SJohannes Berg 	CALL_TXH(ieee80211_tx_h_encrypt);
181230686bf7SJohannes Berg 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
18139aa4aee3SJohannes Berg 		CALL_TXH(ieee80211_tx_h_calculate_duration);
1814d9e8a70fSJohannes Berg #undef CALL_TXH
1815d9e8a70fSJohannes Berg 
1816d9e8a70fSJohannes Berg  txh_done:
181797b045d6SJohannes Berg 	if (unlikely(res == TX_DROP)) {
18185479d0e7STomas Winkler 		I802_DEBUG_INC(tx->local->tx_handlers_drop);
1819252b86c4SJohannes Berg 		if (tx->skb)
1820c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&tx->local->hw, tx->skb);
1821252b86c4SJohannes Berg 		else
18221f98ab7fSFelix Fietkau 			ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
182397b045d6SJohannes Berg 		return -1;
182497b045d6SJohannes Berg 	} else if (unlikely(res == TX_QUEUED)) {
18255479d0e7STomas Winkler 		I802_DEBUG_INC(tx->local->tx_handlers_queued);
182697b045d6SJohannes Berg 		return -1;
182797b045d6SJohannes Berg 	}
182897b045d6SJohannes Berg 
182997b045d6SJohannes Berg 	return 0;
183097b045d6SJohannes Berg }
183197b045d6SJohannes Berg 
1832bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1833bb42f2d1SToke Høiland-Jørgensen {
1834bb42f2d1SToke Høiland-Jørgensen 	int r = invoke_tx_handlers_early(tx);
1835bb42f2d1SToke Høiland-Jørgensen 
1836bb42f2d1SToke Høiland-Jørgensen 	if (r)
1837bb42f2d1SToke Høiland-Jørgensen 		return r;
1838bb42f2d1SToke Høiland-Jørgensen 	return invoke_tx_handlers_late(tx);
1839bb42f2d1SToke Høiland-Jørgensen }
1840bb42f2d1SToke Høiland-Jørgensen 
184106be6b14SFelix Fietkau bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
184206be6b14SFelix Fietkau 			      struct ieee80211_vif *vif, struct sk_buff *skb,
184306be6b14SFelix Fietkau 			      int band, struct ieee80211_sta **sta)
184406be6b14SFelix Fietkau {
184506be6b14SFelix Fietkau 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
184606be6b14SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
184706be6b14SFelix Fietkau 	struct ieee80211_tx_data tx;
184888724a81SJohannes Berg 	struct sk_buff *skb2;
184906be6b14SFelix Fietkau 
18507c10770fSJohannes Berg 	if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
185106be6b14SFelix Fietkau 		return false;
185206be6b14SFelix Fietkau 
185306be6b14SFelix Fietkau 	info->band = band;
185406be6b14SFelix Fietkau 	info->control.vif = vif;
185506be6b14SFelix Fietkau 	info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)];
185606be6b14SFelix Fietkau 
185706be6b14SFelix Fietkau 	if (invoke_tx_handlers(&tx))
185806be6b14SFelix Fietkau 		return false;
185906be6b14SFelix Fietkau 
186006be6b14SFelix Fietkau 	if (sta) {
186106be6b14SFelix Fietkau 		if (tx.sta)
186206be6b14SFelix Fietkau 			*sta = &tx.sta->sta;
186306be6b14SFelix Fietkau 		else
186406be6b14SFelix Fietkau 			*sta = NULL;
186506be6b14SFelix Fietkau 	}
186606be6b14SFelix Fietkau 
186788724a81SJohannes Berg 	/* this function isn't suitable for fragmented data frames */
186888724a81SJohannes Berg 	skb2 = __skb_dequeue(&tx.skbs);
186988724a81SJohannes Berg 	if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) {
187088724a81SJohannes Berg 		ieee80211_free_txskb(hw, skb2);
187188724a81SJohannes Berg 		ieee80211_purge_tx_queue(hw, &tx.skbs);
187288724a81SJohannes Berg 		return false;
187388724a81SJohannes Berg 	}
187488724a81SJohannes Berg 
187506be6b14SFelix Fietkau 	return true;
187606be6b14SFelix Fietkau }
187706be6b14SFelix Fietkau EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
187806be6b14SFelix Fietkau 
18797bb45683SJohannes Berg /*
18807bb45683SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead.
18817bb45683SJohannes Berg  */
18827bb45683SJohannes Berg static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
18837c10770fSJohannes Berg 			 struct sta_info *sta, struct sk_buff *skb,
188408aca29aSMathy Vanhoef 			 bool txpending)
1885e2ebc74dSJohannes Berg {
18863b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
18875cf121c3SJohannes Berg 	struct ieee80211_tx_data tx;
188897b045d6SJohannes Berg 	ieee80211_tx_result res_prepare;
1889e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
18907bb45683SJohannes Berg 	bool result = true;
189174e4dbfdSJohannes Berg 	int led_len;
1892e2ebc74dSJohannes Berg 
1893e2ebc74dSJohannes Berg 	if (unlikely(skb->len < 10)) {
1894e2ebc74dSJohannes Berg 		dev_kfree_skb(skb);
18957bb45683SJohannes Berg 		return true;
1896e2ebc74dSJohannes Berg 	}
1897e2ebc74dSJohannes Berg 
189858d4185eSJohannes Berg 	/* initialises tx */
189974e4dbfdSJohannes Berg 	led_len = skb->len;
19007c10770fSJohannes Berg 	res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
1901e2ebc74dSJohannes Berg 
1902cd8ffc80SJohannes Berg 	if (unlikely(res_prepare == TX_DROP)) {
1903c3e7724bSFelix Fietkau 		ieee80211_free_txskb(&local->hw, skb);
190455de908aSJohannes Berg 		return true;
1905cd8ffc80SJohannes Berg 	} else if (unlikely(res_prepare == TX_QUEUED)) {
190655de908aSJohannes Berg 		return true;
1907e2ebc74dSJohannes Berg 	}
1908e2ebc74dSJohannes Berg 
19093a25a8c8SJohannes Berg 	/* set up hw_queue value early */
19103a25a8c8SJohannes Berg 	if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
191130686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
19123a25a8c8SJohannes Berg 		info->hw_queue =
19133a25a8c8SJohannes Berg 			sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
19143a25a8c8SJohannes Berg 
1915bb42f2d1SToke Høiland-Jørgensen 	if (invoke_tx_handlers_early(&tx))
19166eae4a6cSBob Copeland 		return true;
1917bb42f2d1SToke Høiland-Jørgensen 
1918bb42f2d1SToke Høiland-Jørgensen 	if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
1919bb42f2d1SToke Høiland-Jørgensen 		return true;
1920bb42f2d1SToke Høiland-Jørgensen 
1921bb42f2d1SToke Høiland-Jørgensen 	if (!invoke_tx_handlers_late(&tx))
192274e4dbfdSJohannes Berg 		result = __ieee80211_tx(local, &tx.skbs, led_len,
192374e4dbfdSJohannes Berg 					tx.sta, txpending);
192455de908aSJohannes Berg 
19257bb45683SJohannes Berg 	return result;
1926e2ebc74dSJohannes Berg }
1927e2ebc74dSJohannes Berg 
1928e2ebc74dSJohannes Berg /* device xmit handlers */
1929e2ebc74dSJohannes Berg 
193014f46c1eSJohannes Berg enum ieee80211_encrypt {
193114f46c1eSJohannes Berg 	ENCRYPT_NO,
193214f46c1eSJohannes Berg 	ENCRYPT_MGMT,
193314f46c1eSJohannes Berg 	ENCRYPT_DATA,
193414f46c1eSJohannes Berg };
193514f46c1eSJohannes Berg 
19363bff1865SYogesh Ashok Powar static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
193723c0752aSJohannes Berg 				struct sk_buff *skb,
193814f46c1eSJohannes Berg 				int head_need,
193914f46c1eSJohannes Berg 				enum ieee80211_encrypt encrypt)
194023c0752aSJohannes Berg {
19413bff1865SYogesh Ashok Powar 	struct ieee80211_local *local = sdata->local;
19429d0f50b8SFelix Fietkau 	bool enc_tailroom;
194323c0752aSJohannes Berg 	int tail_need = 0;
194423c0752aSJohannes Berg 
194514f46c1eSJohannes Berg 	enc_tailroom = encrypt == ENCRYPT_MGMT ||
194614f46c1eSJohannes Berg 		       (encrypt == ENCRYPT_DATA &&
194714f46c1eSJohannes Berg 			sdata->crypto_tx_tailroom_needed_cnt);
19489d0f50b8SFelix Fietkau 
19499d0f50b8SFelix Fietkau 	if (enc_tailroom) {
195023c0752aSJohannes Berg 		tail_need = IEEE80211_ENCRYPT_TAILROOM;
195123c0752aSJohannes Berg 		tail_need -= skb_tailroom(skb);
195223c0752aSJohannes Berg 		tail_need = max_t(int, tail_need, 0);
195323c0752aSJohannes Berg 	}
195423c0752aSJohannes Berg 
1955c70f59a2SIdo Yariv 	if (skb_cloned(skb) &&
195630686bf7SJohannes Berg 	    (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
19579d0f50b8SFelix Fietkau 	     !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
195823c0752aSJohannes Berg 		I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
19594cd06a34SFelix Fietkau 	else if (head_need || tail_need)
196023c0752aSJohannes Berg 		I802_DEBUG_INC(local->tx_expand_skb_head);
19614cd06a34SFelix Fietkau 	else
19624cd06a34SFelix Fietkau 		return 0;
196323c0752aSJohannes Berg 
196423c0752aSJohannes Berg 	if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
19650fb9a9ecSJoe Perches 		wiphy_debug(local->hw.wiphy,
19660fb9a9ecSJoe Perches 			    "failed to reallocate TX buffer\n");
196723c0752aSJohannes Berg 		return -ENOMEM;
196823c0752aSJohannes Berg 	}
196923c0752aSJohannes Berg 
197023c0752aSJohannes Berg 	return 0;
197123c0752aSJohannes Berg }
197223c0752aSJohannes Berg 
19737c10770fSJohannes Berg void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
197408aca29aSMathy Vanhoef 		    struct sta_info *sta, struct sk_buff *skb)
1975e2ebc74dSJohannes Berg {
19763b8d81e0SJohannes Berg 	struct ieee80211_local *local = sdata->local;
1977e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
197814f46c1eSJohannes Berg 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1979e2ebc74dSJohannes Berg 	int headroom;
198014f46c1eSJohannes Berg 	enum ieee80211_encrypt encrypt;
1981e2ebc74dSJohannes Berg 
198214f46c1eSJohannes Berg 	if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)
198314f46c1eSJohannes Berg 		encrypt = ENCRYPT_NO;
198414f46c1eSJohannes Berg 	else if (ieee80211_is_mgmt(hdr->frame_control))
198514f46c1eSJohannes Berg 		encrypt = ENCRYPT_MGMT;
198614f46c1eSJohannes Berg 	else
198714f46c1eSJohannes Berg 		encrypt = ENCRYPT_DATA;
198823c0752aSJohannes Berg 
19893b8d81e0SJohannes Berg 	headroom = local->tx_headroom;
199014f46c1eSJohannes Berg 	if (encrypt != ENCRYPT_NO)
19912475b1ccSMax Stepanov 		headroom += sdata->encrypt_headroom;
199223c0752aSJohannes Berg 	headroom -= skb_headroom(skb);
199323c0752aSJohannes Berg 	headroom = max_t(int, 0, headroom);
199423c0752aSJohannes Berg 
199514f46c1eSJohannes Berg 	if (ieee80211_skb_resize(sdata, skb, headroom, encrypt)) {
1996c3e7724bSFelix Fietkau 		ieee80211_free_txskb(&local->hw, skb);
19973b8d81e0SJohannes Berg 		return;
1998e2ebc74dSJohannes Berg 	}
1999e2ebc74dSJohannes Berg 
200014f46c1eSJohannes Berg 	/* reload after potential resize */
2001740c1aa3SSteve deRosier 	hdr = (struct ieee80211_hdr *) skb->data;
20025061b0c2SJohannes Berg 	info->control.vif = &sdata->vif;
2003cd8ffc80SJohannes Berg 
20043f52b7e3SMarco Porsch 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
20053f52b7e3SMarco Porsch 		if (ieee80211_is_data(hdr->frame_control) &&
20063f52b7e3SMarco Porsch 		    is_unicast_ether_addr(hdr->addr1)) {
2007bf7cd94dSJohannes Berg 			if (mesh_nexthop_resolve(sdata, skb))
20083f52b7e3SMarco Porsch 				return; /* skb queued: don't free */
20093f52b7e3SMarco Porsch 		} else {
20103f52b7e3SMarco Porsch 			ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
20113f52b7e3SMarco Porsch 		}
2012cca89496SJavier Cardona 	}
2013cca89496SJavier Cardona 
20142154c81cSJavier Cardona 	ieee80211_set_qos_hdr(sdata, skb);
201508aca29aSMathy Vanhoef 	ieee80211_tx(sdata, sta, skb, false);
2016e2ebc74dSJohannes Berg }
2017e2ebc74dSJohannes Berg 
2018bddc0c41SMathy Vanhoef static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
201973b9f03aSJohannes Berg {
202073b9f03aSJohannes Berg 	struct ieee80211_radiotap_header *rthdr =
202173b9f03aSJohannes Berg 		(struct ieee80211_radiotap_header *)skb->data;
202273b9f03aSJohannes Berg 
2023cb17ed29SMathy Vanhoef 	/* check for not even having the fixed radiotap header part */
2024cb17ed29SMathy Vanhoef 	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2025cb17ed29SMathy Vanhoef 		return false; /* too short to be possibly valid */
2026cb17ed29SMathy Vanhoef 
2027cb17ed29SMathy Vanhoef 	/* is it a header version we can trust to find length from? */
2028cb17ed29SMathy Vanhoef 	if (unlikely(rthdr->it_version))
2029cb17ed29SMathy Vanhoef 		return false; /* only version 0 is supported */
2030cb17ed29SMathy Vanhoef 
2031cb17ed29SMathy Vanhoef 	/* does the skb contain enough to deliver on the alleged length? */
2032cb17ed29SMathy Vanhoef 	if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data)))
2033cb17ed29SMathy Vanhoef 		return false; /* skb too short for claimed rt header extent */
2034cb17ed29SMathy Vanhoef 
2035bddc0c41SMathy Vanhoef 	return true;
2036bddc0c41SMathy Vanhoef }
2037bddc0c41SMathy Vanhoef 
2038bddc0c41SMathy Vanhoef bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
2039bddc0c41SMathy Vanhoef 				 struct net_device *dev)
2040bddc0c41SMathy Vanhoef {
2041bddc0c41SMathy Vanhoef 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2042bddc0c41SMathy Vanhoef 	struct ieee80211_radiotap_iterator iterator;
2043bddc0c41SMathy Vanhoef 	struct ieee80211_radiotap_header *rthdr =
2044bddc0c41SMathy Vanhoef 		(struct ieee80211_radiotap_header *) skb->data;
2045bddc0c41SMathy Vanhoef 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2046bddc0c41SMathy Vanhoef 	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
2047bddc0c41SMathy Vanhoef 						   NULL);
2048bddc0c41SMathy Vanhoef 	u16 txflags;
2049bddc0c41SMathy Vanhoef 	u16 rate = 0;
2050bddc0c41SMathy Vanhoef 	bool rate_found = false;
2051bddc0c41SMathy Vanhoef 	u8 rate_retries = 0;
2052bddc0c41SMathy Vanhoef 	u16 rate_flags = 0;
2053bddc0c41SMathy Vanhoef 	u8 mcs_known, mcs_flags, mcs_bw;
2054bddc0c41SMathy Vanhoef 	u16 vht_known;
2055bddc0c41SMathy Vanhoef 	u8 vht_mcs = 0, vht_nss = 0;
2056bddc0c41SMathy Vanhoef 	int i;
2057bddc0c41SMathy Vanhoef 
2058bddc0c41SMathy Vanhoef 	if (!ieee80211_validate_radiotap_len(skb))
2059bddc0c41SMathy Vanhoef 		return false;
2060bddc0c41SMathy Vanhoef 
206173b9f03aSJohannes Berg 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
206273b9f03aSJohannes Berg 		       IEEE80211_TX_CTL_DONTFRAG;
206373b9f03aSJohannes Berg 
206473b9f03aSJohannes Berg 	/*
206573b9f03aSJohannes Berg 	 * for every radiotap entry that is present
206673b9f03aSJohannes Berg 	 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
206773b9f03aSJohannes Berg 	 * entries present, or -EINVAL on error)
206873b9f03aSJohannes Berg 	 */
206973b9f03aSJohannes Berg 
207073b9f03aSJohannes Berg 	while (!ret) {
207173b9f03aSJohannes Berg 		ret = ieee80211_radiotap_iterator_next(&iterator);
207273b9f03aSJohannes Berg 
207373b9f03aSJohannes Berg 		if (ret)
207473b9f03aSJohannes Berg 			continue;
207573b9f03aSJohannes Berg 
207673b9f03aSJohannes Berg 		/* see if this argument is something we can use */
207773b9f03aSJohannes Berg 		switch (iterator.this_arg_index) {
207873b9f03aSJohannes Berg 		/*
207973b9f03aSJohannes Berg 		 * You must take care when dereferencing iterator.this_arg
208073b9f03aSJohannes Berg 		 * for multibyte types... the pointer is not aligned.  Use
208173b9f03aSJohannes Berg 		 * get_unaligned((type *)iterator.this_arg) to dereference
208273b9f03aSJohannes Berg 		 * iterator.this_arg for type "type" safely on all arches.
208373b9f03aSJohannes Berg 		*/
208473b9f03aSJohannes Berg 		case IEEE80211_RADIOTAP_FLAGS:
208573b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
208673b9f03aSJohannes Berg 				/*
208773b9f03aSJohannes Berg 				 * this indicates that the skb we have been
208873b9f03aSJohannes Berg 				 * handed has the 32-bit FCS CRC at the end...
208973b9f03aSJohannes Berg 				 * we should react to that by snipping it off
209073b9f03aSJohannes Berg 				 * because it will be recomputed and added
209173b9f03aSJohannes Berg 				 * on transmission
209273b9f03aSJohannes Berg 				 */
209373b9f03aSJohannes Berg 				if (skb->len < (iterator._max_length + FCS_LEN))
209473b9f03aSJohannes Berg 					return false;
209573b9f03aSJohannes Berg 
209673b9f03aSJohannes Berg 				skb_trim(skb, skb->len - FCS_LEN);
209773b9f03aSJohannes Berg 			}
209873b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
209973b9f03aSJohannes Berg 				info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
210073b9f03aSJohannes Berg 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
210173b9f03aSJohannes Berg 				info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
210273b9f03aSJohannes Berg 			break;
210373b9f03aSJohannes Berg 
210473b9f03aSJohannes Berg 		case IEEE80211_RADIOTAP_TX_FLAGS:
210573b9f03aSJohannes Berg 			txflags = get_unaligned_le16(iterator.this_arg);
210673b9f03aSJohannes Berg 			if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
210773b9f03aSJohannes Berg 				info->flags |= IEEE80211_TX_CTL_NO_ACK;
2108e02281e7SMathy Vanhoef 			if (txflags & IEEE80211_RADIOTAP_F_TX_NOSEQNO)
2109e02281e7SMathy Vanhoef 				info->control.flags |= IEEE80211_TX_CTRL_NO_SEQNO;
211030df8130SMathy Vanhoef 			if (txflags & IEEE80211_RADIOTAP_F_TX_ORDER)
211130df8130SMathy Vanhoef 				info->control.flags |=
211230df8130SMathy Vanhoef 					IEEE80211_TX_CTRL_DONT_REORDER;
211373b9f03aSJohannes Berg 			break;
211473b9f03aSJohannes Berg 
2115dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_RATE:
2116dfdfc2beSSven Eckelmann 			rate = *iterator.this_arg;
2117dfdfc2beSSven Eckelmann 			rate_flags = 0;
2118dfdfc2beSSven Eckelmann 			rate_found = true;
2119dfdfc2beSSven Eckelmann 			break;
2120dfdfc2beSSven Eckelmann 
2121dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_DATA_RETRIES:
2122dfdfc2beSSven Eckelmann 			rate_retries = *iterator.this_arg;
2123dfdfc2beSSven Eckelmann 			break;
2124dfdfc2beSSven Eckelmann 
2125dfdfc2beSSven Eckelmann 		case IEEE80211_RADIOTAP_MCS:
2126dfdfc2beSSven Eckelmann 			mcs_known = iterator.this_arg[0];
2127dfdfc2beSSven Eckelmann 			mcs_flags = iterator.this_arg[1];
2128dfdfc2beSSven Eckelmann 			if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
2129dfdfc2beSSven Eckelmann 				break;
2130dfdfc2beSSven Eckelmann 
2131dfdfc2beSSven Eckelmann 			rate_found = true;
2132dfdfc2beSSven Eckelmann 			rate = iterator.this_arg[2];
2133dfdfc2beSSven Eckelmann 			rate_flags = IEEE80211_TX_RC_MCS;
2134dfdfc2beSSven Eckelmann 
2135dfdfc2beSSven Eckelmann 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
2136dfdfc2beSSven Eckelmann 			    mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
2137dfdfc2beSSven Eckelmann 				rate_flags |= IEEE80211_TX_RC_SHORT_GI;
2138dfdfc2beSSven Eckelmann 
2139f66b60f6SSven Eckelmann 			mcs_bw = mcs_flags & IEEE80211_RADIOTAP_MCS_BW_MASK;
2140dfdfc2beSSven Eckelmann 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
2141f66b60f6SSven Eckelmann 			    mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40)
2142dfdfc2beSSven Eckelmann 				rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2143f1864e19SPhilipp Borgers 
2144f1864e19SPhilipp Borgers 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC &&
2145f1864e19SPhilipp Borgers 			    mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC)
2146f1864e19SPhilipp Borgers 				info->flags |= IEEE80211_TX_CTL_LDPC;
2147549fdd34SPhilipp Borgers 
2148549fdd34SPhilipp Borgers 			if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_STBC) {
2149549fdd34SPhilipp Borgers 				u8 stbc = u8_get_bits(mcs_flags,
2150549fdd34SPhilipp Borgers 						      IEEE80211_RADIOTAP_MCS_STBC_MASK);
2151549fdd34SPhilipp Borgers 
2152549fdd34SPhilipp Borgers 				info->flags |=
2153549fdd34SPhilipp Borgers 					u32_encode_bits(stbc,
2154549fdd34SPhilipp Borgers 							IEEE80211_TX_CTL_STBC);
2155549fdd34SPhilipp Borgers 			}
2156dfdfc2beSSven Eckelmann 			break;
2157dfdfc2beSSven Eckelmann 
2158646e76bbSLorenzo Bianconi 		case IEEE80211_RADIOTAP_VHT:
2159646e76bbSLorenzo Bianconi 			vht_known = get_unaligned_le16(iterator.this_arg);
2160646e76bbSLorenzo Bianconi 			rate_found = true;
2161646e76bbSLorenzo Bianconi 
2162646e76bbSLorenzo Bianconi 			rate_flags = IEEE80211_TX_RC_VHT_MCS;
2163646e76bbSLorenzo Bianconi 			if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) &&
2164646e76bbSLorenzo Bianconi 			    (iterator.this_arg[2] &
2165646e76bbSLorenzo Bianconi 			     IEEE80211_RADIOTAP_VHT_FLAG_SGI))
2166646e76bbSLorenzo Bianconi 				rate_flags |= IEEE80211_TX_RC_SHORT_GI;
2167646e76bbSLorenzo Bianconi 			if (vht_known &
2168646e76bbSLorenzo Bianconi 			    IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) {
2169646e76bbSLorenzo Bianconi 				if (iterator.this_arg[3] == 1)
2170646e76bbSLorenzo Bianconi 					rate_flags |=
2171646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_40_MHZ_WIDTH;
2172646e76bbSLorenzo Bianconi 				else if (iterator.this_arg[3] == 4)
2173646e76bbSLorenzo Bianconi 					rate_flags |=
2174646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_80_MHZ_WIDTH;
2175646e76bbSLorenzo Bianconi 				else if (iterator.this_arg[3] == 11)
2176646e76bbSLorenzo Bianconi 					rate_flags |=
2177646e76bbSLorenzo Bianconi 						IEEE80211_TX_RC_160_MHZ_WIDTH;
2178646e76bbSLorenzo Bianconi 			}
2179646e76bbSLorenzo Bianconi 
2180646e76bbSLorenzo Bianconi 			vht_mcs = iterator.this_arg[4] >> 4;
2181646e76bbSLorenzo Bianconi 			vht_nss = iterator.this_arg[4] & 0xF;
2182646e76bbSLorenzo Bianconi 			break;
2183646e76bbSLorenzo Bianconi 
218473b9f03aSJohannes Berg 		/*
218573b9f03aSJohannes Berg 		 * Please update the file
2186429ff87bSMauro Carvalho Chehab 		 * Documentation/networking/mac80211-injection.rst
218773b9f03aSJohannes Berg 		 * when parsing new fields here.
218873b9f03aSJohannes Berg 		 */
218973b9f03aSJohannes Berg 
219073b9f03aSJohannes Berg 		default:
219173b9f03aSJohannes Berg 			break;
219273b9f03aSJohannes Berg 		}
219373b9f03aSJohannes Berg 	}
219473b9f03aSJohannes Berg 
219573b9f03aSJohannes Berg 	if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
219673b9f03aSJohannes Berg 		return false;
219773b9f03aSJohannes Berg 
2198dfdfc2beSSven Eckelmann 	if (rate_found) {
2199bddc0c41SMathy Vanhoef 		struct ieee80211_supported_band *sband =
2200bddc0c41SMathy Vanhoef 			local->hw.wiphy->bands[info->band];
2201bddc0c41SMathy Vanhoef 
2202dfdfc2beSSven Eckelmann 		info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
2203dfdfc2beSSven Eckelmann 
2204dfdfc2beSSven Eckelmann 		for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
2205dfdfc2beSSven Eckelmann 			info->control.rates[i].idx = -1;
2206dfdfc2beSSven Eckelmann 			info->control.rates[i].flags = 0;
2207dfdfc2beSSven Eckelmann 			info->control.rates[i].count = 0;
2208dfdfc2beSSven Eckelmann 		}
2209dfdfc2beSSven Eckelmann 
2210dfdfc2beSSven Eckelmann 		if (rate_flags & IEEE80211_TX_RC_MCS) {
2211dfdfc2beSSven Eckelmann 			info->control.rates[0].idx = rate;
2212646e76bbSLorenzo Bianconi 		} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
2213646e76bbSLorenzo Bianconi 			ieee80211_rate_set_vht(info->control.rates, vht_mcs,
2214646e76bbSLorenzo Bianconi 					       vht_nss);
2215bddc0c41SMathy Vanhoef 		} else if (sband) {
2216dfdfc2beSSven Eckelmann 			for (i = 0; i < sband->n_bitrates; i++) {
2217dfdfc2beSSven Eckelmann 				if (rate * 5 != sband->bitrates[i].bitrate)
2218dfdfc2beSSven Eckelmann 					continue;
2219dfdfc2beSSven Eckelmann 
2220dfdfc2beSSven Eckelmann 				info->control.rates[0].idx = i;
2221dfdfc2beSSven Eckelmann 				break;
2222dfdfc2beSSven Eckelmann 			}
2223dfdfc2beSSven Eckelmann 		}
2224dfdfc2beSSven Eckelmann 
222507310a63SFelix Fietkau 		if (info->control.rates[0].idx < 0)
222607310a63SFelix Fietkau 			info->control.flags &= ~IEEE80211_TX_CTRL_RATE_INJECT;
222707310a63SFelix Fietkau 
2228dfdfc2beSSven Eckelmann 		info->control.rates[0].flags = rate_flags;
2229dfdfc2beSSven Eckelmann 		info->control.rates[0].count = min_t(u8, rate_retries + 1,
2230dfdfc2beSSven Eckelmann 						     local->hw.max_rate_tries);
2231dfdfc2beSSven Eckelmann 	}
2232dfdfc2beSSven Eckelmann 
223373b9f03aSJohannes Berg 	return true;
223473b9f03aSJohannes Berg }
223573b9f03aSJohannes Berg 
2236d0cf9c0dSStephen Hemminger netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
2237e2ebc74dSJohannes Berg 					 struct net_device *dev)
2238e2ebc74dSJohannes Berg {
2239e2ebc74dSJohannes Berg 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
224055de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
22413b8d81e0SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2242f75f5c6fSHelmut Schaa 	struct ieee80211_hdr *hdr;
22435d9cf4a5SJohannes Berg 	struct ieee80211_sub_if_data *tmp_sdata, *sdata;
2244b4932836SJanusz Dziedzic 	struct cfg80211_chan_def *chandef;
22459b8a74e3SAndy Green 	u16 len_rthdr;
22465d9cf4a5SJohannes Berg 	int hdrlen;
2247e2ebc74dSJohannes Berg 
2248cb17ed29SMathy Vanhoef 	memset(info, 0, sizeof(*info));
2249cb17ed29SMathy Vanhoef 	info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
2250cb17ed29SMathy Vanhoef 		      IEEE80211_TX_CTL_INJECTED;
22519b8a74e3SAndy Green 
2252bddc0c41SMathy Vanhoef 	/* Sanity-check the length of the radiotap header */
2253bddc0c41SMathy Vanhoef 	if (!ieee80211_validate_radiotap_len(skb))
2254cb17ed29SMathy Vanhoef 		goto fail;
22559b8a74e3SAndy Green 
2256cb17ed29SMathy Vanhoef 	/* we now know there is a radiotap header with a length we can use */
22579b8a74e3SAndy Green 	len_rthdr = ieee80211_get_radiotap_len(skb->data);
22589b8a74e3SAndy Green 
2259e2ebc74dSJohannes Berg 	/*
2260e2ebc74dSJohannes Berg 	 * fix up the pointers accounting for the radiotap
2261e2ebc74dSJohannes Berg 	 * header still being in there.  We are being given
2262e2ebc74dSJohannes Berg 	 * a precooked IEEE80211 header so no need for
2263e2ebc74dSJohannes Berg 	 * normal processing
2264e2ebc74dSJohannes Berg 	 */
22659b8a74e3SAndy Green 	skb_set_mac_header(skb, len_rthdr);
2266e2ebc74dSJohannes Berg 	/*
22679b8a74e3SAndy Green 	 * these are just fixed to the end of the rt area since we
22689b8a74e3SAndy Green 	 * don't have any better information and at this point, nobody cares
2269e2ebc74dSJohannes Berg 	 */
22709b8a74e3SAndy Green 	skb_set_network_header(skb, len_rthdr);
22719b8a74e3SAndy Green 	skb_set_transport_header(skb, len_rthdr);
2272e2ebc74dSJohannes Berg 
22735d9cf4a5SJohannes Berg 	if (skb->len < len_rthdr + 2)
22745d9cf4a5SJohannes Berg 		goto fail;
22755d9cf4a5SJohannes Berg 
22765d9cf4a5SJohannes Berg 	hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
22775d9cf4a5SJohannes Berg 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
22785d9cf4a5SJohannes Berg 
22795d9cf4a5SJohannes Berg 	if (skb->len < len_rthdr + hdrlen)
22805d9cf4a5SJohannes Berg 		goto fail;
22815d9cf4a5SJohannes Berg 
2282f75f5c6fSHelmut Schaa 	/*
2283f75f5c6fSHelmut Schaa 	 * Initialize skb->protocol if the injected frame is a data frame
2284f75f5c6fSHelmut Schaa 	 * carrying a rfc1042 header
2285f75f5c6fSHelmut Schaa 	 */
2286f75f5c6fSHelmut Schaa 	if (ieee80211_is_data(hdr->frame_control) &&
22875d9cf4a5SJohannes Berg 	    skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) {
22885d9cf4a5SJohannes Berg 		u8 *payload = (u8 *)hdr + hdrlen;
22895d9cf4a5SJohannes Berg 
2290b203ca39SJoe Perches 		if (ether_addr_equal(payload, rfc1042_header))
2291f75f5c6fSHelmut Schaa 			skb->protocol = cpu_to_be16((payload[6] << 8) |
2292f75f5c6fSHelmut Schaa 						    payload[7]);
2293f75f5c6fSHelmut Schaa 	}
2294f75f5c6fSHelmut Schaa 
22955d9cf4a5SJohannes Berg 	rcu_read_lock();
22965d9cf4a5SJohannes Berg 
22975d9cf4a5SJohannes Berg 	/*
22985d9cf4a5SJohannes Berg 	 * We process outgoing injected frames that have a local address
22995d9cf4a5SJohannes Berg 	 * we handle as though they are non-injected frames.
23005d9cf4a5SJohannes Berg 	 * This code here isn't entirely correct, the local MAC address
23015d9cf4a5SJohannes Berg 	 * isn't always enough to find the interface to use; for proper
230270d9c599SJohannes Berg 	 * VLAN support we have an nl80211-based mechanism.
2303b226a826SJohannes Berg 	 *
2304b226a826SJohannes Berg 	 * This is necessary, for example, for old hostapd versions that
2305b226a826SJohannes Berg 	 * don't use nl80211-based management TX/RX.
23065d9cf4a5SJohannes Berg 	 */
23075d9cf4a5SJohannes Berg 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
23085d9cf4a5SJohannes Berg 
23095d9cf4a5SJohannes Berg 	list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) {
23105d9cf4a5SJohannes Berg 		if (!ieee80211_sdata_running(tmp_sdata))
23115d9cf4a5SJohannes Berg 			continue;
23125d9cf4a5SJohannes Berg 		if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
231370d9c599SJohannes Berg 		    tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
23145d9cf4a5SJohannes Berg 			continue;
2315b203ca39SJoe Perches 		if (ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) {
23165d9cf4a5SJohannes Berg 			sdata = tmp_sdata;
23175d9cf4a5SJohannes Berg 			break;
23185d9cf4a5SJohannes Berg 		}
23195d9cf4a5SJohannes Berg 	}
23207351c6bdSJohannes Berg 
232155de908aSJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
232255de908aSJohannes Berg 	if (!chanctx_conf) {
232355de908aSJohannes Berg 		tmp_sdata = rcu_dereference(local->monitor_sdata);
232455de908aSJohannes Berg 		if (tmp_sdata)
232555de908aSJohannes Berg 			chanctx_conf =
232655de908aSJohannes Berg 				rcu_dereference(tmp_sdata->vif.chanctx_conf);
232755de908aSJohannes Berg 	}
232855de908aSJohannes Berg 
2329b4a7ff75SFelix Fietkau 	if (chanctx_conf)
2330b4932836SJanusz Dziedzic 		chandef = &chanctx_conf->def;
2331b4a7ff75SFelix Fietkau 	else if (!local->use_chanctx)
2332b4932836SJanusz Dziedzic 		chandef = &local->_oper_chandef;
2333b4a7ff75SFelix Fietkau 	else
2334b4a7ff75SFelix Fietkau 		goto fail_rcu;
233555de908aSJohannes Berg 
233655de908aSJohannes Berg 	/*
233755de908aSJohannes Berg 	 * Frame injection is not allowed if beaconing is not allowed
233855de908aSJohannes Berg 	 * or if we need radar detection. Beaconing is usually not allowed when
233955de908aSJohannes Berg 	 * the mode or operation (Adhoc, AP, Mesh) does not support DFS.
234055de908aSJohannes Berg 	 * Passive scan is also used in world regulatory domains where
234155de908aSJohannes Berg 	 * your country is not known and as such it should be treated as
234255de908aSJohannes Berg 	 * NO TX unless the channel is explicitly allowed in which case
234355de908aSJohannes Berg 	 * your current regulatory domain would not have the passive scan
234455de908aSJohannes Berg 	 * flag.
234555de908aSJohannes Berg 	 *
234655de908aSJohannes Berg 	 * Since AP mode uses monitor interfaces to inject/TX management
234755de908aSJohannes Berg 	 * frames we can make AP mode the exception to this rule once it
234855de908aSJohannes Berg 	 * supports radar detection as its implementation can deal with
234955de908aSJohannes Berg 	 * radar detection by itself. We can do that later by adding a
235055de908aSJohannes Berg 	 * monitor flag interfaces used for AP support.
235155de908aSJohannes Berg 	 */
2352b4932836SJanusz Dziedzic 	if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
2353b4932836SJanusz Dziedzic 				     sdata->vif.type))
235455de908aSJohannes Berg 		goto fail_rcu;
235555de908aSJohannes Berg 
235673c4e195SJohannes Berg 	info->band = chandef->chan->band;
2357109843b0SLorenzo Bianconi 
235896a7109aSJohan Almbladh 	/* Initialize skb->priority according to frame type and TID class,
235996a7109aSJohan Almbladh 	 * with respect to the sub interface that the frame will actually
236096a7109aSJohan Almbladh 	 * be transmitted on. If the DONT_REORDER flag is set, the original
236196a7109aSJohan Almbladh 	 * skb-priority is preserved to assure frames injected with this
236296a7109aSJohan Almbladh 	 * flag are not reordered relative to each other.
236396a7109aSJohan Almbladh 	 */
236496a7109aSJohan Almbladh 	ieee80211_select_queue_80211(sdata, skb, hdr);
236596a7109aSJohan Almbladh 	skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority));
236696a7109aSJohan Almbladh 
2367bddc0c41SMathy Vanhoef 	/*
2368bddc0c41SMathy Vanhoef 	 * Process the radiotap header. This will now take into account the
2369bddc0c41SMathy Vanhoef 	 * selected chandef above to accurately set injection rates and
2370bddc0c41SMathy Vanhoef 	 * retransmissions.
2371bddc0c41SMathy Vanhoef 	 */
2372bddc0c41SMathy Vanhoef 	if (!ieee80211_parse_tx_radiotap(skb, dev))
2373bddc0c41SMathy Vanhoef 		goto fail_rcu;
2374bddc0c41SMathy Vanhoef 
2375cb17ed29SMathy Vanhoef 	/* remove the injection radiotap header */
2376cb17ed29SMathy Vanhoef 	skb_pull(skb, len_rthdr);
2377109843b0SLorenzo Bianconi 
237808aca29aSMathy Vanhoef 	ieee80211_xmit(sdata, NULL, skb);
23795d9cf4a5SJohannes Berg 	rcu_read_unlock();
23805d9cf4a5SJohannes Berg 
2381e2ebc74dSJohannes Berg 	return NETDEV_TX_OK;
23829b8a74e3SAndy Green 
238355de908aSJohannes Berg fail_rcu:
238455de908aSJohannes Berg 	rcu_read_unlock();
23859b8a74e3SAndy Green fail:
23869b8a74e3SAndy Green 	dev_kfree_skb(skb);
23879b8a74e3SAndy Green 	return NETDEV_TX_OK; /* meaning, we dealt with the skb */
2388e2ebc74dSJohannes Berg }
2389e2ebc74dSJohannes Berg 
239097ffe757SJohannes Berg static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
2391ad38bfc9SMatti Gottlieb {
239297ffe757SJohannes Berg 	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
2393ad38bfc9SMatti Gottlieb 
239497ffe757SJohannes Berg 	return ethertype == ETH_P_TDLS &&
239597ffe757SJohannes Berg 	       skb->len > 14 &&
239697ffe757SJohannes Berg 	       skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
239797ffe757SJohannes Berg }
239897ffe757SJohannes Berg 
239950ff477aSJohn Crispin int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
240097ffe757SJohannes Berg 			    struct sk_buff *skb,
240197ffe757SJohannes Berg 			    struct sta_info **sta_out)
240297ffe757SJohannes Berg {
240397ffe757SJohannes Berg 	struct sta_info *sta;
240497ffe757SJohannes Berg 
240597ffe757SJohannes Berg 	switch (sdata->vif.type) {
240697ffe757SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
240797ffe757SJohannes Berg 		sta = rcu_dereference(sdata->u.vlan.sta);
240897ffe757SJohannes Berg 		if (sta) {
240997ffe757SJohannes Berg 			*sta_out = sta;
241097ffe757SJohannes Berg 			return 0;
241197ffe757SJohannes Berg 		} else if (sdata->wdev.use_4addr) {
241297ffe757SJohannes Berg 			return -ENOLINK;
241397ffe757SJohannes Berg 		}
2414fc0561dcSGustavo A. R. Silva 		fallthrough;
241597ffe757SJohannes Berg 	case NL80211_IFTYPE_AP:
241697ffe757SJohannes Berg 	case NL80211_IFTYPE_OCB:
241797ffe757SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
241897ffe757SJohannes Berg 		if (is_multicast_ether_addr(skb->data)) {
241997ffe757SJohannes Berg 			*sta_out = ERR_PTR(-ENOENT);
242097ffe757SJohannes Berg 			return 0;
242197ffe757SJohannes Berg 		}
242297ffe757SJohannes Berg 		sta = sta_info_get_bss(sdata, skb->data);
242397ffe757SJohannes Berg 		break;
242497ffe757SJohannes Berg #ifdef CONFIG_MAC80211_MESH
242597ffe757SJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
242697ffe757SJohannes Berg 		/* determined much later */
242797ffe757SJohannes Berg 		*sta_out = NULL;
242897ffe757SJohannes Berg 		return 0;
242997ffe757SJohannes Berg #endif
243097ffe757SJohannes Berg 	case NL80211_IFTYPE_STATION:
243197ffe757SJohannes Berg 		if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
243297ffe757SJohannes Berg 			sta = sta_info_get(sdata, skb->data);
243311d62cafSJohannes Berg 			if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
243411d62cafSJohannes Berg 				if (test_sta_flag(sta,
243511d62cafSJohannes Berg 						  WLAN_STA_TDLS_PEER_AUTH)) {
243697ffe757SJohannes Berg 					*sta_out = sta;
243797ffe757SJohannes Berg 					return 0;
243897ffe757SJohannes Berg 				}
243997ffe757SJohannes Berg 
244097ffe757SJohannes Berg 				/*
244197ffe757SJohannes Berg 				 * TDLS link during setup - throw out frames to
244297ffe757SJohannes Berg 				 * peer. Allow TDLS-setup frames to unauthorized
244397ffe757SJohannes Berg 				 * peers for the special case of a link teardown
244497ffe757SJohannes Berg 				 * after a TDLS sta is removed due to being
244597ffe757SJohannes Berg 				 * unreachable.
244697ffe757SJohannes Berg 				 */
244711d62cafSJohannes Berg 				if (!ieee80211_is_tdls_setup(skb))
244897ffe757SJohannes Berg 					return -EINVAL;
244997ffe757SJohannes Berg 			}
245097ffe757SJohannes Berg 
245197ffe757SJohannes Berg 		}
245297ffe757SJohannes Berg 
245397ffe757SJohannes Berg 		sta = sta_info_get(sdata, sdata->u.mgd.bssid);
245497ffe757SJohannes Berg 		if (!sta)
245597ffe757SJohannes Berg 			return -ENOLINK;
245697ffe757SJohannes Berg 		break;
245797ffe757SJohannes Berg 	default:
245897ffe757SJohannes Berg 		return -EINVAL;
245997ffe757SJohannes Berg 	}
246097ffe757SJohannes Berg 
246197ffe757SJohannes Berg 	*sta_out = sta ?: ERR_PTR(-ENOENT);
246297ffe757SJohannes Berg 	return 0;
2463ad38bfc9SMatti Gottlieb }
2464ad38bfc9SMatti Gottlieb 
2465a7528198SMarkus Theil static u16 ieee80211_store_ack_skb(struct ieee80211_local *local,
24665d8983c8SJohn Crispin 				   struct sk_buff *skb,
2467a7528198SMarkus Theil 				   u32 *info_flags,
2468a7528198SMarkus Theil 				   u64 *cookie)
24695d8983c8SJohn Crispin {
2470a7528198SMarkus Theil 	struct sk_buff *ack_skb;
24715d8983c8SJohn Crispin 	u16 info_id = 0;
24725d8983c8SJohn Crispin 
2473a7528198SMarkus Theil 	if (skb->sk)
2474a7528198SMarkus Theil 		ack_skb = skb_clone_sk(skb);
2475a7528198SMarkus Theil 	else
2476a7528198SMarkus Theil 		ack_skb = skb_clone(skb, GFP_ATOMIC);
2477a7528198SMarkus Theil 
24785d8983c8SJohn Crispin 	if (ack_skb) {
24795d8983c8SJohn Crispin 		unsigned long flags;
24805d8983c8SJohn Crispin 		int id;
24815d8983c8SJohn Crispin 
24825d8983c8SJohn Crispin 		spin_lock_irqsave(&local->ack_status_lock, flags);
24835d8983c8SJohn Crispin 		id = idr_alloc(&local->ack_status_frames, ack_skb,
2484f2b18bacSJohannes Berg 			       1, 0x2000, GFP_ATOMIC);
24855d8983c8SJohn Crispin 		spin_unlock_irqrestore(&local->ack_status_lock, flags);
24865d8983c8SJohn Crispin 
24875d8983c8SJohn Crispin 		if (id >= 0) {
24885d8983c8SJohn Crispin 			info_id = id;
24895d8983c8SJohn Crispin 			*info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
2490a7528198SMarkus Theil 			if (cookie) {
2491a7528198SMarkus Theil 				*cookie = ieee80211_mgmt_tx_cookie(local);
2492a7528198SMarkus Theil 				IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie;
2493a7528198SMarkus Theil 			}
24945d8983c8SJohn Crispin 		} else {
24955d8983c8SJohn Crispin 			kfree_skb(ack_skb);
24965d8983c8SJohn Crispin 		}
24975d8983c8SJohn Crispin 	}
24985d8983c8SJohn Crispin 
24995d8983c8SJohn Crispin 	return info_id;
25005d8983c8SJohn Crispin }
25015d8983c8SJohn Crispin 
2502e2ebc74dSJohannes Berg /**
25034c9451edSJohannes Berg  * ieee80211_build_hdr - build 802.11 header in the given frame
25044c9451edSJohannes Berg  * @sdata: virtual interface to build the header for
25054c9451edSJohannes Berg  * @skb: the skb to build the header in
250624d342c5SLiad Kaufman  * @info_flags: skb flags to set
2507f0daf54fSJohannes Berg  * @sta: the station pointer
250806016772SRajkumar Manoharan  * @ctrl_flags: info control flags to set
2509f0daf54fSJohannes Berg  * @cookie: cookie pointer to fill (if not %NULL)
2510e2ebc74dSJohannes Berg  *
25114c9451edSJohannes Berg  * This function takes the skb with 802.3 header and reformats the header to
25124c9451edSJohannes Berg  * the appropriate IEEE 802.11 header based on which interface the packet is
25134c9451edSJohannes Berg  * being transmitted on.
2514e2ebc74dSJohannes Berg  *
25154c9451edSJohannes Berg  * Note that this function also takes care of the TX status request and
25164c9451edSJohannes Berg  * potential unsharing of the SKB - this needs to be interleaved with the
25174c9451edSJohannes Berg  * header building.
25184c9451edSJohannes Berg  *
25194c9451edSJohannes Berg  * The function requires the read-side RCU lock held
25204c9451edSJohannes Berg  *
25214c9451edSJohannes Berg  * Returns: the (possibly reallocated) skb or an ERR_PTR() code
2522e2ebc74dSJohannes Berg  */
25234c9451edSJohannes Berg static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
25247c10770fSJohannes Berg 					   struct sk_buff *skb, u32 info_flags,
2525a7528198SMarkus Theil 					   struct sta_info *sta, u32 ctrl_flags,
2526a7528198SMarkus Theil 					   u64 *cookie)
2527e2ebc74dSJohannes Berg {
2528133b8226SJohannes Berg 	struct ieee80211_local *local = sdata->local;
2529489ee919SFelix Fietkau 	struct ieee80211_tx_info *info;
2530dcf33963SJohannes Berg 	int head_need;
2531065e9605SHarvey Harrison 	u16 ethertype, hdrlen,  meshhdrlen = 0;
2532065e9605SHarvey Harrison 	__le16 fc;
2533e2ebc74dSJohannes Berg 	struct ieee80211_hdr hdr;
2534ff67bb86SWey-Yi Guy 	struct ieee80211s_hdr mesh_hdr __maybe_unused;
2535b8bacc18SChun-Yeow Yeoh 	struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
2536e2ebc74dSJohannes Berg 	const u8 *encaps_data;
2537e2ebc74dSJohannes Berg 	int encaps_len, skip_header_bytes;
253897ffe757SJohannes Berg 	bool wme_sta = false, authorized = false;
253997ffe757SJohannes Berg 	bool tdls_peer;
2540a729cff8SJohannes Berg 	bool multicast;
2541a729cff8SJohannes Berg 	u16 info_id = 0;
254255de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
254355de908aSJohannes Berg 	struct ieee80211_sub_if_data *ap_sdata;
254457fbcce3SJohannes Berg 	enum nl80211_band band;
25454c9451edSJohannes Berg 	int ret;
2546e2ebc74dSJohannes Berg 
254797ffe757SJohannes Berg 	if (IS_ERR(sta))
254897ffe757SJohannes Berg 		sta = NULL;
254997ffe757SJohannes Berg 
2550276d9e82SJulius Niedworok #ifdef CONFIG_MAC80211_DEBUGFS
2551276d9e82SJulius Niedworok 	if (local->force_tx_status)
2552276d9e82SJulius Niedworok 		info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
2553276d9e82SJulius Niedworok #endif
2554276d9e82SJulius Niedworok 
2555e2ebc74dSJohannes Berg 	/* convert Ethernet header to proper 802.11 header (based on
2556e2ebc74dSJohannes Berg 	 * operation mode) */
2557e2ebc74dSJohannes Berg 	ethertype = (skb->data[12] << 8) | skb->data[13];
2558065e9605SHarvey Harrison 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
2559e2ebc74dSJohannes Berg 
256051fb61e7SJohannes Berg 	switch (sdata->vif.type) {
256105c914feSJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
256297ffe757SJohannes Berg 		if (sdata->wdev.use_4addr) {
2563f14543eeSFelix Fietkau 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
2564f14543eeSFelix Fietkau 			/* RA TA DA SA */
2565f14543eeSFelix Fietkau 			memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
256647846c9bSJohannes Berg 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2567f14543eeSFelix Fietkau 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2568f14543eeSFelix Fietkau 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
2569f14543eeSFelix Fietkau 			hdrlen = 30;
2570c2c98fdeSJohannes Berg 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
2571a74a8c84SJohannes Berg 			wme_sta = sta->sta.wme;
2572f14543eeSFelix Fietkau 		}
257355de908aSJohannes Berg 		ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
257455de908aSJohannes Berg 					u.ap);
257555de908aSJohannes Berg 		chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
25764c9451edSJohannes Berg 		if (!chanctx_conf) {
25774c9451edSJohannes Berg 			ret = -ENOTCONN;
25784c9451edSJohannes Berg 			goto free;
25794c9451edSJohannes Berg 		}
25804bf88530SJohannes Berg 		band = chanctx_conf->def.chan->band;
258197ffe757SJohannes Berg 		if (sdata->wdev.use_4addr)
2582f14543eeSFelix Fietkau 			break;
2583fc0561dcSGustavo A. R. Silva 		fallthrough;
2584f14543eeSFelix Fietkau 	case NL80211_IFTYPE_AP:
2585fe80123dSArnd Bergmann 		if (sdata->vif.type == NL80211_IFTYPE_AP)
2586fe80123dSArnd Bergmann 			chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
25874c9451edSJohannes Berg 		if (!chanctx_conf) {
25884c9451edSJohannes Berg 			ret = -ENOTCONN;
25894c9451edSJohannes Berg 			goto free;
25904c9451edSJohannes Berg 		}
2591065e9605SHarvey Harrison 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
2592e2ebc74dSJohannes Berg 		/* DA BSSID SA */
2593e2ebc74dSJohannes Berg 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
259447846c9bSJohannes Berg 		memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2595e2ebc74dSJohannes Berg 		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
2596e2ebc74dSJohannes Berg 		hdrlen = 24;
25974bf88530SJohannes Berg 		band = chanctx_conf->def.chan->band;
2598cf966838SJohannes Berg 		break;
259933b64eb2SLuis Carlos Cobo #ifdef CONFIG_MAC80211_MESH
260005c914feSJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
2601b8bacc18SChun-Yeow Yeoh 		if (!is_multicast_ether_addr(skb->data)) {
2602163df6cfSChun-Yeow Yeoh 			struct sta_info *next_hop;
2603163df6cfSChun-Yeow Yeoh 			bool mpp_lookup = true;
2604163df6cfSChun-Yeow Yeoh 
2605bf7cd94dSJohannes Berg 			mpath = mesh_path_lookup(sdata, skb->data);
2606163df6cfSChun-Yeow Yeoh 			if (mpath) {
2607163df6cfSChun-Yeow Yeoh 				mpp_lookup = false;
2608163df6cfSChun-Yeow Yeoh 				next_hop = rcu_dereference(mpath->next_hop);
2609163df6cfSChun-Yeow Yeoh 				if (!next_hop ||
2610163df6cfSChun-Yeow Yeoh 				    !(mpath->flags & (MESH_PATH_ACTIVE |
2611163df6cfSChun-Yeow Yeoh 						      MESH_PATH_RESOLVING)))
2612163df6cfSChun-Yeow Yeoh 					mpp_lookup = true;
2613163df6cfSChun-Yeow Yeoh 			}
2614163df6cfSChun-Yeow Yeoh 
2615ab1c7906SHenning Rogge 			if (mpp_lookup) {
2616bf7cd94dSJohannes Berg 				mppath = mpp_path_lookup(sdata, skb->data);
2617ab1c7906SHenning Rogge 				if (mppath)
2618ab1c7906SHenning Rogge 					mppath->exp_time = jiffies;
2619ab1c7906SHenning Rogge 			}
2620163df6cfSChun-Yeow Yeoh 
2621163df6cfSChun-Yeow Yeoh 			if (mppath && mpath)
26222bdaf386SBob Copeland 				mesh_path_del(sdata, mpath->dst);
2623b8bacc18SChun-Yeow Yeoh 		}
262479617deeSYanBo 
2625f76b57b4SJoel A Fernandes 		/*
26269d52501bSJoel A Fernandes 		 * Use address extension if it is a packet from
26279d52501bSJoel A Fernandes 		 * another interface or if we know the destination
26289d52501bSJoel A Fernandes 		 * is being proxied by a portal (i.e. portal address
26299d52501bSJoel A Fernandes 		 * differs from proxied address)
2630f76b57b4SJoel A Fernandes 		 */
2631b203ca39SJoe Perches 		if (ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN) &&
2632b203ca39SJoe Perches 		    !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
26333c5772a5SJavier Cardona 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
26343c5772a5SJavier Cardona 					skb->data, skb->data + ETH_ALEN);
2635bf7cd94dSJohannes Berg 			meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr,
2636bf7cd94dSJohannes Berg 							       NULL, NULL);
263779617deeSYanBo 		} else {
263827f01124SThomas Pedersen 			/* DS -> MBSS (802.11-2012 13.11.3.3).
263927f01124SThomas Pedersen 			 * For unicast with unknown forwarding information,
264027f01124SThomas Pedersen 			 * destination might be in the MBSS or if that fails
264127f01124SThomas Pedersen 			 * forwarded to another mesh gate. In either case
264227f01124SThomas Pedersen 			 * resolution will be handled in ieee80211_xmit(), so
264327f01124SThomas Pedersen 			 * leave the original DA. This also works for mcast */
264427f01124SThomas Pedersen 			const u8 *mesh_da = skb->data;
264579617deeSYanBo 
264627f01124SThomas Pedersen 			if (mppath)
26473c5772a5SJavier Cardona 				mesh_da = mppath->mpp;
264827f01124SThomas Pedersen 			else if (mpath)
26497c41f315SChun-Yeow Yeoh 				mesh_da = mpath->dst;
265027f01124SThomas Pedersen 
26513c5772a5SJavier Cardona 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
265247846c9bSJohannes Berg 					mesh_da, sdata->vif.addr);
265327f01124SThomas Pedersen 			if (is_multicast_ether_addr(mesh_da))
265427f01124SThomas Pedersen 				/* DA TA mSA AE:SA */
2655bf7cd94dSJohannes Berg 				meshhdrlen = ieee80211_new_mesh_header(
2656bf7cd94dSJohannes Berg 						sdata, &mesh_hdr,
2657bf7cd94dSJohannes Berg 						skb->data + ETH_ALEN, NULL);
26583c5772a5SJavier Cardona 			else
265927f01124SThomas Pedersen 				/* RA TA mDA mSA AE:DA SA */
2660bf7cd94dSJohannes Berg 				meshhdrlen = ieee80211_new_mesh_header(
2661bf7cd94dSJohannes Berg 						sdata, &mesh_hdr, skb->data,
26623c5772a5SJavier Cardona 						skb->data + ETH_ALEN);
266379617deeSYanBo 
266479617deeSYanBo 		}
266555de908aSJohannes Berg 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
26664c9451edSJohannes Berg 		if (!chanctx_conf) {
26674c9451edSJohannes Berg 			ret = -ENOTCONN;
26684c9451edSJohannes Berg 			goto free;
26694c9451edSJohannes Berg 		}
26704bf88530SJohannes Berg 		band = chanctx_conf->def.chan->band;
26718828f81aSRajkumar Manoharan 
26728828f81aSRajkumar Manoharan 		/* For injected frames, fill RA right away as nexthop lookup
26738828f81aSRajkumar Manoharan 		 * will be skipped.
26748828f81aSRajkumar Manoharan 		 */
26758828f81aSRajkumar Manoharan 		if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) &&
26768828f81aSRajkumar Manoharan 		    is_zero_ether_addr(hdr.addr1))
26778828f81aSRajkumar Manoharan 			memcpy(hdr.addr1, skb->data, ETH_ALEN);
267833b64eb2SLuis Carlos Cobo 		break;
267933b64eb2SLuis Carlos Cobo #endif
268005c914feSJohannes Berg 	case NL80211_IFTYPE_STATION:
268197ffe757SJohannes Berg 		/* we already did checks when looking up the RA STA */
268297ffe757SJohannes Berg 		tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
2683941c93cdSArik Nemtsov 
268497ffe757SJohannes Berg 		if (tdls_peer) {
2685941c93cdSArik Nemtsov 			/* DA SA BSSID */
2686941c93cdSArik Nemtsov 			memcpy(hdr.addr1, skb->data, ETH_ALEN);
2687941c93cdSArik Nemtsov 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
2688941c93cdSArik Nemtsov 			memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN);
2689941c93cdSArik Nemtsov 			hdrlen = 24;
2690941c93cdSArik Nemtsov 		}  else if (sdata->u.mgd.use_4addr &&
2691a621fa4dSJohannes Berg 			    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
2692941c93cdSArik Nemtsov 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
2693941c93cdSArik Nemtsov 					  IEEE80211_FCTL_TODS);
2694f14543eeSFelix Fietkau 			/* RA TA DA SA */
2695941c93cdSArik Nemtsov 			memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
269647846c9bSJohannes Berg 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
2697f14543eeSFelix Fietkau 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2698f14543eeSFelix Fietkau 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
2699f14543eeSFelix Fietkau 			hdrlen = 30;
2700f14543eeSFelix Fietkau 		} else {
2701065e9605SHarvey Harrison 			fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
2702e2ebc74dSJohannes Berg 			/* BSSID SA DA */
2703941c93cdSArik Nemtsov 			memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
2704e2ebc74dSJohannes Berg 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
2705e2ebc74dSJohannes Berg 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
2706e2ebc74dSJohannes Berg 			hdrlen = 24;
2707f14543eeSFelix Fietkau 		}
270855de908aSJohannes Berg 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
27094c9451edSJohannes Berg 		if (!chanctx_conf) {
27104c9451edSJohannes Berg 			ret = -ENOTCONN;
27114c9451edSJohannes Berg 			goto free;
27124c9451edSJohannes Berg 		}
27134bf88530SJohannes Berg 		band = chanctx_conf->def.chan->band;
2714cf966838SJohannes Berg 		break;
2715239281f8SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
2716239281f8SRostislav Lisovy 		/* DA SA BSSID */
2717239281f8SRostislav Lisovy 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
2718239281f8SRostislav Lisovy 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
2719239281f8SRostislav Lisovy 		eth_broadcast_addr(hdr.addr3);
2720239281f8SRostislav Lisovy 		hdrlen = 24;
2721239281f8SRostislav Lisovy 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
27224c9451edSJohannes Berg 		if (!chanctx_conf) {
27234c9451edSJohannes Berg 			ret = -ENOTCONN;
27244c9451edSJohannes Berg 			goto free;
27254c9451edSJohannes Berg 		}
2726239281f8SRostislav Lisovy 		band = chanctx_conf->def.chan->band;
2727239281f8SRostislav Lisovy 		break;
272805c914feSJohannes Berg 	case NL80211_IFTYPE_ADHOC:
2729e2ebc74dSJohannes Berg 		/* DA SA BSSID */
2730e2ebc74dSJohannes Berg 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
2731e2ebc74dSJohannes Berg 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
273246900298SJohannes Berg 		memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
2733e2ebc74dSJohannes Berg 		hdrlen = 24;
273455de908aSJohannes Berg 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
27354c9451edSJohannes Berg 		if (!chanctx_conf) {
27364c9451edSJohannes Berg 			ret = -ENOTCONN;
27374c9451edSJohannes Berg 			goto free;
27384c9451edSJohannes Berg 		}
27394bf88530SJohannes Berg 		band = chanctx_conf->def.chan->band;
2740cf966838SJohannes Berg 		break;
2741cf966838SJohannes Berg 	default:
27424c9451edSJohannes Berg 		ret = -EINVAL;
27434c9451edSJohannes Berg 		goto free;
2744e2ebc74dSJohannes Berg 	}
2745e2ebc74dSJohannes Berg 
2746a729cff8SJohannes Berg 	multicast = is_multicast_ether_addr(hdr.addr1);
274797ffe757SJohannes Berg 
274897ffe757SJohannes Berg 	/* sta is always NULL for mesh */
2749c2c98fdeSJohannes Berg 	if (sta) {
2750c2c98fdeSJohannes Berg 		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
2751a74a8c84SJohannes Berg 		wme_sta = sta->sta.wme;
275297ffe757SJohannes Berg 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
27534777be41SJavier Cardona 		/* For mesh, the use of the QoS header is mandatory */
2754c2c98fdeSJohannes Berg 		wme_sta = true;
275597ffe757SJohannes Berg 	}
27564777be41SJavier Cardona 
2757527871d7SJohannes Berg 	/* receiver does QoS (which also means we do) use it */
2758527871d7SJohannes Berg 	if (wme_sta) {
2759065e9605SHarvey Harrison 		fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
2760e2ebc74dSJohannes Berg 		hdrlen += 2;
2761e2ebc74dSJohannes Berg 	}
2762ce3edf6dSJohannes Berg 
2763ce3edf6dSJohannes Berg 	/*
2764238814fdSJohannes Berg 	 * Drop unicast frames to unauthorised stations unless they are
2765238814fdSJohannes Berg 	 * EAPOL frames from the local station.
2766ce3edf6dSJohannes Berg 	 */
276755182e4aSJohannes Berg 	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
2768239281f8SRostislav Lisovy 		     (sdata->vif.type != NL80211_IFTYPE_OCB) &&
2769a6ececf4SSergey Ryazanov 		     !multicast && !authorized &&
277055182e4aSJohannes Berg 		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
2771b203ca39SJoe Perches 		      !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
2772ce3edf6dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2773bdcbd8e0SJohannes Berg 		net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
27744c9451edSJohannes Berg 				    sdata->name, hdr.addr1);
2775ce3edf6dSJohannes Berg #endif
2776ce3edf6dSJohannes Berg 
2777ce3edf6dSJohannes Berg 		I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
2778ce3edf6dSJohannes Berg 
27794c9451edSJohannes Berg 		ret = -EPERM;
27804c9451edSJohannes Berg 		goto free;
2781e2ebc74dSJohannes Berg 	}
2782e2ebc74dSJohannes Berg 
2783a7528198SMarkus Theil 	if (unlikely(!multicast && ((skb->sk &&
2784a7528198SMarkus Theil 		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) ||
2785a7528198SMarkus Theil 		     ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS)))
2786a7528198SMarkus Theil 		info_id = ieee80211_store_ack_skb(local, skb, &info_flags,
2787a7528198SMarkus Theil 						  cookie);
2788a729cff8SJohannes Berg 
27897e244707SHelmut Schaa 	/*
27907e244707SHelmut Schaa 	 * If the skb is shared we need to obtain our own copy.
27917e244707SHelmut Schaa 	 */
27927e244707SHelmut Schaa 	if (skb_shared(skb)) {
2793a729cff8SJohannes Berg 		struct sk_buff *tmp_skb = skb;
2794a729cff8SJohannes Berg 
2795a729cff8SJohannes Berg 		/* can't happen -- skb is a clone if info_id != 0 */
2796a729cff8SJohannes Berg 		WARN_ON(info_id);
2797a729cff8SJohannes Berg 
2798f8a0a781SFelix Fietkau 		skb = skb_clone(skb, GFP_ATOMIC);
27997e244707SHelmut Schaa 		kfree_skb(tmp_skb);
28007e244707SHelmut Schaa 
28014c9451edSJohannes Berg 		if (!skb) {
28024c9451edSJohannes Berg 			ret = -ENOMEM;
28034c9451edSJohannes Berg 			goto free;
28044c9451edSJohannes Berg 		}
28057e244707SHelmut Schaa 	}
28067e244707SHelmut Schaa 
2807065e9605SHarvey Harrison 	hdr.frame_control = fc;
2808e2ebc74dSJohannes Berg 	hdr.duration_id = 0;
2809e2ebc74dSJohannes Berg 	hdr.seq_ctrl = 0;
2810e2ebc74dSJohannes Berg 
2811e2ebc74dSJohannes Berg 	skip_header_bytes = ETH_HLEN;
2812e2ebc74dSJohannes Berg 	if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
2813e2ebc74dSJohannes Berg 		encaps_data = bridge_tunnel_header;
2814e2ebc74dSJohannes Berg 		encaps_len = sizeof(bridge_tunnel_header);
2815e2ebc74dSJohannes Berg 		skip_header_bytes -= 2;
2816e5c5d22eSSimon Horman 	} else if (ethertype >= ETH_P_802_3_MIN) {
2817e2ebc74dSJohannes Berg 		encaps_data = rfc1042_header;
2818e2ebc74dSJohannes Berg 		encaps_len = sizeof(rfc1042_header);
2819e2ebc74dSJohannes Berg 		skip_header_bytes -= 2;
2820e2ebc74dSJohannes Berg 	} else {
2821e2ebc74dSJohannes Berg 		encaps_data = NULL;
2822e2ebc74dSJohannes Berg 		encaps_len = 0;
2823e2ebc74dSJohannes Berg 	}
2824e2ebc74dSJohannes Berg 
2825e2ebc74dSJohannes Berg 	skb_pull(skb, skip_header_bytes);
282623c0752aSJohannes Berg 	head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
2827e2ebc74dSJohannes Berg 
282823c0752aSJohannes Berg 	/*
282923c0752aSJohannes Berg 	 * So we need to modify the skb header and hence need a copy of
283023c0752aSJohannes Berg 	 * that. The head_need variable above doesn't, so far, include
283123c0752aSJohannes Berg 	 * the needed header space that we don't need right away. If we
283223c0752aSJohannes Berg 	 * can, then we don't reallocate right now but only after the
283323c0752aSJohannes Berg 	 * frame arrives at the master device (if it does...)
283423c0752aSJohannes Berg 	 *
283523c0752aSJohannes Berg 	 * If we cannot, however, then we will reallocate to include all
283623c0752aSJohannes Berg 	 * the ever needed space. Also, if we need to reallocate it anyway,
283723c0752aSJohannes Berg 	 * make it big enough for everything we may ever need.
283823c0752aSJohannes Berg 	 */
2839e2ebc74dSJohannes Berg 
28403a5be7d4SDavid S. Miller 	if (head_need > 0 || skb_cloned(skb)) {
28412475b1ccSMax Stepanov 		head_need += sdata->encrypt_headroom;
284223c0752aSJohannes Berg 		head_need += local->tx_headroom;
284323c0752aSJohannes Berg 		head_need = max_t(int, 0, head_need);
284414f46c1eSJohannes Berg 		if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
2845c3e7724bSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
28461c963becSJohannes Berg 			skb = NULL;
28474c9451edSJohannes Berg 			return ERR_PTR(-ENOMEM);
2848c3e7724bSFelix Fietkau 		}
2849e2ebc74dSJohannes Berg 	}
2850e2ebc74dSJohannes Berg 
2851eae4430eSFelix Fietkau 	if (encaps_data)
2852e2ebc74dSJohannes Berg 		memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
2853c29b9b9bSJohannes Berg 
2854e4ab7eb0SYuri Ershov #ifdef CONFIG_MAC80211_MESH
2855eae4430eSFelix Fietkau 	if (meshhdrlen > 0)
285633b64eb2SLuis Carlos Cobo 		memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
2857e4ab7eb0SYuri Ershov #endif
285833b64eb2SLuis Carlos Cobo 
2859065e9605SHarvey Harrison 	if (ieee80211_is_data_qos(fc)) {
2860c29b9b9bSJohannes Berg 		__le16 *qos_control;
2861c29b9b9bSJohannes Berg 
2862d58ff351SJohannes Berg 		qos_control = skb_push(skb, 2);
2863c29b9b9bSJohannes Berg 		memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
2864c29b9b9bSJohannes Berg 		/*
2865c29b9b9bSJohannes Berg 		 * Maybe we could actually set some fields here, for now just
2866c29b9b9bSJohannes Berg 		 * initialise to zero to indicate no special operation.
2867c29b9b9bSJohannes Berg 		 */
2868c29b9b9bSJohannes Berg 		*qos_control = 0;
2869c29b9b9bSJohannes Berg 	} else
2870e2ebc74dSJohannes Berg 		memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
2871c29b9b9bSJohannes Berg 
2872d57a544dSZhang Shengju 	skb_reset_mac_header(skb);
2873e2ebc74dSJohannes Berg 
2874489ee919SFelix Fietkau 	info = IEEE80211_SKB_CB(skb);
28753b8d81e0SJohannes Berg 	memset(info, 0, sizeof(*info));
28763b8d81e0SJohannes Berg 
2877a729cff8SJohannes Berg 	info->flags = info_flags;
2878a729cff8SJohannes Berg 	info->ack_frame_id = info_id;
287973c4e195SJohannes Berg 	info->band = band;
288006016772SRajkumar Manoharan 	info->control.flags = ctrl_flags;
2881a729cff8SJohannes Berg 
28824c9451edSJohannes Berg 	return skb;
28834c9451edSJohannes Berg  free:
28844c9451edSJohannes Berg 	kfree_skb(skb);
28854c9451edSJohannes Berg 	return ERR_PTR(ret);
2886e2ebc74dSJohannes Berg }
2887e2ebc74dSJohannes Berg 
288817c18bf8SJohannes Berg /*
288917c18bf8SJohannes Berg  * fast-xmit overview
289017c18bf8SJohannes Berg  *
289117c18bf8SJohannes Berg  * The core idea of this fast-xmit is to remove per-packet checks by checking
289217c18bf8SJohannes Berg  * them out of band. ieee80211_check_fast_xmit() implements the out-of-band
289317c18bf8SJohannes Berg  * checks that are needed to get the sta->fast_tx pointer assigned, after which
289417c18bf8SJohannes Berg  * much less work can be done per packet. For example, fragmentation must be
289517c18bf8SJohannes Berg  * disabled or the fast_tx pointer will not be set. All the conditions are seen
289617c18bf8SJohannes Berg  * in the code here.
289717c18bf8SJohannes Berg  *
289817c18bf8SJohannes Berg  * Once assigned, the fast_tx data structure also caches the per-packet 802.11
289917c18bf8SJohannes Berg  * header and other data to aid packet processing in ieee80211_xmit_fast().
290017c18bf8SJohannes Berg  *
290117c18bf8SJohannes Berg  * The most difficult part of this is that when any of these assumptions
290217c18bf8SJohannes Berg  * change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(),
290317c18bf8SJohannes Berg  * ieee80211_check_fast_xmit() or friends) is required to reset the data,
290417c18bf8SJohannes Berg  * since the per-packet code no longer checks the conditions. This is reflected
290517c18bf8SJohannes Berg  * by the calls to these functions throughout the rest of the code, and must be
290617c18bf8SJohannes Berg  * maintained if any of the TX path checks change.
290717c18bf8SJohannes Berg  */
290817c18bf8SJohannes Berg 
290917c18bf8SJohannes Berg void ieee80211_check_fast_xmit(struct sta_info *sta)
291017c18bf8SJohannes Berg {
291117c18bf8SJohannes Berg 	struct ieee80211_fast_tx build = {}, *fast_tx = NULL, *old;
291217c18bf8SJohannes Berg 	struct ieee80211_local *local = sta->local;
291317c18bf8SJohannes Berg 	struct ieee80211_sub_if_data *sdata = sta->sdata;
291417c18bf8SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)build.hdr;
291517c18bf8SJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
291617c18bf8SJohannes Berg 	__le16 fc;
291717c18bf8SJohannes Berg 
291830686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
291917c18bf8SJohannes Berg 		return;
292017c18bf8SJohannes Berg 
292117c18bf8SJohannes Berg 	/* Locking here protects both the pointer itself, and against concurrent
292217c18bf8SJohannes Berg 	 * invocations winning data access races to, e.g., the key pointer that
292317c18bf8SJohannes Berg 	 * is used.
292417c18bf8SJohannes Berg 	 * Without it, the invocation of this function right after the key
292517c18bf8SJohannes Berg 	 * pointer changes wouldn't be sufficient, as another CPU could access
292617c18bf8SJohannes Berg 	 * the pointer, then stall, and then do the cache update after the CPU
292717c18bf8SJohannes Berg 	 * that invalidated the key.
292817c18bf8SJohannes Berg 	 * With the locking, such scenarios cannot happen as the check for the
292917c18bf8SJohannes Berg 	 * key and the fast-tx assignment are done atomically, so the CPU that
293017c18bf8SJohannes Berg 	 * modifies the key will either wait or other one will see the key
293117c18bf8SJohannes Berg 	 * cleared/changed already.
293217c18bf8SJohannes Berg 	 */
293317c18bf8SJohannes Berg 	spin_lock_bh(&sta->lock);
293430686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
293530686bf7SJohannes Berg 	    !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) &&
293617c18bf8SJohannes Berg 	    sdata->vif.type == NL80211_IFTYPE_STATION)
293717c18bf8SJohannes Berg 		goto out;
293817c18bf8SJohannes Berg 
293917c18bf8SJohannes Berg 	if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
294017c18bf8SJohannes Berg 		goto out;
294117c18bf8SJohannes Berg 
294217c18bf8SJohannes Berg 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
294317c18bf8SJohannes Berg 	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
2944f7418bc1SFelix Fietkau 	    test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
2945f7418bc1SFelix Fietkau 	    test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
294617c18bf8SJohannes Berg 		goto out;
294717c18bf8SJohannes Berg 
294817c18bf8SJohannes Berg 	if (sdata->noack_map)
294917c18bf8SJohannes Berg 		goto out;
295017c18bf8SJohannes Berg 
295117c18bf8SJohannes Berg 	/* fast-xmit doesn't handle fragmentation at all */
2952725b812cSJohannes Berg 	if (local->hw.wiphy->frag_threshold != (u32)-1 &&
2953f3fe4e93SSara Sharon 	    !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
295417c18bf8SJohannes Berg 		goto out;
295517c18bf8SJohannes Berg 
295617c18bf8SJohannes Berg 	rcu_read_lock();
295717c18bf8SJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
295817c18bf8SJohannes Berg 	if (!chanctx_conf) {
295917c18bf8SJohannes Berg 		rcu_read_unlock();
296017c18bf8SJohannes Berg 		goto out;
296117c18bf8SJohannes Berg 	}
296217c18bf8SJohannes Berg 	build.band = chanctx_conf->def.chan->band;
296317c18bf8SJohannes Berg 	rcu_read_unlock();
296417c18bf8SJohannes Berg 
296517c18bf8SJohannes Berg 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
296617c18bf8SJohannes Berg 
296717c18bf8SJohannes Berg 	switch (sdata->vif.type) {
29683ffd8840SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
29693ffd8840SJohannes Berg 		/* DA SA BSSID */
29703ffd8840SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr1);
29713ffd8840SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
29723ffd8840SJohannes Berg 		memcpy(hdr->addr3, sdata->u.ibss.bssid, ETH_ALEN);
29733ffd8840SJohannes Berg 		build.hdr_len = 24;
29743ffd8840SJohannes Berg 		break;
297517c18bf8SJohannes Berg 	case NL80211_IFTYPE_STATION:
297617c18bf8SJohannes Berg 		if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
297717c18bf8SJohannes Berg 			/* DA SA BSSID */
297817c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr1);
297917c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
298017c18bf8SJohannes Berg 			memcpy(hdr->addr3, sdata->u.mgd.bssid, ETH_ALEN);
298117c18bf8SJohannes Berg 			build.hdr_len = 24;
298217c18bf8SJohannes Berg 			break;
298317c18bf8SJohannes Berg 		}
298417c18bf8SJohannes Berg 
298517c18bf8SJohannes Berg 		if (sdata->u.mgd.use_4addr) {
298617c18bf8SJohannes Berg 			/* non-regular ethertype cannot use the fastpath */
298717c18bf8SJohannes Berg 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
298817c18bf8SJohannes Berg 					  IEEE80211_FCTL_TODS);
298917c18bf8SJohannes Berg 			/* RA TA DA SA */
299017c18bf8SJohannes Berg 			memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN);
299117c18bf8SJohannes Berg 			memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
299217c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr3);
299317c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
299417c18bf8SJohannes Berg 			build.hdr_len = 30;
299517c18bf8SJohannes Berg 			break;
299617c18bf8SJohannes Berg 		}
299717c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
299817c18bf8SJohannes Berg 		/* BSSID SA DA */
299917c18bf8SJohannes Berg 		memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN);
300017c18bf8SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr3);
300117c18bf8SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
300217c18bf8SJohannes Berg 		build.hdr_len = 24;
300317c18bf8SJohannes Berg 		break;
300417c18bf8SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
300517c18bf8SJohannes Berg 		if (sdata->wdev.use_4addr) {
300617c18bf8SJohannes Berg 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
300717c18bf8SJohannes Berg 					  IEEE80211_FCTL_TODS);
300817c18bf8SJohannes Berg 			/* RA TA DA SA */
300917c18bf8SJohannes Berg 			memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
301017c18bf8SJohannes Berg 			memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
301117c18bf8SJohannes Berg 			build.da_offs = offsetof(struct ieee80211_hdr, addr3);
301217c18bf8SJohannes Berg 			build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
301317c18bf8SJohannes Berg 			build.hdr_len = 30;
301417c18bf8SJohannes Berg 			break;
301517c18bf8SJohannes Berg 		}
3016fc0561dcSGustavo A. R. Silva 		fallthrough;
301717c18bf8SJohannes Berg 	case NL80211_IFTYPE_AP:
301817c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
301917c18bf8SJohannes Berg 		/* DA BSSID SA */
302017c18bf8SJohannes Berg 		build.da_offs = offsetof(struct ieee80211_hdr, addr1);
302117c18bf8SJohannes Berg 		memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
302217c18bf8SJohannes Berg 		build.sa_offs = offsetof(struct ieee80211_hdr, addr3);
302317c18bf8SJohannes Berg 		build.hdr_len = 24;
302417c18bf8SJohannes Berg 		break;
302517c18bf8SJohannes Berg 	default:
302617c18bf8SJohannes Berg 		/* not handled on fast-xmit */
302717c18bf8SJohannes Berg 		goto out;
302817c18bf8SJohannes Berg 	}
302917c18bf8SJohannes Berg 
303017c18bf8SJohannes Berg 	if (sta->sta.wme) {
303117c18bf8SJohannes Berg 		build.hdr_len += 2;
303217c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
303317c18bf8SJohannes Berg 	}
303417c18bf8SJohannes Berg 
303517c18bf8SJohannes Berg 	/* We store the key here so there's no point in using rcu_dereference()
303617c18bf8SJohannes Berg 	 * but that's fine because the code that changes the pointers will call
303717c18bf8SJohannes Berg 	 * this function after doing so. For a single CPU that would be enough,
303817c18bf8SJohannes Berg 	 * for multiple see the comment above.
303917c18bf8SJohannes Berg 	 */
304017c18bf8SJohannes Berg 	build.key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
304117c18bf8SJohannes Berg 	if (!build.key)
304217c18bf8SJohannes Berg 		build.key = rcu_access_pointer(sdata->default_unicast_key);
304317c18bf8SJohannes Berg 	if (build.key) {
3044e495c247SJohannes Berg 		bool gen_iv, iv_spc, mmic;
304517c18bf8SJohannes Berg 
304617c18bf8SJohannes Berg 		gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
304717c18bf8SJohannes Berg 		iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
30489de18d81SDavid Spinadel 		mmic = build.key->conf.flags &
30499de18d81SDavid Spinadel 			(IEEE80211_KEY_FLAG_GENERATE_MMIC |
30509de18d81SDavid Spinadel 			 IEEE80211_KEY_FLAG_PUT_MIC_SPACE);
305117c18bf8SJohannes Berg 
305217c18bf8SJohannes Berg 		/* don't handle software crypto */
305317c18bf8SJohannes Berg 		if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
305417c18bf8SJohannes Berg 			goto out;
305517c18bf8SJohannes Berg 
305662872a9bSAlexander Wetzel 		/* Key is being removed */
305762872a9bSAlexander Wetzel 		if (build.key->flags & KEY_FLAG_TAINTED)
305862872a9bSAlexander Wetzel 			goto out;
305962872a9bSAlexander Wetzel 
306017c18bf8SJohannes Berg 		switch (build.key->conf.cipher) {
306117c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP:
306217c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP_256:
306396fc6efbSAlexander Wetzel 			if (gen_iv)
306417c18bf8SJohannes Berg 				build.pn_offs = build.hdr_len;
306517c18bf8SJohannes Berg 			if (gen_iv || iv_spc)
306617c18bf8SJohannes Berg 				build.hdr_len += IEEE80211_CCMP_HDR_LEN;
306717c18bf8SJohannes Berg 			break;
306817c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_GCMP:
306917c18bf8SJohannes Berg 		case WLAN_CIPHER_SUITE_GCMP_256:
307096fc6efbSAlexander Wetzel 			if (gen_iv)
307117c18bf8SJohannes Berg 				build.pn_offs = build.hdr_len;
307217c18bf8SJohannes Berg 			if (gen_iv || iv_spc)
307317c18bf8SJohannes Berg 				build.hdr_len += IEEE80211_GCMP_HDR_LEN;
307417c18bf8SJohannes Berg 			break;
3075e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_TKIP:
3076e495c247SJohannes Berg 			/* cannot handle MMIC or IV generation in xmit-fast */
3077e495c247SJohannes Berg 			if (mmic || gen_iv)
307817c18bf8SJohannes Berg 				goto out;
3079e495c247SJohannes Berg 			if (iv_spc)
3080e495c247SJohannes Berg 				build.hdr_len += IEEE80211_TKIP_IV_LEN;
3081e495c247SJohannes Berg 			break;
3082e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP40:
3083e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP104:
3084e495c247SJohannes Berg 			/* cannot handle IV generation in fast-xmit */
3085e495c247SJohannes Berg 			if (gen_iv)
3086e495c247SJohannes Berg 				goto out;
3087e495c247SJohannes Berg 			if (iv_spc)
3088e495c247SJohannes Berg 				build.hdr_len += IEEE80211_WEP_IV_LEN;
3089e495c247SJohannes Berg 			break;
3090e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_AES_CMAC:
3091e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3092e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
3093e495c247SJohannes Berg 		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
3094e495c247SJohannes Berg 			WARN(1,
3095e495c247SJohannes Berg 			     "management cipher suite 0x%x enabled for data\n",
3096e495c247SJohannes Berg 			     build.key->conf.cipher);
3097e495c247SJohannes Berg 			goto out;
3098e495c247SJohannes Berg 		default:
3099e495c247SJohannes Berg 			/* we don't know how to generate IVs for this at all */
3100e495c247SJohannes Berg 			if (WARN_ON(gen_iv))
3101e495c247SJohannes Berg 				goto out;
3102e495c247SJohannes Berg 			/* pure hardware keys are OK, of course */
3103e495c247SJohannes Berg 			if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME))
3104e495c247SJohannes Berg 				break;
3105e495c247SJohannes Berg 			/* cipher scheme might require space allocation */
3106e495c247SJohannes Berg 			if (iv_spc &&
3107e495c247SJohannes Berg 			    build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV)
3108e495c247SJohannes Berg 				goto out;
3109e495c247SJohannes Berg 			if (iv_spc)
3110e495c247SJohannes Berg 				build.hdr_len += build.key->conf.iv_len;
311117c18bf8SJohannes Berg 		}
311217c18bf8SJohannes Berg 
311317c18bf8SJohannes Berg 		fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
311417c18bf8SJohannes Berg 	}
311517c18bf8SJohannes Berg 
311617c18bf8SJohannes Berg 	hdr->frame_control = fc;
311717c18bf8SJohannes Berg 
311817c18bf8SJohannes Berg 	memcpy(build.hdr + build.hdr_len,
311917c18bf8SJohannes Berg 	       rfc1042_header,  sizeof(rfc1042_header));
312017c18bf8SJohannes Berg 	build.hdr_len += sizeof(rfc1042_header);
312117c18bf8SJohannes Berg 
312217c18bf8SJohannes Berg 	fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC);
312317c18bf8SJohannes Berg 	/* if the kmemdup fails, continue w/o fast_tx */
312417c18bf8SJohannes Berg 	if (!fast_tx)
312517c18bf8SJohannes Berg 		goto out;
312617c18bf8SJohannes Berg 
312717c18bf8SJohannes Berg  out:
312817c18bf8SJohannes Berg 	/* we might have raced against another call to this function */
312917c18bf8SJohannes Berg 	old = rcu_dereference_protected(sta->fast_tx,
313017c18bf8SJohannes Berg 					lockdep_is_held(&sta->lock));
313117c18bf8SJohannes Berg 	rcu_assign_pointer(sta->fast_tx, fast_tx);
313217c18bf8SJohannes Berg 	if (old)
313317c18bf8SJohannes Berg 		kfree_rcu(old, rcu_head);
313417c18bf8SJohannes Berg 	spin_unlock_bh(&sta->lock);
313517c18bf8SJohannes Berg }
313617c18bf8SJohannes Berg 
313717c18bf8SJohannes Berg void ieee80211_check_fast_xmit_all(struct ieee80211_local *local)
313817c18bf8SJohannes Berg {
313917c18bf8SJohannes Berg 	struct sta_info *sta;
314017c18bf8SJohannes Berg 
314117c18bf8SJohannes Berg 	rcu_read_lock();
314217c18bf8SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list)
314317c18bf8SJohannes Berg 		ieee80211_check_fast_xmit(sta);
314417c18bf8SJohannes Berg 	rcu_read_unlock();
314517c18bf8SJohannes Berg }
314617c18bf8SJohannes Berg 
314717c18bf8SJohannes Berg void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata)
314817c18bf8SJohannes Berg {
314917c18bf8SJohannes Berg 	struct ieee80211_local *local = sdata->local;
315017c18bf8SJohannes Berg 	struct sta_info *sta;
315117c18bf8SJohannes Berg 
315217c18bf8SJohannes Berg 	rcu_read_lock();
315317c18bf8SJohannes Berg 
315417c18bf8SJohannes Berg 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
315517c18bf8SJohannes Berg 		if (sdata != sta->sdata &&
315617c18bf8SJohannes Berg 		    (!sta->sdata->bss || sta->sdata->bss != sdata->bss))
315717c18bf8SJohannes Berg 			continue;
315817c18bf8SJohannes Berg 		ieee80211_check_fast_xmit(sta);
315917c18bf8SJohannes Berg 	}
316017c18bf8SJohannes Berg 
316117c18bf8SJohannes Berg 	rcu_read_unlock();
316217c18bf8SJohannes Berg }
316317c18bf8SJohannes Berg 
316417c18bf8SJohannes Berg void ieee80211_clear_fast_xmit(struct sta_info *sta)
316517c18bf8SJohannes Berg {
316617c18bf8SJohannes Berg 	struct ieee80211_fast_tx *fast_tx;
316717c18bf8SJohannes Berg 
316817c18bf8SJohannes Berg 	spin_lock_bh(&sta->lock);
316917c18bf8SJohannes Berg 	fast_tx = rcu_dereference_protected(sta->fast_tx,
317017c18bf8SJohannes Berg 					    lockdep_is_held(&sta->lock));
317117c18bf8SJohannes Berg 	RCU_INIT_POINTER(sta->fast_tx, NULL);
317217c18bf8SJohannes Berg 	spin_unlock_bh(&sta->lock);
317317c18bf8SJohannes Berg 
317417c18bf8SJohannes Berg 	if (fast_tx)
317517c18bf8SJohannes Berg 		kfree_rcu(fast_tx, rcu_head);
317617c18bf8SJohannes Berg }
317717c18bf8SJohannes Berg 
31786e0456b5SFelix Fietkau static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local,
3179166ac9d5SSara Sharon 					struct sk_buff *skb, int headroom)
31806e0456b5SFelix Fietkau {
3181166ac9d5SSara Sharon 	if (skb_headroom(skb) < headroom) {
31826e0456b5SFelix Fietkau 		I802_DEBUG_INC(local->tx_expand_skb_head);
31836e0456b5SFelix Fietkau 
3184166ac9d5SSara Sharon 		if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
31856e0456b5SFelix Fietkau 			wiphy_debug(local->hw.wiphy,
31866e0456b5SFelix Fietkau 				    "failed to reallocate TX buffer\n");
31876e0456b5SFelix Fietkau 			return false;
31886e0456b5SFelix Fietkau 		}
31896e0456b5SFelix Fietkau 	}
31906e0456b5SFelix Fietkau 
31916e0456b5SFelix Fietkau 	return true;
31926e0456b5SFelix Fietkau }
31936e0456b5SFelix Fietkau 
31946e0456b5SFelix Fietkau static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
31956e0456b5SFelix Fietkau 					 struct ieee80211_fast_tx *fast_tx,
31966e0456b5SFelix Fietkau 					 struct sk_buff *skb)
31976e0456b5SFelix Fietkau {
31986e0456b5SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
31996e0456b5SFelix Fietkau 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
32006e0456b5SFelix Fietkau 	struct ieee80211_hdr *hdr;
320106f2bb1eSMichael Braun 	struct ethhdr *amsdu_hdr;
32026e0456b5SFelix Fietkau 	int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
32036e0456b5SFelix Fietkau 	int subframe_len = skb->len - hdr_len;
32046e0456b5SFelix Fietkau 	void *data;
320506f2bb1eSMichael Braun 	u8 *qc, *h_80211_src, *h_80211_dst;
3206a3e2f4b6SMichael Braun 	const u8 *bssid;
32076e0456b5SFelix Fietkau 
32086e0456b5SFelix Fietkau 	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
32096e0456b5SFelix Fietkau 		return false;
32106e0456b5SFelix Fietkau 
32116e0456b5SFelix Fietkau 	if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
32126e0456b5SFelix Fietkau 		return true;
32136e0456b5SFelix Fietkau 
3214166ac9d5SSara Sharon 	if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr)))
32156e0456b5SFelix Fietkau 		return false;
32166e0456b5SFelix Fietkau 
321706f2bb1eSMichael Braun 	data = skb_push(skb, sizeof(*amsdu_hdr));
321806f2bb1eSMichael Braun 	memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
32196e0456b5SFelix Fietkau 	hdr = data;
322006f2bb1eSMichael Braun 	amsdu_hdr = data + hdr_len;
322106f2bb1eSMichael Braun 	/* h_80211_src/dst is addr* field within hdr */
322206f2bb1eSMichael Braun 	h_80211_src = data + fast_tx->sa_offs;
322306f2bb1eSMichael Braun 	h_80211_dst = data + fast_tx->da_offs;
322406f2bb1eSMichael Braun 
322506f2bb1eSMichael Braun 	amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
322606f2bb1eSMichael Braun 	ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
322706f2bb1eSMichael Braun 	ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
322806f2bb1eSMichael Braun 
3229a3e2f4b6SMichael Braun 	/* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
3230a3e2f4b6SMichael Braun 	 * fields needs to be changed to BSSID for A-MSDU frames depending
3231a3e2f4b6SMichael Braun 	 * on FromDS/ToDS values.
3232a3e2f4b6SMichael Braun 	 */
3233a3e2f4b6SMichael Braun 	switch (sdata->vif.type) {
3234a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_STATION:
3235a3e2f4b6SMichael Braun 		bssid = sdata->u.mgd.bssid;
3236a3e2f4b6SMichael Braun 		break;
3237a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_AP:
3238a3e2f4b6SMichael Braun 	case NL80211_IFTYPE_AP_VLAN:
3239a3e2f4b6SMichael Braun 		bssid = sdata->vif.addr;
3240a3e2f4b6SMichael Braun 		break;
3241a3e2f4b6SMichael Braun 	default:
3242a3e2f4b6SMichael Braun 		bssid = NULL;
3243a3e2f4b6SMichael Braun 	}
3244a3e2f4b6SMichael Braun 
3245a3e2f4b6SMichael Braun 	if (bssid && ieee80211_has_fromds(hdr->frame_control))
3246a3e2f4b6SMichael Braun 		ether_addr_copy(h_80211_src, bssid);
3247a3e2f4b6SMichael Braun 
3248a3e2f4b6SMichael Braun 	if (bssid && ieee80211_has_tods(hdr->frame_control))
3249a3e2f4b6SMichael Braun 		ether_addr_copy(h_80211_dst, bssid);
3250a3e2f4b6SMichael Braun 
32516e0456b5SFelix Fietkau 	qc = ieee80211_get_qos_ctl(hdr);
32526e0456b5SFelix Fietkau 	*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
32536e0456b5SFelix Fietkau 
32546e0456b5SFelix Fietkau 	info->control.flags |= IEEE80211_TX_CTRL_AMSDU;
32556e0456b5SFelix Fietkau 
32566e0456b5SFelix Fietkau 	return true;
32576e0456b5SFelix Fietkau }
32586e0456b5SFelix Fietkau 
32596e0456b5SFelix Fietkau static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
32606e0456b5SFelix Fietkau 				      struct sta_info *sta,
32616e0456b5SFelix Fietkau 				      struct ieee80211_fast_tx *fast_tx,
32626e0456b5SFelix Fietkau 				      struct sk_buff *skb)
32636e0456b5SFelix Fietkau {
32646e0456b5SFelix Fietkau 	struct ieee80211_local *local = sdata->local;
3265fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
3266fa962b92SMichal Kazior 	struct fq_tin *tin;
3267fa962b92SMichal Kazior 	struct fq_flow *flow;
32686e0456b5SFelix Fietkau 	u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
32696e0456b5SFelix Fietkau 	struct ieee80211_txq *txq = sta->sta.txq[tid];
32706e0456b5SFelix Fietkau 	struct txq_info *txqi;
32716e0456b5SFelix Fietkau 	struct sk_buff **frag_tail, *head;
32726e0456b5SFelix Fietkau 	int subframe_len = skb->len - ETH_ALEN;
32736e0456b5SFelix Fietkau 	u8 max_subframes = sta->sta.max_amsdu_subframes;
32746e0456b5SFelix Fietkau 	int max_frags = local->hw.max_tx_fragments;
32756e0456b5SFelix Fietkau 	int max_amsdu_len = sta->sta.max_amsdu_len;
3276eb9b64e3SFelix Fietkau 	int orig_truesize;
3277f2af2df8SFelix Fietkau 	u32 flow_idx;
32786e0456b5SFelix Fietkau 	__be16 len;
32796e0456b5SFelix Fietkau 	void *data;
32806e0456b5SFelix Fietkau 	bool ret = false;
3281fa962b92SMichal Kazior 	unsigned int orig_len;
328266eb02d8SLorenzo Bianconi 	int n = 2, nfrags, pad = 0;
3283166ac9d5SSara Sharon 	u16 hdrlen;
32846e0456b5SFelix Fietkau 
32856e0456b5SFelix Fietkau 	if (!ieee80211_hw_check(&local->hw, TX_AMSDU))
32866e0456b5SFelix Fietkau 		return false;
32876e0456b5SFelix Fietkau 
3288344f8e00SSara Sharon 	if (skb_is_gso(skb))
3289344f8e00SSara Sharon 		return false;
3290344f8e00SSara Sharon 
32916e0456b5SFelix Fietkau 	if (!txq)
32926e0456b5SFelix Fietkau 		return false;
32936e0456b5SFelix Fietkau 
32946e0456b5SFelix Fietkau 	txqi = to_txq_info(txq);
32956e0456b5SFelix Fietkau 	if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags))
32966e0456b5SFelix Fietkau 		return false;
32976e0456b5SFelix Fietkau 
32986e0456b5SFelix Fietkau 	if (sta->sta.max_rc_amsdu_len)
32996e0456b5SFelix Fietkau 		max_amsdu_len = min_t(int, max_amsdu_len,
33006e0456b5SFelix Fietkau 				      sta->sta.max_rc_amsdu_len);
33016e0456b5SFelix Fietkau 
3302edba6bdaSSara Sharon 	if (sta->sta.max_tid_amsdu_len[tid])
3303edba6bdaSSara Sharon 		max_amsdu_len = min_t(int, max_amsdu_len,
3304edba6bdaSSara Sharon 				      sta->sta.max_tid_amsdu_len[tid]);
3305edba6bdaSSara Sharon 
3306f2af2df8SFelix Fietkau 	flow_idx = fq_flow_idx(fq, skb);
3307f2af2df8SFelix Fietkau 
3308fa962b92SMichal Kazior 	spin_lock_bh(&fq->lock);
33096e0456b5SFelix Fietkau 
3310fa962b92SMichal Kazior 	/* TODO: Ideally aggregation should be done on dequeue to remain
3311fa962b92SMichal Kazior 	 * responsive to environment changes.
3312fa962b92SMichal Kazior 	 */
3313fa962b92SMichal Kazior 
3314fa962b92SMichal Kazior 	tin = &txqi->tin;
3315bf9009bfSFelix Fietkau 	flow = fq_flow_classify(fq, tin, flow_idx, skb);
3316fa962b92SMichal Kazior 	head = skb_peek_tail(&flow->queue);
3317344f8e00SSara Sharon 	if (!head || skb_is_gso(head))
33186e0456b5SFelix Fietkau 		goto out;
33196e0456b5SFelix Fietkau 
3320eb9b64e3SFelix Fietkau 	orig_truesize = head->truesize;
3321fa962b92SMichal Kazior 	orig_len = head->len;
3322fa962b92SMichal Kazior 
33236e0456b5SFelix Fietkau 	if (skb->len + head->len > max_amsdu_len)
33246e0456b5SFelix Fietkau 		goto out;
33256e0456b5SFelix Fietkau 
33266e0456b5SFelix Fietkau 	nfrags = 1 + skb_shinfo(skb)->nr_frags;
33276e0456b5SFelix Fietkau 	nfrags += 1 + skb_shinfo(head)->nr_frags;
33286e0456b5SFelix Fietkau 	frag_tail = &skb_shinfo(head)->frag_list;
33296e0456b5SFelix Fietkau 	while (*frag_tail) {
33306e0456b5SFelix Fietkau 		nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags;
33316e0456b5SFelix Fietkau 		frag_tail = &(*frag_tail)->next;
33326e0456b5SFelix Fietkau 		n++;
33336e0456b5SFelix Fietkau 	}
33346e0456b5SFelix Fietkau 
33356e0456b5SFelix Fietkau 	if (max_subframes && n > max_subframes)
33366e0456b5SFelix Fietkau 		goto out;
33376e0456b5SFelix Fietkau 
33386e0456b5SFelix Fietkau 	if (max_frags && nfrags > max_frags)
33396e0456b5SFelix Fietkau 		goto out;
33406e0456b5SFelix Fietkau 
33419739fe29SSara Sharon 	if (!drv_can_aggregate_in_amsdu(local, head, skb))
33429739fe29SSara Sharon 		goto out;
33439739fe29SSara Sharon 
33441eb50790SLorenzo Bianconi 	if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
33456e0456b5SFelix Fietkau 		goto out;
33466e0456b5SFelix Fietkau 
3347166ac9d5SSara Sharon 	/*
3348166ac9d5SSara Sharon 	 * Pad out the previous subframe to a multiple of 4 by adding the
3349166ac9d5SSara Sharon 	 * padding to the next one, that's being added. Note that head->len
3350166ac9d5SSara Sharon 	 * is the length of the full A-MSDU, but that works since each time
3351166ac9d5SSara Sharon 	 * we add a new subframe we pad out the previous one to a multiple
3352166ac9d5SSara Sharon 	 * of 4 and thus it no longer matters in the next round.
3353166ac9d5SSara Sharon 	 */
3354166ac9d5SSara Sharon 	hdrlen = fast_tx->hdr_len - sizeof(rfc1042_header);
3355166ac9d5SSara Sharon 	if ((head->len - hdrlen) & 3)
3356166ac9d5SSara Sharon 		pad = 4 - ((head->len - hdrlen) & 3);
3357166ac9d5SSara Sharon 
3358166ac9d5SSara Sharon 	if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) +
3359166ac9d5SSara Sharon 						     2 + pad))
3360aa58acf3SJohannes Berg 		goto out_recalc;
33616e0456b5SFelix Fietkau 
33626e0456b5SFelix Fietkau 	ret = true;
33636e0456b5SFelix Fietkau 	data = skb_push(skb, ETH_ALEN + 2);
33646e0456b5SFelix Fietkau 	memmove(data, data + ETH_ALEN + 2, 2 * ETH_ALEN);
33656e0456b5SFelix Fietkau 
33666e0456b5SFelix Fietkau 	data += 2 * ETH_ALEN;
33676e0456b5SFelix Fietkau 	len = cpu_to_be16(subframe_len);
33686e0456b5SFelix Fietkau 	memcpy(data, &len, 2);
33696e0456b5SFelix Fietkau 	memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header));
33706e0456b5SFelix Fietkau 
3371166ac9d5SSara Sharon 	memset(skb_push(skb, pad), 0, pad);
3372166ac9d5SSara Sharon 
33736e0456b5SFelix Fietkau 	head->len += skb->len;
33746e0456b5SFelix Fietkau 	head->data_len += skb->len;
33756e0456b5SFelix Fietkau 	*frag_tail = skb;
33766e0456b5SFelix Fietkau 
3377aa58acf3SJohannes Berg out_recalc:
3378eb9b64e3SFelix Fietkau 	fq->memory_usage += head->truesize - orig_truesize;
3379aa58acf3SJohannes Berg 	if (head->len != orig_len) {
3380fa962b92SMichal Kazior 		flow->backlog += head->len - orig_len;
3381fa962b92SMichal Kazior 		tin->backlog_bytes += head->len - orig_len;
3382aa58acf3SJohannes Berg 	}
33836e0456b5SFelix Fietkau out:
3384fa962b92SMichal Kazior 	spin_unlock_bh(&fq->lock);
33856e0456b5SFelix Fietkau 
33866e0456b5SFelix Fietkau 	return ret;
33876e0456b5SFelix Fietkau }
33886e0456b5SFelix Fietkau 
3389bb42f2d1SToke Høiland-Jørgensen /*
3390bb42f2d1SToke Høiland-Jørgensen  * Can be called while the sta lock is held. Anything that can cause packets to
3391bb42f2d1SToke Høiland-Jørgensen  * be generated will cause deadlock!
3392bb42f2d1SToke Høiland-Jørgensen  */
3393*03c3911dSRyder Lee static ieee80211_tx_result
3394*03c3911dSRyder Lee ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
3395bb42f2d1SToke Høiland-Jørgensen 			   struct sta_info *sta, u8 pn_offs,
3396bb42f2d1SToke Høiland-Jørgensen 			   struct ieee80211_key *key,
3397*03c3911dSRyder Lee 			   struct ieee80211_tx_data *tx)
3398bb42f2d1SToke Høiland-Jørgensen {
3399*03c3911dSRyder Lee 	struct sk_buff *skb = tx->skb;
3400bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
3401bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_hdr *hdr = (void *)skb->data;
3402bb42f2d1SToke Høiland-Jørgensen 	u8 tid = IEEE80211_NUM_TIDS;
3403bb42f2d1SToke Høiland-Jørgensen 
3404*03c3911dSRyder Lee 	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL) &&
3405*03c3911dSRyder Lee 	    ieee80211_tx_h_rate_ctrl(tx) != TX_CONTINUE)
3406*03c3911dSRyder Lee 		return TX_DROP;
3407*03c3911dSRyder Lee 
3408bb42f2d1SToke Høiland-Jørgensen 	if (key)
3409bb42f2d1SToke Høiland-Jørgensen 		info->control.hw_key = &key->conf;
3410bb42f2d1SToke Høiland-Jørgensen 
341136ec144fSLev Stipakov 	dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
3412bb42f2d1SToke Høiland-Jørgensen 
3413bb42f2d1SToke Høiland-Jørgensen 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
3414bb42f2d1SToke Høiland-Jørgensen 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
3415bb42f2d1SToke Høiland-Jørgensen 		hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
3416bb42f2d1SToke Høiland-Jørgensen 	} else {
3417bb42f2d1SToke Høiland-Jørgensen 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
3418bb42f2d1SToke Høiland-Jørgensen 		hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
3419bb42f2d1SToke Høiland-Jørgensen 		sdata->sequence_number += 0x10;
3420bb42f2d1SToke Høiland-Jørgensen 	}
3421bb42f2d1SToke Høiland-Jørgensen 
3422bb42f2d1SToke Høiland-Jørgensen 	if (skb_shinfo(skb)->gso_size)
3423bb42f2d1SToke Høiland-Jørgensen 		sta->tx_stats.msdu[tid] +=
3424bb42f2d1SToke Høiland-Jørgensen 			DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
3425bb42f2d1SToke Høiland-Jørgensen 	else
3426bb42f2d1SToke Høiland-Jørgensen 		sta->tx_stats.msdu[tid]++;
3427bb42f2d1SToke Høiland-Jørgensen 
3428bb42f2d1SToke Høiland-Jørgensen 	info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
3429bb42f2d1SToke Høiland-Jørgensen 
3430bb42f2d1SToke Høiland-Jørgensen 	/* statistics normally done by ieee80211_tx_h_stats (but that
3431bb42f2d1SToke Høiland-Jørgensen 	 * has to consider fragmentation, so is more complex)
3432bb42f2d1SToke Høiland-Jørgensen 	 */
3433bb42f2d1SToke Høiland-Jørgensen 	sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
3434bb42f2d1SToke Høiland-Jørgensen 	sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
3435bb42f2d1SToke Høiland-Jørgensen 
3436bb42f2d1SToke Høiland-Jørgensen 	if (pn_offs) {
3437bb42f2d1SToke Høiland-Jørgensen 		u64 pn;
3438bb42f2d1SToke Høiland-Jørgensen 		u8 *crypto_hdr = skb->data + pn_offs;
3439bb42f2d1SToke Høiland-Jørgensen 
3440bb42f2d1SToke Høiland-Jørgensen 		switch (key->conf.cipher) {
3441bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_CCMP:
3442bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_CCMP_256:
3443bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_GCMP:
3444bb42f2d1SToke Høiland-Jørgensen 		case WLAN_CIPHER_SUITE_GCMP_256:
3445bb42f2d1SToke Høiland-Jørgensen 			pn = atomic64_inc_return(&key->conf.tx_pn);
3446bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[0] = pn;
3447bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[1] = pn >> 8;
344896fc6efbSAlexander Wetzel 			crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6);
3449bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[4] = pn >> 16;
3450bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[5] = pn >> 24;
3451bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[6] = pn >> 32;
3452bb42f2d1SToke Høiland-Jørgensen 			crypto_hdr[7] = pn >> 40;
3453bb42f2d1SToke Høiland-Jørgensen 			break;
3454bb42f2d1SToke Høiland-Jørgensen 		}
3455bb42f2d1SToke Høiland-Jørgensen 	}
3456*03c3911dSRyder Lee 
3457*03c3911dSRyder Lee 	return TX_CONTINUE;
3458bb42f2d1SToke Høiland-Jørgensen }
3459bb42f2d1SToke Høiland-Jørgensen 
346017c18bf8SJohannes Berg static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
3461bb42f2d1SToke Høiland-Jørgensen 				struct sta_info *sta,
346217c18bf8SJohannes Berg 				struct ieee80211_fast_tx *fast_tx,
346317c18bf8SJohannes Berg 				struct sk_buff *skb)
346417c18bf8SJohannes Berg {
346517c18bf8SJohannes Berg 	struct ieee80211_local *local = sdata->local;
346617c18bf8SJohannes Berg 	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
346717c18bf8SJohannes Berg 	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
346817c18bf8SJohannes Berg 	int hw_headroom = sdata->local->hw.extra_tx_headroom;
346917c18bf8SJohannes Berg 	struct ethhdr eth;
347035f432a0SJohannes Berg 	struct ieee80211_tx_info *info;
347117c18bf8SJohannes Berg 	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
347217c18bf8SJohannes Berg 	struct ieee80211_tx_data tx;
347317c18bf8SJohannes Berg 	ieee80211_tx_result r;
347417c18bf8SJohannes Berg 	struct tid_ampdu_tx *tid_tx = NULL;
347517c18bf8SJohannes Berg 	u8 tid = IEEE80211_NUM_TIDS;
347617c18bf8SJohannes Berg 
347717c18bf8SJohannes Berg 	/* control port protocol needs a lot of special handling */
347817c18bf8SJohannes Berg 	if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
347917c18bf8SJohannes Berg 		return false;
348017c18bf8SJohannes Berg 
348117c18bf8SJohannes Berg 	/* only RFC 1042 SNAP */
348217c18bf8SJohannes Berg 	if (ethertype < ETH_P_802_3_MIN)
348317c18bf8SJohannes Berg 		return false;
348417c18bf8SJohannes Berg 
348517c18bf8SJohannes Berg 	/* don't handle TX status request here either */
348617c18bf8SJohannes Berg 	if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
348717c18bf8SJohannes Berg 		return false;
348817c18bf8SJohannes Berg 
348917c18bf8SJohannes Berg 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
349017c18bf8SJohannes Berg 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
349117c18bf8SJohannes Berg 		tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
3492472be00dSJohannes Berg 		if (tid_tx) {
3493472be00dSJohannes Berg 			if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
349417c18bf8SJohannes Berg 				return false;
3495472be00dSJohannes Berg 			if (tid_tx->timeout)
3496472be00dSJohannes Berg 				tid_tx->last_tx = jiffies;
3497472be00dSJohannes Berg 		}
349817c18bf8SJohannes Berg 	}
349917c18bf8SJohannes Berg 
350017c18bf8SJohannes Berg 	/* after this point (skb is modified) we cannot return false */
350117c18bf8SJohannes Berg 
350217c18bf8SJohannes Berg 	if (skb_shared(skb)) {
350317c18bf8SJohannes Berg 		struct sk_buff *tmp_skb = skb;
350417c18bf8SJohannes Berg 
350517c18bf8SJohannes Berg 		skb = skb_clone(skb, GFP_ATOMIC);
350617c18bf8SJohannes Berg 		kfree_skb(tmp_skb);
350717c18bf8SJohannes Berg 
350817c18bf8SJohannes Berg 		if (!skb)
350917c18bf8SJohannes Berg 			return true;
351017c18bf8SJohannes Berg 	}
351117c18bf8SJohannes Berg 
35126e0456b5SFelix Fietkau 	if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
35136e0456b5SFelix Fietkau 	    ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
35146e0456b5SFelix Fietkau 		return true;
35156e0456b5SFelix Fietkau 
351617c18bf8SJohannes Berg 	/* will not be crypto-handled beyond what we do here, so use false
351717c18bf8SJohannes Berg 	 * as the may-encrypt argument for the resize to not account for
351817c18bf8SJohannes Berg 	 * more room than we already have in 'extra_head'
351917c18bf8SJohannes Berg 	 */
352017c18bf8SJohannes Berg 	if (unlikely(ieee80211_skb_resize(sdata, skb,
352117c18bf8SJohannes Berg 					  max_t(int, extra_head + hw_headroom -
352217c18bf8SJohannes Berg 						     skb_headroom(skb), 0),
352314f46c1eSJohannes Berg 					  ENCRYPT_NO))) {
352417c18bf8SJohannes Berg 		kfree_skb(skb);
352517c18bf8SJohannes Berg 		return true;
352617c18bf8SJohannes Berg 	}
352717c18bf8SJohannes Berg 
352817c18bf8SJohannes Berg 	memcpy(&eth, skb->data, ETH_HLEN - 2);
3529d58ff351SJohannes Berg 	hdr = skb_push(skb, extra_head);
353017c18bf8SJohannes Berg 	memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
353117c18bf8SJohannes Berg 	memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
353217c18bf8SJohannes Berg 	memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
353317c18bf8SJohannes Berg 
353435f432a0SJohannes Berg 	info = IEEE80211_SKB_CB(skb);
353517c18bf8SJohannes Berg 	memset(info, 0, sizeof(*info));
353617c18bf8SJohannes Berg 	info->band = fast_tx->band;
353717c18bf8SJohannes Berg 	info->control.vif = &sdata->vif;
353817c18bf8SJohannes Berg 	info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
353917c18bf8SJohannes Berg 		      IEEE80211_TX_CTL_DONTFRAG |
354017c18bf8SJohannes Berg 		      (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
3541bb42f2d1SToke Høiland-Jørgensen 	info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
354217c18bf8SJohannes Berg 
3543276d9e82SJulius Niedworok #ifdef CONFIG_MAC80211_DEBUGFS
3544276d9e82SJulius Niedworok 	if (local->force_tx_status)
3545276d9e82SJulius Niedworok 		info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
3546276d9e82SJulius Niedworok #endif
3547276d9e82SJulius Niedworok 
3548a786f96dSFelix Fietkau 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
3549a786f96dSFelix Fietkau 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
3550a786f96dSFelix Fietkau 		*ieee80211_get_qos_ctl(hdr) = tid;
3551a786f96dSFelix Fietkau 	}
3552a786f96dSFelix Fietkau 
355317c18bf8SJohannes Berg 	__skb_queue_head_init(&tx.skbs);
355417c18bf8SJohannes Berg 
355517c18bf8SJohannes Berg 	tx.flags = IEEE80211_TX_UNICAST;
355617c18bf8SJohannes Berg 	tx.local = local;
355717c18bf8SJohannes Berg 	tx.sdata = sdata;
355817c18bf8SJohannes Berg 	tx.sta = sta;
355917c18bf8SJohannes Berg 	tx.key = fast_tx->key;
356017c18bf8SJohannes Berg 
3561bb42f2d1SToke Høiland-Jørgensen 	if (ieee80211_queue_skb(local, sdata, sta, skb))
3562bb42f2d1SToke Høiland-Jørgensen 		return true;
356317c18bf8SJohannes Berg 
3564*03c3911dSRyder Lee 	tx.skb = skb;
3565*03c3911dSRyder Lee 	r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs,
3566*03c3911dSRyder Lee 				       fast_tx->key, &tx);
3567*03c3911dSRyder Lee 	tx.skb = NULL;
3568*03c3911dSRyder Lee 	if (r == TX_DROP) {
3569*03c3911dSRyder Lee 		kfree_skb(skb);
3570*03c3911dSRyder Lee 		return true;
3571*03c3911dSRyder Lee 	}
357217c18bf8SJohannes Berg 
357317c18bf8SJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
357417c18bf8SJohannes Berg 		sdata = container_of(sdata->bss,
357517c18bf8SJohannes Berg 				     struct ieee80211_sub_if_data, u.ap);
357617c18bf8SJohannes Berg 
357717c18bf8SJohannes Berg 	__skb_queue_tail(&tx.skbs, skb);
35784fd0328dSJohannes Berg 	ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
357917c18bf8SJohannes Berg 	return true;
358017c18bf8SJohannes Berg }
358117c18bf8SJohannes Berg 
3582e0e2efffSToke Høiland-Jørgensen struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
3583e0e2efffSToke Høiland-Jørgensen 				     struct ieee80211_txq *txq)
3584e0e2efffSToke Høiland-Jørgensen {
3585e0e2efffSToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
3586e0e2efffSToke Høiland-Jørgensen 	struct txq_info *txqi = container_of(txq, struct txq_info, txq);
3587e0e2efffSToke Høiland-Jørgensen 	struct ieee80211_hdr *hdr;
3588e0e2efffSToke Høiland-Jørgensen 	struct sk_buff *skb = NULL;
3589e0e2efffSToke Høiland-Jørgensen 	struct fq *fq = &local->fq;
3590e0e2efffSToke Høiland-Jørgensen 	struct fq_tin *tin = &txqi->tin;
3591bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_info *info;
3592bb42f2d1SToke Høiland-Jørgensen 	struct ieee80211_tx_data tx;
3593bb42f2d1SToke Høiland-Jørgensen 	ieee80211_tx_result r;
359421a5d4c3SManikanta Pubbisetty 	struct ieee80211_vif *vif = txq->vif;
3595e0e2efffSToke Høiland-Jørgensen 
3596fb0e76abSErik Stromdahl 	WARN_ON_ONCE(softirq_count() == 0);
3597fb0e76abSErik Stromdahl 
35987a89233aSToke Høiland-Jørgensen 	if (!ieee80211_txq_airtime_check(hw, txq))
35997a89233aSToke Høiland-Jørgensen 		return NULL;
36007a89233aSToke Høiland-Jørgensen 
3601ded4698bSFelix Fietkau begin:
3602e0e2efffSToke Høiland-Jørgensen 	spin_lock_bh(&fq->lock);
3603e0e2efffSToke Høiland-Jørgensen 
360421a5d4c3SManikanta Pubbisetty 	if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ||
360521a5d4c3SManikanta Pubbisetty 	    test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags))
3606e0e2efffSToke Høiland-Jørgensen 		goto out;
3607e0e2efffSToke Høiland-Jørgensen 
36081153a747SJohannes Berg 	if (vif->txqs_stopped[txq->ac]) {
360921a5d4c3SManikanta Pubbisetty 		set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags);
361021a5d4c3SManikanta Pubbisetty 		goto out;
361121a5d4c3SManikanta Pubbisetty 	}
361221a5d4c3SManikanta Pubbisetty 
3613bb42f2d1SToke Høiland-Jørgensen 	/* Make sure fragments stay together. */
3614bb42f2d1SToke Høiland-Jørgensen 	skb = __skb_dequeue(&txqi->frags);
3615ca47b462SJohannes Berg 	if (unlikely(skb)) {
3616ca47b462SJohannes Berg 		if (!(IEEE80211_SKB_CB(skb)->control.flags &
3617ca47b462SJohannes Berg 				IEEE80211_TX_INTCFL_NEED_TXPROCESSING))
3618bb42f2d1SToke Høiland-Jørgensen 			goto out;
3619ca47b462SJohannes Berg 		IEEE80211_SKB_CB(skb)->control.flags &=
3620ca47b462SJohannes Berg 			~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
3621ca47b462SJohannes Berg 	} else {
3622e0e2efffSToke Høiland-Jørgensen 		skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
3623ca47b462SJohannes Berg 	}
3624ca47b462SJohannes Berg 
3625e0e2efffSToke Høiland-Jørgensen 	if (!skb)
3626e0e2efffSToke Høiland-Jørgensen 		goto out;
3627e0e2efffSToke Høiland-Jørgensen 
3628ded4698bSFelix Fietkau 	spin_unlock_bh(&fq->lock);
3629ded4698bSFelix Fietkau 
3630e0e2efffSToke Høiland-Jørgensen 	hdr = (struct ieee80211_hdr *)skb->data;
3631bb42f2d1SToke Høiland-Jørgensen 	info = IEEE80211_SKB_CB(skb);
3632bb42f2d1SToke Høiland-Jørgensen 
3633bb42f2d1SToke Høiland-Jørgensen 	memset(&tx, 0, sizeof(tx));
3634bb42f2d1SToke Høiland-Jørgensen 	__skb_queue_head_init(&tx.skbs);
3635bb42f2d1SToke Høiland-Jørgensen 	tx.local = local;
3636bb42f2d1SToke Høiland-Jørgensen 	tx.skb = skb;
3637bb42f2d1SToke Høiland-Jørgensen 	tx.sdata = vif_to_sdata(info->control.vif);
3638bb42f2d1SToke Høiland-Jørgensen 
3639804fc6a2SMathy Vanhoef 	if (txq->sta) {
3640bb42f2d1SToke Høiland-Jørgensen 		tx.sta = container_of(txq->sta, struct sta_info, sta);
3641ce2e1ca7SJouni Malinen 		/*
3642ce2e1ca7SJouni Malinen 		 * Drop unicast frames to unauthorised stations unless they are
3643804fc6a2SMathy Vanhoef 		 * injected frames or EAPOL frames from the local station.
3644ce2e1ca7SJouni Malinen 		 */
3645804fc6a2SMathy Vanhoef 		if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
3646804fc6a2SMathy Vanhoef 			     ieee80211_is_data(hdr->frame_control) &&
3647be8c827fSJohannes Berg 			     !ieee80211_vif_is_mesh(&tx.sdata->vif) &&
3648ce2e1ca7SJouni Malinen 			     tx.sdata->vif.type != NL80211_IFTYPE_OCB &&
3649ce2e1ca7SJouni Malinen 			     !is_multicast_ether_addr(hdr->addr1) &&
3650ce2e1ca7SJouni Malinen 			     !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) &&
3651ce2e1ca7SJouni Malinen 			     (!(info->control.flags &
3652ce2e1ca7SJouni Malinen 				IEEE80211_TX_CTRL_PORT_CTRL_PROTO) ||
3653ce2e1ca7SJouni Malinen 			      !ether_addr_equal(tx.sdata->vif.addr,
3654ce2e1ca7SJouni Malinen 						hdr->addr2)))) {
3655ce2e1ca7SJouni Malinen 			I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
3656ce2e1ca7SJouni Malinen 			ieee80211_free_txskb(&local->hw, skb);
3657ce2e1ca7SJouni Malinen 			goto begin;
3658ce2e1ca7SJouni Malinen 		}
3659ce2e1ca7SJouni Malinen 	}
3660bb42f2d1SToke Høiland-Jørgensen 
3661bb42f2d1SToke Høiland-Jørgensen 	/*
3662bb42f2d1SToke Høiland-Jørgensen 	 * The key can be removed while the packet was queued, so need to call
3663bb42f2d1SToke Høiland-Jørgensen 	 * this here to get the current key.
3664bb42f2d1SToke Høiland-Jørgensen 	 */
3665bb42f2d1SToke Høiland-Jørgensen 	r = ieee80211_tx_h_select_key(&tx);
3666bb42f2d1SToke Høiland-Jørgensen 	if (r != TX_CONTINUE) {
3667bb42f2d1SToke Høiland-Jørgensen 		ieee80211_free_txskb(&local->hw, skb);
3668bb42f2d1SToke Høiland-Jørgensen 		goto begin;
3669bb42f2d1SToke Høiland-Jørgensen 	}
3670bb42f2d1SToke Høiland-Jørgensen 
3671c1f4c9edSFelix Fietkau 	if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
3672c1f4c9edSFelix Fietkau 		info->flags |= IEEE80211_TX_CTL_AMPDU;
3673c1f4c9edSFelix Fietkau 	else
3674c1f4c9edSFelix Fietkau 		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
3675c1f4c9edSFelix Fietkau 
3676cc20ff2cSFelix Fietkau 	if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
367750ff477aSJohn Crispin 		goto encap_out;
367850ff477aSJohn Crispin 
3679bb42f2d1SToke Høiland-Jørgensen 	if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
3680e0e2efffSToke Høiland-Jørgensen 		struct sta_info *sta = container_of(txq->sta, struct sta_info,
3681e0e2efffSToke Høiland-Jørgensen 						    sta);
3682bb42f2d1SToke Høiland-Jørgensen 		u8 pn_offs = 0;
3683e0e2efffSToke Høiland-Jørgensen 
3684bb42f2d1SToke Høiland-Jørgensen 		if (tx.key &&
3685bb42f2d1SToke Høiland-Jørgensen 		    (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
3686bb42f2d1SToke Høiland-Jørgensen 			pn_offs = ieee80211_hdrlen(hdr->frame_control);
3687bb42f2d1SToke Høiland-Jørgensen 
3688*03c3911dSRyder Lee 		r = ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
3689*03c3911dSRyder Lee 					       tx.key, &tx);
3690*03c3911dSRyder Lee 		if (r != TX_CONTINUE) {
3691*03c3911dSRyder Lee 			ieee80211_free_txskb(&local->hw, skb);
3692*03c3911dSRyder Lee 			goto begin;
3693*03c3911dSRyder Lee 		}
3694bb42f2d1SToke Høiland-Jørgensen 	} else {
3695bb42f2d1SToke Høiland-Jørgensen 		if (invoke_tx_handlers_late(&tx))
3696bb42f2d1SToke Høiland-Jørgensen 			goto begin;
3697bb42f2d1SToke Høiland-Jørgensen 
3698bb42f2d1SToke Høiland-Jørgensen 		skb = __skb_dequeue(&tx.skbs);
3699bb42f2d1SToke Høiland-Jørgensen 
3700ded4698bSFelix Fietkau 		if (!skb_queue_empty(&tx.skbs)) {
3701ded4698bSFelix Fietkau 			spin_lock_bh(&fq->lock);
3702bb42f2d1SToke Høiland-Jørgensen 			skb_queue_splice_tail(&tx.skbs, &txqi->frags);
3703ded4698bSFelix Fietkau 			spin_unlock_bh(&fq->lock);
3704ded4698bSFelix Fietkau 		}
3705e0e2efffSToke Høiland-Jørgensen 	}
3706e0e2efffSToke Høiland-Jørgensen 
3707233e98dcSJohannes Berg 	if (skb_has_frag_list(skb) &&
37081e1430d5SJohannes Berg 	    !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) {
37091e1430d5SJohannes Berg 		if (skb_linearize(skb)) {
37101e1430d5SJohannes Berg 			ieee80211_free_txskb(&local->hw, skb);
37111e1430d5SJohannes Berg 			goto begin;
37121e1430d5SJohannes Berg 		}
37131e1430d5SJohannes Berg 	}
37141e1430d5SJohannes Berg 
371553168215SJohannes Berg 	switch (tx.sdata->vif.type) {
371653168215SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
371753168215SJohannes Berg 		if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
371853168215SJohannes Berg 			vif = &tx.sdata->vif;
371953168215SJohannes Berg 			break;
372053168215SJohannes Berg 		}
372153168215SJohannes Berg 		tx.sdata = rcu_dereference(local->monitor_sdata);
372253168215SJohannes Berg 		if (tx.sdata) {
372353168215SJohannes Berg 			vif = &tx.sdata->vif;
372453168215SJohannes Berg 			info->hw_queue =
372553168215SJohannes Berg 				vif->hw_queue[skb_get_queue_mapping(skb)];
372653168215SJohannes Berg 		} else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
372753168215SJohannes Berg 			ieee80211_free_txskb(&local->hw, skb);
372853168215SJohannes Berg 			goto begin;
372953168215SJohannes Berg 		} else {
373053168215SJohannes Berg 			vif = NULL;
373153168215SJohannes Berg 		}
373253168215SJohannes Berg 		break;
373353168215SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
373453168215SJohannes Berg 		tx.sdata = container_of(tx.sdata->bss,
373553168215SJohannes Berg 					struct ieee80211_sub_if_data, u.ap);
3736fc0561dcSGustavo A. R. Silva 		fallthrough;
373753168215SJohannes Berg 	default:
373853168215SJohannes Berg 		vif = &tx.sdata->vif;
373953168215SJohannes Berg 		break;
374053168215SJohannes Berg 	}
374153168215SJohannes Berg 
374250ff477aSJohn Crispin encap_out:
374353168215SJohannes Berg 	IEEE80211_SKB_CB(skb)->control.vif = vif;
37447a89233aSToke Høiland-Jørgensen 
3745ca98c47dSJohannes Berg 	if (vif &&
3746ca98c47dSJohannes Berg 	    wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
37473ff901cbSFelix Fietkau 		bool ampdu = txq->ac != IEEE80211_AC_VO;
37487a89233aSToke Høiland-Jørgensen 		u32 airtime;
37497a89233aSToke Høiland-Jørgensen 
37507a89233aSToke Høiland-Jørgensen 		airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
37513ff901cbSFelix Fietkau 							     skb->len, ampdu);
37527a89233aSToke Høiland-Jørgensen 		if (airtime) {
37537a89233aSToke Høiland-Jørgensen 			airtime = ieee80211_info_set_tx_time_est(info, airtime);
37547a89233aSToke Høiland-Jørgensen 			ieee80211_sta_update_pending_airtime(local, tx.sta,
37557a89233aSToke Høiland-Jørgensen 							     txq->ac,
37567a89233aSToke Høiland-Jørgensen 							     airtime,
37577a89233aSToke Høiland-Jørgensen 							     false);
37587a89233aSToke Høiland-Jørgensen 		}
37597a89233aSToke Høiland-Jørgensen 	}
37607a89233aSToke Høiland-Jørgensen 
3761ded4698bSFelix Fietkau 	return skb;
376221a5d4c3SManikanta Pubbisetty 
3763e0e2efffSToke Høiland-Jørgensen out:
3764e0e2efffSToke Høiland-Jørgensen 	spin_unlock_bh(&fq->lock);
3765e0e2efffSToke Høiland-Jørgensen 
3766e0e2efffSToke Høiland-Jørgensen 	return skb;
3767e0e2efffSToke Høiland-Jørgensen }
3768e0e2efffSToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_tx_dequeue);
3769e0e2efffSToke Høiland-Jørgensen 
377018667600SToke Høiland-Jørgensen struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
377118667600SToke Høiland-Jørgensen {
377218667600SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
37735b989c18SFelix Fietkau 	struct ieee80211_txq *ret = NULL;
37743ace10f5SKan Yan 	struct txq_info *txqi = NULL, *head = NULL;
37753ace10f5SKan Yan 	bool found_eligible_txq = false;
377618667600SToke Høiland-Jørgensen 
37775b989c18SFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[ac]);
377818667600SToke Høiland-Jørgensen 
3779b4809e94SToke Høiland-Jørgensen  begin:
378018667600SToke Høiland-Jørgensen 	txqi = list_first_entry_or_null(&local->active_txqs[ac],
378118667600SToke Høiland-Jørgensen 					struct txq_info,
378218667600SToke Høiland-Jørgensen 					schedule_order);
3783b4809e94SToke Høiland-Jørgensen 	if (!txqi)
37845b989c18SFelix Fietkau 		goto out;
378518667600SToke Høiland-Jørgensen 
37863ace10f5SKan Yan 	if (txqi == head) {
37873ace10f5SKan Yan 		if (!found_eligible_txq)
37883ace10f5SKan Yan 			goto out;
37893ace10f5SKan Yan 		else
37903ace10f5SKan Yan 			found_eligible_txq = false;
37913ace10f5SKan Yan 	}
37923ace10f5SKan Yan 
37933ace10f5SKan Yan 	if (!head)
37943ace10f5SKan Yan 		head = txqi;
37953ace10f5SKan Yan 
3796b4809e94SToke Høiland-Jørgensen 	if (txqi->txq.sta) {
3797b4809e94SToke Høiland-Jørgensen 		struct sta_info *sta = container_of(txqi->txq.sta,
3798b4809e94SToke Høiland-Jørgensen 						    struct sta_info, sta);
37993ace10f5SKan Yan 		bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
38003ace10f5SKan Yan 		s64 deficit = sta->airtime[txqi->txq.ac].deficit;
3801b4809e94SToke Høiland-Jørgensen 
38023ace10f5SKan Yan 		if (aql_check)
38033ace10f5SKan Yan 			found_eligible_txq = true;
38043ace10f5SKan Yan 
38053ace10f5SKan Yan 		if (deficit < 0)
3806b4809e94SToke Høiland-Jørgensen 			sta->airtime[txqi->txq.ac].deficit +=
3807b4809e94SToke Høiland-Jørgensen 				sta->airtime_weight;
38083ace10f5SKan Yan 
38093ace10f5SKan Yan 		if (deficit < 0 || !aql_check) {
3810b4809e94SToke Høiland-Jørgensen 			list_move_tail(&txqi->schedule_order,
3811b4809e94SToke Høiland-Jørgensen 				       &local->active_txqs[txqi->txq.ac]);
3812b4809e94SToke Høiland-Jørgensen 			goto begin;
3813b4809e94SToke Høiland-Jørgensen 		}
3814b4809e94SToke Høiland-Jørgensen 	}
3815b4809e94SToke Høiland-Jørgensen 
3816b4809e94SToke Høiland-Jørgensen 
3817b4809e94SToke Høiland-Jørgensen 	if (txqi->schedule_round == local->schedule_round[ac])
38185b989c18SFelix Fietkau 		goto out;
381918667600SToke Høiland-Jørgensen 
382018667600SToke Høiland-Jørgensen 	list_del_init(&txqi->schedule_order);
382118667600SToke Høiland-Jørgensen 	txqi->schedule_round = local->schedule_round[ac];
38225b989c18SFelix Fietkau 	ret = &txqi->txq;
38235b989c18SFelix Fietkau 
38245b989c18SFelix Fietkau out:
38255b989c18SFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
38265b989c18SFelix Fietkau 	return ret;
382718667600SToke Høiland-Jørgensen }
382818667600SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_next_txq);
382918667600SToke Høiland-Jørgensen 
38302b4a6698SFelix Fietkau void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
38312b4a6698SFelix Fietkau 			      struct ieee80211_txq *txq,
38322b4a6698SFelix Fietkau 			      bool force)
383318667600SToke Høiland-Jørgensen {
383418667600SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
383518667600SToke Høiland-Jørgensen 	struct txq_info *txqi = to_txq_info(txq);
383618667600SToke Høiland-Jørgensen 
38375b989c18SFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[txq->ac]);
383818667600SToke Høiland-Jørgensen 
383918667600SToke Høiland-Jørgensen 	if (list_empty(&txqi->schedule_order) &&
38402b4a6698SFelix Fietkau 	    (force || !skb_queue_empty(&txqi->frags) ||
38412b4a6698SFelix Fietkau 	     txqi->tin.backlog_packets)) {
3842b4809e94SToke Høiland-Jørgensen 		/* If airtime accounting is active, always enqueue STAs at the
3843b4809e94SToke Høiland-Jørgensen 		 * head of the list to ensure that they only get moved to the
3844b4809e94SToke Høiland-Jørgensen 		 * back by the airtime DRR scheduler once they have a negative
3845b4809e94SToke Høiland-Jørgensen 		 * deficit. A station that already has a negative deficit will
3846b4809e94SToke Høiland-Jørgensen 		 * get immediately moved to the back of the list on the next
3847b4809e94SToke Høiland-Jørgensen 		 * call to ieee80211_next_txq().
3848b4809e94SToke Høiland-Jørgensen 		 */
3849c13cf5c1SLorenzo Bianconi 		if (txqi->txq.sta && local->airtime_flags &&
3850b4809e94SToke Høiland-Jørgensen 		    wiphy_ext_feature_isset(local->hw.wiphy,
3851b4809e94SToke Høiland-Jørgensen 					    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
3852b4809e94SToke Høiland-Jørgensen 			list_add(&txqi->schedule_order,
3853b4809e94SToke Høiland-Jørgensen 				 &local->active_txqs[txq->ac]);
3854b4809e94SToke Høiland-Jørgensen 		else
385518667600SToke Høiland-Jørgensen 			list_add_tail(&txqi->schedule_order,
385618667600SToke Høiland-Jørgensen 				      &local->active_txqs[txq->ac]);
385718667600SToke Høiland-Jørgensen 	}
385818667600SToke Høiland-Jørgensen 
3859390298e8SToke Høiland-Jørgensen 	spin_unlock_bh(&local->active_txq_lock[txq->ac]);
3860390298e8SToke Høiland-Jørgensen }
38612b4a6698SFelix Fietkau EXPORT_SYMBOL(__ieee80211_schedule_txq);
3862390298e8SToke Høiland-Jørgensen 
3863e908435eSLorenzo Bianconi DEFINE_STATIC_KEY_FALSE(aql_disable);
3864e908435eSLorenzo Bianconi 
38653ace10f5SKan Yan bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
38663ace10f5SKan Yan 				 struct ieee80211_txq *txq)
38673ace10f5SKan Yan {
38683ace10f5SKan Yan 	struct sta_info *sta;
38693ace10f5SKan Yan 	struct ieee80211_local *local = hw_to_local(hw);
38703ace10f5SKan Yan 
3871911bde0fSToke Høiland-Jørgensen 	if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
38723ace10f5SKan Yan 		return true;
38733ace10f5SKan Yan 
3874e908435eSLorenzo Bianconi 	if (static_branch_unlikely(&aql_disable))
3875e908435eSLorenzo Bianconi 		return true;
3876e908435eSLorenzo Bianconi 
38773ace10f5SKan Yan 	if (!txq->sta)
38783ace10f5SKan Yan 		return true;
38793ace10f5SKan Yan 
388073bc9e0aSJohannes Berg 	if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
388173bc9e0aSJohannes Berg 		return true;
388273bc9e0aSJohannes Berg 
38833ace10f5SKan Yan 	sta = container_of(txq->sta, struct sta_info, sta);
38843ace10f5SKan Yan 	if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
38853ace10f5SKan Yan 	    sta->airtime[txq->ac].aql_limit_low)
38863ace10f5SKan Yan 		return true;
38873ace10f5SKan Yan 
38883ace10f5SKan Yan 	if (atomic_read(&local->aql_total_pending_airtime) <
38893ace10f5SKan Yan 	    local->aql_threshold &&
38903ace10f5SKan Yan 	    atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
38913ace10f5SKan Yan 	    sta->airtime[txq->ac].aql_limit_high)
38923ace10f5SKan Yan 		return true;
38933ace10f5SKan Yan 
38943ace10f5SKan Yan 	return false;
38953ace10f5SKan Yan }
38963ace10f5SKan Yan EXPORT_SYMBOL(ieee80211_txq_airtime_check);
38973ace10f5SKan Yan 
3898b4809e94SToke Høiland-Jørgensen bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
3899b4809e94SToke Høiland-Jørgensen 				struct ieee80211_txq *txq)
3900b4809e94SToke Høiland-Jørgensen {
3901b4809e94SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
3902b4809e94SToke Høiland-Jørgensen 	struct txq_info *iter, *tmp, *txqi = to_txq_info(txq);
3903b4809e94SToke Høiland-Jørgensen 	struct sta_info *sta;
3904b4809e94SToke Høiland-Jørgensen 	u8 ac = txq->ac;
3905b4809e94SToke Høiland-Jørgensen 
39065b989c18SFelix Fietkau 	spin_lock_bh(&local->active_txq_lock[ac]);
3907b4809e94SToke Høiland-Jørgensen 
3908b4809e94SToke Høiland-Jørgensen 	if (!txqi->txq.sta)
3909b4809e94SToke Høiland-Jørgensen 		goto out;
3910b4809e94SToke Høiland-Jørgensen 
3911b4809e94SToke Høiland-Jørgensen 	if (list_empty(&txqi->schedule_order))
3912b4809e94SToke Høiland-Jørgensen 		goto out;
3913b4809e94SToke Høiland-Jørgensen 
3914b4809e94SToke Høiland-Jørgensen 	list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
3915b4809e94SToke Høiland-Jørgensen 				 schedule_order) {
3916b4809e94SToke Høiland-Jørgensen 		if (iter == txqi)
3917b4809e94SToke Høiland-Jørgensen 			break;
3918b4809e94SToke Høiland-Jørgensen 
3919b4809e94SToke Høiland-Jørgensen 		if (!iter->txq.sta) {
3920b4809e94SToke Høiland-Jørgensen 			list_move_tail(&iter->schedule_order,
3921b4809e94SToke Høiland-Jørgensen 				       &local->active_txqs[ac]);
3922b4809e94SToke Høiland-Jørgensen 			continue;
3923b4809e94SToke Høiland-Jørgensen 		}
3924b4809e94SToke Høiland-Jørgensen 		sta = container_of(iter->txq.sta, struct sta_info, sta);
3925b4809e94SToke Høiland-Jørgensen 		if (sta->airtime[ac].deficit < 0)
3926b4809e94SToke Høiland-Jørgensen 			sta->airtime[ac].deficit += sta->airtime_weight;
3927b4809e94SToke Høiland-Jørgensen 		list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
3928b4809e94SToke Høiland-Jørgensen 	}
3929b4809e94SToke Høiland-Jørgensen 
3930b4809e94SToke Høiland-Jørgensen 	sta = container_of(txqi->txq.sta, struct sta_info, sta);
3931b4809e94SToke Høiland-Jørgensen 	if (sta->airtime[ac].deficit >= 0)
3932b4809e94SToke Høiland-Jørgensen 		goto out;
3933b4809e94SToke Høiland-Jørgensen 
3934b4809e94SToke Høiland-Jørgensen 	sta->airtime[ac].deficit += sta->airtime_weight;
3935b4809e94SToke Høiland-Jørgensen 	list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
39365b989c18SFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
3937b4809e94SToke Høiland-Jørgensen 
3938b4809e94SToke Høiland-Jørgensen 	return false;
3939b4809e94SToke Høiland-Jørgensen out:
3940b4809e94SToke Høiland-Jørgensen 	if (!list_empty(&txqi->schedule_order))
3941b4809e94SToke Høiland-Jørgensen 		list_del_init(&txqi->schedule_order);
39425b989c18SFelix Fietkau 	spin_unlock_bh(&local->active_txq_lock[ac]);
3943b4809e94SToke Høiland-Jørgensen 
3944b4809e94SToke Høiland-Jørgensen 	return true;
3945b4809e94SToke Høiland-Jørgensen }
3946b4809e94SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_txq_may_transmit);
3947b4809e94SToke Høiland-Jørgensen 
394818667600SToke Høiland-Jørgensen void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
394918667600SToke Høiland-Jørgensen {
395018667600SToke Høiland-Jørgensen 	struct ieee80211_local *local = hw_to_local(hw);
395118667600SToke Høiland-Jørgensen 
395218667600SToke Høiland-Jørgensen 	spin_lock_bh(&local->active_txq_lock[ac]);
395318667600SToke Høiland-Jørgensen 	local->schedule_round[ac]++;
395418667600SToke Høiland-Jørgensen 	spin_unlock_bh(&local->active_txq_lock[ac]);
395518667600SToke Høiland-Jørgensen }
39565b989c18SFelix Fietkau EXPORT_SYMBOL(ieee80211_txq_schedule_start);
395718667600SToke Høiland-Jørgensen 
395808a46c64SFelix Fietkau static void
395908a46c64SFelix Fietkau ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
396008a46c64SFelix Fietkau 		     struct sta_info *sta,
396108a46c64SFelix Fietkau 		     struct sk_buff *skb)
396208a46c64SFelix Fietkau {
396308a46c64SFelix Fietkau 	struct rate_control_ref *ref = sdata->local->rate_ctrl;
396408a46c64SFelix Fietkau 	u16 tid;
396508a46c64SFelix Fietkau 
396608a46c64SFelix Fietkau 	if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER))
396708a46c64SFelix Fietkau 		return;
396808a46c64SFelix Fietkau 
396908a46c64SFelix Fietkau 	if (!sta || !sta->sta.ht_cap.ht_supported ||
397008a46c64SFelix Fietkau 	    !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO ||
397108a46c64SFelix Fietkau 	    skb->protocol == sdata->control_port_protocol)
397208a46c64SFelix Fietkau 		return;
397308a46c64SFelix Fietkau 
397408a46c64SFelix Fietkau 	tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
397508a46c64SFelix Fietkau 	if (likely(sta->ampdu_mlme.tid_tx[tid]))
397608a46c64SFelix Fietkau 		return;
397708a46c64SFelix Fietkau 
397808a46c64SFelix Fietkau 	ieee80211_start_tx_ba_session(&sta->sta, tid, 0);
397908a46c64SFelix Fietkau }
398008a46c64SFelix Fietkau 
39814c9451edSJohannes Berg void __ieee80211_subif_start_xmit(struct sk_buff *skb,
39824c9451edSJohannes Berg 				  struct net_device *dev,
398306016772SRajkumar Manoharan 				  u32 info_flags,
3984a7528198SMarkus Theil 				  u32 ctrl_flags,
3985a7528198SMarkus Theil 				  u64 *cookie)
39864c9451edSJohannes Berg {
39874c9451edSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
39881974da8bSFelix Fietkau 	struct ieee80211_local *local = sdata->local;
398997ffe757SJohannes Berg 	struct sta_info *sta;
399080616c0dSJohannes Berg 	struct sk_buff *next;
39914c9451edSJohannes Berg 
39924c9451edSJohannes Berg 	if (unlikely(skb->len < ETH_HLEN)) {
39934c9451edSJohannes Berg 		kfree_skb(skb);
39944c9451edSJohannes Berg 		return;
39954c9451edSJohannes Berg 	}
39964c9451edSJohannes Berg 
39974c9451edSJohannes Berg 	rcu_read_lock();
39984c9451edSJohannes Berg 
39992d981fddSJohannes Berg 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
40002d981fddSJohannes Berg 		goto out_free;
40014c9451edSJohannes Berg 
40021974da8bSFelix Fietkau 	if (IS_ERR(sta))
40031974da8bSFelix Fietkau 		sta = NULL;
40041974da8bSFelix Fietkau 
40051974da8bSFelix Fietkau 	if (local->ops->wake_tx_queue) {
40061974da8bSFelix Fietkau 		u16 queue = __ieee80211_select_queue(sdata, sta, skb);
40071974da8bSFelix Fietkau 		skb_set_queue_mapping(skb, queue);
4008180ac48eSFelix Fietkau 		skb_get_hash(skb);
40091974da8bSFelix Fietkau 	}
40101974da8bSFelix Fietkau 
401108a46c64SFelix Fietkau 	ieee80211_aggr_check(sdata, sta, skb);
401208a46c64SFelix Fietkau 
40131974da8bSFelix Fietkau 	if (sta) {
401417c18bf8SJohannes Berg 		struct ieee80211_fast_tx *fast_tx;
401517c18bf8SJohannes Berg 
401670e53669SWen Gong 		sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
401736148c2bSToke Høiland-Jørgensen 
401817c18bf8SJohannes Berg 		fast_tx = rcu_dereference(sta->fast_tx);
401917c18bf8SJohannes Berg 
402017c18bf8SJohannes Berg 		if (fast_tx &&
4021bb42f2d1SToke Høiland-Jørgensen 		    ieee80211_xmit_fast(sdata, sta, fast_tx, skb))
402217c18bf8SJohannes Berg 			goto out;
402317c18bf8SJohannes Berg 	}
402417c18bf8SJohannes Berg 
402580616c0dSJohannes Berg 	if (skb_is_gso(skb)) {
402680616c0dSJohannes Berg 		struct sk_buff *segs;
402780616c0dSJohannes Berg 
402880616c0dSJohannes Berg 		segs = skb_gso_segment(skb, 0);
402980616c0dSJohannes Berg 		if (IS_ERR(segs)) {
403080616c0dSJohannes Berg 			goto out_free;
403180616c0dSJohannes Berg 		} else if (segs) {
403280616c0dSJohannes Berg 			consume_skb(skb);
403380616c0dSJohannes Berg 			skb = segs;
403480616c0dSJohannes Berg 		}
403580616c0dSJohannes Berg 	} else {
4036680a0dabSJohannes Berg 		/* we cannot process non-linear frames on this path */
4037680a0dabSJohannes Berg 		if (skb_linearize(skb)) {
4038680a0dabSJohannes Berg 			kfree_skb(skb);
4039680a0dabSJohannes Berg 			goto out;
4040680a0dabSJohannes Berg 		}
4041680a0dabSJohannes Berg 
404280616c0dSJohannes Berg 		/* the frame could be fragmented, software-encrypted, and other
404380616c0dSJohannes Berg 		 * things so we cannot really handle checksum offload with it -
404480616c0dSJohannes Berg 		 * fix it up in software before we handle anything else.
40452d981fddSJohannes Berg 		 */
40462d981fddSJohannes Berg 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
40472d981fddSJohannes Berg 			skb_set_transport_header(skb,
40482d981fddSJohannes Berg 						 skb_checksum_start_offset(skb));
40492d981fddSJohannes Berg 			if (skb_checksum_help(skb))
40502d981fddSJohannes Berg 				goto out_free;
40512d981fddSJohannes Berg 		}
405280616c0dSJohannes Berg 	}
405380616c0dSJohannes Berg 
40549f3ef3d7SJason A. Donenfeld 	skb_list_walk_safe(skb, skb, next) {
40559f3ef3d7SJason A. Donenfeld 		skb_mark_not_on_list(skb);
40562d981fddSJohannes Berg 
40575af7fef3SMarkus Theil 		if (skb->protocol == sdata->control_port_protocol)
40585af7fef3SMarkus Theil 			ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
40595af7fef3SMarkus Theil 
406006016772SRajkumar Manoharan 		skb = ieee80211_build_hdr(sdata, skb, info_flags,
4061a7528198SMarkus Theil 					  sta, ctrl_flags, cookie);
40629f3ef3d7SJason A. Donenfeld 		if (IS_ERR(skb)) {
40639f3ef3d7SJason A. Donenfeld 			kfree_skb_list(next);
40644c9451edSJohannes Berg 			goto out;
40659f3ef3d7SJason A. Donenfeld 		}
40664c9451edSJohannes Berg 
406736ec144fSLev Stipakov 		dev_sw_netstats_tx_add(dev, 1, skb->len);
40684c9451edSJohannes Berg 
406908aca29aSMathy Vanhoef 		ieee80211_xmit(sdata, sta, skb);
407080616c0dSJohannes Berg 	}
40712d981fddSJohannes Berg 	goto out;
40722d981fddSJohannes Berg  out_free:
40732d981fddSJohannes Berg 	kfree_skb(skb);
40744c9451edSJohannes Berg  out:
40754c9451edSJohannes Berg 	rcu_read_unlock();
40764c9451edSJohannes Berg }
40774c9451edSJohannes Berg 
4078ebceec86SMichael Braun static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta)
4079ebceec86SMichael Braun {
4080ebceec86SMichael Braun 	struct ethhdr *eth;
4081ebceec86SMichael Braun 	int err;
4082ebceec86SMichael Braun 
4083ebceec86SMichael Braun 	err = skb_ensure_writable(skb, ETH_HLEN);
4084ebceec86SMichael Braun 	if (unlikely(err))
4085ebceec86SMichael Braun 		return err;
4086ebceec86SMichael Braun 
4087ebceec86SMichael Braun 	eth = (void *)skb->data;
4088ebceec86SMichael Braun 	ether_addr_copy(eth->h_dest, sta->sta.addr);
4089ebceec86SMichael Braun 
4090ebceec86SMichael Braun 	return 0;
4091ebceec86SMichael Braun }
4092ebceec86SMichael Braun 
4093ebceec86SMichael Braun static bool ieee80211_multicast_to_unicast(struct sk_buff *skb,
4094ebceec86SMichael Braun 					   struct net_device *dev)
4095ebceec86SMichael Braun {
4096ebceec86SMichael Braun 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4097ebceec86SMichael Braun 	const struct ethhdr *eth = (void *)skb->data;
4098ebceec86SMichael Braun 	const struct vlan_ethhdr *ethvlan = (void *)skb->data;
4099ebceec86SMichael Braun 	__be16 ethertype;
4100ebceec86SMichael Braun 
4101ebceec86SMichael Braun 	if (likely(!is_multicast_ether_addr(eth->h_dest)))
4102ebceec86SMichael Braun 		return false;
4103ebceec86SMichael Braun 
4104ebceec86SMichael Braun 	switch (sdata->vif.type) {
4105ebceec86SMichael Braun 	case NL80211_IFTYPE_AP_VLAN:
4106ebceec86SMichael Braun 		if (sdata->u.vlan.sta)
4107ebceec86SMichael Braun 			return false;
4108ebceec86SMichael Braun 		if (sdata->wdev.use_4addr)
4109ebceec86SMichael Braun 			return false;
4110fc0561dcSGustavo A. R. Silva 		fallthrough;
4111ebceec86SMichael Braun 	case NL80211_IFTYPE_AP:
4112ebceec86SMichael Braun 		/* check runtime toggle for this bss */
4113ebceec86SMichael Braun 		if (!sdata->bss->multicast_to_unicast)
4114ebceec86SMichael Braun 			return false;
4115ebceec86SMichael Braun 		break;
4116ebceec86SMichael Braun 	default:
4117ebceec86SMichael Braun 		return false;
4118ebceec86SMichael Braun 	}
4119ebceec86SMichael Braun 
4120ebceec86SMichael Braun 	/* multicast to unicast conversion only for some payload */
4121ebceec86SMichael Braun 	ethertype = eth->h_proto;
4122ebceec86SMichael Braun 	if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN)
4123ebceec86SMichael Braun 		ethertype = ethvlan->h_vlan_encapsulated_proto;
4124ebceec86SMichael Braun 	switch (ethertype) {
4125ebceec86SMichael Braun 	case htons(ETH_P_ARP):
4126ebceec86SMichael Braun 	case htons(ETH_P_IP):
4127ebceec86SMichael Braun 	case htons(ETH_P_IPV6):
4128ebceec86SMichael Braun 		break;
4129ebceec86SMichael Braun 	default:
4130ebceec86SMichael Braun 		return false;
4131ebceec86SMichael Braun 	}
4132ebceec86SMichael Braun 
4133ebceec86SMichael Braun 	return true;
4134ebceec86SMichael Braun }
4135ebceec86SMichael Braun 
4136ebceec86SMichael Braun static void
4137ebceec86SMichael Braun ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev,
4138ebceec86SMichael Braun 			     struct sk_buff_head *queue)
4139ebceec86SMichael Braun {
4140ebceec86SMichael Braun 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4141ebceec86SMichael Braun 	struct ieee80211_local *local = sdata->local;
4142ebceec86SMichael Braun 	const struct ethhdr *eth = (struct ethhdr *)skb->data;
4143ebceec86SMichael Braun 	struct sta_info *sta, *first = NULL;
4144ebceec86SMichael Braun 	struct sk_buff *cloned_skb;
4145ebceec86SMichael Braun 
4146ebceec86SMichael Braun 	rcu_read_lock();
4147ebceec86SMichael Braun 
4148ebceec86SMichael Braun 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
4149ebceec86SMichael Braun 		if (sdata != sta->sdata)
4150ebceec86SMichael Braun 			/* AP-VLAN mismatch */
4151ebceec86SMichael Braun 			continue;
4152ebceec86SMichael Braun 		if (unlikely(ether_addr_equal(eth->h_source, sta->sta.addr)))
4153ebceec86SMichael Braun 			/* do not send back to source */
4154ebceec86SMichael Braun 			continue;
4155ebceec86SMichael Braun 		if (!first) {
4156ebceec86SMichael Braun 			first = sta;
4157ebceec86SMichael Braun 			continue;
4158ebceec86SMichael Braun 		}
4159ebceec86SMichael Braun 		cloned_skb = skb_clone(skb, GFP_ATOMIC);
4160ebceec86SMichael Braun 		if (!cloned_skb)
4161ebceec86SMichael Braun 			goto multicast;
4162ebceec86SMichael Braun 		if (unlikely(ieee80211_change_da(cloned_skb, sta))) {
4163ebceec86SMichael Braun 			dev_kfree_skb(cloned_skb);
4164ebceec86SMichael Braun 			goto multicast;
4165ebceec86SMichael Braun 		}
4166ebceec86SMichael Braun 		__skb_queue_tail(queue, cloned_skb);
4167ebceec86SMichael Braun 	}
4168ebceec86SMichael Braun 
4169ebceec86SMichael Braun 	if (likely(first)) {
4170ebceec86SMichael Braun 		if (unlikely(ieee80211_change_da(skb, first)))
4171ebceec86SMichael Braun 			goto multicast;
4172ebceec86SMichael Braun 		__skb_queue_tail(queue, skb);
4173ebceec86SMichael Braun 	} else {
4174ebceec86SMichael Braun 		/* no STA connected, drop */
4175ebceec86SMichael Braun 		kfree_skb(skb);
4176ebceec86SMichael Braun 		skb = NULL;
4177ebceec86SMichael Braun 	}
4178ebceec86SMichael Braun 
4179ebceec86SMichael Braun 	goto out;
4180ebceec86SMichael Braun multicast:
4181ebceec86SMichael Braun 	__skb_queue_purge(queue);
4182ebceec86SMichael Braun 	__skb_queue_tail(queue, skb);
4183ebceec86SMichael Braun out:
4184ebceec86SMichael Braun 	rcu_read_unlock();
4185ebceec86SMichael Braun }
4186ebceec86SMichael Braun 
41874c9451edSJohannes Berg /**
41884c9451edSJohannes Berg  * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
41894c9451edSJohannes Berg  * @skb: packet to be sent
41904c9451edSJohannes Berg  * @dev: incoming interface
41914c9451edSJohannes Berg  *
41924c9451edSJohannes Berg  * On failure skb will be freed.
41934c9451edSJohannes Berg  */
419424d342c5SLiad Kaufman netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
419524d342c5SLiad Kaufman 				       struct net_device *dev)
419624d342c5SLiad Kaufman {
4197ebceec86SMichael Braun 	if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
4198ebceec86SMichael Braun 		struct sk_buff_head queue;
4199ebceec86SMichael Braun 
4200ebceec86SMichael Braun 		__skb_queue_head_init(&queue);
4201ebceec86SMichael Braun 		ieee80211_convert_to_unicast(skb, dev, &queue);
4202ebceec86SMichael Braun 		while ((skb = __skb_dequeue(&queue)))
4203a7528198SMarkus Theil 			__ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
4204ebceec86SMichael Braun 	} else {
4205a7528198SMarkus Theil 		__ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
4206ebceec86SMichael Braun 	}
4207ebceec86SMichael Braun 
420824d342c5SLiad Kaufman 	return NETDEV_TX_OK;
420924d342c5SLiad Kaufman }
4210e2ebc74dSJohannes Berg 
421150ff477aSJohn Crispin static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
421250ff477aSJohn Crispin 			      struct sk_buff *skb, int led_len,
421350ff477aSJohn Crispin 			      struct sta_info *sta,
421450ff477aSJohn Crispin 			      bool txpending)
421550ff477aSJohn Crispin {
421650ff477aSJohn Crispin 	struct ieee80211_local *local = sdata->local;
421750ff477aSJohn Crispin 	struct ieee80211_tx_control control = {};
421850ff477aSJohn Crispin 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
421950ff477aSJohn Crispin 	struct ieee80211_sta *pubsta = NULL;
422050ff477aSJohn Crispin 	unsigned long flags;
422150ff477aSJohn Crispin 	int q = info->hw_queue;
422250ff477aSJohn Crispin 
4223196900fdSLorenzo Bianconi 	if (sta)
4224196900fdSLorenzo Bianconi 		sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift);
4225196900fdSLorenzo Bianconi 
422650ff477aSJohn Crispin 	if (ieee80211_queue_skb(local, sdata, sta, skb))
422750ff477aSJohn Crispin 		return true;
422850ff477aSJohn Crispin 
422950ff477aSJohn Crispin 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
423050ff477aSJohn Crispin 
423150ff477aSJohn Crispin 	if (local->queue_stop_reasons[q] ||
423250ff477aSJohn Crispin 	    (!txpending && !skb_queue_empty(&local->pending[q]))) {
423350ff477aSJohn Crispin 		if (txpending)
423450ff477aSJohn Crispin 			skb_queue_head(&local->pending[q], skb);
423550ff477aSJohn Crispin 		else
423650ff477aSJohn Crispin 			skb_queue_tail(&local->pending[q], skb);
423750ff477aSJohn Crispin 
423850ff477aSJohn Crispin 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
423950ff477aSJohn Crispin 
424050ff477aSJohn Crispin 		return false;
424150ff477aSJohn Crispin 	}
424250ff477aSJohn Crispin 
424350ff477aSJohn Crispin 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
424450ff477aSJohn Crispin 
424550ff477aSJohn Crispin 	if (sta && sta->uploaded)
424650ff477aSJohn Crispin 		pubsta = &sta->sta;
424750ff477aSJohn Crispin 
424850ff477aSJohn Crispin 	control.sta = pubsta;
424950ff477aSJohn Crispin 
425050ff477aSJohn Crispin 	drv_tx(local, &control, skb);
425150ff477aSJohn Crispin 
425250ff477aSJohn Crispin 	return true;
425350ff477aSJohn Crispin }
425450ff477aSJohn Crispin 
425550ff477aSJohn Crispin static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
425650ff477aSJohn Crispin 				struct net_device *dev, struct sta_info *sta,
42576aea26ceSFelix Fietkau 				struct ieee80211_key *key, struct sk_buff *skb)
425850ff477aSJohn Crispin {
425950ff477aSJohn Crispin 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
426050ff477aSJohn Crispin 	struct ieee80211_local *local = sdata->local;
426196ae9cd0SFelix Fietkau 	struct tid_ampdu_tx *tid_tx;
426296ae9cd0SFelix Fietkau 	u8 tid;
426350ff477aSJohn Crispin 
42645f8d69eaSFelix Fietkau 	if (local->ops->wake_tx_queue) {
42655f8d69eaSFelix Fietkau 		u16 queue = __ieee80211_select_queue(sdata, sta, skb);
42665f8d69eaSFelix Fietkau 		skb_set_queue_mapping(skb, queue);
42675f8d69eaSFelix Fietkau 		skb_get_hash(skb);
42685f8d69eaSFelix Fietkau 	}
42695f8d69eaSFelix Fietkau 
427050ff477aSJohn Crispin 	if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
427150ff477aSJohn Crispin 	    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
427250ff477aSJohn Crispin 		goto out_free;
427350ff477aSJohn Crispin 
4274e61fbfcaSVasanthakumar Thiagarajan 	memset(info, 0, sizeof(*info));
4275e61fbfcaSVasanthakumar Thiagarajan 
427608a46c64SFelix Fietkau 	ieee80211_aggr_check(sdata, sta, skb);
427708a46c64SFelix Fietkau 
427896ae9cd0SFelix Fietkau 	tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
427996ae9cd0SFelix Fietkau 	tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
428096ae9cd0SFelix Fietkau 	if (tid_tx) {
428196ae9cd0SFelix Fietkau 		if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
428296ae9cd0SFelix Fietkau 			/* fall back to non-offload slow path */
428396ae9cd0SFelix Fietkau 			__ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
428496ae9cd0SFelix Fietkau 			return;
428596ae9cd0SFelix Fietkau 		}
428696ae9cd0SFelix Fietkau 
428796ae9cd0SFelix Fietkau 		info->flags |= IEEE80211_TX_CTL_AMPDU;
428896ae9cd0SFelix Fietkau 		if (tid_tx->timeout)
428996ae9cd0SFelix Fietkau 			tid_tx->last_tx = jiffies;
429096ae9cd0SFelix Fietkau 	}
429196ae9cd0SFelix Fietkau 
4292aea6a3f0SFelix Fietkau 	if (unlikely(skb->sk &&
429350ff477aSJohn Crispin 		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
4294e61fbfcaSVasanthakumar Thiagarajan 		info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
4295e61fbfcaSVasanthakumar Thiagarajan 							     &info->flags, NULL);
429650ff477aSJohn Crispin 
429750ff477aSJohn Crispin 	info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
429850ff477aSJohn Crispin 
429936ec144fSLev Stipakov 	dev_sw_netstats_tx_add(dev, 1, skb->len);
430050ff477aSJohn Crispin 
430150ff477aSJohn Crispin 	sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
430250ff477aSJohn Crispin 	sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
430350ff477aSJohn Crispin 
430450ff477aSJohn Crispin 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
430550ff477aSJohn Crispin 		sdata = container_of(sdata->bss,
430650ff477aSJohn Crispin 				     struct ieee80211_sub_if_data, u.ap);
430750ff477aSJohn Crispin 
4308cc20ff2cSFelix Fietkau 	info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
430950ff477aSJohn Crispin 	info->control.vif = &sdata->vif;
431050ff477aSJohn Crispin 
4311ae045152SFelix Fietkau 	if (key)
4312ae045152SFelix Fietkau 		info->control.hw_key = &key->conf;
4313ae045152SFelix Fietkau 
431450ff477aSJohn Crispin 	ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
431550ff477aSJohn Crispin 
431650ff477aSJohn Crispin 	return;
431750ff477aSJohn Crispin 
431850ff477aSJohn Crispin out_free:
431950ff477aSJohn Crispin 	kfree_skb(skb);
432050ff477aSJohn Crispin }
432150ff477aSJohn Crispin 
432250ff477aSJohn Crispin netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
432350ff477aSJohn Crispin 					    struct net_device *dev)
432450ff477aSJohn Crispin {
432550ff477aSJohn Crispin 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4326aea6a3f0SFelix Fietkau 	struct ethhdr *ehdr = (struct ethhdr *)skb->data;
43276aea26ceSFelix Fietkau 	struct ieee80211_key *key;
432850ff477aSJohn Crispin 	struct sta_info *sta;
432950ff477aSJohn Crispin 
433050ff477aSJohn Crispin 	if (unlikely(skb->len < ETH_HLEN)) {
433150ff477aSJohn Crispin 		kfree_skb(skb);
433250ff477aSJohn Crispin 		return NETDEV_TX_OK;
433350ff477aSJohn Crispin 	}
433450ff477aSJohn Crispin 
433550ff477aSJohn Crispin 	rcu_read_lock();
433650ff477aSJohn Crispin 
43376aea26ceSFelix Fietkau 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
433850ff477aSJohn Crispin 		kfree_skb(skb);
43396aea26ceSFelix Fietkau 		goto out;
43406aea26ceSFelix Fietkau 	}
43416aea26ceSFelix Fietkau 
43426aea26ceSFelix Fietkau 	if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
4343aea6a3f0SFelix Fietkau 	    !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
4344aea6a3f0SFelix Fietkau 	    sdata->control_port_protocol == ehdr->h_proto))
4345b101dd2dSFelix Fietkau 		goto skip_offload;
4346b101dd2dSFelix Fietkau 
4347b101dd2dSFelix Fietkau 	key = rcu_dereference(sta->ptk[sta->ptk_idx]);
4348b101dd2dSFelix Fietkau 	if (!key)
4349b101dd2dSFelix Fietkau 		key = rcu_dereference(sdata->default_unicast_key);
4350b101dd2dSFelix Fietkau 
4351b101dd2dSFelix Fietkau 	if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
43526aea26ceSFelix Fietkau 		    key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
4353b101dd2dSFelix Fietkau 		goto skip_offload;
435450ff477aSJohn Crispin 
43556aea26ceSFelix Fietkau 	ieee80211_8023_xmit(sdata, dev, sta, key, skb);
4356b101dd2dSFelix Fietkau 	goto out;
43576aea26ceSFelix Fietkau 
4358b101dd2dSFelix Fietkau skip_offload:
4359b101dd2dSFelix Fietkau 	ieee80211_subif_start_xmit(skb, dev);
43606aea26ceSFelix Fietkau out:
436150ff477aSJohn Crispin 	rcu_read_unlock();
436250ff477aSJohn Crispin 
436350ff477aSJohn Crispin 	return NETDEV_TX_OK;
436450ff477aSJohn Crispin }
436550ff477aSJohn Crispin 
43667528ec57SJohannes Berg struct sk_buff *
43677528ec57SJohannes Berg ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
43687528ec57SJohannes Berg 			      struct sk_buff *skb, u32 info_flags)
43697528ec57SJohannes Berg {
43707528ec57SJohannes Berg 	struct ieee80211_hdr *hdr;
43717528ec57SJohannes Berg 	struct ieee80211_tx_data tx = {
43727528ec57SJohannes Berg 		.local = sdata->local,
43737528ec57SJohannes Berg 		.sdata = sdata,
43747528ec57SJohannes Berg 	};
437597ffe757SJohannes Berg 	struct sta_info *sta;
43767528ec57SJohannes Berg 
43777528ec57SJohannes Berg 	rcu_read_lock();
43787528ec57SJohannes Berg 
437997ffe757SJohannes Berg 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
438097ffe757SJohannes Berg 		kfree_skb(skb);
438197ffe757SJohannes Berg 		skb = ERR_PTR(-EINVAL);
438297ffe757SJohannes Berg 		goto out;
438397ffe757SJohannes Berg 	}
438497ffe757SJohannes Berg 
4385a7528198SMarkus Theil 	skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0, NULL);
43867528ec57SJohannes Berg 	if (IS_ERR(skb))
43877528ec57SJohannes Berg 		goto out;
43887528ec57SJohannes Berg 
43897528ec57SJohannes Berg 	hdr = (void *)skb->data;
43907528ec57SJohannes Berg 	tx.sta = sta_info_get(sdata, hdr->addr1);
43917528ec57SJohannes Berg 	tx.skb = skb;
43927528ec57SJohannes Berg 
43937528ec57SJohannes Berg 	if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
43947528ec57SJohannes Berg 		rcu_read_unlock();
43957528ec57SJohannes Berg 		kfree_skb(skb);
43967528ec57SJohannes Berg 		return ERR_PTR(-EINVAL);
43977528ec57SJohannes Berg 	}
43987528ec57SJohannes Berg 
43997528ec57SJohannes Berg out:
44007528ec57SJohannes Berg 	rcu_read_unlock();
44017528ec57SJohannes Berg 	return skb;
44027528ec57SJohannes Berg }
44037528ec57SJohannes Berg 
4404e2530083SJohannes Berg /*
4405e2530083SJohannes Berg  * ieee80211_clear_tx_pending may not be called in a context where
4406e2530083SJohannes Berg  * it is possible that it packets could come in again.
4407e2530083SJohannes Berg  */
4408e2ebc74dSJohannes Berg void ieee80211_clear_tx_pending(struct ieee80211_local *local)
4409e2ebc74dSJohannes Berg {
44101f98ab7fSFelix Fietkau 	struct sk_buff *skb;
44112de8e0d9SJohannes Berg 	int i;
4412e2ebc74dSJohannes Berg 
44131f98ab7fSFelix Fietkau 	for (i = 0; i < local->hw.queues; i++) {
44141f98ab7fSFelix Fietkau 		while ((skb = skb_dequeue(&local->pending[i])) != NULL)
44151f98ab7fSFelix Fietkau 			ieee80211_free_txskb(&local->hw, skb);
44161f98ab7fSFelix Fietkau 	}
4417e2ebc74dSJohannes Berg }
4418e2ebc74dSJohannes Berg 
44197bb45683SJohannes Berg /*
44207bb45683SJohannes Berg  * Returns false if the frame couldn't be transmitted but was queued instead,
44217bb45683SJohannes Berg  * which in this case means re-queued -- take as an indication to stop sending
44227bb45683SJohannes Berg  * more pending frames.
44237bb45683SJohannes Berg  */
4424cd8ffc80SJohannes Berg static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
4425cd8ffc80SJohannes Berg 				     struct sk_buff *skb)
4426cd8ffc80SJohannes Berg {
4427cd8ffc80SJohannes Berg 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4428cd8ffc80SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
4429cd8ffc80SJohannes Berg 	struct sta_info *sta;
4430cd8ffc80SJohannes Berg 	struct ieee80211_hdr *hdr;
44317bb45683SJohannes Berg 	bool result;
443255de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
4433cd8ffc80SJohannes Berg 
44345061b0c2SJohannes Berg 	sdata = vif_to_sdata(info->control.vif);
4435cd8ffc80SJohannes Berg 
4436cc20ff2cSFelix Fietkau 	if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
443755de908aSJohannes Berg 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
443855de908aSJohannes Berg 		if (unlikely(!chanctx_conf)) {
443955de908aSJohannes Berg 			dev_kfree_skb(skb);
444055de908aSJohannes Berg 			return true;
444155de908aSJohannes Berg 		}
444273c4e195SJohannes Berg 		info->band = chanctx_conf->def.chan->band;
444308aca29aSMathy Vanhoef 		result = ieee80211_tx(sdata, NULL, skb, true);
4444cc20ff2cSFelix Fietkau 	} else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
444550ff477aSJohn Crispin 		if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
444650ff477aSJohn Crispin 			dev_kfree_skb(skb);
444750ff477aSJohn Crispin 			return true;
444850ff477aSJohn Crispin 		}
444950ff477aSJohn Crispin 
445050ff477aSJohn Crispin 		if (IS_ERR(sta) || (sta && !sta->uploaded))
445150ff477aSJohn Crispin 			sta = NULL;
445250ff477aSJohn Crispin 
445350ff477aSJohn Crispin 		result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
4454cd8ffc80SJohannes Berg 	} else {
4455252b86c4SJohannes Berg 		struct sk_buff_head skbs;
4456252b86c4SJohannes Berg 
4457252b86c4SJohannes Berg 		__skb_queue_head_init(&skbs);
4458252b86c4SJohannes Berg 		__skb_queue_tail(&skbs, skb);
4459252b86c4SJohannes Berg 
4460cd8ffc80SJohannes Berg 		hdr = (struct ieee80211_hdr *)skb->data;
4461abe60632SJohannes Berg 		sta = sta_info_get(sdata, hdr->addr1);
4462cd8ffc80SJohannes Berg 
446374e4dbfdSJohannes Berg 		result = __ieee80211_tx(local, &skbs, skb->len, sta, true);
4464cd8ffc80SJohannes Berg 	}
4465cd8ffc80SJohannes Berg 
4466cd8ffc80SJohannes Berg 	return result;
4467cd8ffc80SJohannes Berg }
4468cd8ffc80SJohannes Berg 
4469e2530083SJohannes Berg /*
44703b8d81e0SJohannes Berg  * Transmit all pending packets. Called from tasklet.
4471e2530083SJohannes Berg  */
4472da1cad73SAllen Pais void ieee80211_tx_pending(struct tasklet_struct *t)
4473e2ebc74dSJohannes Berg {
4474da1cad73SAllen Pais 	struct ieee80211_local *local = from_tasklet(local, t,
4475da1cad73SAllen Pais 						     tx_pending_tasklet);
44762a577d98SJohannes Berg 	unsigned long flags;
4477cd8ffc80SJohannes Berg 	int i;
44783b8d81e0SJohannes Berg 	bool txok;
4479e2ebc74dSJohannes Berg 
4480f0e72851SJohannes Berg 	rcu_read_lock();
44812a577d98SJohannes Berg 
44823b8d81e0SJohannes Berg 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
4483176be728SJohannes Berg 	for (i = 0; i < local->hw.queues; i++) {
44842a577d98SJohannes Berg 		/*
44852a577d98SJohannes Berg 		 * If queue is stopped by something other than due to pending
44862a577d98SJohannes Berg 		 * frames, or we have no pending frames, proceed to next queue.
44872a577d98SJohannes Berg 		 */
44883b8d81e0SJohannes Berg 		if (local->queue_stop_reasons[i] ||
44892a577d98SJohannes Berg 		    skb_queue_empty(&local->pending[i]))
4490e2ebc74dSJohannes Berg 			continue;
4491e2530083SJohannes Berg 
44922a577d98SJohannes Berg 		while (!skb_queue_empty(&local->pending[i])) {
44933b8d81e0SJohannes Berg 			struct sk_buff *skb = __skb_dequeue(&local->pending[i]);
44945061b0c2SJohannes Berg 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
44955061b0c2SJohannes Berg 
4496a7bc376cSJohannes Berg 			if (WARN_ON(!info->control.vif)) {
4497c3e7724bSFelix Fietkau 				ieee80211_free_txskb(&local->hw, skb);
4498a7bc376cSJohannes Berg 				continue;
4499a7bc376cSJohannes Berg 			}
4500a7bc376cSJohannes Berg 
45013b8d81e0SJohannes Berg 			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
45023b8d81e0SJohannes Berg 						flags);
45032a577d98SJohannes Berg 
45043b8d81e0SJohannes Berg 			txok = ieee80211_tx_pending_skb(local, skb);
45053b8d81e0SJohannes Berg 			spin_lock_irqsave(&local->queue_stop_reason_lock,
45063b8d81e0SJohannes Berg 					  flags);
45073b8d81e0SJohannes Berg 			if (!txok)
45082a577d98SJohannes Berg 				break;
4509e2ebc74dSJohannes Berg 		}
45107236fe29SJohannes Berg 
45117236fe29SJohannes Berg 		if (skb_queue_empty(&local->pending[i]))
45123a25a8c8SJohannes Berg 			ieee80211_propagate_queue_wake(local, i);
4513e2ebc74dSJohannes Berg 	}
45143b8d81e0SJohannes Berg 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
45152a577d98SJohannes Berg 
4516f0e72851SJohannes Berg 	rcu_read_unlock();
4517e2ebc74dSJohannes Berg }
4518e2ebc74dSJohannes Berg 
4519e2ebc74dSJohannes Berg /* functions for drivers to get certain frames */
4520e2ebc74dSJohannes Berg 
4521eac70c13SMarco Porsch static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
45226ec8c332SAndrei Otcheretianski 				       struct ps_data *ps, struct sk_buff *skb,
45236ec8c332SAndrei Otcheretianski 				       bool is_template)
4524e2ebc74dSJohannes Berg {
4525e2ebc74dSJohannes Berg 	u8 *pos, *tim;
4526e2ebc74dSJohannes Berg 	int aid0 = 0;
4527e2ebc74dSJohannes Berg 	int i, have_bits = 0, n1, n2;
4528e2ebc74dSJohannes Berg 
4529e2ebc74dSJohannes Berg 	/* Generate bitmap for TIM only if there are any STAs in power save
4530e2ebc74dSJohannes Berg 	 * mode. */
4531d012a605SMarco Porsch 	if (atomic_read(&ps->num_sta_ps) > 0)
4532e2ebc74dSJohannes Berg 		/* in the hope that this is faster than
4533e2ebc74dSJohannes Berg 		 * checking byte-for-byte */
4534d012a605SMarco Porsch 		have_bits = !bitmap_empty((unsigned long *)ps->tim,
4535e2ebc74dSJohannes Berg 					  IEEE80211_MAX_AID+1);
45366ec8c332SAndrei Otcheretianski 	if (!is_template) {
4537d012a605SMarco Porsch 		if (ps->dtim_count == 0)
4538d012a605SMarco Porsch 			ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
4539e2ebc74dSJohannes Berg 		else
4540d012a605SMarco Porsch 			ps->dtim_count--;
45416ec8c332SAndrei Otcheretianski 	}
4542e2ebc74dSJohannes Berg 
45434df864c1SJohannes Berg 	tim = pos = skb_put(skb, 6);
4544e2ebc74dSJohannes Berg 	*pos++ = WLAN_EID_TIM;
4545e2ebc74dSJohannes Berg 	*pos++ = 4;
4546d012a605SMarco Porsch 	*pos++ = ps->dtim_count;
45478860020eSJohannes Berg 	*pos++ = sdata->vif.bss_conf.dtim_period;
4548e2ebc74dSJohannes Berg 
4549d012a605SMarco Porsch 	if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf))
4550e2ebc74dSJohannes Berg 		aid0 = 1;
4551e2ebc74dSJohannes Berg 
4552d012a605SMarco Porsch 	ps->dtim_bc_mc = aid0 == 1;
4553512119b3SChristian Lamparter 
4554e2ebc74dSJohannes Berg 	if (have_bits) {
4555e2ebc74dSJohannes Berg 		/* Find largest even number N1 so that bits numbered 1 through
4556e2ebc74dSJohannes Berg 		 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
4557e2ebc74dSJohannes Berg 		 * (N2 + 1) x 8 through 2007 are 0. */
4558e2ebc74dSJohannes Berg 		n1 = 0;
4559e2ebc74dSJohannes Berg 		for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
4560d012a605SMarco Porsch 			if (ps->tim[i]) {
4561e2ebc74dSJohannes Berg 				n1 = i & 0xfe;
4562e2ebc74dSJohannes Berg 				break;
4563e2ebc74dSJohannes Berg 			}
4564e2ebc74dSJohannes Berg 		}
4565e2ebc74dSJohannes Berg 		n2 = n1;
4566e2ebc74dSJohannes Berg 		for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
4567d012a605SMarco Porsch 			if (ps->tim[i]) {
4568e2ebc74dSJohannes Berg 				n2 = i;
4569e2ebc74dSJohannes Berg 				break;
4570e2ebc74dSJohannes Berg 			}
4571e2ebc74dSJohannes Berg 		}
4572e2ebc74dSJohannes Berg 
4573e2ebc74dSJohannes Berg 		/* Bitmap control */
4574e2ebc74dSJohannes Berg 		*pos++ = n1 | aid0;
4575e2ebc74dSJohannes Berg 		/* Part Virt Bitmap */
45765220da39SEliad Peller 		skb_put(skb, n2 - n1);
4577d012a605SMarco Porsch 		memcpy(pos, ps->tim + n1, n2 - n1 + 1);
4578e2ebc74dSJohannes Berg 
4579e2ebc74dSJohannes Berg 		tim[1] = n2 - n1 + 4;
4580e2ebc74dSJohannes Berg 	} else {
4581e2ebc74dSJohannes Berg 		*pos++ = aid0; /* Bitmap control */
4582e2ebc74dSJohannes Berg 		*pos++ = 0; /* Part Virt Bitmap */
4583e2ebc74dSJohannes Berg 	}
4584e2ebc74dSJohannes Berg }
4585e2ebc74dSJohannes Berg 
4586eac70c13SMarco Porsch static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
45876ec8c332SAndrei Otcheretianski 				    struct ps_data *ps, struct sk_buff *skb,
45886ec8c332SAndrei Otcheretianski 				    bool is_template)
4589eac70c13SMarco Porsch {
4590eac70c13SMarco Porsch 	struct ieee80211_local *local = sdata->local;
4591eac70c13SMarco Porsch 
4592eac70c13SMarco Porsch 	/*
4593eac70c13SMarco Porsch 	 * Not very nice, but we want to allow the driver to call
4594eac70c13SMarco Porsch 	 * ieee80211_beacon_get() as a response to the set_tim()
4595eac70c13SMarco Porsch 	 * callback. That, however, is already invoked under the
4596eac70c13SMarco Porsch 	 * sta_lock to guarantee consistent and race-free update
4597eac70c13SMarco Porsch 	 * of the tim bitmap in mac80211 and the driver.
4598eac70c13SMarco Porsch 	 */
4599eac70c13SMarco Porsch 	if (local->tim_in_locked_section) {
46006ec8c332SAndrei Otcheretianski 		__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
4601eac70c13SMarco Porsch 	} else {
46021b91731dSJohannes Berg 		spin_lock_bh(&local->tim_lock);
46036ec8c332SAndrei Otcheretianski 		__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
46041b91731dSJohannes Berg 		spin_unlock_bh(&local->tim_lock);
4605eac70c13SMarco Porsch 	}
4606eac70c13SMarco Porsch 
4607eac70c13SMarco Porsch 	return 0;
4608eac70c13SMarco Porsch }
4609eac70c13SMarco Porsch 
46108552a434SJohn Crispin static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
461173da7d5bSSimon Wunderlich 					struct beacon_data *beacon)
461273da7d5bSSimon Wunderlich {
461373da7d5bSSimon Wunderlich 	struct probe_resp *resp;
4614cd7760e6SSimon Wunderlich 	u8 *beacon_data;
4615cd7760e6SSimon Wunderlich 	size_t beacon_data_len;
46160d06d9baSAndrei Otcheretianski 	int i;
46178552a434SJohn Crispin 	u8 count = beacon->cntdwn_current_counter;
461873da7d5bSSimon Wunderlich 
4619cd7760e6SSimon Wunderlich 	switch (sdata->vif.type) {
4620cd7760e6SSimon Wunderlich 	case NL80211_IFTYPE_AP:
4621cd7760e6SSimon Wunderlich 		beacon_data = beacon->tail;
4622cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->tail_len;
4623cd7760e6SSimon Wunderlich 		break;
4624cd7760e6SSimon Wunderlich 	case NL80211_IFTYPE_ADHOC:
4625cd7760e6SSimon Wunderlich 		beacon_data = beacon->head;
4626cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->head_len;
4627cd7760e6SSimon Wunderlich 		break;
4628b8456a14SChun-Yeow Yeoh 	case NL80211_IFTYPE_MESH_POINT:
4629b8456a14SChun-Yeow Yeoh 		beacon_data = beacon->head;
4630b8456a14SChun-Yeow Yeoh 		beacon_data_len = beacon->head_len;
4631b8456a14SChun-Yeow Yeoh 		break;
4632cd7760e6SSimon Wunderlich 	default:
4633cd7760e6SSimon Wunderlich 		return;
4634cd7760e6SSimon Wunderlich 	}
46350d06d9baSAndrei Otcheretianski 
463673da7d5bSSimon Wunderlich 	rcu_read_lock();
46378552a434SJohn Crispin 	for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) {
463873da7d5bSSimon Wunderlich 		resp = rcu_dereference(sdata->u.ap.probe_resp);
463973da7d5bSSimon Wunderlich 
46408552a434SJohn Crispin 		if (beacon->cntdwn_counter_offsets[i]) {
46418552a434SJohn Crispin 			if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >=
4642af296bdbSMichal Kazior 					 beacon_data_len)) {
464373da7d5bSSimon Wunderlich 				rcu_read_unlock();
464473da7d5bSSimon Wunderlich 				return;
464573da7d5bSSimon Wunderlich 			}
4646af296bdbSMichal Kazior 
46478552a434SJohn Crispin 			beacon_data[beacon->cntdwn_counter_offsets[i]] = count;
4648af296bdbSMichal Kazior 		}
4649af296bdbSMichal Kazior 
4650af296bdbSMichal Kazior 		if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
46518552a434SJohn Crispin 			resp->data[resp->cntdwn_counter_offsets[i]] = count;
4652af296bdbSMichal Kazior 	}
465373da7d5bSSimon Wunderlich 	rcu_read_unlock();
465473da7d5bSSimon Wunderlich }
46551af586c9SAndrei Otcheretianski 
46568552a434SJohn Crispin static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)
4657e996ec2aSWojciech Dubowik {
46588552a434SJohn Crispin 	beacon->cntdwn_current_counter--;
4659e996ec2aSWojciech Dubowik 
4660e996ec2aSWojciech Dubowik 	/* the counter should never reach 0 */
46618552a434SJohn Crispin 	WARN_ON_ONCE(!beacon->cntdwn_current_counter);
4662e996ec2aSWojciech Dubowik 
46638552a434SJohn Crispin 	return beacon->cntdwn_current_counter;
4664e996ec2aSWojciech Dubowik }
4665e996ec2aSWojciech Dubowik 
46668552a434SJohn Crispin u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif)
46671af586c9SAndrei Otcheretianski {
46681af586c9SAndrei Otcheretianski 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
4669af296bdbSMichal Kazior 	struct beacon_data *beacon = NULL;
4670af296bdbSMichal Kazior 	u8 count = 0;
467173da7d5bSSimon Wunderlich 
4672af296bdbSMichal Kazior 	rcu_read_lock();
4673af296bdbSMichal Kazior 
4674af296bdbSMichal Kazior 	if (sdata->vif.type == NL80211_IFTYPE_AP)
4675af296bdbSMichal Kazior 		beacon = rcu_dereference(sdata->u.ap.beacon);
4676af296bdbSMichal Kazior 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
4677af296bdbSMichal Kazior 		beacon = rcu_dereference(sdata->u.ibss.presp);
4678af296bdbSMichal Kazior 	else if (ieee80211_vif_is_mesh(&sdata->vif))
4679af296bdbSMichal Kazior 		beacon = rcu_dereference(sdata->u.mesh.beacon);
4680af296bdbSMichal Kazior 
4681af296bdbSMichal Kazior 	if (!beacon)
4682af296bdbSMichal Kazior 		goto unlock;
4683af296bdbSMichal Kazior 
46848552a434SJohn Crispin 	count = __ieee80211_beacon_update_cntdwn(beacon);
46851af586c9SAndrei Otcheretianski 
4686af296bdbSMichal Kazior unlock:
4687af296bdbSMichal Kazior 	rcu_read_unlock();
4688af296bdbSMichal Kazior 	return count;
46890d06d9baSAndrei Otcheretianski }
46908552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_update_cntdwn);
46910d06d9baSAndrei Otcheretianski 
46928552a434SJohn Crispin void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter)
469303737001SGregory Greenman {
469403737001SGregory Greenman 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
469503737001SGregory Greenman 	struct beacon_data *beacon = NULL;
469603737001SGregory Greenman 
469703737001SGregory Greenman 	rcu_read_lock();
469803737001SGregory Greenman 
469903737001SGregory Greenman 	if (sdata->vif.type == NL80211_IFTYPE_AP)
470003737001SGregory Greenman 		beacon = rcu_dereference(sdata->u.ap.beacon);
470103737001SGregory Greenman 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
470203737001SGregory Greenman 		beacon = rcu_dereference(sdata->u.ibss.presp);
470303737001SGregory Greenman 	else if (ieee80211_vif_is_mesh(&sdata->vif))
470403737001SGregory Greenman 		beacon = rcu_dereference(sdata->u.mesh.beacon);
470503737001SGregory Greenman 
470603737001SGregory Greenman 	if (!beacon)
470703737001SGregory Greenman 		goto unlock;
470803737001SGregory Greenman 
47098552a434SJohn Crispin 	if (counter < beacon->cntdwn_current_counter)
47108552a434SJohn Crispin 		beacon->cntdwn_current_counter = counter;
471103737001SGregory Greenman 
471203737001SGregory Greenman unlock:
471303737001SGregory Greenman 	rcu_read_unlock();
471403737001SGregory Greenman }
47158552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn);
471603737001SGregory Greenman 
47178552a434SJohn Crispin bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif)
471873da7d5bSSimon Wunderlich {
471973da7d5bSSimon Wunderlich 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
472073da7d5bSSimon Wunderlich 	struct beacon_data *beacon = NULL;
472173da7d5bSSimon Wunderlich 	u8 *beacon_data;
472273da7d5bSSimon Wunderlich 	size_t beacon_data_len;
472373da7d5bSSimon Wunderlich 	int ret = false;
472473da7d5bSSimon Wunderlich 
472573da7d5bSSimon Wunderlich 	if (!ieee80211_sdata_running(sdata))
472673da7d5bSSimon Wunderlich 		return false;
472773da7d5bSSimon Wunderlich 
472873da7d5bSSimon Wunderlich 	rcu_read_lock();
472973da7d5bSSimon Wunderlich 	if (vif->type == NL80211_IFTYPE_AP) {
473073da7d5bSSimon Wunderlich 		struct ieee80211_if_ap *ap = &sdata->u.ap;
473173da7d5bSSimon Wunderlich 
473273da7d5bSSimon Wunderlich 		beacon = rcu_dereference(ap->beacon);
473373da7d5bSSimon Wunderlich 		if (WARN_ON(!beacon || !beacon->tail))
473473da7d5bSSimon Wunderlich 			goto out;
473573da7d5bSSimon Wunderlich 		beacon_data = beacon->tail;
473673da7d5bSSimon Wunderlich 		beacon_data_len = beacon->tail_len;
4737cd7760e6SSimon Wunderlich 	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
4738cd7760e6SSimon Wunderlich 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
4739cd7760e6SSimon Wunderlich 
4740cd7760e6SSimon Wunderlich 		beacon = rcu_dereference(ifibss->presp);
4741cd7760e6SSimon Wunderlich 		if (!beacon)
4742cd7760e6SSimon Wunderlich 			goto out;
4743cd7760e6SSimon Wunderlich 
4744cd7760e6SSimon Wunderlich 		beacon_data = beacon->head;
4745cd7760e6SSimon Wunderlich 		beacon_data_len = beacon->head_len;
4746b8456a14SChun-Yeow Yeoh 	} else if (vif->type == NL80211_IFTYPE_MESH_POINT) {
4747b8456a14SChun-Yeow Yeoh 		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
4748b8456a14SChun-Yeow Yeoh 
4749b8456a14SChun-Yeow Yeoh 		beacon = rcu_dereference(ifmsh->beacon);
4750b8456a14SChun-Yeow Yeoh 		if (!beacon)
4751b8456a14SChun-Yeow Yeoh 			goto out;
4752b8456a14SChun-Yeow Yeoh 
4753b8456a14SChun-Yeow Yeoh 		beacon_data = beacon->head;
4754b8456a14SChun-Yeow Yeoh 		beacon_data_len = beacon->head_len;
475573da7d5bSSimon Wunderlich 	} else {
475673da7d5bSSimon Wunderlich 		WARN_ON(1);
475773da7d5bSSimon Wunderlich 		goto out;
475873da7d5bSSimon Wunderlich 	}
475973da7d5bSSimon Wunderlich 
47608552a434SJohn Crispin 	if (!beacon->cntdwn_counter_offsets[0])
476110d78f27SMichal Kazior 		goto out;
476210d78f27SMichal Kazior 
47638552a434SJohn Crispin 	if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[0] > beacon_data_len))
476473da7d5bSSimon Wunderlich 		goto out;
476573da7d5bSSimon Wunderlich 
47668552a434SJohn Crispin 	if (beacon_data[beacon->cntdwn_counter_offsets[0]] == 1)
476773da7d5bSSimon Wunderlich 		ret = true;
47688552a434SJohn Crispin 
476973da7d5bSSimon Wunderlich  out:
477073da7d5bSSimon Wunderlich 	rcu_read_unlock();
477173da7d5bSSimon Wunderlich 
477273da7d5bSSimon Wunderlich 	return ret;
477373da7d5bSSimon Wunderlich }
47748552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_cntdwn_is_complete);
477573da7d5bSSimon Wunderlich 
47760a3a8436SJouni Malinen static int ieee80211_beacon_protect(struct sk_buff *skb,
47770a3a8436SJouni Malinen 				    struct ieee80211_local *local,
47780a3a8436SJouni Malinen 				    struct ieee80211_sub_if_data *sdata)
47790a3a8436SJouni Malinen {
47800a3a8436SJouni Malinen 	ieee80211_tx_result res;
47810a3a8436SJouni Malinen 	struct ieee80211_tx_data tx;
478295247705SJohannes Berg 	struct sk_buff *check_skb;
47830a3a8436SJouni Malinen 
47840a3a8436SJouni Malinen 	memset(&tx, 0, sizeof(tx));
47850a3a8436SJouni Malinen 	tx.key = rcu_dereference(sdata->default_beacon_key);
47860a3a8436SJouni Malinen 	if (!tx.key)
47870a3a8436SJouni Malinen 		return 0;
47880a3a8436SJouni Malinen 	tx.local = local;
47890a3a8436SJouni Malinen 	tx.sdata = sdata;
47900a3a8436SJouni Malinen 	__skb_queue_head_init(&tx.skbs);
47910a3a8436SJouni Malinen 	__skb_queue_tail(&tx.skbs, skb);
47920a3a8436SJouni Malinen 	res = ieee80211_tx_h_encrypt(&tx);
479395247705SJohannes Berg 	check_skb = __skb_dequeue(&tx.skbs);
479495247705SJohannes Berg 	/* we may crash after this, but it'd be a bug in crypto */
479595247705SJohannes Berg 	WARN_ON(check_skb != skb);
47960a3a8436SJouni Malinen 	if (WARN_ON_ONCE(res != TX_CONTINUE))
479795247705SJohannes Berg 		return -EINVAL;
47980a3a8436SJouni Malinen 
47990a3a8436SJouni Malinen 	return 0;
48000a3a8436SJouni Malinen }
48010a3a8436SJouni Malinen 
48026ec8c332SAndrei Otcheretianski static struct sk_buff *
48036ec8c332SAndrei Otcheretianski __ieee80211_beacon_get(struct ieee80211_hw *hw,
4804eddcbb94SJohannes Berg 		       struct ieee80211_vif *vif,
48056ec8c332SAndrei Otcheretianski 		       struct ieee80211_mutable_offsets *offs,
48066ec8c332SAndrei Otcheretianski 		       bool is_template)
4807e2ebc74dSJohannes Berg {
4808e2ebc74dSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
4809af296bdbSMichal Kazior 	struct beacon_data *beacon = NULL;
48109d139c81SJohannes Berg 	struct sk_buff *skb = NULL;
4811e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info;
4812e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = NULL;
481357fbcce3SJohannes Berg 	enum nl80211_band band;
4814e00cfce0SJouni Malinen 	struct ieee80211_tx_rate_control txrc;
481555de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
48161af586c9SAndrei Otcheretianski 	int csa_off_base = 0;
48178318d78aSJohannes Berg 
48185dfdaf58SJohannes Berg 	rcu_read_lock();
4819e2ebc74dSJohannes Berg 
482032bfd35dSJohannes Berg 	sdata = vif_to_sdata(vif);
482155de908aSJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
482233b64eb2SLuis Carlos Cobo 
482355de908aSJohannes Berg 	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
4824eb3e554bSFelix Fietkau 		goto out;
4825eb3e554bSFelix Fietkau 
48266ec8c332SAndrei Otcheretianski 	if (offs)
48276ec8c332SAndrei Otcheretianski 		memset(offs, 0, sizeof(*offs));
4828eddcbb94SJohannes Berg 
482905c914feSJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
4830d012a605SMarco Porsch 		struct ieee80211_if_ap *ap = &sdata->u.ap;
4831d012a605SMarco Porsch 
4832af296bdbSMichal Kazior 		beacon = rcu_dereference(ap->beacon);
48333ad97fbcSDan Carpenter 		if (beacon) {
48348552a434SJohn Crispin 			if (beacon->cntdwn_counter_offsets[0]) {
48351af586c9SAndrei Otcheretianski 				if (!is_template)
48368552a434SJohn Crispin 					ieee80211_beacon_update_cntdwn(vif);
48371af586c9SAndrei Otcheretianski 
48388552a434SJohn Crispin 				ieee80211_set_beacon_cntdwn(sdata, beacon);
48391af586c9SAndrei Otcheretianski 			}
484073da7d5bSSimon Wunderlich 
4841902acc78SJohannes Berg 			/*
4842902acc78SJohannes Berg 			 * headroom, head length,
4843902acc78SJohannes Berg 			 * tail length and maximum TIM length
4844902acc78SJohannes Berg 			 */
4845902acc78SJohannes Berg 			skb = dev_alloc_skb(local->tx_headroom +
4846902acc78SJohannes Berg 					    beacon->head_len +
484770dabeb7SFelix Fietkau 					    beacon->tail_len + 256 +
484870dabeb7SFelix Fietkau 					    local->hw.extra_beacon_tailroom);
4849e2ebc74dSJohannes Berg 			if (!skb)
48505dfdaf58SJohannes Berg 				goto out;
4851e2ebc74dSJohannes Berg 
4852e2ebc74dSJohannes Berg 			skb_reserve(skb, local->tx_headroom);
485359ae1d12SJohannes Berg 			skb_put_data(skb, beacon->head, beacon->head_len);
4854e2ebc74dSJohannes Berg 
48556ec8c332SAndrei Otcheretianski 			ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
48566ec8c332SAndrei Otcheretianski 						 is_template);
4857e2ebc74dSJohannes Berg 
48586ec8c332SAndrei Otcheretianski 			if (offs) {
48596ec8c332SAndrei Otcheretianski 				offs->tim_offset = beacon->head_len;
48606ec8c332SAndrei Otcheretianski 				offs->tim_length = skb->len - beacon->head_len;
48611af586c9SAndrei Otcheretianski 
48621af586c9SAndrei Otcheretianski 				/* for AP the csa offsets are from tail */
48631af586c9SAndrei Otcheretianski 				csa_off_base = skb->len;
48646ec8c332SAndrei Otcheretianski 			}
4865eddcbb94SJohannes Berg 
48665dfdaf58SJohannes Berg 			if (beacon->tail)
486759ae1d12SJohannes Berg 				skb_put_data(skb, beacon->tail,
486859ae1d12SJohannes Berg 					     beacon->tail_len);
48690a3a8436SJouni Malinen 
48700a3a8436SJouni Malinen 			if (ieee80211_beacon_protect(skb, local, sdata) < 0)
48710a3a8436SJouni Malinen 				goto out;
48729d139c81SJohannes Berg 		} else
48739d139c81SJohannes Berg 			goto out;
487405c914feSJohannes Berg 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
487546900298SJohannes Berg 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
48769d139c81SJohannes Berg 		struct ieee80211_hdr *hdr;
487733b64eb2SLuis Carlos Cobo 
4878af296bdbSMichal Kazior 		beacon = rcu_dereference(ifibss->presp);
4879af296bdbSMichal Kazior 		if (!beacon)
48809d139c81SJohannes Berg 			goto out;
48819d139c81SJohannes Berg 
48828552a434SJohn Crispin 		if (beacon->cntdwn_counter_offsets[0]) {
48831af586c9SAndrei Otcheretianski 			if (!is_template)
48848552a434SJohn Crispin 				__ieee80211_beacon_update_cntdwn(beacon);
4885cd7760e6SSimon Wunderlich 
48868552a434SJohn Crispin 			ieee80211_set_beacon_cntdwn(sdata, beacon);
48871af586c9SAndrei Otcheretianski 		}
4888cd7760e6SSimon Wunderlich 
4889af296bdbSMichal Kazior 		skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
489070dabeb7SFelix Fietkau 				    local->hw.extra_beacon_tailroom);
48919d139c81SJohannes Berg 		if (!skb)
48929d139c81SJohannes Berg 			goto out;
4893c3ffeab4SJohannes Berg 		skb_reserve(skb, local->tx_headroom);
489459ae1d12SJohannes Berg 		skb_put_data(skb, beacon->head, beacon->head_len);
48959d139c81SJohannes Berg 
48969d139c81SJohannes Berg 		hdr = (struct ieee80211_hdr *) skb->data;
4897e7827a70SHarvey Harrison 		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
48989d139c81SJohannes Berg 						 IEEE80211_STYPE_BEACON);
4899902acc78SJohannes Berg 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
4900dbf498fbSJavier Cardona 		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
4901472dbc45SJohannes Berg 
4902af296bdbSMichal Kazior 		beacon = rcu_dereference(ifmsh->beacon);
4903af296bdbSMichal Kazior 		if (!beacon)
4904ac1bd846SJohannes Berg 			goto out;
4905ac1bd846SJohannes Berg 
49068552a434SJohn Crispin 		if (beacon->cntdwn_counter_offsets[0]) {
49071af586c9SAndrei Otcheretianski 			if (!is_template)
49081af586c9SAndrei Otcheretianski 				/* TODO: For mesh csa_counter is in TU, so
49091af586c9SAndrei Otcheretianski 				 * decrementing it by one isn't correct, but
49101af586c9SAndrei Otcheretianski 				 * for now we leave it consistent with overall
49111af586c9SAndrei Otcheretianski 				 * mac80211's behavior.
49121af586c9SAndrei Otcheretianski 				 */
49138552a434SJohn Crispin 				__ieee80211_beacon_update_cntdwn(beacon);
49141af586c9SAndrei Otcheretianski 
49158552a434SJohn Crispin 			ieee80211_set_beacon_cntdwn(sdata, beacon);
49161af586c9SAndrei Otcheretianski 		}
4917b8456a14SChun-Yeow Yeoh 
4918dbf498fbSJavier Cardona 		if (ifmsh->sync_ops)
4919445cd452SMasashi Honma 			ifmsh->sync_ops->adjust_tsf(sdata, beacon);
4920dbf498fbSJavier Cardona 
49213b69a9c5SThomas Pedersen 		skb = dev_alloc_skb(local->tx_headroom +
4922af296bdbSMichal Kazior 				    beacon->head_len +
49233f52b7e3SMarco Porsch 				    256 + /* TIM IE */
4924af296bdbSMichal Kazior 				    beacon->tail_len +
492570dabeb7SFelix Fietkau 				    local->hw.extra_beacon_tailroom);
4926902acc78SJohannes Berg 		if (!skb)
4927902acc78SJohannes Berg 			goto out;
49282b5e1967SThomas Pedersen 		skb_reserve(skb, local->tx_headroom);
492959ae1d12SJohannes Berg 		skb_put_data(skb, beacon->head, beacon->head_len);
49306ec8c332SAndrei Otcheretianski 		ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
49316ec8c332SAndrei Otcheretianski 
49326ec8c332SAndrei Otcheretianski 		if (offs) {
4933af296bdbSMichal Kazior 			offs->tim_offset = beacon->head_len;
4934af296bdbSMichal Kazior 			offs->tim_length = skb->len - beacon->head_len;
49356ec8c332SAndrei Otcheretianski 		}
49366ec8c332SAndrei Otcheretianski 
493759ae1d12SJohannes Berg 		skb_put_data(skb, beacon->tail, beacon->tail_len);
49389d139c81SJohannes Berg 	} else {
49399d139c81SJohannes Berg 		WARN_ON(1);
494033b64eb2SLuis Carlos Cobo 		goto out;
494133b64eb2SLuis Carlos Cobo 	}
494233b64eb2SLuis Carlos Cobo 
49431af586c9SAndrei Otcheretianski 	/* CSA offsets */
4944af296bdbSMichal Kazior 	if (offs && beacon) {
49451af586c9SAndrei Otcheretianski 		int i;
49461af586c9SAndrei Otcheretianski 
49478552a434SJohn Crispin 		for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
49488552a434SJohn Crispin 			u16 csa_off = beacon->cntdwn_counter_offsets[i];
49491af586c9SAndrei Otcheretianski 
49501af586c9SAndrei Otcheretianski 			if (!csa_off)
49511af586c9SAndrei Otcheretianski 				continue;
49521af586c9SAndrei Otcheretianski 
49538552a434SJohn Crispin 			offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
49541af586c9SAndrei Otcheretianski 		}
49551af586c9SAndrei Otcheretianski 	}
49561af586c9SAndrei Otcheretianski 
49574bf88530SJohannes Berg 	band = chanctx_conf->def.chan->band;
495855de908aSJohannes Berg 
4959e039fa4aSJohannes Berg 	info = IEEE80211_SKB_CB(skb);
4960e039fa4aSJohannes Berg 
49613b8d81e0SJohannes Berg 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
4962e00cfce0SJouni Malinen 	info->flags |= IEEE80211_TX_CTL_NO_ACK;
4963e039fa4aSJohannes Berg 	info->band = band;
4964e00cfce0SJouni Malinen 
4965e00cfce0SJouni Malinen 	memset(&txrc, 0, sizeof(txrc));
4966e00cfce0SJouni Malinen 	txrc.hw = hw;
4967e31583cdSJohannes Berg 	txrc.sband = local->hw.wiphy->bands[band];
4968e00cfce0SJouni Malinen 	txrc.bss_conf = &sdata->vif.bss_conf;
4969e00cfce0SJouni Malinen 	txrc.skb = skb;
4970e00cfce0SJouni Malinen 	txrc.reported_rate.idx = -1;
497108fad438SJouni Malinen 	if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
497208fad438SJouni Malinen 		txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
497308fad438SJouni Malinen 	else
497437eb0b16SJouni Malinen 		txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
49758f0729b1SFelix Fietkau 	txrc.bss = true;
4976e00cfce0SJouni Malinen 	rate_control_get_rate(sdata, NULL, &txrc);
4977e2ebc74dSJohannes Berg 
4978e039fa4aSJohannes Berg 	info->control.vif = vif;
4979f591fa5dSJohannes Berg 
4980a472e71bSJohn W. Linville 	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
4981a472e71bSJohn W. Linville 			IEEE80211_TX_CTL_ASSIGN_SEQ |
4982a472e71bSJohn W. Linville 			IEEE80211_TX_CTL_FIRST_FRAGMENT;
49835dfdaf58SJohannes Berg  out:
49845dfdaf58SJohannes Berg 	rcu_read_unlock();
4985e2ebc74dSJohannes Berg 	return skb;
49866ec8c332SAndrei Otcheretianski 
49876ec8c332SAndrei Otcheretianski }
49886ec8c332SAndrei Otcheretianski 
49896ec8c332SAndrei Otcheretianski struct sk_buff *
49906ec8c332SAndrei Otcheretianski ieee80211_beacon_get_template(struct ieee80211_hw *hw,
49916ec8c332SAndrei Otcheretianski 			      struct ieee80211_vif *vif,
49926ec8c332SAndrei Otcheretianski 			      struct ieee80211_mutable_offsets *offs)
49936ec8c332SAndrei Otcheretianski {
49946ec8c332SAndrei Otcheretianski 	return __ieee80211_beacon_get(hw, vif, offs, true);
49956ec8c332SAndrei Otcheretianski }
49966ec8c332SAndrei Otcheretianski EXPORT_SYMBOL(ieee80211_beacon_get_template);
49976ec8c332SAndrei Otcheretianski 
49986ec8c332SAndrei Otcheretianski struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
49996ec8c332SAndrei Otcheretianski 					 struct ieee80211_vif *vif,
50006ec8c332SAndrei Otcheretianski 					 u16 *tim_offset, u16 *tim_length)
50016ec8c332SAndrei Otcheretianski {
50026ec8c332SAndrei Otcheretianski 	struct ieee80211_mutable_offsets offs = {};
50036ec8c332SAndrei Otcheretianski 	struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
500435afa588SHelmut Schaa 	struct sk_buff *copy;
500535afa588SHelmut Schaa 	struct ieee80211_supported_band *sband;
500635afa588SHelmut Schaa 	int shift;
500735afa588SHelmut Schaa 
500835afa588SHelmut Schaa 	if (!bcn)
500935afa588SHelmut Schaa 		return bcn;
50106ec8c332SAndrei Otcheretianski 
50116ec8c332SAndrei Otcheretianski 	if (tim_offset)
50126ec8c332SAndrei Otcheretianski 		*tim_offset = offs.tim_offset;
50136ec8c332SAndrei Otcheretianski 
50146ec8c332SAndrei Otcheretianski 	if (tim_length)
50156ec8c332SAndrei Otcheretianski 		*tim_length = offs.tim_length;
50166ec8c332SAndrei Otcheretianski 
501735afa588SHelmut Schaa 	if (ieee80211_hw_check(hw, BEACON_TX_STATUS) ||
501835afa588SHelmut Schaa 	    !hw_to_local(hw)->monitors)
501935afa588SHelmut Schaa 		return bcn;
502035afa588SHelmut Schaa 
502135afa588SHelmut Schaa 	/* send a copy to monitor interfaces */
502235afa588SHelmut Schaa 	copy = skb_copy(bcn, GFP_ATOMIC);
502335afa588SHelmut Schaa 	if (!copy)
502435afa588SHelmut Schaa 		return bcn;
502535afa588SHelmut Schaa 
502635afa588SHelmut Schaa 	shift = ieee80211_vif_get_shift(vif);
502721a8e9ddSMohammed Shafi Shajakhan 	sband = ieee80211_get_sband(vif_to_sdata(vif));
502821a8e9ddSMohammed Shafi Shajakhan 	if (!sband)
502921a8e9ddSMohammed Shafi Shajakhan 		return bcn;
503021a8e9ddSMohammed Shafi Shajakhan 
5031b7b2e8caSJohn Crispin 	ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false,
5032b7b2e8caSJohn Crispin 			     NULL);
503335afa588SHelmut Schaa 
50346ec8c332SAndrei Otcheretianski 	return bcn;
5035e2ebc74dSJohannes Berg }
5036eddcbb94SJohannes Berg EXPORT_SYMBOL(ieee80211_beacon_get_tim);
5037e2ebc74dSJohannes Berg 
503802945821SArik Nemtsov struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
503902945821SArik Nemtsov 					struct ieee80211_vif *vif)
504002945821SArik Nemtsov {
504102945821SArik Nemtsov 	struct ieee80211_if_ap *ap = NULL;
5042aa7a0080SEyal Shapira 	struct sk_buff *skb = NULL;
5043aa7a0080SEyal Shapira 	struct probe_resp *presp = NULL;
504402945821SArik Nemtsov 	struct ieee80211_hdr *hdr;
504502945821SArik Nemtsov 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
504602945821SArik Nemtsov 
504702945821SArik Nemtsov 	if (sdata->vif.type != NL80211_IFTYPE_AP)
504802945821SArik Nemtsov 		return NULL;
504902945821SArik Nemtsov 
505002945821SArik Nemtsov 	rcu_read_lock();
505102945821SArik Nemtsov 
505202945821SArik Nemtsov 	ap = &sdata->u.ap;
505302945821SArik Nemtsov 	presp = rcu_dereference(ap->probe_resp);
505402945821SArik Nemtsov 	if (!presp)
505502945821SArik Nemtsov 		goto out;
505602945821SArik Nemtsov 
5057aa7a0080SEyal Shapira 	skb = dev_alloc_skb(presp->len);
505802945821SArik Nemtsov 	if (!skb)
505902945821SArik Nemtsov 		goto out;
506002945821SArik Nemtsov 
506159ae1d12SJohannes Berg 	skb_put_data(skb, presp->data, presp->len);
5062aa7a0080SEyal Shapira 
506302945821SArik Nemtsov 	hdr = (struct ieee80211_hdr *) skb->data;
506402945821SArik Nemtsov 	memset(hdr->addr1, 0, sizeof(hdr->addr1));
506502945821SArik Nemtsov 
506602945821SArik Nemtsov out:
506702945821SArik Nemtsov 	rcu_read_unlock();
506802945821SArik Nemtsov 	return skb;
506902945821SArik Nemtsov }
507002945821SArik Nemtsov EXPORT_SYMBOL(ieee80211_proberesp_get);
507102945821SArik Nemtsov 
5072295b02c4SAloka Dixit struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw,
5073295b02c4SAloka Dixit 						  struct ieee80211_vif *vif)
5074295b02c4SAloka Dixit {
5075295b02c4SAloka Dixit 	struct sk_buff *skb = NULL;
5076295b02c4SAloka Dixit 	struct fils_discovery_data *tmpl = NULL;
5077295b02c4SAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5078295b02c4SAloka Dixit 
5079295b02c4SAloka Dixit 	if (sdata->vif.type != NL80211_IFTYPE_AP)
5080295b02c4SAloka Dixit 		return NULL;
5081295b02c4SAloka Dixit 
5082295b02c4SAloka Dixit 	rcu_read_lock();
5083295b02c4SAloka Dixit 	tmpl = rcu_dereference(sdata->u.ap.fils_discovery);
5084295b02c4SAloka Dixit 	if (!tmpl) {
5085295b02c4SAloka Dixit 		rcu_read_unlock();
5086295b02c4SAloka Dixit 		return NULL;
5087295b02c4SAloka Dixit 	}
5088295b02c4SAloka Dixit 
5089295b02c4SAloka Dixit 	skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
5090295b02c4SAloka Dixit 	if (skb) {
5091295b02c4SAloka Dixit 		skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
5092295b02c4SAloka Dixit 		skb_put_data(skb, tmpl->data, tmpl->len);
5093295b02c4SAloka Dixit 	}
5094295b02c4SAloka Dixit 
5095295b02c4SAloka Dixit 	rcu_read_unlock();
5096295b02c4SAloka Dixit 	return skb;
5097295b02c4SAloka Dixit }
5098295b02c4SAloka Dixit EXPORT_SYMBOL(ieee80211_get_fils_discovery_tmpl);
5099295b02c4SAloka Dixit 
5100632189a0SAloka Dixit struct sk_buff *
5101632189a0SAloka Dixit ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
5102632189a0SAloka Dixit 					  struct ieee80211_vif *vif)
5103632189a0SAloka Dixit {
5104632189a0SAloka Dixit 	struct sk_buff *skb = NULL;
5105632189a0SAloka Dixit 	struct unsol_bcast_probe_resp_data *tmpl = NULL;
5106632189a0SAloka Dixit 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
5107632189a0SAloka Dixit 
5108632189a0SAloka Dixit 	if (sdata->vif.type != NL80211_IFTYPE_AP)
5109632189a0SAloka Dixit 		return NULL;
5110632189a0SAloka Dixit 
5111632189a0SAloka Dixit 	rcu_read_lock();
5112632189a0SAloka Dixit 	tmpl = rcu_dereference(sdata->u.ap.unsol_bcast_probe_resp);
5113632189a0SAloka Dixit 	if (!tmpl) {
5114632189a0SAloka Dixit 		rcu_read_unlock();
5115632189a0SAloka Dixit 		return NULL;
5116632189a0SAloka Dixit 	}
5117632189a0SAloka Dixit 
5118632189a0SAloka Dixit 	skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len);
5119632189a0SAloka Dixit 	if (skb) {
5120632189a0SAloka Dixit 		skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
5121632189a0SAloka Dixit 		skb_put_data(skb, tmpl->data, tmpl->len);
5122632189a0SAloka Dixit 	}
5123632189a0SAloka Dixit 
5124632189a0SAloka Dixit 	rcu_read_unlock();
5125632189a0SAloka Dixit 	return skb;
5126632189a0SAloka Dixit }
5127632189a0SAloka Dixit EXPORT_SYMBOL(ieee80211_get_unsol_bcast_probe_resp_tmpl);
5128632189a0SAloka Dixit 
51297044cc56SKalle Valo struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
51307044cc56SKalle Valo 				     struct ieee80211_vif *vif)
51317044cc56SKalle Valo {
51327044cc56SKalle Valo 	struct ieee80211_sub_if_data *sdata;
51337044cc56SKalle Valo 	struct ieee80211_if_managed *ifmgd;
51347044cc56SKalle Valo 	struct ieee80211_pspoll *pspoll;
51357044cc56SKalle Valo 	struct ieee80211_local *local;
51367044cc56SKalle Valo 	struct sk_buff *skb;
51377044cc56SKalle Valo 
51387044cc56SKalle Valo 	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
51397044cc56SKalle Valo 		return NULL;
51407044cc56SKalle Valo 
51417044cc56SKalle Valo 	sdata = vif_to_sdata(vif);
51427044cc56SKalle Valo 	ifmgd = &sdata->u.mgd;
51437044cc56SKalle Valo 	local = sdata->local;
51447044cc56SKalle Valo 
51457044cc56SKalle Valo 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
5146d15b8459SJoe Perches 	if (!skb)
51477044cc56SKalle Valo 		return NULL;
5148d15b8459SJoe Perches 
51497044cc56SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
51507044cc56SKalle Valo 
5151b080db58SJohannes Berg 	pspoll = skb_put_zero(skb, sizeof(*pspoll));
51527044cc56SKalle Valo 	pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
51537044cc56SKalle Valo 					    IEEE80211_STYPE_PSPOLL);
51541db364c8SJohannes Berg 	pspoll->aid = cpu_to_le16(sdata->vif.bss_conf.aid);
51557044cc56SKalle Valo 
51567044cc56SKalle Valo 	/* aid in PS-Poll has its two MSBs each set to 1 */
51577044cc56SKalle Valo 	pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
51587044cc56SKalle Valo 
51597044cc56SKalle Valo 	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
51607044cc56SKalle Valo 	memcpy(pspoll->ta, vif->addr, ETH_ALEN);
51617044cc56SKalle Valo 
51627044cc56SKalle Valo 	return skb;
51637044cc56SKalle Valo }
51647044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_pspoll_get);
51657044cc56SKalle Valo 
51667044cc56SKalle Valo struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
51677b6ddeafSJohannes Berg 				       struct ieee80211_vif *vif,
51687b6ddeafSJohannes Berg 				       bool qos_ok)
51697044cc56SKalle Valo {
51707044cc56SKalle Valo 	struct ieee80211_hdr_3addr *nullfunc;
51717044cc56SKalle Valo 	struct ieee80211_sub_if_data *sdata;
51727044cc56SKalle Valo 	struct ieee80211_if_managed *ifmgd;
51737044cc56SKalle Valo 	struct ieee80211_local *local;
51747044cc56SKalle Valo 	struct sk_buff *skb;
51757b6ddeafSJohannes Berg 	bool qos = false;
51767044cc56SKalle Valo 
51777044cc56SKalle Valo 	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
51787044cc56SKalle Valo 		return NULL;
51797044cc56SKalle Valo 
51807044cc56SKalle Valo 	sdata = vif_to_sdata(vif);
51817044cc56SKalle Valo 	ifmgd = &sdata->u.mgd;
51827044cc56SKalle Valo 	local = sdata->local;
51837044cc56SKalle Valo 
51847b6ddeafSJohannes Berg 	if (qos_ok) {
51857b6ddeafSJohannes Berg 		struct sta_info *sta;
51867b6ddeafSJohannes Berg 
51877b6ddeafSJohannes Berg 		rcu_read_lock();
51887b6ddeafSJohannes Berg 		sta = sta_info_get(sdata, ifmgd->bssid);
51897b6ddeafSJohannes Berg 		qos = sta && sta->sta.wme;
51907b6ddeafSJohannes Berg 		rcu_read_unlock();
51917b6ddeafSJohannes Berg 	}
51927b6ddeafSJohannes Berg 
51937b6ddeafSJohannes Berg 	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
51947b6ddeafSJohannes Berg 			    sizeof(*nullfunc) + 2);
5195d15b8459SJoe Perches 	if (!skb)
51967044cc56SKalle Valo 		return NULL;
5197d15b8459SJoe Perches 
51987044cc56SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
51997044cc56SKalle Valo 
5200b080db58SJohannes Berg 	nullfunc = skb_put_zero(skb, sizeof(*nullfunc));
52017044cc56SKalle Valo 	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
52027044cc56SKalle Valo 					      IEEE80211_STYPE_NULLFUNC |
52037044cc56SKalle Valo 					      IEEE80211_FCTL_TODS);
52047b6ddeafSJohannes Berg 	if (qos) {
5205e0ba7095SJohannes Berg 		__le16 qoshdr = cpu_to_le16(7);
52067b6ddeafSJohannes Berg 
52077b6ddeafSJohannes Berg 		BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC |
52087b6ddeafSJohannes Berg 			      IEEE80211_STYPE_NULLFUNC) !=
52097b6ddeafSJohannes Berg 			     IEEE80211_STYPE_QOS_NULLFUNC);
52107b6ddeafSJohannes Berg 		nullfunc->frame_control |=
52117b6ddeafSJohannes Berg 			cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC);
52127b6ddeafSJohannes Berg 		skb->priority = 7;
52137b6ddeafSJohannes Berg 		skb_set_queue_mapping(skb, IEEE80211_AC_VO);
5214e0ba7095SJohannes Berg 		skb_put_data(skb, &qoshdr, sizeof(qoshdr));
52157b6ddeafSJohannes Berg 	}
52167b6ddeafSJohannes Berg 
52177044cc56SKalle Valo 	memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
52187044cc56SKalle Valo 	memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
52197044cc56SKalle Valo 	memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
52207044cc56SKalle Valo 
52217044cc56SKalle Valo 	return skb;
52227044cc56SKalle Valo }
52237044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_nullfunc_get);
52247044cc56SKalle Valo 
522505e54ea6SKalle Valo struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
5226a344d677SJohannes Berg 				       const u8 *src_addr,
522705e54ea6SKalle Valo 				       const u8 *ssid, size_t ssid_len,
5228b9a9ada1SJohannes Berg 				       size_t tailroom)
522905e54ea6SKalle Valo {
5230a344d677SJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
523105e54ea6SKalle Valo 	struct ieee80211_hdr_3addr *hdr;
523205e54ea6SKalle Valo 	struct sk_buff *skb;
523305e54ea6SKalle Valo 	size_t ie_ssid_len;
523405e54ea6SKalle Valo 	u8 *pos;
523505e54ea6SKalle Valo 
523605e54ea6SKalle Valo 	ie_ssid_len = 2 + ssid_len;
523705e54ea6SKalle Valo 
523805e54ea6SKalle Valo 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
5239b9a9ada1SJohannes Berg 			    ie_ssid_len + tailroom);
5240d15b8459SJoe Perches 	if (!skb)
524105e54ea6SKalle Valo 		return NULL;
524205e54ea6SKalle Valo 
524305e54ea6SKalle Valo 	skb_reserve(skb, local->hw.extra_tx_headroom);
524405e54ea6SKalle Valo 
5245b080db58SJohannes Berg 	hdr = skb_put_zero(skb, sizeof(*hdr));
524605e54ea6SKalle Valo 	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
524705e54ea6SKalle Valo 					 IEEE80211_STYPE_PROBE_REQ);
5248e83e6541SJohannes Berg 	eth_broadcast_addr(hdr->addr1);
5249a344d677SJohannes Berg 	memcpy(hdr->addr2, src_addr, ETH_ALEN);
5250e83e6541SJohannes Berg 	eth_broadcast_addr(hdr->addr3);
525105e54ea6SKalle Valo 
525205e54ea6SKalle Valo 	pos = skb_put(skb, ie_ssid_len);
525305e54ea6SKalle Valo 	*pos++ = WLAN_EID_SSID;
525405e54ea6SKalle Valo 	*pos++ = ssid_len;
525588c868c4SStanislaw Gruszka 	if (ssid_len)
525605e54ea6SKalle Valo 		memcpy(pos, ssid, ssid_len);
525705e54ea6SKalle Valo 	pos += ssid_len;
525805e54ea6SKalle Valo 
525905e54ea6SKalle Valo 	return skb;
526005e54ea6SKalle Valo }
526105e54ea6SKalle Valo EXPORT_SYMBOL(ieee80211_probereq_get);
526205e54ea6SKalle Valo 
526332bfd35dSJohannes Berg void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5264e2ebc74dSJohannes Berg 		       const void *frame, size_t frame_len,
5265e039fa4aSJohannes Berg 		       const struct ieee80211_tx_info *frame_txctl,
5266e2ebc74dSJohannes Berg 		       struct ieee80211_rts *rts)
5267e2ebc74dSJohannes Berg {
5268e2ebc74dSJohannes Berg 	const struct ieee80211_hdr *hdr = frame;
5269e2ebc74dSJohannes Berg 
5270065e9605SHarvey Harrison 	rts->frame_control =
5271065e9605SHarvey Harrison 	    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
527232bfd35dSJohannes Berg 	rts->duration = ieee80211_rts_duration(hw, vif, frame_len,
527332bfd35dSJohannes Berg 					       frame_txctl);
5274e2ebc74dSJohannes Berg 	memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
5275e2ebc74dSJohannes Berg 	memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
5276e2ebc74dSJohannes Berg }
5277e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_get);
5278e2ebc74dSJohannes Berg 
527932bfd35dSJohannes Berg void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5280e2ebc74dSJohannes Berg 			     const void *frame, size_t frame_len,
5281e039fa4aSJohannes Berg 			     const struct ieee80211_tx_info *frame_txctl,
5282e2ebc74dSJohannes Berg 			     struct ieee80211_cts *cts)
5283e2ebc74dSJohannes Berg {
5284e2ebc74dSJohannes Berg 	const struct ieee80211_hdr *hdr = frame;
5285e2ebc74dSJohannes Berg 
5286065e9605SHarvey Harrison 	cts->frame_control =
5287065e9605SHarvey Harrison 	    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
528832bfd35dSJohannes Berg 	cts->duration = ieee80211_ctstoself_duration(hw, vif,
528932bfd35dSJohannes Berg 						     frame_len, frame_txctl);
5290e2ebc74dSJohannes Berg 	memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
5291e2ebc74dSJohannes Berg }
5292e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_get);
5293e2ebc74dSJohannes Berg 
5294e2ebc74dSJohannes Berg struct sk_buff *
529532bfd35dSJohannes Berg ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
5296e039fa4aSJohannes Berg 			  struct ieee80211_vif *vif)
5297e2ebc74dSJohannes Berg {
5298e2ebc74dSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
5299747cf5e9STomas Winkler 	struct sk_buff *skb = NULL;
53005cf121c3SJohannes Berg 	struct ieee80211_tx_data tx;
5301e2ebc74dSJohannes Berg 	struct ieee80211_sub_if_data *sdata;
5302d012a605SMarco Porsch 	struct ps_data *ps;
5303e039fa4aSJohannes Berg 	struct ieee80211_tx_info *info;
530455de908aSJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
5305e2ebc74dSJohannes Berg 
530632bfd35dSJohannes Berg 	sdata = vif_to_sdata(vif);
53075dfdaf58SJohannes Berg 
53085dfdaf58SJohannes Berg 	rcu_read_lock();
530955de908aSJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
53105dfdaf58SJohannes Berg 
5311d012a605SMarco Porsch 	if (!chanctx_conf)
5312747cf5e9STomas Winkler 		goto out;
53135dfdaf58SJohannes Berg 
5314d012a605SMarco Porsch 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
5315d012a605SMarco Porsch 		struct beacon_data *beacon =
5316d012a605SMarco Porsch 				rcu_dereference(sdata->u.ap.beacon);
5317d012a605SMarco Porsch 
5318d012a605SMarco Porsch 		if (!beacon || !beacon->head)
5319d012a605SMarco Porsch 			goto out;
5320d012a605SMarco Porsch 
5321d012a605SMarco Porsch 		ps = &sdata->u.ap.ps;
53223f52b7e3SMarco Porsch 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
53233f52b7e3SMarco Porsch 		ps = &sdata->u.mesh.ps;
5324d012a605SMarco Porsch 	} else {
5325d012a605SMarco Porsch 		goto out;
5326d012a605SMarco Porsch 	}
5327d012a605SMarco Porsch 
5328d012a605SMarco Porsch 	if (ps->dtim_count != 0 || !ps->dtim_bc_mc)
5329747cf5e9STomas Winkler 		goto out; /* send buffered bc/mc only after DTIM beacon */
5330e039fa4aSJohannes Berg 
5331e2ebc74dSJohannes Berg 	while (1) {
5332d012a605SMarco Porsch 		skb = skb_dequeue(&ps->bc_buf);
5333e2ebc74dSJohannes Berg 		if (!skb)
5334747cf5e9STomas Winkler 			goto out;
5335e2ebc74dSJohannes Berg 		local->total_ps_buffered--;
5336e2ebc74dSJohannes Berg 
5337d012a605SMarco Porsch 		if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) {
5338e2ebc74dSJohannes Berg 			struct ieee80211_hdr *hdr =
5339e2ebc74dSJohannes Berg 				(struct ieee80211_hdr *) skb->data;
5340e2ebc74dSJohannes Berg 			/* more buffered multicast/broadcast frames ==> set
5341e2ebc74dSJohannes Berg 			 * MoreData flag in IEEE 802.11 header to inform PS
5342e2ebc74dSJohannes Berg 			 * STAs */
5343e2ebc74dSJohannes Berg 			hdr->frame_control |=
5344e2ebc74dSJohannes Berg 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5345e2ebc74dSJohannes Berg 		}
5346e2ebc74dSJohannes Berg 
5347112c44b2SMichael Braun 		if (sdata->vif.type == NL80211_IFTYPE_AP)
5348de74a1d9SMichael Braun 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
53497c10770fSJohannes Berg 		if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
5350e2ebc74dSJohannes Berg 			break;
53516b07d9caSFelix Fietkau 		ieee80211_free_txskb(hw, skb);
5352e2ebc74dSJohannes Berg 	}
5353e039fa4aSJohannes Berg 
5354e039fa4aSJohannes Berg 	info = IEEE80211_SKB_CB(skb);
5355e039fa4aSJohannes Berg 
53565cf121c3SJohannes Berg 	tx.flags |= IEEE80211_TX_PS_BUFFERED;
53574bf88530SJohannes Berg 	info->band = chanctx_conf->def.chan->band;
5358e2ebc74dSJohannes Berg 
535997b045d6SJohannes Berg 	if (invoke_tx_handlers(&tx))
5360e2ebc74dSJohannes Berg 		skb = NULL;
5361747cf5e9STomas Winkler  out:
5362d0709a65SJohannes Berg 	rcu_read_unlock();
5363e2ebc74dSJohannes Berg 
5364e2ebc74dSJohannes Berg 	return skb;
5365e2ebc74dSJohannes Berg }
5366e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_get_buffered_bc);
53673b8d81e0SJohannes Berg 
5368b6da911bSLiad Kaufman int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
5369b6da911bSLiad Kaufman {
5370b6da911bSLiad Kaufman 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
5371b6da911bSLiad Kaufman 	struct ieee80211_sub_if_data *sdata = sta->sdata;
5372b6da911bSLiad Kaufman 	struct ieee80211_local *local = sdata->local;
5373b6da911bSLiad Kaufman 	int ret;
5374b6da911bSLiad Kaufman 	u32 queues;
5375b6da911bSLiad Kaufman 
5376b6da911bSLiad Kaufman 	lockdep_assert_held(&local->sta_mtx);
5377b6da911bSLiad Kaufman 
5378b6da911bSLiad Kaufman 	/* only some cases are supported right now */
5379b6da911bSLiad Kaufman 	switch (sdata->vif.type) {
5380b6da911bSLiad Kaufman 	case NL80211_IFTYPE_STATION:
5381b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP:
5382b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP_VLAN:
5383b6da911bSLiad Kaufman 		break;
5384b6da911bSLiad Kaufman 	default:
5385b6da911bSLiad Kaufman 		WARN_ON(1);
5386b6da911bSLiad Kaufman 		return -EINVAL;
5387b6da911bSLiad Kaufman 	}
5388b6da911bSLiad Kaufman 
5389b6da911bSLiad Kaufman 	if (WARN_ON(tid >= IEEE80211_NUM_UPS))
5390b6da911bSLiad Kaufman 		return -EINVAL;
5391b6da911bSLiad Kaufman 
5392b6da911bSLiad Kaufman 	if (sta->reserved_tid == tid) {
5393b6da911bSLiad Kaufman 		ret = 0;
5394b6da911bSLiad Kaufman 		goto out;
5395b6da911bSLiad Kaufman 	}
5396b6da911bSLiad Kaufman 
5397b6da911bSLiad Kaufman 	if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
5398b6da911bSLiad Kaufman 		sdata_err(sdata, "TID reservation already active\n");
5399b6da911bSLiad Kaufman 		ret = -EALREADY;
5400b6da911bSLiad Kaufman 		goto out;
5401b6da911bSLiad Kaufman 	}
5402b6da911bSLiad Kaufman 
5403b6da911bSLiad Kaufman 	ieee80211_stop_vif_queues(sdata->local, sdata,
5404b6da911bSLiad Kaufman 				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
5405b6da911bSLiad Kaufman 
5406b6da911bSLiad Kaufman 	synchronize_net();
5407b6da911bSLiad Kaufman 
5408b6da911bSLiad Kaufman 	/* Tear down BA sessions so we stop aggregating on this TID */
540930686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) {
5410b6da911bSLiad Kaufman 		set_sta_flag(sta, WLAN_STA_BLOCK_BA);
5411b6da911bSLiad Kaufman 		__ieee80211_stop_tx_ba_session(sta, tid,
5412b6da911bSLiad Kaufman 					       AGG_STOP_LOCAL_REQUEST);
5413b6da911bSLiad Kaufman 	}
5414b6da911bSLiad Kaufman 
5415b6da911bSLiad Kaufman 	queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
54163b24f4c6SEmmanuel Grumbach 	__ieee80211_flush_queues(local, sdata, queues, false);
5417b6da911bSLiad Kaufman 
5418b6da911bSLiad Kaufman 	sta->reserved_tid = tid;
5419b6da911bSLiad Kaufman 
5420b6da911bSLiad Kaufman 	ieee80211_wake_vif_queues(local, sdata,
5421b6da911bSLiad Kaufman 				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
5422b6da911bSLiad Kaufman 
542330686bf7SJohannes Berg 	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION))
5424b6da911bSLiad Kaufman 		clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
5425b6da911bSLiad Kaufman 
5426b6da911bSLiad Kaufman 	ret = 0;
5427b6da911bSLiad Kaufman  out:
5428b6da911bSLiad Kaufman 	return ret;
5429b6da911bSLiad Kaufman }
5430b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_reserve_tid);
5431b6da911bSLiad Kaufman 
5432b6da911bSLiad Kaufman void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
5433b6da911bSLiad Kaufman {
5434b6da911bSLiad Kaufman 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
5435b6da911bSLiad Kaufman 	struct ieee80211_sub_if_data *sdata = sta->sdata;
5436b6da911bSLiad Kaufman 
5437b6da911bSLiad Kaufman 	lockdep_assert_held(&sdata->local->sta_mtx);
5438b6da911bSLiad Kaufman 
5439b6da911bSLiad Kaufman 	/* only some cases are supported right now */
5440b6da911bSLiad Kaufman 	switch (sdata->vif.type) {
5441b6da911bSLiad Kaufman 	case NL80211_IFTYPE_STATION:
5442b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP:
5443b6da911bSLiad Kaufman 	case NL80211_IFTYPE_AP_VLAN:
5444b6da911bSLiad Kaufman 		break;
5445b6da911bSLiad Kaufman 	default:
5446b6da911bSLiad Kaufman 		WARN_ON(1);
5447b6da911bSLiad Kaufman 		return;
5448b6da911bSLiad Kaufman 	}
5449b6da911bSLiad Kaufman 
5450b6da911bSLiad Kaufman 	if (tid != sta->reserved_tid) {
5451b6da911bSLiad Kaufman 		sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
5452b6da911bSLiad Kaufman 		return;
5453b6da911bSLiad Kaufman 	}
5454b6da911bSLiad Kaufman 
5455b6da911bSLiad Kaufman 	sta->reserved_tid = IEEE80211_TID_UNRESERVED;
5456b6da911bSLiad Kaufman }
5457b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_unreserve_tid);
5458b6da911bSLiad Kaufman 
545955de908aSJohannes Berg void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
546055de908aSJohannes Berg 				 struct sk_buff *skb, int tid,
546108aca29aSMathy Vanhoef 				 enum nl80211_band band)
54623b8d81e0SJohannes Berg {
5463731977e9SAmadeusz Sławiński 	int ac = ieee80211_ac_from_tid(tid);
54643a25a8c8SJohannes Berg 
5465d57a544dSZhang Shengju 	skb_reset_mac_header(skb);
54663a25a8c8SJohannes Berg 	skb_set_queue_mapping(skb, ac);
5467cf6bb79aSHelmut Schaa 	skb->priority = tid;
5468cf0277e7SJohannes Berg 
546989afe614SJohannes Berg 	skb->dev = sdata->dev;
547089afe614SJohannes Berg 
54713d34deb6SJohannes Berg 	/*
54723d34deb6SJohannes Berg 	 * The other path calling ieee80211_xmit is from the tasklet,
54733d34deb6SJohannes Berg 	 * and while we can handle concurrent transmissions locking
54743d34deb6SJohannes Berg 	 * requirements are that we do not come into tx with bhs on.
54753d34deb6SJohannes Berg 	 */
54763d34deb6SJohannes Berg 	local_bh_disable();
547773c4e195SJohannes Berg 	IEEE80211_SKB_CB(skb)->band = band;
547808aca29aSMathy Vanhoef 	ieee80211_xmit(sdata, NULL, skb);
54793d34deb6SJohannes Berg 	local_bh_enable();
54803b8d81e0SJohannes Berg }
548191180649SDenis Kenzior 
548291180649SDenis Kenzior int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
548391180649SDenis Kenzior 			      const u8 *buf, size_t len,
5484dca9ca2dSMarkus Theil 			      const u8 *dest, __be16 proto, bool unencrypted,
5485dca9ca2dSMarkus Theil 			      u64 *cookie)
548691180649SDenis Kenzior {
548791180649SDenis Kenzior 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
548891180649SDenis Kenzior 	struct ieee80211_local *local = sdata->local;
548910cb8e61SMarkus Theil 	struct sta_info *sta;
549091180649SDenis Kenzior 	struct sk_buff *skb;
549191180649SDenis Kenzior 	struct ethhdr *ehdr;
5492b95d2ccdSJohannes Berg 	u32 ctrl_flags = 0;
5493a7528198SMarkus Theil 	u32 flags = 0;
549491180649SDenis Kenzior 
549591180649SDenis Kenzior 	/* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE
549691180649SDenis Kenzior 	 * or Pre-Authentication
549791180649SDenis Kenzior 	 */
549891180649SDenis Kenzior 	if (proto != sdata->control_port_protocol &&
549991180649SDenis Kenzior 	    proto != cpu_to_be16(ETH_P_PREAUTH))
550091180649SDenis Kenzior 		return -EINVAL;
550191180649SDenis Kenzior 
5502b95d2ccdSJohannes Berg 	if (proto == sdata->control_port_protocol)
55035af7fef3SMarkus Theil 		ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO |
55045af7fef3SMarkus Theil 			      IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
5505b95d2ccdSJohannes Berg 
550691180649SDenis Kenzior 	if (unencrypted)
5507a7528198SMarkus Theil 		flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
5508a7528198SMarkus Theil 
5509a7528198SMarkus Theil 	if (cookie)
5510a7528198SMarkus Theil 		ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
5511a7528198SMarkus Theil 
551210cb8e61SMarkus Theil 	flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX;
551391180649SDenis Kenzior 
551491180649SDenis Kenzior 	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
551591180649SDenis Kenzior 			    sizeof(struct ethhdr) + len);
551691180649SDenis Kenzior 	if (!skb)
551791180649SDenis Kenzior 		return -ENOMEM;
551891180649SDenis Kenzior 
551991180649SDenis Kenzior 	skb_reserve(skb, local->hw.extra_tx_headroom + sizeof(struct ethhdr));
552091180649SDenis Kenzior 
552191180649SDenis Kenzior 	skb_put_data(skb, buf, len);
552291180649SDenis Kenzior 
552391180649SDenis Kenzior 	ehdr = skb_push(skb, sizeof(struct ethhdr));
552491180649SDenis Kenzior 	memcpy(ehdr->h_dest, dest, ETH_ALEN);
55258079e4feSJohannes Berg 	memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
552691180649SDenis Kenzior 	ehdr->h_proto = proto;
552791180649SDenis Kenzior 
552891180649SDenis Kenzior 	skb->dev = dev;
552910cb8e61SMarkus Theil 	skb->protocol = proto;
553091180649SDenis Kenzior 	skb_reset_network_header(skb);
553191180649SDenis Kenzior 	skb_reset_mac_header(skb);
553291180649SDenis Kenzior 
553310cb8e61SMarkus Theil 	/* update QoS header to prioritize control port frames if possible,
553410cb8e61SMarkus Theil 	 * priorization also happens for control port frames send over
553510cb8e61SMarkus Theil 	 * AF_PACKET
553610cb8e61SMarkus Theil 	 */
553710cb8e61SMarkus Theil 	rcu_read_lock();
553810cb8e61SMarkus Theil 
553910cb8e61SMarkus Theil 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta) == 0 && !IS_ERR(sta)) {
554010cb8e61SMarkus Theil 		u16 queue = __ieee80211_select_queue(sdata, sta, skb);
554110cb8e61SMarkus Theil 
554210cb8e61SMarkus Theil 		skb_set_queue_mapping(skb, queue);
554310cb8e61SMarkus Theil 		skb_get_hash(skb);
554410cb8e61SMarkus Theil 	}
554510cb8e61SMarkus Theil 
554610cb8e61SMarkus Theil 	rcu_read_unlock();
554710cb8e61SMarkus Theil 
5548a7528198SMarkus Theil 	/* mutex lock is only needed for incrementing the cookie counter */
5549a7528198SMarkus Theil 	mutex_lock(&local->mtx);
5550a7528198SMarkus Theil 
5551e7441c92SDenis Kenzior 	local_bh_disable();
5552a7528198SMarkus Theil 	__ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags, cookie);
5553e7441c92SDenis Kenzior 	local_bh_enable();
555491180649SDenis Kenzior 
5555a7528198SMarkus Theil 	mutex_unlock(&local->mtx);
5556a7528198SMarkus Theil 
555791180649SDenis Kenzior 	return 0;
555891180649SDenis Kenzior }
55598828f81aSRajkumar Manoharan 
55608828f81aSRajkumar Manoharan int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
55618828f81aSRajkumar Manoharan 			      const u8 *buf, size_t len)
55628828f81aSRajkumar Manoharan {
55638828f81aSRajkumar Manoharan 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
55648828f81aSRajkumar Manoharan 	struct ieee80211_local *local = sdata->local;
55658828f81aSRajkumar Manoharan 	struct sk_buff *skb;
55668828f81aSRajkumar Manoharan 
55678828f81aSRajkumar Manoharan 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + len +
55688828f81aSRajkumar Manoharan 			    30 + /* header size */
55698828f81aSRajkumar Manoharan 			    18); /* 11s header size */
55708828f81aSRajkumar Manoharan 	if (!skb)
55718828f81aSRajkumar Manoharan 		return -ENOMEM;
55728828f81aSRajkumar Manoharan 
55738828f81aSRajkumar Manoharan 	skb_reserve(skb, local->hw.extra_tx_headroom);
55748828f81aSRajkumar Manoharan 	skb_put_data(skb, buf, len);
55758828f81aSRajkumar Manoharan 
55768828f81aSRajkumar Manoharan 	skb->dev = dev;
55778828f81aSRajkumar Manoharan 	skb->protocol = htons(ETH_P_802_3);
55788828f81aSRajkumar Manoharan 	skb_reset_network_header(skb);
55798828f81aSRajkumar Manoharan 	skb_reset_mac_header(skb);
55808828f81aSRajkumar Manoharan 
55818828f81aSRajkumar Manoharan 	local_bh_disable();
55828828f81aSRajkumar Manoharan 	__ieee80211_subif_start_xmit(skb, skb->dev, 0,
5583a7528198SMarkus Theil 				     IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP,
5584a7528198SMarkus Theil 				     NULL);
5585e2ebc74dSJohannes Berg 	local_bh_enable();
5586e2ebc74dSJohannes Berg 
5587e2ebc74dSJohannes Berg 	return 0;
5588e2ebc74dSJohannes Berg }
5589