Commit a5d862da authored by Jonas Jelonek's avatar Jonas Jelonek Committed by Kalle Valo
Browse files

ath5k: switch to rate table based lookup



Switching from legacy usage of ieee80211_get_tx_rates() lookup to direct
rate table lookup in struct ieee80211_sta->rates.

The current rate control API allows drivers to directly get rates from
ieee80211_sta->rates. ath5k is currently one of the legacy drivers that
perform translation/merge with the internal rate table via
ieee80211_get_tx_rates provided by rate control API.
For our upcoming changes to rate control API and the implementation of
transmit power control, this patch changes the behaviour. The call to
ieee80211_get_tx_rates and subsequent calls are also avoided. ath5k now
directly reads rates from sta->rates into its internal rate table. Cause
ath5k does not rely on the rate array in SKB->CB, this is not considered
anymore except for the first entry (used for probing).

Tested this on a PCEngines ALIX with CMP9-GP miniPCI wifi card (Atheros
AR5213A). Generated traffic between AP and multiple STAs before and
after applying the patch and simultaneously measured throughput and
captured rc_stats. Comparison resulted in same rate selection and no
performance loss between both runs.

Co-developed-by: default avatarThomas Huehn <thomas.huehn@hs-nordhausen.de>
Signed-off-by: default avatarThomas Huehn <thomas.huehn@hs-nordhausen.de>
Signed-off-by: default avatarJonas Jelonek <jelonek.jonas@gmail.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211215215042.637-1-jelonek.jonas@gmail.com
parent f75c1d55
Loading
Loading
Loading
Loading
+48 −2
Original line number Diff line number Diff line
@@ -727,6 +727,43 @@ ath5k_get_rate_hw_value(const struct ieee80211_hw *hw,
	return hw_rate;
}

static bool ath5k_merge_ratetbl(struct ieee80211_sta *sta,
				struct ath5k_buf *bf,
				struct ieee80211_tx_info *tx_info)
{
	struct ieee80211_sta_rates *ratetbl;
	u8 i;

	if (!sta)
		return false;

	ratetbl = rcu_dereference(sta->rates);
	if (!ratetbl)
		return false;

	if (tx_info->control.rates[0].idx < 0 ||
	    tx_info->control.rates[0].count == 0)
	{
		i = 0;
	} else {
		bf->rates[0] = tx_info->control.rates[0];
		i = 1;
	}

	for ( ; i < IEEE80211_TX_MAX_RATES; i++) {
		bf->rates[i].idx = ratetbl->rate[i].idx;
		bf->rates[i].flags = ratetbl->rate[i].flags;
		if (tx_info->control.use_rts)
			bf->rates[i].count = ratetbl->rate[i].count_rts;
		else if (tx_info->control.use_cts_prot)
			bf->rates[i].count = ratetbl->rate[i].count_cts;
		else
			bf->rates[i].count = ratetbl->rate[i].count;
	}

	return true;
}

static int
ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
		  struct ath5k_txq *txq, int padsize,
@@ -737,6 +774,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
	struct ieee80211_rate *rate;
	struct ieee80211_sta *sta;
	unsigned int mrr_rate[3], mrr_tries[3];
	int i, ret;
	u16 hw_rate;
@@ -753,8 +791,16 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
	if (dma_mapping_error(ah->dev, bf->skbaddr))
		return -ENOSPC;

	ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates,
	if (control)
		sta = control->sta;
	else
		sta = NULL;

	if (!ath5k_merge_ratetbl(sta, bf, info)) {
		ieee80211_get_tx_rates(info->control.vif,
				       sta, skb, bf->rates,
				       ARRAY_SIZE(bf->rates));
	}

	rate = ath5k_get_rate(ah->hw, info, bf, 0);