mt7601u: use EWMA to calculate avg_rssi
authorStanislaw Gruszka <sgruszka@redhat.com>
Mon, 16 Apr 2018 11:56:17 +0000 (13:56 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 24 Apr 2018 17:33:02 +0000 (20:33 +0300)
avr_rssi is not calculated correctly as we do not divide result
by 256 (mt76 sum avg_rssi1 and avg_rssi2 and divide by 512).
However dividing by 256 will make avg_rssi almost the same as
last rssi value - not really an average. So use EWMA to calculate
avg_rssi. I've chosen weight_rcp=4 to convergence quicker on signal
strength changes.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Jakub Kicinski <kubakici@wp.pl>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mediatek/mt7601u/mac.c
drivers/net/wireless/mediatek/mt7601u/mt7601u.h
drivers/net/wireless/mediatek/mt7601u/phy.c

index d55d704..148c36d 100644 (file)
@@ -453,7 +453,7 @@ mt7601u_rx_monitor_beacon(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
 {
        dev->bcn_freq_off = rxwi->freq_off;
        dev->bcn_phy_mode = FIELD_GET(MT_RXWI_RATE_PHY, rate);
-       dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
+       ewma_rssi_add(&dev->avg_rssi, -rssi);
 }
 
 static int
@@ -503,7 +503,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
        if (mt7601u_rx_is_our_beacon(dev, data))
                mt7601u_rx_monitor_beacon(dev, rxwi, rate, rssi);
        else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_U2M))
-               dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
+               ewma_rssi_add(&dev->avg_rssi, -rssi);
        spin_unlock_bh(&dev->con_mon_lock);
 
        return len;
index 9233744..db317d8 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/completion.h>
 #include <net/mac80211.h>
 #include <linux/debugfs.h>
+#include <linux/average.h>
 
 #include "regs.h"
 
@@ -138,6 +139,8 @@ enum {
        MT7601U_STATE_MORE_STATS,
 };
 
+DECLARE_EWMA(rssi, 10, 4);
+
 /**
  * struct mt7601u_dev - adapter structure
  * @lock:              protects @wcid->tx_rate.
@@ -220,7 +223,7 @@ struct mt7601u_dev {
        s8 bcn_freq_off;
        u8 bcn_phy_mode;
 
-       int avg_rssi; /* starts at 0 and converges */
+       struct ewma_rssi avg_rssi;
 
        u8 agc_save;
 
index 9a90f1f..9d2f9a7 100644 (file)
@@ -975,6 +975,7 @@ void mt7601u_agc_restore(struct mt7601u_dev *dev)
 static void mt7601u_agc_tune(struct mt7601u_dev *dev)
 {
        u8 val = mt7601u_agc_default(dev);
+       long avg_rssi;
 
        if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
                return;
@@ -984,9 +985,12 @@ static void mt7601u_agc_tune(struct mt7601u_dev *dev)
         *       Rssi updates are only on beacons and U2M so should work...
         */
        spin_lock_bh(&dev->con_mon_lock);
-       if (dev->avg_rssi <= -70)
+       avg_rssi = ewma_rssi_read(&dev->avg_rssi);
+       WARN_ON_ONCE(avg_rssi == 0);
+       avg_rssi = -avg_rssi;
+       if (avg_rssi <= -70)
                val -= 0x20;
-       else if (dev->avg_rssi <= -60)
+       else if (avg_rssi <= -60)
                val -= 0x10;
        spin_unlock_bh(&dev->con_mon_lock);
 
@@ -1102,7 +1106,7 @@ void mt7601u_phy_con_cal_onoff(struct mt7601u_dev *dev,
        /* Start/stop collecting beacon data */
        spin_lock_bh(&dev->con_mon_lock);
        ether_addr_copy(dev->ap_bssid, info->bssid);
-       dev->avg_rssi = 0;
+       ewma_rssi_init(&dev->avg_rssi);
        dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
        spin_unlock_bh(&dev->con_mon_lock);