iwlwifi: mvm: rs: refactor rate scale action decision

Extract the scale action decision to a different function
in preparation of modifying it. While at it also convert
the scale action values from hardcoded values to a clear enum.

Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Eyal Shapira 2013-12-11 00:55:36 +02:00 committed by Emmanuel Grumbach
parent 4107dbd277
commit 4e4b815c08
1 changed files with 103 additions and 83 deletions

View File

@ -130,6 +130,12 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ IWL_DECLARE_MCS_RATE(9), /* MCS 9 */
}; };
enum rs_action {
RS_ACTION_STAY = 0,
RS_ACTION_DOWNSCALE = -1,
RS_ACTION_UPSCALE = 1,
};
enum rs_column_mode { enum rs_column_mode {
RS_INVALID = 0, RS_INVALID = 0,
RS_LEGACY, RS_LEGACY,
@ -1616,6 +1622,97 @@ err:
return -1; return -1;
} }
static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl,
s32 sr, int low, int high,
int current_tpt,
int low_tpt, int high_tpt)
{
enum rs_action action = RS_ACTION_STAY;
/* Too many failures, decrease rate */
if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
IWL_DEBUG_RATE(mvm,
"decrease rate because of low SR\n");
action = RS_ACTION_DOWNSCALE;
/* No throughput measured yet for adjacent rates; try increase. */
} else if ((low_tpt == IWL_INVALID_VALUE) &&
(high_tpt == IWL_INVALID_VALUE)) {
if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Good SR and no high rate measurement. "
"Increase rate\n");
action = RS_ACTION_UPSCALE;
} else if (low != IWL_RATE_INVALID) {
IWL_DEBUG_RATE(mvm,
"Remain in current rate\n");
action = RS_ACTION_STAY;
}
}
/* Both adjacent throughputs are measured, but neither one has better
* throughput; we're using the best rate, don't change it!
*/
else if ((low_tpt != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) &&
(high_tpt < current_tpt)) {
IWL_DEBUG_RATE(mvm,
"Both high and low are worse. "
"Maintain rate\n");
action = RS_ACTION_STAY;
}
/* At least one adjacent rate's throughput is measured,
* and may have better performance.
*/
else {
/* Higher adjacent rate's throughput is measured */
if (high_tpt != IWL_INVALID_VALUE) {
/* Higher rate has better throughput */
if (high_tpt > current_tpt &&
sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Higher rate is better and good "
"SR. Increate rate\n");
action = RS_ACTION_UPSCALE;
} else {
IWL_DEBUG_RATE(mvm,
"Higher rate isn't better OR "
"no good SR. Maintain rate\n");
action = RS_ACTION_STAY;
}
/* Lower adjacent rate's throughput is measured */
} else if (low_tpt != IWL_INVALID_VALUE) {
/* Lower rate has better throughput */
if (low_tpt > current_tpt) {
IWL_DEBUG_RATE(mvm,
"Lower rate is better. "
"Decrease rate\n");
action = RS_ACTION_DOWNSCALE;
} else if (sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Lower rate isn't better and "
"good SR. Increase rate\n");
action = RS_ACTION_UPSCALE;
}
}
}
/* Sanity check; asked for decrease, but success rate or throughput
* has been good at old rate. Don't change it.
*/
if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) &&
((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low])))) {
IWL_DEBUG_RATE(mvm,
"Sanity check failed. Maintain rate\n");
action = RS_ACTION_STAY;
}
return action;
}
/* /*
* Do rate scaling and search for new modulation mode. * Do rate scaling and search for new modulation mode.
@ -1636,7 +1733,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
int low_tpt = IWL_INVALID_VALUE; int low_tpt = IWL_INVALID_VALUE;
int high_tpt = IWL_INVALID_VALUE; int high_tpt = IWL_INVALID_VALUE;
u32 fail_count; u32 fail_count;
s8 scale_action = 0; enum rs_action scale_action = RS_ACTION_STAY;
u16 rate_mask; u16 rate_mask;
u8 update_lq = 0; u8 update_lq = 0;
struct iwl_scale_tbl_info *tbl, *tbl1; struct iwl_scale_tbl_info *tbl, *tbl1;
@ -1830,85 +1927,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
rs_pretty_lq_type(rate->type), index, current_tpt, sr, rs_pretty_lq_type(rate->type), index, current_tpt, sr,
low, high, low_tpt, high_tpt); low, high, low_tpt, high_tpt);
scale_action = 0; scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,
current_tpt, low_tpt, high_tpt);
/* Too many failures, decrease rate */
if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
IWL_DEBUG_RATE(mvm,
"decrease rate because of low SR\n");
scale_action = -1;
/* No throughput measured yet for adjacent rates; try increase. */
} else if ((low_tpt == IWL_INVALID_VALUE) &&
(high_tpt == IWL_INVALID_VALUE)) {
if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Good SR and no high rate measurement. "
"Increase rate\n");
scale_action = 1;
} else if (low != IWL_RATE_INVALID) {
IWL_DEBUG_RATE(mvm,
"Remain in current rate\n");
scale_action = 0;
}
}
/* Both adjacent throughputs are measured, but neither one has better
* throughput; we're using the best rate, don't change it! */
else if ((low_tpt != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) &&
(high_tpt < current_tpt)) {
IWL_DEBUG_RATE(mvm,
"Both high and low are worse. "
"Maintain rate\n");
scale_action = 0;
}
/* At least one adjacent rate's throughput is measured,
* and may have better performance. */
else {
/* Higher adjacent rate's throughput is measured */
if (high_tpt != IWL_INVALID_VALUE) {
/* Higher rate has better throughput */
if (high_tpt > current_tpt &&
sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Higher rate is better and good "
"SR. Increate rate\n");
scale_action = 1;
} else {
IWL_DEBUG_RATE(mvm,
"Higher rate isn't better OR "
"no good SR. Maintain rate\n");
scale_action = 0;
}
/* Lower adjacent rate's throughput is measured */
} else if (low_tpt != IWL_INVALID_VALUE) {
/* Lower rate has better throughput */
if (low_tpt > current_tpt) {
IWL_DEBUG_RATE(mvm,
"Lower rate is better. "
"Decrease rate\n");
scale_action = -1;
} else if (sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm,
"Lower rate isn't better and "
"good SR. Increase rate\n");
scale_action = 1;
}
}
}
/* Sanity check; asked for decrease, but success rate or throughput
* has been good at old rate. Don't change it. */
if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low])))) {
IWL_DEBUG_RATE(mvm,
"Sanity check failed. Maintain rate\n");
scale_action = 0;
}
/* Force a search in case BT doesn't like us being in MIMO */ /* Force a search in case BT doesn't like us being in MIMO */
if (is_mimo(rate) && if (is_mimo(rate) &&
@ -1920,7 +1940,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
} }
switch (scale_action) { switch (scale_action) {
case -1: case RS_ACTION_DOWNSCALE:
/* Decrease starting rate, update uCode's rate table */ /* Decrease starting rate, update uCode's rate table */
if (low != IWL_RATE_INVALID) { if (low != IWL_RATE_INVALID) {
update_lq = 1; update_lq = 1;
@ -1931,7 +1951,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
} }
break; break;
case 1: case RS_ACTION_UPSCALE:
/* Increase starting rate, update uCode's rate table */ /* Increase starting rate, update uCode's rate table */
if (high != IWL_RATE_INVALID) { if (high != IWL_RATE_INVALID) {
update_lq = 1; update_lq = 1;
@ -1942,7 +1962,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
} }
break; break;
case 0: case RS_ACTION_STAY:
/* No change */ /* No change */
default: default:
break; break;