diff options
Diffstat (limited to 'sys/contrib/dev/iwlwifi/mvm/rx.c')
| -rw-r--r-- | sys/contrib/dev/iwlwifi/mvm/rx.c | 77 | 
1 files changed, 51 insertions, 26 deletions
| diff --git a/sys/contrib/dev/iwlwifi/mvm/rx.c b/sys/contrib/dev/iwlwifi/mvm/rx.c index 0802887fb261..f6127c0b5344 100644 --- a/sys/contrib/dev/iwlwifi/mvm/rx.c +++ b/sys/contrib/dev/iwlwifi/mvm/rx.c @@ -1,10 +1,10 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2024 Intel Corporation + * Copyright (C) 2012-2014, 2018-2025 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ -#include <asm/unaligned.h> +#include <linux/unaligned.h>  #include <linux/etherdevice.h>  #include <linux/skbuff.h>  #include "iwl-trans.h" @@ -499,8 +499,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,  	if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) &&  	    rate_n_flags & RATE_MCS_SGI_MSK_V1)  		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; -	if (rate_n_flags & RATE_HT_MCS_GF_MSK) -		rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;  	if (rate_n_flags & RATE_MCS_LDPC_MSK_V1)  		rx_status->enc_flags |= RX_ENC_FLAG_LDPC;  	if (rate_n_flags & RATE_MCS_HT_MSK_V1) { @@ -569,7 +567,8 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,  				    struct iwl_mvm_vif_link_info *link_info,  				    struct ieee80211_bss_conf *bss_conf)  { -	struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(vif)->mvm; +	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	struct iwl_mvm *mvm = mvmvif->mvm;  	int thold = bss_conf->cqm_rssi_thold;  	int hyst = bss_conf->cqm_rssi_hyst;  	int last_event; @@ -634,6 +633,13 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,  	if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))  		return; +	/* We're not in EMLSR and our signal is bad, try to switch link maybe */ +	if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) { +		iwl_mvm_int_mlo_scan(mvm, vif); +		return; +	} + +	/* We are in EMLSR, check if we need to exit */  	exit_esr_thresh =  		iwl_mvm_get_esr_rssi_thresh(mvm,  					    &bss_conf->chanreq.oper, @@ -751,8 +757,8 @@ static void iwl_mvm_stats_energy_iter(void *_data,  	u8 *energy = _data;  	u32 sta_id = mvmsta->deflink.sta_id; -	if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT_MAX, "sta_id %d >= %d", -		      sta_id, IWL_MVM_STATION_COUNT_MAX)) +	if (WARN_ONCE(sta_id >= IWL_STATION_COUNT_MAX, "sta_id %d >= %d", +		      sta_id, IWL_STATION_COUNT_MAX))  		return;  	if (energy[sta_id]) @@ -794,6 +800,8 @@ static void iwl_mvm_handle_per_phy_stats(struct iwl_mvm *mvm,  			continue;  		mvm->phy_ctxts[i].channel_load_by_us =  			le32_to_cpu(per_phy[i].channel_load_by_us); +		mvm->phy_ctxts[i].channel_load_not_by_us = +			le32_to_cpu(per_phy[i].channel_load_not_by_us);  	}  } @@ -882,28 +890,28 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,  	u32 rx_bytes[MAC_INDEX_AUX] = {};  	int fw_link_id; -	for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf); +	/* driver uses link ID == MAC ID */ +	for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->vif_id_to_mac);  	     fw_link_id++) {  		struct iwl_stats_ntfy_per_link *link_stats; -		struct ieee80211_bss_conf *bss_conf; -		struct iwl_mvm_vif *mvmvif;  		struct iwl_mvm_vif_link_info *link_info; +		struct iwl_mvm_vif *mvmvif; +		struct ieee80211_vif *vif;  		int link_id;  		int sig; -		bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, -							       false); -		if (!bss_conf) +		vif = iwl_mvm_rcu_dereference_vif_id(mvm, fw_link_id, false); +		if (!vif)  			continue; -		if (bss_conf->vif->type != NL80211_IFTYPE_STATION) +		if (vif->type != NL80211_IFTYPE_STATION)  			continue; -		link_id = bss_conf->link_id; +		link_id = vif->bss_conf.link_id;  		if (link_id >= ARRAY_SIZE(mvmvif->link))  			continue; -		mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif); +		mvmvif = iwl_mvm_vif_from_mac80211(vif);  		link_info = mvmvif->link[link_id];  		if (!link_info)  			continue; @@ -921,8 +929,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,  		if (link_info->phy_ctxt &&  		    link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) -			iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif, -							link_id); +			iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);  		/* make sure that beacon statistics don't go backwards with TCM  		 * request to clear statistics @@ -932,8 +939,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,  				mvmvif->link[link_id]->beacon_stats.num_beacons;  		sig = -le32_to_cpu(link_stats->beacon_filter_average_energy); -		iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info, -					bss_conf); +		iwl_mvm_update_link_sig(vif, sig, link_info, &vif->bss_conf);  		if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,  			      "invalid mvmvif id: %d", mvmvif->id)) @@ -967,6 +973,9 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,  #define SEC_LINK_MIN_TX 3000  #define SEC_LINK_MIN_RX 400 +/* Accept a ~20% short window to avoid issues due to jitter */ +#define IWL_MVM_TPT_MIN_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ * 4 / 5) +  static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  {  	struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); @@ -976,6 +985,7 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  	unsigned long sec_link_tx = 0, sec_link_rx = 0;  	u8 sec_link_tx_perc, sec_link_rx_perc;  	u8 sec_link; +	bool skip = false;  	lockdep_assert_held(&mvm->mutex); @@ -1000,11 +1010,11 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  	sec_link = mvmvif->link[sec_link]->fw_link_id;  	/* Sum up RX and TX MPDUs from the different queues/links */ -	for (int q = 0; q < mvm->trans->num_rx_queues; q++) { +	for (int q = 0; q < mvm->trans->info.num_rxqs; q++) {  		spin_lock_bh(&mvmsta->mpdu_counters[q].lock);  		/* The link IDs that doesn't exist will contain 0 */ -		for (int link = 0; link < IWL_MVM_FW_MAX_LINK_ID; link++) { +		for (int link = 0; link < IWL_FW_MAX_LINK_ID; link++) {  			total_tx += mvmsta->mpdu_counters[q].per_link[link].tx;  			total_rx += mvmsta->mpdu_counters[q].per_link[link].rx;  		} @@ -1015,15 +1025,27 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  		/*  		 * In EMLSR we have statistics every 5 seconds, so we can reset  		 * the counters upon every statistics notification. +		 * The FW sends the notification regularly, but it will be +		 * misaligned at the start. Skipping the measurement if it is +		 * short will synchronize us.  		 */ +		if (jiffies - mvmsta->mpdu_counters[q].window_start < +		    IWL_MVM_TPT_MIN_COUNT_WINDOW) +			skip = true; +		mvmsta->mpdu_counters[q].window_start = jiffies;  		memset(mvmsta->mpdu_counters[q].per_link, 0,  		       sizeof(mvmsta->mpdu_counters[q].per_link));  		spin_unlock_bh(&mvmsta->mpdu_counters[q].lock);  	} -	IWL_DEBUG_STATS(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", -			total_tx, total_rx); +	if (skip) { +		IWL_DEBUG_INFO(mvm, "MPDU statistics window was short\n"); +		return; +	} + +	IWL_DEBUG_INFO(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", +		       total_tx, total_rx);  	/* If we don't have enough MPDUs - exit EMLSR */  	if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH && @@ -1033,6 +1055,9 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  		return;  	} +	IWL_DEBUG_INFO(mvm, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n", +		       sec_link, sec_link_tx, sec_link_rx); +  	/* Calculate the percentage of the secondary link TX/RX */  	sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;  	sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0; @@ -1052,7 +1077,7 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)  void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,  					 struct iwl_rx_cmd_buffer *rxb)  { -	u8 average_energy[IWL_MVM_STATION_COUNT_MAX]; +	u8 average_energy[IWL_STATION_COUNT_MAX];  	struct iwl_rx_packet *pkt = rxb_addr(rxb);  	struct iwl_system_statistics_notif_oper *stats;  	int i; @@ -1111,7 +1136,7 @@ static void  iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,  				 struct iwl_rx_packet *pkt)  { -	u8 average_energy[IWL_MVM_STATION_COUNT_MAX]; +	u8 average_energy[IWL_STATION_COUNT_MAX];  	__le32 air_time[MAC_INDEX_AUX];  	__le32 rx_bytes[MAC_INDEX_AUX];  	__le32 flags = 0; | 
