diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 709 | 
1 files changed, 631 insertions, 78 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 549dbe0be223..6226e4e54a51 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2015-2017 Intel Deutschland GmbH   */ @@ -9,6 +9,7 @@  #include "iwl-trans.h"  #include "mvm.h"  #include "fw-api.h" +#include "time-sync.h"  static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,  				   int queue, struct ieee80211_sta *sta) @@ -105,28 +106,12 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,  	/*  	 * For non monitor interface strip the bytes the RADA might not have -	 * removed. As monitor interface cannot exist with other interfaces -	 * this removal is safe. +	 * removed (it might be disabled, e.g. for mgmt frames). As a monitor +	 * interface cannot exist with other interfaces, this removal is safe +	 * and sufficient, in monitor mode there's no decryption being done.  	 */ -	if (mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) { -		u32 pkt_flags = le32_to_cpu(pkt->len_n_flags); - -		/* -		 * If RADA was not enabled then decryption was not performed so -		 * the MIC cannot be removed. -		 */ -		if (!(pkt_flags & FH_RSCSR_RADA_EN)) { -			if (WARN_ON(crypt_len > mic_crc_len)) -				return -EINVAL; - -			mic_crc_len -= crypt_len; -		} - -		if (WARN_ON(mic_crc_len > len)) -			return -EINVAL; - +	if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))  		len -= mic_crc_len; -	}  	/* If frame is small enough to fit in skb->head, pull it completely.  	 * If not, only pull ieee80211_hdr (including crypto if present, and @@ -171,8 +156,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,  	 * Starting from Bz hardware, it calculates starting directly after  	 * the MAC header, so that matches mac80211's expectation.  	 */ -	if (skb->ip_summed == CHECKSUM_COMPLETE && -	    mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ) { +	if (skb->ip_summed == CHECKSUM_COMPLETE) {  		struct {  			u8 hdr[6];  			__be16 type; @@ -187,7 +171,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,  			      shdr->type != htons(ETH_P_PAE) &&  			      shdr->type != htons(ETH_P_TDLS))))  			skb->ip_summed = CHECKSUM_NONE; -		else +		else if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)  			/* mac80211 assumes full CSUM including SNAP header */  			skb_postpush_rcsum(skb, shdr, sizeof(*shdr));  	} @@ -205,49 +189,69 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,  	return 0;  } +/* put a TLV on the skb and return data pointer + * + * Also pad to 4 the len and zero out all data part + */ +static void * +iwl_mvm_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len) +{ +	struct ieee80211_radiotap_tlv *tlv; + +	tlv = skb_put(skb, sizeof(*tlv)); +	tlv->type = cpu_to_le16(type); +	tlv->len = cpu_to_le16(len); +	return skb_put_zero(skb, ALIGN(len, 4)); +} +  static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,  					    struct sk_buff *skb)  {  	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); -	struct ieee80211_vendor_radiotap *radiotap; -	const int size = sizeof(*radiotap) + sizeof(__le16); +	struct ieee80211_radiotap_vendor_content *radiotap; +	const u16 vendor_data_len = sizeof(mvm->cur_aid);  	if (!mvm->cur_aid)  		return; -	/* ensure alignment */ -	BUILD_BUG_ON((size + 2) % 4); +	radiotap = iwl_mvm_radiotap_put_tlv(skb, +					    IEEE80211_RADIOTAP_VENDOR_NAMESPACE, +					    sizeof(*radiotap) + vendor_data_len); -	radiotap = skb_put(skb, size + 2); -	radiotap->align = 1;  	/* Intel OUI */  	radiotap->oui[0] = 0xf6;  	radiotap->oui[1] = 0x54;  	radiotap->oui[2] = 0x25;  	/* radiotap sniffer config sub-namespace */ -	radiotap->subns = 1; -	radiotap->present = 0x1; -	radiotap->len = size - sizeof(*radiotap); -	radiotap->pad = 2; +	radiotap->oui_subtype = 1; +	radiotap->vendor_type = 0;  	/* fill the data now */  	memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); -	/* and clear the padding */ -	memset(radiotap->data + sizeof(__le16), 0, radiotap->pad); -	rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; +	rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;  }  /* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */  static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,  					    struct napi_struct *napi,  					    struct sk_buff *skb, int queue, -					    struct ieee80211_sta *sta) +					    struct ieee80211_sta *sta, +					    struct ieee80211_link_sta *link_sta)  { -	if (iwl_mvm_check_pn(mvm, skb, queue, sta)) +	if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {  		kfree_skb(skb); -	else -		ieee80211_rx_napi(mvm->hw, sta, skb, napi); +		return; +	} + +	if (sta && sta->valid_links && link_sta) { +		struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + +		rx_status->link_valid = 1; +		rx_status->link_id = link_sta->link_id; +	} + +	ieee80211_rx_napi(mvm->hw, sta, skb, napi);  }  static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, @@ -391,9 +395,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  		if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))  			return -1; -		stats->flag |= RX_FLAG_DECRYPTED; -		if (pkt_flags & FH_RSCSR_RADA_EN) -			stats->flag |= RX_FLAG_MIC_STRIPPED; +		stats->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MIC_STRIPPED;  		*crypt_len = IEEE80211_CCMP_HDR_LEN;  		return 0;  	case IWL_RX_MPDU_STATUS_SEC_TKIP: @@ -443,7 +445,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  		 */  		if (!is_multicast_ether_addr(hdr->addr1) &&  		    !mvm->monitor_on && net_ratelimit()) -			IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status); +			IWL_WARN(mvm, "Unhandled alg: 0x%x\n", status);  	}  	return 0; @@ -620,7 +622,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,  		while ((skb = __skb_dequeue(skb_list))) {  			iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,  							reorder_buf->queue, -							sta); +							sta, NULL /* FIXME */);  			reorder_buf->num_stored--;  		}  	} @@ -685,10 +687,15 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)  	if (expired) {  		struct ieee80211_sta *sta;  		struct iwl_mvm_sta *mvmsta; -		u8 sta_id = baid_data->sta_id; +		u8 sta_id = ffs(baid_data->sta_mask) - 1;  		rcu_read_lock();  		sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]); +		if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { +			rcu_read_unlock(); +			goto out; +		} +  		mvmsta = iwl_mvm_sta_from_mac80211(sta);  		/* SN is set to the last expired frame + 1 */ @@ -710,6 +717,8 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)  			  entries[index].e.reorder_time +  			  1 + RX_REORDER_BUF_TIMEOUT_MQ);  	} + +out:  	spin_unlock(&buf->lock);  } @@ -720,6 +729,7 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,  	struct ieee80211_sta *sta;  	struct iwl_mvm_reorder_buffer *reorder_buf;  	u8 baid = data->baid; +	u32 sta_id;  	if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))  		return; @@ -730,7 +740,9 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,  	if (WARN_ON_ONCE(!ba_data))  		goto out; -	sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]); +	/* pick any STA ID to find the pointer */ +	sta_id = ffs(ba_data->sta_mask) - 1; +	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);  	if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))  		goto out; @@ -757,6 +769,7 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,  	struct ieee80211_sta *sta;  	struct iwl_mvm_reorder_buffer *reorder_buf;  	struct iwl_mvm_baid_data *ba_data; +	u32 sta_id;  	IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",  		     baid, nssn); @@ -774,7 +787,9 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,  		goto out;  	} -	sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]); +	/* pick any STA ID to find the pointer */ +	sta_id = ffs(ba_data->sta_mask) - 1; +	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);  	if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))  		goto out; @@ -915,7 +930,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,  {  	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);  	struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb); -	struct iwl_mvm_sta *mvm_sta;  	struct iwl_mvm_baid_data *baid_data;  	struct iwl_mvm_reorder_buffer *buffer;  	struct sk_buff *tail; @@ -927,6 +941,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,  	u8 sub_frame_idx = desc->amsdu_info &  			   IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;  	struct iwl_mvm_reorder_buf_entry *entries; +	u32 sta_mask;  	int index;  	u16 nssn, sn;  	u8 baid; @@ -949,8 +964,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,  		      "Got valid BAID without a valid station assigned\n"))  		return false; -	mvm_sta = iwl_mvm_sta_from_mac80211(sta); -  	/* not a data packet or a bar */  	if (!ieee80211_is_back_req(hdr->frame_control) &&  	    (!ieee80211_is_data_qos(hdr->frame_control) || @@ -968,10 +981,14 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,  		return false;  	} -	if (WARN(tid != baid_data->tid || mvm_sta->sta_id != baid_data->sta_id, -		 "baid 0x%x is mapped to sta:%d tid:%d, but was received for sta:%d tid:%d\n", -		 baid, baid_data->sta_id, baid_data->tid, mvm_sta->sta_id, -		 tid)) +	rcu_read_lock(); +	sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1); +	rcu_read_unlock(); + +	if (WARN(tid != baid_data->tid || +		 !(sta_mask & baid_data->sta_mask), +		 "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n", +		 baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))  		return false;  	nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK; @@ -1167,8 +1184,11 @@ static void iwl_mvm_flip_address(u8 *addr)  struct iwl_mvm_rx_phy_data {  	enum iwl_rx_phy_info_type info_type; -	__le32 d0, d1, d2, d3; +	__le32 d0, d1, d2, d3, eht_d4, d5;  	__le16 d4; +	bool with_data; +	bool first_subframe; +	__le32 rx_vec[4];  	u32 rate_n_flags;  	u32 gp2_on_air_rise; @@ -1446,6 +1466,528 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,  	}  } +#define LE32_DEC_ENC(value, dec_bits, enc_bits) \ +	le32_encode_bits(le32_get_bits(value, dec_bits), enc_bits) + +#define IWL_MVM_ENC_USIG_VALUE_MASK(usig, in_value, dec_bits, enc_bits) do { \ +	typeof(enc_bits) _enc_bits = enc_bits; \ +	typeof(usig) _usig = usig; \ +	(_usig)->mask |= cpu_to_le32(_enc_bits); \ +	(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \ +} while (0) + +#define __IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \ +	eht->data[(rt_data)] |= \ +		(cpu_to_le32 \ +		 (IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \ +		 LE32_DEC_ENC(data ## fw_data, \ +			      IWL_RX_PHY_DATA ## fw_data ## _EHT_MU_EXT_RU_ALLOC_ ## fw_ru, \ +			      IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru)) + +#define _IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)	\ +	__IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) + +#define IEEE80211_RADIOTAP_RU_DATA_1_1_1	1 +#define IEEE80211_RADIOTAP_RU_DATA_2_1_1	2 +#define IEEE80211_RADIOTAP_RU_DATA_1_1_2	2 +#define IEEE80211_RADIOTAP_RU_DATA_2_1_2	2 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_1	3 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_1	3 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_2	3 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_2	4 + +#define IWL_RX_RU_DATA_A1			2 +#define IWL_RX_RU_DATA_A2			2 +#define IWL_RX_RU_DATA_B1			2 +#define IWL_RX_RU_DATA_B2			3 +#define IWL_RX_RU_DATA_C1			3 +#define IWL_RX_RU_DATA_C2			3 +#define IWL_RX_RU_DATA_D1			4 +#define IWL_RX_RU_DATA_D2			4 + +#define IWL_MVM_ENC_EHT_RU(rt_ru, fw_ru)				\ +	_IWL_MVM_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru,	\ +			    rt_ru,					\ +			    IWL_RX_RU_DATA_ ## fw_ru,			\ +			    fw_ru) + +static void iwl_mvm_decode_eht_ext_mu(struct iwl_mvm *mvm, +				      struct iwl_mvm_rx_phy_data *phy_data, +				      struct ieee80211_rx_status *rx_status, +				      struct ieee80211_radiotap_eht *eht, +				      struct ieee80211_radiotap_eht_usig *usig) +{ +	if (phy_data->with_data) { +		__le32 data1 = phy_data->d1; +		__le32 data2 = phy_data->d2; +		__le32 data3 = phy_data->d3; +		__le32 data4 = phy_data->eht_d4; +		__le32 data5 = phy_data->d5; +		u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK; + +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5, +					    IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5, +					    IWL_RX_PHY_DATA5_EHT_MU_PUNC_CH_CODE, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data4, +					    IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS); +		IWL_MVM_ENC_USIG_VALUE_MASK +			(usig, data1, IWL_RX_PHY_DATA1_EHT_MU_NUM_SIG_SYM_USIGA2, +			 IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS); + +		eht->user_info[0] |= +			cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) | +			LE32_DEC_ENC(data5, IWL_RX_PHY_DATA5_EHT_MU_STA_ID_USR, +				     IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID); + +		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M); +		eht->data[7] |= LE32_DEC_ENC +			(data5, IWL_RX_PHY_DATA5_EHT_MU_NUM_USR_NON_OFDMA, +			 IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS); + +		/* +		 * Hardware labels the content channels/RU allocation values +		 * as follows: +		 *           Content Channel 1		Content Channel 2 +		 *   20 MHz: A1 +		 *   40 MHz: A1				B1 +		 *   80 MHz: A1 C1			B1 D1 +		 *  160 MHz: A1 C1 A2 C2		B1 D1 B2 D2 +		 *  320 MHz: A1 C1 A2 C2 A3 C3 A4 C4	B1 D1 B2 D2 B3 D3 B4 D4 +		 * +		 * However firmware can only give us A1-D2, so the higher +		 * frequencies are missing. +		 */ + +		switch (phy_bw) { +		case RATE_MCS_CHAN_WIDTH_320: +			/* additional values are missing in RX metadata */ +		case RATE_MCS_CHAN_WIDTH_160: +			/* content channel 1 */ +			IWL_MVM_ENC_EHT_RU(1_2_1, A2); +			IWL_MVM_ENC_EHT_RU(1_2_2, C2); +			/* content channel 2 */ +			IWL_MVM_ENC_EHT_RU(2_2_1, B2); +			IWL_MVM_ENC_EHT_RU(2_2_2, D2); +			fallthrough; +		case RATE_MCS_CHAN_WIDTH_80: +			/* content channel 1 */ +			IWL_MVM_ENC_EHT_RU(1_1_2, C1); +			/* content channel 2 */ +			IWL_MVM_ENC_EHT_RU(2_1_2, D1); +			fallthrough; +		case RATE_MCS_CHAN_WIDTH_40: +			/* content channel 2 */ +			IWL_MVM_ENC_EHT_RU(2_1_1, B1); +			fallthrough; +		case RATE_MCS_CHAN_WIDTH_20: +			IWL_MVM_ENC_EHT_RU(1_1_1, A1); +			break; +		} +	} else { +		__le32 usig_a1 = phy_data->rx_vec[0]; +		__le32 usig_a2 = phy_data->rx_vec[1]; + +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1, +					    IWL_RX_USIG_A1_DISREGARD, +					    IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1, +					    IWL_RX_USIG_A1_VALIDATE, +					    IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_PPDU_TYPE, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_PUNC_CHANNEL, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_SIG_MCS, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS); +		IWL_MVM_ENC_USIG_VALUE_MASK +			(usig, usig_a2, IWL_RX_USIG_A2_EHT_SIG_SYM_NUM, +			 IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_CRC_OK, +					    IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC); +	} +} + +static void iwl_mvm_decode_eht_ext_tb(struct iwl_mvm *mvm, +				      struct iwl_mvm_rx_phy_data *phy_data, +				      struct ieee80211_rx_status *rx_status, +				      struct ieee80211_radiotap_eht *eht, +				      struct ieee80211_radiotap_eht_usig *usig) +{ +	if (phy_data->with_data) { +		__le32 data5 = phy_data->d5; + +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5, +					    IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5, +					    IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE1, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1); + +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5, +					    IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE2, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2); +	} else { +		__le32 usig_a1 = phy_data->rx_vec[0]; +		__le32 usig_a2 = phy_data->rx_vec[1]; + +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1, +					    IWL_RX_USIG_A1_DISREGARD, +					    IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_PPDU_TYPE, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD); +		IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2, +					    IWL_RX_USIG_A2_EHT_CRC_OK, +					    IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC); +	} +} + +static void iwl_mvm_decode_eht_ru(struct iwl_mvm *mvm, +				  struct ieee80211_rx_status *rx_status, +				  struct ieee80211_radiotap_eht *eht) +{ +	u32 ru = le32_get_bits(eht->data[8], +			       IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1); +	enum nl80211_eht_ru_alloc nl_ru; + +	/* Using D1.5 Table 9-53a - Encoding of PS160 and RU Allocation subfields +	 * in an EHT variant User Info field +	 */ + +	switch (ru) { +	case 0 ... 36: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_26; +		break; +	case 37 ... 52: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52; +		break; +	case 53 ... 60: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106; +		break; +	case 61 ... 64: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_242; +		break; +	case 65 ... 66: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484; +		break; +	case 67: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996; +		break; +	case 68: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996; +		break; +	case 69: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_4x996; +		break; +	case 70 ... 81: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52P26; +		break; +	case 82 ... 89: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106P26; +		break; +	case 90 ... 93: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484P242; +		break; +	case 94 ... 95: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484; +		break; +	case 96 ... 99: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242; +		break; +	case 100 ... 103: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484; +		break; +	case 104: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996; +		break; +	case 105 ... 106: +		nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484; +		break; +	default: +		return; +	} + +	rx_status->bw = RATE_INFO_BW_EHT_RU; +	rx_status->eht.ru = nl_ru; +} + +static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm, +					struct iwl_mvm_rx_phy_data *phy_data, +					struct ieee80211_rx_status *rx_status, +					struct ieee80211_radiotap_eht *eht, +					struct ieee80211_radiotap_eht_usig *usig) + +{ +	__le32 data0 = phy_data->d0; +	__le32 data1 = phy_data->d1; +	__le32 usig_a1 = phy_data->rx_vec[0]; +	u8 info_type = phy_data->info_type; + +	/* Not in EHT range */ +	if (info_type < IWL_RX_PHY_INFO_TYPE_EHT_MU || +	    info_type > IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT) +		return; + +	usig->common |= cpu_to_le32 +		(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN | +		 IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN); +	if (phy_data->with_data) { +		usig->common |= LE32_DEC_ENC(data0, +					     IWL_RX_PHY_DATA0_EHT_UPLINK, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL); +		usig->common |= LE32_DEC_ENC(data0, +					     IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR); +	} else { +		usig->common |= LE32_DEC_ENC(usig_a1, +					     IWL_RX_USIG_A1_UL_FLAG, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL); +		usig->common |= LE32_DEC_ENC(usig_a1, +					     IWL_RX_USIG_A1_BSS_COLOR, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR); +	} + +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE); +	eht->data[0] |= LE32_DEC_ENC(data0, +				     IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK, +				     IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE); + +	/* All RU allocating size/index is in TB format */ +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT); +	eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160, +				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160); +	eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0, +				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0); +	eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC, +				     IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1); + +	iwl_mvm_decode_eht_ru(mvm, rx_status, eht); + +	/* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set +	 * which is on only in case of monitor mode so no need to check monitor +	 * mode +	 */ +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80); +	eht->data[1] |= +		le32_encode_bits(mvm->monitor_p80, +				 IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80); + +	usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN); +	if (phy_data->with_data) +		usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP); +	else +		usig->common |= LE32_DEC_ENC(usig_a1, IWL_RX_USIG_A1_TXOP_DURATION, +					     IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP); + +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM); +	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_LDPC_EXT_SYM, +				     IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM); + +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM); +	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PRE_FEC_PAD_MASK, +				    IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM); + +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM); +	eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PE_DISAMBIG, +				     IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM); + +	/* TODO: what about IWL_RX_PHY_DATA0_EHT_BW320_SLOT */ + +	if (!le32_get_bits(data0, IWL_RX_PHY_DATA0_EHT_SIGA_CRC_OK)) +		usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC); + +	usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN); +	usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PHY_VER, +				     IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER); + +	/* +	 * TODO: what about TB - IWL_RX_PHY_DATA1_EHT_TB_PILOT_TYPE, +	 *			 IWL_RX_PHY_DATA1_EHT_TB_LOW_SS +	 */ + +	eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF); +	eht->data[0] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM, +				     IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF); + +	if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT || +	    info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB) +		iwl_mvm_decode_eht_ext_tb(mvm, phy_data, rx_status, eht, usig); + +	if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT || +	    info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU) +		iwl_mvm_decode_eht_ext_mu(mvm, phy_data, rx_status, eht, usig); +} + +static void iwl_mvm_rx_eht(struct iwl_mvm *mvm, struct sk_buff *skb, +			   struct iwl_mvm_rx_phy_data *phy_data, +			   int queue) +{ +	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + +	struct ieee80211_radiotap_eht *eht; +	struct ieee80211_radiotap_eht_usig *usig; +	size_t eht_len = sizeof(*eht); + +	u32 rate_n_flags = phy_data->rate_n_flags; +	u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; +	/* EHT and HE have the same valus for LTF */ +	u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN; +	u16 phy_info = phy_data->phy_info; +	u32 bw; + +	/* u32 for 1 user_info */ +	if (phy_data->with_data) +		eht_len += sizeof(u32); + +	eht = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len); + +	usig = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG, +					sizeof(*usig)); +	rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END; +	usig->common |= +		cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN); + +	/* specific handling for 320MHz */ +	bw = FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags); +	if (bw == RATE_MCS_CHAN_WIDTH_320_VAL) +		bw += FIELD_GET(IWL_RX_PHY_DATA0_EHT_BW320_SLOT, +				le32_to_cpu(phy_data->d0)); + +	usig->common |= cpu_to_le32 +		(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW, bw)); + +	/* report the AMPDU-EOF bit on single frames */ +	if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { +		rx_status->flag |= RX_FLAG_AMPDU_DETAILS; +		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; +		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF)) +			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; +	} + +	/* update aggregation data for monitor sake on default queue */ +	if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) && +	    (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) { +		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; +		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF)) +			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; +	} + +	if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) +		iwl_mvm_decode_eht_phy_data(mvm, phy_data, rx_status, eht, usig); + +#define CHECK_TYPE(F)							\ +	BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F !=	\ +		     (RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS)) + +	CHECK_TYPE(SU); +	CHECK_TYPE(EXT_SU); +	CHECK_TYPE(MU); +	CHECK_TYPE(TRIG); + +	switch (FIELD_GET(RATE_MCS_HE_GI_LTF_MSK, rate_n_flags)) { +	case 0: +		if (he_type == RATE_MCS_HE_TYPE_TRIG) { +			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6; +			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; +		} else { +			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8; +			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; +		} +		break; +	case 1: +		rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6; +		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; +		break; +	case 2: +		ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; +		if (he_type == RATE_MCS_HE_TYPE_TRIG) +			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2; +		else +			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8; +		break; +	case 3: +		if (he_type != RATE_MCS_HE_TYPE_TRIG) { +			ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; +			rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2; +		} +		break; +	default: +		/* nothing here */ +		break; +	} + +	if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) { +		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI); +		eht->data[0] |= cpu_to_le32 +			(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF, +				    ltf) | +			 FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI, +				    rx_status->eht.gi)); +	} + + +	if (!phy_data->with_data) { +		eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S | +					  IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S); +		eht->data[7] |= +			le32_encode_bits(le32_get_bits(phy_data->rx_vec[2], +						       RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK), +					 IEEE80211_RADIOTAP_EHT_DATA7_NSS_S); +		if (rate_n_flags & RATE_MCS_BF_MSK) +			eht->data[7] |= +				cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S); +	} else { +		eht->user_info[0] |= +			cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN | +				    IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN | +				    IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O | +				    IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O | +				    IEEE80211_RADIOTAP_EHT_USER_INFO_DATA_FOR_USER); + +		if (rate_n_flags & RATE_MCS_BF_MSK) +			eht->user_info[0] |= +				cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O); + +		if (rate_n_flags & RATE_MCS_LDPC_MSK) +			eht->user_info[0] |= +				cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING); + +		eht->user_info[0] |= cpu_to_le32 +			(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS, +				    FIELD_GET(RATE_VHT_MCS_RATE_CODE_MSK, +					      rate_n_flags)) | +			 FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O, +				    FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags))); +	} +} +  static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,  			  struct iwl_mvm_rx_phy_data *phy_data,  			  int queue) @@ -1497,15 +2039,10 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,  	/* update aggregation data for monitor sake on default queue */  	if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) && -	    (phy_info & IWL_RX_MPDU_PHY_AMPDU)) { -		bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; - -		/* toggle is switched whenever new aggregation starts */ -		if (toggle_bit != mvm->ampdu_toggle) { -			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; -			if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF)) -				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; -		} +	    (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) { +		rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; +		if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF)) +			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;  	}  	if (he_type == RATE_MCS_HE_TYPE_EXT_SU && @@ -1593,6 +2130,10 @@ static void iwl_mvm_decode_lsig(struct sk_buff *skb,  	case IWL_RX_PHY_INFO_TYPE_HE_MU:  	case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:  	case IWL_RX_PHY_INFO_TYPE_HE_TB: +	case IWL_RX_PHY_INFO_TYPE_EHT_MU: +	case IWL_RX_PHY_INFO_TYPE_EHT_TB: +	case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT: +	case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:  		lsig = skb_put(skb, sizeof(*lsig));  		lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);  		lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->d1, @@ -1689,6 +2230,10 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,  	iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,  				    phy_data->energy_a, phy_data->energy_b); +	/* using TLV format and must be after all fixed len fields */ +	if (format == RATE_MCS_EHT_MSK) +		iwl_mvm_rx_eht(mvm, skb, phy_data, queue); +  	if (unlikely(mvm->monitor_on))  		iwl_mvm_add_rtap_sniffer_config(mvm, skb); @@ -1758,6 +2303,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  	u32 len;  	u32 pkt_len = iwl_rx_packet_payload_len(pkt);  	struct ieee80211_sta *sta = NULL; +	struct ieee80211_link_sta *link_sta = NULL;  	struct sk_buff *skb;  	u8 crypt_len = 0;  	size_t desc_size; @@ -1788,6 +2334,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		phy_data.d1 = desc->v3.phy_data1;  		phy_data.d2 = desc->v3.phy_data2;  		phy_data.d3 = desc->v3.phy_data3; +		phy_data.eht_d4 = desc->phy_eht_data4; +		phy_data.d5 = desc->v3.phy_data5;  	} else {  		phy_data.rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);  		phy_data.channel = desc->v1.channel; @@ -1817,6 +2365,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		return;  	} +	phy_data.with_data = true;  	phy_data.phy_info = le16_to_cpu(desc->phy_info);  	phy_data.d4 = desc->phy_data4; @@ -1897,6 +2446,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  			if (mvm->ampdu_ref == 0)  				mvm->ampdu_ref++;  			mvm->ampdu_toggle = toggle_bit; +			phy_data.first_subframe = true;  		}  		rx_status->ampdu_reference = mvm->ampdu_ref;  	} @@ -1910,6 +2460,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  			sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);  			if (IS_ERR(sta))  				sta = NULL; +			link_sta = rcu_dereference(mvm->fw_id_to_link_sta[id]);  		}  	} else if (!is_multicast_ether_addr(hdr->addr2)) {  		/* @@ -1968,7 +2519,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  				RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);  				/* Unblock BCAST / MCAST station */  				iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false); -				cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork); +				cancel_delayed_work(&mvm->cs_tx_unblock_dwork);  			}  		} @@ -2043,9 +2594,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  		goto out;  	} -	if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc)) -		iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, -						sta); +	if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) && +	    likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) && +	    likely(!iwl_mvm_mei_filter_scan(mvm, skb))) +		iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, +						link_sta);  out:  	rcu_read_unlock();  } @@ -2079,6 +2632,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  	phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);  	phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);  	phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK); +	phy_data.with_data = false;  	if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,  				    RX_NO_DATA_NOTIF, 0) < 2) { @@ -2097,6 +2651,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  		    sizeof(struct iwl_rx_no_data_ver_3)))  		/* invalid len for ver 3 */  			return; +		memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec));  	} else {  		if (format == RATE_MCS_EHT_MSK)  			/* no support for EHT before version 3 API */ @@ -2123,7 +2678,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  			IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;  		break;  	case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED: -	case RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED: +	case RX_NO_DATA_INFO_TYPE_TB_UNMATCHED:  		rx_status->zero_length_psdu_type =  			IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;  		break; @@ -2142,11 +2697,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,  	 *  	 * We mark it as mac header, for upper layers to know where  	 * all radio tap header ends. -	 * -	 * Since data doesn't move data while putting data on skb and that is -	 * the only way we use, data + len is the next place that hdr would be put  	 */ -	skb_set_mac_header(skb, skb->len); +	skb_reset_mac_header(skb);  	/*  	 * Override the nss from the rx_vec since the rate_n_flags has @@ -2220,9 +2772,10 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,  		goto out;  	} -	if (WARN(tid != baid_data->tid || sta_id != baid_data->sta_id, -		 "baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\n", -		 baid, baid_data->sta_id, baid_data->tid, sta_id, +	if (WARN(tid != baid_data->tid || sta_id > IWL_MVM_STATION_COUNT_MAX || +		 !(baid_data->sta_mask & BIT(sta_id)), +		 "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n", +		 baid, baid_data->sta_mask, baid_data->tid, sta_id,  		 tid))  		goto out;  |