Commit 7d9d0d56 authored by Luca Coelho's avatar Luca Coelho
Browse files

iwlwifi: mvm: add traffic condition monitoring (TCM)



Traffic condition monitor gathers data about the traffic load and
other conditions and can be used to make decisions regarding latency,
throughput etc.  This patch introduces the code and data structures to
collect this data for future use.

Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 5d136594
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -112,6 +112,9 @@
#define IWL_MVM_PARSE_NVM			0
#define IWL_MVM_ADWELL_ENABLE			1
#define IWL_MVM_ADWELL_MAX_BUDGET		0
#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH		10 /* percentage */
#define IWL_MVM_TCM_LOAD_HIGH_THRESH		50 /* percentage */
#define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH	100 /* packets/10 seconds */
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE    1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE      2
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW   1
+7 −0
Original line number Diff line number Diff line
@@ -1097,6 +1097,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)

	/* make sure the d0i3 exit work is not pending */
	flush_work(&mvm->d0i3_exit_work);
	iwl_mvm_pause_tcm(mvm, true);

	iwl_fw_runtime_suspend(&mvm->fwrt);

@@ -2014,6 +2015,8 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)

	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;

	iwl_mvm_resume_tcm(mvm);

	iwl_fw_runtime_resume(&mvm->fwrt);

	return ret;
@@ -2042,6 +2045,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)

	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;

	iwl_mvm_pause_tcm(mvm, true);

	iwl_fw_runtime_suspend(&mvm->fwrt);

	/* start pseudo D3 */
@@ -2104,6 +2109,8 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
	__iwl_mvm_resume(mvm, true);
	rtnl_unlock();

	iwl_mvm_resume_tcm(mvm);

	iwl_fw_runtime_resume(&mvm->fwrt);

	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
+2 −0
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
			 mvmvif->id, mvmvif->color);
	pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
			 vif->bss_conf.bssid);
	pos += scnprintf(buf+pos, bufsz-pos, "Load: %d\n",
			 mvm->tcm.result.load[mvmvif->id]);
	pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
	for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
		pos += scnprintf(buf+pos, bufsz-pos,
+59 −0
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@
#include "fw/acpi.h"
#include "fw/debugfs.h"

#include <linux/average.h>

#define IWL_MVM_MAX_ADDRESSES		5
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
@@ -595,6 +597,51 @@ enum iwl_mvm_tdls_cs_state {
	IWL_MVM_TDLS_SW_ACTIVE,
};

enum iwl_mvm_traffic_load {
	IWL_MVM_TRAFFIC_LOW,
	IWL_MVM_TRAFFIC_MEDIUM,
	IWL_MVM_TRAFFIC_HIGH,
};

DECLARE_EWMA(rate, 16, 16)

struct iwl_mvm_tcm_mac {
	struct {
		u32 pkts[IEEE80211_NUM_ACS];
		u32 airtime;
	} tx;
	struct {
		u32 pkts[IEEE80211_NUM_ACS];
		u32 airtime;
		u32 last_ampdu_ref;
	} rx;
	struct {
		/* track AP's transfer in client mode */
		u64 rx_bytes;
		struct ewma_rate rate;
		bool detected;
	} uapsd_nonagg_detect;
};

struct iwl_mvm_tcm {
	struct delayed_work work;
	spinlock_t lock; /* used when time elapsed */
	unsigned long ts; /* timestamp when period ends */
	unsigned long ll_ts;
	unsigned long uapsd_nonagg_ts;
	bool paused;
	struct iwl_mvm_tcm_mac data[NUM_MAC_INDEX_DRIVER];
	struct {
		u32 elapsed; /* milliseconds for this TCM period */
		u32 airtime[NUM_MAC_INDEX_DRIVER];
		enum iwl_mvm_traffic_load load[NUM_MAC_INDEX_DRIVER];
		enum iwl_mvm_traffic_load global_load;
		bool low_latency[NUM_MAC_INDEX_DRIVER];
		bool change[NUM_MAC_INDEX_DRIVER];
		bool global_change;
	} result;
};

/**
 * struct iwl_mvm_reorder_buffer - per ra/tid/queue reorder buffer
 * @head_sn: reorder window head sn
@@ -978,6 +1025,9 @@ struct iwl_mvm {
	 */
	bool temperature_test;  /* Debug test temperature is enabled */

	unsigned long bt_coex_last_tcm_ts;
	struct iwl_mvm_tcm tcm;

	struct iwl_time_quota_cmd last_quota_cmd;

#ifdef CONFIG_NL80211_TESTMODE
@@ -1906,6 +1956,15 @@ bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm);

void iwl_mvm_inactivity_check(struct iwl_mvm *mvm);

#define MVM_TCM_PERIOD_MSEC 500
#define MVM_TCM_PERIOD (HZ * MVM_TCM_PERIOD_MSEC / 1000)
#define MVM_LL_PERIOD (10 * HZ)
void iwl_mvm_tcm_work(struct work_struct *work);
void iwl_mvm_recalc_tcm(struct iwl_mvm *mvm);
void iwl_mvm_pause_tcm(struct iwl_mvm *mvm, bool with_cancel);
void iwl_mvm_resume_tcm(struct iwl_mvm *mvm);
u8 iwl_mvm_tcm_load_percentage(u32 airtime, u32 elapsed);

void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
				    struct ieee80211_vif *vif,
+10 −0
Original line number Diff line number Diff line
@@ -667,6 +667,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,

	SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);

	spin_lock_init(&mvm->tcm.lock);
	INIT_DELAYED_WORK(&mvm->tcm.work, iwl_mvm_tcm_work);
	mvm->tcm.ts = jiffies;
	mvm->tcm.ll_ts = jiffies;
	mvm->tcm.uapsd_nonagg_ts = jiffies;

	INIT_DELAYED_WORK(&mvm->cs_tx_unblock_dwork, iwl_mvm_tx_unblock_dwork);

	/*
@@ -859,6 +865,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
	for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
		kfree(mvm->nvm_sections[i].data);

	cancel_delayed_work_sync(&mvm->tcm.work);

	iwl_mvm_tof_clean(mvm);

	mutex_destroy(&mvm->mutex);
@@ -1432,6 +1440,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
		mvm->d0i3_offloading = false;
	}

	iwl_mvm_pause_tcm(mvm, true);
	/* make sure we have no running tx while configuring the seqno */
	synchronize_net();

@@ -1615,6 +1624,7 @@ out:
	/* the FW might have updated the regdomain */
	iwl_mvm_update_changed_regdom(mvm);

	iwl_mvm_resume_tcm(mvm);
	iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK);
	mutex_unlock(&mvm->mutex);
}
Loading