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

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: default avatarEyal Shapira <eyal@wizery.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 4107dbd2
Loading
Loading
Loading
Loading
+103 −83
Original line number Diff line number Diff line
@@ -130,6 +130,12 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
	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 {
	RS_INVALID = 0,
	RS_LEGACY,
@@ -1616,6 +1622,97 @@ err:
	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.
@@ -1636,7 +1733,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
	int low_tpt = IWL_INVALID_VALUE;
	int high_tpt = IWL_INVALID_VALUE;
	u32 fail_count;
	s8 scale_action = 0;
	enum rs_action scale_action = RS_ACTION_STAY;
	u16 rate_mask;
	u8 update_lq = 0;
	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,
		       low, high, low_tpt, high_tpt);

	scale_action = 0;

	/* 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;
	}
	scale_action = rs_get_rate_action(mvm, tbl, sr, low, high,
					  current_tpt, low_tpt, high_tpt);

	/* Force a search in case BT doesn't like us being in MIMO */
	if (is_mimo(rate) &&
@@ -1920,7 +1940,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
	}

	switch (scale_action) {
	case -1:
	case RS_ACTION_DOWNSCALE:
		/* Decrease starting rate, update uCode's rate table */
		if (low != IWL_RATE_INVALID) {
			update_lq = 1;
@@ -1931,7 +1951,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
		}

		break;
	case 1:
	case RS_ACTION_UPSCALE:
		/* Increase starting rate, update uCode's rate table */
		if (high != IWL_RATE_INVALID) {
			update_lq = 1;
@@ -1942,7 +1962,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
		}

		break;
	case 0:
	case RS_ACTION_STAY:
		/* No change */
	default:
		break;