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

Commit 90c66bd2 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Johannes Berg
Browse files

mac80211: remove ieee80211_tx_rate dependency in rate mask code



Remove ieee80211_tx_rate dependency in rate_idx_match_legacy_mask(),
rate_idx_match_mcs_mask() and rate_idx_match_mask() in order to use the
previous logic to define a ratemask in rate_control_set_rates() for
station rate table. Moreover move rate mask definition logic in
rate_control_cap_mask()

Signed-off-by: default avatarLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 35225eb7
Loading
Loading
Loading
Loading
+71 −68
Original line number Diff line number Diff line
@@ -353,39 +353,37 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta,
}
EXPORT_SYMBOL(rate_control_send_low);

static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate,
				       int n_bitrates, u32 mask)
static bool rate_idx_match_legacy_mask(s8 *rate_idx, int n_bitrates, u32 mask)
{
	int j;

	/* See whether the selected rate or anything below it is allowed. */
	for (j = rate->idx; j >= 0; j--) {
	for (j = *rate_idx; j >= 0; j--) {
		if (mask & (1 << j)) {
			/* Okay, found a suitable rate. Use it. */
			rate->idx = j;
			*rate_idx = j;
			return true;
		}
	}

	/* Try to find a higher rate that would be allowed */
	for (j = rate->idx + 1; j < n_bitrates; j++) {
	for (j = *rate_idx + 1; j < n_bitrates; j++) {
		if (mask & (1 << j)) {
			/* Okay, found a suitable rate. Use it. */
			rate->idx = j;
			*rate_idx = j;
			return true;
		}
	}
	return false;
}

static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
				    u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
static bool rate_idx_match_mcs_mask(s8 *rate_idx, u8 *mcs_mask)
{
	int i, j;
	int ridx, rbit;

	ridx = rate->idx / 8;
	rbit = rate->idx % 8;
	ridx = *rate_idx / 8;
	rbit = *rate_idx % 8;

	/* sanity check */
	if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN)
@@ -395,20 +393,20 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
	for (i = ridx; i >= 0; i--) {
		for (j = rbit; j >= 0; j--)
			if (mcs_mask[i] & BIT(j)) {
				rate->idx = i * 8 + j;
				*rate_idx = i * 8 + j;
				return true;
			}
		rbit = 7;
	}

	/* Try to find a higher rate that would be allowed */
	ridx = (rate->idx + 1) / 8;
	rbit = (rate->idx + 1) % 8;
	ridx = (*rate_idx + 1) / 8;
	rbit = (*rate_idx + 1) % 8;

	for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
		for (j = rbit; j < 8; j++)
			if (mcs_mask[i] & BIT(j)) {
				rate->idx = i * 8 + j;
				*rate_idx = i * 8 + j;
				return true;
			}
		rbit = 0;
@@ -418,35 +416,30 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,



static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
static void rate_idx_match_mask(s8 *rate_idx, u16 *rate_flags,
				struct ieee80211_supported_band *sband,
				enum nl80211_chan_width chan_width,
				u32 mask,
				u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
{
	struct ieee80211_tx_rate alt_rate;

	/* handle HT rates */
	if (rate->flags & IEEE80211_TX_RC_MCS) {
		if (rate_idx_match_mcs_mask(rate, mcs_mask))
	if (*rate_flags & IEEE80211_TX_RC_MCS) {
		if (rate_idx_match_mcs_mask(rate_idx, mcs_mask))
			return;

		/* also try the legacy rates. */
		alt_rate.idx = 0;
		*rate_idx = 0;
		/* keep protection flags */
		alt_rate.flags = rate->flags &
				 (IEEE80211_TX_RC_USE_RTS_CTS |
		*rate_flags &= (IEEE80211_TX_RC_USE_RTS_CTS |
				IEEE80211_TX_RC_USE_CTS_PROTECT |
				IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
		alt_rate.count = rate->count;
		if (rate_idx_match_legacy_mask(&alt_rate,
					       sband->n_bitrates, mask)) {
			*rate = alt_rate;
		if (rate_idx_match_legacy_mask(rate_idx, sband->n_bitrates,
					       mask))
			return;
		}
	} else if (!(rate->flags & IEEE80211_TX_RC_VHT_MCS)) {
	} else if (!(*rate_flags & IEEE80211_TX_RC_VHT_MCS)) {
		/* handle legacy rates */
		if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask))
		if (rate_idx_match_legacy_mask(rate_idx, sband->n_bitrates,
					       mask))
			return;

		/* if HT BSS, and we handle a data frame, also try HT rates */
@@ -459,24 +452,20 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
			break;
		}

		alt_rate.idx = 0;
		*rate_idx = 0;
		/* keep protection flags */
		alt_rate.flags = rate->flags &
				 (IEEE80211_TX_RC_USE_RTS_CTS |
		*rate_flags &= (IEEE80211_TX_RC_USE_RTS_CTS |
				IEEE80211_TX_RC_USE_CTS_PROTECT |
				IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
		alt_rate.count = rate->count;

		alt_rate.flags |= IEEE80211_TX_RC_MCS;
		*rate_flags |= IEEE80211_TX_RC_MCS;

		if (chan_width == NL80211_CHAN_WIDTH_40)
			alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
			*rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;

		if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
			*rate = alt_rate;
		if (rate_idx_match_mcs_mask(rate_idx, mcs_mask))
			return;
	}
	}

	/*
	 * Uh.. No suitable rate exists. This should not really happen with
@@ -628,6 +617,40 @@ static void rate_control_fill_sta_table(struct ieee80211_sta *sta,
	}
}

static bool rate_control_cap_mask(struct ieee80211_sub_if_data *sdata,
				  struct ieee80211_supported_band *sband,
				  struct ieee80211_sta *sta, u32 *mask,
				  u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
{
	u32 i, flags;

	*mask = sdata->rc_rateidx_mask[sband->band];
	flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
	for (i = 0; i < sband->n_bitrates; i++) {
		if ((flags & sband->bitrates[i].flags) != flags)
			*mask &= ~BIT(i);
	}

	if (*mask == (1 << sband->n_bitrates) - 1 &&
	    !sdata->rc_has_mcs_mask[sband->band])
		return false;

	if (sdata->rc_has_mcs_mask[sband->band])
		memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[sband->band],
		       IEEE80211_HT_MCS_MASK_LEN);
	else
		memset(mcs_mask, 0xff, IEEE80211_HT_MCS_MASK_LEN);

	if (sta) {
		/* Filter out rates that the STA does not support */
		*mask &= sta->supp_rates[sband->band];
		for (i = 0; i < sizeof(mcs_mask); i++)
			mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i];
	}

	return true;
}

static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
				    struct ieee80211_sta *sta,
				    struct ieee80211_supported_band *sband,
@@ -636,9 +659,8 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
{
	enum nl80211_chan_width chan_width;
	u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
	bool has_mcs_mask;
	u32 mask;
	u32 rate_flags;
	u16 rate_flags;
	int i;

	/*
@@ -646,30 +668,9 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
	 * default mask (allow all rates) is used to save some processing for
	 * the common case.
	 */
	mask = sdata->rc_rateidx_mask[sband->band];
	has_mcs_mask = sdata->rc_has_mcs_mask[sband->band];
	rate_flags =
		ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
	for (i = 0; i < sband->n_bitrates; i++)
		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
			mask &= ~BIT(i);

	if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask)
	if (!rate_control_cap_mask(sdata, sband, sta, &mask, mcs_mask))
		return;

	if (has_mcs_mask)
		memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[sband->band],
		       sizeof(mcs_mask));
	else
		memset(mcs_mask, 0xff, sizeof(mcs_mask));

	if (sta) {
		/* Filter out rates that the STA does not support */
		mask &= sta->supp_rates[sband->band];
		for (i = 0; i < sizeof(mcs_mask); i++)
			mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i];
	}

	/*
	 * Make sure the rate index selected for each TX rate is
	 * included in the configured mask and change the rate indexes
@@ -681,8 +682,10 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
		if (rates[i].idx < 0)
			break;

		rate_idx_match_mask(&rates[i], sband, chan_width, mask,
				    mcs_mask);
		rate_flags = rates[i].flags;
		rate_idx_match_mask(&rates[i].idx, &rate_flags, sband,
				    chan_width, mask, mcs_mask);
		rates[i].flags = rate_flags;
	}
}