Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c630b477 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho
Browse files

iwlwifi: mvm: move he RX handling to a separate function



The HE code is bloating the RX handling, and makes it too big.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 621f3f57
Loading
Loading
Loading
Loading
+286 −296
Original line number Diff line number Diff line
@@ -856,69 +856,19 @@ static void iwl_mvm_flip_address(u8 *addr)
	ether_addr_copy(addr, mac_addr);
}

void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			struct iwl_rx_cmd_buffer *rxb, int queue)
static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
			  struct iwl_rx_mpdu_desc *desc,
			  u32 rate_n_flags, u16 phy_info, int queue)
{
	struct ieee80211_rx_status *rx_status;
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
	struct ieee80211_hdr *hdr;
	u32 len = le16_to_cpu(desc->mpdu_len);
	u32 rate_n_flags, gp2_on_air_rise;
	u16 phy_info = le16_to_cpu(desc->phy_info);
	struct ieee80211_sta *sta = NULL;
	struct sk_buff *skb;
	u8 crypt_len = 0, channel, energy_a, energy_b;
	struct ieee80211_radiotap_he *he = NULL;
	struct ieee80211_radiotap_he_mu *he_mu = NULL;
	u32 he_type = 0xffffffff;
	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
	/* this is invalid e.g. because puncture type doesn't allow 0b11 */
#define HE_PHY_DATA_INVAL ((u64)-1)
	u64 he_phy_data = HE_PHY_DATA_INVAL;
	size_t desc_size;

	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
		return;

	if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
		rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
		channel = desc->v3.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
		energy_a = desc->v3.energy_a;
		energy_b = desc->v3.energy_b;
		desc_size = sizeof(*desc);
	} else {
		rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
		channel = desc->v1.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
		energy_a = desc->v1.energy_a;
		energy_b = desc->v1.energy_b;
		desc_size = IWL_RX_DESC_SIZE_V1;
	}

	hdr = (void *)(pkt->data + desc_size);
	/* Dont use dev_alloc_skb(), we'll have enough headroom once
	 * ieee80211_hdr pulled.
	 */
	skb = alloc_skb(128, GFP_ATOMIC);
	if (!skb) {
		IWL_ERR(mvm, "alloc_skb failed\n");
		return;
	}

	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
		/*
		 * If the device inserted padding it means that (it thought)
		 * the 802.11 header wasn't a multiple of 4 bytes long. In
		 * this case, reserve two bytes at the start of the SKB to
		 * align the payload properly in case we end up copying it.
		 */
		skb_reserve(skb, 2);
	}

	rx_status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_radiotap_he *he = NULL;
	struct ieee80211_radiotap_he_mu *he_mu = NULL;
	u32 he_type = 0xffffffff;
	u8 stbc;

	if (rate_n_flags & RATE_MCS_HE_MSK) {
	static const struct ieee80211_radiotap_he known = {
		.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
				     IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |
@@ -935,6 +885,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN),
	};
	unsigned int radiotap_len = 0;
	bool overload = phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD;

	he = skb_put_data(skb, &known, sizeof(known));
	radiotap_len += sizeof(known);
