OSDN Git Service

wifi: mt76: mt7996: enable ack signal support
authorRyder Lee <ryder.lee@mediatek.com>
Thu, 1 Dec 2022 03:44:43 +0000 (11:44 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 1 Dec 2022 16:29:15 +0000 (17:29 +0100)
This reports signal strength of ACK packets from the peer as measured
at each interface.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7996/init.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
drivers/net/wireless/mediatek/mt76/mt7996/regs.h

index cd1657e..46b2905 100644 (file)
@@ -180,6 +180,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
 
        if (!mdev->dev->of_node ||
            !of_property_read_bool(mdev->dev->of_node,
@@ -240,6 +241,12 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
        set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) |
              FIELD_PREP(MT_WF_RMAC_MIB_ED_OFFSET, 4);
        mt76_rmw(dev, MT_WF_RMAC_MIB_AIRTIME0(band), mask, set);
+
+       /* filter out non-resp frames and get instanstaeous signal reporting */
+       mask = MT_WTBLOFF_RSCR_RCPI_MODE | MT_WTBLOFF_RSCR_RCPI_PARAM;
+       set = FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_MODE, 0) |
+             FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_PARAM, 0x3);
+       mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
 }
 
 static void mt7996_mac_init(struct mt7996_dev *dev)
index 9e6aa9c..0b3e287 100644 (file)
@@ -10,7 +10,7 @@
 #include "mac.h"
 #include "mcu.h"
 
-#define to_rssi(field, rxv)    ((FIELD_GET(field, rxv) - 220) / 2)
+#define to_rssi(field, rcpi)   ((FIELD_GET(field, rcpi) - 220) / 2)
 
 #define HE_BITS(f)             cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
 #define HE_PREP(f, m, v)       le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
@@ -124,6 +124,7 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
                bool clear = false;
                u32 addr, val;
                u16 idx;
+               s8 rssi[4];
                u8 bw;
 
                spin_lock_bh(&dev->sta_poll_lock);
@@ -137,6 +138,8 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
                spin_unlock_bh(&dev->sta_poll_lock);
 
                idx = msta->wcid.idx;
+
+               /* refresh peer's airtime reporting */
                addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
 
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
@@ -213,6 +216,20 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
                        else
                                rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
                }
+
+               /* get signal strength of resp frames (CTS/BA/ACK) */
+               addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
+               val = mt76_rr(dev, addr);
+
+               rssi[0] = to_rssi(GENMASK(7, 0), val);
+               rssi[1] = to_rssi(GENMASK(15, 8), val);
+               rssi[2] = to_rssi(GENMASK(23, 16), val);
+               rssi[3] = to_rssi(GENMASK(31, 14), val);
+
+               msta->ack_signal =
+                       mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
+
+               ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
        }
 
        rcu_read_unlock();
index d43530a..f2129be 100644 (file)
@@ -595,6 +595,8 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
        msta->jiffies = jiffies;
 
+       ewma_avg_signal_init(&msta->avg_ack_signal);
+
        mt7996_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -917,6 +919,12 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
        }
        sinfo->txrate.flags = txrate->flags;
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+
+       sinfo->ack_signal = (s8)msta->ack_signal;
+       sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
+
+       sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
+       sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
 }
 
 static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
