Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 482e4844 authored by Gregory Greenman's avatar Gregory Greenman Committed by Luca Coelho
Browse files

iwlwifi: mvm: change open and close criteria of a BA session



Tx BA session should be started according to the current throughput
without any dependence on the internal rate scaling state. The criteria
for opening a BA session will be 10 frames per second.

Sending frequent del BAs can cause inter-op issues with some APs. We'll
not close a BA session until we receive an explicit del BA from the
peer.

Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b823cf3b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@
#define IWL_MVM_RS_SR_NO_DECREASE		85	/* percent */
#define IWL_MVM_RS_AGG_TIME_LIMIT	        4000    /* 4 msecs. valid 100-8000 */
#define IWL_MVM_RS_AGG_DISABLE_START	        3
#define IWL_MVM_RS_AGG_START_THRESHOLD	        10	/* num frames per second */
#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE	75	/* percent */
#define IWL_MVM_RS_TPC_SR_NO_INCREASE		85	/* percent */
#define IWL_MVM_RS_TPC_TX_POWER_STEP		3
+65 −52
Original line number Diff line number Diff line
@@ -622,7 +622,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,

	IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n",
		     sta->addr, tid);
	ret = ieee80211_start_tx_ba_session(sta, tid, 5000);

	/* start BA session until the peer sends del BA */
	ret = ieee80211_start_tx_ba_session(sta, tid, 0);
	if (ret == -EAGAIN) {
		/*
		 * driver and mac80211 is out of sync
@@ -636,15 +638,31 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
	return ret;
}

static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, u8 tid,
			      struct iwl_lq_sta *lq_data,
static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
			      u8 tid, struct iwl_lq_sta *lq_sta,
			      struct ieee80211_sta *sta)
{
	if (tid < IWL_MAX_TID_COUNT)
		rs_tl_turn_on_agg_for_tid(mvm, lq_data, tid, sta);
	else
	struct iwl_mvm_tid_data *tid_data;

	/*
	 * In AP mode, tid can be equal to IWL_MAX_TID_COUNT
	 * when the frame is not QoS
	 */
	if (WARN_ON_ONCE(tid > IWL_MAX_TID_COUNT)) {
		IWL_ERR(mvm, "tid exceeds max TID count: %d/%d\n",
			tid, IWL_MAX_TID_COUNT);
		return;
	} else if (tid == IWL_MAX_TID_COUNT) {
		return;
	}

	tid_data = &mvmsta->tid_data[tid];
	if ((tid_data->state == IWL_AGG_OFF) &&
	    (lq_sta->tx_agg_tid_en & BIT(tid)) &&
	    (tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
		IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid);
		rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta);
	}
}

static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
@@ -753,8 +771,38 @@ static int rs_collect_tpc_data(struct iwl_mvm *mvm,
				    window);
}

