Commit b6e3d1ba authored by Anjaneyulu's avatar Anjaneyulu Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: implement new firmware API for statistics



The new firmware API uses a new command and notification,
the command configures in which statistics types driver is
interested and the notification is sent periodically.
An additional change in the API is that most of the statistics
data is accumulated and reported by the firmware per MLO link.
Implement new command and notification handlers and adjust to
per-link statistics.

Signed-off-by: default avatarAnjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20231022173519.8cc7df0ebff2.If1dcb57145841c5b3c68ed112bbfcd0201f7acc3@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent ea02a208
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
 * @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
 *	&enum iwl_regulatory_and_nvm_subcmd_ids
 * @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
 * @STATISTICS_GROUP: Statistics group, uses command IDs from
 *	&enum iwl_statistics_subcmd_ids
 */
enum iwl_mvm_command_groups {
	LEGACY_GROUP = 0x0,
@@ -44,6 +46,7 @@ enum iwl_mvm_command_groups {
	PROT_OFFLOAD_GROUP = 0xb,
	REGULATORY_AND_NVM_GROUP = 0xc,
	DEBUG_GROUP = 0xf,
	STATISTICS_GROUP = 0x10,
};

/**
@@ -616,10 +619,37 @@ enum iwl_system_subcmd_ids {
	 */
	SYSTEM_FEATURES_CONTROL_CMD = 0xd,

	/**
	 * @SYSTEM_STATISTICS_CMD: &struct iwl_system_statistics_cmd
	 */
	SYSTEM_STATISTICS_CMD = 0xf,

	/**
	 * @SYSTEM_STATISTICS_END_NOTIF: &struct iwl_system_statistics_end_notif
	 */
	SYSTEM_STATISTICS_END_NOTIF = 0xfd,

	/**
	 * @RFI_DEACTIVATE_NOTIF: &struct iwl_rfi_deactivate_notif
	 */
	RFI_DEACTIVATE_NOTIF = 0xff,
};

/**
 * enum iwl_statistics_subcmd_ids - Statistics group command IDs
 */
enum iwl_statistics_subcmd_ids {
	/**
	 * @STATISTICS_OPER_NOTIF: Notification about operational
	 *	statistics &struct iwl_system_statistics_notif_oper
	 */
	STATISTICS_OPER_NOTIF = 0x0,

	/**
	 * @STATISTICS_OPER_PART1_NOTIF: Notification about operational part1
	 *	statistics &struct iwl_system_statistics_part1_notif_oper
	 */
	STATISTICS_OPER_PART1_NOTIF = 0x1,
};

#endif /* __iwl_fw_api_commands_h__ */
+139 −14
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (C) 2012-2014, 2018, 2020 - 2021 Intel Corporation
 * Copyright (C) 2012-2014, 2018, 2020 - 2021, 2023 Intel Corporation
 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
 * Copyright (C) 2016-2017 Intel Deutschland GmbH
 */
#ifndef __iwl_fw_api_stats_h__
#define __iwl_fw_api_stats_h__
#include "mac.h"
#include "mac-cfg.h"

