blob: d1301436dd4ca47a1856c098480011b7b3e458a3 [file] [log] [blame]
From 19082cf5d84a2c1a8e92d525a96de49b08d086fd Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Wed, 28 Jun 2023 08:10:25 +0800
Subject: [PATCH 17/22] wifi: mt76: mt7996: Add mcu commands for getting sta tx
statistic
Add ALL_STA command to query station tx statistic from WM mcu.
The commands are called periodically to query information from the WM mcu.
The response events are sent as unsolicited event.
We get tx bytes and rx bytes counts with tag UNI_ALL_STA_TXRX_ADM_STAT
and get MSDU packet counts with tag UNI_ALL_STA_TRX_MSDU_COUNT.
The MSDU packet counts are based on UWTBL DW10 and DW11.
It's accumulative and not read-clear.
---
mt76_connac_mcu.h | 15 +++++++++++
mt7996/mac.c | 3 +++
mt7996/main.c | 12 +++++++++
mt7996/mcu.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.h | 29 ++++++++++++++++++++
mt7996/mt7996.h | 1 +
6 files changed, 128 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
index 90c08d276..e9dd9aa64 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -1023,6 +1023,8 @@ enum {
MCU_UNI_EVENT_TX_DONE = 0x2d,
MCU_UNI_EVENT_THERMAL = 0x35,
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)
@@ -1242,6 +1244,8 @@ enum {
MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
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,
};
@@ -1322,6 +1326,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,
diff --git a/mt7996/mac.c b/mt7996/mac.c
index 8f3742c4e..8f75da695 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -2212,6 +2212,9 @@ void mt7996_mac_work(struct work_struct *work)
mphy->mac_work_count = 0;
mt7996_mac_update_stats(phy);
+
+ 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);
diff --git a/mt7996/main.c b/mt7996/main.c
index 32d975c63..284fb373b 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -1008,6 +1008,18 @@ 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);
+
+ 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)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index 56b2bbc69..146e284fc 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -477,6 +477,54 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
phy->throttle_state = n->duty_percent;
}
+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)
{
@@ -524,6 +572,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_THERMAL:
mt7996_mcu_rx_thermal_notify(dev, skb);
break;
+ case MCU_UNI_EVENT_ALL_STA_INFO:
+ mt7996_mcu_rx_all_sta_info_event(dev, skb);
+ break;
default:
break;
}
@@ -4194,3 +4245,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);
+}
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
index 05785cb9f..66af7a90f 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -191,6 +191,35 @@ struct mt7996_mcu_thermal_notify {
u8 __rsv2[4];
} __packed;
+struct all_sta_trx_adm_stat {
+ __le16 wlan_idx;
+ u8 __rsv[2];
+ __le32 tx_bytes[IEEE80211_NUM_ACS];
+ __le32 rx_bytes[IEEE80211_NUM_ACS];
+} __packed;
+
+struct all_sta_trx_msdu_cnt {
+ __le16 wlan_idx;
+ u8 __rsv[2];
+ __le32 tx_msdu_cnt;
+ __le32 rx_msdu_cnt;
+} __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 all_sta_trx_adm_stat adm_stat[0];
+ struct all_sta_trx_msdu_cnt msdu_cnt[0];
+ };
+} __packed;
+
enum mt7996_chan_mib_offs {
UNI_MIB_OBSS_AIRTIME = 26,
UNI_MIB_NON_WIFI_TIME = 27,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index 3ac354b18..bf9960e30 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -423,6 +423,7 @@ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
--
2.39.2