]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mt76: track ewma rssi for gain adjustment per station
authorFelix Fietkau <nbd@nbd.name>
Thu, 21 Jun 2018 09:18:00 +0000 (11:18 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 27 Jun 2018 16:15:10 +0000 (19:15 +0300)
This preserves more sensitivity when weak stations are active and avoids
counting signal measurements from other unrelated networks

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mediatek/mt76/mt76x2.h
drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
drivers/net/wireless/mediatek/mt76/mt76x2_main.c
drivers/net/wireless/mediatek/mt76/mt76x2_phy.c

index 21de1168076d828b7cb57f47c5ef6901131c6a49..71fcfa44fb2e3aebfb39fda33e705ddd6a32eff2 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mutex.h>
 #include <linux/bitops.h>
 #include <linux/kfifo.h>
+#include <linux/average.h>
 
 #define MT7662_FIRMWARE                "mt7662.bin"
 #define MT7662_ROM_PATCH       "mt7662_rom_patch.bin"
@@ -47,6 +48,8 @@
 #include "mt76x2_mac.h"
 #include "mt76x2_dfs.h"
 
+DECLARE_EWMA(signal, 10, 8)
+
 struct mt76x2_mcu {
        struct mutex mutex;
 
@@ -69,10 +72,8 @@ struct mt76x2_calibration {
        u8 agc_gain_init[MT_MAX_CHAINS];
        u8 agc_gain_cur[MT_MAX_CHAINS];
 
-       int avg_rssi[MT_MAX_CHAINS];
-       int avg_rssi_all;
-
        u16 false_cca;
+       s8 avg_rssi_all;
        s8 agc_gain_adjust;
        s8 low_gain;
 
@@ -153,6 +154,9 @@ struct mt76x2_sta {
        struct mt76x2_vif *vif;
        struct mt76x2_tx_status status;
        int n_frames;
+
+       struct ewma_signal rssi;
+       int inactive_count;
 };
 
 static inline bool is_mt7612(struct mt76x2_dev *dev)
index 8985446570bdf1750d249578dfc54c0c22ac108b..fc9af79b3e6948f41ddeaa4af2ef5e703c7b1d2e 100644 (file)
@@ -269,21 +269,31 @@ static void mt76x2_remove_hdr_pad(struct sk_buff *skb, int len)
        skb_pull(skb, len);
 }
 
-static struct mt76_wcid *
-mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, u8 idx, bool unicast)
+static struct mt76x2_sta *
+mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx)
 {
-       struct mt76x2_sta *sta;
        struct mt76_wcid *wcid;
 
        if (idx >= ARRAY_SIZE(dev->wcid))
                return NULL;
 
        wcid = rcu_dereference(dev->wcid[idx]);
-       if (unicast || !wcid)
-               return wcid;
+       if (!wcid)
+               return NULL;
 
-       sta = container_of(wcid, struct mt76x2_sta, wcid);
-       return &sta->vif->group_wcid;
+       return container_of(wcid, struct mt76x2_sta, wcid);
+}
+
+static struct mt76_wcid *
+mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x2_sta *sta, bool unicast)
+{
+       if (!sta)
+               return NULL;
+
+       if (unicast)
+               return &sta->wcid;
+       else
+               return &sta->vif->group_wcid;
 }
 
 int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
@@ -291,6 +301,7 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
 {
        struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
        struct mt76x2_rxwi *rxwi = rxi;
+       struct mt76x2_sta *sta;
        u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
        u32 ctl = le32_to_cpu(rxwi->ctl);
        u16 rate = le16_to_cpu(rxwi->rate);
@@ -315,7 +326,8 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
        }
 
        wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl);
-       status->wcid = mt76x2_rx_get_sta_wcid(dev, wcid, unicast);
+       sta = mt76x2_rx_get_sta(dev, wcid);
+       status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast);
 
        len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
        pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo);
@@ -361,6 +373,11 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
        status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
        status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
 
+       if (sta) {
+               ewma_signal_add(&sta->rssi, status->signal);
+               sta->inactive_count = 0;
+       }
+
        return mt76x2_mac_process_rate(status, rate);
 }
 
index e4e41faf6739761d848353f4f7bd7485a87f51c4..3c0ebe6d231c8724fd1284118a20b10edd0ee051 100644 (file)
@@ -294,6 +294,8 @@ mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (vif->type == NL80211_IFTYPE_AP)
                set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
 
+       ewma_signal_init(&msta->rssi);
+
        rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
 
 out:
index 94943aeb249d16a9941a6abb6ab9838ab2f418d8..14aedc3ef731d71c71855020c4837fd0aa74e56c 100644 (file)
@@ -499,22 +499,62 @@ mt76x2_phy_adjust_vga_gain(struct mt76x2_dev *dev)
        mt76x2_phy_set_gain_val(dev);
 }
 
+static int
+mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev)
+{
+       struct mt76x2_sta *sta;
+       struct mt76_wcid *wcid;
+       int i, j, min_rssi = 0;
+       s8 cur_rssi;
+
+       local_bh_disable();
+       rcu_read_lock();
+
+       for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
+               unsigned long mask = dev->wcid_mask[i];
+
+               if (!mask)
+                       continue;
+
+               for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
+                       if (!(mask & 1))
+                               continue;
+
+                       wcid = rcu_dereference(dev->wcid[j]);
+                       if (!wcid)
+                               continue;
+
+                       sta = container_of(wcid, struct mt76x2_sta, wcid);
+                       spin_lock(&dev->mt76.rx_lock);
+                       if (sta->inactive_count++ < 5)
+                               cur_rssi = ewma_signal_read(&sta->rssi);
+                       else
+                               cur_rssi = 0;
+                       spin_unlock(&dev->mt76.rx_lock);
+
+                       if (cur_rssi < min_rssi)
+                               min_rssi = cur_rssi;
+               }
+       }
+
+       rcu_read_unlock();
+       local_bh_enable();
+
+       if (!min_rssi)
+               return -75;
+
+       return min_rssi;
+}
+
 static void
 mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev)
 {
-       u32 val = mt76_rr(dev, MT_BBP(AGC, 20));
-       int rssi0 = (s8) FIELD_GET(MT_BBP_AGC20_RSSI0, val);
-       int rssi1 = (s8) FIELD_GET(MT_BBP_AGC20_RSSI1, val);
        u8 *gain = dev->cal.agc_gain_init;
        u8 gain_delta;
        int low_gain;
+       u32 val;
 
-       dev->cal.avg_rssi[0] = (dev->cal.avg_rssi[0] * 15) / 16 +
-                              (rssi0 << 8) / 16;
-       dev->cal.avg_rssi[1] = (dev->cal.avg_rssi[1] * 15) / 16 +
-                              (rssi1 << 8) / 16;
-       dev->cal.avg_rssi_all = (dev->cal.avg_rssi[0] +
-                                dev->cal.avg_rssi[1]) / 512;
+       dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev);
 
        low_gain = (dev->cal.avg_rssi_all > mt76x2_get_rssi_gain_thresh(dev)) +
                   (dev->cal.avg_rssi_all > mt76x2_get_low_rssi_gain_thresh(dev));