summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShahar Tzarfati <shahar.tzarfati@intel.com>2026-05-15 15:09:47 +0300
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>2026-05-26 15:17:12 +0300
commit5864b87863dbd061dc3a2f779fa6137dbee4a2cb (patch)
treedc0e8ae2d755b179a97c2a4b256d12e245fcf7be
parent5f88b045d959f8a51757e0fde29d5d204da1176f (diff)
wifi: iwlwifi: mld: expose beacon avg signal
Store beacon_average_energy from per-link FW statistics and expose it via station_info as rx_beacon_signal_avg in sta statistics. This fixes missing beacon average signal reporting to upper layers. Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com> Link: https://patch.msgid.link/20260515150751.a74a22d90890.I74d596359c5b69364fb977fdf31396eb57ca0927@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/link.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/stats.c47
2 files changed, 48 insertions, 2 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h
index 4527f054ce92..0b3974d86531 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h
@@ -36,6 +36,8 @@ struct iwl_probe_resp_data {
* @rcu_head: RCU head for freeing this data.
* @fw_id: the fw id of the link.
* @active: if the link is active or not.
+ * @avg_signal: The current average signal of beacons [dBm] retrieved from
+ * firmware per-link periodic stats (STATISTICS_OPER_NOTIF).
* @queue_params: QoS data from mac80211. This is updated with a call to
* drv_conf_tx per each AC, and then notified once with BSS_CHANGED_QOS.
* So we store it here and then send one link cmd for all the ACs.
@@ -68,6 +70,7 @@ struct iwl_mld_link {
struct_group(zeroed_on_hw_restart,
u8 fw_id;
bool active;
+ s8 avg_signal;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct ieee80211_chanctx_conf __rcu *chan_ctx;
bool he_ru_2mhz_block;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
index b93e0f8ab5fb..e7b283cbe199 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
@@ -311,6 +311,40 @@ static void iwl_mld_sta_stats_fill_txrate(struct iwl_mld_sta *mld_sta,
}
}
+static void iwl_mld_sta_stats_fill_beacon_signal_avg(struct ieee80211_vif *vif,
+ struct station_info *sinfo)
+{
+ struct ieee80211_bss_conf *link_conf;
+ struct iwl_mld_link *link;
+ u8 link_id;
+
+ if (iwl_mld_emlsr_active(vif))
+ return;
+
+ /* TODO: support statistics for NAN */
+ if (vif->type == NL80211_IFTYPE_NAN ||
+ vif->type == NL80211_IFTYPE_NAN_DATA)
+ return;
+
+ link_id = iwl_mld_get_primary_link(vif);
+ link_conf = link_conf_dereference_protected(vif, link_id);
+
+ if (WARN_ONCE(!link_conf,
+ "link_conf is NULL for link_id=%u\n", link_id))
+ return;
+
+ link = iwl_mld_link_from_mac80211(link_conf);
+ if (WARN_ONCE(!link,
+ "iwl_mld_link is NULL for link_id=%u\n", link_id))
+ return;
+
+ if (!link->avg_signal)
+ return;
+
+ sinfo->rx_beacon_signal_avg = link->avg_signal;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
+}
+
void iwl_mld_mac80211_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -329,9 +363,9 @@ void iwl_mld_mac80211_sta_statistics(struct ieee80211_hw *hw,
iwl_mld_sta_stats_fill_txrate(mld_sta, sinfo);
- /* TODO: NL80211_STA_INFO_BEACON_RX */
+ iwl_mld_sta_stats_fill_beacon_signal_avg(vif, sinfo);
- /* TODO: NL80211_STA_INFO_BEACON_SIGNAL_AVG */
+ /* TODO: NL80211_STA_INFO_BEACON_RX */
}
#define IWL_MLD_TRAFFIC_LOAD_MEDIUM_THRESH 10 /* percentage */
@@ -443,6 +477,8 @@ iwl_mld_process_per_link_stats(struct iwl_mld *mld,
fw_id++) {
const struct iwl_stats_ntfy_per_link *link_stats;
struct ieee80211_bss_conf *bss_conf;
+ struct iwl_mld_link *link;
+ u32 avg_raw;
int sig;
bss_conf = iwl_mld_fw_id_to_link_conf(mld, fw_id);
@@ -456,6 +492,13 @@ iwl_mld_process_per_link_stats(struct iwl_mld *mld,
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
iwl_mld_update_link_sig(bss_conf->vif, sig, bss_conf);
+ link = iwl_mld_link_from_mac80211(bss_conf);
+ if (WARN_ON_ONCE(!link))
+ continue;
+
+ avg_raw = le32_to_cpu(link_stats->beacon_average_energy);
+ link->avg_signal = clamp_t(int, -(int)avg_raw, S8_MIN, 0);
+
/* TODO: parse more fields here (task=statistics)*/
}