Search Linux Wireless

[PATCH v2] ath9k: switch to rate table based lookup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch changes mac80211 rate control for the ath9k driver.
The rate lookup per packet is changed from legacy usage of
ieee80211_get_tx_rates() to the new rate table based lookup in struct
ieee80211_sta->rates.

The most recent rate control API (introduced with
0d528d85c519b755b6f4e1bafa3a39984370e1c1) allows drivers to directly get
rates from ieee80211_sta->rates. This is not used by every driver yet,
the translation/merge is currently performed in ieee80211_get_tx_rates.
This patch changes the behaviour and avoids the call to
ieee80211_get_tx_rates and subsequent calls. ath9k now directly reads
rates from sta->rates into its rate table. Cause ath9k does not
expect rate selection in SKB->CB, the table merge does not consider rate
array in SKB->CB except for the first entry (used for probing).

Tested with a 8devices Rambutan with QCA9558 SoC by performing two
runs, one without the patch and one with. Generated traffic between
AP and multiple STAs in each run, measured throughput and captured rc_stats.
Comparison of both runs resulted in same rate selection and no
performance loss or other negative effects.

Co-developed-by: Thomas Huehn <thomas.huehn@xxxxxxxxxxxxxxxx>
Signed-off-by: Thomas Huehn <thomas.huehn@xxxxxxxxxxxxxxxx>
Signed-off-by: Jonas Jelonek <jelonek.jonas@xxxxxxxxx>

---
v2: Improved commit message with context information and testing
---
 drivers/net/wireless/ath/ath9k/xmit.c | 45 +++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 5691bd6eb82c..d0caf1de2bde 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -154,11 +154,52 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
 			   seqno << IEEE80211_SEQ_SEQ_SHIFT);
 }
 
+static bool ath_merge_ratetbl(struct ieee80211_sta *sta, struct ath_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 void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
 			  struct ath_buf *bf)
 {
-	ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
-			       ARRAY_SIZE(bf->rates));
+	struct ieee80211_tx_info *tx_info;
+
+	tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+
+	if (!ath_merge_ratetbl(sta, bf, tx_info))
+		ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
+				       ARRAY_SIZE(bf->rates));
 }
 
 static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
-- 
2.30.2




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux