Commit e581b7fe authored by Sarika Sharma's avatar Sarika Sharma Committed by Johannes Berg
Browse files

wifi: mac80211: add support towards MLO handling of station statistics



Currently, in supporting API's to fill sinfo structure from sta
structure, is mapped to fill the fields from sta->deflink. However,
for multi-link (ML) station, sinfo structure should be filled from
corresponding link_id.

Therefore, add  link_id as an additional argument in supporting API's
for filling sinfo structure correctly. Link_id is set to -1 for non-ML
station and corresponding link_id for ML stations. In supporting API's
for filling sinfo structure, check for link_id, if link_id < 0, fill
the sinfo structure from sta->deflink, otherwise fill from
sta->link[link_id].

Current, changes are done at the deflink level i.e, pass -1 as link_id.
Actual link_id will be added in subsequent patches to support
station statistics for MLO.

Signed-off-by: default avatarSarika Sharma <quic_sarishar@quicinc.com>
Link: https://patch.msgid.link/20250528054420.3050133-2-quic_sarishar@quicinc.com


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 140c6a61
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -586,7 +586,7 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
		return false;
	}

	ave_rssi = ieee80211_ave_rssi(ctx->vif);
	ave_rssi = ieee80211_ave_rssi(ctx->vif, -1);
	if (!ave_rssi) {
		/* no rssi data, no changes to reduce tx power */
		IWL_DEBUG_COEX(priv, "no rssi data available\n");
+2 −1
Original line number Diff line number Diff line
@@ -7242,13 +7242,14 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
 * ieee80211_ave_rssi - report the average RSSI for the specified interface
 *
 * @vif: the specified virtual interface
 * @link_id: the link ID for MLO, or -1 for non-MLO
 *
 * Note: This function assumes that the given vif is valid.
 *
 * Return: The average RSSI value for the requested interface, or 0 if not
 * applicable.
 */
int ieee80211_ave_rssi(struct ieee80211_vif *vif);
int ieee80211_ave_rssi(struct ieee80211_vif *vif, int link_id);

/**
 * ieee80211_report_wowlan_wakeup - report WoWLAN wakeup
+2 −2
Original line number Diff line number Diff line
@@ -635,7 +635,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
	rcu_read_lock();

	list_for_each_entry_rcu(sta, &local->sta_list, list) {
		unsigned long last_active = ieee80211_sta_last_active(sta);
		unsigned long last_active = ieee80211_sta_last_active(sta, -1);

		if (sta->sdata == sdata &&
		    time_is_after_jiffies(last_active +
@@ -1228,7 +1228,7 @@ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
	lockdep_assert_wiphy(local->hw.wiphy);

	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
		unsigned long last_active = ieee80211_sta_last_active(sta);
		unsigned long last_active = ieee80211_sta_last_active(sta, -1);

		if (sdata != sta->sdata)
			continue;
+56 −25
Original line number Diff line number Diff line
@@ -1651,7 +1651,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
	lockdep_assert_wiphy(local->hw.wiphy);

	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
		unsigned long last_active = ieee80211_sta_last_active(sta);
		unsigned long last_active = ieee80211_sta_last_active(sta, -1);

		if (sdata != sta->sdata)
			continue;
@@ -2420,18 +2420,27 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
}

static struct ieee80211_sta_rx_stats *
sta_get_last_rx_stats(struct sta_info *sta)
sta_get_last_rx_stats(struct sta_info *sta, int link_id)
{
	struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats;
	struct ieee80211_sta_rx_stats *stats;
	struct link_sta_info *link_sta_info;
	int cpu;

	if (!sta->deflink.pcpu_rx_stats)
	if (link_id < 0)
		link_sta_info = &sta->deflink;
	else
		link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
						  sta->link[link_id]);

	stats = &link_sta_info->rx_stats;

	if (!link_sta_info->pcpu_rx_stats)
		return stats;

	for_each_possible_cpu(cpu) {
		struct ieee80211_sta_rx_stats *cpustats;

		cpustats = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu);
		cpustats = per_cpu_ptr(link_sta_info->pcpu_rx_stats, cpu);

		if (time_after(cpustats->last_rx, stats->last_rx))
			stats = cpustats;
@@ -2499,9 +2508,10 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
	}
}

static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo,
				int link_id)
{
	u32 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate);
	u32 rate = READ_ONCE(sta_get_last_rx_stats(sta, link_id)->last_rate);

	if (rate == STA_STATS_RATE_INVALID)
		return -EINVAL;
@@ -2526,20 +2536,28 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,

static void sta_set_tidstats(struct sta_info *sta,
			     struct cfg80211_tid_stats *tidstats,
			     int tid)
			     int tid, int link_id)
{
	struct ieee80211_local *local = sta->local;
	struct link_sta_info *link_sta_info;
	int cpu;

	if (link_id < 0)
		link_sta_info = &sta->deflink;
	else
		link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
						  sta->link[link_id]);

	if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
		tidstats->rx_msdu += sta_get_tidstats_msdu(&sta->deflink.rx_stats,
		tidstats->rx_msdu +=
			sta_get_tidstats_msdu(&link_sta_info->rx_stats,
					      tid);

		if (sta->deflink.pcpu_rx_stats) {
		if (link_sta_info->pcpu_rx_stats) {
			for_each_possible_cpu(cpu) {
				struct ieee80211_sta_rx_stats *cpurxs;

				cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats,
				cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats,
						     cpu);
				tidstats->rx_msdu +=
					sta_get_tidstats_msdu(cpurxs, tid);
@@ -2551,19 +2569,21 @@ static void sta_set_tidstats(struct sta_info *sta,

	if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
		tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
		tidstats->tx_msdu = sta->deflink.tx_stats.msdu[tid];
		tidstats->tx_msdu = link_sta_info->tx_stats.msdu[tid];
	}

	if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
	    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
		tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
		tidstats->tx_msdu_retries = sta->deflink.status_stats.msdu_retries[tid];
		tidstats->tx_msdu_retries =
			link_sta_info->status_stats.msdu_retries[tid];
	}

	if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
	    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
		tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
		tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
		tidstats->tx_msdu_failed =
			link_sta_info->status_stats.msdu_failed[tid];
	}

	if (tid < IEEE80211_NUM_TIDS) {
@@ -2634,7 +2654,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
	int i, ac, cpu;
	struct ieee80211_sta_rx_stats *last_rxstats;

	last_rxstats = sta_get_last_rx_stats(sta);
	last_rxstats = sta_get_last_rx_stats(sta, -1);

	sinfo->generation = sdata->local->sta_generation;

@@ -2662,7 +2682,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
	sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
	sinfo->assoc_at = sta->assoc_at;
	sinfo->inactive_time =
		jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
		jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1));

	if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
			       BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
@@ -2751,7 +2771,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
	    !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
				 BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
		sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
		sinfo->rx_beacon_signal_avg =
			ieee80211_ave_rssi(&sdata->vif, -1);
	}

	if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
@@ -2800,13 +2821,13 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,

	if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) &&
	    !sta->sta.valid_links) {
		if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0)
		if (sta_set_rate_info_rx(sta, &sinfo->rxrate, -1) == 0)
			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
	}

	if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
		for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
			sta_set_tidstats(sta, &sinfo->pertid[i], i);
			sta_set_tidstats(sta, &sinfo->pertid[i], i, -1);
	}

#ifdef CONFIG_MAC80211_MESH
@@ -2889,14 +2910,24 @@ u32 sta_get_expected_throughput(struct sta_info *sta)
	return thr;
}

unsigned long ieee80211_sta_last_active(struct sta_info *sta)
unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id)
{
	struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
	struct ieee80211_sta_rx_stats *stats;
	struct link_sta_info *link_sta_info;

	stats = sta_get_last_rx_stats(sta, link_id);

	if (!sta->deflink.status_stats.last_ack ||
	    time_after(stats->last_rx, sta->deflink.status_stats.last_ack))
	if (link_id < 0)
		link_sta_info = &sta->deflink;
	else
		link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
						  sta->link[link_id]);

	if (!link_sta_info->status_stats.last_ack ||
	    time_after(stats->last_rx, link_sta_info->status_stats.last_ack))
		return stats->last_rx;
	return sta->deflink.status_stats.last_ack;

	return link_sta_info->status_stats.last_ack;
}

int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)
+1 −1
Original line number Diff line number Diff line
@@ -936,7 +936,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);

unsigned long ieee80211_sta_last_active(struct sta_info *sta);
unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id);

void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
					   const u8 *ext_capab,
Loading