@@ -957,12 +908,298 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		}
	}

		/* temporarily hide the radiotap data */
		__skb_pull(skb, radiotap_len);
	/* temporarily hide the radiotap data */
	__skb_pull(skb, radiotap_len);

	if (overload && he_type == RATE_MCS_HE_TYPE_SU) {
		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
		if (FIELD_GET(IWL_RX_HE_PHY_UPLINK, he_phy_data))
			he->data3 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);

		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 (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF, he_phy_data))
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
		}
	} else if (overload && he_mu && he_phy_data != HE_PHY_DATA_INVAL) {
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIBG_SYM_OR_USER_NUM_MASK,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_DCM,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_MCS_MASK,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
		he_mu->flags2 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_COMPRESSION,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
		he_mu->flags2 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PREAMBLE_PUNC_TYPE_MASK,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
	}

	if (he_phy_data != HE_PHY_DATA_INVAL) {
		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
		he->data3 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK,
						  he_phy_data),
					 IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
	}

	/* update aggregation data for monitor sake on default queue */
	if (!queue && (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 &&
		    he_phy_data != HE_PHY_DATA_INVAL &&
		    (he_type == RATE_MCS_HE_TYPE_MU ||
		     he_type == RATE_MCS_HE_TYPE_SU)) {
			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
			if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
				      he_phy_data))
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
		}
	}

	if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
	    rate_n_flags & RATE_MCS_HE_106T_MSK) {
		rx_status->bw = RATE_INFO_BW_HE_RU;
		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
	}
	if (he_mu) {
		/*
		 * Unfortunately, we have to leave the mac80211 data
		 * incorrect for the case that we receive an HE-MU
		 * transmission and *don't* have the he_mu pointer,
		 * i.e. we don't have the phy data (due to the bits
		 * being used for TSF). This shouldn't happen though
		 * as management frames where we need the TSF/timers
		 * are not be transmitted in HE-MU, I think.
		 */
		u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
		u8 offs = 0;

		rx_status->bw = RATE_INFO_BW_HE_RU;

		switch (ru) {
		case 0 ... 36:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
			offs = ru;
			break;
		case 37 ... 52:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
			offs = ru - 37;
			break;
		case 53 ... 60:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
			offs = ru - 53;
			break;
		case 61 ... 64:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
			offs = ru - 61;
			break;
		case 65 ... 66:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
			offs = ru - 65;
			break;
		case 67:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
			break;
		case 68:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
			break;
		}
		he->data2 |=
			le16_encode_bits(offs,
					 IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
		he->data2 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN);
		if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
			he->data2 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
	} else if (he) {
		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
	}

	stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS;
	rx_status->nss =
		((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
					RATE_VHT_MCS_NSS_POS) + 1;
	rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
	rx_status->encoding = RX_ENC_HE;
	rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
	if (rate_n_flags & RATE_MCS_BF_MSK)
		rx_status->enc_flags |= RX_ENC_FLAG_BF;

	rx_status->he_dcm =
		!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);

#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);

	he->data1 |= cpu_to_le16(he_type >> RATE_MCS_HE_TYPE_POS);

	if (rate_n_flags & RATE_MCS_BF_POS)
		he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);

	switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>
		RATE_MCS_HE_GI_LTF_POS) {
	case 0:
		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
		break;
	case 1:
		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
		break;
	case 2:
		rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
		break;
	case 3:
		if (rate_n_flags & RATE_MCS_SGI_MSK)
			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
		else
			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
		break;
	}

	switch (he_type) {
	case RATE_MCS_HE_TYPE_SU: {
		u16 val;

		/* LTF syms correspond to streams */
		he->data2 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
		switch (rx_status->nss) {
		case 1:
			val = 0;
			break;
		case 2:
			val = 1;
			break;
		case 3:
		case 4:
			val = 2;
			break;
		case 5:
		case 6:
			val = 3;
			break;
		case 7:
		case 8:
			val = 4;
			break;
		default:
			WARN_ONCE(1, "invalid nss: %d\n",
				  rx_status->nss);
			val = 0;
		}
		he->data5 |=
			le16_encode_bits(val,
					 IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
		}
		break;
	case RATE_MCS_HE_TYPE_MU: {
		u16 val;

		if (he_phy_data == HE_PHY_DATA_INVAL)
			break;

		val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
				he_phy_data);

		he->data2 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
		he->data5 |=
			cpu_to_le16(FIELD_PREP(
				IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS,
				val));
		}
		break;
	case RATE_MCS_HE_TYPE_EXT_SU:
	case RATE_MCS_HE_TYPE_TRIG:
		/* not supported */
		break;
	}
}

