blob: cb7b3510f8aa5c594070a6ab4901f4d4f85f9c26 [file] [log] [blame]
developerd0c89452024-10-11 16:53:27 +08001From 5b0810ecadc01482ef25b7e063ebe69f42e39a8e Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
3Date: Fri, 17 Nov 2023 18:08:06 +0800
developerd0c89452024-10-11 16:53:27 +08004Subject: [PATCH 068/223] mtk: mt76: mt7996: get airtime and RSSI via MCU
developer66e89bc2024-04-23 14:50:01 +08005 commands
6
7Direct access to WTBL for airtime and RSSI may cause synchronization issue with FW.
8Moreover, frequent access to WTBL, whenever TX-Free-Done event is received, leads to heavy CPU overheads.
9Therefore, indirect access to WTBL, through FW, with lower frequence is performed.
10
developerd0c89452024-10-11 16:53:27 +080011Change-Id: I978e7432603742fae9c753f055ff3087cf6b632c
developer66e89bc2024-04-23 14:50:01 +080012Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
developer05f3b2b2024-08-19 19:17:34 +080013Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
developer66e89bc2024-04-23 14:50:01 +080014---
developer05f3b2b2024-08-19 19:17:34 +080015 mt76.h | 18 +++++
developer66e89bc2024-04-23 14:50:01 +080016 mt76_connac_mcu.h | 14 +++-
developer05f3b2b2024-08-19 19:17:34 +080017 mt7996/debugfs.c | 17 +++--
18 mt7996/mac.c | 145 +++++++-------------------------------
19 mt7996/mcu.c | 161 +++++++++++++++++++++++++++++++++++++++++--
20 mt7996/mcu.h | 24 +++++++
21 mt7996/mt7996.h | 26 +++++--
22 mt7996/mtk_debugfs.c | 71 +++++++++++++++++++
developer66e89bc2024-04-23 14:50:01 +080023 mt7996/regs.h | 2 +
developer05f3b2b2024-08-19 19:17:34 +080024 9 files changed, 336 insertions(+), 142 deletions(-)
developer66e89bc2024-04-23 14:50:01 +080025
26diff --git a/mt76.h b/mt76.h
developerd0c89452024-10-11 16:53:27 +080027index e7901e57..aad7f557 100644
developer66e89bc2024-04-23 14:50:01 +080028--- a/mt76.h
29+++ b/mt76.h
developerd0c89452024-10-11 16:53:27 +080030@@ -336,11 +336,13 @@ struct mt76_sta_stats {
developer66e89bc2024-04-23 14:50:01 +080031 u32 tx_packets; /* unit: MSDU */
32 u32 tx_retries;
33 u32 tx_failed;
developer66e89bc2024-04-23 14:50:01 +080034+ u64 tx_airtime;
35 /* WED RX */
36 u64 rx_bytes;
37 u32 rx_packets;
38 u32 rx_errors;
39 u32 rx_drops;
40+ u64 rx_airtime;
41 };
42
43 enum mt76_wcid_flags {
developerd0c89452024-10-11 16:53:27 +080044@@ -1339,6 +1341,22 @@ static inline int mt76_decr(int val, int size)
developer66e89bc2024-04-23 14:50:01 +080045
46 u8 mt76_ac_to_hwq(u8 ac);
47
48+static inline u8
49+mt76_ac_to_tid(u8 ac)
50+{
51+ static const u8 ac_to_tid[] = {
52+ [IEEE80211_AC_BE] = 0,
53+ [IEEE80211_AC_BK] = 1,
54+ [IEEE80211_AC_VI] = 4,
55+ [IEEE80211_AC_VO] = 6
56+ };
57+
58+ if (WARN_ON(ac >= IEEE80211_NUM_ACS))
59+ return 0;
60+
61+ return ac_to_tid[ac];
62+}
63+
64 static inline struct ieee80211_txq *
65 mtxq_to_txq(struct mt76_txq *mtxq)
66 {
67diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080068index db152167..adecb0ed 100644
developer66e89bc2024-04-23 14:50:01 +080069--- a/mt76_connac_mcu.h
70+++ b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080071@@ -1387,11 +1387,23 @@ enum {
developer66e89bc2024-04-23 14:50:01 +080072 UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
73 };
74
75+enum UNI_PER_STA_INFO_TAG {
76+ UNI_PER_STA_RSSI,
77+ UNI_PER_STA_CONTENTION_RX_RATE,
78+ UNI_PER_STA_PER,
79+ UNI_PER_STA_SNR,
80+ UNI_PER_STA_TX_RATE,
81+ UNI_PER_STA_TX_CNT,
82+ UNI_PER_STA_TID_SN_GET,
83+ UNI_PER_STA_TID_SN_SET,
84+ UNI_PER_STA_MAX_NUM
85+};
86+
87 enum UNI_ALL_STA_INFO_TAG {
88 UNI_ALL_STA_TXRX_RATE,
89 UNI_ALL_STA_TX_STAT,
90 UNI_ALL_STA_TXRX_ADM_STAT,
91- UNI_ALL_STA_TXRX_AIR_TIME,
92+ UNI_ALL_STA_TXRX_AIRTIME,
93 UNI_ALL_STA_DATA_TX_RETRY_COUNT,
94 UNI_ALL_STA_GI_MODE,
95 UNI_ALL_STA_TXRX_MSDU_COUNT,
96diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
developerd0c89452024-10-11 16:53:27 +080097index 0ef8fee6..e46a0fb9 100644
developer66e89bc2024-04-23 14:50:01 +080098--- a/mt7996/debugfs.c
99+++ b/mt7996/debugfs.c
developer05f3b2b2024-08-19 19:17:34 +0800100@@ -979,12 +979,11 @@ mt7996_airtime_read(struct seq_file *s, void *data)
developer66e89bc2024-04-23 14:50:01 +0800101 {
102 struct mt7996_dev *dev = dev_get_drvdata(s->private);
103 struct mt76_dev *mdev = &dev->mt76;
104- struct mt7996_vow_sta_ctrl *vow;
105+ struct mt76_sta_stats *stats;
106 struct ieee80211_sta *sta;
107 struct mt7996_sta *msta;
108 struct mt76_wcid *wcid;
109 struct mt76_vif *vif;
110- u64 airtime;
111 u16 i;
112
113 seq_printf(s, "VoW Airtime Information:\n");
developer05f3b2b2024-08-19 19:17:34 +0800114@@ -996,16 +995,16 @@ mt7996_airtime_read(struct seq_file *s, void *data)
developer66e89bc2024-04-23 14:50:01 +0800115
116 msta = container_of(wcid, struct mt7996_sta, wcid);
117 sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
118- vow = &msta->vow;
119 vif = &msta->vif->mt76;
120+ stats = &wcid->stats;
121
122- spin_lock_bh(&vow->lock);
123- airtime = vow->tx_airtime;
124- vow->tx_airtime = 0;
125- spin_unlock_bh(&vow->lock);
126+ seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\t"
127+ "TxAirtime: %llu\tRxAirtime: %llu\n",
128+ sta->addr, i, vif->band_idx, vif->omac_idx,
129+ stats->tx_airtime, stats->rx_airtime);
130
131- seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\tTxAirtime: %llu\n",
132- sta->addr, i, vif->band_idx, vif->omac_idx, airtime);
133+ stats->tx_airtime = 0;
134+ stats->rx_airtime = 0;
135 }
136 rcu_read_unlock();
137
138diff --git a/mt7996/mac.c b/mt7996/mac.c
developerd0c89452024-10-11 16:53:27 +0800139index c72f70db..8b753148 100644
developer66e89bc2024-04-23 14:50:01 +0800140--- a/mt7996/mac.c
141+++ b/mt7996/mac.c
142@@ -12,8 +12,6 @@
143 #include "mcu.h"
144 #include "vendor.h"
145
146-#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
147-
148 static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
149 .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
150 .radar_pattern = {
151@@ -93,110 +91,6 @@ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw)
152 return MT_WTBL_LMAC_OFFS(wcid, dw);
153 }
154
155-static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
156-{
157- static const u8 ac_to_tid[] = {
158- [IEEE80211_AC_BE] = 0,
159- [IEEE80211_AC_BK] = 1,
160- [IEEE80211_AC_VI] = 4,
161- [IEEE80211_AC_VO] = 6
162- };
163- struct ieee80211_sta *sta;
164- struct mt7996_sta *msta;
165- struct mt7996_vow_sta_ctrl *vow;
166- u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
167- LIST_HEAD(sta_poll_list);
168- int i;
169-
170- spin_lock_bh(&dev->mt76.sta_poll_lock);
171- list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
172- spin_unlock_bh(&dev->mt76.sta_poll_lock);
173-
174- rcu_read_lock();
175-
176- while (true) {
177- bool clear = false;
178- u32 addr, val;
179- u16 idx;
180- s8 rssi[4];
181-
182- spin_lock_bh(&dev->mt76.sta_poll_lock);
183- if (list_empty(&sta_poll_list)) {
184- spin_unlock_bh(&dev->mt76.sta_poll_lock);
185- break;
186- }
187- msta = list_first_entry(&sta_poll_list,
188- struct mt7996_sta, wcid.poll_list);
189- list_del_init(&msta->wcid.poll_list);
190- spin_unlock_bh(&dev->mt76.sta_poll_lock);
191-
192- idx = msta->wcid.idx;
193-
194- /* refresh peer's airtime reporting */
195- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
196-
197- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
198- u32 tx_last = msta->airtime_ac[i];
199- u32 rx_last = msta->airtime_ac[i + 4];
200-
201- msta->airtime_ac[i] = mt76_rr(dev, addr);
202- msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
203-
204- tx_time[i] = msta->airtime_ac[i] - tx_last;
205- rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
206-
207- if ((tx_last | rx_last) & BIT(30))
208- clear = true;
209-
210- addr += 8;
211- }
212-
213- if (clear) {
214- mt7996_mac_wtbl_update(dev, idx,
215- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
216- memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
217- }
218-
219- if (!msta->wcid.sta)
220- continue;
221-
222- sta = container_of((void *)msta, struct ieee80211_sta,
223- drv_priv);
224- vow = &msta->vow;
225- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
226- u8 q = mt76_connac_lmac_mapping(i);
227- u32 tx_cur = tx_time[q];
228- u32 rx_cur = rx_time[q];
229- u8 tid = ac_to_tid[i];
230-
231- if (!tx_cur && !rx_cur)
232- continue;
233-
234- ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
235-
236- spin_lock_bh(&vow->lock);
237- vow->tx_airtime += tx_cur;
238- spin_unlock_bh(&vow->lock);
239- }
240-
241- /* get signal strength of resp frames (CTS/BA/ACK) */
242- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
243- val = mt76_rr(dev, addr);
244-
245- rssi[0] = to_rssi(GENMASK(7, 0), val);
246- rssi[1] = to_rssi(GENMASK(15, 8), val);
247- rssi[2] = to_rssi(GENMASK(23, 16), val);
248- rssi[3] = to_rssi(GENMASK(31, 14), val);
249-
250- msta->ack_signal =
251- mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
252-
253- ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
254- }
255-
256- rcu_read_unlock();
257-}
258-
259 void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
260 struct ieee80211_vif *vif, bool enable)
261 {
developerd0c89452024-10-11 16:53:27 +0800262@@ -1221,8 +1115,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
developer66e89bc2024-04-23 14:50:01 +0800263 }
264 }
265
266- mt7996_mac_sta_poll(dev);
267-
268 if (wake)
269 mt76_set_tx_blocked(&dev->mt76, false);
270
developerd0c89452024-10-11 16:53:27 +0800271@@ -2391,31 +2283,42 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
developer66e89bc2024-04-23 14:50:01 +0800272
273 void mt7996_mac_work(struct work_struct *work)
274 {
275- struct mt7996_phy *phy;
276- struct mt76_phy *mphy;
277-
278- mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
279- mac_work.work);
280- phy = mphy->priv;
281+ struct mt76_phy *mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
282+ mac_work.work);
283+ struct mt7996_phy *phy = mphy->priv;
284+ struct mt76_dev *mdev = mphy->dev;
285
286- mutex_lock(&mphy->dev->mutex);
287+ mutex_lock(&mdev->mutex);
288
289 mt76_update_survey(mphy);
290 if (++mphy->mac_work_count == 5) {
291+ int i;
292+
293 mphy->mac_work_count = 0;
294
295 mt7996_mac_update_stats(phy);
296
297- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_RATE);
298- if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
299- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
300- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
301+ /* Update DEV-wise information only in
302+ * the MAC work of the first band running.
303+ */
304+ for (i = MT_BAND0; i <= mphy->band_idx; ++i) {
305+ if (i == mphy->band_idx) {
306+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_RATE);
307+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_AIRTIME);
308+ mt7996_mcu_get_rssi(mdev);
309+ if (mtk_wed_device_active(&mdev->mmio.wed)) {
310+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_ADM_STAT);
311+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_MSDU_COUNT);
312+ }
313+ } else if (mt7996_band_valid(phy->dev, i) &&
314+ test_bit(MT76_STATE_RUNNING, &mdev->phys[i]->state))
315+ break;
316 }
317 }
318
319- mutex_unlock(&mphy->dev->mutex);
320+ mutex_unlock(&mdev->mutex);
321
322- mt76_tx_status_check(mphy->dev, false);
323+ mt76_tx_status_check(mdev, false);
324
325 ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
326 MT7996_WATCHDOG_TIME);
327diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800328index be273181..db877d75 100644
developer66e89bc2024-04-23 14:50:01 +0800329--- a/mt7996/mcu.c
330+++ b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800331@@ -568,7 +568,8 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +0800332 u16 wlan_idx;
333 struct mt76_wcid *wcid;
334 struct mt76_phy *mphy;
335- u32 tx_bytes, rx_bytes, tx_packets, rx_packets;
336+ struct ieee80211_sta *sta;
337+ u32 tx_bytes, rx_bytes, tx_airtime, rx_airtime, tx_packets, rx_packets;
338
339 switch (le16_to_cpu(res->tag)) {
340 case UNI_ALL_STA_TXRX_RATE:
developerd0c89452024-10-11 16:53:27 +0800341@@ -589,7 +590,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +0800342 break;
343
344 mphy = mt76_dev_phy(&dev->mt76, wcid->phy_idx);
345- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
346+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
347 tx_bytes = le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
348 rx_bytes = le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
349
developerd0c89452024-10-11 16:53:27 +0800350@@ -621,6 +622,24 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer66e89bc2024-04-23 14:50:01 +0800351 __mt7996_stat_to_netdev(mphy, wcid, 0, 0,
352 tx_packets, rx_packets);
353 break;
354+ case UNI_ALL_STA_TXRX_AIRTIME:
355+ wlan_idx = le16_to_cpu(res->airtime[i].wlan_idx);
356+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
357+ sta = wcid_to_sta(wcid);
358+ if (!sta)
359+ continue;
360+
361+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ++ac) {
362+ u8 lmac_ac = mt76_connac_lmac_mapping(ac);
363+ tx_airtime = le32_to_cpu(res->airtime[i].tx[lmac_ac]);
364+ rx_airtime = le32_to_cpu(res->airtime[i].rx[lmac_ac]);
365+
366+ wcid->stats.tx_airtime += tx_airtime;
367+ wcid->stats.rx_airtime += rx_airtime;
368+ ieee80211_sta_register_airtime(sta, mt76_ac_to_tid(ac),
369+ tx_airtime, rx_airtime);
370+ }
371+ break;
372 default:
373 break;
374 }
developerd0c89452024-10-11 16:53:27 +0800375@@ -2249,8 +2268,6 @@ mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
developer66e89bc2024-04-23 14:50:01 +0800376 vow->drr_quantum[IEEE80211_AC_VI] = VOW_DRR_QUANTUM_IDX1;
377 vow->drr_quantum[IEEE80211_AC_BE] = VOW_DRR_QUANTUM_IDX2;
378 vow->drr_quantum[IEEE80211_AC_BK] = VOW_DRR_QUANTUM_IDX2;
379- vow->tx_airtime = 0;
380- spin_lock_init(&vow->lock);
381
382 ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
383 if (ret)
developerd0c89452024-10-11 16:53:27 +0800384@@ -4868,9 +4885,139 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
developer66e89bc2024-04-23 14:50:01 +0800385 sizeof(req), true);
386 }
387
388-int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
389+int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
390+ u16 sta_num, u16 *sta_list)
391+{
392+#define PER_STA_INFO_MAX_NUM 90
393+ struct mt7996_mcu_per_sta_info_event *res;
394+ struct mt76_wcid *wcid;
395+ struct sk_buff *skb;
396+ u16 wlan_idx;
397+ int i, ret;
398+ struct {
399+ u8 __rsv1;
400+ u8 unsolicit;
401+ u8 __rsv2[2];
402+
403+ __le16 tag;
404+ __le16 len;
405+ __le16 sta_num;
406+ u8 __rsv3[2];
407+ __le16 sta_list[PER_STA_INFO_MAX_NUM];
408+ } __packed req = {
409+ .unsolicit = 0,
410+ .tag = cpu_to_le16(tag),
411+ .len = cpu_to_le16(sizeof(req) - 4),
412+ .sta_num = cpu_to_le16(sta_num)
413+ };
414+
415+ if (sta_num > PER_STA_INFO_MAX_NUM)
416+ return -EINVAL;
417+
418+ for (i = 0; i < sta_num; ++i)
419+ req.sta_list[i] = cpu_to_le16(sta_list[i]);
420+
421+ ret = mt76_mcu_send_and_get_msg(dev, MCU_WM_UNI_CMD(PER_STA_INFO),
422+ &req, sizeof(req), true, &skb);
423+ if (ret)
424+ return ret;
425+
426+ res = (struct mt7996_mcu_per_sta_info_event *)skb->data;
427+ if (le16_to_cpu(res->tag) != tag) {
428+ ret = -EINVAL;
429+ goto out;
430+ }
431+
432+ rcu_read_lock();
433+ switch (tag) {
434+ case UNI_PER_STA_RSSI:
435+ for (i = 0; i < sta_num; ++i) {
436+ struct mt7996_sta *msta;
437+ struct mt76_phy *phy;
438+ s8 rssi[4];
439+ u8 *rcpi;
440+
441+ wlan_idx = le16_to_cpu(res->rssi[i].wlan_idx);
442+ wcid = rcu_dereference(dev->wcid[wlan_idx]);
443+ if (wcid) {
444+ rcpi = res->rssi[i].rcpi;
445+ rssi[0] = to_rssi(MT_PRXV_RCPI0, rcpi[0]);
446+ rssi[1] = to_rssi(MT_PRXV_RCPI0, rcpi[1]);
447+ rssi[2] = to_rssi(MT_PRXV_RCPI0, rcpi[2]);
448+ rssi[3] = to_rssi(MT_PRXV_RCPI0, rcpi[3]);
449+
450+ msta = container_of(wcid, struct mt7996_sta, wcid);
451+ phy = msta->vif->phy->mt76;
452+ msta->ack_signal = mt76_rx_signal(phy->antenna_mask, rssi);
453+ ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
454+ } else {
455+ ret = -EINVAL;
456+ dev_err(dev->dev, "Failed to update RSSI for "
457+ "invalid WCID: %hu\n", wlan_idx);
458+ }
459+ }
460+ break;
developer66e89bc2024-04-23 14:50:01 +0800461+ default:
462+ ret = -EINVAL;
463+ dev_err(dev->dev, "Unknown UNI_PER_STA_INFO_TAG: %d\n", tag);
464+ }
465+ rcu_read_unlock();
466+out:
467+ dev_kfree_skb(skb);
468+ return ret;
469+}
470+
471+int mt7996_mcu_get_rssi(struct mt76_dev *dev)
472+{
473+ u16 sta_list[PER_STA_INFO_MAX_NUM];
474+ LIST_HEAD(sta_poll_list);
475+ struct mt7996_sta *msta;
476+ int i, ret;
477+ bool empty = false;
478+
479+ spin_lock_bh(&dev->sta_poll_lock);
480+ list_splice_init(&dev->sta_poll_list, &sta_poll_list);
481+ spin_unlock_bh(&dev->sta_poll_lock);
482+
483+ while (!empty) {
484+ for (i = 0; i < PER_STA_INFO_MAX_NUM; ++i) {
485+ spin_lock_bh(&dev->sta_poll_lock);
486+ if (list_empty(&sta_poll_list)) {
487+ spin_unlock_bh(&dev->sta_poll_lock);
488+
489+ if (i == 0)
490+ return 0;
491+
492+ empty = true;
493+ break;
494+ }
495+ msta = list_first_entry(&sta_poll_list,
496+ struct mt7996_sta,
497+ wcid.poll_list);
498+ list_del_init(&msta->wcid.poll_list);
499+ spin_unlock_bh(&dev->sta_poll_lock);
500+
501+ sta_list[i] = msta->wcid.idx;
502+ }
503+
504+ ret = mt7996_mcu_get_per_sta_info(dev, UNI_PER_STA_RSSI,
505+ i, sta_list);
506+ if (ret) {
507+ /* Add STAs, whose RSSI has not been updated,
508+ * back to polling list.
509+ */
510+ spin_lock_bh(&dev->sta_poll_lock);
511+ list_splice(&sta_poll_list, &dev->sta_poll_list);
512+ spin_unlock_bh(&dev->sta_poll_lock);
513+ break;
514+ }
515+ }
516+
517+ return ret;
518+}
519+
520+int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag)
521 {
522- struct mt7996_dev *dev = phy->dev;
523 struct {
524 u8 _rsv[4];
525
developerd0c89452024-10-11 16:53:27 +0800526@@ -4881,7 +5028,7 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
developer66e89bc2024-04-23 14:50:01 +0800527 .len = cpu_to_le16(sizeof(req) - 4),
528 };
529
530- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
531+ return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(ALL_STA_INFO),
532 &req, sizeof(req), false);
533 }
534
535diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800536index 19572d85..5aa55e4f 100644
developer66e89bc2024-04-23 14:50:01 +0800537--- a/mt7996/mcu.h
538+++ b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800539@@ -199,6 +199,23 @@ struct mt7996_mcu_mib {
developer66e89bc2024-04-23 14:50:01 +0800540 __le64 data;
541 } __packed;
542
543+struct per_sta_rssi {
544+ __le16 wlan_idx;
545+ u8 __rsv[2];
546+ u8 rcpi[4];
547+} __packed;
548+
developer66e89bc2024-04-23 14:50:01 +0800549+struct mt7996_mcu_per_sta_info_event {
550+ u8 __rsv[4];
551+
552+ __le16 tag;
553+ __le16 len;
554+
555+ union {
556+ struct per_sta_rssi rssi[0];
developer66e89bc2024-04-23 14:50:01 +0800557+ };
558+} __packed;
559+
560 struct all_sta_trx_rate {
561 __le16 wlan_idx;
562 u8 __rsv1[2];
developer05f3b2b2024-08-19 19:17:34 +0800563@@ -244,6 +261,13 @@ struct mt7996_mcu_all_sta_info_event {
developer66e89bc2024-04-23 14:50:01 +0800564 __le32 tx_msdu_cnt;
565 __le32 rx_msdu_cnt;
developer05f3b2b2024-08-19 19:17:34 +0800566 } __packed, msdu_cnt);
567+
568+ DECLARE_FLEX_ARRAY(struct {
developer66e89bc2024-04-23 14:50:01 +0800569+ __le16 wlan_idx;
developer05f3b2b2024-08-19 19:17:34 +0800570+ u8 rsv[2];
developer66e89bc2024-04-23 14:50:01 +0800571+ __le32 tx[IEEE80211_NUM_ACS];
572+ __le32 rx[IEEE80211_NUM_ACS];
developer05f3b2b2024-08-19 19:17:34 +0800573+ } __packed, airtime);
developer66e89bc2024-04-23 14:50:01 +0800574 } __packed;
575 } __packed;
576
577diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800578index 7d0f7dda..f6d3bd19 100644
developer66e89bc2024-04-23 14:50:01 +0800579--- a/mt7996/mt7996.h
580+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800581@@ -128,6 +128,8 @@
developer66e89bc2024-04-23 14:50:01 +0800582 #define MT7996_RRO_MSDU_PG_CR_CNT 8
583 #define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
584
585+#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
586+
587 struct mt7996_vif;
588 struct mt7996_sta;
589 struct mt7996_dfs_pulse;
developerd0c89452024-10-11 16:53:27 +0800590@@ -299,8 +301,6 @@ struct mt7996_vow_sta_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800591 bool paused;
592 u8 bss_grp_idx;
593 u8 drr_quantum[IEEE80211_NUM_ACS];
594- u64 tx_airtime;
595- spinlock_t lock;
596 };
597
598 struct mt7996_sta {
developerd0c89452024-10-11 16:53:27 +0800599@@ -309,7 +309,6 @@ struct mt7996_sta {
developer66e89bc2024-04-23 14:50:01 +0800600 struct mt7996_vif *vif;
601
602 struct list_head rc_list;
603- u32 airtime_ac[8];
604
605 int ack_signal;
606 struct ewma_avg_signal avg_ack_signal;
developerd0c89452024-10-11 16:53:27 +0800607@@ -406,6 +405,21 @@ struct mt7996_air_monitor_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800608 };
609 #endif
610
611+struct mt7996_rro_ba_session {
612+ u32 ack_sn :12;
613+ u32 win_sz :3;
614+ u32 bn :1;
615+ u32 last_in_sn :12;
616+ u32 bc :1;
617+ u32 bd :1;
618+ u32 sat :1;
619+ u32 cn :1;
620+ u32 within_cnt :12;
621+ u32 to_sel :3;
622+ u32 rsv :1;
623+ u32 last_in_rxtime :12;
624+};
625+
626 struct mt7996_phy {
627 struct mt76_phy *mt76;
628 struct mt7996_dev *dev;
developerd0c89452024-10-11 16:53:27 +0800629@@ -605,6 +619,7 @@ struct mt7996_dev {
developer66e89bc2024-04-23 14:50:01 +0800630 u32 fw_dbg_module;
631 u8 fw_dbg_lv;
632 u32 bcn_total_cnt[__MT_MAX_BAND];
633+ u32 sid;
634 } dbg;
635 const struct mt7996_dbg_reg_desc *dbg_reg;
636 #endif
developerd0c89452024-10-11 16:53:27 +0800637@@ -829,7 +844,10 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
developer66e89bc2024-04-23 14:50:01 +0800638 int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
639 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
640 void mt7996_mcu_exit(struct mt7996_dev *dev);
641-int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
642+int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
643+ u16 sta_num, u16 *sta_list);
644+int mt7996_mcu_get_rssi(struct mt76_dev *dev);
645+int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag);
646 int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
647 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
648 int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
649diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
developerd0c89452024-10-11 16:53:27 +0800650index 5a140f51..4ce4ac0d 100644
developer66e89bc2024-04-23 14:50:01 +0800651--- a/mt7996/mtk_debugfs.c
652+++ b/mt7996/mtk_debugfs.c
developerd0c89452024-10-11 16:53:27 +0800653@@ -3064,6 +3064,69 @@ mt7996_vow_drr_dbg(void *data, u64 val)
developer66e89bc2024-04-23 14:50:01 +0800654 DEFINE_DEBUGFS_ATTRIBUTE(fops_vow_drr_dbg, NULL,
655 mt7996_vow_drr_dbg, "%lld\n");
656
657+static int
658+mt7996_rro_session_read(struct seq_file *s, void *data)
659+{
660+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
661+ struct mt7996_rro_ba_session *tbl;
662+ u32 value[2];
663+
664+ mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC +
665+ (dev->dbg.sid >> 1) + 0x200);
666+
667+ if (dev->dbg.sid & 0x1) {
668+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
669+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(3));
670+ } else {
671+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
672+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
673+ }
674+
675+ tbl = (struct mt7996_rro_ba_session *)&value[0];
676+
677+ seq_printf(s, " seid %d:\nba session table DW0:%08x DW2:%08x\n",
678+ dev->dbg.sid, value[0], value[1]);
679+
680+ seq_printf(s, "ack_sn = 0x%x, last_in_sn = 0x%x, sat/bn/bc/bd/cn = %d/%d/%d/%d/%d\n",
681+ tbl->ack_sn, tbl->last_in_sn, tbl->sat, tbl->bn, tbl->bc, tbl->bd, tbl->cn);
682+
683+ seq_printf(s, "within_cnt = %d, to_sel = %d, last_in_rxtime = %d\n",
684+ tbl->within_cnt, tbl->to_sel, tbl->last_in_rxtime);
685+
686+ return 0;
687+}
688+
689+static int
690+mt7996_show_rro_mib(struct seq_file *s, void *data)
691+{
692+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
693+ u32 reg[12];
694+
695+ seq_printf(s, "RRO mib Info:\n");
696+
697+ reg[0] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(0));
698+ reg[1] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(1));
699+ reg[2] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(2));
700+ reg[3] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(3));
701+ reg[4] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(4));
702+ reg[5] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(5));
703+ reg[6] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(6));
704+ reg[7] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(7));
705+ reg[8] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(8));
706+ reg[9] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(9));
707+ reg[10] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(10));
708+ reg[11] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(11));
709+
710+ seq_printf(s, "STEP_ONE/WITHIN/SURPASS = %x/%x/%x\n", reg[0], reg[3], reg[4]);
711+ seq_printf(s, "REPEAT/OLDPKT/BAR = %x/%x/%x\n", reg[1], reg[2], reg[5]);
712+ seq_printf(s, "SURPASS with big gap = %x\n", reg[6]);
713+ seq_printf(s, "DISCONNECT/INVALID = %x/%x\n", reg[7], reg[8]);
714+ seq_printf(s, "TO(Step one)/TO(flush all) = %x/%x\n", reg[9], reg[10]);
715+ seq_printf(s, "buf ran out = %x\n", reg[11]);
716+
717+ return 0;
718+}
719+
720 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
721 {
722 struct mt7996_dev *dev = phy->dev;
developerd0c89452024-10-11 16:53:27 +0800723@@ -3162,6 +3225,14 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
developer66e89bc2024-04-23 14:50:01 +0800724
725 debugfs_create_file("muru_prot_thr", 0200, dir, phy, &fops_muru_prot_thr);
726
727+ if (dev->has_rro) {
728+ debugfs_create_u32("rro_sid", 0600, dir, &dev->dbg.sid);
729+ debugfs_create_devm_seqfile(dev->mt76.dev, "rro_sid_info", dir,
730+ mt7996_rro_session_read);
731+ debugfs_create_devm_seqfile(dev->mt76.dev, "rro_mib", dir,
732+ mt7996_show_rro_mib);
733+ }
734+
735 return 0;
736 }
737
738diff --git a/mt7996/regs.h b/mt7996/regs.h
developerd0c89452024-10-11 16:53:27 +0800739index 87bf0012..96438cca 100644
developer66e89bc2024-04-23 14:50:01 +0800740--- a/mt7996/regs.h
741+++ b/mt7996/regs.h
742@@ -122,6 +122,8 @@ enum offs_rev {
743 #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
744 #define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
745
746+#define WF_RRO_TOP_STATISTIC(_n) MT_RRO_TOP(0x180 + _n * 0x4)
747+
748 /* PLE */
749 #define MT_PLE_BASE 0x820c0000
750 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
751--
developerd0c89452024-10-11 16:53:27 +08007522.45.2
developer66e89bc2024-04-23 14:50:01 +0800753