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