wifi: mt76: mt7996: Add mcu commands for getting sta tx statistic
authorYi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Thu, 21 Sep 2023 21:04:01 +0000 (14:04 -0700)
committerFelix Fietkau <nbd@nbd.name>
Sat, 30 Sep 2023 18:17:18 +0000 (20:17 +0200)
Per peer Tx/Rx statistic can only be obtained by querying WM when WED is
on. This patch switches to periodic event reporting in the case of WED
being enabled.

Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Signed-off-by: Money Wang <Money.Wang@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 9bc97a35fc1dcbf759ee6b6ac4c1436ec5d85337..e97adaf9976c862d7a01be98f55a54cf9fda94c4 100644 (file)
@@ -1022,6 +1022,8 @@ enum {
        MCU_UNI_EVENT_ROC = 0x27,
        MCU_UNI_EVENT_TX_DONE = 0x2d,
        MCU_UNI_EVENT_NIC_CAPAB = 0x43,
+       MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
+       MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
 };
 
 #define MCU_UNI_CMD_EVENT                      BIT(1)
@@ -1240,6 +1242,8 @@ enum {
        MCU_UNI_CMD_VOW = 0x37,
        MCU_UNI_CMD_RRO = 0x57,
        MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+       MCU_UNI_CMD_PER_STA_INFO = 0x6d,
+       MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
        MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
 };
 
@@ -1320,6 +1324,17 @@ enum {
        UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
 };
 
+enum UNI_ALL_STA_INFO_TAG {
+       UNI_ALL_STA_TX_RATE,
+       UNI_ALL_STA_TX_STAT,
+       UNI_ALL_STA_TXRX_ADM_STAT,
+       UNI_ALL_STA_TXRX_AIR_TIME,
+       UNI_ALL_STA_DATA_TX_RETRY_COUNT,
+       UNI_ALL_STA_GI_MODE,
+       UNI_ALL_STA_TXRX_MSDU_COUNT,
+       UNI_ALL_STA_MAX_NUM
+};
+
 enum {
        MT_NIC_CAP_TX_RESOURCE,
        MT_NIC_CAP_TX_EFUSE_ADDR,
index 83e910eb755ca7558117f258757bfc76fb0eb7d5..dc5e4739fd0796d9aefab9c880947114c8a7be5d 100644 (file)
@@ -2202,6 +2202,11 @@ void mt7996_mac_work(struct work_struct *work)
                mphy->mac_work_count = 0;
 
                mt7996_mac_update_stats(phy);
+
+               if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
+                       mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
+                       mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
+               }
        }
 
        mutex_unlock(&mphy->dev->mutex);
index 0072809ae6172e68732542613f7800c4cca2ed7f..ce16637b45ce7f1e994454c05e7d3231d4095da4 100644 (file)
@@ -969,6 +969,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
                                  struct ieee80211_sta *sta,
                                  struct station_info *sinfo)
 {
+       struct mt7996_phy *phy = mt7996_hw_phy(hw);
        struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
        struct rate_info *txrate = &msta->wcid.rate;
 
@@ -1000,6 +1001,20 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
 
        sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
+
+       if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
+               sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
+
+               sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
+
+               sinfo->tx_packets = msta->wcid.stats.tx_packets;
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+
+               sinfo->rx_packets = msta->wcid.stats.rx_packets;
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
+       }
 }
 
 static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
index 12bf4e5038b51949edf4291e7761635cff49365a..bf917beb943961e7606544080306f9645048606c 100644 (file)
@@ -449,6 +449,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
        }
 }
 
+static void
+mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+{
+       struct mt7996_mcu_all_sta_info_event *res;
+       u16 i;
+
+       skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
+
+       res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
+
+       for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
+               u8 ac;
+               u16 wlan_idx;
+               struct mt76_wcid *wcid;
+
+               switch (le16_to_cpu(res->tag)) {
+               case UNI_ALL_STA_TXRX_ADM_STAT:
+                       wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
+                       wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+
+                       if (!wcid)
+                               break;
+
+                       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+                               wcid->stats.tx_bytes +=
+                                       le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
+                               wcid->stats.rx_bytes +=
+                                       le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
+                       }
+                       break;
+               case UNI_ALL_STA_TXRX_MSDU_COUNT:
+                       wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
+                       wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+
+                       if (!wcid)
+                               break;
+
+                       wcid->stats.tx_packets +=
+                               le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
+                       wcid->stats.rx_packets +=
+                               le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
 static void
 mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
 {
@@ -493,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
        case MCU_UNI_EVENT_RDD_REPORT:
                mt7996_mcu_rx_radar_detected(dev, skb);
                break;
+       case MCU_UNI_EVENT_ALL_STA_INFO:
+               mt7996_mcu_rx_all_sta_info_event(dev, skb);
+               break;
        default:
                break;
        }
@@ -4013,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
        return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
                                 sizeof(req), true);
 }
+
+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+{
+       struct mt7996_dev *dev = phy->dev;
+       struct {
+               u8 _rsv[4];
+
+               __le16 tag;
+               __le16 len;
+       } __packed req = {
+               .tag = cpu_to_le16(tag),
+               .len = cpu_to_le16(sizeof(req) - 4),
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
+                                &req, sizeof(req), false);
+}
index e4b31228ba0d278b8d19d28789a7d605eed5a16c..a88f6af323dae08554aa81f152f913aad9c7b795 100644 (file)
@@ -153,6 +153,32 @@ struct mt7996_mcu_mib {
        __le64 data;
 } __packed;
 
+struct mt7996_mcu_all_sta_info_event {
+       u8 rsv[4];
+       __le16 tag;
+       __le16 len;
+       u8 more;
+       u8 rsv2;
+       __le16 sta_num;
+       u8 rsv3[2];
+
+       union {
+               struct {
+                       __le16 wlan_idx;
+                       u8 rsv[2];
+                       __le32 tx_bytes[IEEE80211_NUM_ACS];
+                       __le32 rx_bytes[IEEE80211_NUM_ACS];
+               } adm_stat[0];
+
+               struct {
+                       __le16 wlan_idx;
+                       u8 rsv[2];
+                       __le32 tx_msdu_cnt;
+                       __le32 rx_msdu_cnt;
+               } msdu_cnt[0];
+       };
+} __packed;
+
 enum mt7996_chan_mib_offs {
        UNI_MIB_OBSS_AIRTIME = 26,
        UNI_MIB_NON_WIFI_TIME = 27,
index 7354e5cf8e674869092db1cb8a88893d9a59fa08..cb67a2d4c6d4bca839d05226a5e7f4cda37c2117 100644 (file)
@@ -402,6 +402,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
 int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
 void mt7996_mcu_exit(struct mt7996_dev *dev);
+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
 
 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
 {