blob: 8f61926db7c68204692d6e949f53b20c8a5cd74d [file] [log] [blame]
developer47efbdb2023-06-29 20:33:22 +08001From 3a498fb75b2f609a41019f844873496117b1fff6 Mon Sep 17 00:00:00 2001
2From: Peter Chiu <chui-hao.chiu@mediatek.com>
3Date: Wed, 11 Jan 2023 10:56:27 +0800
4Subject: [PATCH] wifi: mt76: add debugfs knob to show packet error rate
5
6Get tx count and tx failed from mcu command
7---
8 mt76.h | 2 +
9 mt76_connac_mcu.h | 1 +
10 mt7915/mcu.c | 108 +++++++++++++++++++++++++++++++++++++++++++
11 mt7915/mcu.h | 21 ++++++++-
12 mt7915/mt7915.h | 1 +
13 mt7915/mtk_debugfs.c | 62 +++++++++++++++++++++++++
14 6 files changed, 194 insertions(+), 1 deletion(-)
15
16diff --git a/mt76.h b/mt76.h
17index 6c488bd1..cbd63695 100644
18--- a/mt76.h
19+++ b/mt76.h
20@@ -297,8 +297,10 @@ struct mt76_sta_stats {
21 u64 tx_bytes;
22 /* WED TX */
23 u32 tx_packets; /* unit: MSDU */
24+ u32 tx_mpdu_cnt;
25 u32 tx_retries;
26 u32 tx_failed;
27+ u32 tx_failed_wm;
28 /* WED RX */
29 u64 rx_bytes;
30 u32 rx_packets;
31diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
32index 1257dfa1..cfdee7c1 100644
33--- a/mt76_connac_mcu.h
34+++ b/mt76_connac_mcu.h
35@@ -1162,6 +1162,7 @@ enum {
36 MCU_EXT_CMD_EDCA_UPDATE = 0x27,
37 MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
38 MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
39+ MCU_EXT_CMD_GET_TX_STAT = 0x30,
40 MCU_EXT_CMD_WTBL_UPDATE = 0x32,
41 MCU_EXT_CMD_SET_DRR_CTRL = 0x36,
42 MCU_EXT_CMD_SET_FEATURE_CTRL = 0x38,
43diff --git a/mt7915/mcu.c b/mt7915/mcu.c
44index 74728252..07a4b085 100644
45--- a/mt7915/mcu.c
46+++ b/mt7915/mcu.c
47@@ -4214,6 +4214,114 @@ int mt7915_mcu_get_tx_rate(struct mt7915_phy *phy, u16 wcidx)
48 return mt7915_mcu_get_tx_rate_v2(phy, wcidx);
49 }
50
51+static int mt7915_mcu_get_tx_stat_v1(struct mt7915_phy *phy,
52+ u16 wlan_idx)
53+{
54+#define to_wcid(hi, lo) (hi << 8 | lo)
55+ struct mt7915_dev *dev = phy->dev;
56+ struct mt76_phy *mphy = phy->mt76;
57+ struct mt7915_mcu_tx_stat_v1 *res;
58+ struct mt76_wcid *wcid;
59+ struct sk_buff *skb;
60+ struct {
61+ __le32 category;
62+ u8 wlan_idx_lo;
63+ u8 band;
64+ u8 wlan_idx_hi;
65+ u8 __rsv[5];
66+ } __packed req = {
67+ .category = cpu_to_le32(MCU_GET_TX_STAT_CNT),
68+ .band = mphy->band_idx,
69+ .wlan_idx_lo = to_wcid_lo(wlan_idx),
70+ .wlan_idx_hi = to_wcid_hi(wlan_idx),
71+ };
72+ int ret;
73+
74+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT),
75+ &req, sizeof(req), true, &skb);
76+ if (ret)
77+ return ret;
78+
79+ res = (struct mt7915_mcu_tx_stat_v1 *)skb->data;
80+
81+ if (to_wcid(res->wlan_idx_hi, res->wlan_idx_lo) != wlan_idx) {
82+ ret = -EINVAL;
83+ goto out;
84+ }
85+
86+ rcu_read_lock();
87+
88+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
89+ if (wcid) {
90+ wcid->stats.tx_mpdu_cnt += le32_to_cpu(res->tx_cnt);
91+ wcid->stats.tx_failed_wm += le32_to_cpu(res->tx_failed);
92+ } else {
93+ ret = -EINVAL;
94+ }
95+
96+ rcu_read_unlock();
97+out:
98+ dev_kfree_skb(skb);
99+
100+ return ret;
101+}
102+
103+static int mt7915_mcu_get_tx_stat_v2(struct mt7915_phy *phy,
104+ u16 wlan_idx)
105+{
106+ struct mt7915_dev *dev = phy->dev;
107+ struct mt76_phy *mphy = phy->mt76;
108+ struct mt7915_mcu_tx_stat_v2 *res;
109+ struct mt76_wcid *wcid;
110+ struct sk_buff *skb;
111+ struct {
112+ u8 category;
113+ u8 band;
114+ __le16 wcid;
115+ } __packed req = {
116+ .category = MCU_GET_TX_STAT_CNT,
117+ .band = mphy->band_idx,
118+ .wcid = cpu_to_le16(wlan_idx),
119+ };
120+ int ret;
121+
122+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT),
123+ &req, sizeof(req), true, &skb);
124+ if (ret)
125+ return ret;
126+
127+ res = (struct mt7915_mcu_tx_stat_v2 *)skb->data;
128+
129+ if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
130+ ret = -EINVAL;
131+ goto out;
132+ }
133+
134+ rcu_read_lock();
135+
136+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
137+ if (wcid) {
138+ wcid->stats.tx_mpdu_cnt += le32_to_cpu(res->tx_cnt);
139+ wcid->stats.tx_failed_wm += le32_to_cpu(res->tx_failed);
140+ } else {
141+ ret = -EINVAL;
142+ }
143+
144+ rcu_read_unlock();
145+out:
146+ dev_kfree_skb(skb);
147+
148+ return ret;
149+}
150+
151+int mt7915_get_tx_stat(struct mt7915_phy *phy, u16 wlan_idx)
152+{
153+ if (is_mt7915(&phy->dev->mt76))
154+ return mt7915_mcu_get_tx_stat_v1(phy, wlan_idx);
155+
156+ return mt7915_mcu_get_tx_stat_v2(phy, wlan_idx);
157+}
158+
159 int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
160 struct cfg80211_he_bss_color *he_bss_color)
161 {
162diff --git a/mt7915/mcu.h b/mt7915/mcu.h
163index 82b0847d..d6849797 100644
164--- a/mt7915/mcu.h
165+++ b/mt7915/mcu.h
166@@ -790,7 +790,8 @@ mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
167 }
168
169 enum {
170- MCU_GET_TX_RATE = 4
171+ MCU_GET_TX_RATE = 4,
172+ MCU_GET_TX_STAT_CNT = 8
173 };
174
175 #ifdef CONFIG_MTK_VENDOR
176@@ -1069,6 +1070,24 @@ struct mt7915_muru {
177 /* DL&UL User config */
178 #define MURU_USER_CNT BIT(4)
179
180+struct mt7915_mcu_tx_stat_v1 {
181+ u8 wlan_idx_lo;
182+ u8 band_idx;
183+ u8 wlan_idx_hi;
184+ u8 __rsv1[29];
185+ __le32 tx_cnt;
186+ __le32 tx_failed;
187+ u8 __rsv2[26];
188+};
189+
190+struct mt7915_mcu_tx_stat_v2 {
191+ u8 __rsv1[4];
192+ __le16 wlan_idx;
193+ u8 __rsv2[2];
194+ __le32 tx_cnt;
195+ __le32 tx_failed;
196+};
197+
198 enum {
199 CAPI_SU,
200 CAPI_MU,
201diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
202index 0153e5fe..85c5c95c 100644
203--- a/mt7915/mt7915.h
204+++ b/mt7915/mt7915.h
205@@ -661,6 +661,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
206 int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
207 struct cfg80211_chan_def *chandef);
208 int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid);
209+int mt7915_get_tx_stat(struct mt7915_phy *phy, u16 wlan_idx);
210 int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
211 int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
212 int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
213diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
214index 3eeb921f..da33578c 100644
215--- a/mt7915/mtk_debugfs.c
216+++ b/mt7915/mtk_debugfs.c
217@@ -3790,6 +3790,66 @@ mt7915_sw_aci_set(void *data, u64 val)
218 DEFINE_DEBUGFS_ATTRIBUTE(fops_sw_aci, NULL,
219 mt7915_sw_aci_set, "%llx\n");
220
221+static int mt7915_reset_counter(void *data, u64 val)
222+{
223+ struct mt7915_phy *phy = data;
224+ struct mt7915_dev *dev = phy->dev;
225+ struct mt76_wcid *wcid;
226+
227+ /* Clear the firmware counters */
228+ mt7915_mcu_wed_wa_tx_stats(dev, dev->wlan_idx);
229+ mt7915_get_tx_stat(phy, dev->wlan_idx);
230+
231+ rcu_read_lock();
232+ wcid = rcu_dereference(dev->mt76.wcid[dev->wlan_idx]);
233+ if (!wcid)
234+ return -EINVAL;
235+
236+ memset(&wcid->stats, 0, sizeof(struct mt76_sta_stats));
237+
238+ rcu_read_unlock();
239+
240+ return 0;
241+}
242+
243+DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_counter, NULL,
244+ mt7915_reset_counter, "%lld\n");
245+
246+static int
247+mt7915_per_read(struct seq_file *s, void *data)
248+{
249+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
250+ struct mt76_sta_stats *stats;
251+ struct mt76_wcid *wcid;
252+ int ret;
253+ u8 phy_idx;
254+
255+ if (!dev->mt76.wcid[dev->wlan_idx])
256+ return -EINVAL;
257+
258+ phy_idx = dev->mt76.wcid[dev->wlan_idx]->phy_idx;
259+
260+ ret = mt7915_get_tx_stat(dev->mt76.phys[phy_idx]->priv, dev->wlan_idx);
261+ if (ret)
262+ return ret;
263+
264+ rcu_read_lock();
265+ wcid = rcu_dereference(dev->mt76.wcid[dev->wlan_idx]);
266+ if (!wcid)
267+ return -EINVAL;
268+
269+ stats = &wcid->stats;
270+
271+ seq_printf(s, "sta %d, tx_mpdu_cnt = %u, tx_failed = %u, PER = %u.%u%%\n", dev->wlan_idx,
272+ stats->tx_mpdu_cnt, stats->tx_failed_wm,
273+ stats->tx_mpdu_cnt ? stats->tx_failed_wm * 1000 / stats->tx_mpdu_cnt / 10 : 0,
274+ stats->tx_mpdu_cnt ? stats->tx_failed_wm * 1000 / stats->tx_mpdu_cnt % 10 : 0);
275+
276+ rcu_read_unlock();
277+
278+ return 0;
279+}
280+
281 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir)
282 {
283 struct mt7915_dev *dev = phy->dev;
284@@ -3880,6 +3940,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir)
285 mt7915_show_eeprom_mode);
286 debugfs_create_file("sw_aci", 0600, dir, dev,
287 &fops_sw_aci);
288+ debugfs_create_file("reset_counter", 0200, dir, dev, &fops_reset_counter);
289+ debugfs_create_devm_seqfile(dev->mt76.dev, "per", dir, mt7915_per_read);
290 return 0;
291 }
292 #endif
293--
2942.18.0
295