[source] ath9k: fix various issues in the airtime-fairness implementation

LEDE Commits lede-commits at lists.infradead.org
Sun Feb 12 05:40:18 PST 2017


nbd pushed a commit to source.git, branch lede-17.01:
https://git.lede-project.org/e967f4dd27774ed5e760cae8a9c6d8f1be08f7b1

commit e967f4dd27774ed5e760cae8a9c6d8f1be08f7b1
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Sun Feb 12 13:25:08 2017 +0100

    ath9k: fix various issues in the airtime-fairness implementation
    
    Effects of the bugs could include memory corruption, tx hangs, kernel
    crahes, possibly other things as well
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...h9k-clean-up-and-fix-ath_tx_count_airtime.patch | 107 +++++++++++++++++++++
 ...-ath9k-consistently-use-get_eeprom_rev-ah.patch |   2 +-
 2 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/package/kernel/mac80211/patches/366-ath9k-clean-up-and-fix-ath_tx_count_airtime.patch b/package/kernel/mac80211/patches/366-ath9k-clean-up-and-fix-ath_tx_count_airtime.patch
new file mode 100644
index 0000000..a6a3bfc
--- /dev/null
+++ b/package/kernel/mac80211/patches/366-ath9k-clean-up-and-fix-ath_tx_count_airtime.patch
@@ -0,0 +1,107 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Sun, 12 Feb 2017 13:13:05 +0100
+Subject: [PATCH] ath9k: clean up and fix ath_tx_count_airtime
+
+ath_tx_count_airtime is doing a lot of unnecessary work:
+
+- Redundant station lookup
+- Redundant rcu_read_lock/unlock
+- Useless memcpy of bf->rates
+- Useless NULL check of bf->bf_mpdu
+- Redundant lookup of the skb tid
+
+Additionally, it tries to look up the mac80211 queue index from the txq,
+which fails if the frame was delivered via the power save queue.
+
+This patch fixes all of these issues by passing down the right set of
+pointers instead of doing extra work
+
+Cc: stable at vger.kernel.org
+Fixes: 63fefa050477 ("ath9k: Introduce airtime fairness scheduling between stations")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -723,51 +723,31 @@ static bool bf_is_ampdu_not_probing(stru
+     return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+ }
+ 
+-static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq,
+-				 struct ath_buf *bf, struct ath_tx_status *ts)
++static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
++				 struct ath_atx_tid *tid, struct ath_buf *bf,
++				 struct ath_tx_status *ts)
+ {
+-	struct ath_node *an;
+-	struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum];
+-	struct sk_buff *skb;
+-	struct ieee80211_hdr *hdr;
+-	struct ieee80211_hw *hw = sc->hw;
+-	struct ieee80211_tx_rate rates[4];
+-	struct ieee80211_sta *sta;
+-	int i;
++	struct ath_txq *txq = tid->txq;
+ 	u32 airtime = 0;
+-
+-	skb = bf->bf_mpdu;
+-	if(!skb)
+-		return;
+-
+-	hdr = (struct ieee80211_hdr *)skb->data;
+-	memcpy(rates, bf->rates, sizeof(rates));
+-
+-	rcu_read_lock();
+-
+-	sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+-	if(!sta)
+-		goto exit;
+-
+-
+-	an = (struct ath_node *) sta->drv_priv;
++	int i;
+ 
+ 	airtime += ts->duration * (ts->ts_longretry + 1);
++	for(i = 0; i < ts->ts_rateindex; i++) {
++		int rate_dur = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i);
++		airtime += rate_dur * bf->rates[i].count;
++	}
+ 
+-	for(i=0; i < ts->ts_rateindex; i++)
+-		airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count;
++	if (sc->airtime_flags & AIRTIME_USE_TX) {
++		int q = txq->mac80211_qnum;
++		struct ath_acq *acq = &sc->cur_chan->acq[q];
+ 
+-	if (!!(sc->airtime_flags & AIRTIME_USE_TX)) {
+ 		spin_lock_bh(&acq->lock);
+-		an->airtime_deficit[txq->mac80211_qnum] -= airtime;
+-		if (an->airtime_deficit[txq->mac80211_qnum] <= 0)
+-			__ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb));
++		an->airtime_deficit[q] -= airtime;
++		if (an->airtime_deficit[q] <= 0)
++			__ath_tx_queue_tid(sc, tid);
+ 		spin_unlock_bh(&acq->lock);
+ 	}
+ 	ath_debug_airtime(sc, an, 0, airtime);
+-
+-exit:
+-	rcu_read_unlock();
+ }
+ 
+ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+@@ -791,13 +771,13 @@ static void ath_tx_process_buffer(struct
+ 
+ 	ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
+ 					     ts->ts_rateindex);
+-	ath_tx_count_airtime(sc, txq, bf, ts);
+ 
+ 	hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
+ 	sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+ 	if (sta) {
+ 		struct ath_node *an = (struct ath_node *)sta->drv_priv;
+ 		tid = ath_get_skb_tid(sc, an, bf->bf_mpdu);
++		ath_tx_count_airtime(sc, an, tid, bf, ts);
+ 		if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
+ 			tid->clear_ps_filter = true;
+ 	}
diff --git a/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch b/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
index 86809fd..fd53492 100644
--- a/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
+++ b/package/kernel/mac80211/patches/554-ath9k-consistently-use-get_eeprom_rev-ah.patch
@@ -329,7 +329,7 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
  					       &ratesArray[0], cfgCtl,
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1236,8 +1236,9 @@ static u8 ath_get_rate_txpower(struct at
+@@ -1216,8 +1216,9 @@ static u8 ath_get_rate_txpower(struct at
  		if (is_40) {
  			u8 power_ht40delta;
  			struct ar5416_eeprom_def *eep = &ah->eeprom.def;



More information about the lede-commits mailing list