ath9k: dynack: make ewma estimation faster [Linux 4.9.156]

This Linux kernel change "ath9k: dynack: make ewma estimation faster" is included in the Linux 4.9.156 release. This change is authored by Lorenzo Bianconi <lorenzo.bianconi [at] redhat.com> on Fri Nov 2 21:49:58 2018 +0100. The commit for this change in Linux stable tree is e7b2ead (patch) which is from upstream commit 0c60c49. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 0c60c49.

ath9k: dynack: make ewma estimation faster

commit 0c60c490830a1a756c80f8de8d33d9c6359d4a36 upstream.

In order to make propagation time estimation faster,
use current sample as ewma output value during 'late ack'
tracking

Tested-by: Koen Vandeputte <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 41 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/wireless/ath/ath9k/ath9k.h  |  2 +-
 drivers/net/wireless/ath/ath9k/dynack.c | 28 +++++++++++++++++++++-------
 drivers/net/wireless/ath/ath9k/dynack.h |  6 ++++--
 drivers/net/wireless/ath/ath9k/xmit.c   |  5 +++--
 4 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a731671..7bda18c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -267,7 +267,7 @@ struct ath_node {
 #endif
    u8 key_idx[4];

-   u32 ackto;
+   int ackto;
    struct list_head list;
 };

diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
index cc0dc96..d2a7531 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -29,9 +29,13 @@
  * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
  *
  */
-static inline u32 ath_dynack_ewma(u32 old, u32 new)
+static inline int ath_dynack_ewma(int old, int new)
 {
-   return (new * (EWMA_DIV - EWMA_LEVEL) + old * EWMA_LEVEL) / EWMA_DIV;
+   if (old > 0)
+       return (new * (EWMA_DIV - EWMA_LEVEL) +
+           old * EWMA_LEVEL) / EWMA_DIV;
+   else
+       return new;
 }

 /**
@@ -82,10 +86,10 @@ static inline bool ath_dynack_bssidmask(struct ath_hw *ah, const u8 *mac)
  */
 static void ath_dynack_compute_ackto(struct ath_hw *ah)
 {
-   struct ath_node *an;
-   u32 to = 0;
-   struct ath_dynack *da = &ah->dynack;
    struct ath_common *common = ath9k_hw_common(ah);
+   struct ath_dynack *da = &ah->dynack;
+   struct ath_node *an;
+   int to = 0;

    list_for_each_entry(an, &da->nodes, list)
        if (an->ackto > to)
@@ -144,7 +148,8 @@ static void ath_dynack_compute_to(struct ath_hw *ah)
                    an->ackto = ath_dynack_ewma(an->ackto,
                                    ackto);
                    ath_dbg(ath9k_hw_common(ah), DYNACK,
-                       "%pM to %u\n", dst, an->ackto);
+                       "%pM to %d [%u]\n", dst,
+                       an->ackto, ackto);
                    if (time_is_before_jiffies(da->lto)) {
                        ath_dynack_compute_ackto(ah);
                        da->lto = jiffies + COMPUTE_TO;
@@ -166,10 +171,12 @@ static void ath_dynack_compute_to(struct ath_hw *ah)
  * @ah: ath hw
  * @skb: socket buffer
  * @ts: tx status info
+ * @sta: station pointer
  *
  */
 void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
-                struct ath_tx_status *ts)
+                struct ath_tx_status *ts,
+                struct ieee80211_sta *sta)
 {
    u8 ridx;
    struct ieee80211_hdr *hdr;
@@ -190,9 +197,16 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
            ieee80211_is_assoc_resp(hdr->frame_control) ||
            ieee80211_is_auth(hdr->frame_control)) {
            ath_dbg(common, DYNACK, "late ack\n");
+
            ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2);
            ath9k_hw_set_ack_timeout(ah, LATEACK_TO);
            ath9k_hw_set_cts_timeout(ah, LATEACK_TO);
+           if (sta) {
+               struct ath_node *an;
+
+               an = (struct ath_node *)sta->drv_priv;
+               an->ackto = -1;
+           }
            da->lto = jiffies + LATEACK_DELAY;
        }

diff --git a/drivers/net/wireless/ath/ath9k/dynack.h b/drivers/net/wireless/ath/ath9k/dynack.h
index 6d7bef9..cf60224 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.h
+++ b/drivers/net/wireless/ath/ath9k/dynack.h
@@ -86,7 +86,8 @@ struct ath_dynack {
 void ath_dynack_init(struct ath_hw *ah);
 void ath_dynack_sample_ack_ts(struct ath_hw *ah, struct sk_buff *skb, u32 ts);
 void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
-                struct ath_tx_status *ts);
+                struct ath_tx_status *ts,
+                struct ieee80211_sta *sta);
 #else
 static inline void ath_dynack_init(struct ath_hw *ah) {}
 static inline void ath_dynack_node_init(struct ath_hw *ah,
@@ -97,7 +98,8 @@ static inline void ath_dynack_sample_ack_ts(struct ath_hw *ah,
                        struct sk_buff *skb, u32 ts) {}
 static inline void ath_dynack_sample_tx_ts(struct ath_hw *ah,
                       struct sk_buff *skb,
-                      struct ath_tx_status *ts) {}
+                      struct ath_tx_status *ts,
+                      struct ieee80211_sta *sta) {}
 #endif

 #endif /* DYNACK_H */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 8a504af..0ef27d9 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -593,7 +593,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                if (bf == bf->bf_lastbf)
                    ath_dynack_sample_tx_ts(sc->sc_ah,
                                bf->bf_mpdu,
-                               ts);
+                               ts, sta);
            }

            ath_tx_complete_buf(sc, bf, txq, &bf_head, sta, ts,
@@ -709,7 +709,8 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
            memcpy(info->control.rates, bf->rates,
                   sizeof(info->control.rates));
            ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
-           ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts);
+           ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts,
+                       sta);
        }
        ath_tx_complete_buf(sc, bf, txq, bf_head, sta, ts, txok);
    } else

Leave a Reply

Your email address will not be published. Required fields are marked *