wifi: mt76: mt7915: add ack signal support
authorRyder Lee <ryder.lee@mediatek.com>
Fri, 14 Oct 2022 02:57:48 +0000 (10:57 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 1 Dec 2022 16:29:12 +0000 (17:29 +0100)
This reports signal strength of ACK packets from the peer as measured
at each interface.

Tested-by: Shurong Wen <shurong.wen@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
drivers/net/wireless/mediatek/mt76/mt7915/regs.h

index 4bdbfd0f623374772877572ae28b67adf28737f0..c59d1200445900cd886f76b50a5c224bd5fdae78 100644 (file)
@@ -951,14 +951,12 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
 }
 EXPORT_SYMBOL(mt76_wcid_key_setup);
 
-static int
-mt76_rx_signal(struct mt76_rx_status *status)
+int mt76_rx_signal(u8 chain_mask, s8 *chain_signal)
 {
-       s8 *chain_signal = status->chain_signal;
        int signal = -128;
        u8 chains;
 
-       for (chains = status->chains; chains; chains >>= 1, chain_signal++) {
+       for (chains = chain_mask; chains; chains >>= 1, chain_signal++) {
                int cur, diff;
 
                cur = *chain_signal;
@@ -980,6 +978,7 @@ mt76_rx_signal(struct mt76_rx_status *status)
 
        return signal;
 }
+EXPORT_SYMBOL(mt76_rx_signal);
 
 static void
 mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
@@ -1009,7 +1008,7 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
        status->ampdu_reference = mstat.ampdu_ref;
        status->device_timestamp = mstat.timestamp;
        status->mactime = mstat.timestamp;
-       status->signal = mt76_rx_signal(&mstat);
+       status->signal = mt76_rx_signal(mstat.chains, mstat.chain_signal);
        if (status->signal <= -128)
                status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
index f9bdf16fc6c4a58f6d542483521a2ee7132aaeeb..c91fb9bde63280ca04918ddd1296183ea7f401f6 100644 (file)
@@ -1149,6 +1149,7 @@ void mt76_update_survey(struct mt76_phy *phy);
 void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time);
 int mt76_get_survey(struct ieee80211_hw *hw, int idx,
                    struct survey_info *survey);
+int mt76_rx_signal(u8 chain_mask, s8 *chain_signal);
 void mt76_set_stream_caps(struct mt76_phy *phy, bool vht);
 
 int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid,
index e864c0ab6c7fbdcc8746b072c36443d7f11fff17..a042e01542117c35f80d469a5ed137ade9df10cd 100644 (file)
@@ -353,6 +353,7 @@ mt7915_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,
@@ -461,6 +462,12 @@ mt7915_mac_init_band(struct mt7915_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_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
+       set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
+             FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
+       mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
 }
 
 static void mt7915_mac_init(struct mt7915_dev *dev)
index 324f0f58572b12efefce6c61e5b3c835c7b6595c..760ad786e56618c4cf2aac5acdc65a0103ed54a8 100644 (file)
@@ -8,7 +8,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)
 
 static const struct mt7915_dfs_radar_spec etsi_radar_specs = {
        .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
@@ -118,6 +118,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
                bool clear = false;
                u32 addr, val;
                u16 idx;
+               s8 rssi[4];
                u8 bw;
 
                spin_lock_bh(&dev->sta_poll_lock);
@@ -131,6 +132,8 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
                spin_unlock_bh(&dev->sta_poll_lock);
 
                idx = msta->wcid.idx;
+
+               /* refresh peer's airtime reporting */
                addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 20);
 
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
@@ -209,6 +212,20 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
                        else
                                rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
                }
+
+               /* get signal strength of resp frames (CTS/BA/ACK) */
+               addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 30);
+               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 0ebaed174d5da1c7c9602bf596ec8b40b2c6e050..7f1e76d591186c2205a3793e53873390d67780e9 100644 (file)
@@ -665,6 +665,8 @@ int mt7915_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);
+
        mt7915_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -1025,6 +1027,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
                sinfo->tx_retries = msta->wcid.stats.tx_retries;
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
        }
+
+       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 mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
index fe6a6d3b0a32d928c692fb0b29ae25474cc42c12..e6ae02eb2731501f169bcd1ae17831f8e9672d1e 100644 (file)
@@ -114,6 +114,8 @@ struct mt7915_twt_flow {
        u8 sched:1;
 };
 
+DECLARE_EWMA(avg_signal, 10, 8)
+
 struct mt7915_sta {
        struct mt76_wcid wcid; /* must be first */
 
@@ -123,10 +125,12 @@ struct mt7915_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;
-
        struct mt76_connac_sta_key_conf bip;
 
        struct {
index 7db809671230955e64dbc89c1a37ed557e3f9f72..9924271d8e36eb78af52725d251f9eb3c6dbe88d 100644 (file)
@@ -226,6 +226,14 @@ enum offs_rev {
 #define MT_DMA_DCR0_MAX_RX_LEN         GENMASK(15, 3)
 #define MT_DMA_DCR0_RXD_G5_EN          BIT(23)
 
+/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */
+#define MT_WTBLOFF_TOP_BASE(_band)     ((_band) ? 0x820f9000 : 0x820e9000)
+#define MT_WTBLOFF_TOP(_band, ofs)     (MT_WTBLOFF_TOP_BASE(_band) + (ofs))
+
+#define MT_WTBLOFF_TOP_RSCR(_band)     MT_WTBLOFF_TOP(_band, 0x008)
+#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE  GENMASK(31, 30)
+#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24)
+
 /* ETBF: band 0(0x820ea000), band 1(0x820fa000) */
 #define MT_WF_ETBF_BASE(_band)         ((_band) ? 0x820fa000 : 0x820ea000)
 #define MT_WF_ETBF(_band, ofs)         (MT_WF_ETBF_BASE(_band) + (ofs))