void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			struct iwl_rx_cmd_buffer *rxb, int queue)
{
	struct ieee80211_rx_status *rx_status;
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
	struct ieee80211_hdr *hdr;
	u32 len = le16_to_cpu(desc->mpdu_len);
	u32 rate_n_flags, gp2_on_air_rise;
	u16 phy_info = le16_to_cpu(desc->phy_info);
	struct ieee80211_sta *sta = NULL;
	struct sk_buff *skb;
	u8 crypt_len = 0, channel, energy_a, energy_b;
	size_t desc_size;

	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
		return;

	if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
		rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
		channel = desc->v3.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
		energy_a = desc->v3.energy_a;
		energy_b = desc->v3.energy_b;
		desc_size = sizeof(*desc);
	} else {
		rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
		channel = desc->v1.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
		energy_a = desc->v1.energy_a;
		energy_b = desc->v1.energy_b;
		desc_size = IWL_RX_DESC_SIZE_V1;
	}

	hdr = (void *)(pkt->data + desc_size);
	/* Dont use dev_alloc_skb(), we'll have enough headroom once
	 * ieee80211_hdr pulled.
	 */
	skb = alloc_skb(128, GFP_ATOMIC);
	if (!skb) {
		IWL_ERR(mvm, "alloc_skb failed\n");
		return;
	}

	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
		/*
		 * If the device inserted padding it means that (it thought)
		 * the 802.11 header wasn't a multiple of 4 bytes long. In
		 * this case, reserve two bytes at the start of the SKB to
		 * align the payload properly in case we end up copying it.
		 */
		skb_reserve(skb, 2);
	}

	rx_status = IEEE80211_SKB_RXCB(skb);

	if (rate_n_flags & RATE_MCS_HE_MSK)
		iwl_mvm_rx_he(mvm, skb, desc, rate_n_flags, phy_info, queue);

	rx_status = IEEE80211_SKB_RXCB(skb);

	if (iwl_mvm_rx_crypto(mvm, hdr, rx_status, phy_info, desc,
			      le32_to_cpu(pkt->len_n_flags), queue,
			      &crypt_len)) {
@@ -995,65 +1232,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		rx_status->mactime = tsf_on_air_rise;
		/* TSF as indicated by the firmware is at INA time */
		rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
	} else if (he_type == RATE_MCS_HE_TYPE_SU) {
		u64 he_phy_data;

		if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
			he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
		else
			he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
		if (FIELD_GET(IWL_RX_HE_PHY_UPLINK,
			      he_phy_data))
			he->data3 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);

		if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
			rx_status->ampdu_reference = mvm->ampdu_ref;
			mvm->ampdu_ref++;

			rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
			if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
				      he_phy_data))
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
		}
	} else if (he_mu && he_phy_data != HE_PHY_DATA_INVAL) {
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIBG_SYM_OR_USER_NUM_MASK,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_DCM,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
		he_mu->flags1 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_MCS_MASK,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
		he_mu->flags2 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_COMPRESSION,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
		he_mu->flags2 |=
			le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PREAMBLE_PUNC_TYPE_MASK,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
	}

	if (he_phy_data != HE_PHY_DATA_INVAL &&
	    (he_type == RATE_MCS_HE_TYPE_SU ||
	     he_type == RATE_MCS_HE_TYPE_MU)) {
		u8 bss_color = FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK,
					 he_phy_data);

		if (bss_color) {
			he->data1 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
			he->data3 |= cpu_to_le16(bss_color);
		}
	}

	rx_status->device_timestamp = gp2_on_air_rise;
@@ -1080,16 +1258,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		if (toggle_bit != mvm->ampdu_toggle) {
			mvm->ampdu_ref++;
			mvm->ampdu_toggle = toggle_bit;

			if (he_phy_data != HE_PHY_DATA_INVAL &&
			    (he_type == RATE_MCS_HE_TYPE_MU ||
			     he_type == RATE_MCS_HE_TYPE_SU)) {
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
				if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
					      he_phy_data))
					rx_status->flag |=
						RX_FLAG_AMPDU_EOF_BIT;
			}
		}
	}

