blob: a553070d20650326d47c17c696d6de5be442563f [file] [log] [blame]
developer9237f442024-06-14 17:13:04 +08001From a08f12c4e90f1c849c3e8dc0db60fe294b63f3fe 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
developer9237f442024-06-14 17:13:04 +08004Subject: [PATCH 075/116] mtk: wifi: 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
developer66e89bc2024-04-23 14:50:01 +080011Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
12Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
13---
14 mt76.h | 20 +++++
15 mt76_connac_mcu.h | 14 +++-
16 mt7996/debugfs.c | 17 ++---
17 mt7996/mac.c | 145 ++++++-----------------------------
18 mt7996/mcu.c | 177 +++++++++++++++++++++++++++++++++++++++++--
19 mt7996/mcu.h | 32 +++++++-
20 mt7996/mt7996.h | 26 ++++++-
21 mt7996/mtk_debugfs.c | 71 +++++++++++++++++
22 mt7996/regs.h | 2 +
23 9 files changed, 361 insertions(+), 143 deletions(-)
24
25diff --git a/mt76.h b/mt76.h
developer9237f442024-06-14 17:13:04 +080026index 677f68f..28defd4 100644
developer66e89bc2024-04-23 14:50:01 +080027--- a/mt76.h
28+++ b/mt76.h
29@@ -332,11 +332,15 @@ struct mt76_sta_stats {
30 u32 tx_packets; /* unit: MSDU */
31 u32 tx_retries;
32 u32 tx_failed;
33+ u32 tx_total_mpdu_cnt;
34+ u32 tx_failed_mpdu_cnt;
35+ u64 tx_airtime;
36 /* WED RX */
37 u64 rx_bytes;
38 u32 rx_packets;
39 u32 rx_errors;
40 u32 rx_drops;
41+ u64 rx_airtime;
42 };
43
44 enum mt76_wcid_flags {
45@@ -1335,6 +1339,22 @@ static inline int mt76_decr(int val, int size)
46
47 u8 mt76_ac_to_hwq(u8 ac);
48
49+static inline u8
50+mt76_ac_to_tid(u8 ac)
51+{
52+ static const u8 ac_to_tid[] = {
53+ [IEEE80211_AC_BE] = 0,
54+ [IEEE80211_AC_BK] = 1,
55+ [IEEE80211_AC_VI] = 4,
56+ [IEEE80211_AC_VO] = 6
57+ };
58+
59+ if (WARN_ON(ac >= IEEE80211_NUM_ACS))
60+ return 0;
61+
62+ return ac_to_tid[ac];
63+}
64+
65 static inline struct ieee80211_txq *
66 mtxq_to_txq(struct mt76_txq *mtxq)
67 {
68diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developer9237f442024-06-14 17:13:04 +080069index 61a14a8..f389470 100644
developer66e89bc2024-04-23 14:50:01 +080070--- a/mt76_connac_mcu.h
71+++ b/mt76_connac_mcu.h
developer9237f442024-06-14 17:13:04 +080072@@ -1372,11 +1372,23 @@ enum {
developer66e89bc2024-04-23 14:50:01 +080073 UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
74 };
75
76+enum UNI_PER_STA_INFO_TAG {
77+ UNI_PER_STA_RSSI,
78+ UNI_PER_STA_CONTENTION_RX_RATE,
79+ UNI_PER_STA_PER,
80+ UNI_PER_STA_SNR,
81+ UNI_PER_STA_TX_RATE,
82+ UNI_PER_STA_TX_CNT,
83+ UNI_PER_STA_TID_SN_GET,
84+ UNI_PER_STA_TID_SN_SET,
85+ UNI_PER_STA_MAX_NUM
86+};
87+
88 enum UNI_ALL_STA_INFO_TAG {
89 UNI_ALL_STA_TXRX_RATE,
90 UNI_ALL_STA_TX_STAT,
91 UNI_ALL_STA_TXRX_ADM_STAT,
92- UNI_ALL_STA_TXRX_AIR_TIME,
93+ UNI_ALL_STA_TXRX_AIRTIME,
94 UNI_ALL_STA_DATA_TX_RETRY_COUNT,
95 UNI_ALL_STA_GI_MODE,
96 UNI_ALL_STA_TXRX_MSDU_COUNT,
97diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
developer9237f442024-06-14 17:13:04 +080098index f8ba573..e26de48 100644
developer66e89bc2024-04-23 14:50:01 +080099--- a/mt7996/debugfs.c
100+++ b/mt7996/debugfs.c
101@@ -992,12 +992,11 @@ mt7996_airtime_read(struct seq_file *s, void *data)
102 {
103 struct mt7996_dev *dev = dev_get_drvdata(s->private);
104 struct mt76_dev *mdev = &dev->mt76;
105- struct mt7996_vow_sta_ctrl *vow;
106+ struct mt76_sta_stats *stats;
107 struct ieee80211_sta *sta;
108 struct mt7996_sta *msta;
109 struct mt76_wcid *wcid;
110 struct mt76_vif *vif;
111- u64 airtime;
112 u16 i;
113
114 seq_printf(s, "VoW Airtime Information:\n");
115@@ -1009,16 +1008,16 @@ mt7996_airtime_read(struct seq_file *s, void *data)
116
117 msta = container_of(wcid, struct mt7996_sta, wcid);
118 sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
119- vow = &msta->vow;
120 vif = &msta->vif->mt76;
121+ stats = &wcid->stats;
122
123- spin_lock_bh(&vow->lock);
124- airtime = vow->tx_airtime;
125- vow->tx_airtime = 0;
126- spin_unlock_bh(&vow->lock);
127+ seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\t"
128+ "TxAirtime: %llu\tRxAirtime: %llu\n",
129+ sta->addr, i, vif->band_idx, vif->omac_idx,
130+ stats->tx_airtime, stats->rx_airtime);
131
132- seq_printf(s, "%pM WCID: %hu BandIdx: %hhu OmacIdx: 0x%hhx\tTxAirtime: %llu\n",
133- sta->addr, i, vif->band_idx, vif->omac_idx, airtime);
134+ stats->tx_airtime = 0;
135+ stats->rx_airtime = 0;
136 }
137 rcu_read_unlock();
138
139diff --git a/mt7996/mac.c b/mt7996/mac.c
developer9237f442024-06-14 17:13:04 +0800140index 0805251..782594c 100644
developer66e89bc2024-04-23 14:50:01 +0800141--- a/mt7996/mac.c
142+++ b/mt7996/mac.c
143@@ -12,8 +12,6 @@
144 #include "mcu.h"
145 #include "vendor.h"
146
147-#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
148-
149 static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
150 .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
151 .radar_pattern = {
152@@ -93,110 +91,6 @@ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw)
153 return MT_WTBL_LMAC_OFFS(wcid, dw);
154 }
155
156-static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
157-{
158- static const u8 ac_to_tid[] = {
159- [IEEE80211_AC_BE] = 0,
160- [IEEE80211_AC_BK] = 1,
161- [IEEE80211_AC_VI] = 4,
162- [IEEE80211_AC_VO] = 6
163- };
164- struct ieee80211_sta *sta;
165- struct mt7996_sta *msta;
166- struct mt7996_vow_sta_ctrl *vow;
167- u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
168- LIST_HEAD(sta_poll_list);
169- int i;
170-
171- spin_lock_bh(&dev->mt76.sta_poll_lock);
172- list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
173- spin_unlock_bh(&dev->mt76.sta_poll_lock);
174-
175- rcu_read_lock();
176-
177- while (true) {
178- bool clear = false;
179- u32 addr, val;
180- u16 idx;
181- s8 rssi[4];
182-
183- spin_lock_bh(&dev->mt76.sta_poll_lock);
184- if (list_empty(&sta_poll_list)) {
185- spin_unlock_bh(&dev->mt76.sta_poll_lock);
186- break;
187- }
188- msta = list_first_entry(&sta_poll_list,
189- struct mt7996_sta, wcid.poll_list);
190- list_del_init(&msta->wcid.poll_list);
191- spin_unlock_bh(&dev->mt76.sta_poll_lock);
192-
193- idx = msta->wcid.idx;
194-
195- /* refresh peer's airtime reporting */
196- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
197-
198- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
199- u32 tx_last = msta->airtime_ac[i];
200- u32 rx_last = msta->airtime_ac[i + 4];
201-
202- msta->airtime_ac[i] = mt76_rr(dev, addr);
203- msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
204-
205- tx_time[i] = msta->airtime_ac[i] - tx_last;
206- rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
207-
208- if ((tx_last | rx_last) & BIT(30))
209- clear = true;
210-
211- addr += 8;
212- }
213-
214- if (clear) {
215- mt7996_mac_wtbl_update(dev, idx,
216- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
217- memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
218- }
219-
220- if (!msta->wcid.sta)
221- continue;
222-
223- sta = container_of((void *)msta, struct ieee80211_sta,
224- drv_priv);
225- vow = &msta->vow;
226- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
227- u8 q = mt76_connac_lmac_mapping(i);
228- u32 tx_cur = tx_time[q];
229- u32 rx_cur = rx_time[q];
230- u8 tid = ac_to_tid[i];
231-
232- if (!tx_cur && !rx_cur)
233- continue;
234-
235- ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
236-
237- spin_lock_bh(&vow->lock);
238- vow->tx_airtime += tx_cur;
239- spin_unlock_bh(&vow->lock);
240- }
241-
242- /* get signal strength of resp frames (CTS/BA/ACK) */
243- addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
244- val = mt76_rr(dev, addr);
245-
246- rssi[0] = to_rssi(GENMASK(7, 0), val);
247- rssi[1] = to_rssi(GENMASK(15, 8), val);
248- rssi[2] = to_rssi(GENMASK(23, 16), val);
249- rssi[3] = to_rssi(GENMASK(31, 14), val);
250-
251- msta->ack_signal =
252- mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
253-
254- ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
255- }
256-
257- rcu_read_unlock();
258-}
259-
260 void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
261 struct ieee80211_vif *vif, bool enable)
262 {
263@@ -1206,8 +1100,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
264 }
265 }
266
267- mt7996_mac_sta_poll(dev);
268-
269 if (wake)
270 mt76_set_tx_blocked(&dev->mt76, false);
271
272@@ -2379,31 +2271,42 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
273
274 void mt7996_mac_work(struct work_struct *work)
275 {
276- struct mt7996_phy *phy;
277- struct mt76_phy *mphy;
278-
279- mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
280- mac_work.work);
281- phy = mphy->priv;
282+ struct mt76_phy *mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
283+ mac_work.work);
284+ struct mt7996_phy *phy = mphy->priv;
285+ struct mt76_dev *mdev = mphy->dev;
286
287- mutex_lock(&mphy->dev->mutex);
288+ mutex_lock(&mdev->mutex);
289
290 mt76_update_survey(mphy);
291 if (++mphy->mac_work_count == 5) {
292+ int i;
293+
294 mphy->mac_work_count = 0;
295
296 mt7996_mac_update_stats(phy);
297
298- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_RATE);
299- if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
300- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
301- mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
302+ /* Update DEV-wise information only in
303+ * the MAC work of the first band running.
304+ */
305+ for (i = MT_BAND0; i <= mphy->band_idx; ++i) {
306+ if (i == mphy->band_idx) {
307+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_RATE);
308+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_AIRTIME);
309+ mt7996_mcu_get_rssi(mdev);
310+ if (mtk_wed_device_active(&mdev->mmio.wed)) {
311+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_ADM_STAT);
312+ mt7996_mcu_get_all_sta_info(mdev, UNI_ALL_STA_TXRX_MSDU_COUNT);
313+ }
314+ } else if (mt7996_band_valid(phy->dev, i) &&
315+ test_bit(MT76_STATE_RUNNING, &mdev->phys[i]->state))
316+ break;
317 }
318 }
319
320- mutex_unlock(&mphy->dev->mutex);
321+ mutex_unlock(&mdev->mutex);
322
323- mt76_tx_status_check(mphy->dev, false);
324+ mt76_tx_status_check(mdev, false);
325
326 ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
327 MT7996_WATCHDOG_TIME);
328diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer9237f442024-06-14 17:13:04 +0800329index 6366cf0..b02303b 100644
developer66e89bc2024-04-23 14:50:01 +0800330--- a/mt7996/mcu.c
331+++ b/mt7996/mcu.c
332@@ -563,7 +563,8 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
333 u16 wlan_idx;
334 struct mt76_wcid *wcid;
335 struct mt76_phy *mphy;
336- u32 tx_bytes, rx_bytes, tx_packets, rx_packets;
337+ struct ieee80211_sta *sta;
338+ u32 tx_bytes, rx_bytes, tx_airtime, rx_airtime, tx_packets, rx_packets;
339
340 switch (le16_to_cpu(res->tag)) {
341 case UNI_ALL_STA_TXRX_RATE:
342@@ -584,7 +585,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
343 break;
344
345 mphy = mt76_dev_phy(&dev->mt76, wcid->phy_idx);
346- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
347+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
348 tx_bytes = le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
349 rx_bytes = le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
350
351@@ -616,6 +617,24 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
352 __mt7996_stat_to_netdev(mphy, wcid, 0, 0,
353 tx_packets, rx_packets);
354 break;
355+ case UNI_ALL_STA_TXRX_AIRTIME:
356+ wlan_idx = le16_to_cpu(res->airtime[i].wlan_idx);
357+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
358+ sta = wcid_to_sta(wcid);
359+ if (!sta)
360+ continue;
361+
362+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ++ac) {
363+ u8 lmac_ac = mt76_connac_lmac_mapping(ac);
364+ tx_airtime = le32_to_cpu(res->airtime[i].tx[lmac_ac]);
365+ rx_airtime = le32_to_cpu(res->airtime[i].rx[lmac_ac]);
366+
367+ wcid->stats.tx_airtime += tx_airtime;
368+ wcid->stats.rx_airtime += rx_airtime;
369+ ieee80211_sta_register_airtime(sta, mt76_ac_to_tid(ac),
370+ tx_airtime, rx_airtime);
371+ }
372+ break;
373 default:
374 break;
375 }
376@@ -2244,8 +2263,6 @@ mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
377 vow->drr_quantum[IEEE80211_AC_VI] = VOW_DRR_QUANTUM_IDX1;
378 vow->drr_quantum[IEEE80211_AC_BE] = VOW_DRR_QUANTUM_IDX2;
379 vow->drr_quantum[IEEE80211_AC_BK] = VOW_DRR_QUANTUM_IDX2;
380- vow->tx_airtime = 0;
381- spin_lock_init(&vow->lock);
382
383 ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
384 if (ret)
385@@ -4839,9 +4856,155 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
386 sizeof(req), true);
387 }
388
389-int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
390+int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
391+ u16 sta_num, u16 *sta_list)
392+{
393+#define PER_STA_INFO_MAX_NUM 90
394+ struct mt7996_mcu_per_sta_info_event *res;
395+ struct mt76_wcid *wcid;
396+ struct sk_buff *skb;
397+ u16 wlan_idx;
398+ int i, ret;
399+ struct {
400+ u8 __rsv1;
401+ u8 unsolicit;
402+ u8 __rsv2[2];
403+
404+ __le16 tag;
405+ __le16 len;
406+ __le16 sta_num;
407+ u8 __rsv3[2];
408+ __le16 sta_list[PER_STA_INFO_MAX_NUM];
409+ } __packed req = {
410+ .unsolicit = 0,
411+ .tag = cpu_to_le16(tag),
412+ .len = cpu_to_le16(sizeof(req) - 4),
413+ .sta_num = cpu_to_le16(sta_num)
414+ };
415+
416+ if (sta_num > PER_STA_INFO_MAX_NUM)
417+ return -EINVAL;
418+
419+ for (i = 0; i < sta_num; ++i)
420+ req.sta_list[i] = cpu_to_le16(sta_list[i]);
421+
422+ ret = mt76_mcu_send_and_get_msg(dev, MCU_WM_UNI_CMD(PER_STA_INFO),
423+ &req, sizeof(req), true, &skb);
424+ if (ret)
425+ return ret;
426+
427+ res = (struct mt7996_mcu_per_sta_info_event *)skb->data;
428+ if (le16_to_cpu(res->tag) != tag) {
429+ ret = -EINVAL;
430+ goto out;
431+ }
432+
433+ rcu_read_lock();
434+ switch (tag) {
435+ case UNI_PER_STA_RSSI:
436+ for (i = 0; i < sta_num; ++i) {
437+ struct mt7996_sta *msta;
438+ struct mt76_phy *phy;
439+ s8 rssi[4];
440+ u8 *rcpi;
441+
442+ wlan_idx = le16_to_cpu(res->rssi[i].wlan_idx);
443+ wcid = rcu_dereference(dev->wcid[wlan_idx]);
444+ if (wcid) {
445+ rcpi = res->rssi[i].rcpi;
446+ rssi[0] = to_rssi(MT_PRXV_RCPI0, rcpi[0]);
447+ rssi[1] = to_rssi(MT_PRXV_RCPI0, rcpi[1]);
448+ rssi[2] = to_rssi(MT_PRXV_RCPI0, rcpi[2]);
449+ rssi[3] = to_rssi(MT_PRXV_RCPI0, rcpi[3]);
450+
451+ msta = container_of(wcid, struct mt7996_sta, wcid);
452+ phy = msta->vif->phy->mt76;
453+ msta->ack_signal = mt76_rx_signal(phy->antenna_mask, rssi);
454+ ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
455+ } else {
456+ ret = -EINVAL;
457+ dev_err(dev->dev, "Failed to update RSSI for "
458+ "invalid WCID: %hu\n", wlan_idx);
459+ }
460+ }
461+ break;
462+ case UNI_PER_STA_TX_CNT:
463+ for (i = 0; i < sta_num; ++i) {
464+ wlan_idx = le16_to_cpu(res->tx_cnt[i].wlan_idx);
465+ wcid = rcu_dereference(dev->wcid[wlan_idx]);
466+ if (wcid) {
467+ wcid->stats.tx_total_mpdu_cnt +=
468+ le32_to_cpu(res->tx_cnt[i].total);
469+ wcid->stats.tx_failed_mpdu_cnt +=
470+ le32_to_cpu(res->tx_cnt[i].failed);
471+ } else {
472+ ret = -EINVAL;
473+ dev_err(dev->dev, "Failed to update TX MPDU counts "
474+ "for invalid WCID: %hu\n", wlan_idx);
475+ }
476+ }
477+ break;
478+ default:
479+ ret = -EINVAL;
480+ dev_err(dev->dev, "Unknown UNI_PER_STA_INFO_TAG: %d\n", tag);
481+ }
482+ rcu_read_unlock();
483+out:
484+ dev_kfree_skb(skb);
485+ return ret;
486+}
487+
488+int mt7996_mcu_get_rssi(struct mt76_dev *dev)
489+{
490+ u16 sta_list[PER_STA_INFO_MAX_NUM];
491+ LIST_HEAD(sta_poll_list);
492+ struct mt7996_sta *msta;
493+ int i, ret;
494+ bool empty = false;
495+
496+ spin_lock_bh(&dev->sta_poll_lock);
497+ list_splice_init(&dev->sta_poll_list, &sta_poll_list);
498+ spin_unlock_bh(&dev->sta_poll_lock);
499+
500+ while (!empty) {
501+ for (i = 0; i < PER_STA_INFO_MAX_NUM; ++i) {
502+ spin_lock_bh(&dev->sta_poll_lock);
503+ if (list_empty(&sta_poll_list)) {
504+ spin_unlock_bh(&dev->sta_poll_lock);
505+
506+ if (i == 0)
507+ return 0;
508+
509+ empty = true;
510+ break;
511+ }
512+ msta = list_first_entry(&sta_poll_list,
513+ struct mt7996_sta,
514+ wcid.poll_list);
515+ list_del_init(&msta->wcid.poll_list);
516+ spin_unlock_bh(&dev->sta_poll_lock);
517+
518+ sta_list[i] = msta->wcid.idx;
519+ }
520+
521+ ret = mt7996_mcu_get_per_sta_info(dev, UNI_PER_STA_RSSI,
522+ i, sta_list);
523+ if (ret) {
524+ /* Add STAs, whose RSSI has not been updated,
525+ * back to polling list.
526+ */
527+ spin_lock_bh(&dev->sta_poll_lock);
528+ list_splice(&sta_poll_list, &dev->sta_poll_list);
529+ spin_unlock_bh(&dev->sta_poll_lock);
530+ break;
531+ }
532+ }
533+
534+ return ret;
535+}
536+
537+int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag)
538 {
539- struct mt7996_dev *dev = phy->dev;
540 struct {
541 u8 _rsv[4];
542
543@@ -4852,7 +5015,7 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
544 .len = cpu_to_le16(sizeof(req) - 4),
545 };
546
547- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
548+ return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(ALL_STA_INFO),
549 &req, sizeof(req), false);
550 }
551
552diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer9237f442024-06-14 17:13:04 +0800553index a58f52d..e64812c 100644
developer66e89bc2024-04-23 14:50:01 +0800554--- a/mt7996/mcu.h
555+++ b/mt7996/mcu.h
556@@ -199,6 +199,31 @@ struct mt7996_mcu_mib {
557 __le64 data;
558 } __packed;
559
560+struct per_sta_rssi {
561+ __le16 wlan_idx;
562+ u8 __rsv[2];
563+ u8 rcpi[4];
564+} __packed;
565+
566+struct per_sta_tx_cnt {
567+ __le16 wlan_idx;
568+ u8 __rsv[2];
569+ __le32 total;
570+ __le32 failed;
571+} __packed;
572+
573+struct mt7996_mcu_per_sta_info_event {
574+ u8 __rsv[4];
575+
576+ __le16 tag;
577+ __le16 len;
578+
579+ union {
580+ struct per_sta_rssi rssi[0];
581+ struct per_sta_tx_cnt tx_cnt[0];
582+ };
583+} __packed;
584+
585 struct all_sta_trx_rate {
586 __le16 wlan_idx;
587 u8 __rsv1[2];
588@@ -237,13 +262,18 @@ struct mt7996_mcu_all_sta_info_event {
589 __le32 tx_bytes[IEEE80211_NUM_ACS];
590 __le32 rx_bytes[IEEE80211_NUM_ACS];
591 } adm_stat[0] __packed;
592-
593 struct {
594 __le16 wlan_idx;
595 u8 rsv[2];
596 __le32 tx_msdu_cnt;
597 __le32 rx_msdu_cnt;
598 } msdu_cnt[0] __packed;
599+ struct {
600+ __le16 wlan_idx;
601+ u8 __rsv[2];
602+ __le32 tx[IEEE80211_NUM_ACS];
603+ __le32 rx[IEEE80211_NUM_ACS];
604+ } airtime[0] __packed;
605 } __packed;
606 } __packed;
607
608diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer9237f442024-06-14 17:13:04 +0800609index 929a077..a0cc8f3 100644
developer66e89bc2024-04-23 14:50:01 +0800610--- a/mt7996/mt7996.h
611+++ b/mt7996/mt7996.h
612@@ -125,6 +125,8 @@
613 #define MT7996_RRO_MSDU_PG_CR_CNT 8
614 #define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
615
616+#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
617+
618 struct mt7996_vif;
619 struct mt7996_sta;
620 struct mt7996_dfs_pulse;
621@@ -297,8 +299,6 @@ struct mt7996_vow_sta_ctrl {
622 bool paused;
623 u8 bss_grp_idx;
624 u8 drr_quantum[IEEE80211_NUM_ACS];
625- u64 tx_airtime;
626- spinlock_t lock;
627 };
628
629 struct mt7996_sta {
630@@ -307,7 +307,6 @@ struct mt7996_sta {
631 struct mt7996_vif *vif;
632
633 struct list_head rc_list;
634- u32 airtime_ac[8];
635
636 int ack_signal;
637 struct ewma_avg_signal avg_ack_signal;
638@@ -404,6 +403,21 @@ struct mt7996_air_monitor_ctrl {
639 };
640 #endif
641
642+struct mt7996_rro_ba_session {
643+ u32 ack_sn :12;
644+ u32 win_sz :3;
645+ u32 bn :1;
646+ u32 last_in_sn :12;
647+ u32 bc :1;
648+ u32 bd :1;
649+ u32 sat :1;
650+ u32 cn :1;
651+ u32 within_cnt :12;
652+ u32 to_sel :3;
653+ u32 rsv :1;
654+ u32 last_in_rxtime :12;
655+};
656+
657 struct mt7996_phy {
658 struct mt76_phy *mt76;
659 struct mt7996_dev *dev;
660@@ -599,6 +613,7 @@ struct mt7996_dev {
661 u32 fw_dbg_module;
662 u8 fw_dbg_lv;
663 u32 bcn_total_cnt[__MT_MAX_BAND];
664+ u32 sid;
665 } dbg;
666 const struct mt7996_dbg_reg_desc *dbg_reg;
667 #endif
668@@ -824,7 +839,10 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
669 int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
670 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
671 void mt7996_mcu_exit(struct mt7996_dev *dev);
672-int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
673+int mt7996_mcu_get_per_sta_info(struct mt76_dev *dev, u16 tag,
674+ u16 sta_num, u16 *sta_list);
675+int mt7996_mcu_get_rssi(struct mt76_dev *dev);
676+int mt7996_mcu_get_all_sta_info(struct mt76_dev *dev, u16 tag);
677 int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
678 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
679 int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
680diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
developer9237f442024-06-14 17:13:04 +0800681index 70ff761..dab5b23 100644
developer66e89bc2024-04-23 14:50:01 +0800682--- a/mt7996/mtk_debugfs.c
683+++ b/mt7996/mtk_debugfs.c
684@@ -3106,6 +3106,69 @@ mt7996_vow_drr_dbg(void *data, u64 val)
685 DEFINE_DEBUGFS_ATTRIBUTE(fops_vow_drr_dbg, NULL,
686 mt7996_vow_drr_dbg, "%lld\n");
687
688+static int
689+mt7996_rro_session_read(struct seq_file *s, void *data)
690+{
691+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
692+ struct mt7996_rro_ba_session *tbl;
693+ u32 value[2];
694+
695+ mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC +
696+ (dev->dbg.sid >> 1) + 0x200);
697+
698+ if (dev->dbg.sid & 0x1) {
699+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
700+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(3));
701+ } else {
702+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
703+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
704+ }
705+
706+ tbl = (struct mt7996_rro_ba_session *)&value[0];
707+
708+ seq_printf(s, " seid %d:\nba session table DW0:%08x DW2:%08x\n",
709+ dev->dbg.sid, value[0], value[1]);
710+
711+ seq_printf(s, "ack_sn = 0x%x, last_in_sn = 0x%x, sat/bn/bc/bd/cn = %d/%d/%d/%d/%d\n",
712+ tbl->ack_sn, tbl->last_in_sn, tbl->sat, tbl->bn, tbl->bc, tbl->bd, tbl->cn);
713+
714+ seq_printf(s, "within_cnt = %d, to_sel = %d, last_in_rxtime = %d\n",
715+ tbl->within_cnt, tbl->to_sel, tbl->last_in_rxtime);
716+
717+ return 0;
718+}
719+
720+static int
721+mt7996_show_rro_mib(struct seq_file *s, void *data)
722+{
723+ struct mt7996_dev *dev = dev_get_drvdata(s->private);
724+ u32 reg[12];
725+
726+ seq_printf(s, "RRO mib Info:\n");
727+
728+ reg[0] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(0));
729+ reg[1] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(1));
730+ reg[2] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(2));
731+ reg[3] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(3));
732+ reg[4] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(4));
733+ reg[5] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(5));
734+ reg[6] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(6));
735+ reg[7] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(7));
736+ reg[8] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(8));
737+ reg[9] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(9));
738+ reg[10] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(10));
739+ reg[11] = mt76_rr(dev, WF_RRO_TOP_STATISTIC(11));
740+
741+ seq_printf(s, "STEP_ONE/WITHIN/SURPASS = %x/%x/%x\n", reg[0], reg[3], reg[4]);
742+ seq_printf(s, "REPEAT/OLDPKT/BAR = %x/%x/%x\n", reg[1], reg[2], reg[5]);
743+ seq_printf(s, "SURPASS with big gap = %x\n", reg[6]);
744+ seq_printf(s, "DISCONNECT/INVALID = %x/%x\n", reg[7], reg[8]);
745+ seq_printf(s, "TO(Step one)/TO(flush all) = %x/%x\n", reg[9], reg[10]);
746+ seq_printf(s, "buf ran out = %x\n", reg[11]);
747+
748+ return 0;
749+}
750+
751 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
752 {
753 struct mt7996_dev *dev = phy->dev;
754@@ -3205,6 +3268,14 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
755
756 debugfs_create_file("muru_prot_thr", 0200, dir, phy, &fops_muru_prot_thr);
757
758+ if (dev->has_rro) {
759+ debugfs_create_u32("rro_sid", 0600, dir, &dev->dbg.sid);
760+ debugfs_create_devm_seqfile(dev->mt76.dev, "rro_sid_info", dir,
761+ mt7996_rro_session_read);
762+ debugfs_create_devm_seqfile(dev->mt76.dev, "rro_mib", dir,
763+ mt7996_show_rro_mib);
764+ }
765+
766 return 0;
767 }
768
769diff --git a/mt7996/regs.h b/mt7996/regs.h
developer9237f442024-06-14 17:13:04 +0800770index cbd7170..a001d9f 100644
developer66e89bc2024-04-23 14:50:01 +0800771--- a/mt7996/regs.h
772+++ b/mt7996/regs.h
773@@ -122,6 +122,8 @@ enum offs_rev {
774 #define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
775 #define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
776
777+#define WF_RRO_TOP_STATISTIC(_n) MT_RRO_TOP(0x180 + _n * 0x4)
778+
779 /* PLE */
780 #define MT_PLE_BASE 0x820c0000
781 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
782--
developer9237f442024-06-14 17:13:04 +08007832.18.0
developer66e89bc2024-04-23 14:50:01 +0800784