cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rx.c (32380B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2/*
      3 * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
      4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
      5 * Copyright (C) 2016-2017 Intel Deutschland GmbH
      6 */
      7#include <asm/unaligned.h>
      8#include <linux/etherdevice.h>
      9#include <linux/skbuff.h>
     10#include "iwl-trans.h"
     11#include "mvm.h"
     12#include "fw-api.h"
     13
     14/*
     15 * iwl_mvm_rx_rx_phy_cmd - REPLY_RX_PHY_CMD handler
     16 *
     17 * Copies the phy information in mvm->last_phy_info, it will be used when the
     18 * actual data will come from the fw in the next packet.
     19 */
     20void iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
     21{
     22	struct iwl_rx_packet *pkt = rxb_addr(rxb);
     23	unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
     24
     25	if (unlikely(pkt_len < sizeof(mvm->last_phy_info)))
     26		return;
     27
     28	memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info));
     29	mvm->ampdu_ref++;
     30
     31#ifdef CONFIG_IWLWIFI_DEBUGFS
     32	if (mvm->last_phy_info.phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
     33		spin_lock(&mvm->drv_stats_lock);
     34		mvm->drv_rx_stats.ampdu_count++;
     35		spin_unlock(&mvm->drv_stats_lock);
     36	}
     37#endif
     38}
     39
     40/*
     41 * iwl_mvm_pass_packet_to_mac80211 - builds the packet for mac80211
     42 *
     43 * Adds the rxb to a new skb and give it to mac80211
     44 */
     45static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
     46					    struct ieee80211_sta *sta,
     47					    struct napi_struct *napi,
     48					    struct sk_buff *skb,
     49					    struct ieee80211_hdr *hdr, u16 len,
     50					    u8 crypt_len,
     51					    struct iwl_rx_cmd_buffer *rxb)
     52{
     53	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
     54	unsigned int fraglen;
     55
     56	/*
     57	 * The 'hdrlen' (plus the 8 bytes for the SNAP and the crypt_len,
     58	 * but those are all multiples of 4 long) all goes away, but we
     59	 * want the *end* of it, which is going to be the start of the IP
     60	 * header, to be aligned when it gets pulled in.
     61	 * The beginning of the skb->data is aligned on at least a 4-byte
     62	 * boundary after allocation. Everything here is aligned at least
     63	 * on a 2-byte boundary so we can just take hdrlen & 3 and pad by
     64	 * the result.
     65	 */
     66	skb_reserve(skb, hdrlen & 3);
     67
     68	/* If frame is small enough to fit in skb->head, pull it completely.
     69	 * If not, only pull ieee80211_hdr (including crypto if present, and
     70	 * an additional 8 bytes for SNAP/ethertype, see below) so that
     71	 * splice() or TCP coalesce are more efficient.
     72	 *
     73	 * Since, in addition, ieee80211_data_to_8023() always pull in at
     74	 * least 8 bytes (possibly more for mesh) we can do the same here
     75	 * to save the cost of doing it later. That still doesn't pull in
     76	 * the actual IP header since the typical case has a SNAP header.
     77	 * If the latter changes (there are efforts in the standards group
     78	 * to do so) we should revisit this and ieee80211_data_to_8023().
     79	 */
     80	hdrlen = (len <= skb_tailroom(skb)) ? len : hdrlen + crypt_len + 8;
     81
     82	skb_put_data(skb, hdr, hdrlen);
     83	fraglen = len - hdrlen;
     84
     85	if (fraglen) {
     86		int offset = (u8 *)hdr + hdrlen -
     87			     (u8 *)rxb_addr(rxb) + rxb_offset(rxb);
     88
     89		skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
     90				fraglen, rxb->truesize);
     91	}
     92
     93	ieee80211_rx_napi(mvm->hw, sta, skb, napi);
     94}
     95
     96/*
     97 * iwl_mvm_get_signal_strength - use new rx PHY INFO API
     98 * values are reported by the fw as positive values - need to negate
     99 * to obtain their dBM.  Account for missing antennas by replacing 0
    100 * values by -256dBm: practically 0 power and a non-feasible 8 bit value.
    101 */
    102static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
    103					struct iwl_rx_phy_info *phy_info,
    104					struct ieee80211_rx_status *rx_status)
    105{
    106	int energy_a, energy_b, max_energy;
    107	u32 val;
    108
    109	val =
    110	    le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
    111	energy_a = (val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
    112						IWL_RX_INFO_ENERGY_ANT_A_POS;
    113	energy_a = energy_a ? -energy_a : S8_MIN;
    114	energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
    115						IWL_RX_INFO_ENERGY_ANT_B_POS;
    116	energy_b = energy_b ? -energy_b : S8_MIN;
    117	max_energy = max(energy_a, energy_b);
    118
    119	IWL_DEBUG_STATS(mvm, "energy In A %d B %d  , and max %d\n",
    120			energy_a, energy_b, max_energy);
    121
    122	rx_status->signal = max_energy;
    123	rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
    124				RX_RES_PHY_FLAGS_ANTENNA)
    125					>> RX_RES_PHY_FLAGS_ANTENNA_POS;
    126	rx_status->chain_signal[0] = energy_a;
    127	rx_status->chain_signal[1] = energy_b;
    128}
    129
    130/*
    131 * iwl_mvm_set_mac80211_rx_flag - translate fw status to mac80211 format
    132 * @mvm: the mvm object
    133 * @hdr: 80211 header
    134 * @stats: status in mac80211's format
    135 * @rx_pkt_status: status coming from fw
    136 *
    137 * returns non 0 value if the packet should be dropped
    138 */
    139static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
    140					struct ieee80211_hdr *hdr,
    141					struct ieee80211_rx_status *stats,
    142					u32 rx_pkt_status,
    143					u8 *crypt_len)
    144{
    145	if (!ieee80211_has_protected(hdr->frame_control) ||
    146	    (rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
    147			     RX_MPDU_RES_STATUS_SEC_NO_ENC)
    148		return 0;
    149
    150	/* packet was encrypted with unknown alg */
    151	if ((rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
    152					RX_MPDU_RES_STATUS_SEC_ENC_ERR)
    153		return 0;
    154
    155	switch (rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) {
    156	case RX_MPDU_RES_STATUS_SEC_CCM_ENC:
    157		/* alg is CCM: check MIC only */
    158		if (!(rx_pkt_status & RX_MPDU_RES_STATUS_MIC_OK))
    159			return -1;
    160
    161		stats->flag |= RX_FLAG_DECRYPTED;
    162		*crypt_len = IEEE80211_CCMP_HDR_LEN;
    163		return 0;
    164
    165	case RX_MPDU_RES_STATUS_SEC_TKIP_ENC:
    166		/* Don't drop the frame and decrypt it in SW */
    167		if (!fw_has_api(&mvm->fw->ucode_capa,
    168				IWL_UCODE_TLV_API_DEPRECATE_TTAK) &&
    169		    !(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
    170			return 0;
    171		*crypt_len = IEEE80211_TKIP_IV_LEN;
    172		fallthrough;
    173
    174	case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
    175		if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK))
    176			return -1;
    177
    178		stats->flag |= RX_FLAG_DECRYPTED;
    179		if ((rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
    180				RX_MPDU_RES_STATUS_SEC_WEP_ENC)
    181			*crypt_len = IEEE80211_WEP_IV_LEN;
    182		return 0;
    183
    184	case RX_MPDU_RES_STATUS_SEC_EXT_ENC:
    185		if (!(rx_pkt_status & RX_MPDU_RES_STATUS_MIC_OK))
    186			return -1;
    187		stats->flag |= RX_FLAG_DECRYPTED;
    188		return 0;
    189
    190	default:
    191		/* Expected in monitor (not having the keys) */
    192		if (!mvm->monitor_on)
    193			IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
    194	}
    195
    196	return 0;
    197}
    198
    199static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
    200				  struct ieee80211_sta *sta,
    201				  struct ieee80211_hdr *hdr, u32 len,
    202				  struct iwl_rx_phy_info *phy_info,
    203				  u32 rate_n_flags)
    204{
    205	struct iwl_mvm_sta *mvmsta;
    206	struct iwl_mvm_tcm_mac *mdata;
    207	int mac;
    208	int ac = IEEE80211_AC_BE; /* treat non-QoS as BE */
    209	struct iwl_mvm_vif *mvmvif;
    210	/* expected throughput in 100Kbps, single stream, 20 MHz */
    211	static const u8 thresh_tpt[] = {
    212		9, 18, 30, 42, 60, 78, 90, 96, 120, 135,
    213	};
    214	u16 thr;
    215
    216	if (ieee80211_is_data_qos(hdr->frame_control))
    217		ac = tid_to_mac80211_ac[ieee80211_get_tid(hdr)];
    218
    219	mvmsta = iwl_mvm_sta_from_mac80211(sta);
    220	mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK;
    221
    222	if (time_after(jiffies, mvm->tcm.ts + MVM_TCM_PERIOD))
    223		schedule_delayed_work(&mvm->tcm.work, 0);
    224	mdata = &mvm->tcm.data[mac];
    225	mdata->rx.pkts[ac]++;
    226
    227	/* count the airtime only once for each ampdu */
    228	if (mdata->rx.last_ampdu_ref != mvm->ampdu_ref) {
    229		mdata->rx.last_ampdu_ref = mvm->ampdu_ref;
    230		mdata->rx.airtime += le16_to_cpu(phy_info->frame_time);
    231	}
    232
    233	if (!(rate_n_flags & (RATE_MCS_HT_MSK_V1 | RATE_MCS_VHT_MSK_V1)))
    234		return;
    235
    236	mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
    237
    238	if (mdata->opened_rx_ba_sessions ||
    239	    mdata->uapsd_nonagg_detect.detected ||
    240	    (!mvmvif->queue_params[IEEE80211_AC_VO].uapsd &&
    241	     !mvmvif->queue_params[IEEE80211_AC_VI].uapsd &&
    242	     !mvmvif->queue_params[IEEE80211_AC_BE].uapsd &&
    243	     !mvmvif->queue_params[IEEE80211_AC_BK].uapsd) ||
    244	    mvmsta->sta_id != mvmvif->ap_sta_id)
    245		return;
    246
    247	if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
    248		thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1];
    249		thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK_V1) >>
    250					RATE_HT_MCS_NSS_POS_V1);
    251	} else {
    252		if (WARN_ON((rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK) >=
    253				ARRAY_SIZE(thresh_tpt)))
    254			return;
    255		thr = thresh_tpt[rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK];
    256		thr *= 1 + ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
    257					RATE_VHT_MCS_NSS_POS);
    258	}
    259
    260	thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) >>
    261				RATE_MCS_CHAN_WIDTH_POS);
    262
    263	mdata->uapsd_nonagg_detect.rx_bytes += len;
    264	ewma_rate_add(&mdata->uapsd_nonagg_detect.rate, thr);
    265}
    266
    267static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
    268			    struct sk_buff *skb,
    269			    u32 status)
    270{
    271	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
    272	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
    273
    274	if (mvmvif->features & NETIF_F_RXCSUM &&
    275	    status & RX_MPDU_RES_STATUS_CSUM_DONE &&
    276	    status & RX_MPDU_RES_STATUS_CSUM_OK)
    277		skb->ip_summed = CHECKSUM_UNNECESSARY;
    278}
    279
    280/*
    281 * iwl_mvm_rx_rx_mpdu - REPLY_RX_MPDU_CMD handler
    282 *
    283 * Handles the actual data of the Rx packet from the fw
    284 */
    285void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
    286			struct iwl_rx_cmd_buffer *rxb)
    287{
    288	struct ieee80211_hdr *hdr;
    289	struct ieee80211_rx_status *rx_status;
    290	struct iwl_rx_packet *pkt = rxb_addr(rxb);
    291	struct iwl_rx_phy_info *phy_info;
    292	struct iwl_rx_mpdu_res_start *rx_res;
    293	struct ieee80211_sta *sta = NULL;
    294	struct sk_buff *skb;
    295	u32 len, pkt_len = iwl_rx_packet_payload_len(pkt);
    296	u32 rate_n_flags;
    297	u32 rx_pkt_status;
    298	u8 crypt_len = 0;
    299
    300	if (unlikely(pkt_len < sizeof(*rx_res))) {
    301		IWL_DEBUG_DROP(mvm, "Bad REPLY_RX_MPDU_CMD size\n");
    302		return;
    303	}
    304
    305	phy_info = &mvm->last_phy_info;
    306	rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
    307	hdr = (struct ieee80211_hdr *)(pkt->data + sizeof(*rx_res));
    308	len = le16_to_cpu(rx_res->byte_count);
    309
    310	if (unlikely(len + sizeof(*rx_res) + sizeof(__le32) > pkt_len)) {
    311		IWL_DEBUG_DROP(mvm, "FW lied about packet len\n");
    312		return;
    313	}
    314
    315	rx_pkt_status = get_unaligned_le32((__le32 *)
    316		(pkt->data + sizeof(*rx_res) + len));
    317
    318	/* Dont use dev_alloc_skb(), we'll have enough headroom once
    319	 * ieee80211_hdr pulled.
    320	 */
    321	skb = alloc_skb(128, GFP_ATOMIC);
    322	if (!skb) {
    323		IWL_ERR(mvm, "alloc_skb failed\n");
    324		return;
    325	}
    326
    327	rx_status = IEEE80211_SKB_RXCB(skb);
    328
    329	/*
    330	 * Keep packets with CRC errors (and with overrun) for monitor mode
    331	 * (otherwise the firmware discards them) but mark them as bad.
    332	 */
    333	if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) ||
    334	    !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) {
    335		IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status);
    336		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
    337	}
    338
    339	/* This will be used in several places later */
    340	rate_n_flags = le32_to_cpu(phy_info->rate_n_flags);
    341
    342	/* rx_status carries information about the packet to mac80211 */
    343	rx_status->mactime = le64_to_cpu(phy_info->timestamp);
    344	rx_status->device_timestamp = le32_to_cpu(phy_info->system_timestamp);
    345	rx_status->band =
    346		(phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
    347				NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
    348	rx_status->freq =
    349		ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel),
    350					       rx_status->band);
    351
    352	/* TSF as indicated by the firmware  is at INA time */
    353	rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
    354
    355	iwl_mvm_get_signal_strength(mvm, phy_info, rx_status);
    356
    357	IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status->signal,
    358			      (unsigned long long)rx_status->mactime);
    359
    360	rcu_read_lock();
    361	if (rx_pkt_status & RX_MPDU_RES_STATUS_SRC_STA_FOUND) {
    362		u32 id = rx_pkt_status & RX_MPDU_RES_STATUS_STA_ID_MSK;
    363
    364		id >>= RX_MDPU_RES_STATUS_STA_ID_SHIFT;
    365
    366		if (!WARN_ON_ONCE(id >= mvm->fw->ucode_capa.num_stations)) {
    367			sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
    368			if (IS_ERR(sta))
    369				sta = NULL;
    370		}
    371	} else if (!is_multicast_ether_addr(hdr->addr2)) {
    372		/* This is fine since we prevent two stations with the same
    373		 * address from being added.
    374		 */
    375		sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
    376	}
    377
    378	if (sta) {
    379		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
    380		struct ieee80211_vif *vif = mvmsta->vif;
    381		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    382
    383		/*
    384		 * Don't even try to decrypt a MCAST frame that was received
    385		 * before the managed vif is authorized, we'd fail anyway.
    386		 */
    387		if (vif->type == NL80211_IFTYPE_STATION &&
    388		    !mvmvif->authorized &&
    389		    is_multicast_ether_addr(hdr->addr1)) {
    390			IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n");
    391			kfree_skb(skb);
    392			rcu_read_unlock();
    393			return;
    394		}
    395	}
    396
    397	/*
    398	 * drop the packet if it has failed being decrypted by HW
    399	 */
    400	if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
    401					 &crypt_len)) {
    402		IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
    403			       rx_pkt_status);
    404		kfree_skb(skb);
    405		rcu_read_unlock();
    406		return;
    407	}
    408
    409	if (sta) {
    410		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
    411		struct ieee80211_vif *tx_blocked_vif =
    412			rcu_dereference(mvm->csa_tx_blocked_vif);
    413		struct iwl_fw_dbg_trigger_tlv *trig;
    414		struct ieee80211_vif *vif = mvmsta->vif;
    415
    416		/* We have tx blocked stations (with CS bit). If we heard
    417		 * frames from a blocked station on a new channel we can
    418		 * TX to it again.
    419		 */
    420		if (unlikely(tx_blocked_vif) && vif == tx_blocked_vif) {
    421			struct iwl_mvm_vif *mvmvif =
    422				iwl_mvm_vif_from_mac80211(tx_blocked_vif);
    423
    424			if (mvmvif->csa_target_freq == rx_status->freq)
    425				iwl_mvm_sta_modify_disable_tx_ap(mvm, sta,
    426								 false);
    427		}
    428
    429		rs_update_last_rssi(mvm, mvmsta, rx_status);
    430
    431		trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
    432					     ieee80211_vif_to_wdev(vif),
    433					     FW_DBG_TRIGGER_RSSI);
    434
    435		if (trig && ieee80211_is_beacon(hdr->frame_control)) {
    436			struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;
    437			s32 rssi;
    438
    439			rssi_trig = (void *)trig->data;
    440			rssi = le32_to_cpu(rssi_trig->rssi);
    441
    442			if (rx_status->signal < rssi)
    443				iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
    444							NULL);
    445		}
    446
    447		if (!mvm->tcm.paused && len >= sizeof(*hdr) &&
    448		    !is_multicast_ether_addr(hdr->addr1) &&
    449		    ieee80211_is_data(hdr->frame_control))
    450			iwl_mvm_rx_handle_tcm(mvm, sta, hdr, len, phy_info,
    451					      rate_n_flags);
    452
    453		if (ieee80211_is_data(hdr->frame_control))
    454			iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
    455	}
    456	rcu_read_unlock();
    457
    458	/* set the preamble flag if appropriate */
    459	if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
    460		rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
    461
    462	if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
    463		/*
    464		 * We know which subframes of an A-MPDU belong
    465		 * together since we get a single PHY response
    466		 * from the firmware for all of them
    467		 */
    468		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
    469		rx_status->ampdu_reference = mvm->ampdu_ref;
    470	}
    471
    472	/* Set up the HT phy flags */
    473	switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) {
    474	case RATE_MCS_CHAN_WIDTH_20:
    475		break;
    476	case RATE_MCS_CHAN_WIDTH_40:
    477		rx_status->bw = RATE_INFO_BW_40;
    478		break;
    479	case RATE_MCS_CHAN_WIDTH_80:
    480		rx_status->bw = RATE_INFO_BW_80;
    481		break;
    482	case RATE_MCS_CHAN_WIDTH_160:
    483		rx_status->bw = RATE_INFO_BW_160;
    484		break;
    485	}
    486	if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) &&
    487	    rate_n_flags & RATE_MCS_SGI_MSK_V1)
    488		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
    489	if (rate_n_flags & RATE_HT_MCS_GF_MSK)
    490		rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
    491	if (rate_n_flags & RATE_MCS_LDPC_MSK_V1)
    492		rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
    493	if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
    494		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
    495				RATE_MCS_STBC_POS;
    496		rx_status->encoding = RX_ENC_HT;
    497		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1;
    498		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
    499	} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
    500		u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
    501				RATE_MCS_STBC_POS;
    502		rx_status->nss =
    503			((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
    504						RATE_VHT_MCS_NSS_POS) + 1;
    505		rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
    506		rx_status->encoding = RX_ENC_VHT;
    507		rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
    508		if (rate_n_flags & RATE_MCS_BF_MSK)
    509			rx_status->enc_flags |= RX_ENC_FLAG_BF;
    510	} else {
    511		int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
    512							       rx_status->band);
    513
    514		if (WARN(rate < 0 || rate > 0xFF,
    515			 "Invalid rate flags 0x%x, band %d,\n",
    516			 rate_n_flags, rx_status->band)) {
    517			kfree_skb(skb);
    518			return;
    519		}
    520		rx_status->rate_idx = rate;
    521	}
    522
    523#ifdef CONFIG_IWLWIFI_DEBUGFS
    524	iwl_mvm_update_frame_stats(mvm, rate_n_flags,
    525				   rx_status->flag & RX_FLAG_AMPDU_DETAILS);
    526#endif
    527
    528	if (unlikely((ieee80211_is_beacon(hdr->frame_control) ||
    529		      ieee80211_is_probe_resp(hdr->frame_control)) &&
    530		     mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED))
    531		mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND;
    532
    533	if (unlikely(ieee80211_is_beacon(hdr->frame_control) ||
    534		     ieee80211_is_probe_resp(hdr->frame_control)))
    535		rx_status->boottime_ns = ktime_get_boottime_ns();
    536
    537	iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len,
    538					crypt_len, rxb);
    539}
    540
    541struct iwl_mvm_stat_data {
    542	struct iwl_mvm *mvm;
    543	__le32 flags;
    544	__le32 mac_id;
    545	u8 beacon_filter_average_energy;
    546	__le32 *beacon_counter;
    547	u8 *beacon_average_energy;
    548};
    549
    550struct iwl_mvm_stat_data_all_macs {
    551	struct iwl_mvm *mvm;
    552	__le32 flags;
    553	struct iwl_statistics_ntfy_per_mac *per_mac_stats;
    554};
    555
    556static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
    557{
    558	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    559	struct iwl_mvm *mvm = mvmvif->mvm;
    560	int thold = vif->bss_conf.cqm_rssi_thold;
    561	int hyst = vif->bss_conf.cqm_rssi_hyst;
    562	int last_event;
    563
    564	if (sig == 0) {
    565		IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
    566		return;
    567	}
    568
    569	mvmvif->bf_data.ave_beacon_signal = sig;
    570
    571	/* BT Coex */
    572	if (mvmvif->bf_data.bt_coex_min_thold !=
    573	    mvmvif->bf_data.bt_coex_max_thold) {
    574		last_event = mvmvif->bf_data.last_bt_coex_event;
    575		if (sig > mvmvif->bf_data.bt_coex_max_thold &&
    576		    (last_event <= mvmvif->bf_data.bt_coex_min_thold ||
    577		     last_event == 0)) {
    578			mvmvif->bf_data.last_bt_coex_event = sig;
    579			IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n",
    580				     sig);
    581			iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH);
    582		} else if (sig < mvmvif->bf_data.bt_coex_min_thold &&
    583			   (last_event >= mvmvif->bf_data.bt_coex_max_thold ||
    584			    last_event == 0)) {
    585			mvmvif->bf_data.last_bt_coex_event = sig;
    586			IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n",
    587				     sig);
    588			iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW);
    589		}
    590	}
    591
    592	if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
    593		return;
    594
    595	/* CQM Notification */
    596	last_event = mvmvif->bf_data.last_cqm_event;
    597	if (thold && sig < thold && (last_event == 0 ||
    598				     sig < last_event - hyst)) {
    599		mvmvif->bf_data.last_cqm_event = sig;
    600		IWL_DEBUG_RX(mvm, "cqm_iterator cqm low %d\n",
    601			     sig);
    602		ieee80211_cqm_rssi_notify(
    603			vif,
    604			NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
    605			sig,
    606			GFP_KERNEL);
    607	} else if (sig > thold &&
    608		   (last_event == 0 || sig > last_event + hyst)) {
    609		mvmvif->bf_data.last_cqm_event = sig;
    610		IWL_DEBUG_RX(mvm, "cqm_iterator cqm high %d\n",
    611			     sig);
    612		ieee80211_cqm_rssi_notify(
    613			vif,
    614			NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
    615			sig,
    616			GFP_KERNEL);
    617	}
    618}
    619
    620static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
    621				  struct ieee80211_vif *vif)
    622{
    623	struct iwl_mvm_stat_data *data = _data;
    624	int sig = -data->beacon_filter_average_energy;
    625	u16 id = le32_to_cpu(data->mac_id);
    626	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    627	u16 vif_id = mvmvif->id;
    628
    629	/* This doesn't need the MAC ID check since it's not taking the
    630	 * data copied into the "data" struct, but rather the data from
    631	 * the notification directly.
    632	 */
    633	mvmvif->beacon_stats.num_beacons =
    634		le32_to_cpu(data->beacon_counter[vif_id]);
    635	mvmvif->beacon_stats.avg_signal =
    636		-data->beacon_average_energy[vif_id];
    637
    638	if (mvmvif->id != id)
    639		return;
    640
    641	if (vif->type != NL80211_IFTYPE_STATION)
    642		return;
    643
    644	/* make sure that beacon statistics don't go backwards with TCM
    645	 * request to clear statistics
    646	 */
    647	if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
    648		mvmvif->beacon_stats.accu_num_beacons +=
    649			mvmvif->beacon_stats.num_beacons;
    650
    651	iwl_mvm_update_vif_sig(vif, sig);
    652}
    653
    654static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
    655					   struct ieee80211_vif *vif)
    656{
    657	struct iwl_mvm_stat_data_all_macs *data = _data;
    658	struct iwl_statistics_ntfy_per_mac *mac_stats;
    659	int sig;
    660	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    661	u16 vif_id = mvmvif->id;
    662
    663	if (WARN_ONCE(vif_id >= MAC_INDEX_AUX, "invalid vif id: %d", vif_id))
    664		return;
    665
    666	if (vif->type != NL80211_IFTYPE_STATION)
    667		return;
    668
    669	mac_stats = &data->per_mac_stats[vif_id];
    670
    671	mvmvif->beacon_stats.num_beacons =
    672		le32_to_cpu(mac_stats->beacon_counter);
    673	mvmvif->beacon_stats.avg_signal =
    674		-le32_to_cpu(mac_stats->beacon_average_energy);
    675
    676	/* make sure that beacon statistics don't go backwards with TCM
    677	 * request to clear statistics
    678	 */
    679	if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
    680		mvmvif->beacon_stats.accu_num_beacons +=
    681			mvmvif->beacon_stats.num_beacons;
    682
    683	sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
    684	iwl_mvm_update_vif_sig(vif, sig);
    685}
    686
    687static inline void
    688iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
    689{
    690	struct iwl_fw_dbg_trigger_tlv *trig;
    691	struct iwl_fw_dbg_trigger_stats *trig_stats;
    692	u32 trig_offset, trig_thold;
    693
    694	trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_STATS);
    695	if (!trig)
    696		return;
    697
    698	trig_stats = (void *)trig->data;
    699
    700	trig_offset = le32_to_cpu(trig_stats->stop_offset);
    701	trig_thold = le32_to_cpu(trig_stats->stop_threshold);
    702
    703	if (WARN_ON_ONCE(trig_offset >= iwl_rx_packet_payload_len(pkt)))
    704		return;
    705
    706	if (le32_to_cpup((__le32 *) (pkt->data + trig_offset)) < trig_thold)
    707		return;
    708
    709	iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, NULL);
    710}
    711
    712static void iwl_mvm_stats_energy_iter(void *_data,
    713				      struct ieee80211_sta *sta)
    714{
    715	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
    716	u8 *energy = _data;
    717	u32 sta_id = mvmsta->sta_id;
    718
    719	if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT_MAX, "sta_id %d >= %d",
    720		      sta_id, IWL_MVM_STATION_COUNT_MAX))
    721		return;
    722
    723	if (energy[sta_id])
    724		mvmsta->avg_energy = energy[sta_id];
    725
    726}
    727
    728static void
    729iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
    730			      __le32 *rx_bytes_le)
    731{
    732	int i;
    733
    734	spin_lock(&mvm->tcm.lock);
    735	for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
    736		struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[i];
    737		u32 rx_bytes = le32_to_cpu(rx_bytes_le[i]);
    738		u32 airtime = le32_to_cpu(air_time_le[i]);
    739
    740		mdata->rx.airtime += airtime;
    741		mdata->uapsd_nonagg_detect.rx_bytes += rx_bytes;
    742		if (airtime) {
    743			/* re-init every time to store rate from FW */
    744			ewma_rate_init(&mdata->uapsd_nonagg_detect.rate);
    745			ewma_rate_add(&mdata->uapsd_nonagg_detect.rate,
    746				      rx_bytes * 8 / airtime);
    747		}
    748	}
    749	spin_unlock(&mvm->tcm.lock);
    750}
    751
    752static void
    753iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
    754		     struct iwl_statistics_operational_ntfy *stats)
    755{
    756	struct iwl_mvm_stat_data_all_macs data = {
    757		.mvm = mvm,
    758		.flags = stats->flags,
    759		.per_mac_stats = stats->per_mac_stats,
    760	};
    761
    762	ieee80211_iterate_active_interfaces(mvm->hw,
    763					    IEEE80211_IFACE_ITER_NORMAL,
    764					    iwl_mvm_stat_iterator_all_macs,
    765					    &data);
    766}
    767
    768static void
    769iwl_mvm_stats_ver_14(struct iwl_mvm *mvm,
    770		     struct iwl_statistics_operational_ntfy_ver_14 *stats)
    771{
    772	struct iwl_mvm_stat_data data = {
    773		.mvm = mvm,
    774	};
    775
    776	u8 beacon_average_energy[MAC_INDEX_AUX];
    777	__le32 flags;
    778	int i;
    779
    780	flags = stats->flags;
    781
    782	data.mac_id = stats->mac_id;
    783	data.beacon_filter_average_energy =
    784		le32_to_cpu(stats->beacon_filter_average_energy);
    785	data.flags = flags;
    786	data.beacon_counter = stats->beacon_counter;
    787
    788	for (i = 0; i < ARRAY_SIZE(beacon_average_energy); i++)
    789		beacon_average_energy[i] =
    790			le32_to_cpu(stats->beacon_average_energy[i]);
    791
    792	data.beacon_average_energy = beacon_average_energy;
    793
    794	ieee80211_iterate_active_interfaces(mvm->hw,
    795					    IEEE80211_IFACE_ITER_NORMAL,
    796					    iwl_mvm_stat_iterator,
    797					    &data);
    798}
    799
    800static bool iwl_mvm_verify_stats_len(struct iwl_mvm *mvm,
    801				     struct iwl_rx_packet *pkt,
    802				     u32 expected_size)
    803{
    804	struct iwl_statistics_ntfy_hdr *hdr;
    805
    806	if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
    807		      "received invalid statistics size (%d)!, expected_size: %d\n",
    808		      iwl_rx_packet_payload_len(pkt), expected_size))
    809		return false;
    810
    811	hdr = (void *)&pkt->data;
    812
    813	if (WARN_ONCE((hdr->type & IWL_STATISTICS_TYPE_MSK) != FW_STATISTICS_OPERATIONAL ||
    814		      hdr->version !=
    815		      iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, STATISTICS_NOTIFICATION, 0),
    816		      "received unsupported hdr type %d, version %d\n",
    817		      hdr->type, hdr->version))
    818		return false;
    819
    820	if (WARN_ONCE(le16_to_cpu(hdr->size) != expected_size,
    821		      "received invalid statistics size in header (%d)!, expected_size: %d\n",
    822		      le16_to_cpu(hdr->size), expected_size))
    823		return false;
    824
    825	return true;
    826}
    827
    828static void
    829iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
    830				 struct iwl_rx_packet *pkt)
    831{
    832	u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
    833	__le32 air_time[MAC_INDEX_AUX];
    834	__le32 rx_bytes[MAC_INDEX_AUX];
    835	__le32 flags = 0;
    836	int i;
    837	u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
    838					      STATISTICS_NOTIFICATION, 0);
    839
    840	if (WARN_ONCE(notif_ver > 15,
    841		      "invalid statistics version id: %d\n", notif_ver))
    842		return;
    843
    844	if (notif_ver == 14) {
    845		struct iwl_statistics_operational_ntfy_ver_14 *stats =
    846			(void *)pkt->data;
    847
    848		if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
    849			return;
    850
    851		iwl_mvm_stats_ver_14(mvm, stats);
    852
    853		flags = stats->flags;
    854		mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
    855		mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
    856		mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
    857		mvm->radio_stats.on_time_scan =
    858			le64_to_cpu(stats->on_time_scan);
    859
    860		for (i = 0; i < ARRAY_SIZE(average_energy); i++)
    861			average_energy[i] = le32_to_cpu(stats->average_energy[i]);
    862
    863		for (i = 0; i < ARRAY_SIZE(air_time); i++) {
    864			air_time[i] = stats->air_time[i];
    865			rx_bytes[i] = stats->rx_bytes[i];
    866		}
    867	}
    868
    869	if (notif_ver == 15) {
    870		struct iwl_statistics_operational_ntfy *stats =
    871			(void *)pkt->data;
    872
    873		if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
    874			return;
    875
    876		iwl_mvm_stats_ver_15(mvm, stats);
    877
    878		flags = stats->flags;
    879		mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
    880		mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
    881		mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
    882		mvm->radio_stats.on_time_scan =
    883			le64_to_cpu(stats->on_time_scan);
    884
    885		for (i = 0; i < ARRAY_SIZE(average_energy); i++)
    886			average_energy[i] =
    887				le32_to_cpu(stats->per_sta_stats[i].average_energy);
    888
    889		for (i = 0; i < ARRAY_SIZE(air_time); i++) {
    890			air_time[i] = stats->per_mac_stats[i].air_time;
    891			rx_bytes[i] = stats->per_mac_stats[i].rx_bytes;
    892		}
    893	}
    894
    895	iwl_mvm_rx_stats_check_trigger(mvm, pkt);
    896
    897	ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
    898					  average_energy);
    899	/*
    900	 * Don't update in case the statistics are not cleared, since
    901	 * we will end up counting twice the same airtime, once in TCM
    902	 * request and once in statistics notification.
    903	 */
    904	if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
    905		iwl_mvm_update_tcm_from_stats(mvm, air_time, rx_bytes);
    906}
    907
    908void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
    909				  struct iwl_rx_packet *pkt)
    910{
    911	struct iwl_mvm_stat_data data = {
    912		.mvm = mvm,
    913	};
    914	__le32 *bytes, *air_time, flags;
    915	int expected_size;
    916	u8 *energy;
    917
    918	/* From ver 14 and up we use TLV statistics format */
    919	if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
    920				    STATISTICS_NOTIFICATION, 0) >= 14)
    921		return iwl_mvm_handle_rx_statistics_tlv(mvm, pkt);
    922
    923	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
    924		if (iwl_mvm_has_new_rx_api(mvm))
    925			expected_size = sizeof(struct iwl_notif_statistics_v11);
    926		else
    927			expected_size = sizeof(struct iwl_notif_statistics_v10);
    928	} else {
    929		expected_size = sizeof(struct iwl_notif_statistics);
    930	}
    931
    932	if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) != expected_size,
    933		      "received invalid statistics size (%d)!\n",
    934		      iwl_rx_packet_payload_len(pkt)))
    935		return;
    936
    937	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
    938		struct iwl_notif_statistics_v11 *stats = (void *)&pkt->data;
    939
    940		data.mac_id = stats->rx.general.mac_id;
    941		data.beacon_filter_average_energy =
    942			stats->general.common.beacon_filter_average_energy;
    943
    944		mvm->rx_stats_v3 = stats->rx;
    945
    946		mvm->radio_stats.rx_time =
    947			le64_to_cpu(stats->general.common.rx_time);
    948		mvm->radio_stats.tx_time =
    949			le64_to_cpu(stats->general.common.tx_time);
    950		mvm->radio_stats.on_time_rf =
    951			le64_to_cpu(stats->general.common.on_time_rf);
    952		mvm->radio_stats.on_time_scan =
    953			le64_to_cpu(stats->general.common.on_time_scan);
    954
    955		data.beacon_counter = stats->general.beacon_counter;
    956		data.beacon_average_energy =
    957			stats->general.beacon_average_energy;
    958		flags = stats->flag;
    959	} else {
    960		struct iwl_notif_statistics *stats = (void *)&pkt->data;
    961
    962		data.mac_id = stats->rx.general.mac_id;
    963		data.beacon_filter_average_energy =
    964			stats->general.common.beacon_filter_average_energy;
    965
    966		mvm->rx_stats = stats->rx;
    967
    968		mvm->radio_stats.rx_time =
    969			le64_to_cpu(stats->general.common.rx_time);
    970		mvm->radio_stats.tx_time =
    971			le64_to_cpu(stats->general.common.tx_time);
    972		mvm->radio_stats.on_time_rf =
    973			le64_to_cpu(stats->general.common.on_time_rf);
    974		mvm->radio_stats.on_time_scan =
    975			le64_to_cpu(stats->general.common.on_time_scan);
    976
    977		data.beacon_counter = stats->general.beacon_counter;
    978		data.beacon_average_energy =
    979			stats->general.beacon_average_energy;
    980		flags = stats->flag;
    981	}
    982	data.flags = flags;
    983
    984	iwl_mvm_rx_stats_check_trigger(mvm, pkt);
    985
    986	ieee80211_iterate_active_interfaces(mvm->hw,
    987					    IEEE80211_IFACE_ITER_NORMAL,
    988					    iwl_mvm_stat_iterator,
    989					    &data);
    990
    991	if (!iwl_mvm_has_new_rx_api(mvm))
    992		return;
    993
    994	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
    995		struct iwl_notif_statistics_v11 *v11 = (void *)&pkt->data;
    996
    997		energy = (void *)&v11->load_stats.avg_energy;
    998		bytes = (void *)&v11->load_stats.byte_count;
    999		air_time = (void *)&v11->load_stats.air_time;
   1000	} else {
   1001		struct iwl_notif_statistics *stats = (void *)&pkt->data;
   1002
   1003		energy = (void *)&stats->load_stats.avg_energy;
   1004		bytes = (void *)&stats->load_stats.byte_count;
   1005		air_time = (void *)&stats->load_stats.air_time;
   1006	}
   1007	ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
   1008					  energy);
   1009
   1010	/*
   1011	 * Don't update in case the statistics are not cleared, since
   1012	 * we will end up counting twice the same airtime, once in TCM
   1013	 * request and once in statistics notification.
   1014	 */
   1015	if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
   1016		iwl_mvm_update_tcm_from_stats(mvm, air_time, bytes);
   1017
   1018}
   1019
   1020void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
   1021{
   1022	iwl_mvm_handle_rx_statistics(mvm, rxb_addr(rxb));
   1023}
   1024
   1025void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
   1026				 struct iwl_rx_cmd_buffer *rxb)
   1027{
   1028	struct iwl_rx_packet *pkt = rxb_addr(rxb);
   1029	struct iwl_ba_window_status_notif *notif = (void *)pkt->data;
   1030	int i;
   1031
   1032	BUILD_BUG_ON(ARRAY_SIZE(notif->ra_tid) != BA_WINDOW_STREAMS_MAX);
   1033	BUILD_BUG_ON(ARRAY_SIZE(notif->mpdu_rx_count) != BA_WINDOW_STREAMS_MAX);
   1034	BUILD_BUG_ON(ARRAY_SIZE(notif->bitmap) != BA_WINDOW_STREAMS_MAX);
   1035	BUILD_BUG_ON(ARRAY_SIZE(notif->start_seq_num) != BA_WINDOW_STREAMS_MAX);
   1036
   1037	rcu_read_lock();
   1038	for (i = 0; i < BA_WINDOW_STREAMS_MAX; i++) {
   1039		struct ieee80211_sta *sta;
   1040		u8 sta_id, tid;
   1041		u64 bitmap;
   1042		u32 ssn;
   1043		u16 ratid;
   1044		u16 received_mpdu;
   1045
   1046		ratid = le16_to_cpu(notif->ra_tid[i]);
   1047		/* check that this TID is valid */
   1048		if (!(ratid & BA_WINDOW_STATUS_VALID_MSK))
   1049			continue;
   1050
   1051		received_mpdu = le16_to_cpu(notif->mpdu_rx_count[i]);
   1052		if (received_mpdu == 0)
   1053			continue;
   1054
   1055		tid = ratid & BA_WINDOW_STATUS_TID_MSK;
   1056		/* get the station */
   1057		sta_id = (ratid & BA_WINDOW_STATUS_STA_ID_MSK)
   1058			 >> BA_WINDOW_STATUS_STA_ID_POS;
   1059		sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
   1060		if (IS_ERR_OR_NULL(sta))
   1061			continue;
   1062		bitmap = le64_to_cpu(notif->bitmap[i]);
   1063		ssn = le32_to_cpu(notif->start_seq_num[i]);
   1064
   1065		/* update mac80211 with the bitmap for the reordering buffer */
   1066		ieee80211_mark_rx_ba_filtered_frames(sta, tid, ssn, bitmap,
   1067						     received_mpdu);
   1068	}
   1069	rcu_read_unlock();
   1070}