static void rs_update_tid_tpt_stats(struct iwl_mvm *mvm,
				    struct iwl_mvm_sta *mvmsta,
				    u8 tid, int successes)
{
	struct iwl_mvm_tid_data *tid_data;

	if (tid >= IWL_MAX_TID_COUNT)
		return;

	tid_data = &mvmsta->tid_data[tid];

	/*
	 * Measure if there're enough successful transmits per second.
	 * These statistics are used only to decide if we can start a
	 * BA session, so it should be updated only when A-MPDU is
	 * off.
	 */
	if (tid_data->state != IWL_AGG_OFF)
		return;

	if (time_is_before_jiffies(tid_data->tpt_meas_start + HZ) ||
	    (tid_data->tx_count >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
		tid_data->tx_count_last = tid_data->tx_count;
		tid_data->tx_count = 0;
		tid_data->tpt_meas_start = jiffies;
	} else {
		tid_data->tx_count += successes;
	}
}

static int rs_collect_tlc_data(struct iwl_mvm *mvm,
			       struct iwl_lq_sta *lq_sta,
			       struct iwl_mvm_sta *mvmsta, u8 tid,
			       struct iwl_scale_tbl_info *tbl,
			       int scale_index, int attempts, int successes)
{
@@ -764,12 +812,14 @@ static int rs_collect_tlc_data(struct iwl_mvm *mvm,
		return -EINVAL;

	if (tbl->column != RS_COLUMN_INVALID) {
		struct lq_sta_pers *pers = &lq_sta->pers;
		struct lq_sta_pers *pers = &mvmsta->lq_sta.pers;

		pers->tx_stats[tbl->column][scale_index].total += attempts;
		pers->tx_stats[tbl->column][scale_index].success += successes;
	}

	rs_update_tid_tpt_stats(mvm, mvmsta, tid, successes);

	/* Select window for current tx bit rate */
	window = &(tbl->win[scale_index]);
	return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
@@ -1211,12 +1261,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
	if (time_after(jiffies,
		       (unsigned long)(lq_sta->last_tx +
				       (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
		int t;

		IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
		for (t = 0; t < IWL_MAX_TID_COUNT; t++)
			ieee80211_stop_tx_ba_session(sta, t);

		iwl_mvm_rs_rate_init(mvm, sta, info->band, false);
		return;
	}
@@ -1312,7 +1357,8 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
		if (info->status.ampdu_ack_len == 0)
			info->status.ampdu_len = 1;

		rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
		rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl,
				    lq_rate.index,
				    info->status.ampdu_len,
				    info->status.ampdu_ack_len);

@@ -1351,7 +1397,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
					    lq_rate.index, 1,
					    i < retries ? 0 : legacy_success,
					    reduced_txp);
			rs_collect_tlc_data(mvm, lq_sta, tmp_tbl,
			rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
					    lq_rate.index, 1,
					    i < retries ? 0 : legacy_success);
		}
@@ -2229,7 +2275,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
	s32 sr;
	u8 prev_agg = lq_sta->is_agg;
	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
	struct iwl_mvm_tid_data *tid_data;
	struct rs_rate *rate;

	lq_sta->is_agg = !!mvmsta->agg_tids;
@@ -2480,44 +2525,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
		}
	}

	if (!ndp)
		rs_tl_turn_on_agg(mvm, mvmsta, tid, lq_sta, sta);

	if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) {
		/* If the "active" (non-search) mode was legacy,
		 * and we've tried switching antennas,
		 * but we haven't been able to try HT modes (not available),
		 * stay with best antenna legacy modulation for a while
		 * before next round of mode comparisons. */
		tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
		if (is_legacy(&tbl1->rate)) {
			IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");

			if (tid != IWL_MAX_TID_COUNT) {
				tid_data = &mvmsta->tid_data[tid];
				if (tid_data->state != IWL_AGG_OFF) {
					IWL_DEBUG_RATE(mvm,
						       "Stop aggregation on tid %d\n",
						       tid);
					ieee80211_stop_tx_ba_session(sta, tid);
				}
			}
			rs_set_stay_in_table(mvm, 1, lq_sta);
		} else {
		/* If we're in an HT mode, and all 3 mode switch actions
		 * have been tried and compared, stay in this best modulation
		 * mode for a while before next round of mode comparisons. */
			if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
			    (lq_sta->tx_agg_tid_en & (1 << tid)) &&
			    (tid != IWL_MAX_TID_COUNT)) {
				tid_data = &mvmsta->tid_data[tid];
				if (tid_data->state == IWL_AGG_OFF && !ndp) {
					IWL_DEBUG_RATE(mvm,
						       "try to aggregate tid %d\n",
						       tid);
					rs_tl_turn_on_agg(mvm, tid,
							  lq_sta, sta);
				}
			}
			rs_set_stay_in_table(mvm, 0, lq_sta);
		}
		rs_set_stay_in_table(mvm, is_legacy(&tbl1->rate), lq_sta);
	}
}

+7 −0
Original line number Diff line number Diff line
@@ -316,6 +316,10 @@ enum iwl_mvm_agg_state {
 * @is_tid_active: has this TID sent traffic in the last
 *	%IWL_MVM_DQA_QUEUE_TIMEOUT time period. If %txq_id is invalid, this
 *	field should be ignored.
 * @tpt_meas_start: time of the throughput measurements start, is reset every HZ
 * @tx_count_last: number of frames transmitted during the last second
 * @tx_count: counts the number of frames transmitted since the last reset of
 *	 tpt_meas_start
 */
struct iwl_mvm_tid_data {
	struct sk_buff_head deferred_tx_frames;
@@ -330,6 +334,9 @@ struct iwl_mvm_tid_data {
	u16 ssn;
	u16 tx_time;
	bool is_tid_active;
	unsigned long tpt_meas_start;
	u32 tx_count_last;
	u32 tx_count;
};

struct iwl_mvm_key_pn {