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

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

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
Loading
Loading
Loading
Loading
+59 −68
Original line number Diff line number Diff line
@@ -1658,85 +1658,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
{
	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) {
			       "Decrease rate because of low SR\n");
		return RS_ACTION_DOWNSCALE;
	}

	if ((low_tpt == IWL_INVALID_VALUE) &&
	    (high_tpt == IWL_INVALID_VALUE) &&
	    (high != IWL_RATE_INVALID)) {
		IWL_DEBUG_RATE(mvm,
				       "Good SR and no high rate measurement. "
				       "Increase rate\n");
			action = RS_ACTION_UPSCALE;
		} else if (low != IWL_RATE_INVALID) {
			       "No data about high/low rates. Increase rate\n");
		return RS_ACTION_UPSCALE;
	}

	if ((high_tpt == IWL_INVALID_VALUE) &&
	    (high != IWL_RATE_INVALID) &&
	    (low_tpt != IWL_INVALID_VALUE) &&
	    (low_tpt < current_tpt)) {
		IWL_DEBUG_RATE(mvm,
				       "Remain in current rate\n");
			action = RS_ACTION_STAY;
			       "No data about high rate and low rate is worse. Increase rate\n");
		return RS_ACTION_UPSCALE;
	}

	if ((high_tpt != IWL_INVALID_VALUE) &&
	    (high_tpt > current_tpt)) {
		IWL_DEBUG_RATE(mvm,
			       "Higher rate is better. Increate rate\n");
		return RS_ACTION_UPSCALE;
	}

	/* 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) &&
	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;
			       "Both high and low are worse. Maintain rate\n");
		return 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) {
	if ((low_tpt != IWL_INVALID_VALUE) &&
	    (low_tpt > current_tpt)) {
		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 rate is better\n");
		action = RS_ACTION_DOWNSCALE;
		goto out;
	}

		/* Lower adjacent rate's throughput is measured */
		} else if (low_tpt != IWL_INVALID_VALUE) {
			/* Lower rate has better throughput */
			if (low_tpt > current_tpt) {
	if ((low_tpt == IWL_INVALID_VALUE) &&
	    (low != IWL_RATE_INVALID)) {
		IWL_DEBUG_RATE(mvm,
					       "Lower rate is better. "
					       "Decrease rate\n");
			       "No data about lower 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;
			}
		}
		goto out;
	}

	/* 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, "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,
			       "Sanity check failed. Maintain rate\n");
				       "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;
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ enum {
#define IWL_RATE_HIGH_TH		10880	/*  85% */
#define IWL_RATE_INCREASE_TH		6400	/*  50% */
#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_MAX	(8000)