struct mvm_statistics_dbg {
	__le32 burst_check;
@@ -411,6 +412,49 @@ struct iwl_statistics_cmd {

#define MAX_BCAST_FILTER_NUM		8

/**
 * enum iwl_statistics_notify_type_id - type_id used in system statistics
 *	command
 * @IWL_STATS_NTFY_TYPE_ID_OPER: request legacy statistics
 * @IWL_STATS_NTFY_TYPE_ID_OPER_PART1: request operational part1 statistics
 * @IWL_STATS_NTFY_TYPE_ID_OPER_PART2: request operational part2 statistics
 * @IWL_STATS_NTFY_TYPE_ID_OPER_PART3: request operational part3 statistics
 * @IWL_STATS_NTFY_TYPE_ID_OPER_PART4: request operational part4 statistics
 */
enum iwl_statistics_notify_type_id {
	IWL_STATS_NTFY_TYPE_ID_OPER		= BIT(0),
	IWL_STATS_NTFY_TYPE_ID_OPER_PART1	= BIT(1),
	IWL_STATS_NTFY_TYPE_ID_OPER_PART2	= BIT(2),
	IWL_STATS_NTFY_TYPE_ID_OPER_PART3	= BIT(3),
	IWL_STATS_NTFY_TYPE_ID_OPER_PART4	= BIT(4),
};

/**
 * enum iwl_statistics_cfg_flags - cfg_mask used in system statistics command
 * @IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK: 0 for enable, 1 for disable
 * @IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK: 0 for periodic, 1 for on-demand
 * @IWL_STATS_CFG_FLG_RESET_MSK: 0 for reset statistics after
 *	sending the notification, 1 for do not reset statistics after sending
 *	the notification
 */
enum iwl_statistics_cfg_flags {
	IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK	= BIT(0),
	IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK	= BIT(1),
	IWL_STATS_CFG_FLG_RESET_MSK		= BIT(2),
};

/**
 * struct iwl_system_statistics_cmd - system statistics command
 * @cfg_mask: configuration mask, &enum iwl_statistics_cfg_flags
 * @config_time_sec: time in sec for periodic notification
 * @type_id_mask: type_id masks, &enum iwl_statistics_notify_type_id
 */
struct iwl_system_statistics_cmd {
	__le32 cfg_mask;
	__le32 config_time_sec;
	__le32 type_id_mask;
} __packed; /* STATISTICS_FW_CMD_API_S_VER_1 */

/**
 * enum iwl_fw_statistics_type
 *
@@ -447,7 +491,49 @@ struct iwl_statistics_ntfy_hdr {
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */

/**
 * struct iwl_statistics_ntfy_per_mac
 * struct iwl_stats_ntfy_per_link
 *
 * @beacon_filter_average_energy: Average energy [-dBm] of the 2
 *	 antennas.
 * @air_time: air time
 * @beacon_counter: all beacons (both filtered and not filtered)
 * @beacon_average_energy: Average energy [-dBm] of all beacons
 *	(both filtered and not filtered)
 * @beacon_rssi_a: beacon RSSI on antenna A
 * @beacon_rssi_b: beacon RSSI on antenna B
 * @rx_bytes: RX byte count
 */
struct iwl_stats_ntfy_per_link {
	__le32 beacon_filter_average_energy;
	__le32 air_time;
	__le32 beacon_counter;
	__le32 beacon_average_energy;
	__le32 beacon_rssi_a;
	__le32 beacon_rssi_b;
	__le32 rx_bytes;
} __packed; /* STATISTICS_NTFY_PER_LINK_API_S_VER_1 */

/**
 * struct iwl_stats_ntfy_part1_per_link
 *
 * @rx_time: rx time
 * @tx_time: tx time
 * @rx_action: action frames handled by FW
 * @tx_action: action frames generated and transmitted by FW
 * @cca_defers: cca defer count
 * @beacon_filtered: filtered out beacons
 */
struct iwl_stats_ntfy_part1_per_link {
	__le64 rx_time;
	__le64 tx_time;
	__le32 rx_action;
	__le32 tx_action;
	__le32 cca_defers;
	__le32 beacon_filtered;
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_PER_LINK_API_S_VER_1 */

/**
 * struct iwl_stats_ntfy_per_mac
 *
 * @beacon_filter_average_energy: Average energy [-dBm] of the 2
 *	 antennas.
@@ -459,7 +545,7 @@ struct iwl_statistics_ntfy_hdr {
 * @beacon_rssi_b: beacon RSSI on antenna B
 * @rx_bytes: RX byte count
 */
struct iwl_statistics_ntfy_per_mac {
struct iwl_stats_ntfy_per_mac {
	__le32 beacon_filter_average_energy;
	__le32 air_time;
	__le32 beacon_counter;
@@ -470,7 +556,7 @@ struct iwl_statistics_ntfy_per_mac {
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */

#define IWL_STATS_MAX_BW_INDEX 5
/** struct iwl_statistics_ntfy_per_phy
/** struct iwl_stats_ntfy_per_phy
 * @channel_load: channel load
 * @channel_load_by_us: device contribution to MCLM
 * @channel_load_not_by_us: other devices' contribution to MCLM
@@ -485,7 +571,7 @@ struct iwl_statistics_ntfy_per_mac {
 *	per channel BW. note BACK counted as 1
 * @last_tx_ch_width_indx: last txed frame channel width index
 */
struct iwl_statistics_ntfy_per_phy {
struct iwl_stats_ntfy_per_phy {
	__le32 channel_load;
	__le32 channel_load_by_us;
	__le32 channel_load_not_by_us;
@@ -499,23 +585,62 @@ struct iwl_statistics_ntfy_per_phy {
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */

/**
 * struct iwl_statistics_ntfy_per_sta
 * struct iwl_stats_ntfy_per_sta
 *
 * @average_energy: in fact it is minus the energy..
 */
struct iwl_statistics_ntfy_per_sta {
struct iwl_stats_ntfy_per_sta {
	__le32 average_energy;
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */

#define IWL_STATS_MAX_PHY_OPERTINAL 3
#define IWL_STATS_MAX_PHY_OPERATIONAL 3
#define IWL_STATS_MAX_FW_LINKS	(IWL_MVM_FW_MAX_LINK_ID + 1)

/**
 * struct iwl_system_statistics_notif_oper
 *
 * @time_stamp: time when the notification is sent from firmware
 * @per_link: per link statistics, &struct iwl_stats_ntfy_per_link
 * @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
 * @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
 */
struct iwl_system_statistics_notif_oper {
	__le32 time_stamp;
	struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];
	struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
	struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */

/**
 * struct iwl_system_statistics_part1_notif_oper
 *
 * @time_stamp: time when the notification is sent from firmware
 * @per_link: per link statistics &struct iwl_stats_ntfy_part1_per_link
 * @per_phy_crc_error_stats: per phy crc error statistics
 */
struct iwl_system_statistics_part1_notif_oper {
	__le32 time_stamp;
	struct iwl_stats_ntfy_part1_per_link per_link[IWL_STATS_MAX_FW_LINKS];
	__le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */

/**
 * struct iwl_system_statistics_end_notif
 *
 * @time_stamp: time when the notification is sent from firmware
 */
struct iwl_system_statistics_end_notif {
	__le32 time_stamp;
} __packed; /* STATISTICS_FW_NTFY_END_API_S_VER_1 */

/**
 * struct iwl_statistics_operational_ntfy
 *
 * @hdr: general statistics header
 * @flags: bitmap of possible notification structures
 * @per_mac_stats: per mac statistics, &struct iwl_statistics_ntfy_per_mac
 * @per_phy_stats: per phy statistics, &struct iwl_statistics_ntfy_per_phy
 * @per_sta_stats: per sta statistics, &struct iwl_statistics_ntfy_per_sta
 * @per_mac: per mac statistics, &struct iwl_stats_ntfy_per_mac
 * @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
 * @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
 * @rx_time: rx time
 * @tx_time: usec the radio is transmitting.
 * @on_time_rf: The total time in usec the RF is awake.
@@ -524,9 +649,9 @@ struct iwl_statistics_ntfy_per_sta {
struct iwl_statistics_operational_ntfy {
	struct iwl_statistics_ntfy_hdr hdr;
	__le32 flags;
	struct iwl_statistics_ntfy_per_mac per_mac_stats[MAC_INDEX_AUX];
	struct iwl_statistics_ntfy_per_phy per_phy_stats[IWL_STATS_MAX_PHY_OPERTINAL];
	struct iwl_statistics_ntfy_per_sta per_sta_stats[IWL_MVM_STATION_COUNT_MAX];
	struct iwl_stats_ntfy_per_mac per_mac[MAC_INDEX_AUX];
	struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
	struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
	__le64 rx_time;
	__le64 tx_time;
	__le64 on_time_rf;
+31 −15
Original line number Diff line number Diff line
@@ -1539,6 +1539,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret;
	int i;

	mutex_lock(&mvm->mutex);

@@ -1555,8 +1556,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,

	/* make sure that beacon statistics don't go backwards with FW reset */
	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
		mvmvif->deflink.beacon_stats.accu_num_beacons +=
			mvmvif->deflink.beacon_stats.num_beacons;
		for_each_mvm_vif_valid_link(mvmvif, i)
			mvmvif->link[i]->beacon_stats.accu_num_beacons +=
				mvmvif->link[i]->beacon_stats.num_beacons;

	/* Allocate resources for the MAC context, and add it to the fw  */
	ret = iwl_mvm_mac_ctxt_init(mvm, vif);
@@ -2581,6 +2583,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret;
	int i;

	/*
	 * Re-calculate the tsf id, as the leader-follower relations depend
@@ -2627,8 +2630,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
		if (vif->cfg.assoc) {
			/* clear statistics to get clean beacon counter */
			iwl_mvm_request_statistics(mvm, true);
			memset(&mvmvif->deflink.beacon_stats, 0,
			       sizeof(mvmvif->deflink.beacon_stats));
			for_each_mvm_vif_valid_link(mvmvif, i)
				memset(&mvmvif->link[i]->beacon_stats, 0,
				       sizeof(mvmvif->link[i]->beacon_stats));

			/* add quota for this interface */
			ret = iwl_mvm_update_quotas(mvm, true, NULL);
@@ -5726,7 +5730,11 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
			   struct survey_info *survey)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	int ret;
	int ret = 0;
	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
					   WIDE_ID(SYSTEM_GROUP,
						   SYSTEM_STATISTICS_CMD),
					   IWL_FW_CMD_VER_UNKNOWN);

	memset(survey, 0, sizeof(*survey));

@@ -5746,13 +5754,8 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
			goto out;
	}

	survey->filled = SURVEY_INFO_TIME |
			 SURVEY_INFO_TIME_RX |
			 SURVEY_INFO_TIME_TX |
			 SURVEY_INFO_TIME_SCAN;
	survey->time = mvm->accu_radio_stats.on_time_rf +
		       mvm->radio_stats.on_time_rf;
	do_div(survey->time, USEC_PER_MSEC);
	survey->filled = SURVEY_INFO_TIME_RX |
			 SURVEY_INFO_TIME_TX;

	survey->time_rx = mvm->accu_radio_stats.rx_time +
			  mvm->radio_stats.rx_time;
@@ -5762,11 +5765,20 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
			  mvm->radio_stats.tx_time;
	do_div(survey->time_tx, USEC_PER_MSEC);

	/* the new fw api doesn't support the following fields */
	if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
		goto out;

	survey->filled |= SURVEY_INFO_TIME |
			  SURVEY_INFO_TIME_SCAN;
	survey->time = mvm->accu_radio_stats.on_time_rf +
		       mvm->radio_stats.on_time_rf;
	do_div(survey->time, USEC_PER_MSEC);

	survey->time_scan = mvm->accu_radio_stats.on_time_scan +
			    mvm->radio_stats.on_time_scan;
	do_div(survey->time_scan, USEC_PER_MSEC);

	ret = 0;
 out:
	mutex_unlock(&mvm->mutex);
	return ret;
@@ -5915,6 +5927,7 @@ void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
	int i;

	if (mvmsta->deflink.avg_energy) {
		sinfo->signal_avg = -(s8)mvmsta->deflink.avg_energy;
@@ -5943,8 +5956,11 @@ void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
	if (iwl_mvm_request_statistics(mvm, false))
		goto unlock;

	sinfo->rx_beacon = mvmvif->deflink.beacon_stats.num_beacons +
			   mvmvif->deflink.beacon_stats.accu_num_beacons;
	sinfo->rx_beacon = 0;
	for_each_mvm_vif_valid_link(mvmvif, i)
		sinfo->rx_beacon += mvmvif->link[i]->beacon_stats.num_beacons +
			mvmvif->link[i]->beacon_stats.accu_num_beacons;

	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
	if (mvmvif->deflink.beacon_stats.avg_signal) {
		/* firmware only reports a value after RXing a few beacons */
+4 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret;
	int i;

	mutex_lock(&mvm->mutex);

@@ -22,8 +23,9 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,

	/* make sure that beacon statistics don't go backwards with FW reset */
	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
		mvmvif->deflink.beacon_stats.accu_num_beacons +=
			mvmvif->deflink.beacon_stats.num_beacons;
		for_each_mvm_vif_valid_link(mvmvif, i)
			mvmvif->link[i]->beacon_stats.accu_num_beacons +=
				mvmvif->link[i]->beacon_stats.num_beacons;

	/* Allocate resources for the MAC context, and add it to the fw  */
	ret = iwl_mvm_mac_ctxt_init(mvm, vif);
+12 −0
Original line number Diff line number Diff line
@@ -1194,6 +1194,8 @@ struct iwl_mvm {
	struct iwl_time_sync_data time_sync;

	struct iwl_mei_scan_filter mei_scan_filter;

	bool statistics_clear;
};

/* Extract MVM priv from op_mode and _hw */
@@ -1685,6 +1687,16 @@ static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
}

/* Statistics */
void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
					 struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
					       struct iwl_rx_cmd_buffer *rxb);
static inline void
iwl_mvm_handle_rx_system_end_stats_notif(struct iwl_mvm *mvm,
					 struct iwl_rx_cmd_buffer *rxb)
{
}

void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
				  struct iwl_rx_packet *pkt);
void iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
Loading