@@ -1212,70 +1380,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		break;
	}

	if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
	    rate_n_flags & RATE_MCS_HE_106T_MSK) {
		rx_status->bw = RATE_INFO_BW_HE_RU;
		rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
	}

	if (rate_n_flags & RATE_MCS_HE_MSK &&
	    phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD &&
	    he_type == RATE_MCS_HE_TYPE_MU) {
		/*
		 * Unfortunately, we have to leave the mac80211 data
		 * incorrect for the case that we receive an HE-MU
		 * transmission and *don't* have the he_mu pointer,
		 * i.e. we don't have the phy data (due to the bits
		 * being used for TSF). This shouldn't happen though
		 * as management frames where we need the TSF/timers
		 * are not be transmitted in HE-MU, I think.
		 */
		u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
		u8 offs = 0;

		rx_status->bw = RATE_INFO_BW_HE_RU;

		switch (ru) {
		case 0 ... 36:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
			offs = ru;
			break;
		case 37 ... 52:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
			offs = ru - 37;
			break;
		case 53 ... 60:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
			offs = ru - 53;
			break;
		case 61 ... 64:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
			offs = ru - 61;
			break;
		case 65 ... 66:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
			offs = ru - 65;
			break;
		case 67:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
			break;
		case 68:
			rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
			break;
		}
		he->data2 |=
			le16_encode_bits(offs,
					 IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
		he->data2 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN);
		if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
			he->data2 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
	} else if (he) {
		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
	}

	if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
	    rate_n_flags & RATE_MCS_SGI_MSK)
		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
@@ -1300,120 +1404,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
		if (rate_n_flags & RATE_MCS_BF_MSK)
			rx_status->enc_flags |= RX_ENC_FLAG_BF;
	} else if (he) {
		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
				RATE_MCS_STBC_POS;
		rx_status->nss =
			((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
						RATE_VHT_MCS_NSS_POS) + 1;
		rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
		rx_status->encoding = RX_ENC_HE;
		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
		if (rate_n_flags & RATE_MCS_BF_MSK)
			rx_status->enc_flags |= RX_ENC_FLAG_BF;

		rx_status->he_dcm =
			!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);

#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);

		he->data1 |= cpu_to_le16(he_type >> RATE_MCS_HE_TYPE_POS);

		if (rate_n_flags & RATE_MCS_BF_POS)
			he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);

		switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>
			RATE_MCS_HE_GI_LTF_POS) {
		case 0:
			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
			break;
		case 1:
			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
			break;
		case 2:
			rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
			break;
		case 3:
			if (rate_n_flags & RATE_MCS_SGI_MSK)
				rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
			else
				rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
			break;
		}

		switch (he_type) {
		case RATE_MCS_HE_TYPE_SU: {
			u16 val;

			/* LTF syms correspond to streams */
			he->data2 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
			switch (rx_status->nss) {
			case 1:
				val = 0;
				break;
			case 2:
				val = 1;
				break;
			case 3:
			case 4:
				val = 2;
				break;
			case 5:
			case 6:
				val = 3;
				break;
			case 7:
			case 8:
				val = 4;
				break;
			default:
				WARN_ONCE(1, "invalid nss: %d\n",
					  rx_status->nss);
				val = 0;
			}
			he->data5 |=
				le16_encode_bits(val,
						 IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
			}
			break;
		case RATE_MCS_HE_TYPE_MU: {
			u16 val;
			u64 he_phy_data;

			if (mvm->trans->cfg->device_family >=
			    IWL_DEVICE_FAMILY_22560)
				he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
			else
				he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

			if (he_phy_data == HE_PHY_DATA_INVAL)
				break;

			val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
					he_phy_data);

			he->data2 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
			he->data5 |=
				cpu_to_le16(FIELD_PREP(
					IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS,
					val));
			}
			break;
		case RATE_MCS_HE_TYPE_EXT_SU:
		case RATE_MCS_HE_TYPE_TRIG:
			/* not supported yet */
			break;
		}
	} else {
	} else if (!(rate_n_flags & RATE_MCS_HE_MSK)) {
		int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
							       rx_status->band);

@@ -1424,7 +1415,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			goto out;
		}
		rx_status->rate_idx = rate;

	}

	/* management stuff on default queue */