xref: /freebsd/sys/contrib/dev/iwlwifi/mvm/rxmq.c (revision a4128aad8503277614f2d214011ef60a19447b83)
1bfcc09ddSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2bfcc09ddSBjoern A. Zeeb /*
3*a4128aadSBjoern A. Zeeb  * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
4bfcc09ddSBjoern A. Zeeb  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
5bfcc09ddSBjoern A. Zeeb  * Copyright (C) 2015-2017 Intel Deutschland GmbH
6bfcc09ddSBjoern A. Zeeb  */
7bfcc09ddSBjoern A. Zeeb #include <linux/etherdevice.h>
8bfcc09ddSBjoern A. Zeeb #include <linux/skbuff.h>
9bfcc09ddSBjoern A. Zeeb #if defined(__FreeBSD__)
10bfcc09ddSBjoern A. Zeeb #include <net/ieee80211_radiotap.h>
11bfcc09ddSBjoern A. Zeeb #endif
12bfcc09ddSBjoern A. Zeeb #include "iwl-trans.h"
13bfcc09ddSBjoern A. Zeeb #include "mvm.h"
14bfcc09ddSBjoern A. Zeeb #include "fw-api.h"
159af1bba4SBjoern A. Zeeb #include "time-sync.h"
16bfcc09ddSBjoern A. Zeeb 
17bfcc09ddSBjoern A. Zeeb static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
18bfcc09ddSBjoern A. Zeeb 				   int queue, struct ieee80211_sta *sta)
19bfcc09ddSBjoern A. Zeeb {
20bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_sta *mvmsta;
219af1bba4SBjoern A. Zeeb 	struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
22bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
23bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_key_pn *ptk_pn;
24bfcc09ddSBjoern A. Zeeb 	int res;
25bfcc09ddSBjoern A. Zeeb 	u8 tid, keyidx;
26bfcc09ddSBjoern A. Zeeb 	u8 pn[IEEE80211_CCMP_PN_LEN];
27bfcc09ddSBjoern A. Zeeb 	u8 *extiv;
28bfcc09ddSBjoern A. Zeeb 
29bfcc09ddSBjoern A. Zeeb 	/* do PN checking */
30bfcc09ddSBjoern A. Zeeb 
31bfcc09ddSBjoern A. Zeeb 	/* multicast and non-data only arrives on default queue */
32bfcc09ddSBjoern A. Zeeb 	if (!ieee80211_is_data(hdr->frame_control) ||
33bfcc09ddSBjoern A. Zeeb 	    is_multicast_ether_addr(hdr->addr1))
34bfcc09ddSBjoern A. Zeeb 		return 0;
35bfcc09ddSBjoern A. Zeeb 
36bfcc09ddSBjoern A. Zeeb 	/* do not check PN for open AP */
37bfcc09ddSBjoern A. Zeeb 	if (!(stats->flag & RX_FLAG_DECRYPTED))
38bfcc09ddSBjoern A. Zeeb 		return 0;
39bfcc09ddSBjoern A. Zeeb 
40bfcc09ddSBjoern A. Zeeb 	/*
41bfcc09ddSBjoern A. Zeeb 	 * avoid checking for default queue - we don't want to replicate
42bfcc09ddSBjoern A. Zeeb 	 * all the logic that's necessary for checking the PN on fragmented
43bfcc09ddSBjoern A. Zeeb 	 * frames, leave that to mac80211
44bfcc09ddSBjoern A. Zeeb 	 */
45bfcc09ddSBjoern A. Zeeb 	if (queue == 0)
46bfcc09ddSBjoern A. Zeeb 		return 0;
47bfcc09ddSBjoern A. Zeeb 
48bfcc09ddSBjoern A. Zeeb 	/* if we are here - this for sure is either CCMP or GCMP */
49bfcc09ddSBjoern A. Zeeb 	if (IS_ERR_OR_NULL(sta)) {
50bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm,
51bfcc09ddSBjoern A. Zeeb 			       "expected hw-decrypted unicast frame for station\n");
52bfcc09ddSBjoern A. Zeeb 		return -1;
53bfcc09ddSBjoern A. Zeeb 	}
54bfcc09ddSBjoern A. Zeeb 
55bfcc09ddSBjoern A. Zeeb 	mvmsta = iwl_mvm_sta_from_mac80211(sta);
56bfcc09ddSBjoern A. Zeeb 
57bfcc09ddSBjoern A. Zeeb 	extiv = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
58bfcc09ddSBjoern A. Zeeb 	keyidx = extiv[3] >> 6;
59bfcc09ddSBjoern A. Zeeb 
60bfcc09ddSBjoern A. Zeeb 	ptk_pn = rcu_dereference(mvmsta->ptk_pn[keyidx]);
61bfcc09ddSBjoern A. Zeeb 	if (!ptk_pn)
62bfcc09ddSBjoern A. Zeeb 		return -1;
63bfcc09ddSBjoern A. Zeeb 
64bfcc09ddSBjoern A. Zeeb 	if (ieee80211_is_data_qos(hdr->frame_control))
65bfcc09ddSBjoern A. Zeeb 		tid = ieee80211_get_tid(hdr);
66bfcc09ddSBjoern A. Zeeb 	else
67bfcc09ddSBjoern A. Zeeb 		tid = 0;
68bfcc09ddSBjoern A. Zeeb 
69bfcc09ddSBjoern A. Zeeb 	/* we don't use HCCA/802.11 QoS TSPECs, so drop such frames */
70bfcc09ddSBjoern A. Zeeb 	if (tid >= IWL_MAX_TID_COUNT)
71bfcc09ddSBjoern A. Zeeb 		return -1;
72bfcc09ddSBjoern A. Zeeb 
73bfcc09ddSBjoern A. Zeeb 	/* load pn */
74bfcc09ddSBjoern A. Zeeb 	pn[0] = extiv[7];
75bfcc09ddSBjoern A. Zeeb 	pn[1] = extiv[6];
76bfcc09ddSBjoern A. Zeeb 	pn[2] = extiv[5];
77bfcc09ddSBjoern A. Zeeb 	pn[3] = extiv[4];
78bfcc09ddSBjoern A. Zeeb 	pn[4] = extiv[1];
79bfcc09ddSBjoern A. Zeeb 	pn[5] = extiv[0];
80bfcc09ddSBjoern A. Zeeb 
81bfcc09ddSBjoern A. Zeeb 	res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
82bfcc09ddSBjoern A. Zeeb 	if (res < 0)
83bfcc09ddSBjoern A. Zeeb 		return -1;
84bfcc09ddSBjoern A. Zeeb 	if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))
85bfcc09ddSBjoern A. Zeeb 		return -1;
86bfcc09ddSBjoern A. Zeeb 
87bfcc09ddSBjoern A. Zeeb 	memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
88bfcc09ddSBjoern A. Zeeb 	stats->flag |= RX_FLAG_PN_VALIDATED;
89bfcc09ddSBjoern A. Zeeb 
90bfcc09ddSBjoern A. Zeeb 	return 0;
91bfcc09ddSBjoern A. Zeeb }
92bfcc09ddSBjoern A. Zeeb 
93bfcc09ddSBjoern A. Zeeb /* iwl_mvm_create_skb Adds the rxb to a new skb */
94bfcc09ddSBjoern A. Zeeb static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
95bfcc09ddSBjoern A. Zeeb 			      struct ieee80211_hdr *hdr, u16 len, u8 crypt_len,
96bfcc09ddSBjoern A. Zeeb 			      struct iwl_rx_cmd_buffer *rxb)
97bfcc09ddSBjoern A. Zeeb {
98bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
99bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
100bfcc09ddSBjoern A. Zeeb 	unsigned int headlen, fraglen, pad_len = 0;
101bfcc09ddSBjoern A. Zeeb 	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
102d9836fb4SBjoern A. Zeeb 	u8 mic_crc_len = u8_get_bits(desc->mac_flags1,
103d9836fb4SBjoern A. Zeeb 				     IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1;
104bfcc09ddSBjoern A. Zeeb 
105bfcc09ddSBjoern A. Zeeb 	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
106bfcc09ddSBjoern A. Zeeb 		len -= 2;
107bfcc09ddSBjoern A. Zeeb 		pad_len = 2;
108bfcc09ddSBjoern A. Zeeb 	}
109bfcc09ddSBjoern A. Zeeb 
110d9836fb4SBjoern A. Zeeb 	/*
111d9836fb4SBjoern A. Zeeb 	 * For non monitor interface strip the bytes the RADA might not have
1129af1bba4SBjoern A. Zeeb 	 * removed (it might be disabled, e.g. for mgmt frames). As a monitor
1139af1bba4SBjoern A. Zeeb 	 * interface cannot exist with other interfaces, this removal is safe
1149af1bba4SBjoern A. Zeeb 	 * and sufficient, in monitor mode there's no decryption being done.
115d9836fb4SBjoern A. Zeeb 	 */
1169af1bba4SBjoern A. Zeeb 	if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))
117d9836fb4SBjoern A. Zeeb 		len -= mic_crc_len;
118d9836fb4SBjoern A. Zeeb 
119bfcc09ddSBjoern A. Zeeb 	/* If frame is small enough to fit in skb->head, pull it completely.
120bfcc09ddSBjoern A. Zeeb 	 * If not, only pull ieee80211_hdr (including crypto if present, and
121bfcc09ddSBjoern A. Zeeb 	 * an additional 8 bytes for SNAP/ethertype, see below) so that
122bfcc09ddSBjoern A. Zeeb 	 * splice() or TCP coalesce are more efficient.
123bfcc09ddSBjoern A. Zeeb 	 *
124bfcc09ddSBjoern A. Zeeb 	 * Since, in addition, ieee80211_data_to_8023() always pull in at
125bfcc09ddSBjoern A. Zeeb 	 * least 8 bytes (possibly more for mesh) we can do the same here
126bfcc09ddSBjoern A. Zeeb 	 * to save the cost of doing it later. That still doesn't pull in
127bfcc09ddSBjoern A. Zeeb 	 * the actual IP header since the typical case has a SNAP header.
128bfcc09ddSBjoern A. Zeeb 	 * If the latter changes (there are efforts in the standards group
129bfcc09ddSBjoern A. Zeeb 	 * to do so) we should revisit this and ieee80211_data_to_8023().
130bfcc09ddSBjoern A. Zeeb 	 */
131bfcc09ddSBjoern A. Zeeb 	headlen = (len <= skb_tailroom(skb)) ? len :
132bfcc09ddSBjoern A. Zeeb 					       hdrlen + crypt_len + 8;
133bfcc09ddSBjoern A. Zeeb 
134bfcc09ddSBjoern A. Zeeb 	/* The firmware may align the packet to DWORD.
135bfcc09ddSBjoern A. Zeeb 	 * The padding is inserted after the IV.
136bfcc09ddSBjoern A. Zeeb 	 * After copying the header + IV skip the padding if
137bfcc09ddSBjoern A. Zeeb 	 * present before copying packet data.
138bfcc09ddSBjoern A. Zeeb 	 */
139bfcc09ddSBjoern A. Zeeb 	hdrlen += crypt_len;
140bfcc09ddSBjoern A. Zeeb 
141d9836fb4SBjoern A. Zeeb 	if (unlikely(headlen < hdrlen))
142bfcc09ddSBjoern A. Zeeb 		return -EINVAL;
143bfcc09ddSBjoern A. Zeeb 
1449af1bba4SBjoern A. Zeeb 	/* Since data doesn't move data while putting data on skb and that is
1459af1bba4SBjoern A. Zeeb 	 * the only way we use, data + len is the next place that hdr would be put
1469af1bba4SBjoern A. Zeeb 	 */
1479af1bba4SBjoern A. Zeeb 	skb_set_mac_header(skb, skb->len);
148bfcc09ddSBjoern A. Zeeb 	skb_put_data(skb, hdr, hdrlen);
149bfcc09ddSBjoern A. Zeeb 	skb_put_data(skb, (u8 *)hdr + hdrlen + pad_len, headlen - hdrlen);
150bfcc09ddSBjoern A. Zeeb 
151bfcc09ddSBjoern A. Zeeb 	/*
152bfcc09ddSBjoern A. Zeeb 	 * If we did CHECKSUM_COMPLETE, the hardware only does it right for
153bfcc09ddSBjoern A. Zeeb 	 * certain cases and starts the checksum after the SNAP. Check if
154bfcc09ddSBjoern A. Zeeb 	 * this is the case - it's easier to just bail out to CHECKSUM_NONE
155bfcc09ddSBjoern A. Zeeb 	 * in the cases the hardware didn't handle, since it's rare to see
156bfcc09ddSBjoern A. Zeeb 	 * such packets, even though the hardware did calculate the checksum
157bfcc09ddSBjoern A. Zeeb 	 * in this case, just starting after the MAC header instead.
158d9836fb4SBjoern A. Zeeb 	 *
159d9836fb4SBjoern A. Zeeb 	 * Starting from Bz hardware, it calculates starting directly after
160d9836fb4SBjoern A. Zeeb 	 * the MAC header, so that matches mac80211's expectation.
161bfcc09ddSBjoern A. Zeeb 	 */
1629af1bba4SBjoern A. Zeeb 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
163bfcc09ddSBjoern A. Zeeb 		struct {
164bfcc09ddSBjoern A. Zeeb 			u8 hdr[6];
165bfcc09ddSBjoern A. Zeeb 			__be16 type;
166bfcc09ddSBjoern A. Zeeb 		} __packed *shdr = (void *)((u8 *)hdr + hdrlen + pad_len);
167bfcc09ddSBjoern A. Zeeb 
168bfcc09ddSBjoern A. Zeeb 		if (unlikely(headlen - hdrlen < sizeof(*shdr) ||
169bfcc09ddSBjoern A. Zeeb 			     !ether_addr_equal(shdr->hdr, rfc1042_header) ||
170bfcc09ddSBjoern A. Zeeb 			     (shdr->type != htons(ETH_P_IP) &&
171bfcc09ddSBjoern A. Zeeb 			      shdr->type != htons(ETH_P_ARP) &&
172bfcc09ddSBjoern A. Zeeb 			      shdr->type != htons(ETH_P_IPV6) &&
173bfcc09ddSBjoern A. Zeeb 			      shdr->type != htons(ETH_P_8021Q) &&
174bfcc09ddSBjoern A. Zeeb 			      shdr->type != htons(ETH_P_PAE) &&
175bfcc09ddSBjoern A. Zeeb 			      shdr->type != htons(ETH_P_TDLS))))
176bfcc09ddSBjoern A. Zeeb 			skb->ip_summed = CHECKSUM_NONE;
1779af1bba4SBjoern A. Zeeb 		else if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
178d9836fb4SBjoern A. Zeeb 			/* mac80211 assumes full CSUM including SNAP header */
179d9836fb4SBjoern A. Zeeb 			skb_postpush_rcsum(skb, shdr, sizeof(*shdr));
180bfcc09ddSBjoern A. Zeeb 	}
181bfcc09ddSBjoern A. Zeeb 
182bfcc09ddSBjoern A. Zeeb 	fraglen = len - headlen;
183bfcc09ddSBjoern A. Zeeb 
184bfcc09ddSBjoern A. Zeeb 	if (fraglen) {
185bfcc09ddSBjoern A. Zeeb 		int offset = (u8 *)hdr + headlen + pad_len -
186bfcc09ddSBjoern A. Zeeb 			     (u8 *)rxb_addr(rxb) + rxb_offset(rxb);
187bfcc09ddSBjoern A. Zeeb 
188bfcc09ddSBjoern A. Zeeb 		skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
189bfcc09ddSBjoern A. Zeeb 				fraglen, rxb->truesize);
190bfcc09ddSBjoern A. Zeeb 	}
191bfcc09ddSBjoern A. Zeeb 
192bfcc09ddSBjoern A. Zeeb 	return 0;
193bfcc09ddSBjoern A. Zeeb }
194bfcc09ddSBjoern A. Zeeb 
1959af1bba4SBjoern A. Zeeb /* put a TLV on the skb and return data pointer
1969af1bba4SBjoern A. Zeeb  *
1979af1bba4SBjoern A. Zeeb  * Also pad to 4 the len and zero out all data part
1989af1bba4SBjoern A. Zeeb  */
1999af1bba4SBjoern A. Zeeb static void *
2009af1bba4SBjoern A. Zeeb iwl_mvm_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
2019af1bba4SBjoern A. Zeeb {
2029af1bba4SBjoern A. Zeeb 	struct ieee80211_radiotap_tlv *tlv;
2039af1bba4SBjoern A. Zeeb 
2049af1bba4SBjoern A. Zeeb 	tlv = skb_put(skb, sizeof(*tlv));
2059af1bba4SBjoern A. Zeeb 	tlv->type = cpu_to_le16(type);
2069af1bba4SBjoern A. Zeeb 	tlv->len = cpu_to_le16(len);
2079af1bba4SBjoern A. Zeeb 	return skb_put_zero(skb, ALIGN(len, 4));
2089af1bba4SBjoern A. Zeeb }
2099af1bba4SBjoern A. Zeeb 
210bfcc09ddSBjoern A. Zeeb static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
211bfcc09ddSBjoern A. Zeeb 					    struct sk_buff *skb)
212bfcc09ddSBjoern A. Zeeb {
213bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
2149af1bba4SBjoern A. Zeeb 	struct ieee80211_radiotap_vendor_content *radiotap;
2159af1bba4SBjoern A. Zeeb 	const u16 vendor_data_len = sizeof(mvm->cur_aid);
216bfcc09ddSBjoern A. Zeeb 
217bfcc09ddSBjoern A. Zeeb 	if (!mvm->cur_aid)
218bfcc09ddSBjoern A. Zeeb 		return;
219bfcc09ddSBjoern A. Zeeb 
2209af1bba4SBjoern A. Zeeb 	radiotap = iwl_mvm_radiotap_put_tlv(skb,
2219af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_VENDOR_NAMESPACE,
2229af1bba4SBjoern A. Zeeb 					    sizeof(*radiotap) + vendor_data_len);
223bfcc09ddSBjoern A. Zeeb 
224bfcc09ddSBjoern A. Zeeb 	/* Intel OUI */
225bfcc09ddSBjoern A. Zeeb 	radiotap->oui[0] = 0xf6;
226bfcc09ddSBjoern A. Zeeb 	radiotap->oui[1] = 0x54;
227bfcc09ddSBjoern A. Zeeb 	radiotap->oui[2] = 0x25;
228bfcc09ddSBjoern A. Zeeb 	/* radiotap sniffer config sub-namespace */
2299af1bba4SBjoern A. Zeeb 	radiotap->oui_subtype = 1;
2309af1bba4SBjoern A. Zeeb 	radiotap->vendor_type = 0;
231bfcc09ddSBjoern A. Zeeb 
232bfcc09ddSBjoern A. Zeeb 	/* fill the data now */
233bfcc09ddSBjoern A. Zeeb 	memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
234bfcc09ddSBjoern A. Zeeb 
2359af1bba4SBjoern A. Zeeb 	rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
236bfcc09ddSBjoern A. Zeeb }
237bfcc09ddSBjoern A. Zeeb 
238bfcc09ddSBjoern A. Zeeb /* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */
239bfcc09ddSBjoern A. Zeeb static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
240bfcc09ddSBjoern A. Zeeb 					    struct napi_struct *napi,
241bfcc09ddSBjoern A. Zeeb 					    struct sk_buff *skb, int queue,
242*a4128aadSBjoern A. Zeeb 					    struct ieee80211_sta *sta)
243bfcc09ddSBjoern A. Zeeb {
2449af1bba4SBjoern A. Zeeb 	if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {
245bfcc09ddSBjoern A. Zeeb 		kfree_skb(skb);
2469af1bba4SBjoern A. Zeeb 		return;
2479af1bba4SBjoern A. Zeeb 	}
2489af1bba4SBjoern A. Zeeb 
249bfcc09ddSBjoern A. Zeeb 	ieee80211_rx_napi(mvm->hw, sta, skb, napi);
250bfcc09ddSBjoern A. Zeeb }
251bfcc09ddSBjoern A. Zeeb 
252bfcc09ddSBjoern A. Zeeb static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
253bfcc09ddSBjoern A. Zeeb 					struct ieee80211_rx_status *rx_status,
254bfcc09ddSBjoern A. Zeeb 					u32 rate_n_flags, int energy_a,
255bfcc09ddSBjoern A. Zeeb 					int energy_b)
256bfcc09ddSBjoern A. Zeeb {
257bfcc09ddSBjoern A. Zeeb 	int max_energy;
258bfcc09ddSBjoern A. Zeeb 	u32 rate_flags = rate_n_flags;
259bfcc09ddSBjoern A. Zeeb 
260bfcc09ddSBjoern A. Zeeb 	energy_a = energy_a ? -energy_a : S8_MIN;
261bfcc09ddSBjoern A. Zeeb 	energy_b = energy_b ? -energy_b : S8_MIN;
262bfcc09ddSBjoern A. Zeeb 	max_energy = max(energy_a, energy_b);
263bfcc09ddSBjoern A. Zeeb 
264bfcc09ddSBjoern A. Zeeb 	IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n",
265bfcc09ddSBjoern A. Zeeb 			energy_a, energy_b, max_energy);
266bfcc09ddSBjoern A. Zeeb 
267bfcc09ddSBjoern A. Zeeb 	rx_status->signal = max_energy;
268bfcc09ddSBjoern A. Zeeb 	rx_status->chains =
269bfcc09ddSBjoern A. Zeeb 		(rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
270bfcc09ddSBjoern A. Zeeb 	rx_status->chain_signal[0] = energy_a;
271bfcc09ddSBjoern A. Zeeb 	rx_status->chain_signal[1] = energy_b;
272bfcc09ddSBjoern A. Zeeb }
273bfcc09ddSBjoern A. Zeeb 
274bfcc09ddSBjoern A. Zeeb static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
275bfcc09ddSBjoern A. Zeeb 				struct ieee80211_hdr *hdr,
276bfcc09ddSBjoern A. Zeeb 				struct iwl_rx_mpdu_desc *desc,
2779af1bba4SBjoern A. Zeeb 				u32 status,
2789af1bba4SBjoern A. Zeeb 				struct ieee80211_rx_status *stats)
279bfcc09ddSBjoern A. Zeeb {
280*a4128aadSBjoern A. Zeeb 	struct wireless_dev *wdev;
281bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_sta *mvmsta;
282bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_vif *mvmvif;
283bfcc09ddSBjoern A. Zeeb 	u8 keyid;
284bfcc09ddSBjoern A. Zeeb 	struct ieee80211_key_conf *key;
285bfcc09ddSBjoern A. Zeeb 	u32 len = le16_to_cpu(desc->mpdu_len);
286bfcc09ddSBjoern A. Zeeb 	const u8 *frame = (void *)hdr;
287bfcc09ddSBjoern A. Zeeb 
288bfcc09ddSBjoern A. Zeeb 	if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE)
289bfcc09ddSBjoern A. Zeeb 		return 0;
290bfcc09ddSBjoern A. Zeeb 
291bfcc09ddSBjoern A. Zeeb 	/*
292bfcc09ddSBjoern A. Zeeb 	 * For non-beacon, we don't really care. But beacons may
293bfcc09ddSBjoern A. Zeeb 	 * be filtered out, and we thus need the firmware's replay
294bfcc09ddSBjoern A. Zeeb 	 * detection, otherwise beacons the firmware previously
295bfcc09ddSBjoern A. Zeeb 	 * filtered could be replayed, or something like that, and
296bfcc09ddSBjoern A. Zeeb 	 * it can filter a lot - though usually only if nothing has
297bfcc09ddSBjoern A. Zeeb 	 * changed.
298bfcc09ddSBjoern A. Zeeb 	 */
299bfcc09ddSBjoern A. Zeeb 	if (!ieee80211_is_beacon(hdr->frame_control))
300bfcc09ddSBjoern A. Zeeb 		return 0;
301bfcc09ddSBjoern A. Zeeb 
302*a4128aadSBjoern A. Zeeb 	if (!sta)
303*a4128aadSBjoern A. Zeeb 		return -1;
304*a4128aadSBjoern A. Zeeb 
305*a4128aadSBjoern A. Zeeb 	mvmsta = iwl_mvm_sta_from_mac80211(sta);
306*a4128aadSBjoern A. Zeeb 	mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
307*a4128aadSBjoern A. Zeeb 
308bfcc09ddSBjoern A. Zeeb 	/* key mismatch - will also report !MIC_OK but we shouldn't count it */
309bfcc09ddSBjoern A. Zeeb 	if (!(status & IWL_RX_MPDU_STATUS_KEY_VALID))
310*a4128aadSBjoern A. Zeeb 		goto report;
311bfcc09ddSBjoern A. Zeeb 
312bfcc09ddSBjoern A. Zeeb 	/* good cases */
313bfcc09ddSBjoern A. Zeeb 	if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
3149af1bba4SBjoern A. Zeeb 		   !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) {
3159af1bba4SBjoern A. Zeeb 		stats->flag |= RX_FLAG_DECRYPTED;
316bfcc09ddSBjoern A. Zeeb 		return 0;
3179af1bba4SBjoern A. Zeeb 	}
318bfcc09ddSBjoern A. Zeeb 
319bfcc09ddSBjoern A. Zeeb 	/*
320bfcc09ddSBjoern A. Zeeb 	 * both keys will have the same cipher and MIC length, use
321bfcc09ddSBjoern A. Zeeb 	 * whichever one is available
322bfcc09ddSBjoern A. Zeeb 	 */
323bfcc09ddSBjoern A. Zeeb 	key = rcu_dereference(mvmvif->bcn_prot.keys[0]);
324bfcc09ddSBjoern A. Zeeb 	if (!key) {
325bfcc09ddSBjoern A. Zeeb 		key = rcu_dereference(mvmvif->bcn_prot.keys[1]);
326bfcc09ddSBjoern A. Zeeb 		if (!key)
327*a4128aadSBjoern A. Zeeb 			goto report;
328bfcc09ddSBjoern A. Zeeb 	}
329bfcc09ddSBjoern A. Zeeb 
330bfcc09ddSBjoern A. Zeeb 	if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)
331*a4128aadSBjoern A. Zeeb 		goto report;
332bfcc09ddSBjoern A. Zeeb 
333bfcc09ddSBjoern A. Zeeb 	/* get the real key ID */
334bfcc09ddSBjoern A. Zeeb 	keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];
335bfcc09ddSBjoern A. Zeeb 	/* and if that's the other key, look it up */
336bfcc09ddSBjoern A. Zeeb 	if (keyid != key->keyidx) {
337bfcc09ddSBjoern A. Zeeb 		/*
338bfcc09ddSBjoern A. Zeeb 		 * shouldn't happen since firmware checked, but be safe
339bfcc09ddSBjoern A. Zeeb 		 * in case the MIC length is wrong too, for example
340bfcc09ddSBjoern A. Zeeb 		 */
341bfcc09ddSBjoern A. Zeeb 		if (keyid != 6 && keyid != 7)
342bfcc09ddSBjoern A. Zeeb 			return -1;
343bfcc09ddSBjoern A. Zeeb 		key = rcu_dereference(mvmvif->bcn_prot.keys[keyid - 6]);
344bfcc09ddSBjoern A. Zeeb 		if (!key)
345*a4128aadSBjoern A. Zeeb 			goto report;
346bfcc09ddSBjoern A. Zeeb 	}
347bfcc09ddSBjoern A. Zeeb 
348bfcc09ddSBjoern A. Zeeb 	/* Report status to mac80211 */
349bfcc09ddSBjoern A. Zeeb 	if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))
350bfcc09ddSBjoern A. Zeeb 		ieee80211_key_mic_failure(key);
351bfcc09ddSBjoern A. Zeeb 	else if (status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)
352bfcc09ddSBjoern A. Zeeb 		ieee80211_key_replay(key);
353*a4128aadSBjoern A. Zeeb report:
354*a4128aadSBjoern A. Zeeb 	wdev = ieee80211_vif_to_wdev(mvmsta->vif);
355*a4128aadSBjoern A. Zeeb 	if (wdev->netdev)
356*a4128aadSBjoern A. Zeeb 		cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr, len);
357bfcc09ddSBjoern A. Zeeb 
358bfcc09ddSBjoern A. Zeeb 	return -1;
359bfcc09ddSBjoern A. Zeeb }
360bfcc09ddSBjoern A. Zeeb 
361bfcc09ddSBjoern A. Zeeb static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
362bfcc09ddSBjoern A. Zeeb 			     struct ieee80211_hdr *hdr,
363bfcc09ddSBjoern A. Zeeb 			     struct ieee80211_rx_status *stats, u16 phy_info,
364bfcc09ddSBjoern A. Zeeb 			     struct iwl_rx_mpdu_desc *desc,
365bfcc09ddSBjoern A. Zeeb 			     u32 pkt_flags, int queue, u8 *crypt_len)
366bfcc09ddSBjoern A. Zeeb {
367bfcc09ddSBjoern A. Zeeb 	u32 status = le32_to_cpu(desc->status);
368bfcc09ddSBjoern A. Zeeb 
369bfcc09ddSBjoern A. Zeeb 	/*
370bfcc09ddSBjoern A. Zeeb 	 * Drop UNKNOWN frames in aggregation, unless in monitor mode
371bfcc09ddSBjoern A. Zeeb 	 * (where we don't have the keys).
372bfcc09ddSBjoern A. Zeeb 	 * We limit this to aggregation because in TKIP this is a valid
373bfcc09ddSBjoern A. Zeeb 	 * scenario, since we may not have the (correct) TTAK (phase 1
374bfcc09ddSBjoern A. Zeeb 	 * key) in the firmware.
375bfcc09ddSBjoern A. Zeeb 	 */
376bfcc09ddSBjoern A. Zeeb 	if (phy_info & IWL_RX_MPDU_PHY_AMPDU &&
377bfcc09ddSBjoern A. Zeeb 	    (status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
378*a4128aadSBjoern A. Zeeb 	    IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on) {
379*a4128aadSBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, "Dropping packets, bad enc status\n");
380bfcc09ddSBjoern A. Zeeb 		return -1;
381*a4128aadSBjoern A. Zeeb 	}
382bfcc09ddSBjoern A. Zeeb 
383bfcc09ddSBjoern A. Zeeb 	if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&
384bfcc09ddSBjoern A. Zeeb 		     !ieee80211_has_protected(hdr->frame_control)))
3859af1bba4SBjoern A. Zeeb 		return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats);
386bfcc09ddSBjoern A. Zeeb 
387bfcc09ddSBjoern A. Zeeb 	if (!ieee80211_has_protected(hdr->frame_control) ||
388bfcc09ddSBjoern A. Zeeb 	    (status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
389bfcc09ddSBjoern A. Zeeb 	    IWL_RX_MPDU_STATUS_SEC_NONE)
390bfcc09ddSBjoern A. Zeeb 		return 0;
391bfcc09ddSBjoern A. Zeeb 
392bfcc09ddSBjoern A. Zeeb 	/* TODO: handle packets encrypted with unknown alg */
393bfcc09ddSBjoern A. Zeeb #if defined(__FreeBSD__)
394bfcc09ddSBjoern A. Zeeb 	/* XXX-BZ do similar to rx.c for now as these are plenty. */
395bfcc09ddSBjoern A. Zeeb 	if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
396bfcc09ddSBjoern A. Zeeb 	    IWL_RX_MPDU_STATUS_SEC_ENC_ERR)
397bfcc09ddSBjoern A. Zeeb 		return (0);
398bfcc09ddSBjoern A. Zeeb #endif
399bfcc09ddSBjoern A. Zeeb 
400bfcc09ddSBjoern A. Zeeb 	switch (status & IWL_RX_MPDU_STATUS_SEC_MASK) {
401bfcc09ddSBjoern A. Zeeb 	case IWL_RX_MPDU_STATUS_SEC_CCM:
402bfcc09ddSBjoern A. Zeeb 	case IWL_RX_MPDU_STATUS_SEC_GCM:
403bfcc09ddSBjoern A. Zeeb 		BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != IEEE80211_GCMP_PN_LEN);
404bfcc09ddSBjoern A. Zeeb 		/* alg is CCM: check MIC only */
405*a4128aadSBjoern A. Zeeb 		if (!(status & IWL_RX_MPDU_STATUS_MIC_OK)) {
406*a4128aadSBjoern A. Zeeb 			IWL_DEBUG_DROP(mvm,
407*a4128aadSBjoern A. Zeeb 				       "Dropping packet, bad MIC (CCM/GCM)\n");
408bfcc09ddSBjoern A. Zeeb 			return -1;
409*a4128aadSBjoern A. Zeeb 		}
410bfcc09ddSBjoern A. Zeeb 
4119af1bba4SBjoern A. Zeeb 		stats->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MIC_STRIPPED;
412bfcc09ddSBjoern A. Zeeb 		*crypt_len = IEEE80211_CCMP_HDR_LEN;
413bfcc09ddSBjoern A. Zeeb 		return 0;
414bfcc09ddSBjoern A. Zeeb 	case IWL_RX_MPDU_STATUS_SEC_TKIP:
415bfcc09ddSBjoern A. Zeeb 		/* Don't drop the frame and decrypt it in SW */
416bfcc09ddSBjoern A. Zeeb 		if (!fw_has_api(&mvm->fw->ucode_capa,
417bfcc09ddSBjoern A. Zeeb 				IWL_UCODE_TLV_API_DEPRECATE_TTAK) &&
418bfcc09ddSBjoern A. Zeeb 		    !(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))
419bfcc09ddSBjoern A. Zeeb 			return 0;
420bfcc09ddSBjoern A. Zeeb 
421bfcc09ddSBjoern A. Zeeb 		if (mvm->trans->trans_cfg->gen2 &&
422bfcc09ddSBjoern A. Zeeb 		    !(status & RX_MPDU_RES_STATUS_MIC_OK))
423bfcc09ddSBjoern A. Zeeb 			stats->flag |= RX_FLAG_MMIC_ERROR;
424bfcc09ddSBjoern A. Zeeb 
425bfcc09ddSBjoern A. Zeeb 		*crypt_len = IEEE80211_TKIP_IV_LEN;
426bfcc09ddSBjoern A. Zeeb 		fallthrough;
427bfcc09ddSBjoern A. Zeeb 	case IWL_RX_MPDU_STATUS_SEC_WEP:
428bfcc09ddSBjoern A. Zeeb 		if (!(status & IWL_RX_MPDU_STATUS_ICV_OK))
429bfcc09ddSBjoern A. Zeeb 			return -1;
430bfcc09ddSBjoern A. Zeeb 
431bfcc09ddSBjoern A. Zeeb 		stats->flag |= RX_FLAG_DECRYPTED;
432bfcc09ddSBjoern A. Zeeb 		if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
433bfcc09ddSBjoern A. Zeeb 				IWL_RX_MPDU_STATUS_SEC_WEP)
434bfcc09ddSBjoern A. Zeeb 			*crypt_len = IEEE80211_WEP_IV_LEN;
435bfcc09ddSBjoern A. Zeeb 
436bfcc09ddSBjoern A. Zeeb 		if (pkt_flags & FH_RSCSR_RADA_EN) {
437bfcc09ddSBjoern A. Zeeb 			stats->flag |= RX_FLAG_ICV_STRIPPED;
438bfcc09ddSBjoern A. Zeeb 			if (mvm->trans->trans_cfg->gen2)
439bfcc09ddSBjoern A. Zeeb 				stats->flag |= RX_FLAG_MMIC_STRIPPED;
440bfcc09ddSBjoern A. Zeeb 		}
441bfcc09ddSBjoern A. Zeeb 
442bfcc09ddSBjoern A. Zeeb 		return 0;
443bfcc09ddSBjoern A. Zeeb 	case IWL_RX_MPDU_STATUS_SEC_EXT_ENC:
444bfcc09ddSBjoern A. Zeeb 		if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))
445bfcc09ddSBjoern A. Zeeb 			return -1;
446bfcc09ddSBjoern A. Zeeb 		stats->flag |= RX_FLAG_DECRYPTED;
447bfcc09ddSBjoern A. Zeeb 		return 0;
448bfcc09ddSBjoern A. Zeeb 	case RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC:
449bfcc09ddSBjoern A. Zeeb 		break;
450bfcc09ddSBjoern A. Zeeb 	default:
451bfcc09ddSBjoern A. Zeeb 		/*
452bfcc09ddSBjoern A. Zeeb 		 * Sometimes we can get frames that were not decrypted
453bfcc09ddSBjoern A. Zeeb 		 * because the firmware didn't have the keys yet. This can
454bfcc09ddSBjoern A. Zeeb 		 * happen after connection where we can get multicast frames
455bfcc09ddSBjoern A. Zeeb 		 * before the GTK is installed.
456bfcc09ddSBjoern A. Zeeb 		 * Silently drop those frames.
457bfcc09ddSBjoern A. Zeeb 		 * Also drop un-decrypted frames in monitor mode.
458bfcc09ddSBjoern A. Zeeb 		 */
459bfcc09ddSBjoern A. Zeeb 		if (!is_multicast_ether_addr(hdr->addr1) &&
460bfcc09ddSBjoern A. Zeeb 		    !mvm->monitor_on && net_ratelimit())
461d9836fb4SBjoern A. Zeeb #if defined(__linux__)
4629af1bba4SBjoern A. Zeeb 			IWL_WARN(mvm, "Unhandled alg: 0x%x\n", status);
463d9836fb4SBjoern A. Zeeb #elif defined(__FreeBSD__)
4649af1bba4SBjoern A. Zeeb 			IWL_WARN(mvm, "%s: Unhandled alg: 0x%x\n", __func__, status);
465d9836fb4SBjoern A. Zeeb #endif
466bfcc09ddSBjoern A. Zeeb 	}
467bfcc09ddSBjoern A. Zeeb 
468bfcc09ddSBjoern A. Zeeb 	return 0;
469bfcc09ddSBjoern A. Zeeb }
470bfcc09ddSBjoern A. Zeeb 
471bfcc09ddSBjoern A. Zeeb static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,
472bfcc09ddSBjoern A. Zeeb 			    struct ieee80211_sta *sta,
473bfcc09ddSBjoern A. Zeeb 			    struct sk_buff *skb,
474bfcc09ddSBjoern A. Zeeb 			    struct iwl_rx_packet *pkt)
475bfcc09ddSBjoern A. Zeeb {
476bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
477bfcc09ddSBjoern A. Zeeb 
478bfcc09ddSBjoern A. Zeeb 	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
479bfcc09ddSBjoern A. Zeeb 		if (pkt->len_n_flags & cpu_to_le32(FH_RSCSR_RPA_EN)) {
480bfcc09ddSBjoern A. Zeeb 			u16 hwsum = be16_to_cpu(desc->v3.raw_xsum);
481bfcc09ddSBjoern A. Zeeb 
482bfcc09ddSBjoern A. Zeeb 			skb->ip_summed = CHECKSUM_COMPLETE;
483bfcc09ddSBjoern A. Zeeb 			skb->csum = csum_unfold(~(__force __sum16)hwsum);
484bfcc09ddSBjoern A. Zeeb 		}
485bfcc09ddSBjoern A. Zeeb 	} else {
486bfcc09ddSBjoern A. Zeeb 		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
487bfcc09ddSBjoern A. Zeeb 		struct iwl_mvm_vif *mvmvif;
488bfcc09ddSBjoern A. Zeeb 		u16 flags = le16_to_cpu(desc->l3l4_flags);
489bfcc09ddSBjoern A. Zeeb 		u8 l3_prot = (u8)((flags & IWL_RX_L3L4_L3_PROTO_MASK) >>
490bfcc09ddSBjoern A. Zeeb 				  IWL_RX_L3_PROTO_POS);
491bfcc09ddSBjoern A. Zeeb 
492bfcc09ddSBjoern A. Zeeb 		mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
493bfcc09ddSBjoern A. Zeeb 
494bfcc09ddSBjoern A. Zeeb 		if (mvmvif->features & NETIF_F_RXCSUM &&
495bfcc09ddSBjoern A. Zeeb 		    flags & IWL_RX_L3L4_TCP_UDP_CSUM_OK &&
496bfcc09ddSBjoern A. Zeeb 		    (flags & IWL_RX_L3L4_IP_HDR_CSUM_OK ||
497bfcc09ddSBjoern A. Zeeb 		     l3_prot == IWL_RX_L3_TYPE_IPV6 ||
498bfcc09ddSBjoern A. Zeeb 		     l3_prot == IWL_RX_L3_TYPE_IPV6_FRAG))
499bfcc09ddSBjoern A. Zeeb 			skb->ip_summed = CHECKSUM_UNNECESSARY;
500bfcc09ddSBjoern A. Zeeb 	}
501bfcc09ddSBjoern A. Zeeb }
502bfcc09ddSBjoern A. Zeeb 
503bfcc09ddSBjoern A. Zeeb /*
5049af1bba4SBjoern A. Zeeb  * returns true if a packet is a duplicate or invalid tid and should be dropped.
505bfcc09ddSBjoern A. Zeeb  * Updates AMSDU PN tracking info
506bfcc09ddSBjoern A. Zeeb  */
507bfcc09ddSBjoern A. Zeeb static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
508bfcc09ddSBjoern A. Zeeb 			   struct ieee80211_rx_status *rx_status,
509bfcc09ddSBjoern A. Zeeb 			   struct ieee80211_hdr *hdr,
510bfcc09ddSBjoern A. Zeeb 			   struct iwl_rx_mpdu_desc *desc)
511bfcc09ddSBjoern A. Zeeb {
512bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_sta *mvm_sta;
513bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_rxq_dup_data *dup_data;
514bfcc09ddSBjoern A. Zeeb 	u8 tid, sub_frame_idx;
515bfcc09ddSBjoern A. Zeeb 
516bfcc09ddSBjoern A. Zeeb 	if (WARN_ON(IS_ERR_OR_NULL(sta)))
517bfcc09ddSBjoern A. Zeeb 		return false;
518bfcc09ddSBjoern A. Zeeb 
519bfcc09ddSBjoern A. Zeeb 	mvm_sta = iwl_mvm_sta_from_mac80211(sta);
520*a4128aadSBjoern A. Zeeb 
521*a4128aadSBjoern A. Zeeb 	if (WARN_ON_ONCE(!mvm_sta->dup_data))
522586c8e32SBjoern A. Zeeb 		return false;
523*a4128aadSBjoern A. Zeeb 
524bfcc09ddSBjoern A. Zeeb 	dup_data = &mvm_sta->dup_data[queue];
525bfcc09ddSBjoern A. Zeeb 
526bfcc09ddSBjoern A. Zeeb 	/*
527bfcc09ddSBjoern A. Zeeb 	 * Drop duplicate 802.11 retransmissions
528bfcc09ddSBjoern A. Zeeb 	 * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
529bfcc09ddSBjoern A. Zeeb 	 */
530bfcc09ddSBjoern A. Zeeb 	if (ieee80211_is_ctl(hdr->frame_control) ||
531*a4128aadSBjoern A. Zeeb 	    ieee80211_is_any_nullfunc(hdr->frame_control) ||
532*a4128aadSBjoern A. Zeeb 	    is_multicast_ether_addr(hdr->addr1))
533bfcc09ddSBjoern A. Zeeb 		return false;
534bfcc09ddSBjoern A. Zeeb 
5359af1bba4SBjoern A. Zeeb 	if (ieee80211_is_data_qos(hdr->frame_control)) {
536bfcc09ddSBjoern A. Zeeb 		/* frame has qos control */
537bfcc09ddSBjoern A. Zeeb 		tid = ieee80211_get_tid(hdr);
5389af1bba4SBjoern A. Zeeb 		if (tid >= IWL_MAX_TID_COUNT)
5399af1bba4SBjoern A. Zeeb 			return true;
5409af1bba4SBjoern A. Zeeb 	} else {
541bfcc09ddSBjoern A. Zeeb 		tid = IWL_MAX_TID_COUNT;
5429af1bba4SBjoern A. Zeeb 	}
543bfcc09ddSBjoern A. Zeeb 
544bfcc09ddSBjoern A. Zeeb 	/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
545bfcc09ddSBjoern A. Zeeb 	sub_frame_idx = desc->amsdu_info &
546bfcc09ddSBjoern A. Zeeb 		IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
547bfcc09ddSBjoern A. Zeeb 
548bfcc09ddSBjoern A. Zeeb 	if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
549bfcc09ddSBjoern A. Zeeb 		     dup_data->last_seq[tid] == hdr->seq_ctrl &&
550bfcc09ddSBjoern A. Zeeb 		     dup_data->last_sub_frame[tid] >= sub_frame_idx))
551bfcc09ddSBjoern A. Zeeb 		return true;
552bfcc09ddSBjoern A. Zeeb 
553bfcc09ddSBjoern A. Zeeb 	/* Allow same PN as the first subframe for following sub frames */
554bfcc09ddSBjoern A. Zeeb 	if (dup_data->last_seq[tid] == hdr->seq_ctrl &&
555bfcc09ddSBjoern A. Zeeb 	    sub_frame_idx > dup_data->last_sub_frame[tid] &&
556bfcc09ddSBjoern A. Zeeb 	    desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU)
557bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_ALLOW_SAME_PN;
558bfcc09ddSBjoern A. Zeeb 
559bfcc09ddSBjoern A. Zeeb 	dup_data->last_seq[tid] = hdr->seq_ctrl;
560bfcc09ddSBjoern A. Zeeb 	dup_data->last_sub_frame[tid] = sub_frame_idx;
561bfcc09ddSBjoern A. Zeeb 
562bfcc09ddSBjoern A. Zeeb 	rx_status->flag |= RX_FLAG_DUP_VALIDATED;
563bfcc09ddSBjoern A. Zeeb 
564bfcc09ddSBjoern A. Zeeb 	return false;
565bfcc09ddSBjoern A. Zeeb }
566bfcc09ddSBjoern A. Zeeb 
567bfcc09ddSBjoern A. Zeeb static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
568bfcc09ddSBjoern A. Zeeb 				   struct ieee80211_sta *sta,
569bfcc09ddSBjoern A. Zeeb 				   struct napi_struct *napi,
570bfcc09ddSBjoern A. Zeeb 				   struct iwl_mvm_baid_data *baid_data,
571bfcc09ddSBjoern A. Zeeb 				   struct iwl_mvm_reorder_buffer *reorder_buf,
572*a4128aadSBjoern A. Zeeb 				   u16 nssn)
573bfcc09ddSBjoern A. Zeeb {
574bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_reorder_buf_entry *entries =
575bfcc09ddSBjoern A. Zeeb 		&baid_data->entries[reorder_buf->queue *
576bfcc09ddSBjoern A. Zeeb 				    baid_data->entries_per_queue];
577bfcc09ddSBjoern A. Zeeb 	u16 ssn = reorder_buf->head_sn;
578bfcc09ddSBjoern A. Zeeb 
579bfcc09ddSBjoern A. Zeeb 	lockdep_assert_held(&reorder_buf->lock);
580bfcc09ddSBjoern A. Zeeb 
581*a4128aadSBjoern A. Zeeb 	while (ieee80211_sn_less(ssn, nssn)) {
582*a4128aadSBjoern A. Zeeb 		int index = ssn % baid_data->buf_size;
583*a4128aadSBjoern A. Zeeb 		struct sk_buff_head *skb_list = &entries[index].frames;
584bfcc09ddSBjoern A. Zeeb 		struct sk_buff *skb;
585bfcc09ddSBjoern A. Zeeb 
586bfcc09ddSBjoern A. Zeeb 		ssn = ieee80211_sn_inc(ssn);
587bfcc09ddSBjoern A. Zeeb 
588bfcc09ddSBjoern A. Zeeb 		/*
589bfcc09ddSBjoern A. Zeeb 		 * Empty the list. Will have more than one frame for A-MSDU.
590bfcc09ddSBjoern A. Zeeb 		 * Empty list is valid as well since nssn indicates frames were
591bfcc09ddSBjoern A. Zeeb 		 * received.
592bfcc09ddSBjoern A. Zeeb 		 */
593bfcc09ddSBjoern A. Zeeb 		while ((skb = __skb_dequeue(skb_list))) {
594bfcc09ddSBjoern A. Zeeb 			iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
595bfcc09ddSBjoern A. Zeeb 							reorder_buf->queue,
596*a4128aadSBjoern A. Zeeb 							sta);
597bfcc09ddSBjoern A. Zeeb 			reorder_buf->num_stored--;
598bfcc09ddSBjoern A. Zeeb 		}
599bfcc09ddSBjoern A. Zeeb 	}
600bfcc09ddSBjoern A. Zeeb 	reorder_buf->head_sn = nssn;
601bfcc09ddSBjoern A. Zeeb }
602bfcc09ddSBjoern A. Zeeb 
603bfcc09ddSBjoern A. Zeeb static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
604bfcc09ddSBjoern A. Zeeb 			   struct iwl_mvm_delba_data *data)
605bfcc09ddSBjoern A. Zeeb {
606bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_baid_data *ba_data;
607bfcc09ddSBjoern A. Zeeb 	struct ieee80211_sta *sta;
608bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_reorder_buffer *reorder_buf;
609bfcc09ddSBjoern A. Zeeb 	u8 baid = data->baid;
6109af1bba4SBjoern A. Zeeb 	u32 sta_id;
611bfcc09ddSBjoern A. Zeeb 
612bfcc09ddSBjoern A. Zeeb 	if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
613bfcc09ddSBjoern A. Zeeb 		return;
614bfcc09ddSBjoern A. Zeeb 
615bfcc09ddSBjoern A. Zeeb 	rcu_read_lock();
616bfcc09ddSBjoern A. Zeeb 
617bfcc09ddSBjoern A. Zeeb 	ba_data = rcu_dereference(mvm->baid_map[baid]);
618bfcc09ddSBjoern A. Zeeb 	if (WARN_ON_ONCE(!ba_data))
619bfcc09ddSBjoern A. Zeeb 		goto out;
620bfcc09ddSBjoern A. Zeeb 
6219af1bba4SBjoern A. Zeeb 	/* pick any STA ID to find the pointer */
6229af1bba4SBjoern A. Zeeb 	sta_id = ffs(ba_data->sta_mask) - 1;
6239af1bba4SBjoern A. Zeeb 	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
624bfcc09ddSBjoern A. Zeeb 	if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
625bfcc09ddSBjoern A. Zeeb 		goto out;
626bfcc09ddSBjoern A. Zeeb 
627bfcc09ddSBjoern A. Zeeb 	reorder_buf = &ba_data->reorder_buf[queue];
628bfcc09ddSBjoern A. Zeeb 
629bfcc09ddSBjoern A. Zeeb 	/* release all frames that are in the reorder buffer to the stack */
630bfcc09ddSBjoern A. Zeeb 	spin_lock_bh(&reorder_buf->lock);
631bfcc09ddSBjoern A. Zeeb 	iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
632bfcc09ddSBjoern A. Zeeb 			       ieee80211_sn_add(reorder_buf->head_sn,
633*a4128aadSBjoern A. Zeeb 						ba_data->buf_size));
634bfcc09ddSBjoern A. Zeeb 	spin_unlock_bh(&reorder_buf->lock);
635bfcc09ddSBjoern A. Zeeb 
636bfcc09ddSBjoern A. Zeeb out:
637bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
638bfcc09ddSBjoern A. Zeeb }
639bfcc09ddSBjoern A. Zeeb 
640bfcc09ddSBjoern A. Zeeb static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
641bfcc09ddSBjoern A. Zeeb 					      struct napi_struct *napi,
642*a4128aadSBjoern A. Zeeb 					      u8 baid, u16 nssn, int queue)
643bfcc09ddSBjoern A. Zeeb {
644bfcc09ddSBjoern A. Zeeb 	struct ieee80211_sta *sta;
645bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_reorder_buffer *reorder_buf;
646bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_baid_data *ba_data;
6479af1bba4SBjoern A. Zeeb 	u32 sta_id;
648bfcc09ddSBjoern A. Zeeb 
649bfcc09ddSBjoern A. Zeeb 	IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
650bfcc09ddSBjoern A. Zeeb 		     baid, nssn);
651bfcc09ddSBjoern A. Zeeb 
652bfcc09ddSBjoern A. Zeeb 	if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
653bfcc09ddSBjoern A. Zeeb 			 baid >= ARRAY_SIZE(mvm->baid_map)))
654bfcc09ddSBjoern A. Zeeb 		return;
655bfcc09ddSBjoern A. Zeeb 
656bfcc09ddSBjoern A. Zeeb 	rcu_read_lock();
657bfcc09ddSBjoern A. Zeeb 
658bfcc09ddSBjoern A. Zeeb 	ba_data = rcu_dereference(mvm->baid_map[baid]);
659*a4128aadSBjoern A. Zeeb 	if (WARN(!ba_data, "BAID %d not found in map\n", baid))
660bfcc09ddSBjoern A. Zeeb 		goto out;
661bfcc09ddSBjoern A. Zeeb 
6629af1bba4SBjoern A. Zeeb 	/* pick any STA ID to find the pointer */
6639af1bba4SBjoern A. Zeeb 	sta_id = ffs(ba_data->sta_mask) - 1;
6649af1bba4SBjoern A. Zeeb 	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
665bfcc09ddSBjoern A. Zeeb 	if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
666bfcc09ddSBjoern A. Zeeb 		goto out;
667bfcc09ddSBjoern A. Zeeb 
668bfcc09ddSBjoern A. Zeeb 	reorder_buf = &ba_data->reorder_buf[queue];
669bfcc09ddSBjoern A. Zeeb 
670bfcc09ddSBjoern A. Zeeb 	spin_lock_bh(&reorder_buf->lock);
671bfcc09ddSBjoern A. Zeeb 	iwl_mvm_release_frames(mvm, sta, napi, ba_data,
672*a4128aadSBjoern A. Zeeb 			       reorder_buf, nssn);
673bfcc09ddSBjoern A. Zeeb 	spin_unlock_bh(&reorder_buf->lock);
674bfcc09ddSBjoern A. Zeeb 
675bfcc09ddSBjoern A. Zeeb out:
676bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
677bfcc09ddSBjoern A. Zeeb }
678bfcc09ddSBjoern A. Zeeb 
679bfcc09ddSBjoern A. Zeeb void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
680bfcc09ddSBjoern A. Zeeb 			    struct iwl_rx_cmd_buffer *rxb, int queue)
681bfcc09ddSBjoern A. Zeeb {
682bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
683bfcc09ddSBjoern A. Zeeb 	struct iwl_rxq_sync_notification *notif;
684bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_internal_rxq_notif *internal_notif;
685bfcc09ddSBjoern A. Zeeb 	u32 len = iwl_rx_packet_payload_len(pkt);
686bfcc09ddSBjoern A. Zeeb 
687bfcc09ddSBjoern A. Zeeb 	notif = (void *)pkt->data;
688bfcc09ddSBjoern A. Zeeb 	internal_notif = (void *)notif->payload;
689bfcc09ddSBjoern A. Zeeb 
690bfcc09ddSBjoern A. Zeeb 	if (WARN_ONCE(len < sizeof(*notif) + sizeof(*internal_notif),
691bfcc09ddSBjoern A. Zeeb 		      "invalid notification size %d (%d)",
692bfcc09ddSBjoern A. Zeeb 		      len, (int)(sizeof(*notif) + sizeof(*internal_notif))))
693bfcc09ddSBjoern A. Zeeb 		return;
694bfcc09ddSBjoern A. Zeeb 	len -= sizeof(*notif) + sizeof(*internal_notif);
695bfcc09ddSBjoern A. Zeeb 
696*a4128aadSBjoern A. Zeeb 	if (WARN_ONCE(internal_notif->sync &&
697*a4128aadSBjoern A. Zeeb 		      mvm->queue_sync_cookie != internal_notif->cookie,
698*a4128aadSBjoern A. Zeeb 		      "Received expired RX queue sync message (cookie %d but wanted %d, queue %d)\n",
699*a4128aadSBjoern A. Zeeb 		      internal_notif->cookie, mvm->queue_sync_cookie, queue))
700bfcc09ddSBjoern A. Zeeb 		return;
701bfcc09ddSBjoern A. Zeeb 
702bfcc09ddSBjoern A. Zeeb 	switch (internal_notif->type) {
703bfcc09ddSBjoern A. Zeeb 	case IWL_MVM_RXQ_EMPTY:
704bfcc09ddSBjoern A. Zeeb 		WARN_ONCE(len, "invalid empty notification size %d", len);
705bfcc09ddSBjoern A. Zeeb 		break;
706bfcc09ddSBjoern A. Zeeb 	case IWL_MVM_RXQ_NOTIF_DEL_BA:
707bfcc09ddSBjoern A. Zeeb 		if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data),
708bfcc09ddSBjoern A. Zeeb 			      "invalid delba notification size %d (%d)",
709bfcc09ddSBjoern A. Zeeb 			      len, (int)sizeof(struct iwl_mvm_delba_data)))
710bfcc09ddSBjoern A. Zeeb 			break;
711bfcc09ddSBjoern A. Zeeb 		iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
712bfcc09ddSBjoern A. Zeeb 		break;
713bfcc09ddSBjoern A. Zeeb 	default:
714bfcc09ddSBjoern A. Zeeb 		WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
715bfcc09ddSBjoern A. Zeeb 	}
716bfcc09ddSBjoern A. Zeeb 
717bfcc09ddSBjoern A. Zeeb 	if (internal_notif->sync) {
718bfcc09ddSBjoern A. Zeeb 		WARN_ONCE(!test_and_clear_bit(queue, &mvm->queue_sync_state),
719bfcc09ddSBjoern A. Zeeb 			  "queue sync: queue %d responded a second time!\n",
720bfcc09ddSBjoern A. Zeeb 			  queue);
721bfcc09ddSBjoern A. Zeeb 		if (READ_ONCE(mvm->queue_sync_state) == 0)
722bfcc09ddSBjoern A. Zeeb 			wake_up(&mvm->rx_sync_waitq);
723bfcc09ddSBjoern A. Zeeb 	}
724bfcc09ddSBjoern A. Zeeb }
725bfcc09ddSBjoern A. Zeeb 
726bfcc09ddSBjoern A. Zeeb /*
727bfcc09ddSBjoern A. Zeeb  * Returns true if the MPDU was buffered\dropped, false if it should be passed
728bfcc09ddSBjoern A. Zeeb  * to upper layer.
729bfcc09ddSBjoern A. Zeeb  */
730bfcc09ddSBjoern A. Zeeb static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
731bfcc09ddSBjoern A. Zeeb 			    struct napi_struct *napi,
732bfcc09ddSBjoern A. Zeeb 			    int queue,
733bfcc09ddSBjoern A. Zeeb 			    struct ieee80211_sta *sta,
734bfcc09ddSBjoern A. Zeeb 			    struct sk_buff *skb,
735bfcc09ddSBjoern A. Zeeb 			    struct iwl_rx_mpdu_desc *desc)
736bfcc09ddSBjoern A. Zeeb {
7379af1bba4SBjoern A. Zeeb 	struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
738bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_baid_data *baid_data;
739bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_reorder_buffer *buffer;
740bfcc09ddSBjoern A. Zeeb 	u32 reorder = le32_to_cpu(desc->reorder_data);
741bfcc09ddSBjoern A. Zeeb 	bool amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
742bfcc09ddSBjoern A. Zeeb 	bool last_subframe =
743bfcc09ddSBjoern A. Zeeb 		desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME;
74426a36948SBjoern A. Zeeb #if defined(__linux__)
745bfcc09ddSBjoern A. Zeeb 	u8 tid = ieee80211_get_tid(hdr);
74626a36948SBjoern A. Zeeb #elif defined(__FreeBSD__)
74726a36948SBjoern A. Zeeb 	u8 tid;
74826a36948SBjoern A. Zeeb #endif
749bfcc09ddSBjoern A. Zeeb 	u8 sub_frame_idx = desc->amsdu_info &
750bfcc09ddSBjoern A. Zeeb 			   IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
751bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_reorder_buf_entry *entries;
7529af1bba4SBjoern A. Zeeb 	u32 sta_mask;
753bfcc09ddSBjoern A. Zeeb 	int index;
754bfcc09ddSBjoern A. Zeeb 	u16 nssn, sn;
755bfcc09ddSBjoern A. Zeeb 	u8 baid;
756bfcc09ddSBjoern A. Zeeb 
757bfcc09ddSBjoern A. Zeeb 	baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
758bfcc09ddSBjoern A. Zeeb 		IWL_RX_MPDU_REORDER_BAID_SHIFT;
759bfcc09ddSBjoern A. Zeeb 
760*a4128aadSBjoern A. Zeeb 	if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000)
761*a4128aadSBjoern A. Zeeb 		return false;
762*a4128aadSBjoern A. Zeeb 
763bfcc09ddSBjoern A. Zeeb 	/*
764bfcc09ddSBjoern A. Zeeb 	 * This also covers the case of receiving a Block Ack Request
765bfcc09ddSBjoern A. Zeeb 	 * outside a BA session; we'll pass it to mac80211 and that
766bfcc09ddSBjoern A. Zeeb 	 * then sends a delBA action frame.
767bfcc09ddSBjoern A. Zeeb 	 * This also covers pure monitor mode, in which case we won't
768bfcc09ddSBjoern A. Zeeb 	 * have any BA sessions.
769bfcc09ddSBjoern A. Zeeb 	 */
770bfcc09ddSBjoern A. Zeeb 	if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
771bfcc09ddSBjoern A. Zeeb 		return false;
772bfcc09ddSBjoern A. Zeeb 
773bfcc09ddSBjoern A. Zeeb 	/* no sta yet */
774bfcc09ddSBjoern A. Zeeb 	if (WARN_ONCE(IS_ERR_OR_NULL(sta),
775bfcc09ddSBjoern A. Zeeb 		      "Got valid BAID without a valid station assigned\n"))
776bfcc09ddSBjoern A. Zeeb 		return false;
777bfcc09ddSBjoern A. Zeeb 
778bfcc09ddSBjoern A. Zeeb 	/* not a data packet or a bar */
779bfcc09ddSBjoern A. Zeeb 	if (!ieee80211_is_back_req(hdr->frame_control) &&
780bfcc09ddSBjoern A. Zeeb 	    (!ieee80211_is_data_qos(hdr->frame_control) ||
781bfcc09ddSBjoern A. Zeeb 	     is_multicast_ether_addr(hdr->addr1)))
782bfcc09ddSBjoern A. Zeeb 		return false;
783bfcc09ddSBjoern A. Zeeb 
784bfcc09ddSBjoern A. Zeeb 	if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
785bfcc09ddSBjoern A. Zeeb 		return false;
786bfcc09ddSBjoern A. Zeeb 
787bfcc09ddSBjoern A. Zeeb 	baid_data = rcu_dereference(mvm->baid_map[baid]);
788bfcc09ddSBjoern A. Zeeb 	if (!baid_data) {
789bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_RX(mvm,
790bfcc09ddSBjoern A. Zeeb 			     "Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",
791bfcc09ddSBjoern A. Zeeb 			      baid, reorder);
792bfcc09ddSBjoern A. Zeeb 		return false;
793bfcc09ddSBjoern A. Zeeb 	}
794bfcc09ddSBjoern A. Zeeb 
79526a36948SBjoern A. Zeeb #if defined(__FreeBSD__)
79626a36948SBjoern A. Zeeb 	tid = ieee80211_get_tid(hdr);
79726a36948SBjoern A. Zeeb #endif
7989af1bba4SBjoern A. Zeeb 	rcu_read_lock();
7999af1bba4SBjoern A. Zeeb 	sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
8009af1bba4SBjoern A. Zeeb 	rcu_read_unlock();
8019af1bba4SBjoern A. Zeeb 
8029af1bba4SBjoern A. Zeeb 	if (IWL_FW_CHECK(mvm,
8039af1bba4SBjoern A. Zeeb 			 tid != baid_data->tid ||
8049af1bba4SBjoern A. Zeeb 			 !(sta_mask & baid_data->sta_mask),
8059af1bba4SBjoern A. Zeeb 			 "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
8069af1bba4SBjoern A. Zeeb 			 baid, baid_data->sta_mask, baid_data->tid,
8079af1bba4SBjoern A. Zeeb 			 sta_mask, tid))
808bfcc09ddSBjoern A. Zeeb 		return false;
809bfcc09ddSBjoern A. Zeeb 
810bfcc09ddSBjoern A. Zeeb 	nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
811bfcc09ddSBjoern A. Zeeb 	sn = (reorder & IWL_RX_MPDU_REORDER_SN_MASK) >>
812bfcc09ddSBjoern A. Zeeb 		IWL_RX_MPDU_REORDER_SN_SHIFT;
813bfcc09ddSBjoern A. Zeeb 
814bfcc09ddSBjoern A. Zeeb 	buffer = &baid_data->reorder_buf[queue];
815bfcc09ddSBjoern A. Zeeb 	entries = &baid_data->entries[queue * baid_data->entries_per_queue];
816bfcc09ddSBjoern A. Zeeb 
817bfcc09ddSBjoern A. Zeeb 	spin_lock_bh(&buffer->lock);
818bfcc09ddSBjoern A. Zeeb 
819bfcc09ddSBjoern A. Zeeb 	if (!buffer->valid) {
820bfcc09ddSBjoern A. Zeeb 		if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN) {
821bfcc09ddSBjoern A. Zeeb 			spin_unlock_bh(&buffer->lock);
822bfcc09ddSBjoern A. Zeeb 			return false;
823bfcc09ddSBjoern A. Zeeb 		}
824bfcc09ddSBjoern A. Zeeb 		buffer->valid = true;
825bfcc09ddSBjoern A. Zeeb 	}
826bfcc09ddSBjoern A. Zeeb 
827*a4128aadSBjoern A. Zeeb 	/* drop any duplicated packets */
828*a4128aadSBjoern A. Zeeb 	if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE))
829bfcc09ddSBjoern A. Zeeb 		goto drop;
830bfcc09ddSBjoern A. Zeeb 
831bfcc09ddSBjoern A. Zeeb 	/* drop any oudated packets */
832*a4128aadSBjoern A. Zeeb 	if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN)
833bfcc09ddSBjoern A. Zeeb 		goto drop;
834bfcc09ddSBjoern A. Zeeb 
835bfcc09ddSBjoern A. Zeeb 	/* release immediately if allowed by nssn and no stored frames */
836bfcc09ddSBjoern A. Zeeb 	if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
837*a4128aadSBjoern A. Zeeb 		if (!amsdu || last_subframe)
838bfcc09ddSBjoern A. Zeeb 			buffer->head_sn = nssn;
839bfcc09ddSBjoern A. Zeeb 		/* No need to update AMSDU last SN - we are moving the head */
840bfcc09ddSBjoern A. Zeeb 		spin_unlock_bh(&buffer->lock);
841bfcc09ddSBjoern A. Zeeb 		return false;
842bfcc09ddSBjoern A. Zeeb 	}
843bfcc09ddSBjoern A. Zeeb 
844bfcc09ddSBjoern A. Zeeb 	/*
845bfcc09ddSBjoern A. Zeeb 	 * release immediately if there are no stored frames, and the sn is
846bfcc09ddSBjoern A. Zeeb 	 * equal to the head.
847bfcc09ddSBjoern A. Zeeb 	 * This can happen due to reorder timer, where NSSN is behind head_sn.
848bfcc09ddSBjoern A. Zeeb 	 * When we released everything, and we got the next frame in the
849bfcc09ddSBjoern A. Zeeb 	 * sequence, according to the NSSN we can't release immediately,
850bfcc09ddSBjoern A. Zeeb 	 * while technically there is no hole and we can move forward.
851bfcc09ddSBjoern A. Zeeb 	 */
852bfcc09ddSBjoern A. Zeeb 	if (!buffer->num_stored && sn == buffer->head_sn) {
853*a4128aadSBjoern A. Zeeb 		if (!amsdu || last_subframe)
854bfcc09ddSBjoern A. Zeeb 			buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
855*a4128aadSBjoern A. Zeeb 
856bfcc09ddSBjoern A. Zeeb 		/* No need to update AMSDU last SN - we are moving the head */
857bfcc09ddSBjoern A. Zeeb 		spin_unlock_bh(&buffer->lock);
858bfcc09ddSBjoern A. Zeeb 		return false;
859bfcc09ddSBjoern A. Zeeb 	}
860bfcc09ddSBjoern A. Zeeb 
861bfcc09ddSBjoern A. Zeeb 	/* put in reorder buffer */
862*a4128aadSBjoern A. Zeeb 	index = sn % baid_data->buf_size;
863*a4128aadSBjoern A. Zeeb 	__skb_queue_tail(&entries[index].frames, skb);
864bfcc09ddSBjoern A. Zeeb 	buffer->num_stored++;
865bfcc09ddSBjoern A. Zeeb 
866bfcc09ddSBjoern A. Zeeb 	if (amsdu) {
867bfcc09ddSBjoern A. Zeeb 		buffer->last_amsdu = sn;
868bfcc09ddSBjoern A. Zeeb 		buffer->last_sub_index = sub_frame_idx;
869bfcc09ddSBjoern A. Zeeb 	}
870bfcc09ddSBjoern A. Zeeb 
871bfcc09ddSBjoern A. Zeeb 	/*
872bfcc09ddSBjoern A. Zeeb 	 * We cannot trust NSSN for AMSDU sub-frames that are not the last.
873bfcc09ddSBjoern A. Zeeb 	 * The reason is that NSSN advances on the first sub-frame, and may
874bfcc09ddSBjoern A. Zeeb 	 * cause the reorder buffer to advance before all the sub-frames arrive.
875bfcc09ddSBjoern A. Zeeb 	 * Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with
876bfcc09ddSBjoern A. Zeeb 	 * SN 1. NSSN for first sub frame will be 3 with the result of driver
877bfcc09ddSBjoern A. Zeeb 	 * releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is
878bfcc09ddSBjoern A. Zeeb 	 * already ahead and it will be dropped.
879bfcc09ddSBjoern A. Zeeb 	 * If the last sub-frame is not on this queue - we will get frame
880bfcc09ddSBjoern A. Zeeb 	 * release notification with up to date NSSN.
881bfcc09ddSBjoern A. Zeeb 	 */
882bfcc09ddSBjoern A. Zeeb 	if (!amsdu || last_subframe)
883bfcc09ddSBjoern A. Zeeb 		iwl_mvm_release_frames(mvm, sta, napi, baid_data,
884*a4128aadSBjoern A. Zeeb 				       buffer, nssn);
885bfcc09ddSBjoern A. Zeeb 
886bfcc09ddSBjoern A. Zeeb 	spin_unlock_bh(&buffer->lock);
887bfcc09ddSBjoern A. Zeeb 	return true;
888bfcc09ddSBjoern A. Zeeb 
889bfcc09ddSBjoern A. Zeeb drop:
890bfcc09ddSBjoern A. Zeeb 	kfree_skb(skb);
891bfcc09ddSBjoern A. Zeeb 	spin_unlock_bh(&buffer->lock);
892bfcc09ddSBjoern A. Zeeb 	return true;
893bfcc09ddSBjoern A. Zeeb }
894bfcc09ddSBjoern A. Zeeb 
895bfcc09ddSBjoern A. Zeeb static void iwl_mvm_agg_rx_received(struct iwl_mvm *mvm,
896bfcc09ddSBjoern A. Zeeb 				    u32 reorder_data, u8 baid)
897bfcc09ddSBjoern A. Zeeb {
898bfcc09ddSBjoern A. Zeeb 	unsigned long now = jiffies;
899bfcc09ddSBjoern A. Zeeb 	unsigned long timeout;
900bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_baid_data *data;
901bfcc09ddSBjoern A. Zeeb 
902bfcc09ddSBjoern A. Zeeb 	rcu_read_lock();
903bfcc09ddSBjoern A. Zeeb 
904bfcc09ddSBjoern A. Zeeb 	data = rcu_dereference(mvm->baid_map[baid]);
905bfcc09ddSBjoern A. Zeeb 	if (!data) {
906bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_RX(mvm,
907bfcc09ddSBjoern A. Zeeb 			     "Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",
908bfcc09ddSBjoern A. Zeeb 			      baid, reorder_data);
909bfcc09ddSBjoern A. Zeeb 		goto out;
910bfcc09ddSBjoern A. Zeeb 	}
911bfcc09ddSBjoern A. Zeeb 
912bfcc09ddSBjoern A. Zeeb 	if (!data->timeout)
913bfcc09ddSBjoern A. Zeeb 		goto out;
914bfcc09ddSBjoern A. Zeeb 
915bfcc09ddSBjoern A. Zeeb 	timeout = data->timeout;
916bfcc09ddSBjoern A. Zeeb 	/*
917bfcc09ddSBjoern A. Zeeb 	 * Do not update last rx all the time to avoid cache bouncing
918bfcc09ddSBjoern A. Zeeb 	 * between the rx queues.
919bfcc09ddSBjoern A. Zeeb 	 * Update it every timeout. Worst case is the session will
920bfcc09ddSBjoern A. Zeeb 	 * expire after ~ 2 * timeout, which doesn't matter that much.
921bfcc09ddSBjoern A. Zeeb 	 */
922bfcc09ddSBjoern A. Zeeb 	if (time_before(data->last_rx + TU_TO_JIFFIES(timeout), now))
923bfcc09ddSBjoern A. Zeeb 		/* Update is atomic */
924bfcc09ddSBjoern A. Zeeb 		data->last_rx = now;
925bfcc09ddSBjoern A. Zeeb 
926bfcc09ddSBjoern A. Zeeb out:
927bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
928bfcc09ddSBjoern A. Zeeb }
929bfcc09ddSBjoern A. Zeeb 
930bfcc09ddSBjoern A. Zeeb static void iwl_mvm_flip_address(u8 *addr)
931bfcc09ddSBjoern A. Zeeb {
932bfcc09ddSBjoern A. Zeeb 	int i;
933bfcc09ddSBjoern A. Zeeb 	u8 mac_addr[ETH_ALEN];
934bfcc09ddSBjoern A. Zeeb 
935bfcc09ddSBjoern A. Zeeb 	for (i = 0; i < ETH_ALEN; i++)
936bfcc09ddSBjoern A. Zeeb 		mac_addr[i] = addr[ETH_ALEN - i - 1];
937bfcc09ddSBjoern A. Zeeb 	ether_addr_copy(addr, mac_addr);
938bfcc09ddSBjoern A. Zeeb }
939bfcc09ddSBjoern A. Zeeb 
940bfcc09ddSBjoern A. Zeeb struct iwl_mvm_rx_phy_data {
941bfcc09ddSBjoern A. Zeeb 	enum iwl_rx_phy_info_type info_type;
9429af1bba4SBjoern A. Zeeb 	__le32 d0, d1, d2, d3, eht_d4, d5;
943bfcc09ddSBjoern A. Zeeb 	__le16 d4;
9449af1bba4SBjoern A. Zeeb 	bool with_data;
9459af1bba4SBjoern A. Zeeb 	bool first_subframe;
9469af1bba4SBjoern A. Zeeb 	__le32 rx_vec[4];
9479af1bba4SBjoern A. Zeeb 
9489af1bba4SBjoern A. Zeeb 	u32 rate_n_flags;
9499af1bba4SBjoern A. Zeeb 	u32 gp2_on_air_rise;
9509af1bba4SBjoern A. Zeeb 	u16 phy_info;
9519af1bba4SBjoern A. Zeeb 	u8 energy_a, energy_b;
9529af1bba4SBjoern A. Zeeb 	u8 channel;
953bfcc09ddSBjoern A. Zeeb };
954bfcc09ddSBjoern A. Zeeb 
955bfcc09ddSBjoern A. Zeeb static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm,
956bfcc09ddSBjoern A. Zeeb 				     struct iwl_mvm_rx_phy_data *phy_data,
957bfcc09ddSBjoern A. Zeeb 				     struct ieee80211_radiotap_he_mu *he_mu)
958bfcc09ddSBjoern A. Zeeb {
959bfcc09ddSBjoern A. Zeeb 	u32 phy_data2 = le32_to_cpu(phy_data->d2);
960bfcc09ddSBjoern A. Zeeb 	u32 phy_data3 = le32_to_cpu(phy_data->d3);
961bfcc09ddSBjoern A. Zeeb 	u16 phy_data4 = le16_to_cpu(phy_data->d4);
9629af1bba4SBjoern A. Zeeb 	u32 rate_n_flags = phy_data->rate_n_flags;
963bfcc09ddSBjoern A. Zeeb 
964bfcc09ddSBjoern A. Zeeb 	if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CRC_OK, phy_data4)) {
965bfcc09ddSBjoern A. Zeeb 		he_mu->flags1 |=
966bfcc09ddSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN |
967bfcc09ddSBjoern A. Zeeb 				    IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN);
968bfcc09ddSBjoern A. Zeeb 
969bfcc09ddSBjoern A. Zeeb 		he_mu->flags1 |=
970bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CTR_RU,
971bfcc09ddSBjoern A. Zeeb 						   phy_data4),
972bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU);
973bfcc09ddSBjoern A. Zeeb 
974bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch1[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU0,
975bfcc09ddSBjoern A. Zeeb 					     phy_data2);
976bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch1[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1,
977bfcc09ddSBjoern A. Zeeb 					     phy_data3);
978bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch1[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU2,
979bfcc09ddSBjoern A. Zeeb 					     phy_data2);
980bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch1[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU3,
981bfcc09ddSBjoern A. Zeeb 					     phy_data3);
982bfcc09ddSBjoern A. Zeeb 	}
983bfcc09ddSBjoern A. Zeeb 
984bfcc09ddSBjoern A. Zeeb 	if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) &&
985bfcc09ddSBjoern A. Zeeb 	    (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) != RATE_MCS_CHAN_WIDTH_20) {
986bfcc09ddSBjoern A. Zeeb 		he_mu->flags1 |=
987bfcc09ddSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |
988bfcc09ddSBjoern A. Zeeb 				    IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN);
989bfcc09ddSBjoern A. Zeeb 
990bfcc09ddSBjoern A. Zeeb 		he_mu->flags2 |=
991bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CTR_RU,
992bfcc09ddSBjoern A. Zeeb 						   phy_data4),
993bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU);
994bfcc09ddSBjoern A. Zeeb 
995bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch2[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU0,
996bfcc09ddSBjoern A. Zeeb 					     phy_data2);
997bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch2[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU1,
998bfcc09ddSBjoern A. Zeeb 					     phy_data3);
999bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch2[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU2,
1000bfcc09ddSBjoern A. Zeeb 					     phy_data2);
1001bfcc09ddSBjoern A. Zeeb 		he_mu->ru_ch2[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU3,
1002bfcc09ddSBjoern A. Zeeb 					     phy_data3);
1003bfcc09ddSBjoern A. Zeeb 	}
1004bfcc09ddSBjoern A. Zeeb }
1005bfcc09ddSBjoern A. Zeeb 
1006bfcc09ddSBjoern A. Zeeb static void
1007bfcc09ddSBjoern A. Zeeb iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
1008bfcc09ddSBjoern A. Zeeb 			       struct ieee80211_radiotap_he *he,
1009bfcc09ddSBjoern A. Zeeb 			       struct ieee80211_radiotap_he_mu *he_mu,
1010bfcc09ddSBjoern A. Zeeb 			       struct ieee80211_rx_status *rx_status)
1011bfcc09ddSBjoern A. Zeeb {
1012bfcc09ddSBjoern A. Zeeb 	/*
1013bfcc09ddSBjoern A. Zeeb 	 * Unfortunately, we have to leave the mac80211 data
1014bfcc09ddSBjoern A. Zeeb 	 * incorrect for the case that we receive an HE-MU
1015bfcc09ddSBjoern A. Zeeb 	 * transmission and *don't* have the HE phy data (due
1016bfcc09ddSBjoern A. Zeeb 	 * to the bits being used for TSF). This shouldn't
1017bfcc09ddSBjoern A. Zeeb 	 * happen though as management frames where we need
1018bfcc09ddSBjoern A. Zeeb 	 * the TSF/timers are not be transmitted in HE-MU.
1019bfcc09ddSBjoern A. Zeeb 	 */
1020bfcc09ddSBjoern A. Zeeb 	u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
10219af1bba4SBjoern A. Zeeb 	u32 rate_n_flags = phy_data->rate_n_flags;
1022bfcc09ddSBjoern A. Zeeb 	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1;
1023bfcc09ddSBjoern A. Zeeb 	u8 offs = 0;
1024bfcc09ddSBjoern A. Zeeb 
1025bfcc09ddSBjoern A. Zeeb 	rx_status->bw = RATE_INFO_BW_HE_RU;
1026bfcc09ddSBjoern A. Zeeb 
1027bfcc09ddSBjoern A. Zeeb 	he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
1028bfcc09ddSBjoern A. Zeeb 
1029bfcc09ddSBjoern A. Zeeb 	switch (ru) {
1030bfcc09ddSBjoern A. Zeeb 	case 0 ... 36:
1031bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
1032bfcc09ddSBjoern A. Zeeb 		offs = ru;
1033bfcc09ddSBjoern A. Zeeb 		break;
1034bfcc09ddSBjoern A. Zeeb 	case 37 ... 52:
1035bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
1036bfcc09ddSBjoern A. Zeeb 		offs = ru - 37;
1037bfcc09ddSBjoern A. Zeeb 		break;
1038bfcc09ddSBjoern A. Zeeb 	case 53 ... 60:
1039bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
1040bfcc09ddSBjoern A. Zeeb 		offs = ru - 53;
1041bfcc09ddSBjoern A. Zeeb 		break;
1042bfcc09ddSBjoern A. Zeeb 	case 61 ... 64:
1043bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
1044bfcc09ddSBjoern A. Zeeb 		offs = ru - 61;
1045bfcc09ddSBjoern A. Zeeb 		break;
1046bfcc09ddSBjoern A. Zeeb 	case 65 ... 66:
1047bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
1048bfcc09ddSBjoern A. Zeeb 		offs = ru - 65;
1049bfcc09ddSBjoern A. Zeeb 		break;
1050bfcc09ddSBjoern A. Zeeb 	case 67:
1051bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
1052bfcc09ddSBjoern A. Zeeb 		break;
1053bfcc09ddSBjoern A. Zeeb 	case 68:
1054bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
1055bfcc09ddSBjoern A. Zeeb 		break;
1056bfcc09ddSBjoern A. Zeeb 	}
1057bfcc09ddSBjoern A. Zeeb 	he->data2 |= le16_encode_bits(offs,
1058bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
1059bfcc09ddSBjoern A. Zeeb 	he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
1060bfcc09ddSBjoern A. Zeeb 				 IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
1061bfcc09ddSBjoern A. Zeeb 	if (phy_data->d1 & cpu_to_le32(IWL_RX_PHY_DATA1_HE_RU_ALLOC_SEC80))
1062bfcc09ddSBjoern A. Zeeb 		he->data2 |=
1063bfcc09ddSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
1064bfcc09ddSBjoern A. Zeeb 
1065bfcc09ddSBjoern A. Zeeb #define CHECK_BW(bw) \
1066bfcc09ddSBjoern A. Zeeb 	BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
1067bfcc09ddSBjoern A. Zeeb 		     RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \
1068bfcc09ddSBjoern A. Zeeb 	BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \
1069bfcc09ddSBjoern A. Zeeb 		     RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
1070bfcc09ddSBjoern A. Zeeb 	CHECK_BW(20);
1071bfcc09ddSBjoern A. Zeeb 	CHECK_BW(40);
1072bfcc09ddSBjoern A. Zeeb 	CHECK_BW(80);
1073bfcc09ddSBjoern A. Zeeb 	CHECK_BW(160);
1074bfcc09ddSBjoern A. Zeeb 
1075bfcc09ddSBjoern A. Zeeb 	if (he_mu)
1076bfcc09ddSBjoern A. Zeeb 		he_mu->flags2 |=
1077bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,
1078bfcc09ddSBjoern A. Zeeb 						   rate_n_flags),
1079bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
1080bfcc09ddSBjoern A. Zeeb 	else if (he_type == RATE_MCS_HE_TYPE_TRIG_V1)
1081bfcc09ddSBjoern A. Zeeb 		he->data6 |=
1082bfcc09ddSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
1083bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,
1084bfcc09ddSBjoern A. Zeeb 						   rate_n_flags),
1085bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
1086bfcc09ddSBjoern A. Zeeb }
1087bfcc09ddSBjoern A. Zeeb 
1088bfcc09ddSBjoern A. Zeeb static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
1089bfcc09ddSBjoern A. Zeeb 				       struct iwl_mvm_rx_phy_data *phy_data,
1090bfcc09ddSBjoern A. Zeeb 				       struct ieee80211_radiotap_he *he,
1091bfcc09ddSBjoern A. Zeeb 				       struct ieee80211_radiotap_he_mu *he_mu,
1092bfcc09ddSBjoern A. Zeeb 				       struct ieee80211_rx_status *rx_status,
10939af1bba4SBjoern A. Zeeb 				       int queue)
1094bfcc09ddSBjoern A. Zeeb {
1095bfcc09ddSBjoern A. Zeeb 	switch (phy_data->info_type) {
1096bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_NONE:
1097bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_CCK:
1098bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_OFDM_LGCY:
1099bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HT:
1100bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_VHT_SU:
1101bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_VHT_MU:
11029af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_MU:
11039af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_TB:
11049af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:
11059af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:
1106bfcc09ddSBjoern A. Zeeb 		return;
1107bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
1108bfcc09ddSBjoern A. Zeeb 		he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
1109bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
1110bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
1111bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
1112bfcc09ddSBjoern A. Zeeb 		he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
1113bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
1114bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
1115bfcc09ddSBjoern A. Zeeb 		he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
1116bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
1117bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
1118bfcc09ddSBjoern A. Zeeb 		he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
1119bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
1120bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
1121bfcc09ddSBjoern A. Zeeb 		he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,
1122bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
1123bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
1124bfcc09ddSBjoern A. Zeeb 		fallthrough;
1125bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_SU:
1126bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU:
1127bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
1128bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB:
1129bfcc09ddSBjoern A. Zeeb 		/* HE common */
1130bfcc09ddSBjoern A. Zeeb 		he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
1131bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
1132bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
1133bfcc09ddSBjoern A. Zeeb 		he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
1134bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
1135bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |
1136bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
1137bfcc09ddSBjoern A. Zeeb 		he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1138bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_BSS_COLOR_MASK),
1139bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
1140bfcc09ddSBjoern A. Zeeb 		if (phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB &&
1141bfcc09ddSBjoern A. Zeeb 		    phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB_EXT) {
1142bfcc09ddSBjoern A. Zeeb 			he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
1143bfcc09ddSBjoern A. Zeeb 			he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1144bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_UPLINK),
1145bfcc09ddSBjoern A. Zeeb 						      IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
1146bfcc09ddSBjoern A. Zeeb 		}
1147bfcc09ddSBjoern A. Zeeb 		he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1148bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
1149bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
1150bfcc09ddSBjoern A. Zeeb 		he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1151bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
1152bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
1153bfcc09ddSBjoern A. Zeeb 		he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1154bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_PE_DISAMBIG),
1155bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
1156bfcc09ddSBjoern A. Zeeb 		he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d1,
1157bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA1_HE_LTF_NUM_MASK),
1158bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
1159bfcc09ddSBjoern A. Zeeb 		he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1160bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_TXOP_DUR_MASK),
1161bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA6_TXOP);
1162bfcc09ddSBjoern A. Zeeb 		he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1163bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_DOPPLER),
1164bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
1165bfcc09ddSBjoern A. Zeeb 		break;
1166bfcc09ddSBjoern A. Zeeb 	}
1167bfcc09ddSBjoern A. Zeeb 
1168bfcc09ddSBjoern A. Zeeb 	switch (phy_data->info_type) {
1169bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
1170bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU:
1171bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_SU:
1172bfcc09ddSBjoern A. Zeeb 		he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);
1173bfcc09ddSBjoern A. Zeeb 		he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1174bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
1175bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
1176bfcc09ddSBjoern A. Zeeb 		break;
1177bfcc09ddSBjoern A. Zeeb 	default:
1178bfcc09ddSBjoern A. Zeeb 		/* nothing here */
1179bfcc09ddSBjoern A. Zeeb 		break;
1180bfcc09ddSBjoern A. Zeeb 	}
1181bfcc09ddSBjoern A. Zeeb 
1182bfcc09ddSBjoern A. Zeeb 	switch (phy_data->info_type) {
1183bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
1184bfcc09ddSBjoern A. Zeeb 		he_mu->flags1 |=
1185bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(le16_get_bits(phy_data->d4,
1186bfcc09ddSBjoern A. Zeeb 						       IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM),
1187bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
1188bfcc09ddSBjoern A. Zeeb 		he_mu->flags1 |=
1189bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(le16_get_bits(phy_data->d4,
1190bfcc09ddSBjoern A. Zeeb 						       IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_MCS_MASK),
1191bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
1192bfcc09ddSBjoern A. Zeeb 		he_mu->flags2 |=
1193bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(le16_get_bits(phy_data->d4,
1194bfcc09ddSBjoern A. Zeeb 						       IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK),
1195bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
11969af1bba4SBjoern A. Zeeb 		iwl_mvm_decode_he_mu_ext(mvm, phy_data, he_mu);
1197bfcc09ddSBjoern A. Zeeb 		fallthrough;
1198bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU:
1199bfcc09ddSBjoern A. Zeeb 		he_mu->flags2 |=
1200bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(le32_get_bits(phy_data->d1,
1201bfcc09ddSBjoern A. Zeeb 						       IWL_RX_PHY_DATA1_HE_MU_SIBG_SYM_OR_USER_NUM_MASK),
1202bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
1203bfcc09ddSBjoern A. Zeeb 		he_mu->flags2 |=
1204bfcc09ddSBjoern A. Zeeb 			le16_encode_bits(le32_get_bits(phy_data->d1,
1205bfcc09ddSBjoern A. Zeeb 						       IWL_RX_PHY_DATA1_HE_MU_SIGB_COMPRESSION),
1206bfcc09ddSBjoern A. Zeeb 					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
1207bfcc09ddSBjoern A. Zeeb 		fallthrough;
1208bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB:
1209bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
12109af1bba4SBjoern A. Zeeb 		iwl_mvm_decode_he_phy_ru_alloc(phy_data, he, he_mu, rx_status);
1211bfcc09ddSBjoern A. Zeeb 		break;
1212bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_SU:
1213bfcc09ddSBjoern A. Zeeb 		he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);
1214bfcc09ddSBjoern A. Zeeb 		he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
1215bfcc09ddSBjoern A. Zeeb 							    IWL_RX_PHY_DATA0_HE_BEAM_CHNG),
1216bfcc09ddSBjoern A. Zeeb 					      IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
1217bfcc09ddSBjoern A. Zeeb 		break;
1218bfcc09ddSBjoern A. Zeeb 	default:
1219bfcc09ddSBjoern A. Zeeb 		/* nothing */
1220bfcc09ddSBjoern A. Zeeb 		break;
1221bfcc09ddSBjoern A. Zeeb 	}
1222bfcc09ddSBjoern A. Zeeb }
1223bfcc09ddSBjoern A. Zeeb 
12249af1bba4SBjoern A. Zeeb #define LE32_DEC_ENC(value, dec_bits, enc_bits) \
12259af1bba4SBjoern A. Zeeb 	le32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)
12269af1bba4SBjoern A. Zeeb 
12279af1bba4SBjoern A. Zeeb #define IWL_MVM_ENC_USIG_VALUE_MASK(usig, in_value, dec_bits, enc_bits) do { \
12289af1bba4SBjoern A. Zeeb 	typeof(enc_bits) _enc_bits = enc_bits; \
12299af1bba4SBjoern A. Zeeb 	typeof(usig) _usig = usig; \
12309af1bba4SBjoern A. Zeeb 	(_usig)->mask |= cpu_to_le32(_enc_bits); \
12319af1bba4SBjoern A. Zeeb 	(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \
12329af1bba4SBjoern A. Zeeb } while (0)
12339af1bba4SBjoern A. Zeeb 
12349af1bba4SBjoern A. Zeeb #define __IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
12359af1bba4SBjoern A. Zeeb 	eht->data[(rt_data)] |= \
12369af1bba4SBjoern A. Zeeb 		(cpu_to_le32 \
12379af1bba4SBjoern A. Zeeb 		 (IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \
12389af1bba4SBjoern A. Zeeb 		 LE32_DEC_ENC(data ## fw_data, \
12399af1bba4SBjoern A. Zeeb 			      IWL_RX_PHY_DATA ## fw_data ## _EHT_MU_EXT_RU_ALLOC_ ## fw_ru, \
12409af1bba4SBjoern A. Zeeb 			      IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))
12419af1bba4SBjoern A. Zeeb 
12429af1bba4SBjoern A. Zeeb #define _IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)	\
12439af1bba4SBjoern A. Zeeb 	__IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)
12449af1bba4SBjoern A. Zeeb 
12459af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_1_1_1	1
12469af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_2_1_1	2
12479af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_1_1_2	2
12489af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_2_1_2	2
12499af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_1_2_1	3
12509af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_2_2_1	3
12519af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_1_2_2	3
12529af1bba4SBjoern A. Zeeb #define IEEE80211_RADIOTAP_RU_DATA_2_2_2	4
12539af1bba4SBjoern A. Zeeb 
12549af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_A1			2
12559af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_A2			2
12569af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_B1			2
1257*a4128aadSBjoern A. Zeeb #define IWL_RX_RU_DATA_B2			4
12589af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_C1			3
12599af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_C2			3
12609af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_D1			4
12619af1bba4SBjoern A. Zeeb #define IWL_RX_RU_DATA_D2			4
12629af1bba4SBjoern A. Zeeb 
12639af1bba4SBjoern A. Zeeb #define IWL_MVM_ENC_EHT_RU(rt_ru, fw_ru)				\
12649af1bba4SBjoern A. Zeeb 	_IWL_MVM_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru,	\
12659af1bba4SBjoern A. Zeeb 			    rt_ru,					\
12669af1bba4SBjoern A. Zeeb 			    IWL_RX_RU_DATA_ ## fw_ru,			\
12679af1bba4SBjoern A. Zeeb 			    fw_ru)
12689af1bba4SBjoern A. Zeeb 
12699af1bba4SBjoern A. Zeeb static void iwl_mvm_decode_eht_ext_mu(struct iwl_mvm *mvm,
12709af1bba4SBjoern A. Zeeb 				      struct iwl_mvm_rx_phy_data *phy_data,
12719af1bba4SBjoern A. Zeeb 				      struct ieee80211_rx_status *rx_status,
12729af1bba4SBjoern A. Zeeb 				      struct ieee80211_radiotap_eht *eht,
12739af1bba4SBjoern A. Zeeb 				      struct ieee80211_radiotap_eht_usig *usig)
12749af1bba4SBjoern A. Zeeb {
12759af1bba4SBjoern A. Zeeb 	if (phy_data->with_data) {
12769af1bba4SBjoern A. Zeeb 		__le32 data1 = phy_data->d1;
12779af1bba4SBjoern A. Zeeb 		__le32 data2 = phy_data->d2;
12789af1bba4SBjoern A. Zeeb 		__le32 data3 = phy_data->d3;
12799af1bba4SBjoern A. Zeeb 		__le32 data4 = phy_data->eht_d4;
12809af1bba4SBjoern A. Zeeb 		__le32 data5 = phy_data->d5;
12819af1bba4SBjoern A. Zeeb 		u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
12829af1bba4SBjoern A. Zeeb 
12839af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
12849af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
12859af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
12869af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
12879af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA5_EHT_MU_PUNC_CH_CODE,
12889af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
12899af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data4,
12909af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS,
12919af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
12929af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK
12939af1bba4SBjoern A. Zeeb 			(usig, data1, IWL_RX_PHY_DATA1_EHT_MU_NUM_SIG_SYM_USIGA2,
12949af1bba4SBjoern A. Zeeb 			 IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
12959af1bba4SBjoern A. Zeeb 
12969af1bba4SBjoern A. Zeeb 		eht->user_info[0] |=
12979af1bba4SBjoern A. Zeeb 			cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) |
12989af1bba4SBjoern A. Zeeb 			LE32_DEC_ENC(data5, IWL_RX_PHY_DATA5_EHT_MU_STA_ID_USR,
12999af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID);
13009af1bba4SBjoern A. Zeeb 
13019af1bba4SBjoern A. Zeeb 		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M);
13029af1bba4SBjoern A. Zeeb 		eht->data[7] |= LE32_DEC_ENC
13039af1bba4SBjoern A. Zeeb 			(data5, IWL_RX_PHY_DATA5_EHT_MU_NUM_USR_NON_OFDMA,
13049af1bba4SBjoern A. Zeeb 			 IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
13059af1bba4SBjoern A. Zeeb 
13069af1bba4SBjoern A. Zeeb 		/*
13079af1bba4SBjoern A. Zeeb 		 * Hardware labels the content channels/RU allocation values
13089af1bba4SBjoern A. Zeeb 		 * as follows:
13099af1bba4SBjoern A. Zeeb 		 *           Content Channel 1		Content Channel 2
13109af1bba4SBjoern A. Zeeb 		 *   20 MHz: A1
13119af1bba4SBjoern A. Zeeb 		 *   40 MHz: A1				B1
13129af1bba4SBjoern A. Zeeb 		 *   80 MHz: A1 C1			B1 D1
13139af1bba4SBjoern A. Zeeb 		 *  160 MHz: A1 C1 A2 C2		B1 D1 B2 D2
13149af1bba4SBjoern A. Zeeb 		 *  320 MHz: A1 C1 A2 C2 A3 C3 A4 C4	B1 D1 B2 D2 B3 D3 B4 D4
13159af1bba4SBjoern A. Zeeb 		 *
13169af1bba4SBjoern A. Zeeb 		 * However firmware can only give us A1-D2, so the higher
13179af1bba4SBjoern A. Zeeb 		 * frequencies are missing.
13189af1bba4SBjoern A. Zeeb 		 */
13199af1bba4SBjoern A. Zeeb 
13209af1bba4SBjoern A. Zeeb 		switch (phy_bw) {
13219af1bba4SBjoern A. Zeeb 		case RATE_MCS_CHAN_WIDTH_320:
13229af1bba4SBjoern A. Zeeb 			/* additional values are missing in RX metadata */
13239af1bba4SBjoern A. Zeeb 		case RATE_MCS_CHAN_WIDTH_160:
13249af1bba4SBjoern A. Zeeb 			/* content channel 1 */
13259af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(1_2_1, A2);
13269af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(1_2_2, C2);
13279af1bba4SBjoern A. Zeeb 			/* content channel 2 */
13289af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(2_2_1, B2);
13299af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(2_2_2, D2);
13309af1bba4SBjoern A. Zeeb 			fallthrough;
13319af1bba4SBjoern A. Zeeb 		case RATE_MCS_CHAN_WIDTH_80:
13329af1bba4SBjoern A. Zeeb 			/* content channel 1 */
13339af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(1_1_2, C1);
13349af1bba4SBjoern A. Zeeb 			/* content channel 2 */
13359af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(2_1_2, D1);
13369af1bba4SBjoern A. Zeeb 			fallthrough;
13379af1bba4SBjoern A. Zeeb 		case RATE_MCS_CHAN_WIDTH_40:
13389af1bba4SBjoern A. Zeeb 			/* content channel 2 */
13399af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(2_1_1, B1);
13409af1bba4SBjoern A. Zeeb 			fallthrough;
13419af1bba4SBjoern A. Zeeb 		case RATE_MCS_CHAN_WIDTH_20:
13429af1bba4SBjoern A. Zeeb 			IWL_MVM_ENC_EHT_RU(1_1_1, A1);
13439af1bba4SBjoern A. Zeeb 			break;
13449af1bba4SBjoern A. Zeeb 		}
13459af1bba4SBjoern A. Zeeb 	} else {
13469af1bba4SBjoern A. Zeeb 		__le32 usig_a1 = phy_data->rx_vec[0];
13479af1bba4SBjoern A. Zeeb 		__le32 usig_a2 = phy_data->rx_vec[1];
13489af1bba4SBjoern A. Zeeb 
13499af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
13509af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A1_DISREGARD,
13519af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD);
13529af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
13539af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A1_VALIDATE,
13549af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE);
13559af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13569af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_PPDU_TYPE,
13579af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
13589af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13599af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
13609af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE);
13619af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13629af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_PUNC_CHANNEL,
13639af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
13649af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13659af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8,
13669af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE);
13679af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13689af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_SIG_MCS,
13699af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
13709af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK
13719af1bba4SBjoern A. Zeeb 			(usig, usig_a2, IWL_RX_USIG_A2_EHT_SIG_SYM_NUM,
13729af1bba4SBjoern A. Zeeb 			 IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
13739af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
13749af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_CRC_OK,
13759af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC);
13769af1bba4SBjoern A. Zeeb 	}
13779af1bba4SBjoern A. Zeeb }
13789af1bba4SBjoern A. Zeeb 
13799af1bba4SBjoern A. Zeeb static void iwl_mvm_decode_eht_ext_tb(struct iwl_mvm *mvm,
13809af1bba4SBjoern A. Zeeb 				      struct iwl_mvm_rx_phy_data *phy_data,
13819af1bba4SBjoern A. Zeeb 				      struct ieee80211_rx_status *rx_status,
13829af1bba4SBjoern A. Zeeb 				      struct ieee80211_radiotap_eht *eht,
13839af1bba4SBjoern A. Zeeb 				      struct ieee80211_radiotap_eht_usig *usig)
13849af1bba4SBjoern A. Zeeb {
13859af1bba4SBjoern A. Zeeb 	if (phy_data->with_data) {
13869af1bba4SBjoern A. Zeeb 		__le32 data5 = phy_data->d5;
13879af1bba4SBjoern A. Zeeb 
13889af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
13899af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
13909af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
13919af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
13929af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE1,
13939af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
13949af1bba4SBjoern A. Zeeb 
13959af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
13969af1bba4SBjoern A. Zeeb 					    IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE2,
13979af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
13989af1bba4SBjoern A. Zeeb 	} else {
13999af1bba4SBjoern A. Zeeb 		__le32 usig_a1 = phy_data->rx_vec[0];
14009af1bba4SBjoern A. Zeeb 		__le32 usig_a2 = phy_data->rx_vec[1];
14019af1bba4SBjoern A. Zeeb 
14029af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
14039af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A1_DISREGARD,
14049af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);
14059af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14069af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_PPDU_TYPE,
14079af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
14089af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14099af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
14109af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE);
14119af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14129af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1,
14139af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
14149af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14159af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2,
14169af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
14179af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14189af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD,
14199af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD);
14209af1bba4SBjoern A. Zeeb 		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
14219af1bba4SBjoern A. Zeeb 					    IWL_RX_USIG_A2_EHT_CRC_OK,
14229af1bba4SBjoern A. Zeeb 					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC);
14239af1bba4SBjoern A. Zeeb 	}
14249af1bba4SBjoern A. Zeeb }
14259af1bba4SBjoern A. Zeeb 
14269af1bba4SBjoern A. Zeeb static void iwl_mvm_decode_eht_ru(struct iwl_mvm *mvm,
14279af1bba4SBjoern A. Zeeb 				  struct ieee80211_rx_status *rx_status,
14289af1bba4SBjoern A. Zeeb 				  struct ieee80211_radiotap_eht *eht)
14299af1bba4SBjoern A. Zeeb {
14309af1bba4SBjoern A. Zeeb 	u32 ru = le32_get_bits(eht->data[8],
14319af1bba4SBjoern A. Zeeb 			       IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
14329af1bba4SBjoern A. Zeeb 	enum nl80211_eht_ru_alloc nl_ru;
14339af1bba4SBjoern A. Zeeb 
14349af1bba4SBjoern A. Zeeb 	/* Using D1.5 Table 9-53a - Encoding of PS160 and RU Allocation subfields
14359af1bba4SBjoern A. Zeeb 	 * in an EHT variant User Info field
14369af1bba4SBjoern A. Zeeb 	 */
14379af1bba4SBjoern A. Zeeb 
14389af1bba4SBjoern A. Zeeb 	switch (ru) {
14399af1bba4SBjoern A. Zeeb 	case 0 ... 36:
14409af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_26;
14419af1bba4SBjoern A. Zeeb 		break;
14429af1bba4SBjoern A. Zeeb 	case 37 ... 52:
14439af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52;
14449af1bba4SBjoern A. Zeeb 		break;
14459af1bba4SBjoern A. Zeeb 	case 53 ... 60:
14469af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106;
14479af1bba4SBjoern A. Zeeb 		break;
14489af1bba4SBjoern A. Zeeb 	case 61 ... 64:
14499af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_242;
14509af1bba4SBjoern A. Zeeb 		break;
14519af1bba4SBjoern A. Zeeb 	case 65 ... 66:
14529af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484;
14539af1bba4SBjoern A. Zeeb 		break;
14549af1bba4SBjoern A. Zeeb 	case 67:
14559af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996;
14569af1bba4SBjoern A. Zeeb 		break;
14579af1bba4SBjoern A. Zeeb 	case 68:
14589af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996;
14599af1bba4SBjoern A. Zeeb 		break;
14609af1bba4SBjoern A. Zeeb 	case 69:
14619af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_4x996;
14629af1bba4SBjoern A. Zeeb 		break;
14639af1bba4SBjoern A. Zeeb 	case 70 ... 81:
14649af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52P26;
14659af1bba4SBjoern A. Zeeb 		break;
14669af1bba4SBjoern A. Zeeb 	case 82 ... 89:
14679af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106P26;
14689af1bba4SBjoern A. Zeeb 		break;
14699af1bba4SBjoern A. Zeeb 	case 90 ... 93:
14709af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484P242;
14719af1bba4SBjoern A. Zeeb 		break;
14729af1bba4SBjoern A. Zeeb 	case 94 ... 95:
14739af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484;
14749af1bba4SBjoern A. Zeeb 		break;
14759af1bba4SBjoern A. Zeeb 	case 96 ... 99:
14769af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242;
14779af1bba4SBjoern A. Zeeb 		break;
14789af1bba4SBjoern A. Zeeb 	case 100 ... 103:
14799af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484;
14809af1bba4SBjoern A. Zeeb 		break;
14819af1bba4SBjoern A. Zeeb 	case 104:
14829af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996;
14839af1bba4SBjoern A. Zeeb 		break;
14849af1bba4SBjoern A. Zeeb 	case 105 ... 106:
14859af1bba4SBjoern A. Zeeb 		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484;
14869af1bba4SBjoern A. Zeeb 		break;
14879af1bba4SBjoern A. Zeeb 	default:
14889af1bba4SBjoern A. Zeeb 		return;
14899af1bba4SBjoern A. Zeeb 	}
14909af1bba4SBjoern A. Zeeb 
14919af1bba4SBjoern A. Zeeb 	rx_status->bw = RATE_INFO_BW_EHT_RU;
14929af1bba4SBjoern A. Zeeb 	rx_status->eht.ru = nl_ru;
14939af1bba4SBjoern A. Zeeb }
14949af1bba4SBjoern A. Zeeb 
14959af1bba4SBjoern A. Zeeb static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
14969af1bba4SBjoern A. Zeeb 					struct iwl_mvm_rx_phy_data *phy_data,
14979af1bba4SBjoern A. Zeeb 					struct ieee80211_rx_status *rx_status,
14989af1bba4SBjoern A. Zeeb 					struct ieee80211_radiotap_eht *eht,
14999af1bba4SBjoern A. Zeeb 					struct ieee80211_radiotap_eht_usig *usig)
15009af1bba4SBjoern A. Zeeb 
15019af1bba4SBjoern A. Zeeb {
15029af1bba4SBjoern A. Zeeb 	__le32 data0 = phy_data->d0;
15039af1bba4SBjoern A. Zeeb 	__le32 data1 = phy_data->d1;
15049af1bba4SBjoern A. Zeeb 	__le32 usig_a1 = phy_data->rx_vec[0];
15059af1bba4SBjoern A. Zeeb 	u8 info_type = phy_data->info_type;
15069af1bba4SBjoern A. Zeeb 
15079af1bba4SBjoern A. Zeeb 	/* Not in EHT range */
15089af1bba4SBjoern A. Zeeb 	if (info_type < IWL_RX_PHY_INFO_TYPE_EHT_MU ||
15099af1bba4SBjoern A. Zeeb 	    info_type > IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT)
15109af1bba4SBjoern A. Zeeb 		return;
15119af1bba4SBjoern A. Zeeb 
15129af1bba4SBjoern A. Zeeb 	usig->common |= cpu_to_le32
15139af1bba4SBjoern A. Zeeb 		(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
15149af1bba4SBjoern A. Zeeb 		 IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN);
15159af1bba4SBjoern A. Zeeb 	if (phy_data->with_data) {
15169af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(data0,
15179af1bba4SBjoern A. Zeeb 					     IWL_RX_PHY_DATA0_EHT_UPLINK,
15189af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
15199af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(data0,
15209af1bba4SBjoern A. Zeeb 					     IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK,
15219af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
15229af1bba4SBjoern A. Zeeb 	} else {
15239af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(usig_a1,
15249af1bba4SBjoern A. Zeeb 					     IWL_RX_USIG_A1_UL_FLAG,
15259af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
15269af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(usig_a1,
15279af1bba4SBjoern A. Zeeb 					     IWL_RX_USIG_A1_BSS_COLOR,
15289af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
15299af1bba4SBjoern A. Zeeb 	}
15309af1bba4SBjoern A. Zeeb 
15319af1bba4SBjoern A. Zeeb 	if (fw_has_capa(&mvm->fw->ucode_capa,
15329af1bba4SBjoern A. Zeeb 			IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT)) {
15339af1bba4SBjoern A. Zeeb 		usig->common |=
15349af1bba4SBjoern A. Zeeb 			cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED);
15359af1bba4SBjoern A. Zeeb 		usig->common |=
15369af1bba4SBjoern A. Zeeb 			LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE,
15379af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
15389af1bba4SBjoern A. Zeeb 	}
15399af1bba4SBjoern A. Zeeb 
15409af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);
15419af1bba4SBjoern A. Zeeb 	eht->data[0] |= LE32_DEC_ENC(data0,
15429af1bba4SBjoern A. Zeeb 				     IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,
15439af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
15449af1bba4SBjoern A. Zeeb 
15459af1bba4SBjoern A. Zeeb 	/* All RU allocating size/index is in TB format */
15469af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);
15479af1bba4SBjoern A. Zeeb 	eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,
15489af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
15499af1bba4SBjoern A. Zeeb 	eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0,
15509af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);
15519af1bba4SBjoern A. Zeeb 	eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7,
15529af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
15539af1bba4SBjoern A. Zeeb 
15549af1bba4SBjoern A. Zeeb 	iwl_mvm_decode_eht_ru(mvm, rx_status, eht);
15559af1bba4SBjoern A. Zeeb 
15569af1bba4SBjoern A. Zeeb 	/* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
15579af1bba4SBjoern A. Zeeb 	 * which is on only in case of monitor mode so no need to check monitor
15589af1bba4SBjoern A. Zeeb 	 * mode
15599af1bba4SBjoern A. Zeeb 	 */
15609af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);
15619af1bba4SBjoern A. Zeeb 	eht->data[1] |=
15629af1bba4SBjoern A. Zeeb 		le32_encode_bits(mvm->monitor_p80,
15639af1bba4SBjoern A. Zeeb 				 IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
15649af1bba4SBjoern A. Zeeb 
15659af1bba4SBjoern A. Zeeb 	usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);
15669af1bba4SBjoern A. Zeeb 	if (phy_data->with_data)
15679af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK,
15689af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
15699af1bba4SBjoern A. Zeeb 	else
15709af1bba4SBjoern A. Zeeb 		usig->common |= LE32_DEC_ENC(usig_a1, IWL_RX_USIG_A1_TXOP_DURATION,
15719af1bba4SBjoern A. Zeeb 					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
15729af1bba4SBjoern A. Zeeb 
15739af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM);
15749af1bba4SBjoern A. Zeeb 	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_LDPC_EXT_SYM,
15759af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
15769af1bba4SBjoern A. Zeeb 
15779af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM);
15789af1bba4SBjoern A. Zeeb 	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PRE_FEC_PAD_MASK,
15799af1bba4SBjoern A. Zeeb 				    IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
15809af1bba4SBjoern A. Zeeb 
15819af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM);
15829af1bba4SBjoern A. Zeeb 	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PE_DISAMBIG,
15839af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
15849af1bba4SBjoern A. Zeeb 
15859af1bba4SBjoern A. Zeeb 	/* TODO: what about IWL_RX_PHY_DATA0_EHT_BW320_SLOT */
15869af1bba4SBjoern A. Zeeb 
15879af1bba4SBjoern A. Zeeb 	if (!le32_get_bits(data0, IWL_RX_PHY_DATA0_EHT_SIGA_CRC_OK))
15889af1bba4SBjoern A. Zeeb 		usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
15899af1bba4SBjoern A. Zeeb 
15909af1bba4SBjoern A. Zeeb 	usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);
15919af1bba4SBjoern A. Zeeb 	usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PHY_VER,
15929af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);
15939af1bba4SBjoern A. Zeeb 
15949af1bba4SBjoern A. Zeeb 	/*
15959af1bba4SBjoern A. Zeeb 	 * TODO: what about TB - IWL_RX_PHY_DATA1_EHT_TB_PILOT_TYPE,
15969af1bba4SBjoern A. Zeeb 	 *			 IWL_RX_PHY_DATA1_EHT_TB_LOW_SS
15979af1bba4SBjoern A. Zeeb 	 */
15989af1bba4SBjoern A. Zeeb 
15999af1bba4SBjoern A. Zeeb 	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF);
16009af1bba4SBjoern A. Zeeb 	eht->data[0] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM,
16019af1bba4SBjoern A. Zeeb 				     IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
16029af1bba4SBjoern A. Zeeb 
16039af1bba4SBjoern A. Zeeb 	if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT ||
16049af1bba4SBjoern A. Zeeb 	    info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB)
16059af1bba4SBjoern A. Zeeb 		iwl_mvm_decode_eht_ext_tb(mvm, phy_data, rx_status, eht, usig);
16069af1bba4SBjoern A. Zeeb 
16079af1bba4SBjoern A. Zeeb 	if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT ||
16089af1bba4SBjoern A. Zeeb 	    info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU)
16099af1bba4SBjoern A. Zeeb 		iwl_mvm_decode_eht_ext_mu(mvm, phy_data, rx_status, eht, usig);
16109af1bba4SBjoern A. Zeeb }
16119af1bba4SBjoern A. Zeeb 
16129af1bba4SBjoern A. Zeeb static void iwl_mvm_rx_eht(struct iwl_mvm *mvm, struct sk_buff *skb,
16139af1bba4SBjoern A. Zeeb 			   struct iwl_mvm_rx_phy_data *phy_data,
16149af1bba4SBjoern A. Zeeb 			   int queue)
16159af1bba4SBjoern A. Zeeb {
16169af1bba4SBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
16179af1bba4SBjoern A. Zeeb 
16189af1bba4SBjoern A. Zeeb 	struct ieee80211_radiotap_eht *eht;
16199af1bba4SBjoern A. Zeeb 	struct ieee80211_radiotap_eht_usig *usig;
16209af1bba4SBjoern A. Zeeb 	size_t eht_len = sizeof(*eht);
16219af1bba4SBjoern A. Zeeb 
16229af1bba4SBjoern A. Zeeb 	u32 rate_n_flags = phy_data->rate_n_flags;
16239af1bba4SBjoern A. Zeeb 	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
16249af1bba4SBjoern A. Zeeb 	/* EHT and HE have the same valus for LTF */
16259af1bba4SBjoern A. Zeeb 	u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
16269af1bba4SBjoern A. Zeeb 	u16 phy_info = phy_data->phy_info;
16279af1bba4SBjoern A. Zeeb 	u32 bw;
16289af1bba4SBjoern A. Zeeb 
16299af1bba4SBjoern A. Zeeb 	/* u32 for 1 user_info */
16309af1bba4SBjoern A. Zeeb 	if (phy_data->with_data)
16319af1bba4SBjoern A. Zeeb 		eht_len += sizeof(u32);
16329af1bba4SBjoern A. Zeeb 
16339af1bba4SBjoern A. Zeeb 	eht = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
16349af1bba4SBjoern A. Zeeb 
16359af1bba4SBjoern A. Zeeb 	usig = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
16369af1bba4SBjoern A. Zeeb 					sizeof(*usig));
16379af1bba4SBjoern A. Zeeb 	rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
16389af1bba4SBjoern A. Zeeb 	usig->common |=
16399af1bba4SBjoern A. Zeeb 		cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN);
16409af1bba4SBjoern A. Zeeb 
16419af1bba4SBjoern A. Zeeb 	/* specific handling for 320MHz */
16429af1bba4SBjoern A. Zeeb 	bw = FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags);
16439af1bba4SBjoern A. Zeeb 	if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)
16449af1bba4SBjoern A. Zeeb 		bw += FIELD_GET(IWL_RX_PHY_DATA0_EHT_BW320_SLOT,
16459af1bba4SBjoern A. Zeeb 				le32_to_cpu(phy_data->d0));
16469af1bba4SBjoern A. Zeeb 
16479af1bba4SBjoern A. Zeeb 	usig->common |= cpu_to_le32
16489af1bba4SBjoern A. Zeeb 		(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW, bw));
16499af1bba4SBjoern A. Zeeb 
16509af1bba4SBjoern A. Zeeb 	/* report the AMPDU-EOF bit on single frames */
16519af1bba4SBjoern A. Zeeb 	if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
16529af1bba4SBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
16539af1bba4SBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
16549af1bba4SBjoern A. Zeeb 		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
16559af1bba4SBjoern A. Zeeb 			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
16569af1bba4SBjoern A. Zeeb 	}
16579af1bba4SBjoern A. Zeeb 
16589af1bba4SBjoern A. Zeeb 	/* update aggregation data for monitor sake on default queue */
16599af1bba4SBjoern A. Zeeb 	if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
16609af1bba4SBjoern A. Zeeb 	    (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
16619af1bba4SBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
16629af1bba4SBjoern A. Zeeb 		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
16639af1bba4SBjoern A. Zeeb 			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
16649af1bba4SBjoern A. Zeeb 	}
16659af1bba4SBjoern A. Zeeb 
16669af1bba4SBjoern A. Zeeb 	if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
16679af1bba4SBjoern A. Zeeb 		iwl_mvm_decode_eht_phy_data(mvm, phy_data, rx_status, eht, usig);
16689af1bba4SBjoern A. Zeeb 
16699af1bba4SBjoern A. Zeeb #define CHECK_TYPE(F)							\
16709af1bba4SBjoern A. Zeeb 	BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F !=	\
16719af1bba4SBjoern A. Zeeb 		     (RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))
16729af1bba4SBjoern A. Zeeb 
16739af1bba4SBjoern A. Zeeb 	CHECK_TYPE(SU);
16749af1bba4SBjoern A. Zeeb 	CHECK_TYPE(EXT_SU);
16759af1bba4SBjoern A. Zeeb 	CHECK_TYPE(MU);
16769af1bba4SBjoern A. Zeeb 	CHECK_TYPE(TRIG);
16779af1bba4SBjoern A. Zeeb 
16789af1bba4SBjoern A. Zeeb 	switch (FIELD_GET(RATE_MCS_HE_GI_LTF_MSK, rate_n_flags)) {
16799af1bba4SBjoern A. Zeeb 	case 0:
16809af1bba4SBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_TRIG) {
16819af1bba4SBjoern A. Zeeb 			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
16829af1bba4SBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;
16839af1bba4SBjoern A. Zeeb 		} else {
16849af1bba4SBjoern A. Zeeb 			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
16859af1bba4SBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
16869af1bba4SBjoern A. Zeeb 		}
16879af1bba4SBjoern A. Zeeb 		break;
16889af1bba4SBjoern A. Zeeb 	case 1:
16899af1bba4SBjoern A. Zeeb 		rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
16909af1bba4SBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
16919af1bba4SBjoern A. Zeeb 		break;
16929af1bba4SBjoern A. Zeeb 	case 2:
16939af1bba4SBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
16949af1bba4SBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_TRIG)
16959af1bba4SBjoern A. Zeeb 			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
16969af1bba4SBjoern A. Zeeb 		else
16979af1bba4SBjoern A. Zeeb 			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
16989af1bba4SBjoern A. Zeeb 		break;
16999af1bba4SBjoern A. Zeeb 	case 3:
17009af1bba4SBjoern A. Zeeb 		if (he_type != RATE_MCS_HE_TYPE_TRIG) {
17019af1bba4SBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
17029af1bba4SBjoern A. Zeeb 			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
17039af1bba4SBjoern A. Zeeb 		}
17049af1bba4SBjoern A. Zeeb 		break;
17059af1bba4SBjoern A. Zeeb 	default:
17069af1bba4SBjoern A. Zeeb 		/* nothing here */
17079af1bba4SBjoern A. Zeeb 		break;
17089af1bba4SBjoern A. Zeeb 	}
17099af1bba4SBjoern A. Zeeb 
17109af1bba4SBjoern A. Zeeb 	if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) {
17119af1bba4SBjoern A. Zeeb 		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI);
17129af1bba4SBjoern A. Zeeb 		eht->data[0] |= cpu_to_le32
17139af1bba4SBjoern A. Zeeb 			(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF,
17149af1bba4SBjoern A. Zeeb 				    ltf) |
17159af1bba4SBjoern A. Zeeb 			 FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI,
17169af1bba4SBjoern A. Zeeb 				    rx_status->eht.gi));
17179af1bba4SBjoern A. Zeeb 	}
17189af1bba4SBjoern A. Zeeb 
17199af1bba4SBjoern A. Zeeb 
17209af1bba4SBjoern A. Zeeb 	if (!phy_data->with_data) {
17219af1bba4SBjoern A. Zeeb 		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |
17229af1bba4SBjoern A. Zeeb 					  IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S);
17239af1bba4SBjoern A. Zeeb 		eht->data[7] |=
17249af1bba4SBjoern A. Zeeb 			le32_encode_bits(le32_get_bits(phy_data->rx_vec[2],
17259af1bba4SBjoern A. Zeeb 						       RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK),
17269af1bba4SBjoern A. Zeeb 					 IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
17279af1bba4SBjoern A. Zeeb 		if (rate_n_flags & RATE_MCS_BF_MSK)
17289af1bba4SBjoern A. Zeeb 			eht->data[7] |=
17299af1bba4SBjoern A. Zeeb 				cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);
17309af1bba4SBjoern A. Zeeb 	} else {
17319af1bba4SBjoern A. Zeeb 		eht->user_info[0] |=
17329af1bba4SBjoern A. Zeeb 			cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
17339af1bba4SBjoern A. Zeeb 				    IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
17349af1bba4SBjoern A. Zeeb 				    IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |
17359af1bba4SBjoern A. Zeeb 				    IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O |
17369af1bba4SBjoern A. Zeeb 				    IEEE80211_RADIOTAP_EHT_USER_INFO_DATA_FOR_USER);
17379af1bba4SBjoern A. Zeeb 
17389af1bba4SBjoern A. Zeeb 		if (rate_n_flags & RATE_MCS_BF_MSK)
17399af1bba4SBjoern A. Zeeb 			eht->user_info[0] |=
17409af1bba4SBjoern A. Zeeb 				cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O);
17419af1bba4SBjoern A. Zeeb 
17429af1bba4SBjoern A. Zeeb 		if (rate_n_flags & RATE_MCS_LDPC_MSK)
17439af1bba4SBjoern A. Zeeb 			eht->user_info[0] |=
17449af1bba4SBjoern A. Zeeb 				cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING);
17459af1bba4SBjoern A. Zeeb 
17469af1bba4SBjoern A. Zeeb 		eht->user_info[0] |= cpu_to_le32
17479af1bba4SBjoern A. Zeeb 			(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS,
17489af1bba4SBjoern A. Zeeb 				    FIELD_GET(RATE_VHT_MCS_RATE_CODE_MSK,
17499af1bba4SBjoern A. Zeeb 					      rate_n_flags)) |
17509af1bba4SBjoern A. Zeeb 			 FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O,
17519af1bba4SBjoern A. Zeeb 				    FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags)));
17529af1bba4SBjoern A. Zeeb 	}
17539af1bba4SBjoern A. Zeeb }
17549af1bba4SBjoern A. Zeeb 
1755bfcc09ddSBjoern A. Zeeb static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
1756bfcc09ddSBjoern A. Zeeb 			  struct iwl_mvm_rx_phy_data *phy_data,
17579af1bba4SBjoern A. Zeeb 			  int queue)
1758bfcc09ddSBjoern A. Zeeb {
1759bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
1760bfcc09ddSBjoern A. Zeeb 	struct ieee80211_radiotap_he *he = NULL;
1761bfcc09ddSBjoern A. Zeeb 	struct ieee80211_radiotap_he_mu *he_mu = NULL;
17629af1bba4SBjoern A. Zeeb 	u32 rate_n_flags = phy_data->rate_n_flags;
1763bfcc09ddSBjoern A. Zeeb 	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
17649af1bba4SBjoern A. Zeeb 	u8 ltf;
1765bfcc09ddSBjoern A. Zeeb 	static const struct ieee80211_radiotap_he known = {
1766bfcc09ddSBjoern A. Zeeb 		.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
1767bfcc09ddSBjoern A. Zeeb 				     IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |
1768bfcc09ddSBjoern A. Zeeb 				     IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN |
1769bfcc09ddSBjoern A. Zeeb 				     IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN),
1770bfcc09ddSBjoern A. Zeeb 		.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN |
1771bfcc09ddSBjoern A. Zeeb 				     IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN),
1772bfcc09ddSBjoern A. Zeeb 	};
1773bfcc09ddSBjoern A. Zeeb 	static const struct ieee80211_radiotap_he_mu mu_known = {
1774bfcc09ddSBjoern A. Zeeb 		.flags1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN |
1775bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN |
1776bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN |
1777bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN),
1778bfcc09ddSBjoern A. Zeeb 		.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |
1779bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
1780bfcc09ddSBjoern A. Zeeb 	};
17819af1bba4SBjoern A. Zeeb 	u16 phy_info = phy_data->phy_info;
1782bfcc09ddSBjoern A. Zeeb 
1783bfcc09ddSBjoern A. Zeeb 	he = skb_put_data(skb, &known, sizeof(known));
1784bfcc09ddSBjoern A. Zeeb 	rx_status->flag |= RX_FLAG_RADIOTAP_HE;
1785bfcc09ddSBjoern A. Zeeb 
1786bfcc09ddSBjoern A. Zeeb 	if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
1787bfcc09ddSBjoern A. Zeeb 	    phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
1788bfcc09ddSBjoern A. Zeeb 		he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
1789bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
1790bfcc09ddSBjoern A. Zeeb 	}
1791bfcc09ddSBjoern A. Zeeb 
1792bfcc09ddSBjoern A. Zeeb 	/* report the AMPDU-EOF bit on single frames */
1793bfcc09ddSBjoern A. Zeeb 	if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
1794bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
1795bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
1796bfcc09ddSBjoern A. Zeeb 		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
1797bfcc09ddSBjoern A. Zeeb 			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
1798bfcc09ddSBjoern A. Zeeb 	}
1799bfcc09ddSBjoern A. Zeeb 
1800bfcc09ddSBjoern A. Zeeb 	if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
1801bfcc09ddSBjoern A. Zeeb 		iwl_mvm_decode_he_phy_data(mvm, phy_data, he, he_mu, rx_status,
18029af1bba4SBjoern A. Zeeb 					   queue);
1803bfcc09ddSBjoern A. Zeeb 
1804bfcc09ddSBjoern A. Zeeb 	/* update aggregation data for monitor sake on default queue */
1805bfcc09ddSBjoern A. Zeeb 	if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
18069af1bba4SBjoern A. Zeeb 	    (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
1807bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
18089af1bba4SBjoern A. Zeeb 		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
1809bfcc09ddSBjoern A. Zeeb 			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
1810bfcc09ddSBjoern A. Zeeb 	}
1811bfcc09ddSBjoern A. Zeeb 
1812bfcc09ddSBjoern A. Zeeb 	if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
1813bfcc09ddSBjoern A. Zeeb 	    rate_n_flags & RATE_MCS_HE_106T_MSK) {
1814bfcc09ddSBjoern A. Zeeb 		rx_status->bw = RATE_INFO_BW_HE_RU;
1815bfcc09ddSBjoern A. Zeeb 		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
1816bfcc09ddSBjoern A. Zeeb 	}
1817bfcc09ddSBjoern A. Zeeb 
1818bfcc09ddSBjoern A. Zeeb 	/* actually data is filled in mac80211 */
1819bfcc09ddSBjoern A. Zeeb 	if (he_type == RATE_MCS_HE_TYPE_SU ||
1820bfcc09ddSBjoern A. Zeeb 	    he_type == RATE_MCS_HE_TYPE_EXT_SU)
1821bfcc09ddSBjoern A. Zeeb 		he->data1 |=
1822bfcc09ddSBjoern A. Zeeb 			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
1823bfcc09ddSBjoern A. Zeeb 
1824bfcc09ddSBjoern A. Zeeb #define CHECK_TYPE(F)							\
1825bfcc09ddSBjoern A. Zeeb 	BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F !=	\
1826bfcc09ddSBjoern A. Zeeb 		     (RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))
1827bfcc09ddSBjoern A. Zeeb 
1828bfcc09ddSBjoern A. Zeeb 	CHECK_TYPE(SU);
1829bfcc09ddSBjoern A. Zeeb 	CHECK_TYPE(EXT_SU);
1830bfcc09ddSBjoern A. Zeeb 	CHECK_TYPE(MU);
1831bfcc09ddSBjoern A. Zeeb 	CHECK_TYPE(TRIG);
1832bfcc09ddSBjoern A. Zeeb 
1833bfcc09ddSBjoern A. Zeeb 	he->data1 |= cpu_to_le16(he_type >> RATE_MCS_HE_TYPE_POS);
1834bfcc09ddSBjoern A. Zeeb 
1835bfcc09ddSBjoern A. Zeeb 	if (rate_n_flags & RATE_MCS_BF_MSK)
1836bfcc09ddSBjoern A. Zeeb 		he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);
1837bfcc09ddSBjoern A. Zeeb 
1838bfcc09ddSBjoern A. Zeeb 	switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>
1839bfcc09ddSBjoern A. Zeeb 		RATE_MCS_HE_GI_LTF_POS) {
1840bfcc09ddSBjoern A. Zeeb 	case 0:
1841bfcc09ddSBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_TRIG)
1842bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
1843bfcc09ddSBjoern A. Zeeb 		else
1844bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
1845bfcc09ddSBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_MU)
1846bfcc09ddSBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
1847bfcc09ddSBjoern A. Zeeb 		else
1848bfcc09ddSBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;
1849bfcc09ddSBjoern A. Zeeb 		break;
1850bfcc09ddSBjoern A. Zeeb 	case 1:
1851bfcc09ddSBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_TRIG)
1852bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
1853bfcc09ddSBjoern A. Zeeb 		else
1854bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
1855bfcc09ddSBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
1856bfcc09ddSBjoern A. Zeeb 		break;
1857bfcc09ddSBjoern A. Zeeb 	case 2:
1858bfcc09ddSBjoern A. Zeeb 		if (he_type == RATE_MCS_HE_TYPE_TRIG) {
1859bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
1860bfcc09ddSBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
1861bfcc09ddSBjoern A. Zeeb 		} else {
1862bfcc09ddSBjoern A. Zeeb 			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
1863bfcc09ddSBjoern A. Zeeb 			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
1864bfcc09ddSBjoern A. Zeeb 		}
1865bfcc09ddSBjoern A. Zeeb 		break;
1866bfcc09ddSBjoern A. Zeeb 	case 3:
1867bfcc09ddSBjoern A. Zeeb 		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
1868bfcc09ddSBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
1869bfcc09ddSBjoern A. Zeeb 		break;
1870bfcc09ddSBjoern A. Zeeb 	case 4:
1871bfcc09ddSBjoern A. Zeeb 		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
1872bfcc09ddSBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
1873bfcc09ddSBjoern A. Zeeb 		break;
1874bfcc09ddSBjoern A. Zeeb 	default:
1875bfcc09ddSBjoern A. Zeeb 		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
1876bfcc09ddSBjoern A. Zeeb 	}
1877bfcc09ddSBjoern A. Zeeb 
1878bfcc09ddSBjoern A. Zeeb 	he->data5 |= le16_encode_bits(ltf,
1879bfcc09ddSBjoern A. Zeeb 				      IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
1880bfcc09ddSBjoern A. Zeeb }
1881bfcc09ddSBjoern A. Zeeb 
1882bfcc09ddSBjoern A. Zeeb static void iwl_mvm_decode_lsig(struct sk_buff *skb,
1883bfcc09ddSBjoern A. Zeeb 				struct iwl_mvm_rx_phy_data *phy_data)
1884bfcc09ddSBjoern A. Zeeb {
1885bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
1886bfcc09ddSBjoern A. Zeeb 	struct ieee80211_radiotap_lsig *lsig;
1887bfcc09ddSBjoern A. Zeeb 
1888bfcc09ddSBjoern A. Zeeb 	switch (phy_data->info_type) {
1889bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HT:
1890bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_VHT_SU:
1891bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_VHT_MU:
1892bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
1893bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_SU:
1894bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU:
1895bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
1896bfcc09ddSBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_HE_TB:
18979af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_MU:
18989af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_TB:
18999af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:
19009af1bba4SBjoern A. Zeeb 	case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:
1901bfcc09ddSBjoern A. Zeeb 		lsig = skb_put(skb, sizeof(*lsig));
1902bfcc09ddSBjoern A. Zeeb 		lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);
1903bfcc09ddSBjoern A. Zeeb 		lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->d1,
1904bfcc09ddSBjoern A. Zeeb 							     IWL_RX_PHY_DATA1_LSIG_LEN_MASK),
1905bfcc09ddSBjoern A. Zeeb 					       IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH);
1906bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_RADIOTAP_LSIG;
1907bfcc09ddSBjoern A. Zeeb 		break;
1908bfcc09ddSBjoern A. Zeeb 	default:
1909bfcc09ddSBjoern A. Zeeb 		break;
1910bfcc09ddSBjoern A. Zeeb 	}
1911bfcc09ddSBjoern A. Zeeb }
1912bfcc09ddSBjoern A. Zeeb 
1913bfcc09ddSBjoern A. Zeeb struct iwl_rx_sta_csa {
1914bfcc09ddSBjoern A. Zeeb 	bool all_sta_unblocked;
1915bfcc09ddSBjoern A. Zeeb 	struct ieee80211_vif *vif;
1916bfcc09ddSBjoern A. Zeeb };
1917bfcc09ddSBjoern A. Zeeb 
1918bfcc09ddSBjoern A. Zeeb static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta)
1919bfcc09ddSBjoern A. Zeeb {
1920bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1921bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_sta_csa *rx_sta_csa = data;
1922bfcc09ddSBjoern A. Zeeb 
1923bfcc09ddSBjoern A. Zeeb 	if (mvmsta->vif != rx_sta_csa->vif)
1924bfcc09ddSBjoern A. Zeeb 		return;
1925bfcc09ddSBjoern A. Zeeb 
1926bfcc09ddSBjoern A. Zeeb 	if (mvmsta->disable_tx)
1927bfcc09ddSBjoern A. Zeeb 		rx_sta_csa->all_sta_unblocked = false;
1928bfcc09ddSBjoern A. Zeeb }
1929bfcc09ddSBjoern A. Zeeb 
19309af1bba4SBjoern A. Zeeb /*
19319af1bba4SBjoern A. Zeeb  * Note: requires also rx_status->band to be prefilled, as well
19329af1bba4SBjoern A. Zeeb  * as phy_data (apart from phy_data->info_type)
19339af1bba4SBjoern A. Zeeb  */
19349af1bba4SBjoern A. Zeeb static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
19359af1bba4SBjoern A. Zeeb 				   struct sk_buff *skb,
19369af1bba4SBjoern A. Zeeb 				   struct iwl_mvm_rx_phy_data *phy_data,
19379af1bba4SBjoern A. Zeeb 				   int queue)
19389af1bba4SBjoern A. Zeeb {
19399af1bba4SBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
19409af1bba4SBjoern A. Zeeb 	u32 rate_n_flags = phy_data->rate_n_flags;
19419af1bba4SBjoern A. Zeeb 	u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
19429af1bba4SBjoern A. Zeeb 	u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
19439af1bba4SBjoern A. Zeeb 	bool is_sgi;
19449af1bba4SBjoern A. Zeeb 
19459af1bba4SBjoern A. Zeeb 	phy_data->info_type = IWL_RX_PHY_INFO_TYPE_NONE;
19469af1bba4SBjoern A. Zeeb 
19479af1bba4SBjoern A. Zeeb 	if (phy_data->phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
19489af1bba4SBjoern A. Zeeb 		phy_data->info_type =
19499af1bba4SBjoern A. Zeeb 			le32_get_bits(phy_data->d1,
19509af1bba4SBjoern A. Zeeb 				      IWL_RX_PHY_DATA1_INFO_TYPE_MASK);
19519af1bba4SBjoern A. Zeeb 
19529af1bba4SBjoern A. Zeeb 	/* This may be overridden by iwl_mvm_rx_he() to HE_RU */
19539af1bba4SBjoern A. Zeeb 	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
19549af1bba4SBjoern A. Zeeb 	case RATE_MCS_CHAN_WIDTH_20:
19559af1bba4SBjoern A. Zeeb 		break;
19569af1bba4SBjoern A. Zeeb 	case RATE_MCS_CHAN_WIDTH_40:
19579af1bba4SBjoern A. Zeeb 		rx_status->bw = RATE_INFO_BW_40;
19589af1bba4SBjoern A. Zeeb 		break;
19599af1bba4SBjoern A. Zeeb 	case RATE_MCS_CHAN_WIDTH_80:
19609af1bba4SBjoern A. Zeeb 		rx_status->bw = RATE_INFO_BW_80;
19619af1bba4SBjoern A. Zeeb 		break;
19629af1bba4SBjoern A. Zeeb 	case RATE_MCS_CHAN_WIDTH_160:
19639af1bba4SBjoern A. Zeeb 		rx_status->bw = RATE_INFO_BW_160;
19649af1bba4SBjoern A. Zeeb 		break;
19659af1bba4SBjoern A. Zeeb 	case RATE_MCS_CHAN_WIDTH_320:
19669af1bba4SBjoern A. Zeeb 		rx_status->bw = RATE_INFO_BW_320;
19679af1bba4SBjoern A. Zeeb 		break;
19689af1bba4SBjoern A. Zeeb 	}
19699af1bba4SBjoern A. Zeeb 
19709af1bba4SBjoern A. Zeeb 	/* must be before L-SIG data */
19719af1bba4SBjoern A. Zeeb 	if (format == RATE_MCS_HE_MSK)
19729af1bba4SBjoern A. Zeeb 		iwl_mvm_rx_he(mvm, skb, phy_data, queue);
19739af1bba4SBjoern A. Zeeb 
19749af1bba4SBjoern A. Zeeb 	iwl_mvm_decode_lsig(skb, phy_data);
19759af1bba4SBjoern A. Zeeb 
19769af1bba4SBjoern A. Zeeb 	rx_status->device_timestamp = phy_data->gp2_on_air_rise;
1977*a4128aadSBjoern A. Zeeb 
1978*a4128aadSBjoern A. Zeeb 	if (mvm->rx_ts_ptp && mvm->monitor_on) {
1979*a4128aadSBjoern A. Zeeb 		u64 adj_time =
1980*a4128aadSBjoern A. Zeeb 			iwl_mvm_ptp_get_adj_time(mvm, phy_data->gp2_on_air_rise * NSEC_PER_USEC);
1981*a4128aadSBjoern A. Zeeb 
1982*a4128aadSBjoern A. Zeeb 		rx_status->mactime = div64_u64(adj_time, NSEC_PER_USEC);
1983*a4128aadSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_MACTIME_IS_RTAP_TS64;
1984*a4128aadSBjoern A. Zeeb 		rx_status->flag &= ~RX_FLAG_MACTIME;
1985*a4128aadSBjoern A. Zeeb 	}
1986*a4128aadSBjoern A. Zeeb 
19879af1bba4SBjoern A. Zeeb 	rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,
19889af1bba4SBjoern A. Zeeb 							 rx_status->band);
19899af1bba4SBjoern A. Zeeb 	iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,
19909af1bba4SBjoern A. Zeeb 				    phy_data->energy_a, phy_data->energy_b);
19919af1bba4SBjoern A. Zeeb 
19929af1bba4SBjoern A. Zeeb 	/* using TLV format and must be after all fixed len fields */
19939af1bba4SBjoern A. Zeeb 	if (format == RATE_MCS_EHT_MSK)
19949af1bba4SBjoern A. Zeeb 		iwl_mvm_rx_eht(mvm, skb, phy_data, queue);
19959af1bba4SBjoern A. Zeeb 
19969af1bba4SBjoern A. Zeeb 	if (unlikely(mvm->monitor_on))
19979af1bba4SBjoern A. Zeeb 		iwl_mvm_add_rtap_sniffer_config(mvm, skb);
19989af1bba4SBjoern A. Zeeb 
19999af1bba4SBjoern A. Zeeb 	is_sgi = format == RATE_MCS_HE_MSK ?
20009af1bba4SBjoern A. Zeeb 		iwl_he_is_sgi(rate_n_flags) :
20019af1bba4SBjoern A. Zeeb 		rate_n_flags & RATE_MCS_SGI_MSK;
20029af1bba4SBjoern A. Zeeb 
20039af1bba4SBjoern A. Zeeb 	if (!(format == RATE_MCS_CCK_MSK) && is_sgi)
20049af1bba4SBjoern A. Zeeb 		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
20059af1bba4SBjoern A. Zeeb 
20069af1bba4SBjoern A. Zeeb 	if (rate_n_flags & RATE_MCS_LDPC_MSK)
20079af1bba4SBjoern A. Zeeb 		rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
20089af1bba4SBjoern A. Zeeb 
20099af1bba4SBjoern A. Zeeb 	switch (format) {
20109af1bba4SBjoern A. Zeeb 	case RATE_MCS_VHT_MSK:
20119af1bba4SBjoern A. Zeeb 		rx_status->encoding = RX_ENC_VHT;
20129af1bba4SBjoern A. Zeeb 		break;
20139af1bba4SBjoern A. Zeeb 	case RATE_MCS_HE_MSK:
20149af1bba4SBjoern A. Zeeb 		rx_status->encoding = RX_ENC_HE;
20159af1bba4SBjoern A. Zeeb 		rx_status->he_dcm =
20169af1bba4SBjoern A. Zeeb 			!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);
20179af1bba4SBjoern A. Zeeb 		break;
20189af1bba4SBjoern A. Zeeb 	case RATE_MCS_EHT_MSK:
20199af1bba4SBjoern A. Zeeb 		rx_status->encoding = RX_ENC_EHT;
20209af1bba4SBjoern A. Zeeb 		break;
20219af1bba4SBjoern A. Zeeb 	}
20229af1bba4SBjoern A. Zeeb 
20239af1bba4SBjoern A. Zeeb 	switch (format) {
20249af1bba4SBjoern A. Zeeb 	case RATE_MCS_HT_MSK:
20259af1bba4SBjoern A. Zeeb 		rx_status->encoding = RX_ENC_HT;
20269af1bba4SBjoern A. Zeeb 		rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
20279af1bba4SBjoern A. Zeeb 		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
20289af1bba4SBjoern A. Zeeb 		break;
20299af1bba4SBjoern A. Zeeb 	case RATE_MCS_VHT_MSK:
20309af1bba4SBjoern A. Zeeb 	case RATE_MCS_HE_MSK:
20319af1bba4SBjoern A. Zeeb 	case RATE_MCS_EHT_MSK:
20329af1bba4SBjoern A. Zeeb 		rx_status->nss =
20339af1bba4SBjoern A. Zeeb 			u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;
20349af1bba4SBjoern A. Zeeb 		rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
20359af1bba4SBjoern A. Zeeb 		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
20369af1bba4SBjoern A. Zeeb 		break;
20379af1bba4SBjoern A. Zeeb 	default: {
20389af1bba4SBjoern A. Zeeb 		int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
20399af1bba4SBjoern A. Zeeb 								 rx_status->band);
20409af1bba4SBjoern A. Zeeb 
20419af1bba4SBjoern A. Zeeb 		rx_status->rate_idx = rate;
20429af1bba4SBjoern A. Zeeb 
20439af1bba4SBjoern A. Zeeb 		if ((rate < 0 || rate > 0xFF)) {
20449af1bba4SBjoern A. Zeeb 			rx_status->rate_idx = 0;
20459af1bba4SBjoern A. Zeeb 			if (net_ratelimit())
20469af1bba4SBjoern A. Zeeb 				IWL_ERR(mvm, "Invalid rate flags 0x%x, band %d,\n",
20479af1bba4SBjoern A. Zeeb 					rate_n_flags, rx_status->band);
20489af1bba4SBjoern A. Zeeb 		}
20499af1bba4SBjoern A. Zeeb 
20509af1bba4SBjoern A. Zeeb 		break;
20519af1bba4SBjoern A. Zeeb 		}
20529af1bba4SBjoern A. Zeeb 	}
20539af1bba4SBjoern A. Zeeb }
20549af1bba4SBjoern A. Zeeb 
2055bfcc09ddSBjoern A. Zeeb void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
2056bfcc09ddSBjoern A. Zeeb 			struct iwl_rx_cmd_buffer *rxb, int queue)
2057bfcc09ddSBjoern A. Zeeb {
2058bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status;
2059bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
2060bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
2061bfcc09ddSBjoern A. Zeeb 	struct ieee80211_hdr *hdr;
2062bfcc09ddSBjoern A. Zeeb 	u32 len;
2063bfcc09ddSBjoern A. Zeeb 	u32 pkt_len = iwl_rx_packet_payload_len(pkt);
2064bfcc09ddSBjoern A. Zeeb 	struct ieee80211_sta *sta = NULL;
2065bfcc09ddSBjoern A. Zeeb 	struct sk_buff *skb;
20669af1bba4SBjoern A. Zeeb 	u8 crypt_len = 0;
2067*a4128aadSBjoern A. Zeeb 	u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);
2068bfcc09ddSBjoern A. Zeeb 	size_t desc_size;
20699af1bba4SBjoern A. Zeeb 	struct iwl_mvm_rx_phy_data phy_data = {};
2070bfcc09ddSBjoern A. Zeeb 	u32 format;
2071bfcc09ddSBjoern A. Zeeb 
2072bfcc09ddSBjoern A. Zeeb 	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
2073bfcc09ddSBjoern A. Zeeb 		return;
2074bfcc09ddSBjoern A. Zeeb 
2075bfcc09ddSBjoern A. Zeeb 	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
2076bfcc09ddSBjoern A. Zeeb 		desc_size = sizeof(*desc);
2077bfcc09ddSBjoern A. Zeeb 	else
2078bfcc09ddSBjoern A. Zeeb 		desc_size = IWL_RX_DESC_SIZE_V1;
2079bfcc09ddSBjoern A. Zeeb 
2080bfcc09ddSBjoern A. Zeeb 	if (unlikely(pkt_len < desc_size)) {
2081bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, "Bad REPLY_RX_MPDU_CMD size\n");
2082bfcc09ddSBjoern A. Zeeb 		return;
2083bfcc09ddSBjoern A. Zeeb 	}
2084bfcc09ddSBjoern A. Zeeb 
2085bfcc09ddSBjoern A. Zeeb 	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
20869af1bba4SBjoern A. Zeeb 		phy_data.rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
20879af1bba4SBjoern A. Zeeb 		phy_data.channel = desc->v3.channel;
20889af1bba4SBjoern A. Zeeb 		phy_data.gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
20899af1bba4SBjoern A. Zeeb 		phy_data.energy_a = desc->v3.energy_a;
20909af1bba4SBjoern A. Zeeb 		phy_data.energy_b = desc->v3.energy_b;
2091bfcc09ddSBjoern A. Zeeb 
2092bfcc09ddSBjoern A. Zeeb 		phy_data.d0 = desc->v3.phy_data0;
2093bfcc09ddSBjoern A. Zeeb 		phy_data.d1 = desc->v3.phy_data1;
2094bfcc09ddSBjoern A. Zeeb 		phy_data.d2 = desc->v3.phy_data2;
2095bfcc09ddSBjoern A. Zeeb 		phy_data.d3 = desc->v3.phy_data3;
20969af1bba4SBjoern A. Zeeb 		phy_data.eht_d4 = desc->phy_eht_data4;
20979af1bba4SBjoern A. Zeeb 		phy_data.d5 = desc->v3.phy_data5;
2098bfcc09ddSBjoern A. Zeeb 	} else {
20999af1bba4SBjoern A. Zeeb 		phy_data.rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
21009af1bba4SBjoern A. Zeeb 		phy_data.channel = desc->v1.channel;
21019af1bba4SBjoern A. Zeeb 		phy_data.gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
21029af1bba4SBjoern A. Zeeb 		phy_data.energy_a = desc->v1.energy_a;
21039af1bba4SBjoern A. Zeeb 		phy_data.energy_b = desc->v1.energy_b;
2104bfcc09ddSBjoern A. Zeeb 
2105bfcc09ddSBjoern A. Zeeb 		phy_data.d0 = desc->v1.phy_data0;
2106bfcc09ddSBjoern A. Zeeb 		phy_data.d1 = desc->v1.phy_data1;
2107bfcc09ddSBjoern A. Zeeb 		phy_data.d2 = desc->v1.phy_data2;
2108bfcc09ddSBjoern A. Zeeb 		phy_data.d3 = desc->v1.phy_data3;
2109bfcc09ddSBjoern A. Zeeb 	}
21109af1bba4SBjoern A. Zeeb 
2111bfcc09ddSBjoern A. Zeeb 	if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
2112bfcc09ddSBjoern A. Zeeb 				    REPLY_RX_MPDU_CMD, 0) < 4) {
21139af1bba4SBjoern A. Zeeb 		phy_data.rate_n_flags = iwl_new_rate_from_v1(phy_data.rate_n_flags);
2114bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, "Got old format rate, converting. New rate: 0x%x\n",
21159af1bba4SBjoern A. Zeeb 			       phy_data.rate_n_flags);
2116bfcc09ddSBjoern A. Zeeb 	}
21179af1bba4SBjoern A. Zeeb 
21189af1bba4SBjoern A. Zeeb 	format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
2119bfcc09ddSBjoern A. Zeeb 
2120bfcc09ddSBjoern A. Zeeb 	len = le16_to_cpu(desc->mpdu_len);
2121bfcc09ddSBjoern A. Zeeb 
2122bfcc09ddSBjoern A. Zeeb 	if (unlikely(len + desc_size > pkt_len)) {
2123bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, "FW lied about packet len\n");
2124bfcc09ddSBjoern A. Zeeb 		return;
2125bfcc09ddSBjoern A. Zeeb 	}
2126bfcc09ddSBjoern A. Zeeb 
21279af1bba4SBjoern A. Zeeb 	phy_data.with_data = true;
21289af1bba4SBjoern A. Zeeb 	phy_data.phy_info = le16_to_cpu(desc->phy_info);
2129bfcc09ddSBjoern A. Zeeb 	phy_data.d4 = desc->phy_data4;
2130bfcc09ddSBjoern A. Zeeb 
2131bfcc09ddSBjoern A. Zeeb 	hdr = (void *)(pkt->data + desc_size);
2132bfcc09ddSBjoern A. Zeeb 	/* Dont use dev_alloc_skb(), we'll have enough headroom once
2133bfcc09ddSBjoern A. Zeeb 	 * ieee80211_hdr pulled.
2134bfcc09ddSBjoern A. Zeeb 	 */
2135bfcc09ddSBjoern A. Zeeb 	skb = alloc_skb(128, GFP_ATOMIC);
2136bfcc09ddSBjoern A. Zeeb 	if (!skb) {
2137bfcc09ddSBjoern A. Zeeb 		IWL_ERR(mvm, "alloc_skb failed\n");
2138bfcc09ddSBjoern A. Zeeb 		return;
2139bfcc09ddSBjoern A. Zeeb 	}
2140bfcc09ddSBjoern A. Zeeb 
2141bfcc09ddSBjoern A. Zeeb 	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
2142bfcc09ddSBjoern A. Zeeb 		/*
2143bfcc09ddSBjoern A. Zeeb 		 * If the device inserted padding it means that (it thought)
2144bfcc09ddSBjoern A. Zeeb 		 * the 802.11 header wasn't a multiple of 4 bytes long. In
2145bfcc09ddSBjoern A. Zeeb 		 * this case, reserve two bytes at the start of the SKB to
2146bfcc09ddSBjoern A. Zeeb 		 * align the payload properly in case we end up copying it.
2147bfcc09ddSBjoern A. Zeeb 		 */
2148bfcc09ddSBjoern A. Zeeb 		skb_reserve(skb, 2);
2149bfcc09ddSBjoern A. Zeeb 	}
2150bfcc09ddSBjoern A. Zeeb 
2151bfcc09ddSBjoern A. Zeeb 	rx_status = IEEE80211_SKB_RXCB(skb);
2152bfcc09ddSBjoern A. Zeeb 
2153bfcc09ddSBjoern A. Zeeb 	/*
2154bfcc09ddSBjoern A. Zeeb 	 * Keep packets with CRC errors (and with overrun) for monitor mode
2155bfcc09ddSBjoern A. Zeeb 	 * (otherwise the firmware discards them) but mark them as bad.
2156bfcc09ddSBjoern A. Zeeb 	 */
2157bfcc09ddSBjoern A. Zeeb 	if (!(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_CRC_OK)) ||
2158bfcc09ddSBjoern A. Zeeb 	    !(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_OVERRUN_OK))) {
2159bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n",
2160bfcc09ddSBjoern A. Zeeb 			     le32_to_cpu(desc->status));
2161bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
2162bfcc09ddSBjoern A. Zeeb 	}
21639af1bba4SBjoern A. Zeeb 
2164bfcc09ddSBjoern A. Zeeb 	/* set the preamble flag if appropriate */
2165bfcc09ddSBjoern A. Zeeb 	if (format == RATE_MCS_CCK_MSK &&
21669af1bba4SBjoern A. Zeeb 	    phy_data.phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
2167bfcc09ddSBjoern A. Zeeb 		rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
2168bfcc09ddSBjoern A. Zeeb 
21699af1bba4SBjoern A. Zeeb 	if (likely(!(phy_data.phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
2170bfcc09ddSBjoern A. Zeeb 		u64 tsf_on_air_rise;
2171bfcc09ddSBjoern A. Zeeb 
2172bfcc09ddSBjoern A. Zeeb 		if (mvm->trans->trans_cfg->device_family >=
2173bfcc09ddSBjoern A. Zeeb 		    IWL_DEVICE_FAMILY_AX210)
2174bfcc09ddSBjoern A. Zeeb 			tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
2175bfcc09ddSBjoern A. Zeeb 		else
2176bfcc09ddSBjoern A. Zeeb 			tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);
2177bfcc09ddSBjoern A. Zeeb 
2178bfcc09ddSBjoern A. Zeeb 		rx_status->mactime = tsf_on_air_rise;
2179bfcc09ddSBjoern A. Zeeb 		/* TSF as indicated by the firmware is at INA time */
2180bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
2181bfcc09ddSBjoern A. Zeeb 	}
2182bfcc09ddSBjoern A. Zeeb 
2183bfcc09ddSBjoern A. Zeeb 	if (iwl_mvm_is_band_in_rx_supported(mvm)) {
2184bfcc09ddSBjoern A. Zeeb 		u8 band = BAND_IN_RX_STATUS(desc->mac_phy_idx);
2185bfcc09ddSBjoern A. Zeeb 
2186*a4128aadSBjoern A. Zeeb 		rx_status->band = iwl_mvm_nl80211_band_from_phy(band);
2187bfcc09ddSBjoern A. Zeeb 	} else {
21889af1bba4SBjoern A. Zeeb 		rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
2189bfcc09ddSBjoern A. Zeeb 			NL80211_BAND_2GHZ;
2190bfcc09ddSBjoern A. Zeeb 	}
2191bfcc09ddSBjoern A. Zeeb 
2192bfcc09ddSBjoern A. Zeeb 	/* update aggregation data for monitor sake on default queue */
21939af1bba4SBjoern A. Zeeb 	if (!queue && (phy_data.phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
21949af1bba4SBjoern A. Zeeb 		bool toggle_bit;
2195bfcc09ddSBjoern A. Zeeb 
21969af1bba4SBjoern A. Zeeb 		toggle_bit = phy_data.phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
2197bfcc09ddSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
2198bfcc09ddSBjoern A. Zeeb 		/*
2199bfcc09ddSBjoern A. Zeeb 		 * Toggle is switched whenever new aggregation starts. Make
2200bfcc09ddSBjoern A. Zeeb 		 * sure ampdu_reference is never 0 so we can later use it to
2201bfcc09ddSBjoern A. Zeeb 		 * see if the frame was really part of an A-MPDU or not.
2202bfcc09ddSBjoern A. Zeeb 		 */
2203bfcc09ddSBjoern A. Zeeb 		if (toggle_bit != mvm->ampdu_toggle) {
2204bfcc09ddSBjoern A. Zeeb 			mvm->ampdu_ref++;
2205bfcc09ddSBjoern A. Zeeb 			if (mvm->ampdu_ref == 0)
2206bfcc09ddSBjoern A. Zeeb 				mvm->ampdu_ref++;
2207bfcc09ddSBjoern A. Zeeb 			mvm->ampdu_toggle = toggle_bit;
22089af1bba4SBjoern A. Zeeb 			phy_data.first_subframe = true;
2209bfcc09ddSBjoern A. Zeeb 		}
2210bfcc09ddSBjoern A. Zeeb 		rx_status->ampdu_reference = mvm->ampdu_ref;
2211bfcc09ddSBjoern A. Zeeb 	}
2212bfcc09ddSBjoern A. Zeeb 
2213bfcc09ddSBjoern A. Zeeb 	rcu_read_lock();
2214bfcc09ddSBjoern A. Zeeb 
2215bfcc09ddSBjoern A. Zeeb 	if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
2216*a4128aadSBjoern A. Zeeb 		if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) {
2217*a4128aadSBjoern A. Zeeb 			struct ieee80211_link_sta *link_sta;
2218bfcc09ddSBjoern A. Zeeb 
2219*a4128aadSBjoern A. Zeeb 			sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
2220bfcc09ddSBjoern A. Zeeb 			if (IS_ERR(sta))
2221bfcc09ddSBjoern A. Zeeb 				sta = NULL;
2222*a4128aadSBjoern A. Zeeb 			link_sta = rcu_dereference(mvm->fw_id_to_link_sta[sta_id]);
2223*a4128aadSBjoern A. Zeeb 
2224*a4128aadSBjoern A. Zeeb 			if (sta && sta->valid_links && link_sta) {
2225*a4128aadSBjoern A. Zeeb 				rx_status->link_valid = 1;
2226*a4128aadSBjoern A. Zeeb 				rx_status->link_id = link_sta->link_id;
2227*a4128aadSBjoern A. Zeeb 			}
2228bfcc09ddSBjoern A. Zeeb 		}
2229bfcc09ddSBjoern A. Zeeb 	} else if (!is_multicast_ether_addr(hdr->addr2)) {
2230bfcc09ddSBjoern A. Zeeb 		/*
2231bfcc09ddSBjoern A. Zeeb 		 * This is fine since we prevent two stations with the same
2232bfcc09ddSBjoern A. Zeeb 		 * address from being added.
2233bfcc09ddSBjoern A. Zeeb 		 */
2234bfcc09ddSBjoern A. Zeeb 		sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
2235bfcc09ddSBjoern A. Zeeb 	}
2236bfcc09ddSBjoern A. Zeeb 
22379af1bba4SBjoern A. Zeeb 	if (iwl_mvm_rx_crypto(mvm, sta, hdr, rx_status, phy_data.phy_info, desc,
2238bfcc09ddSBjoern A. Zeeb 			      le32_to_cpu(pkt->len_n_flags), queue,
2239bfcc09ddSBjoern A. Zeeb 			      &crypt_len)) {
2240bfcc09ddSBjoern A. Zeeb 		kfree_skb(skb);
2241bfcc09ddSBjoern A. Zeeb 		goto out;
2242bfcc09ddSBjoern A. Zeeb 	}
2243bfcc09ddSBjoern A. Zeeb 
22449af1bba4SBjoern A. Zeeb 	iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
22459af1bba4SBjoern A. Zeeb 
2246bfcc09ddSBjoern A. Zeeb 	if (sta) {
2247bfcc09ddSBjoern A. Zeeb 		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
2248bfcc09ddSBjoern A. Zeeb 		struct ieee80211_vif *tx_blocked_vif =
2249bfcc09ddSBjoern A. Zeeb 			rcu_dereference(mvm->csa_tx_blocked_vif);
2250bfcc09ddSBjoern A. Zeeb 		u8 baid = (u8)((le32_to_cpu(desc->reorder_data) &
2251bfcc09ddSBjoern A. Zeeb 			       IWL_RX_MPDU_REORDER_BAID_MASK) >>
2252bfcc09ddSBjoern A. Zeeb 			       IWL_RX_MPDU_REORDER_BAID_SHIFT);
2253bfcc09ddSBjoern A. Zeeb 		struct iwl_fw_dbg_trigger_tlv *trig;
2254bfcc09ddSBjoern A. Zeeb 		struct ieee80211_vif *vif = mvmsta->vif;
2255bfcc09ddSBjoern A. Zeeb 
2256bfcc09ddSBjoern A. Zeeb 		if (!mvm->tcm.paused && len >= sizeof(*hdr) &&
2257bfcc09ddSBjoern A. Zeeb 		    !is_multicast_ether_addr(hdr->addr1) &&
2258bfcc09ddSBjoern A. Zeeb 		    ieee80211_is_data(hdr->frame_control) &&
2259bfcc09ddSBjoern A. Zeeb 		    time_after(jiffies, mvm->tcm.ts + MVM_TCM_PERIOD))
2260bfcc09ddSBjoern A. Zeeb 			schedule_delayed_work(&mvm->tcm.work, 0);
2261bfcc09ddSBjoern A. Zeeb 
2262bfcc09ddSBjoern A. Zeeb 		/*
2263bfcc09ddSBjoern A. Zeeb 		 * We have tx blocked stations (with CS bit). If we heard
2264bfcc09ddSBjoern A. Zeeb 		 * frames from a blocked station on a new channel we can
2265bfcc09ddSBjoern A. Zeeb 		 * TX to it again.
2266bfcc09ddSBjoern A. Zeeb 		 */
2267bfcc09ddSBjoern A. Zeeb 		if (unlikely(tx_blocked_vif) && tx_blocked_vif == vif) {
2268bfcc09ddSBjoern A. Zeeb 			struct iwl_mvm_vif *mvmvif =
2269bfcc09ddSBjoern A. Zeeb 				iwl_mvm_vif_from_mac80211(tx_blocked_vif);
2270bfcc09ddSBjoern A. Zeeb 			struct iwl_rx_sta_csa rx_sta_csa = {
2271bfcc09ddSBjoern A. Zeeb 				.all_sta_unblocked = true,
2272bfcc09ddSBjoern A. Zeeb 				.vif = tx_blocked_vif,
2273bfcc09ddSBjoern A. Zeeb 			};
2274bfcc09ddSBjoern A. Zeeb 
2275bfcc09ddSBjoern A. Zeeb 			if (mvmvif->csa_target_freq == rx_status->freq)
2276bfcc09ddSBjoern A. Zeeb 				iwl_mvm_sta_modify_disable_tx_ap(mvm, sta,
2277bfcc09ddSBjoern A. Zeeb 								 false);
2278bfcc09ddSBjoern A. Zeeb 			ieee80211_iterate_stations_atomic(mvm->hw,
2279bfcc09ddSBjoern A. Zeeb 							  iwl_mvm_rx_get_sta_block_tx,
2280bfcc09ddSBjoern A. Zeeb 							  &rx_sta_csa);
2281bfcc09ddSBjoern A. Zeeb 
2282bfcc09ddSBjoern A. Zeeb 			if (rx_sta_csa.all_sta_unblocked) {
2283bfcc09ddSBjoern A. Zeeb 				RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
2284bfcc09ddSBjoern A. Zeeb 				/* Unblock BCAST / MCAST station */
2285bfcc09ddSBjoern A. Zeeb 				iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
22869af1bba4SBjoern A. Zeeb 				cancel_delayed_work(&mvm->cs_tx_unblock_dwork);
2287bfcc09ddSBjoern A. Zeeb 			}
2288bfcc09ddSBjoern A. Zeeb 		}
2289bfcc09ddSBjoern A. Zeeb 
2290bfcc09ddSBjoern A. Zeeb 		rs_update_last_rssi(mvm, mvmsta, rx_status);
2291bfcc09ddSBjoern A. Zeeb 
2292bfcc09ddSBjoern A. Zeeb 		trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
2293bfcc09ddSBjoern A. Zeeb 					     ieee80211_vif_to_wdev(vif),
2294bfcc09ddSBjoern A. Zeeb 					     FW_DBG_TRIGGER_RSSI);
2295bfcc09ddSBjoern A. Zeeb 
2296bfcc09ddSBjoern A. Zeeb 		if (trig && ieee80211_is_beacon(hdr->frame_control)) {
2297bfcc09ddSBjoern A. Zeeb 			struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;
2298bfcc09ddSBjoern A. Zeeb 			s32 rssi;
2299bfcc09ddSBjoern A. Zeeb 
2300bfcc09ddSBjoern A. Zeeb 			rssi_trig = (void *)trig->data;
2301bfcc09ddSBjoern A. Zeeb 			rssi = le32_to_cpu(rssi_trig->rssi);
2302bfcc09ddSBjoern A. Zeeb 
2303bfcc09ddSBjoern A. Zeeb 			if (rx_status->signal < rssi)
2304bfcc09ddSBjoern A. Zeeb 				iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
2305f621b087SBjoern A. Zeeb #if defined(__linux__)
2306bfcc09ddSBjoern A. Zeeb 							NULL);
2307f621b087SBjoern A. Zeeb #elif defined(__FreeBSD__)
2308f621b087SBjoern A. Zeeb 							"");
2309f621b087SBjoern A. Zeeb #endif
2310bfcc09ddSBjoern A. Zeeb 		}
2311bfcc09ddSBjoern A. Zeeb 
2312bfcc09ddSBjoern A. Zeeb 		if (ieee80211_is_data(hdr->frame_control))
2313bfcc09ddSBjoern A. Zeeb 			iwl_mvm_rx_csum(mvm, sta, skb, pkt);
2314bfcc09ddSBjoern A. Zeeb 
2315bfcc09ddSBjoern A. Zeeb 		if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {
2316*a4128aadSBjoern A. Zeeb 			IWL_DEBUG_DROP(mvm, "Dropping duplicate packet 0x%x\n",
2317*a4128aadSBjoern A. Zeeb 				       le16_to_cpu(hdr->seq_ctrl));
2318bfcc09ddSBjoern A. Zeeb 			kfree_skb(skb);
2319bfcc09ddSBjoern A. Zeeb 			goto out;
2320bfcc09ddSBjoern A. Zeeb 		}
2321bfcc09ddSBjoern A. Zeeb 
2322bfcc09ddSBjoern A. Zeeb 		/*
2323bfcc09ddSBjoern A. Zeeb 		 * Our hardware de-aggregates AMSDUs but copies the mac header
2324bfcc09ddSBjoern A. Zeeb 		 * as it to the de-aggregated MPDUs. We need to turn off the
2325bfcc09ddSBjoern A. Zeeb 		 * AMSDU bit in the QoS control ourselves.
2326bfcc09ddSBjoern A. Zeeb 		 * In addition, HW reverses addr3 and addr4 - reverse it back.
2327bfcc09ddSBjoern A. Zeeb 		 */
2328bfcc09ddSBjoern A. Zeeb 		if ((desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&
2329bfcc09ddSBjoern A. Zeeb 		    !WARN_ON(!ieee80211_is_data_qos(hdr->frame_control))) {
2330bfcc09ddSBjoern A. Zeeb 			u8 *qc = ieee80211_get_qos_ctl(hdr);
2331bfcc09ddSBjoern A. Zeeb 
2332bfcc09ddSBjoern A. Zeeb 			*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
2333bfcc09ddSBjoern A. Zeeb 
2334bfcc09ddSBjoern A. Zeeb 			if (mvm->trans->trans_cfg->device_family ==
2335bfcc09ddSBjoern A. Zeeb 			    IWL_DEVICE_FAMILY_9000) {
2336bfcc09ddSBjoern A. Zeeb 				iwl_mvm_flip_address(hdr->addr3);
2337bfcc09ddSBjoern A. Zeeb 
2338bfcc09ddSBjoern A. Zeeb 				if (ieee80211_has_a4(hdr->frame_control))
2339bfcc09ddSBjoern A. Zeeb 					iwl_mvm_flip_address(hdr->addr4);
2340bfcc09ddSBjoern A. Zeeb 			}
2341bfcc09ddSBjoern A. Zeeb 		}
2342bfcc09ddSBjoern A. Zeeb 		if (baid != IWL_RX_REORDER_DATA_INVALID_BAID) {
2343bfcc09ddSBjoern A. Zeeb 			u32 reorder_data = le32_to_cpu(desc->reorder_data);
2344bfcc09ddSBjoern A. Zeeb 
2345bfcc09ddSBjoern A. Zeeb 			iwl_mvm_agg_rx_received(mvm, reorder_data, baid);
2346bfcc09ddSBjoern A. Zeeb 		}
2347*a4128aadSBjoern A. Zeeb 
2348*a4128aadSBjoern A. Zeeb 		if (ieee80211_is_data(hdr->frame_control)) {
2349*a4128aadSBjoern A. Zeeb 			u8 sub_frame_idx = desc->amsdu_info &
2350*a4128aadSBjoern A. Zeeb 				IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
2351*a4128aadSBjoern A. Zeeb 
2352*a4128aadSBjoern A. Zeeb 			/* 0 means not an A-MSDU, and 1 means a new A-MSDU */
2353*a4128aadSBjoern A. Zeeb 			if (!sub_frame_idx || sub_frame_idx == 1)
2354*a4128aadSBjoern A. Zeeb 				iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false,
2355*a4128aadSBjoern A. Zeeb 						   queue);
2356*a4128aadSBjoern A. Zeeb 		}
2357bfcc09ddSBjoern A. Zeeb 	}
2358bfcc09ddSBjoern A. Zeeb 
2359bfcc09ddSBjoern A. Zeeb 	/* management stuff on default queue */
2360bfcc09ddSBjoern A. Zeeb 	if (!queue) {
2361bfcc09ddSBjoern A. Zeeb 		if (unlikely((ieee80211_is_beacon(hdr->frame_control) ||
2362bfcc09ddSBjoern A. Zeeb 			      ieee80211_is_probe_resp(hdr->frame_control)) &&
2363bfcc09ddSBjoern A. Zeeb 			     mvm->sched_scan_pass_all ==
2364bfcc09ddSBjoern A. Zeeb 			     SCHED_SCAN_PASS_ALL_ENABLED))
2365bfcc09ddSBjoern A. Zeeb 			mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND;
2366bfcc09ddSBjoern A. Zeeb 
2367bfcc09ddSBjoern A. Zeeb 		if (unlikely(ieee80211_is_beacon(hdr->frame_control) ||
2368bfcc09ddSBjoern A. Zeeb 			     ieee80211_is_probe_resp(hdr->frame_control)))
2369bfcc09ddSBjoern A. Zeeb 			rx_status->boottime_ns = ktime_get_boottime_ns();
2370bfcc09ddSBjoern A. Zeeb 	}
2371bfcc09ddSBjoern A. Zeeb 
2372bfcc09ddSBjoern A. Zeeb 	if (iwl_mvm_create_skb(mvm, skb, hdr, len, crypt_len, rxb)) {
2373bfcc09ddSBjoern A. Zeeb 		kfree_skb(skb);
2374bfcc09ddSBjoern A. Zeeb 		goto out;
2375bfcc09ddSBjoern A. Zeeb 	}
2376bfcc09ddSBjoern A. Zeeb 
23779af1bba4SBjoern A. Zeeb 	if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
23789af1bba4SBjoern A. Zeeb 	    likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&
2379*a4128aadSBjoern A. Zeeb 	    likely(!iwl_mvm_mei_filter_scan(mvm, skb))) {
2380*a4128aadSBjoern A. Zeeb 		if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
2381*a4128aadSBjoern A. Zeeb 		    (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&
2382*a4128aadSBjoern A. Zeeb 		    !(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))
2383*a4128aadSBjoern A. Zeeb 			rx_status->flag |= RX_FLAG_AMSDU_MORE;
2384*a4128aadSBjoern A. Zeeb 
2385*a4128aadSBjoern A. Zeeb 		iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
2386*a4128aadSBjoern A. Zeeb 	}
2387bfcc09ddSBjoern A. Zeeb out:
2388bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
2389bfcc09ddSBjoern A. Zeeb }
2390bfcc09ddSBjoern A. Zeeb 
2391bfcc09ddSBjoern A. Zeeb void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
2392bfcc09ddSBjoern A. Zeeb 				struct iwl_rx_cmd_buffer *rxb, int queue)
2393bfcc09ddSBjoern A. Zeeb {
2394bfcc09ddSBjoern A. Zeeb 	struct ieee80211_rx_status *rx_status;
2395bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
23969af1bba4SBjoern A. Zeeb 	struct iwl_rx_no_data_ver_3 *desc = (void *)pkt->data;
23979af1bba4SBjoern A. Zeeb 	u32 rssi;
2398bfcc09ddSBjoern A. Zeeb 	struct ieee80211_sta *sta = NULL;
2399bfcc09ddSBjoern A. Zeeb 	struct sk_buff *skb;
24009af1bba4SBjoern A. Zeeb 	struct iwl_mvm_rx_phy_data phy_data;
2401bfcc09ddSBjoern A. Zeeb 	u32 format;
2402bfcc09ddSBjoern A. Zeeb 
2403bfcc09ddSBjoern A. Zeeb 	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
2404bfcc09ddSBjoern A. Zeeb 		return;
2405bfcc09ddSBjoern A. Zeeb 
24069af1bba4SBjoern A. Zeeb 	if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(struct iwl_rx_no_data)))
24079af1bba4SBjoern A. Zeeb 		return;
24089af1bba4SBjoern A. Zeeb 
24099af1bba4SBjoern A. Zeeb 	rssi = le32_to_cpu(desc->rssi);
24109af1bba4SBjoern A. Zeeb 	phy_data.d0 = desc->phy_info[0];
24119af1bba4SBjoern A. Zeeb 	phy_data.d1 = desc->phy_info[1];
24129af1bba4SBjoern A. Zeeb 	phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
24139af1bba4SBjoern A. Zeeb 	phy_data.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);
24149af1bba4SBjoern A. Zeeb 	phy_data.rate_n_flags = le32_to_cpu(desc->rate);
24159af1bba4SBjoern A. Zeeb 	phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);
24169af1bba4SBjoern A. Zeeb 	phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
24179af1bba4SBjoern A. Zeeb 	phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
24189af1bba4SBjoern A. Zeeb 	phy_data.with_data = false;
24199af1bba4SBjoern A. Zeeb 	phy_data.rx_vec[0] = desc->rx_vec[0];
24209af1bba4SBjoern A. Zeeb 	phy_data.rx_vec[1] = desc->rx_vec[1];
24219af1bba4SBjoern A. Zeeb 
24229af1bba4SBjoern A. Zeeb 	if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
24239af1bba4SBjoern A. Zeeb 				    RX_NO_DATA_NOTIF, 0) < 2) {
24249af1bba4SBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n",
24259af1bba4SBjoern A. Zeeb 			       phy_data.rate_n_flags);
24269af1bba4SBjoern A. Zeeb 		phy_data.rate_n_flags = iwl_new_rate_from_v1(phy_data.rate_n_flags);
24279af1bba4SBjoern A. Zeeb 		IWL_DEBUG_DROP(mvm, " Rate after conversion to the new format: 0x%x\n",
24289af1bba4SBjoern A. Zeeb 			       phy_data.rate_n_flags);
24299af1bba4SBjoern A. Zeeb 	}
24309af1bba4SBjoern A. Zeeb 
24319af1bba4SBjoern A. Zeeb 	format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
24329af1bba4SBjoern A. Zeeb 
24339af1bba4SBjoern A. Zeeb 	if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
24349af1bba4SBjoern A. Zeeb 				    RX_NO_DATA_NOTIF, 0) >= 3) {
24359af1bba4SBjoern A. Zeeb 		if (unlikely(iwl_rx_packet_payload_len(pkt) <
24369af1bba4SBjoern A. Zeeb 		    sizeof(struct iwl_rx_no_data_ver_3)))
24379af1bba4SBjoern A. Zeeb 		/* invalid len for ver 3 */
24389af1bba4SBjoern A. Zeeb 			return;
24399af1bba4SBjoern A. Zeeb 		phy_data.rx_vec[2] = desc->rx_vec[2];
24409af1bba4SBjoern A. Zeeb 		phy_data.rx_vec[3] = desc->rx_vec[3];
24419af1bba4SBjoern A. Zeeb 	} else {
24429af1bba4SBjoern A. Zeeb 		if (format == RATE_MCS_EHT_MSK)
24439af1bba4SBjoern A. Zeeb 			/* no support for EHT before version 3 API */
24449af1bba4SBjoern A. Zeeb 			return;
24459af1bba4SBjoern A. Zeeb 	}
2446bfcc09ddSBjoern A. Zeeb 
2447bfcc09ddSBjoern A. Zeeb 	/* Dont use dev_alloc_skb(), we'll have enough headroom once
2448bfcc09ddSBjoern A. Zeeb 	 * ieee80211_hdr pulled.
2449bfcc09ddSBjoern A. Zeeb 	 */
2450bfcc09ddSBjoern A. Zeeb 	skb = alloc_skb(128, GFP_ATOMIC);
2451bfcc09ddSBjoern A. Zeeb 	if (!skb) {
2452bfcc09ddSBjoern A. Zeeb 		IWL_ERR(mvm, "alloc_skb failed\n");
2453bfcc09ddSBjoern A. Zeeb 		return;
2454bfcc09ddSBjoern A. Zeeb 	}
2455bfcc09ddSBjoern A. Zeeb 
2456bfcc09ddSBjoern A. Zeeb 	rx_status = IEEE80211_SKB_RXCB(skb);
2457bfcc09ddSBjoern A. Zeeb 
2458bfcc09ddSBjoern A. Zeeb 	/* 0-length PSDU */
2459bfcc09ddSBjoern A. Zeeb 	rx_status->flag |= RX_FLAG_NO_PSDU;
2460bfcc09ddSBjoern A. Zeeb 
2461*a4128aadSBjoern A. Zeeb 	/* mark as failed PLCP on any errors to skip checks in mac80211 */
2462*a4128aadSBjoern A. Zeeb 	if (le32_get_bits(desc->info, RX_NO_DATA_INFO_ERR_MSK) !=
2463*a4128aadSBjoern A. Zeeb 	    RX_NO_DATA_INFO_ERR_NONE)
2464*a4128aadSBjoern A. Zeeb 		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
2465*a4128aadSBjoern A. Zeeb 
2466*a4128aadSBjoern A. Zeeb 	switch (le32_get_bits(desc->info, RX_NO_DATA_INFO_TYPE_MSK)) {
2467bfcc09ddSBjoern A. Zeeb 	case RX_NO_DATA_INFO_TYPE_NDP:
2468bfcc09ddSBjoern A. Zeeb 		rx_status->zero_length_psdu_type =
2469bfcc09ddSBjoern A. Zeeb 			IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
2470bfcc09ddSBjoern A. Zeeb 		break;
2471bfcc09ddSBjoern A. Zeeb 	case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:
24729af1bba4SBjoern A. Zeeb 	case RX_NO_DATA_INFO_TYPE_TB_UNMATCHED:
2473bfcc09ddSBjoern A. Zeeb 		rx_status->zero_length_psdu_type =
2474bfcc09ddSBjoern A. Zeeb 			IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;
2475bfcc09ddSBjoern A. Zeeb 		break;
2476bfcc09ddSBjoern A. Zeeb 	default:
2477bfcc09ddSBjoern A. Zeeb 		rx_status->zero_length_psdu_type =
2478bfcc09ddSBjoern A. Zeeb 			IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;
2479bfcc09ddSBjoern A. Zeeb 		break;
2480bfcc09ddSBjoern A. Zeeb 	}
2481bfcc09ddSBjoern A. Zeeb 
24829af1bba4SBjoern A. Zeeb 	rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
2483bfcc09ddSBjoern A. Zeeb 		NL80211_BAND_2GHZ;
2484bfcc09ddSBjoern A. Zeeb 
24859af1bba4SBjoern A. Zeeb 	iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
2486bfcc09ddSBjoern A. Zeeb 
24879af1bba4SBjoern A. Zeeb 	/* no more radio tap info should be put after this point.
24889af1bba4SBjoern A. Zeeb 	 *
24899af1bba4SBjoern A. Zeeb 	 * We mark it as mac header, for upper layers to know where
24909af1bba4SBjoern A. Zeeb 	 * all radio tap header ends.
2491*a4128aadSBjoern A. Zeeb 	 *
2492*a4128aadSBjoern A. Zeeb 	 * Since data doesn't move data while putting data on skb and that is
2493*a4128aadSBjoern A. Zeeb 	 * the only way we use, data + len is the next place that hdr would be put
2494bfcc09ddSBjoern A. Zeeb 	 */
2495*a4128aadSBjoern A. Zeeb 	skb_set_mac_header(skb, skb->len);
24969af1bba4SBjoern A. Zeeb 
24979af1bba4SBjoern A. Zeeb 	/*
24989af1bba4SBjoern A. Zeeb 	 * Override the nss from the rx_vec since the rate_n_flags has
24999af1bba4SBjoern A. Zeeb 	 * only 2 bits for the nss which gives a max of 4 ss but there
25009af1bba4SBjoern A. Zeeb 	 * may be up to 8 spatial streams.
25019af1bba4SBjoern A. Zeeb 	 */
25029af1bba4SBjoern A. Zeeb 	switch (format) {
25039af1bba4SBjoern A. Zeeb 	case RATE_MCS_VHT_MSK:
2504bfcc09ddSBjoern A. Zeeb 		rx_status->nss =
2505bfcc09ddSBjoern A. Zeeb 			le32_get_bits(desc->rx_vec[0],
2506bfcc09ddSBjoern A. Zeeb 				      RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;
25079af1bba4SBjoern A. Zeeb 		break;
25089af1bba4SBjoern A. Zeeb 	case RATE_MCS_HE_MSK:
2509bfcc09ddSBjoern A. Zeeb 		rx_status->nss =
2510bfcc09ddSBjoern A. Zeeb 			le32_get_bits(desc->rx_vec[0],
2511bfcc09ddSBjoern A. Zeeb 				      RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;
25129af1bba4SBjoern A. Zeeb 		break;
25139af1bba4SBjoern A. Zeeb 	case RATE_MCS_EHT_MSK:
25149af1bba4SBjoern A. Zeeb 		rx_status->nss =
25159af1bba4SBjoern A. Zeeb 			le32_get_bits(desc->rx_vec[2],
25169af1bba4SBjoern A. Zeeb 				      RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1;
2517bfcc09ddSBjoern A. Zeeb 	}
2518bfcc09ddSBjoern A. Zeeb 
25199af1bba4SBjoern A. Zeeb 	rcu_read_lock();
2520bfcc09ddSBjoern A. Zeeb 	ieee80211_rx_napi(mvm->hw, sta, skb, napi);
2521bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
2522bfcc09ddSBjoern A. Zeeb }
2523bfcc09ddSBjoern A. Zeeb 
2524bfcc09ddSBjoern A. Zeeb void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
2525bfcc09ddSBjoern A. Zeeb 			      struct iwl_rx_cmd_buffer *rxb, int queue)
2526bfcc09ddSBjoern A. Zeeb {
2527bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
2528bfcc09ddSBjoern A. Zeeb 	struct iwl_frame_release *release = (void *)pkt->data;
2529bfcc09ddSBjoern A. Zeeb 
2530bfcc09ddSBjoern A. Zeeb 	if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*release)))
2531bfcc09ddSBjoern A. Zeeb 		return;
2532bfcc09ddSBjoern A. Zeeb 
2533bfcc09ddSBjoern A. Zeeb 	iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
2534bfcc09ddSBjoern A. Zeeb 					  le16_to_cpu(release->nssn),
2535*a4128aadSBjoern A. Zeeb 					  queue);
2536bfcc09ddSBjoern A. Zeeb }
2537bfcc09ddSBjoern A. Zeeb 
2538bfcc09ddSBjoern A. Zeeb void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
2539bfcc09ddSBjoern A. Zeeb 				  struct iwl_rx_cmd_buffer *rxb, int queue)
2540bfcc09ddSBjoern A. Zeeb {
2541bfcc09ddSBjoern A. Zeeb 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
2542bfcc09ddSBjoern A. Zeeb 	struct iwl_bar_frame_release *release = (void *)pkt->data;
2543bfcc09ddSBjoern A. Zeeb 	unsigned int baid = le32_get_bits(release->ba_info,
2544bfcc09ddSBjoern A. Zeeb 					  IWL_BAR_FRAME_RELEASE_BAID_MASK);
2545bfcc09ddSBjoern A. Zeeb 	unsigned int nssn = le32_get_bits(release->ba_info,
2546bfcc09ddSBjoern A. Zeeb 					  IWL_BAR_FRAME_RELEASE_NSSN_MASK);
2547bfcc09ddSBjoern A. Zeeb 	unsigned int sta_id = le32_get_bits(release->sta_tid,
2548bfcc09ddSBjoern A. Zeeb 					    IWL_BAR_FRAME_RELEASE_STA_MASK);
2549bfcc09ddSBjoern A. Zeeb 	unsigned int tid = le32_get_bits(release->sta_tid,
2550bfcc09ddSBjoern A. Zeeb 					 IWL_BAR_FRAME_RELEASE_TID_MASK);
2551bfcc09ddSBjoern A. Zeeb 	struct iwl_mvm_baid_data *baid_data;
2552bfcc09ddSBjoern A. Zeeb 
2553bfcc09ddSBjoern A. Zeeb 	if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*release)))
2554bfcc09ddSBjoern A. Zeeb 		return;
2555bfcc09ddSBjoern A. Zeeb 
2556bfcc09ddSBjoern A. Zeeb 	if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
2557bfcc09ddSBjoern A. Zeeb 			 baid >= ARRAY_SIZE(mvm->baid_map)))
2558bfcc09ddSBjoern A. Zeeb 		return;
2559bfcc09ddSBjoern A. Zeeb 
2560bfcc09ddSBjoern A. Zeeb 	rcu_read_lock();
2561bfcc09ddSBjoern A. Zeeb 	baid_data = rcu_dereference(mvm->baid_map[baid]);
2562bfcc09ddSBjoern A. Zeeb 	if (!baid_data) {
2563bfcc09ddSBjoern A. Zeeb 		IWL_DEBUG_RX(mvm,
2564bfcc09ddSBjoern A. Zeeb 			     "Got valid BAID %d but not allocated, invalid BAR release!\n",
2565bfcc09ddSBjoern A. Zeeb 			      baid);
2566bfcc09ddSBjoern A. Zeeb 		goto out;
2567bfcc09ddSBjoern A. Zeeb 	}
2568bfcc09ddSBjoern A. Zeeb 
25699af1bba4SBjoern A. Zeeb 	if (WARN(tid != baid_data->tid || sta_id > IWL_MVM_STATION_COUNT_MAX ||
25709af1bba4SBjoern A. Zeeb 		 !(baid_data->sta_mask & BIT(sta_id)),
25719af1bba4SBjoern A. Zeeb 		 "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",
25729af1bba4SBjoern A. Zeeb 		 baid, baid_data->sta_mask, baid_data->tid, sta_id,
2573bfcc09ddSBjoern A. Zeeb 		 tid))
2574bfcc09ddSBjoern A. Zeeb 		goto out;
2575bfcc09ddSBjoern A. Zeeb 
2576*a4128aadSBjoern A. Zeeb 	IWL_DEBUG_DROP(mvm, "Received a BAR, expect packet loss: nssn %d\n",
2577*a4128aadSBjoern A. Zeeb 		       nssn);
2578*a4128aadSBjoern A. Zeeb 
2579*a4128aadSBjoern A. Zeeb 	iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue);
2580bfcc09ddSBjoern A. Zeeb out:
2581bfcc09ddSBjoern A. Zeeb 	rcu_read_unlock();
2582bfcc09ddSBjoern A. Zeeb }
2583