index 0d097cd..521769e 100644 (file)
 #include "../trace.h"
 
 static const struct __base mt7996_reg_base[] = {
-       [WF_AGG_BASE]   = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
-       [WF_MIB_BASE]   = { { 0x820ed000, 0x820fd000, 0x830ed000 } },
-       [WF_TMAC_BASE]  = { { 0x820e4000, 0x820f4000, 0x830e4000 } },
-       [WF_RMAC_BASE]  = { { 0x820e5000, 0x820f5000, 0x830e5000 } },
-       [WF_ARB_BASE]   = { { 0x820e3000, 0x820f3000, 0x830e3000 } },
-       [WF_LPON_BASE]  = { { 0x820eb000, 0x820fb000, 0x830eb000 } },
-       [WF_ETBF_BASE]  = { { 0x820ea000, 0x820fa000, 0x830ea000 } },
-       [WF_DMA_BASE]   = { { 0x820e7000, 0x820f7000, 0x830e7000 } },
+       [WF_AGG_BASE]           = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
+       [WF_ARB_BASE]           = { { 0x820e3000, 0x820f3000, 0x830e3000 } },
+       [WF_TMAC_BASE]          = { { 0x820e4000, 0x820f4000, 0x830e4000 } },
+       [WF_RMAC_BASE]          = { { 0x820e5000, 0x820f5000, 0x830e5000 } },
+       [WF_DMA_BASE]           = { { 0x820e7000, 0x820f7000, 0x830e7000 } },
+       [WF_WTBLOFF_BASE]       = { { 0x820e9000, 0x820f9000, 0x830e9000 } },
+       [WF_ETBF_BASE]          = { { 0x820ea000, 0x820fa000, 0x830ea000 } },
+       [WF_LPON_BASE]          = { { 0x820eb000, 0x820fb000, 0x830eb000 } },
+       [WF_MIB_BASE]           = { { 0x820ed000, 0x820fd000, 0x830ed000 } },
 };
 
 static const struct __map mt7996_reg_map[] = {
index 00c5887..17dcd05 100644 (file)
@@ -85,6 +85,8 @@ struct mt7996_twt_flow {
        u8 sched:1;
 };
 
+DECLARE_EWMA(avg_signal, 10, 8)
+
 struct mt7996_sta {
        struct mt76_wcid wcid; /* must be first */
 
@@ -94,6 +96,9 @@ struct mt7996_sta {
        struct list_head rc_list;
        u32 airtime_ac[8];
 
+       int ack_signal;
+       struct ewma_avg_signal avg_ack_signal;
+
        unsigned long changed;
        unsigned long jiffies;
        unsigned long ampdu_state;
index 1d53611..794f61b 100644 (file)
@@ -25,13 +25,14 @@ struct mt7996_reg_desc {
 
 enum base_rev {
        WF_AGG_BASE,
-       WF_MIB_BASE,
+       WF_ARB_BASE,
        WF_TMAC_BASE,
        WF_RMAC_BASE,
-       WF_ARB_BASE,
-       WF_LPON_BASE,
-       WF_ETBF_BASE,
        WF_DMA_BASE,
+       WF_WTBLOFF_BASE,
+       WF_ETBF_BASE,
+       WF_LPON_BASE,
+       WF_MIB_BASE,
        __MT_REG_BASE_MAX,
 };
 
@@ -97,6 +98,14 @@ enum base_rev {
 #define MT_DMA_TCRF1(_band)                    MT_WF_DMA(_band, 0x054)
 #define MT_DMA_TCRF1_QIDX                      GENMASK(15, 13)
 
+/* WTBLOFF TOP: band 0(0x820e9000), band 1(0x820f9000), band 2(0x830e9000) */
+#define MT_WTBLOFF_BASE(_band)                 __BASE(WF_WTBLOFF_BASE, (_band))
+#define MT_WTBLOFF(_band, ofs)                 (MT_WTBLOFF_BASE(_band) + (ofs))
+
+#define MT_WTBLOFF_RSCR(_band)                 MT_WTBLOFF(_band, 0x008)
+#define MT_WTBLOFF_RSCR_RCPI_MODE              GENMASK(31, 30)
+#define MT_WTBLOFF_RSCR_RCPI_PARAM             GENMASK(25, 24)
+
 /* ETBF: band 0(0x820ea000), band 1(0x820fa000), band 2(0x830ea000) */
 #define MT_WF_ETBF_BASE(_band)                 __BASE(WF_ETBF_BASE, (_band))
 #define MT_WF_ETBF(_band, ofs)                 (MT_WF_ETBF_BASE(_band) + (ofs))