Commit 80763515 authored by Eyal Shapira's avatar Eyal Shapira Committed by Emmanuel Grumbach

iwlwifi: mvm: rs: overhaul rs_get_best_rate

rs_get_best_rate determines the optimal rate to try in a
new Tx column. Currently we were sometimes trying a too high
rate which would lead us to fail and avoid switching to the
new column despite it having a potential to be better.
Change the logic to try and find the first rate which would
exceed the current actual throughput or be more aggressive
if the success ratio is good.
Signed-off-by: default avatarEyal Shapira <eyalx.shapira@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 31b20452
...@@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, ...@@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
} }
/*
* Find starting rate for new "search" high-throughput mode of modulation.
* Goal is to find lowest expected rate (under perfect conditions) that is
* above the current measured throughput of "active" mode, to give new mode
* a fair chance to prove itself without too many challenges.
*
* This gets called when transitioning to more aggressive modulation
* (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
* (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need
* to decrease to match "active" throughput. When moving from MIMO to SISO,
* bit rate will typically need to increase, but not if performance was bad.
*/
static s32 rs_get_best_rate(struct iwl_mvm *mvm, static s32 rs_get_best_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta, struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, /* "search" */ struct iwl_scale_tbl_info *tbl, /* "search" */
u16 rate_mask, s8 index) unsigned long rate_mask, s8 index)
{ {
/* "active" values */
struct iwl_scale_tbl_info *active_tbl = struct iwl_scale_tbl_info *active_tbl =
&(lq_sta->lq_info[lq_sta->active_tbl]); &(lq_sta->lq_info[lq_sta->active_tbl]);
s32 active_sr = active_tbl->win[index].success_ratio; s32 success_ratio = active_tbl->win[index].success_ratio;
s32 active_tpt = active_tbl->expected_tpt[index]; u16 expected_current_tpt = active_tbl->expected_tpt[index];
/* expected "search" throughput */
const u16 *tpt_tbl = tbl->expected_tpt; const u16 *tpt_tbl = tbl->expected_tpt;
s32 new_rate, high, low, start_hi;
u16 high_low; u16 high_low;
s8 rate = index; u32 target_tpt;
int rate_idx;
new_rate = high = low = start_hi = IWL_RATE_INVALID;
while (1) {
high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,
tbl->rate.type);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
/*
* Lower the "search" bit rate, to give new "search" mode
* approximately the same throughput as "active" if:
*
* 1) "Active" mode has been working modestly well (but not
* great), and expected "search" throughput (under perfect
* conditions) at candidate rate is above the actual
* measured "active" throughput (but less than expected
* "active" throughput under perfect conditions).
* OR
* 2) "Active" mode has been working perfectly or very well
* and expected "search" throughput (under perfect
* conditions) at candidate rate is above expected
* "active" throughput (under perfect conditions).
*/
if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
((active_sr > RS_SR_FORCE_DECREASE) &&
(active_sr <= IWL_RATE_HIGH_TH) &&
(tpt_tbl[rate] <= active_tpt))) ||
((active_sr >= IWL_RATE_SCALE_SWITCH) &&
(tpt_tbl[rate] > active_tpt))) {
/* (2nd or later pass)
* If we've already tried to raise the rate, and are
* now trying to lower it, use the higher rate. */
if (start_hi != IWL_RATE_INVALID) {
new_rate = start_hi;
break;
}
new_rate = rate;
/* Loop again with lower rate */ if (success_ratio > RS_SR_NO_DECREASE) {
if (low != IWL_RATE_INVALID) target_tpt = 100 * expected_current_tpt;
rate = low; IWL_DEBUG_RATE(mvm,
"SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
success_ratio, target_tpt);
} else {
target_tpt = lq_sta->last_tpt;
IWL_DEBUG_RATE(mvm,
"SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
success_ratio, target_tpt);
}
/* Lower rate not available, use the original */ rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);
else
break;
/* Else try to raise the "search" rate to match "active" */ while (rate_idx != IWL_RATE_INVALID) {
} else { if (target_tpt < (100 * tpt_tbl[rate_idx]))
/* (2nd or later pass) break;
* If we've already tried to lower the rate, and are
* now trying to raise it, use the lower rate. */
if (new_rate != IWL_RATE_INVALID)
break;
/* Loop again with higher rate */ high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask,
else if (high != IWL_RATE_INVALID) { tbl->rate.type);
start_hi = high;
rate = high;
/* Higher rate not available, use the original */ rate_idx = (high_low >> 8) & 0xff;
} else {
new_rate = rate;
break;
}
}
} }
return new_rate; IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n",
rate_idx, target_tpt,
rate_idx != IWL_RATE_INVALID ?
100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);
return rate_idx;
} }
static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
...@@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, ...@@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
u32 sz = (sizeof(struct iwl_scale_tbl_info) - u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u16 rate_mask = 0; unsigned long rate_mask = 0;
u32 rate_idx = 0; u32 rate_idx = 0;
memcpy(search_tbl, tbl, sz); memcpy(search_tbl, tbl, sz);
...@@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, ...@@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
!(BIT(rate_idx) & rate_mask)) { !(BIT(rate_idx) & rate_mask)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"can not switch with index %d" "can not switch with index %d"
" rate mask %x\n", " rate mask %lx\n",
rate_idx, rate_mask); rate_idx, rate_mask);
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment