Path: blob/main/sys/contrib/dev/iwlwifi/mvm/rxmq.c
48287 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/*2* Copyright (C) 2012-2014, 2018-2025 Intel Corporation3* Copyright (C) 2013-2015 Intel Mobile Communications GmbH4* Copyright (C) 2015-2017 Intel Deutschland GmbH5*/6#include <linux/etherdevice.h>7#include <linux/skbuff.h>8#if defined(__FreeBSD__)9#include <net/ieee80211_radiotap.h>10#endif11#include "iwl-trans.h"12#include "mvm.h"13#include "fw-api.h"14#include "time-sync.h"1516static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,17int queue, struct ieee80211_sta *sta)18{19struct iwl_mvm_sta *mvmsta;20struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);21struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);22struct iwl_mvm_key_pn *ptk_pn;23int res;24u8 tid, keyidx;25u8 pn[IEEE80211_CCMP_PN_LEN];26u8 *extiv;2728/* do PN checking */2930/* multicast and non-data only arrives on default queue */31if (!ieee80211_is_data(hdr->frame_control) ||32is_multicast_ether_addr(hdr->addr1))33return 0;3435/* do not check PN for open AP */36if (!(stats->flag & RX_FLAG_DECRYPTED))37return 0;3839/*40* avoid checking for default queue - we don't want to replicate41* all the logic that's necessary for checking the PN on fragmented42* frames, leave that to mac8021143*/44if (queue == 0)45return 0;4647/* if we are here - this for sure is either CCMP or GCMP */48if (IS_ERR_OR_NULL(sta)) {49IWL_DEBUG_DROP(mvm,50"expected hw-decrypted unicast frame for station\n");51return -1;52}5354mvmsta = iwl_mvm_sta_from_mac80211(sta);5556extiv = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);57keyidx = extiv[3] >> 6;5859ptk_pn = rcu_dereference(mvmsta->ptk_pn[keyidx]);60if (!ptk_pn)61return -1;6263if (ieee80211_is_data_qos(hdr->frame_control))64tid = ieee80211_get_tid(hdr);65else66tid = 0;6768/* we don't use HCCA/802.11 QoS TSPECs, so drop such frames */69if (tid >= IWL_MAX_TID_COUNT)70return -1;7172/* load pn */73pn[0] = extiv[7];74pn[1] = extiv[6];75pn[2] = extiv[5];76pn[3] = extiv[4];77pn[4] = extiv[1];78pn[5] = extiv[0];7980res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);81if (res < 0)82return -1;83if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))84return -1;8586memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);87stats->flag |= RX_FLAG_PN_VALIDATED;8889return 0;90}9192/* iwl_mvm_create_skb Adds the rxb to a new skb */93static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,94struct ieee80211_hdr *hdr, u16 len, u8 crypt_len,95struct iwl_rx_cmd_buffer *rxb)96{97struct iwl_rx_packet *pkt = rxb_addr(rxb);98struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;99unsigned int headlen, fraglen, pad_len = 0;100unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);101u8 mic_crc_len = u8_get_bits(desc->mac_flags1,102IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1;103104if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {105len -= 2;106pad_len = 2;107}108109/*110* For non monitor interface strip the bytes the RADA might not have111* removed (it might be disabled, e.g. for mgmt frames). As a monitor112* interface cannot exist with other interfaces, this removal is safe113* and sufficient, in monitor mode there's no decryption being done.114*/115if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))116len -= mic_crc_len;117118/* If frame is small enough to fit in skb->head, pull it completely.119* If not, only pull ieee80211_hdr (including crypto if present, and120* an additional 8 bytes for SNAP/ethertype, see below) so that121* splice() or TCP coalesce are more efficient.122*123* Since, in addition, ieee80211_data_to_8023() always pull in at124* least 8 bytes (possibly more for mesh) we can do the same here125* to save the cost of doing it later. That still doesn't pull in126* the actual IP header since the typical case has a SNAP header.127* If the latter changes (there are efforts in the standards group128* to do so) we should revisit this and ieee80211_data_to_8023().129*/130headlen = (len <= skb_tailroom(skb)) ? len :131hdrlen + crypt_len + 8;132133/* The firmware may align the packet to DWORD.134* The padding is inserted after the IV.135* After copying the header + IV skip the padding if136* present before copying packet data.137*/138hdrlen += crypt_len;139140if (unlikely(headlen < hdrlen))141return -EINVAL;142143/* Since data doesn't move data while putting data on skb and that is144* the only way we use, data + len is the next place that hdr would be put145*/146skb_set_mac_header(skb, skb->len);147skb_put_data(skb, hdr, hdrlen);148skb_put_data(skb, (u8 *)hdr + hdrlen + pad_len, headlen - hdrlen);149150/*151* If we did CHECKSUM_COMPLETE, the hardware only does it right for152* certain cases and starts the checksum after the SNAP. Check if153* this is the case - it's easier to just bail out to CHECKSUM_NONE154* in the cases the hardware didn't handle, since it's rare to see155* such packets, even though the hardware did calculate the checksum156* in this case, just starting after the MAC header instead.157*158* Starting from Bz hardware, it calculates starting directly after159* the MAC header, so that matches mac80211's expectation.160*/161if (skb->ip_summed == CHECKSUM_COMPLETE) {162struct {163u8 hdr[6];164__be16 type;165} __packed *shdr = (void *)((u8 *)hdr + hdrlen + pad_len);166167if (unlikely(headlen - hdrlen < sizeof(*shdr) ||168!ether_addr_equal(shdr->hdr, rfc1042_header) ||169(shdr->type != htons(ETH_P_IP) &&170shdr->type != htons(ETH_P_ARP) &&171shdr->type != htons(ETH_P_IPV6) &&172shdr->type != htons(ETH_P_8021Q) &&173shdr->type != htons(ETH_P_PAE) &&174shdr->type != htons(ETH_P_TDLS))))175skb->ip_summed = CHECKSUM_NONE;176else if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)177/* mac80211 assumes full CSUM including SNAP header */178skb_postpush_rcsum(skb, shdr, sizeof(*shdr));179}180181fraglen = len - headlen;182183if (fraglen) {184int offset = (u8 *)hdr + headlen + pad_len -185(u8 *)rxb_addr(rxb) + rxb_offset(rxb);186187skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,188fraglen, rxb->truesize);189}190191return 0;192}193194/* put a TLV on the skb and return data pointer195*196* Also pad to 4 the len and zero out all data part197*/198static void *199iwl_mvm_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)200{201struct ieee80211_radiotap_tlv *tlv;202203tlv = skb_put(skb, sizeof(*tlv));204tlv->type = cpu_to_le16(type);205tlv->len = cpu_to_le16(len);206return skb_put_zero(skb, ALIGN(len, 4));207}208209static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,210struct sk_buff *skb)211{212struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);213struct ieee80211_radiotap_vendor_content *radiotap;214const u16 vendor_data_len = sizeof(mvm->cur_aid);215216if (!mvm->cur_aid)217return;218219radiotap = iwl_mvm_radiotap_put_tlv(skb,220IEEE80211_RADIOTAP_VENDOR_NAMESPACE,221sizeof(*radiotap) + vendor_data_len);222223/* Intel OUI */224radiotap->oui[0] = 0xf6;225radiotap->oui[1] = 0x54;226radiotap->oui[2] = 0x25;227/* radiotap sniffer config sub-namespace */228radiotap->oui_subtype = 1;229radiotap->vendor_type = 0;230231/* fill the data now */232memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));233234rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;235}236237/* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */238static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,239struct napi_struct *napi,240struct sk_buff *skb, int queue,241struct ieee80211_sta *sta)242{243if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {244kfree_skb(skb);245return;246}247248ieee80211_rx_napi(mvm->hw, sta, skb, napi);249}250251static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm,252struct iwl_rx_mpdu_desc *desc,253struct ieee80211_hdr *hdr,254struct ieee80211_rx_status *rx_status)255{256struct iwl_mvm_vif *mvm_vif;257struct ieee80211_vif *vif;258u32 id;259260if (unlikely(!hdr || !desc))261return false;262263if (likely(!ieee80211_is_beacon(hdr->frame_control)))264return false;265266/* for the link conf lookup */267guard(rcu)();268269/* MAC or link ID depending on FW, but driver has them equal */270id = u8_get_bits(desc->mac_phy_band,271IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK);272273/* >= means AUX MAC/link ID, no energy correction needed then */274if (id >= ARRAY_SIZE(mvm->vif_id_to_mac))275return false;276277vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);278if (!vif)279return false;280281mvm_vif = iwl_mvm_vif_from_mac80211(vif);282283/*284* If we know the MAC by MAC or link ID then the frame was285* received for the link, so by filtering it means it was286* from the AP the link is connected to.287*/288289/* skip also in case we don't have it (yet) */290if (!mvm_vif->deflink.average_beacon_energy)291return false;292293IWL_DEBUG_STATS(mvm, "energy override by average %d\n",294mvm_vif->deflink.average_beacon_energy);295rx_status->signal = -mvm_vif->deflink.average_beacon_energy;296return true;297}298299static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,300struct iwl_rx_mpdu_desc *desc,301struct ieee80211_hdr *hdr,302struct ieee80211_rx_status *rx_status,303u32 rate_n_flags, int energy_a,304int energy_b)305{306int max_energy;307308energy_a = energy_a ? -energy_a : S8_MIN;309energy_b = energy_b ? -energy_b : S8_MIN;310max_energy = max(energy_a, energy_b);311312IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n",313energy_a, energy_b, max_energy);314315if (iwl_mvm_used_average_energy(mvm, desc, hdr, rx_status))316return;317318rx_status->signal = max_energy;319rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK);320rx_status->chain_signal[0] = energy_a;321rx_status->chain_signal[1] = energy_b;322}323324static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,325struct ieee80211_hdr *hdr,326struct iwl_rx_mpdu_desc *desc,327u32 status,328struct ieee80211_rx_status *stats)329{330struct wireless_dev *wdev;331struct iwl_mvm_sta *mvmsta;332struct iwl_mvm_vif *mvmvif;333u8 keyid;334struct ieee80211_key_conf *key;335u32 len = le16_to_cpu(desc->mpdu_len);336const u8 *frame = (void *)hdr;337338if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE)339return 0;340341/*342* For non-beacon, we don't really care. But beacons may343* be filtered out, and we thus need the firmware's replay344* detection, otherwise beacons the firmware previously345* filtered could be replayed, or something like that, and346* it can filter a lot - though usually only if nothing has347* changed.348*/349if (!ieee80211_is_beacon(hdr->frame_control))350return 0;351352if (!sta)353return -1;354355mvmsta = iwl_mvm_sta_from_mac80211(sta);356mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);357358/* key mismatch - will also report !MIC_OK but we shouldn't count it */359if (!(status & IWL_RX_MPDU_STATUS_KEY_VALID))360goto report;361362/* good cases */363if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&364!(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) {365stats->flag |= RX_FLAG_DECRYPTED;366return 0;367}368369/*370* both keys will have the same cipher and MIC length, use371* whichever one is available372*/373key = rcu_dereference(mvmvif->bcn_prot.keys[0]);374if (!key) {375key = rcu_dereference(mvmvif->bcn_prot.keys[1]);376if (!key)377goto report;378}379380if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)381goto report;382383/* get the real key ID */384keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];385/* and if that's the other key, look it up */386if (keyid != key->keyidx) {387/*388* shouldn't happen since firmware checked, but be safe389* in case the MIC length is wrong too, for example390*/391if (keyid != 6 && keyid != 7)392return -1;393key = rcu_dereference(mvmvif->bcn_prot.keys[keyid - 6]);394if (!key)395goto report;396}397398/* Report status to mac80211 */399if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))400ieee80211_key_mic_failure(key);401else if (status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)402ieee80211_key_replay(key);403report:404wdev = ieee80211_vif_to_wdev(mvmsta->vif);405if (wdev->netdev)406cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr, len);407408return -1;409}410411static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,412struct ieee80211_hdr *hdr,413struct ieee80211_rx_status *stats, u16 phy_info,414struct iwl_rx_mpdu_desc *desc,415u32 pkt_flags, int queue, u8 *crypt_len)416{417u32 status = le32_to_cpu(desc->status);418419/*420* Drop UNKNOWN frames in aggregation, unless in monitor mode421* (where we don't have the keys).422* We limit this to aggregation because in TKIP this is a valid423* scenario, since we may not have the (correct) TTAK (phase 1424* key) in the firmware.425*/426if (phy_info & IWL_RX_MPDU_PHY_AMPDU &&427(status & IWL_RX_MPDU_STATUS_SEC_MASK) ==428IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on) {429IWL_DEBUG_DROP(mvm, "Dropping packets, bad enc status\n");430return -1;431}432433if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&434!ieee80211_has_protected(hdr->frame_control)))435return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats);436437if (!ieee80211_has_protected(hdr->frame_control) ||438(status & IWL_RX_MPDU_STATUS_SEC_MASK) ==439IWL_RX_MPDU_STATUS_SEC_NONE)440return 0;441442/* TODO: handle packets encrypted with unknown alg */443#if defined(__FreeBSD__)444/* XXX-BZ do similar to rx.c for now as these are plenty. */445if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) ==446IWL_RX_MPDU_STATUS_SEC_ENC_ERR)447return (0);448#endif449450switch (status & IWL_RX_MPDU_STATUS_SEC_MASK) {451case IWL_RX_MPDU_STATUS_SEC_CCM:452case IWL_RX_MPDU_STATUS_SEC_GCM:453BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != IEEE80211_GCMP_PN_LEN);454/* alg is CCM: check MIC only */455if (!(status & IWL_RX_MPDU_STATUS_MIC_OK)) {456IWL_DEBUG_DROP(mvm,457"Dropping packet, bad MIC (CCM/GCM)\n");458return -1;459}460461stats->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MIC_STRIPPED;462*crypt_len = IEEE80211_CCMP_HDR_LEN;463return 0;464case IWL_RX_MPDU_STATUS_SEC_TKIP:465/* Don't drop the frame and decrypt it in SW */466if (!fw_has_api(&mvm->fw->ucode_capa,467IWL_UCODE_TLV_API_DEPRECATE_TTAK) &&468!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))469return 0;470471if (mvm->trans->mac_cfg->gen2 &&472!(status & RX_MPDU_RES_STATUS_MIC_OK))473stats->flag |= RX_FLAG_MMIC_ERROR;474475*crypt_len = IEEE80211_TKIP_IV_LEN;476fallthrough;477case IWL_RX_MPDU_STATUS_SEC_WEP:478if (!(status & IWL_RX_MPDU_STATUS_ICV_OK))479return -1;480481stats->flag |= RX_FLAG_DECRYPTED;482if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) ==483IWL_RX_MPDU_STATUS_SEC_WEP)484*crypt_len = IEEE80211_WEP_IV_LEN;485486if (pkt_flags & FH_RSCSR_RADA_EN) {487stats->flag |= RX_FLAG_ICV_STRIPPED;488if (mvm->trans->mac_cfg->gen2)489stats->flag |= RX_FLAG_MMIC_STRIPPED;490}491492return 0;493case IWL_RX_MPDU_STATUS_SEC_EXT_ENC:494if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))495return -1;496stats->flag |= RX_FLAG_DECRYPTED;497return 0;498case RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC:499break;500default:501/*502* Sometimes we can get frames that were not decrypted503* because the firmware didn't have the keys yet. This can504* happen after connection where we can get multicast frames505* before the GTK is installed.506* Silently drop those frames.507* Also drop un-decrypted frames in monitor mode.508*/509if (!is_multicast_ether_addr(hdr->addr1) &&510!mvm->monitor_on && net_ratelimit())511#if defined(__linux__)512IWL_WARN(mvm, "Unhandled alg: 0x%x\n", status);513#elif defined(__FreeBSD__)514IWL_WARN(mvm, "%s: Unhandled alg: 0x%x\n", __func__, status);515#endif516}517518return 0;519}520521static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,522struct ieee80211_sta *sta,523struct sk_buff *skb,524struct iwl_rx_packet *pkt)525{526struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;527528if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {529if (pkt->len_n_flags & cpu_to_le32(FH_RSCSR_RPA_EN)) {530u16 hwsum = be16_to_cpu(desc->v3.raw_xsum);531532skb->ip_summed = CHECKSUM_COMPLETE;533skb->csum = csum_unfold(~(__force __sum16)hwsum);534}535} else {536struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);537struct iwl_mvm_vif *mvmvif;538u16 flags = le16_to_cpu(desc->l3l4_flags);539u8 l3_prot = (u8)((flags & IWL_RX_L3L4_L3_PROTO_MASK) >>540IWL_RX_L3_PROTO_POS);541542mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);543544if (mvmvif->features & NETIF_F_RXCSUM &&545flags & IWL_RX_L3L4_TCP_UDP_CSUM_OK &&546(flags & IWL_RX_L3L4_IP_HDR_CSUM_OK ||547l3_prot == IWL_RX_L3_TYPE_IPV6 ||548l3_prot == IWL_RX_L3_TYPE_IPV6_FRAG))549skb->ip_summed = CHECKSUM_UNNECESSARY;550}551}552553/*554* returns true if a packet is a duplicate or invalid tid and should be dropped.555* Updates AMSDU PN tracking info556*/557static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,558struct ieee80211_rx_status *rx_status,559struct ieee80211_hdr *hdr,560struct iwl_rx_mpdu_desc *desc)561{562struct iwl_mvm_sta *mvm_sta;563struct iwl_mvm_rxq_dup_data *dup_data;564u8 tid, sub_frame_idx;565566if (WARN_ON(IS_ERR_OR_NULL(sta)))567return false;568569mvm_sta = iwl_mvm_sta_from_mac80211(sta);570571if (WARN_ON_ONCE(!mvm_sta->dup_data))572return false;573574dup_data = &mvm_sta->dup_data[queue];575576/*577* Drop duplicate 802.11 retransmissions578* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")579*/580if (ieee80211_is_ctl(hdr->frame_control) ||581ieee80211_is_any_nullfunc(hdr->frame_control) ||582is_multicast_ether_addr(hdr->addr1))583return false;584585if (ieee80211_is_data_qos(hdr->frame_control)) {586/* frame has qos control */587tid = ieee80211_get_tid(hdr);588if (tid >= IWL_MAX_TID_COUNT)589return true;590} else {591tid = IWL_MAX_TID_COUNT;592}593594/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */595sub_frame_idx = desc->amsdu_info &596IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;597598if (unlikely(ieee80211_has_retry(hdr->frame_control) &&599dup_data->last_seq[tid] == hdr->seq_ctrl &&600dup_data->last_sub_frame[tid] >= sub_frame_idx))601return true;602603/* Allow same PN as the first subframe for following sub frames */604if (dup_data->last_seq[tid] == hdr->seq_ctrl &&605sub_frame_idx > dup_data->last_sub_frame[tid] &&606desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU)607rx_status->flag |= RX_FLAG_ALLOW_SAME_PN;608609dup_data->last_seq[tid] = hdr->seq_ctrl;610dup_data->last_sub_frame[tid] = sub_frame_idx;611612rx_status->flag |= RX_FLAG_DUP_VALIDATED;613614return false;615}616617static void iwl_mvm_release_frames(struct iwl_mvm *mvm,618struct ieee80211_sta *sta,619struct napi_struct *napi,620struct iwl_mvm_baid_data *baid_data,621struct iwl_mvm_reorder_buffer *reorder_buf,622u16 nssn)623{624struct iwl_mvm_reorder_buf_entry *entries =625&baid_data->entries[reorder_buf->queue *626baid_data->entries_per_queue];627u16 ssn = reorder_buf->head_sn;628629lockdep_assert_held(&reorder_buf->lock);630631while (ieee80211_sn_less(ssn, nssn)) {632int index = ssn % baid_data->buf_size;633struct sk_buff_head *skb_list = &entries[index].frames;634struct sk_buff *skb;635636ssn = ieee80211_sn_inc(ssn);637638/*639* Empty the list. Will have more than one frame for A-MSDU.640* Empty list is valid as well since nssn indicates frames were641* received.642*/643while ((skb = __skb_dequeue(skb_list))) {644iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,645reorder_buf->queue,646sta);647reorder_buf->num_stored--;648}649}650reorder_buf->head_sn = nssn;651}652653static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,654struct iwl_mvm_delba_data *data)655{656struct iwl_mvm_baid_data *ba_data;657struct ieee80211_sta *sta;658struct iwl_mvm_reorder_buffer *reorder_buf;659u8 baid = data->baid;660u32 sta_id;661662if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))663return;664665rcu_read_lock();666667ba_data = rcu_dereference(mvm->baid_map[baid]);668if (WARN_ON_ONCE(!ba_data))669goto out;670671/* pick any STA ID to find the pointer */672sta_id = ffs(ba_data->sta_mask) - 1;673sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);674if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))675goto out;676677reorder_buf = &ba_data->reorder_buf[queue];678679/* release all frames that are in the reorder buffer to the stack */680spin_lock_bh(&reorder_buf->lock);681iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,682ieee80211_sn_add(reorder_buf->head_sn,683ba_data->buf_size));684spin_unlock_bh(&reorder_buf->lock);685686out:687rcu_read_unlock();688}689690static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,691struct napi_struct *napi,692u8 baid, u16 nssn, int queue)693{694struct ieee80211_sta *sta;695struct iwl_mvm_reorder_buffer *reorder_buf;696struct iwl_mvm_baid_data *ba_data;697u32 sta_id;698699IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",700baid, nssn);701702if (IWL_FW_CHECK(mvm,703baid == IWL_RX_REORDER_DATA_INVALID_BAID ||704baid >= ARRAY_SIZE(mvm->baid_map),705"invalid BAID from FW: %d\n", baid))706return;707708rcu_read_lock();709710ba_data = rcu_dereference(mvm->baid_map[baid]);711if (!ba_data) {712IWL_DEBUG_RX(mvm,713"Got valid BAID %d but not allocated, invalid frame release!\n",714baid);715goto out;716}717718/* pick any STA ID to find the pointer */719sta_id = ffs(ba_data->sta_mask) - 1;720sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);721if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))722goto out;723724reorder_buf = &ba_data->reorder_buf[queue];725726spin_lock_bh(&reorder_buf->lock);727iwl_mvm_release_frames(mvm, sta, napi, ba_data,728reorder_buf, nssn);729spin_unlock_bh(&reorder_buf->lock);730731out:732rcu_read_unlock();733}734735void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,736struct iwl_rx_cmd_buffer *rxb, int queue)737{738struct iwl_rx_packet *pkt = rxb_addr(rxb);739struct iwl_rxq_sync_notification *notif;740struct iwl_mvm_internal_rxq_notif *internal_notif;741u32 len = iwl_rx_packet_payload_len(pkt);742743notif = (void *)pkt->data;744internal_notif = (void *)notif->payload;745746if (WARN_ONCE(len < sizeof(*notif) + sizeof(*internal_notif),747"invalid notification size %d (%d)",748len, (int)(sizeof(*notif) + sizeof(*internal_notif))))749return;750len -= sizeof(*notif) + sizeof(*internal_notif);751752if (WARN_ONCE(internal_notif->sync &&753mvm->queue_sync_cookie != internal_notif->cookie,754"Received expired RX queue sync message (cookie %d but wanted %d, queue %d)\n",755internal_notif->cookie, mvm->queue_sync_cookie, queue))756return;757758switch (internal_notif->type) {759case IWL_MVM_RXQ_EMPTY:760WARN_ONCE(len, "invalid empty notification size %d", len);761break;762case IWL_MVM_RXQ_NOTIF_DEL_BA:763if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data),764"invalid delba notification size %d (%d)",765len, (int)sizeof(struct iwl_mvm_delba_data)))766break;767iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);768break;769default:770WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);771}772773if (internal_notif->sync) {774WARN_ONCE(!test_and_clear_bit(queue, &mvm->queue_sync_state),775"queue sync: queue %d responded a second time!\n",776queue);777if (READ_ONCE(mvm->queue_sync_state) == 0)778wake_up(&mvm->rx_sync_waitq);779}780}781782/*783* Returns true if the MPDU was buffered\dropped, false if it should be passed784* to upper layer.785*/786static bool iwl_mvm_reorder(struct iwl_mvm *mvm,787struct napi_struct *napi,788int queue,789struct ieee80211_sta *sta,790struct sk_buff *skb,791struct iwl_rx_mpdu_desc *desc)792{793struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);794struct iwl_mvm_baid_data *baid_data;795struct iwl_mvm_reorder_buffer *buffer;796u32 reorder = le32_to_cpu(desc->reorder_data);797bool amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;798bool last_subframe =799desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME;800#if defined(__linux__)801u8 tid = ieee80211_get_tid(hdr);802#elif defined(__FreeBSD__)803u8 tid;804#endif805struct iwl_mvm_reorder_buf_entry *entries;806u32 sta_mask;807int index;808u16 nssn, sn;809u8 baid;810811baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>812IWL_RX_MPDU_REORDER_BAID_SHIFT;813814if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000)815return false;816817/*818* This also covers the case of receiving a Block Ack Request819* outside a BA session; we'll pass it to mac80211 and that820* then sends a delBA action frame.821* This also covers pure monitor mode, in which case we won't822* have any BA sessions.823*/824if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)825return false;826827/* no sta yet */828if (WARN_ONCE(IS_ERR_OR_NULL(sta),829"Got valid BAID without a valid station assigned\n"))830return false;831832/* not a data packet or a bar */833if (!ieee80211_is_back_req(hdr->frame_control) &&834(!ieee80211_is_data_qos(hdr->frame_control) ||835is_multicast_ether_addr(hdr->addr1)))836return false;837838if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))839return false;840841baid_data = rcu_dereference(mvm->baid_map[baid]);842if (!baid_data) {843IWL_DEBUG_RX(mvm,844"Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",845baid, reorder);846return false;847}848849#if defined(__FreeBSD__)850tid = ieee80211_get_tid(hdr);851#endif852sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);853854if (IWL_FW_CHECK(mvm,855tid != baid_data->tid ||856!(sta_mask & baid_data->sta_mask),857"baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",858baid, baid_data->sta_mask, baid_data->tid,859sta_mask, tid))860return false;861862nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;863sn = (reorder & IWL_RX_MPDU_REORDER_SN_MASK) >>864IWL_RX_MPDU_REORDER_SN_SHIFT;865866buffer = &baid_data->reorder_buf[queue];867entries = &baid_data->entries[queue * baid_data->entries_per_queue];868869spin_lock_bh(&buffer->lock);870871if (!buffer->valid) {872if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN) {873spin_unlock_bh(&buffer->lock);874return false;875}876buffer->valid = true;877}878879/* drop any duplicated packets */880if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE))881goto drop;882883/* drop any oudated packets */884if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN)885goto drop;886887/* release immediately if allowed by nssn and no stored frames */888if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {889if (!amsdu || last_subframe)890buffer->head_sn = nssn;891892spin_unlock_bh(&buffer->lock);893return false;894}895896/*897* release immediately if there are no stored frames, and the sn is898* equal to the head.899* This can happen due to reorder timer, where NSSN is behind head_sn.900* When we released everything, and we got the next frame in the901* sequence, according to the NSSN we can't release immediately,902* while technically there is no hole and we can move forward.903*/904if (!buffer->num_stored && sn == buffer->head_sn) {905if (!amsdu || last_subframe)906buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);907908spin_unlock_bh(&buffer->lock);909return false;910}911912/* put in reorder buffer */913index = sn % baid_data->buf_size;914__skb_queue_tail(&entries[index].frames, skb);915buffer->num_stored++;916917/*918* We cannot trust NSSN for AMSDU sub-frames that are not the last.919* The reason is that NSSN advances on the first sub-frame, and may920* cause the reorder buffer to advance before all the sub-frames arrive.921* Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with922* SN 1. NSSN for first sub frame will be 3 with the result of driver923* releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is924* already ahead and it will be dropped.925* If the last sub-frame is not on this queue - we will get frame926* release notification with up to date NSSN.927* If this is the first frame that is stored in the buffer, the head_sn928* may be outdated. Update it based on the last NSSN to make sure it929* will be released when the frame release notification arrives.930*/931if (!amsdu || last_subframe)932iwl_mvm_release_frames(mvm, sta, napi, baid_data,933buffer, nssn);934else if (buffer->num_stored == 1)935buffer->head_sn = nssn;936937spin_unlock_bh(&buffer->lock);938return true;939940drop:941kfree_skb(skb);942spin_unlock_bh(&buffer->lock);943return true;944}945946static void iwl_mvm_agg_rx_received(struct iwl_mvm *mvm,947u32 reorder_data, u8 baid)948{949unsigned long now = jiffies;950unsigned long timeout;951struct iwl_mvm_baid_data *data;952953rcu_read_lock();954955data = rcu_dereference(mvm->baid_map[baid]);956if (!data) {957IWL_DEBUG_RX(mvm,958"Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",959baid, reorder_data);960goto out;961}962963if (!data->timeout)964goto out;965966timeout = data->timeout;967/*968* Do not update last rx all the time to avoid cache bouncing969* between the rx queues.970* Update it every timeout. Worst case is the session will971* expire after ~ 2 * timeout, which doesn't matter that much.972*/973if (time_before(data->last_rx + TU_TO_JIFFIES(timeout), now))974/* Update is atomic */975data->last_rx = now;976977out:978rcu_read_unlock();979}980981static void iwl_mvm_flip_address(u8 *addr)982{983int i;984u8 mac_addr[ETH_ALEN];985986for (i = 0; i < ETH_ALEN; i++)987mac_addr[i] = addr[ETH_ALEN - i - 1];988ether_addr_copy(addr, mac_addr);989}990991struct iwl_mvm_rx_phy_data {992enum iwl_rx_phy_info_type info_type;993__le32 d0, d1, d2, d3, eht_d4, d5;994__le16 d4;995bool with_data;996bool first_subframe;997__le32 rx_vec[4];998999u32 rate_n_flags;1000u32 gp2_on_air_rise;1001u16 phy_info;1002u8 energy_a, energy_b;1003u8 channel;1004};10051006static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm,1007struct iwl_mvm_rx_phy_data *phy_data,1008struct ieee80211_radiotap_he_mu *he_mu)1009{1010u32 phy_data2 = le32_to_cpu(phy_data->d2);1011u32 phy_data3 = le32_to_cpu(phy_data->d3);1012u16 phy_data4 = le16_to_cpu(phy_data->d4);1013u32 rate_n_flags = phy_data->rate_n_flags;10141015if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CRC_OK, phy_data4)) {1016he_mu->flags1 |=1017cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN |1018IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN);10191020he_mu->flags1 |=1021le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CTR_RU,1022phy_data4),1023IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU);10241025he_mu->ru_ch1[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU0,1026phy_data2);1027he_mu->ru_ch1[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1,1028phy_data3);1029he_mu->ru_ch1[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU2,1030phy_data2);1031he_mu->ru_ch1[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU3,1032phy_data3);1033}10341035if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) &&1036(rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) != RATE_MCS_CHAN_WIDTH_20) {1037he_mu->flags1 |=1038cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |1039IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN);10401041he_mu->flags2 |=1042le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CTR_RU,1043phy_data4),1044IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU);10451046he_mu->ru_ch2[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU0,1047phy_data2);1048he_mu->ru_ch2[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU1,1049phy_data3);1050he_mu->ru_ch2[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU2,1051phy_data2);1052he_mu->ru_ch2[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU3,1053phy_data3);1054}1055}10561057static void1058iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,1059struct ieee80211_radiotap_he *he,1060struct ieee80211_radiotap_he_mu *he_mu,1061struct ieee80211_rx_status *rx_status)1062{1063/*1064* Unfortunately, we have to leave the mac80211 data1065* incorrect for the case that we receive an HE-MU1066* transmission and *don't* have the HE phy data (due1067* to the bits being used for TSF). This shouldn't1068* happen though as management frames where we need1069* the TSF/timers are not be transmitted in HE-MU.1070*/1071u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);1072u32 rate_n_flags = phy_data->rate_n_flags;1073u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;1074u8 offs = 0;10751076rx_status->bw = RATE_INFO_BW_HE_RU;10771078he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);10791080switch (ru) {1081case 0 ... 36:1082rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;1083offs = ru;1084break;1085case 37 ... 52:1086rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;1087offs = ru - 37;1088break;1089case 53 ... 60:1090rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;1091offs = ru - 53;1092break;1093case 61 ... 64:1094rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;1095offs = ru - 61;1096break;1097case 65 ... 66:1098rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;1099offs = ru - 65;1100break;1101case 67:1102rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;1103break;1104case 68:1105rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;1106break;1107}1108he->data2 |= le16_encode_bits(offs,1109IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);1110he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |1111IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);1112if (phy_data->d1 & cpu_to_le32(IWL_RX_PHY_DATA1_HE_RU_ALLOC_SEC80))1113he->data2 |=1114cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);11151116#define CHECK_BW(bw) \1117BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \1118RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \1119BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \1120RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)1121CHECK_BW(20);1122CHECK_BW(40);1123CHECK_BW(80);1124CHECK_BW(160);11251126if (he_mu)1127he_mu->flags2 |=1128le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,1129rate_n_flags),1130IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);1131else if (he_type == RATE_MCS_HE_TYPE_TRIG)1132he->data6 |=1133cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |1134le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,1135rate_n_flags),1136IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);1137}11381139static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,1140struct iwl_mvm_rx_phy_data *phy_data,1141struct ieee80211_radiotap_he *he,1142struct ieee80211_radiotap_he_mu *he_mu,1143struct ieee80211_rx_status *rx_status,1144int queue)1145{1146switch (phy_data->info_type) {1147case IWL_RX_PHY_INFO_TYPE_NONE:1148case IWL_RX_PHY_INFO_TYPE_CCK:1149case IWL_RX_PHY_INFO_TYPE_OFDM_LGCY:1150case IWL_RX_PHY_INFO_TYPE_HT:1151case IWL_RX_PHY_INFO_TYPE_VHT_SU:1152case IWL_RX_PHY_INFO_TYPE_VHT_MU:1153case IWL_RX_PHY_INFO_TYPE_EHT_MU:1154case IWL_RX_PHY_INFO_TYPE_EHT_TB:1155case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:1156case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:1157return;1158case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:1159he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |1160IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |1161IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |1162IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);1163he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,1164IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),1165IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);1166he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,1167IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),1168IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);1169he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,1170IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),1171IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);1172he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2,1173IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),1174IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);1175fallthrough;1176case IWL_RX_PHY_INFO_TYPE_HE_SU:1177case IWL_RX_PHY_INFO_TYPE_HE_MU:1178case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:1179case IWL_RX_PHY_INFO_TYPE_HE_TB:1180/* HE common */1181he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |1182IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |1183IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);1184he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |1185IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |1186IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |1187IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);1188he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,1189IWL_RX_PHY_DATA0_HE_BSS_COLOR_MASK),1190IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);1191if (phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB &&1192phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB_EXT) {1193he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);1194he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,1195IWL_RX_PHY_DATA0_HE_UPLINK),1196IEEE80211_RADIOTAP_HE_DATA3_UL_DL);1197}1198he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,1199IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),1200IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);1201he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,1202IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),1203IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);1204he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,1205IWL_RX_PHY_DATA0_HE_PE_DISAMBIG),1206IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);1207he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d1,1208IWL_RX_PHY_DATA1_HE_LTF_NUM_MASK),1209IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);1210he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,1211IWL_RX_PHY_DATA0_HE_TXOP_DUR_MASK),1212IEEE80211_RADIOTAP_HE_DATA6_TXOP);1213he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,1214IWL_RX_PHY_DATA0_HE_DOPPLER),1215IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);1216break;1217}12181219switch (phy_data->info_type) {1220case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:1221case IWL_RX_PHY_INFO_TYPE_HE_MU:1222case IWL_RX_PHY_INFO_TYPE_HE_SU:1223he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);1224he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,1225IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),1226IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);1227break;1228default:1229/* nothing here */1230break;1231}12321233switch (phy_data->info_type) {1234case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:1235he_mu->flags1 |=1236le16_encode_bits(le16_get_bits(phy_data->d4,1237IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM),1238IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);1239he_mu->flags1 |=1240le16_encode_bits(le16_get_bits(phy_data->d4,1241IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_MCS_MASK),1242IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);1243he_mu->flags2 |=1244le16_encode_bits(le16_get_bits(phy_data->d4,1245IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK),1246IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);1247iwl_mvm_decode_he_mu_ext(mvm, phy_data, he_mu);1248fallthrough;1249case IWL_RX_PHY_INFO_TYPE_HE_MU:1250he_mu->flags2 |=1251le16_encode_bits(le32_get_bits(phy_data->d1,1252IWL_RX_PHY_DATA1_HE_MU_SIBG_SYM_OR_USER_NUM_MASK),1253IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);1254he_mu->flags2 |=1255le16_encode_bits(le32_get_bits(phy_data->d1,1256IWL_RX_PHY_DATA1_HE_MU_SIGB_COMPRESSION),1257IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);1258fallthrough;1259case IWL_RX_PHY_INFO_TYPE_HE_TB:1260case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:1261iwl_mvm_decode_he_phy_ru_alloc(phy_data, he, he_mu, rx_status);1262break;1263case IWL_RX_PHY_INFO_TYPE_HE_SU:1264he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);1265he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,1266IWL_RX_PHY_DATA0_HE_BEAM_CHNG),1267IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);1268break;1269default:1270/* nothing */1271break;1272}1273}12741275#define LE32_DEC_ENC(value, dec_bits, enc_bits) \1276le32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)12771278#define IWL_MVM_ENC_USIG_VALUE_MASK(usig, in_value, dec_bits, enc_bits) do { \1279typeof(enc_bits) _enc_bits = enc_bits; \1280typeof(usig) _usig = usig; \1281(_usig)->mask |= cpu_to_le32(_enc_bits); \1282(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \1283} while (0)12841285#define __IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \1286eht->data[(rt_data)] |= \1287(cpu_to_le32 \1288(IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \1289LE32_DEC_ENC(data ## fw_data, \1290IWL_RX_PHY_DATA ## fw_data ## _EHT_MU_EXT_RU_ALLOC_ ## fw_ru, \1291IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))12921293#define _IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \1294__IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)12951296#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 11297#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 21298#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 21299#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 21300#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 31301#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 31302#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 31303#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 413041305#define IWL_RX_RU_DATA_A1 21306#define IWL_RX_RU_DATA_A2 21307#define IWL_RX_RU_DATA_B1 21308#define IWL_RX_RU_DATA_B2 41309#define IWL_RX_RU_DATA_C1 31310#define IWL_RX_RU_DATA_C2 31311#define IWL_RX_RU_DATA_D1 41312#define IWL_RX_RU_DATA_D2 413131314#define IWL_MVM_ENC_EHT_RU(rt_ru, fw_ru) \1315_IWL_MVM_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \1316rt_ru, \1317IWL_RX_RU_DATA_ ## fw_ru, \1318fw_ru)13191320static void iwl_mvm_decode_eht_ext_mu(struct iwl_mvm *mvm,1321struct iwl_mvm_rx_phy_data *phy_data,1322struct ieee80211_rx_status *rx_status,1323struct ieee80211_radiotap_eht *eht,1324struct ieee80211_radiotap_eht_usig *usig)1325{1326if (phy_data->with_data) {1327__le32 data1 = phy_data->d1;1328__le32 data2 = phy_data->d2;1329__le32 data3 = phy_data->d3;1330__le32 data4 = phy_data->eht_d4;1331__le32 data5 = phy_data->d5;1332u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;13331334IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,1335IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,1336IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);1337IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,1338IWL_RX_PHY_DATA5_EHT_MU_PUNC_CH_CODE,1339IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);1340IWL_MVM_ENC_USIG_VALUE_MASK(usig, data4,1341IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS,1342IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);1343IWL_MVM_ENC_USIG_VALUE_MASK1344(usig, data1, IWL_RX_PHY_DATA1_EHT_MU_NUM_SIG_SYM_USIGA2,1345IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);13461347eht->user_info[0] |=1348cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) |1349LE32_DEC_ENC(data5, IWL_RX_PHY_DATA5_EHT_MU_STA_ID_USR,1350IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID);13511352eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M);1353eht->data[7] |= LE32_DEC_ENC1354(data5, IWL_RX_PHY_DATA5_EHT_MU_NUM_USR_NON_OFDMA,1355IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);13561357/*1358* Hardware labels the content channels/RU allocation values1359* as follows:1360* Content Channel 1 Content Channel 21361* 20 MHz: A11362* 40 MHz: A1 B11363* 80 MHz: A1 C1 B1 D11364* 160 MHz: A1 C1 A2 C2 B1 D1 B2 D21365* 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D41366*1367* However firmware can only give us A1-D2, so the higher1368* frequencies are missing.1369*/13701371switch (phy_bw) {1372case RATE_MCS_CHAN_WIDTH_320:1373/* additional values are missing in RX metadata */1374case RATE_MCS_CHAN_WIDTH_160:1375/* content channel 1 */1376IWL_MVM_ENC_EHT_RU(1_2_1, A2);1377IWL_MVM_ENC_EHT_RU(1_2_2, C2);1378/* content channel 2 */1379IWL_MVM_ENC_EHT_RU(2_2_1, B2);1380IWL_MVM_ENC_EHT_RU(2_2_2, D2);1381fallthrough;1382case RATE_MCS_CHAN_WIDTH_80:1383/* content channel 1 */1384IWL_MVM_ENC_EHT_RU(1_1_2, C1);1385/* content channel 2 */1386IWL_MVM_ENC_EHT_RU(2_1_2, D1);1387fallthrough;1388case RATE_MCS_CHAN_WIDTH_40:1389/* content channel 2 */1390IWL_MVM_ENC_EHT_RU(2_1_1, B1);1391fallthrough;1392case RATE_MCS_CHAN_WIDTH_20:1393IWL_MVM_ENC_EHT_RU(1_1_1, A1);1394break;1395}1396} else {1397__le32 usig_a1 = phy_data->rx_vec[0];1398__le32 usig_a2 = phy_data->rx_vec[1];13991400IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,1401IWL_RX_USIG_A1_DISREGARD,1402IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD);1403IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,1404IWL_RX_USIG_A1_VALIDATE,1405IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE);1406IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1407IWL_RX_USIG_A2_EHT_PPDU_TYPE,1408IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);1409IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1410IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,1411IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE);1412IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1413IWL_RX_USIG_A2_EHT_PUNC_CHANNEL,1414IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);1415IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1416IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8,1417IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE);1418IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1419IWL_RX_USIG_A2_EHT_SIG_MCS,1420IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);1421IWL_MVM_ENC_USIG_VALUE_MASK1422(usig, usig_a2, IWL_RX_USIG_A2_EHT_SIG_SYM_NUM,1423IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);1424IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1425IWL_RX_USIG_A2_EHT_CRC_OK,1426IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC);1427}1428}14291430static void iwl_mvm_decode_eht_ext_tb(struct iwl_mvm *mvm,1431struct iwl_mvm_rx_phy_data *phy_data,1432struct ieee80211_rx_status *rx_status,1433struct ieee80211_radiotap_eht *eht,1434struct ieee80211_radiotap_eht_usig *usig)1435{1436if (phy_data->with_data) {1437__le32 data5 = phy_data->d5;14381439IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,1440IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,1441IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);1442IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,1443IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE1,1444IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);14451446IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,1447IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE2,1448IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);1449} else {1450__le32 usig_a1 = phy_data->rx_vec[0];1451__le32 usig_a2 = phy_data->rx_vec[1];14521453IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,1454IWL_RX_USIG_A1_DISREGARD,1455IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);1456IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1457IWL_RX_USIG_A2_EHT_PPDU_TYPE,1458IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);1459IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1460IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,1461IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE);1462IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1463IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1,1464IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);1465IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1466IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2,1467IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);1468IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1469IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD,1470IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD);1471IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,1472IWL_RX_USIG_A2_EHT_CRC_OK,1473IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC);1474}1475}14761477static void iwl_mvm_decode_eht_ru(struct iwl_mvm *mvm,1478struct ieee80211_rx_status *rx_status,1479struct ieee80211_radiotap_eht *eht)1480{1481u32 ru = le32_get_bits(eht->data[8],1482IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);1483enum nl80211_eht_ru_alloc nl_ru;14841485/* Using D1.5 Table 9-53a - Encoding of PS160 and RU Allocation subfields1486* in an EHT variant User Info field1487*/14881489switch (ru) {1490case 0 ... 36:1491nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_26;1492break;1493case 37 ... 52:1494nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52;1495break;1496case 53 ... 60:1497nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106;1498break;1499case 61 ... 64:1500nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_242;1501break;1502case 65 ... 66:1503nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484;1504break;1505case 67:1506nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996;1507break;1508case 68:1509nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996;1510break;1511case 69:1512nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_4x996;1513break;1514case 70 ... 81:1515nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52P26;1516break;1517case 82 ... 89:1518nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106P26;1519break;1520case 90 ... 93:1521nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484P242;1522break;1523case 94 ... 95:1524nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484;1525break;1526case 96 ... 99:1527nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242;1528break;1529case 100 ... 103:1530nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484;1531break;1532case 104:1533nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996;1534break;1535case 105 ... 106:1536nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484;1537break;1538default:1539return;1540}15411542rx_status->bw = RATE_INFO_BW_EHT_RU;1543rx_status->eht.ru = nl_ru;1544}15451546static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,1547struct iwl_mvm_rx_phy_data *phy_data,1548struct ieee80211_rx_status *rx_status,1549struct ieee80211_radiotap_eht *eht,1550struct ieee80211_radiotap_eht_usig *usig)15511552{1553__le32 data0 = phy_data->d0;1554__le32 data1 = phy_data->d1;1555__le32 usig_a1 = phy_data->rx_vec[0];1556u8 info_type = phy_data->info_type;15571558/* Not in EHT range */1559if (info_type < IWL_RX_PHY_INFO_TYPE_EHT_MU ||1560info_type > IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT)1561return;15621563usig->common |= cpu_to_le321564(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |1565IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN);1566if (phy_data->with_data) {1567usig->common |= LE32_DEC_ENC(data0,1568IWL_RX_PHY_DATA0_EHT_UPLINK,1569IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);1570usig->common |= LE32_DEC_ENC(data0,1571IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK,1572IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);1573} else {1574usig->common |= LE32_DEC_ENC(usig_a1,1575IWL_RX_USIG_A1_UL_FLAG,1576IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);1577usig->common |= LE32_DEC_ENC(usig_a1,1578IWL_RX_USIG_A1_BSS_COLOR,1579IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);1580}15811582if (fw_has_capa(&mvm->fw->ucode_capa,1583IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT)) {1584usig->common |=1585cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED);1586usig->common |=1587LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE,1588IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);1589}15901591eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);1592eht->data[0] |= LE32_DEC_ENC(data0,1593IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,1594IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);15951596/* All RU allocating size/index is in TB format */1597eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);1598eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,1599IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);1600eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0,1601IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);1602eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7,1603IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);16041605iwl_mvm_decode_eht_ru(mvm, rx_status, eht);16061607/* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set1608* which is on only in case of monitor mode so no need to check monitor1609* mode1610*/1611eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);1612eht->data[1] |=1613le32_encode_bits(mvm->monitor_p80,1614IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);16151616usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);1617if (phy_data->with_data)1618usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK,1619IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);1620else1621usig->common |= LE32_DEC_ENC(usig_a1, IWL_RX_USIG_A1_TXOP_DURATION,1622IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);16231624eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM);1625eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_LDPC_EXT_SYM,1626IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);16271628eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM);1629eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PRE_FEC_PAD_MASK,1630IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);16311632eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM);1633eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PE_DISAMBIG,1634IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);16351636/* TODO: what about IWL_RX_PHY_DATA0_EHT_BW320_SLOT */16371638if (!le32_get_bits(data0, IWL_RX_PHY_DATA0_EHT_SIGA_CRC_OK))1639usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);16401641usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);1642usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PHY_VER,1643IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);16441645/*1646* TODO: what about TB - IWL_RX_PHY_DATA1_EHT_TB_PILOT_TYPE,1647* IWL_RX_PHY_DATA1_EHT_TB_LOW_SS1648*/16491650eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF);1651eht->data[0] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM,1652IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);16531654if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT ||1655info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB)1656iwl_mvm_decode_eht_ext_tb(mvm, phy_data, rx_status, eht, usig);16571658if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT ||1659info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU)1660iwl_mvm_decode_eht_ext_mu(mvm, phy_data, rx_status, eht, usig);1661}16621663static void iwl_mvm_rx_eht(struct iwl_mvm *mvm, struct sk_buff *skb,1664struct iwl_mvm_rx_phy_data *phy_data,1665int queue)1666{1667struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);16681669struct ieee80211_radiotap_eht *eht;1670struct ieee80211_radiotap_eht_usig *usig;1671size_t eht_len = sizeof(*eht);16721673u32 rate_n_flags = phy_data->rate_n_flags;1674u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;1675/* EHT and HE have the same valus for LTF */1676u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;1677u16 phy_info = phy_data->phy_info;1678u32 bw;16791680/* u32 for 1 user_info */1681if (phy_data->with_data)1682eht_len += sizeof(u32);16831684eht = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);16851686usig = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,1687sizeof(*usig));1688rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;1689usig->common |=1690cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN);16911692/* specific handling for 320MHz */1693bw = FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags);1694if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)1695bw += FIELD_GET(IWL_RX_PHY_DATA0_EHT_BW320_SLOT,1696le32_to_cpu(phy_data->d0));16971698usig->common |= cpu_to_le321699(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW, bw));17001701/* report the AMPDU-EOF bit on single frames */1702if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {1703rx_status->flag |= RX_FLAG_AMPDU_DETAILS;1704rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;1705if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))1706rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;1707}17081709/* update aggregation data for monitor sake on default queue */1710if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&1711(phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {1712rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;1713if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))1714rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;1715}17161717if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)1718iwl_mvm_decode_eht_phy_data(mvm, phy_data, rx_status, eht, usig);17191720#define CHECK_TYPE(F) \1721BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \1722(RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))17231724CHECK_TYPE(SU);1725CHECK_TYPE(EXT_SU);1726CHECK_TYPE(MU);1727CHECK_TYPE(TRIG);17281729switch (FIELD_GET(RATE_MCS_HE_GI_LTF_MSK, rate_n_flags)) {1730case 0:1731if (he_type == RATE_MCS_HE_TYPE_TRIG) {1732rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;1733ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;1734} else {1735rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;1736ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;1737}1738break;1739case 1:1740rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;1741ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;1742break;1743case 2:1744ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1745if (he_type == RATE_MCS_HE_TYPE_TRIG)1746rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;1747else1748rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;1749break;1750case 3:1751if (he_type != RATE_MCS_HE_TYPE_TRIG) {1752ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1753rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;1754}1755break;1756default:1757/* nothing here */1758break;1759}17601761if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) {1762eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI);1763eht->data[0] |= cpu_to_le321764(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF,1765ltf) |1766FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI,1767rx_status->eht.gi));1768}176917701771if (!phy_data->with_data) {1772eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |1773IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S);1774eht->data[7] |=1775le32_encode_bits(le32_get_bits(phy_data->rx_vec[2],1776RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK),1777IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);1778if (rate_n_flags & RATE_MCS_BF_MSK)1779eht->data[7] |=1780cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);1781} else {1782eht->user_info[0] |=1783cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |1784IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |1785IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |1786IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O |1787IEEE80211_RADIOTAP_EHT_USER_INFO_DATA_FOR_USER);17881789if (rate_n_flags & RATE_MCS_BF_MSK)1790eht->user_info[0] |=1791cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O);17921793if (rate_n_flags & RATE_MCS_LDPC_MSK)1794eht->user_info[0] |=1795cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING);17961797eht->user_info[0] |= cpu_to_le321798(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS,1799FIELD_GET(RATE_VHT_MCS_RATE_CODE_MSK,1800rate_n_flags)) |1801FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O,1802FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags)));1803}1804}18051806static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,1807struct iwl_mvm_rx_phy_data *phy_data,1808int queue)1809{1810struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);1811struct ieee80211_radiotap_he *he = NULL;1812struct ieee80211_radiotap_he_mu *he_mu = NULL;1813u32 rate_n_flags = phy_data->rate_n_flags;1814u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;1815u8 ltf;1816static const struct ieee80211_radiotap_he known = {1817.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |1818IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |1819IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN |1820IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN),1821.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN |1822IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN),1823};1824static const struct ieee80211_radiotap_he_mu mu_known = {1825.flags1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN |1826IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN |1827IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN |1828IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN),1829.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |1830IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),1831};1832u16 phy_info = phy_data->phy_info;18331834he = skb_put_data(skb, &known, sizeof(known));1835rx_status->flag |= RX_FLAG_RADIOTAP_HE;18361837if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||1838phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {1839he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));1840rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;1841}18421843/* report the AMPDU-EOF bit on single frames */1844if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {1845rx_status->flag |= RX_FLAG_AMPDU_DETAILS;1846rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;1847if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))1848rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;1849}18501851if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)1852iwl_mvm_decode_he_phy_data(mvm, phy_data, he, he_mu, rx_status,1853queue);18541855/* update aggregation data for monitor sake on default queue */1856if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&1857(phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {1858rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;1859if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))1860rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;1861}18621863if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&1864rate_n_flags & RATE_MCS_HE_106T_MSK) {1865rx_status->bw = RATE_INFO_BW_HE_RU;1866rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;1867}18681869/* actually data is filled in mac80211 */1870if (he_type == RATE_MCS_HE_TYPE_SU ||1871he_type == RATE_MCS_HE_TYPE_EXT_SU)1872he->data1 |=1873cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);18741875#define CHECK_TYPE(F) \1876BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \1877(RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))18781879CHECK_TYPE(SU);1880CHECK_TYPE(EXT_SU);1881CHECK_TYPE(MU);1882CHECK_TYPE(TRIG);18831884he->data1 |= cpu_to_le16(he_type >> RATE_MCS_HE_TYPE_POS);18851886if (rate_n_flags & RATE_MCS_BF_MSK)1887he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);18881889switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>1890RATE_MCS_HE_GI_LTF_POS) {1891case 0:1892if (he_type == RATE_MCS_HE_TYPE_TRIG)1893rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;1894else1895rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;1896if (he_type == RATE_MCS_HE_TYPE_MU)1897ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1898else1899ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;1900break;1901case 1:1902if (he_type == RATE_MCS_HE_TYPE_TRIG)1903rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;1904else1905rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;1906ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;1907break;1908case 2:1909if (he_type == RATE_MCS_HE_TYPE_TRIG) {1910rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;1911ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1912} else {1913rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;1914ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;1915}1916break;1917case 3:1918rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;1919ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1920break;1921case 4:1922rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;1923ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;1924break;1925default:1926ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;1927}19281929he->data5 |= le16_encode_bits(ltf,1930IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);1931}19321933static void iwl_mvm_decode_lsig(struct sk_buff *skb,1934struct iwl_mvm_rx_phy_data *phy_data)1935{1936struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);1937struct ieee80211_radiotap_lsig *lsig;19381939switch (phy_data->info_type) {1940case IWL_RX_PHY_INFO_TYPE_HT:1941case IWL_RX_PHY_INFO_TYPE_VHT_SU:1942case IWL_RX_PHY_INFO_TYPE_VHT_MU:1943case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:1944case IWL_RX_PHY_INFO_TYPE_HE_SU:1945case IWL_RX_PHY_INFO_TYPE_HE_MU:1946case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:1947case IWL_RX_PHY_INFO_TYPE_HE_TB:1948case IWL_RX_PHY_INFO_TYPE_EHT_MU:1949case IWL_RX_PHY_INFO_TYPE_EHT_TB:1950case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:1951case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:1952lsig = skb_put(skb, sizeof(*lsig));1953lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);1954lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->d1,1955IWL_RX_PHY_DATA1_LSIG_LEN_MASK),1956IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH);1957rx_status->flag |= RX_FLAG_RADIOTAP_LSIG;1958break;1959default:1960break;1961}1962}19631964struct iwl_rx_sta_csa {1965bool all_sta_unblocked;1966struct ieee80211_vif *vif;1967};19681969static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta)1970{1971struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);1972struct iwl_rx_sta_csa *rx_sta_csa = data;19731974if (mvmsta->vif != rx_sta_csa->vif)1975return;19761977if (mvmsta->disable_tx)1978rx_sta_csa->all_sta_unblocked = false;1979}19801981/*1982* Note: requires also rx_status->band to be prefilled, as well1983* as phy_data (apart from phy_data->info_type)1984* Note: desc/hdr may be NULL1985*/1986static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,1987struct iwl_rx_mpdu_desc *desc,1988struct ieee80211_hdr *hdr,1989struct sk_buff *skb,1990struct iwl_mvm_rx_phy_data *phy_data,1991int queue)1992{1993struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);1994u32 rate_n_flags = phy_data->rate_n_flags;1995u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);1996u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;1997bool is_sgi;19981999phy_data->info_type = IWL_RX_PHY_INFO_TYPE_NONE;20002001if (phy_data->phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)2002phy_data->info_type =2003le32_get_bits(phy_data->d1,2004IWL_RX_PHY_DATA1_INFO_TYPE_MASK);20052006/* This may be overridden by iwl_mvm_rx_he() to HE_RU */2007switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {2008case RATE_MCS_CHAN_WIDTH_20:2009break;2010case RATE_MCS_CHAN_WIDTH_40:2011rx_status->bw = RATE_INFO_BW_40;2012break;2013case RATE_MCS_CHAN_WIDTH_80:2014rx_status->bw = RATE_INFO_BW_80;2015break;2016case RATE_MCS_CHAN_WIDTH_160:2017rx_status->bw = RATE_INFO_BW_160;2018break;2019case RATE_MCS_CHAN_WIDTH_320:2020rx_status->bw = RATE_INFO_BW_320;2021break;2022}20232024/* must be before L-SIG data */2025if (format == RATE_MCS_MOD_TYPE_HE)2026iwl_mvm_rx_he(mvm, skb, phy_data, queue);20272028iwl_mvm_decode_lsig(skb, phy_data);20292030rx_status->device_timestamp = phy_data->gp2_on_air_rise;20312032if (mvm->rx_ts_ptp && mvm->monitor_on) {2033u64 adj_time =2034iwl_mvm_ptp_get_adj_time(mvm, phy_data->gp2_on_air_rise * NSEC_PER_USEC);20352036rx_status->mactime = div64_u64(adj_time, NSEC_PER_USEC);2037rx_status->flag |= RX_FLAG_MACTIME_IS_RTAP_TS64;2038rx_status->flag &= ~RX_FLAG_MACTIME;2039}20402041rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,2042rx_status->band);2043iwl_mvm_get_signal_strength(mvm, desc, hdr, rx_status, rate_n_flags,2044phy_data->energy_a, phy_data->energy_b);20452046/* using TLV format and must be after all fixed len fields */2047if (format == RATE_MCS_MOD_TYPE_EHT)2048iwl_mvm_rx_eht(mvm, skb, phy_data, queue);20492050if (unlikely(mvm->monitor_on))2051iwl_mvm_add_rtap_sniffer_config(mvm, skb);20522053is_sgi = format == RATE_MCS_MOD_TYPE_HE ?2054iwl_he_is_sgi(rate_n_flags) :2055rate_n_flags & RATE_MCS_SGI_MSK;20562057if (!(format == RATE_MCS_MOD_TYPE_CCK) && is_sgi)2058rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;20592060if (rate_n_flags & RATE_MCS_LDPC_MSK)2061rx_status->enc_flags |= RX_ENC_FLAG_LDPC;20622063switch (format) {2064case RATE_MCS_MOD_TYPE_VHT:2065rx_status->encoding = RX_ENC_VHT;2066break;2067case RATE_MCS_MOD_TYPE_HE:2068rx_status->encoding = RX_ENC_HE;2069rx_status->he_dcm =2070!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);2071break;2072case RATE_MCS_MOD_TYPE_EHT:2073rx_status->encoding = RX_ENC_EHT;2074break;2075}20762077switch (format) {2078case RATE_MCS_MOD_TYPE_HT:2079rx_status->encoding = RX_ENC_HT;2080rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);2081rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;2082break;2083case RATE_MCS_MOD_TYPE_VHT:2084case RATE_MCS_MOD_TYPE_HE:2085case RATE_MCS_MOD_TYPE_EHT:2086rx_status->nss =2087u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;2088rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;2089rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;2090break;2091default: {2092int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,2093rx_status->band);20942095rx_status->rate_idx = rate;20962097if ((rate < 0 || rate > 0xFF)) {2098rx_status->rate_idx = 0;2099if (net_ratelimit())2100IWL_ERR(mvm, "Invalid rate flags 0x%x, band %d,\n",2101rate_n_flags, rx_status->band);2102}21032104break;2105}2106}2107}21082109void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,2110struct iwl_rx_cmd_buffer *rxb, int queue)2111{2112struct ieee80211_rx_status *rx_status;2113struct iwl_rx_packet *pkt = rxb_addr(rxb);2114struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;2115struct ieee80211_hdr *hdr;2116u32 len;2117u32 pkt_len = iwl_rx_packet_payload_len(pkt);2118struct ieee80211_sta *sta = NULL;2119struct sk_buff *skb;2120u8 crypt_len = 0;2121u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);2122size_t desc_size;2123struct iwl_mvm_rx_phy_data phy_data = {};2124u32 format;21252126if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))2127return;21282129if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)2130desc_size = sizeof(*desc);2131else2132desc_size = IWL_RX_DESC_SIZE_V1;21332134if (unlikely(pkt_len < desc_size)) {2135IWL_DEBUG_DROP(mvm, "Bad REPLY_RX_MPDU_CMD size\n");2136return;2137}21382139if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {2140phy_data.rate_n_flags =2141iwl_mvm_v3_rate_from_fw(desc->v3.rate_n_flags,2142mvm->fw_rates_ver);2143phy_data.channel = desc->v3.channel;2144phy_data.gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);2145phy_data.energy_a = desc->v3.energy_a;2146phy_data.energy_b = desc->v3.energy_b;21472148phy_data.d0 = desc->v3.phy_data0;2149phy_data.d1 = desc->v3.phy_data1;2150phy_data.d2 = desc->v3.phy_data2;2151phy_data.d3 = desc->v3.phy_data3;2152phy_data.eht_d4 = desc->phy_eht_data4;2153phy_data.d5 = desc->v3.phy_data5;2154} else {2155phy_data.rate_n_flags =2156iwl_mvm_v3_rate_from_fw(desc->v1.rate_n_flags,2157mvm->fw_rates_ver);2158phy_data.channel = desc->v1.channel;2159phy_data.gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);2160phy_data.energy_a = desc->v1.energy_a;2161phy_data.energy_b = desc->v1.energy_b;21622163phy_data.d0 = desc->v1.phy_data0;2164phy_data.d1 = desc->v1.phy_data1;2165phy_data.d2 = desc->v1.phy_data2;2166phy_data.d3 = desc->v1.phy_data3;2167}21682169format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;21702171len = le16_to_cpu(desc->mpdu_len);21722173if (unlikely(len + desc_size > pkt_len)) {2174IWL_DEBUG_DROP(mvm, "FW lied about packet len\n");2175return;2176}21772178phy_data.with_data = true;2179phy_data.phy_info = le16_to_cpu(desc->phy_info);2180phy_data.d4 = desc->phy_data4;21812182hdr = (void *)(pkt->data + desc_size);2183/* Dont use dev_alloc_skb(), we'll have enough headroom once2184* ieee80211_hdr pulled.2185*/2186skb = alloc_skb(128, GFP_ATOMIC);2187if (!skb) {2188IWL_ERR(mvm, "alloc_skb failed\n");2189return;2190}21912192if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {2193/*2194* If the device inserted padding it means that (it thought)2195* the 802.11 header wasn't a multiple of 4 bytes long. In2196* this case, reserve two bytes at the start of the SKB to2197* align the payload properly in case we end up copying it.2198*/2199skb_reserve(skb, 2);2200}22012202rx_status = IEEE80211_SKB_RXCB(skb);22032204/*2205* Keep packets with CRC errors (and with overrun) for monitor mode2206* (otherwise the firmware discards them) but mark them as bad.2207*/2208if (!(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_CRC_OK)) ||2209!(desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_OVERRUN_OK))) {2210IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n",2211le32_to_cpu(desc->status));2212rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;2213}22142215/* set the preamble flag if appropriate */2216if (format == RATE_MCS_MOD_TYPE_CCK &&2217phy_data.phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)2218rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;22192220if (likely(!(phy_data.phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {2221u64 tsf_on_air_rise;22222223if (mvm->trans->mac_cfg->device_family >=2224IWL_DEVICE_FAMILY_AX210)2225tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);2226else2227tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);22282229rx_status->mactime = tsf_on_air_rise;2230/* TSF as indicated by the firmware is at INA time */2231rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;2232}22332234if (iwl_mvm_is_band_in_rx_supported(mvm)) {2235u8 band = u8_get_bits(desc->mac_phy_band,2236IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK);22372238rx_status->band = iwl_mvm_nl80211_band_from_phy(band);2239} else {2240rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :2241NL80211_BAND_2GHZ;2242}22432244/* update aggregation data for monitor sake on default queue */2245if (!queue && (phy_data.phy_info & IWL_RX_MPDU_PHY_AMPDU)) {2246bool toggle_bit;22472248toggle_bit = phy_data.phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;2249rx_status->flag |= RX_FLAG_AMPDU_DETAILS;2250/*2251* Toggle is switched whenever new aggregation starts. Make2252* sure ampdu_reference is never 0 so we can later use it to2253* see if the frame was really part of an A-MPDU or not.2254*/2255if (toggle_bit != mvm->ampdu_toggle) {2256mvm->ampdu_ref++;2257if (mvm->ampdu_ref == 0)2258mvm->ampdu_ref++;2259mvm->ampdu_toggle = toggle_bit;2260phy_data.first_subframe = true;2261}2262rx_status->ampdu_reference = mvm->ampdu_ref;2263}22642265rcu_read_lock();22662267if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {2268if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) {2269struct ieee80211_link_sta *link_sta;22702271sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);2272if (IS_ERR(sta))2273sta = NULL;2274link_sta = rcu_dereference(mvm->fw_id_to_link_sta[sta_id]);22752276if (sta && sta->valid_links && link_sta) {2277rx_status->link_valid = 1;2278rx_status->link_id = link_sta->link_id;2279}2280}2281} else if (!is_multicast_ether_addr(hdr->addr2)) {2282/*2283* This is fine since we prevent two stations with the same2284* address from being added.2285*/2286sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);2287}22882289if (iwl_mvm_rx_crypto(mvm, sta, hdr, rx_status, phy_data.phy_info, desc,2290le32_to_cpu(pkt->len_n_flags), queue,2291&crypt_len)) {2292kfree_skb(skb);2293goto out;2294}22952296iwl_mvm_rx_fill_status(mvm, desc, hdr, skb, &phy_data, queue);22972298if (sta) {2299struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);2300struct ieee80211_vif *tx_blocked_vif =2301rcu_dereference(mvm->csa_tx_blocked_vif);2302u8 baid = (u8)((le32_to_cpu(desc->reorder_data) &2303IWL_RX_MPDU_REORDER_BAID_MASK) >>2304IWL_RX_MPDU_REORDER_BAID_SHIFT);2305struct iwl_fw_dbg_trigger_tlv *trig;2306struct ieee80211_vif *vif = mvmsta->vif;23072308if (!mvm->tcm.paused && len >= sizeof(*hdr) &&2309!is_multicast_ether_addr(hdr->addr1) &&2310ieee80211_is_data(hdr->frame_control) &&2311time_after(jiffies, mvm->tcm.ts + MVM_TCM_PERIOD))2312schedule_delayed_work(&mvm->tcm.work, 0);23132314/*2315* We have tx blocked stations (with CS bit). If we heard2316* frames from a blocked station on a new channel we can2317* TX to it again.2318*/2319if (unlikely(tx_blocked_vif) && tx_blocked_vif == vif) {2320struct iwl_mvm_vif *mvmvif =2321iwl_mvm_vif_from_mac80211(tx_blocked_vif);2322struct iwl_rx_sta_csa rx_sta_csa = {2323.all_sta_unblocked = true,2324.vif = tx_blocked_vif,2325};23262327if (mvmvif->csa_target_freq == rx_status->freq)2328iwl_mvm_sta_modify_disable_tx_ap(mvm, sta,2329false);2330ieee80211_iterate_stations_atomic(mvm->hw,2331iwl_mvm_rx_get_sta_block_tx,2332&rx_sta_csa);23332334if (rx_sta_csa.all_sta_unblocked) {2335RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);2336/* Unblock BCAST / MCAST station */2337iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);2338cancel_delayed_work(&mvm->cs_tx_unblock_dwork);2339}2340}23412342rs_update_last_rssi(mvm, mvmsta, rx_status);23432344trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,2345ieee80211_vif_to_wdev(vif),2346FW_DBG_TRIGGER_RSSI);23472348if (trig && ieee80211_is_beacon(hdr->frame_control)) {2349struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;2350s32 rssi;23512352rssi_trig = (void *)trig->data;2353rssi = le32_to_cpu(rssi_trig->rssi);23542355if (rx_status->signal < rssi)2356iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,2357#if defined(__linux__)2358NULL);2359#elif defined(__FreeBSD__)2360"");2361#endif2362}23632364if (ieee80211_is_data(hdr->frame_control))2365iwl_mvm_rx_csum(mvm, sta, skb, pkt);23662367if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {2368IWL_DEBUG_DROP(mvm, "Dropping duplicate packet 0x%x\n",2369le16_to_cpu(hdr->seq_ctrl));2370kfree_skb(skb);2371goto out;2372}23732374/*2375* Our hardware de-aggregates AMSDUs but copies the mac header2376* as it to the de-aggregated MPDUs. We need to turn off the2377* AMSDU bit in the QoS control ourselves.2378* In addition, HW reverses addr3 and addr4 - reverse it back.2379*/2380if ((desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&2381!WARN_ON(!ieee80211_is_data_qos(hdr->frame_control))) {2382u8 *qc = ieee80211_get_qos_ctl(hdr);23832384*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;23852386if (mvm->trans->mac_cfg->device_family ==2387IWL_DEVICE_FAMILY_9000) {2388iwl_mvm_flip_address(hdr->addr3);23892390if (ieee80211_has_a4(hdr->frame_control))2391iwl_mvm_flip_address(hdr->addr4);2392}2393}2394if (baid != IWL_RX_REORDER_DATA_INVALID_BAID) {2395u32 reorder_data = le32_to_cpu(desc->reorder_data);23962397iwl_mvm_agg_rx_received(mvm, reorder_data, baid);2398}23992400if (ieee80211_is_data(hdr->frame_control)) {2401u8 sub_frame_idx = desc->amsdu_info &2402IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;24032404/* 0 means not an A-MSDU, and 1 means a new A-MSDU */2405if (!sub_frame_idx || sub_frame_idx == 1)2406iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false,2407queue);2408}2409}24102411/* management stuff on default queue */2412if (!queue) {2413if (unlikely((ieee80211_is_beacon(hdr->frame_control) ||2414ieee80211_is_probe_resp(hdr->frame_control)) &&2415mvm->sched_scan_pass_all ==2416SCHED_SCAN_PASS_ALL_ENABLED))2417mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND;24182419if (unlikely(ieee80211_is_beacon(hdr->frame_control) ||2420ieee80211_is_probe_resp(hdr->frame_control)))2421rx_status->boottime_ns = ktime_get_boottime_ns();2422}24232424if (iwl_mvm_create_skb(mvm, skb, hdr, len, crypt_len, rxb)) {2425kfree_skb(skb);2426goto out;2427}24282429if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&2430likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&2431likely(!iwl_mvm_mei_filter_scan(mvm, skb))) {2432if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&2433(desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&2434!(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))2435rx_status->flag |= RX_FLAG_AMSDU_MORE;24362437iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);2438}2439out:2440rcu_read_unlock();2441}24422443void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,2444struct iwl_rx_cmd_buffer *rxb, int queue)2445{2446struct ieee80211_rx_status *rx_status;2447struct iwl_rx_packet *pkt = rxb_addr(rxb);2448struct iwl_rx_no_data_ver_3 *desc = (void *)pkt->data;2449u32 rssi;2450struct ieee80211_sta *sta = NULL;2451struct sk_buff *skb;2452struct iwl_mvm_rx_phy_data phy_data;2453u32 format;24542455if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))2456return;24572458if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(struct iwl_rx_no_data)))2459return;24602461rssi = le32_to_cpu(desc->rssi);2462phy_data.d0 = desc->phy_info[0];2463phy_data.d1 = desc->phy_info[1];2464phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;2465phy_data.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);2466phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);2467phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);2468phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);2469phy_data.with_data = false;2470phy_data.rx_vec[0] = desc->rx_vec[0];2471phy_data.rx_vec[1] = desc->rx_vec[1];24722473phy_data.rate_n_flags = iwl_mvm_v3_rate_from_fw(desc->rate,2474mvm->fw_rates_ver);24752476format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;24772478if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,2479RX_NO_DATA_NOTIF, 0) >= 3) {2480if (unlikely(iwl_rx_packet_payload_len(pkt) <2481sizeof(struct iwl_rx_no_data_ver_3)))2482/* invalid len for ver 3 */2483return;2484phy_data.rx_vec[2] = desc->rx_vec[2];2485phy_data.rx_vec[3] = desc->rx_vec[3];2486} else {2487if (format == RATE_MCS_MOD_TYPE_EHT)2488/* no support for EHT before version 3 API */2489return;2490}24912492/* Dont use dev_alloc_skb(), we'll have enough headroom once2493* ieee80211_hdr pulled.2494*/2495skb = alloc_skb(128, GFP_ATOMIC);2496if (!skb) {2497IWL_ERR(mvm, "alloc_skb failed\n");2498return;2499}25002501rx_status = IEEE80211_SKB_RXCB(skb);25022503/* 0-length PSDU */2504rx_status->flag |= RX_FLAG_NO_PSDU;25052506/* mark as failed PLCP on any errors to skip checks in mac80211 */2507if (le32_get_bits(desc->info, RX_NO_DATA_INFO_ERR_MSK) !=2508RX_NO_DATA_INFO_ERR_NONE)2509rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;25102511switch (le32_get_bits(desc->info, RX_NO_DATA_INFO_TYPE_MSK)) {2512case RX_NO_DATA_INFO_TYPE_NDP:2513rx_status->zero_length_psdu_type =2514IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;2515break;2516case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:2517case RX_NO_DATA_INFO_TYPE_TB_UNMATCHED:2518rx_status->zero_length_psdu_type =2519IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;2520break;2521default:2522rx_status->zero_length_psdu_type =2523IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;2524break;2525}25262527rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :2528NL80211_BAND_2GHZ;25292530iwl_mvm_rx_fill_status(mvm, NULL, NULL, skb, &phy_data, queue);25312532/* no more radio tap info should be put after this point.2533*2534* We mark it as mac header, for upper layers to know where2535* all radio tap header ends.2536*2537* Since data doesn't move data while putting data on skb and that is2538* the only way we use, data + len is the next place that hdr would be put2539*/2540skb_set_mac_header(skb, skb->len);25412542/*2543* Override the nss from the rx_vec since the rate_n_flags has2544* only 2 bits for the nss which gives a max of 4 ss but there2545* may be up to 8 spatial streams.2546*/2547switch (format) {2548case RATE_MCS_MOD_TYPE_VHT:2549rx_status->nss =2550le32_get_bits(desc->rx_vec[0],2551RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;2552break;2553case RATE_MCS_MOD_TYPE_HE:2554rx_status->nss =2555le32_get_bits(desc->rx_vec[0],2556RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;2557break;2558case RATE_MCS_MOD_TYPE_EHT:2559rx_status->nss =2560le32_get_bits(desc->rx_vec[2],2561RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1;2562}25632564rcu_read_lock();2565ieee80211_rx_napi(mvm->hw, sta, skb, napi);2566rcu_read_unlock();2567}25682569void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,2570struct iwl_rx_cmd_buffer *rxb, int queue)2571{2572struct iwl_rx_packet *pkt = rxb_addr(rxb);2573struct iwl_frame_release *release = (void *)pkt->data;25742575if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*release)))2576return;25772578iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,2579le16_to_cpu(release->nssn),2580queue);2581}25822583void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,2584struct iwl_rx_cmd_buffer *rxb, int queue)2585{2586struct iwl_rx_packet *pkt = rxb_addr(rxb);2587struct iwl_bar_frame_release *release = (void *)pkt->data;2588struct iwl_mvm_baid_data *baid_data;2589u32 pkt_len = iwl_rx_packet_payload_len(pkt);2590unsigned int baid, nssn, sta_id, tid;25912592if (IWL_FW_CHECK(mvm, pkt_len < sizeof(*release),2593"Unexpected frame release notif size %d (expected %zu)\n",2594pkt_len, sizeof(*release)))2595return;25962597baid = le32_get_bits(release->ba_info,2598IWL_BAR_FRAME_RELEASE_BAID_MASK);2599nssn = le32_get_bits(release->ba_info,2600IWL_BAR_FRAME_RELEASE_NSSN_MASK);2601sta_id = le32_get_bits(release->sta_tid,2602IWL_BAR_FRAME_RELEASE_STA_MASK);2603tid = le32_get_bits(release->sta_tid,2604IWL_BAR_FRAME_RELEASE_TID_MASK);26052606if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||2607baid >= ARRAY_SIZE(mvm->baid_map)))2608return;26092610rcu_read_lock();2611baid_data = rcu_dereference(mvm->baid_map[baid]);2612if (!baid_data) {2613IWL_DEBUG_RX(mvm,2614"Got valid BAID %d but not allocated, invalid BAR release!\n",2615baid);2616goto out;2617}26182619if (WARN(tid != baid_data->tid || sta_id > IWL_STATION_COUNT_MAX ||2620!(baid_data->sta_mask & BIT(sta_id)),2621"baid 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",2622baid, baid_data->sta_mask, baid_data->tid, sta_id,2623tid))2624goto out;26252626IWL_DEBUG_DROP(mvm, "Received a BAR, expect packet loss: nssn %d\n",2627nssn);26282629iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue);2630out:2631rcu_read_unlock();2632}26332634void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,2635struct iwl_rx_cmd_buffer *rxb)2636{2637struct iwl_rx_packet *pkt = rxb_addr(rxb);2638/* MAC or link ID in v1/v2, but driver has the IDs equal */2639struct iwl_beacon_filter_notif *notif = (void *)pkt->data;2640u32 id = le32_to_cpu(notif->link_id);2641struct iwl_mvm_vif *mvm_vif;2642struct ieee80211_vif *vif;26432644/* >= means AUX MAC/link ID, no energy correction needed then */2645if (IWL_FW_CHECK(mvm, id >= ARRAY_SIZE(mvm->vif_id_to_mac),2646"invalid link ID %d\n", id))2647return;26482649vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);2650if (!vif)2651return;26522653mvm_vif = iwl_mvm_vif_from_mac80211(vif);26542655mvm_vif->deflink.average_beacon_energy =2656le32_to_cpu(notif->average_energy);2657}265826592660