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

iwlwifi: mvm: rs: fix and cleanup rs_get_rate_action

Change the down/upscale decision logic a bit to be based
on different success ratio thresholds. This fixes the implementation
compared to the rate scale algorithm which was planned to yield
optimal results. Also fix a case where a lower rate wasn't explored
despite being a potential for better throughput.
While at it rewrite rs_get_rate_action to be more clear and clean.

Cc: <stable@vger.kernel.org> [3.14]
Signed-off-by: default avatarEyal Shapira <eyalx.shapira@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 198266a3
...@@ -1658,85 +1658,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, ...@@ -1658,85 +1658,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
{ {
enum rs_action action = RS_ACTION_STAY; enum rs_action action = RS_ACTION_STAY;
/* Too many failures, decrease rate */
if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"decrease rate because of low SR\n"); "Decrease rate because of low SR\n");
action = RS_ACTION_DOWNSCALE; return 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 if ((low_tpt == IWL_INVALID_VALUE) &&
* throughput; we're using the best rate, don't change it! (high_tpt == IWL_INVALID_VALUE) &&
*/ (high != IWL_RATE_INVALID)) {
else if ((low_tpt != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) &&
(high_tpt < current_tpt)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Both high and low are worse. " "No data about high/low rates. Increase rate\n");
"Maintain rate\n"); return RS_ACTION_UPSCALE;
action = RS_ACTION_STAY;
} }
/* At least one adjacent rate's throughput is measured, if ((high_tpt == IWL_INVALID_VALUE) &&
* and may have better performance. (high != IWL_RATE_INVALID) &&
*/ (low_tpt != IWL_INVALID_VALUE) &&
else { (low_tpt < current_tpt)) {
/* Higher adjacent rate's throughput is measured */ IWL_DEBUG_RATE(mvm,
if (high_tpt != IWL_INVALID_VALUE) { "No data about high rate and low rate is worse. Increase rate\n");
/* Higher rate has better throughput */ return RS_ACTION_UPSCALE;
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 */ if ((high_tpt != IWL_INVALID_VALUE) &&
} else if (low_tpt != IWL_INVALID_VALUE) { (high_tpt > current_tpt)) {
/* Lower rate has better throughput */ IWL_DEBUG_RATE(mvm,
if (low_tpt > current_tpt) { "Higher rate is better. Increate rate\n");
IWL_DEBUG_RATE(mvm, return RS_ACTION_UPSCALE;
"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 if ((low_tpt != IWL_INVALID_VALUE) &&
* has been good at old rate. Don't change it. (high_tpt != IWL_INVALID_VALUE) &&
*/ (low_tpt < current_tpt) &&
if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && (high_tpt < current_tpt)) {
((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low])))) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Sanity check failed. Maintain rate\n"); "Both high and low are worse. Maintain rate\n");
action = RS_ACTION_STAY; return RS_ACTION_STAY;
}
if ((low_tpt != IWL_INVALID_VALUE) &&
(low_tpt > current_tpt)) {
IWL_DEBUG_RATE(mvm,
"Lower rate is better\n");
action = RS_ACTION_DOWNSCALE;
goto out;
}
if ((low_tpt == IWL_INVALID_VALUE) &&
(low != IWL_RATE_INVALID)) {
IWL_DEBUG_RATE(mvm,
"No data about lower rate\n");
action = RS_ACTION_DOWNSCALE;
goto out;
}
IWL_DEBUG_RATE(mvm, "Maintain rate\n");
out:
if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) {
if (sr >= RS_SR_NO_DECREASE) {
IWL_DEBUG_RATE(mvm,
"SR is above NO DECREASE. Avoid downscale\n");
action = RS_ACTION_STAY;
} else if (current_tpt > (100 * tbl->expected_tpt[low])) {
IWL_DEBUG_RATE(mvm,
"Current TPT is higher than max expected in low rate. Avoid downscale\n");
action = RS_ACTION_STAY;
} else {
IWL_DEBUG_RATE(mvm, "Decrease rate\n");
}
} }
return action; return action;
......
...@@ -156,6 +156,7 @@ enum { ...@@ -156,6 +156,7 @@ enum {
#define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_HIGH_TH 10880 /* 85% */
#define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */
#define RS_SR_FORCE_DECREASE 1920 /* 15% */ #define RS_SR_FORCE_DECREASE 1920 /* 15% */
#define RS_SR_NO_DECREASE 10880 /* 85% */
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000)
......
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