blob: 51106440ea4a1e2114c6e3025cc2f91e15ab8608 [file] [log] [blame]
developere35b8e42023-10-16 11:04:00 +08001From 63501a3e941097581dcee61a0149ee5bc944c579 Mon Sep 17 00:00:00 2001
2From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
3Date: Wed, 28 Jun 2023 08:10:25 +0800
4Subject: [PATCH 18/98] wifi: mt76: mt7996: Add mcu commands for getting sta tx
5 statistic
6
7Per peer Tx/Rx statistic can only be obtained by querying WM when WED is
8on. This patch switches to periodic event reporting in the case of WED
9being enabled.
10---
11 mt76_connac_mcu.h | 15 +++++++++++
12 mt7996/mac.c | 5 ++++
13 mt7996/main.c | 15 +++++++++++
14 mt7996/mcu.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
15 mt7996/mcu.h | 26 ++++++++++++++++++
16 mt7996/mt7996.h | 1 +
17 6 files changed, 130 insertions(+)
18
19diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
20index 90c08d2..e9dd9aa 100644
21--- a/mt76_connac_mcu.h
22+++ b/mt76_connac_mcu.h
23@@ -1023,6 +1023,8 @@ enum {
24 MCU_UNI_EVENT_TX_DONE = 0x2d,
25 MCU_UNI_EVENT_THERMAL = 0x35,
26 MCU_UNI_EVENT_NIC_CAPAB = 0x43,
27+ MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
28+ MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
29 };
30
31 #define MCU_UNI_CMD_EVENT BIT(1)
32@@ -1242,6 +1244,8 @@ enum {
33 MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
34 MCU_UNI_CMD_RRO = 0x57,
35 MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
36+ MCU_UNI_CMD_PER_STA_INFO = 0x6d,
37+ MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
38 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
39 };
40
41@@ -1322,6 +1326,17 @@ enum {
42 UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
43 };
44
45+enum UNI_ALL_STA_INFO_TAG {
46+ UNI_ALL_STA_TX_RATE,
47+ UNI_ALL_STA_TX_STAT,
48+ UNI_ALL_STA_TXRX_ADM_STAT,
49+ UNI_ALL_STA_TXRX_AIR_TIME,
50+ UNI_ALL_STA_DATA_TX_RETRY_COUNT,
51+ UNI_ALL_STA_GI_MODE,
52+ UNI_ALL_STA_TXRX_MSDU_COUNT,
53+ UNI_ALL_STA_MAX_NUM
54+};
55+
56 enum {
57 MT_NIC_CAP_TX_RESOURCE,
58 MT_NIC_CAP_TX_EFUSE_ADDR,
59diff --git a/mt7996/mac.c b/mt7996/mac.c
60index bdc90a0..4828f10 100644
61--- a/mt7996/mac.c
62+++ b/mt7996/mac.c
63@@ -2272,6 +2272,11 @@ void mt7996_mac_work(struct work_struct *work)
64 mphy->mac_work_count = 0;
65
66 mt7996_mac_update_stats(phy);
67+
68+ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
69+ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
70+ mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
71+ };
72 }
73
74 mutex_unlock(&mphy->dev->mutex);
75diff --git a/mt7996/main.c b/mt7996/main.c
76index f152e76..e9e1fd9 100644
77--- a/mt7996/main.c
78+++ b/mt7996/main.c
79@@ -977,6 +977,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
80 struct ieee80211_sta *sta,
81 struct station_info *sinfo)
82 {
83+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
84 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
85 struct rate_info *txrate = &msta->wcid.rate;
86
87@@ -1008,6 +1009,20 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
88
89 sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
90 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
91+
92+ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
93+ sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
94+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
95+
96+ sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
97+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
98+
99+ sinfo->tx_packets = msta->wcid.stats.tx_packets;
100+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
101+
102+ sinfo->rx_packets = msta->wcid.stats.rx_packets;
103+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
104+ }
105 }
106
107 static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
108diff --git a/mt7996/mcu.c b/mt7996/mcu.c
109index 2c611e7..652a600 100644
110--- a/mt7996/mcu.c
111+++ b/mt7996/mcu.c
112@@ -477,6 +477,54 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
113 phy->throttle_state = n->duty_percent;
114 }
115
116+static void
117+mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
118+{
119+ struct mt7996_mcu_all_sta_info_event *res;
120+ u16 i;
121+
122+ skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
123+
124+ res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
125+
126+ for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
127+ u8 ac;
128+ u16 wlan_idx;
129+ struct mt76_wcid *wcid;
130+
131+ switch (le16_to_cpu(res->tag)) {
132+ case UNI_ALL_STA_TXRX_ADM_STAT:
133+ wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
134+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
135+
136+ if (!wcid)
137+ break;
138+
139+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
140+ wcid->stats.tx_bytes +=
141+ le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
142+ wcid->stats.rx_bytes +=
143+ le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
144+ }
145+ break;
146+ case UNI_ALL_STA_TXRX_MSDU_COUNT:
147+ wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
148+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
149+
150+ if (!wcid)
151+ break;
152+
153+ wcid->stats.tx_packets +=
154+ le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
155+ wcid->stats.rx_packets +=
156+ le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
157+ break;
158+ default:
159+ break;
160+ }
161+ }
162+}
163+
164 static void
165 mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
166 {
167@@ -524,6 +572,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
168 case MCU_UNI_EVENT_THERMAL:
169 mt7996_mcu_rx_thermal_notify(dev, skb);
170 break;
171+ case MCU_UNI_EVENT_ALL_STA_INFO:
172+ mt7996_mcu_rx_all_sta_info_event(dev, skb);
173+ break;
174 default:
175 break;
176 }
177@@ -4192,3 +4243,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
178 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
179 sizeof(req), true);
180 }
181+
182+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
183+{
184+ struct mt7996_dev *dev = phy->dev;
185+ struct {
186+ u8 _rsv[4];
187+
188+ __le16 tag;
189+ __le16 len;
190+ } __packed req = {
191+ .tag = cpu_to_le16(tag),
192+ .len = cpu_to_le16(sizeof(req) - 4),
193+ };
194+
195+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
196+ &req, sizeof(req), false);
197+}
198diff --git a/mt7996/mcu.h b/mt7996/mcu.h
199index 05785cb..97151d1 100644
200--- a/mt7996/mcu.h
201+++ b/mt7996/mcu.h
202@@ -191,6 +191,32 @@ struct mt7996_mcu_thermal_notify {
203 u8 __rsv2[4];
204 } __packed;
205
206+struct mt7996_mcu_all_sta_info_event {
207+ u8 rsv[4];
208+ __le16 tag;
209+ __le16 len;
210+ u8 more;
211+ u8 rsv2;
212+ __le16 sta_num;
213+ u8 rsv3[2];
214+
215+ union {
216+ struct {
217+ __le16 wlan_idx;
218+ u8 rsv[2];
219+ __le32 tx_bytes[IEEE80211_NUM_ACS];
220+ __le32 rx_bytes[IEEE80211_NUM_ACS];
221+ } adm_stat[0];
222+
223+ struct {
224+ __le16 wlan_idx;
225+ u8 rsv[2];
226+ __le32 tx_msdu_cnt;
227+ __le32 rx_msdu_cnt;
228+ } msdu_cnt[0];
229+ };
230+} __packed;
231+
232 enum mt7996_chan_mib_offs {
233 UNI_MIB_OBSS_AIRTIME = 26,
234 UNI_MIB_NON_WIFI_TIME = 27,
235diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
236index 0bb20a9..420d113 100644
237--- a/mt7996/mt7996.h
238+++ b/mt7996/mt7996.h
239@@ -494,6 +494,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
240 int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
241 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
242 void mt7996_mcu_exit(struct mt7996_dev *dev);
243+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
244
245 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
246 {
247--
2482.18.0
249