1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d5c65159SKalle Valo /*
3d5c65159SKalle Valo * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4*586c7fb1SJeff Johnson * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5d5c65159SKalle Valo */
6d5c65159SKalle Valo
7d5c65159SKalle Valo #include <linux/vmalloc.h>
8d5c65159SKalle Valo
9568f0603SKalle Valo #include "debugfs_sta.h"
10d5c65159SKalle Valo #include "core.h"
11d5c65159SKalle Valo #include "peer.h"
12d5c65159SKalle Valo #include "debug.h"
13559ef68fSAshok Raj Nagarajan #include "dp_tx.h"
1456292162SKalle Valo #include "debugfs_htt_stats.h"
15d5c65159SKalle Valo
ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta * arsta,struct ath11k_per_peer_tx_stats * peer_stats,u8 legacy_rate_idx)16568f0603SKalle Valo void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
17d5c65159SKalle Valo struct ath11k_per_peer_tx_stats *peer_stats,
18d5c65159SKalle Valo u8 legacy_rate_idx)
19d5c65159SKalle Valo {
20d5c65159SKalle Valo struct rate_info *txrate = &arsta->txrate;
21d5c65159SKalle Valo struct ath11k_htt_tx_stats *tx_stats;
22d5c65159SKalle Valo int gi, mcs, bw, nss;
23d5c65159SKalle Valo
24d5c65159SKalle Valo if (!arsta->tx_stats)
25d5c65159SKalle Valo return;
26d5c65159SKalle Valo
27d5c65159SKalle Valo tx_stats = arsta->tx_stats;
28d5c65159SKalle Valo gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
29d5c65159SKalle Valo mcs = txrate->mcs;
3092bacd1cSVenkateswara Naralasetty bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
31d5c65159SKalle Valo nss = txrate->nss - 1;
32d5c65159SKalle Valo
33d5c65159SKalle Valo #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
34d5c65159SKalle Valo
35d5c65159SKalle Valo if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
36d5c65159SKalle Valo STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
37d5c65159SKalle Valo STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
38d5c65159SKalle Valo STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
39d5c65159SKalle Valo STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
40d5c65159SKalle Valo STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
41d5c65159SKalle Valo STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
42d5c65159SKalle Valo } else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
43d5c65159SKalle Valo STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
44d5c65159SKalle Valo STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
45d5c65159SKalle Valo STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
46d5c65159SKalle Valo STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
47d5c65159SKalle Valo STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
48d5c65159SKalle Valo STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
49d5c65159SKalle Valo } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
50d5c65159SKalle Valo STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
51d5c65159SKalle Valo STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
52d5c65159SKalle Valo STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
53d5c65159SKalle Valo STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
54d5c65159SKalle Valo STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
55d5c65159SKalle Valo STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
56d5c65159SKalle Valo } else {
57d5c65159SKalle Valo mcs = legacy_rate_idx;
58d5c65159SKalle Valo
59d5c65159SKalle Valo STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
60d5c65159SKalle Valo STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
61d5c65159SKalle Valo STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
62d5c65159SKalle Valo STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
63d5c65159SKalle Valo STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
64d5c65159SKalle Valo STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
65d5c65159SKalle Valo }
66d5c65159SKalle Valo
67d5c65159SKalle Valo if (peer_stats->is_ampdu) {
68d5c65159SKalle Valo tx_stats->ba_fails += peer_stats->ba_fails;
69d5c65159SKalle Valo
70d5c65159SKalle Valo if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
71d5c65159SKalle Valo STATS_OP_FMT(AMPDU).he[0][mcs] +=
72d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
73d5c65159SKalle Valo STATS_OP_FMT(AMPDU).he[1][mcs] +=
74d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
75d5c65159SKalle Valo } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
76d5c65159SKalle Valo STATS_OP_FMT(AMPDU).ht[0][mcs] +=
77d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
78d5c65159SKalle Valo STATS_OP_FMT(AMPDU).ht[1][mcs] +=
79d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
80d5c65159SKalle Valo } else {
81d5c65159SKalle Valo STATS_OP_FMT(AMPDU).vht[0][mcs] +=
82d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
83d5c65159SKalle Valo STATS_OP_FMT(AMPDU).vht[1][mcs] +=
84d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
85d5c65159SKalle Valo }
86d5c65159SKalle Valo STATS_OP_FMT(AMPDU).bw[0][bw] +=
87d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
88d5c65159SKalle Valo STATS_OP_FMT(AMPDU).nss[0][nss] +=
89d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
90d5c65159SKalle Valo STATS_OP_FMT(AMPDU).gi[0][gi] +=
91d5c65159SKalle Valo peer_stats->succ_bytes + peer_stats->retry_bytes;
92d5c65159SKalle Valo STATS_OP_FMT(AMPDU).bw[1][bw] +=
93d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
94d5c65159SKalle Valo STATS_OP_FMT(AMPDU).nss[1][nss] +=
95d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
96d5c65159SKalle Valo STATS_OP_FMT(AMPDU).gi[1][gi] +=
97d5c65159SKalle Valo peer_stats->succ_pkts + peer_stats->retry_pkts;
98d5c65159SKalle Valo } else {
99d5c65159SKalle Valo tx_stats->ack_fails += peer_stats->ba_fails;
100d5c65159SKalle Valo }
101d5c65159SKalle Valo
102d5c65159SKalle Valo STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
103d5c65159SKalle Valo STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
104d5c65159SKalle Valo STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
105d5c65159SKalle Valo
106d5c65159SKalle Valo STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
107d5c65159SKalle Valo STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
108d5c65159SKalle Valo STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
109d5c65159SKalle Valo
110d5c65159SKalle Valo STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
111d5c65159SKalle Valo STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
112d5c65159SKalle Valo STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
113d5c65159SKalle Valo
114d5c65159SKalle Valo STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
115d5c65159SKalle Valo STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
116d5c65159SKalle Valo STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
117d5c65159SKalle Valo
118d5c65159SKalle Valo STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
119d5c65159SKalle Valo STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
120d5c65159SKalle Valo STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
121d5c65159SKalle Valo
122d5c65159SKalle Valo STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
123d5c65159SKalle Valo STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
124d5c65159SKalle Valo STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
125d5c65159SKalle Valo
126d5c65159SKalle Valo tx_stats->tx_duration += peer_stats->duration;
127d5c65159SKalle Valo }
128d5c65159SKalle Valo
ath11k_debugfs_sta_update_txcompl(struct ath11k * ar,struct hal_tx_status * ts)129568f0603SKalle Valo void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
130d5c65159SKalle Valo struct hal_tx_status *ts)
131d5c65159SKalle Valo {
1321b8bb94cSWen Gong ath11k_dp_tx_update_txcompl(ar, ts);
133d5c65159SKalle Valo }
134d5c65159SKalle Valo
ath11k_dbg_sta_dump_tx_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)135d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
136d5c65159SKalle Valo char __user *user_buf,
137d5c65159SKalle Valo size_t count, loff_t *ppos)
138d5c65159SKalle Valo {
139d5c65159SKalle Valo struct ieee80211_sta *sta = file->private_data;
140d5c65159SKalle Valo struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
141d5c65159SKalle Valo struct ath11k *ar = arsta->arvif->ar;
142d5c65159SKalle Valo struct ath11k_htt_data_stats *stats;
143d5c65159SKalle Valo static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
144d5c65159SKalle Valo "retry", "ampdu"};
145d5c65159SKalle Valo static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
146d5c65159SKalle Valo int len = 0, i, j, k, retval = 0;
147d5c65159SKalle Valo const int size = 2 * 4096;
148d5c65159SKalle Valo char *buf;
149d5c65159SKalle Valo
150fe0ebb51SPravas Kumar Panda if (!arsta->tx_stats)
151fe0ebb51SPravas Kumar Panda return -ENOENT;
152fe0ebb51SPravas Kumar Panda
153d5c65159SKalle Valo buf = kzalloc(size, GFP_KERNEL);
154d5c65159SKalle Valo if (!buf)
155d5c65159SKalle Valo return -ENOMEM;
156d5c65159SKalle Valo
157d5c65159SKalle Valo mutex_lock(&ar->conf_mutex);
158d5c65159SKalle Valo
159d5c65159SKalle Valo spin_lock_bh(&ar->data_lock);
160d5c65159SKalle Valo for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
161d5c65159SKalle Valo for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
162d5c65159SKalle Valo stats = &arsta->tx_stats->stats[k];
163d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "%s_%s\n",
164d5c65159SKalle Valo str_name[k],
165d5c65159SKalle Valo str[j]);
166d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
167d5c65159SKalle Valo " HE MCS %s\n",
168d5c65159SKalle Valo str[j]);
169d5c65159SKalle Valo for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
170d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
171d5c65159SKalle Valo " %llu ",
172d5c65159SKalle Valo stats->he[j][i]);
173d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\n");
174d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
175d5c65159SKalle Valo " VHT MCS %s\n",
176d5c65159SKalle Valo str[j]);
177d5c65159SKalle Valo for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
178d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
179d5c65159SKalle Valo " %llu ",
180d5c65159SKalle Valo stats->vht[j][i]);
181d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\n");
182d5c65159SKalle Valo len += scnprintf(buf + len, size - len, " HT MCS %s\n",
183d5c65159SKalle Valo str[j]);
184d5c65159SKalle Valo for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
185d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
186d5c65159SKalle Valo " %llu ", stats->ht[j][i]);
187d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\n");
188d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
189d5c65159SKalle Valo " BW %s (20,40,80,160 MHz)\n", str[j]);
190d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
191d5c65159SKalle Valo " %llu %llu %llu %llu\n",
192d5c65159SKalle Valo stats->bw[j][0], stats->bw[j][1],
193d5c65159SKalle Valo stats->bw[j][2], stats->bw[j][3]);
194d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
195d5c65159SKalle Valo " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
196d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
197d5c65159SKalle Valo " %llu %llu %llu %llu\n",
198d5c65159SKalle Valo stats->nss[j][0], stats->nss[j][1],
199d5c65159SKalle Valo stats->nss[j][2], stats->nss[j][3]);
200d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
201d5c65159SKalle Valo " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
202d5c65159SKalle Valo str[j]);
203d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
204d5c65159SKalle Valo " %llu %llu %llu %llu\n",
205d5c65159SKalle Valo stats->gi[j][0], stats->gi[j][1],
206d5c65159SKalle Valo stats->gi[j][2], stats->gi[j][3]);
207d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
208d5c65159SKalle Valo " legacy rate %s (1,2 ... Mbps)\n ",
209d5c65159SKalle Valo str[j]);
210d5c65159SKalle Valo for (i = 0; i < ATH11K_LEGACY_NUM; i++)
211d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "%llu ",
212d5c65159SKalle Valo stats->legacy[j][i]);
213d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\n");
214d5c65159SKalle Valo }
215d5c65159SKalle Valo }
216d5c65159SKalle Valo
217d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
218d5c65159SKalle Valo "\nTX duration\n %llu usecs\n",
219d5c65159SKalle Valo arsta->tx_stats->tx_duration);
220d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
221d5c65159SKalle Valo "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
222d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
223d5c65159SKalle Valo "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
224d5c65159SKalle Valo spin_unlock_bh(&ar->data_lock);
225d5c65159SKalle Valo
226d5c65159SKalle Valo if (len > size)
227d5c65159SKalle Valo len = size;
228d5c65159SKalle Valo retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
229d5c65159SKalle Valo kfree(buf);
230d5c65159SKalle Valo
231d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex);
232d5c65159SKalle Valo return retval;
233d5c65159SKalle Valo }
234d5c65159SKalle Valo
235d5c65159SKalle Valo static const struct file_operations fops_tx_stats = {
236d5c65159SKalle Valo .read = ath11k_dbg_sta_dump_tx_stats,
237d5c65159SKalle Valo .open = simple_open,
238d5c65159SKalle Valo .owner = THIS_MODULE,
239d5c65159SKalle Valo .llseek = default_llseek,
240d5c65159SKalle Valo };
241d5c65159SKalle Valo
ath11k_dbg_sta_dump_rx_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)242d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
243d5c65159SKalle Valo char __user *user_buf,
244d5c65159SKalle Valo size_t count, loff_t *ppos)
245d5c65159SKalle Valo {
246d5c65159SKalle Valo struct ieee80211_sta *sta = file->private_data;
247d5c65159SKalle Valo struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
248d5c65159SKalle Valo struct ath11k *ar = arsta->arvif->ar;
249d5c65159SKalle Valo struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
250d5c65159SKalle Valo int len = 0, i, retval = 0;
251d5c65159SKalle Valo const int size = 4096;
252d5c65159SKalle Valo char *buf;
253d5c65159SKalle Valo
254d5c65159SKalle Valo if (!rx_stats)
255d5c65159SKalle Valo return -ENOENT;
256d5c65159SKalle Valo
257d5c65159SKalle Valo buf = kzalloc(size, GFP_KERNEL);
258d5c65159SKalle Valo if (!buf)
259d5c65159SKalle Valo return -ENOMEM;
260d5c65159SKalle Valo
261d5c65159SKalle Valo mutex_lock(&ar->conf_mutex);
262d5c65159SKalle Valo spin_lock_bh(&ar->ab->base_lock);
263d5c65159SKalle Valo
264d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "RX peer stats:\n");
265d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
266d5c65159SKalle Valo rx_stats->num_msdu);
267d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
268d5c65159SKalle Valo rx_stats->tcp_msdu_count);
269d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
270d5c65159SKalle Valo rx_stats->udp_msdu_count);
271d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
272d5c65159SKalle Valo rx_stats->ampdu_msdu_count);
273d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
274d5c65159SKalle Valo rx_stats->non_ampdu_msdu_count);
275d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
276d5c65159SKalle Valo rx_stats->stbc_count);
277d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
278d5c65159SKalle Valo rx_stats->beamformed_count);
279d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
280d5c65159SKalle Valo rx_stats->num_mpdu_fcs_ok);
281d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
282d5c65159SKalle Valo rx_stats->num_mpdu_fcs_err);
283d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
284d5c65159SKalle Valo "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
285d5c65159SKalle Valo rx_stats->gi_count[0], rx_stats->gi_count[1],
286d5c65159SKalle Valo rx_stats->gi_count[2], rx_stats->gi_count[3]);
287d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
288d5c65159SKalle Valo "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
289d5c65159SKalle Valo rx_stats->bw_count[0], rx_stats->bw_count[1],
290d5c65159SKalle Valo rx_stats->bw_count[2], rx_stats->bw_count[3]);
291d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
292d5c65159SKalle Valo rx_stats->coding_count[0], rx_stats->coding_count[1]);
293d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
294d5c65159SKalle Valo "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
295d5c65159SKalle Valo rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
296d5c65159SKalle Valo rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
297d5c65159SKalle Valo rx_stats->pream_cnt[4]);
298d5c65159SKalle Valo len += scnprintf(buf + len, size - len,
299d5c65159SKalle Valo "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
300d5c65159SKalle Valo rx_stats->reception_type[0], rx_stats->reception_type[1],
301d5c65159SKalle Valo rx_stats->reception_type[2], rx_stats->reception_type[3]);
302d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
303d5c65159SKalle Valo for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
304d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
305d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
306d5c65159SKalle Valo for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
307d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
308d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
309d5c65159SKalle Valo for (i = 0; i < HAL_RX_MAX_NSS; i++)
310d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
311d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
312d5c65159SKalle Valo rx_stats->rx_duration);
3136a0c3702SJohn Crispin len += scnprintf(buf + len, size - len,
3146a0c3702SJohn Crispin "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
3156a0c3702SJohn Crispin rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
3166a0c3702SJohn Crispin rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
3176a0c3702SJohn Crispin rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
3186a0c3702SJohn Crispin rx_stats->ru_alloc_cnt[5]);
3196a0c3702SJohn Crispin
320d5c65159SKalle Valo len += scnprintf(buf + len, size - len, "\n");
321d5c65159SKalle Valo
322d5c65159SKalle Valo spin_unlock_bh(&ar->ab->base_lock);
323d5c65159SKalle Valo
324d5c65159SKalle Valo if (len > size)
325d5c65159SKalle Valo len = size;
326d5c65159SKalle Valo retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
327d5c65159SKalle Valo kfree(buf);
328d5c65159SKalle Valo
329d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex);
330d5c65159SKalle Valo return retval;
331d5c65159SKalle Valo }
332d5c65159SKalle Valo
333d5c65159SKalle Valo static const struct file_operations fops_rx_stats = {
334d5c65159SKalle Valo .read = ath11k_dbg_sta_dump_rx_stats,
335d5c65159SKalle Valo .open = simple_open,
336d5c65159SKalle Valo .owner = THIS_MODULE,
337d5c65159SKalle Valo .llseek = default_llseek,
338d5c65159SKalle Valo };
339d5c65159SKalle Valo
340d5c65159SKalle Valo static int
ath11k_dbg_sta_open_htt_peer_stats(struct inode * inode,struct file * file)341d5c65159SKalle Valo ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
342d5c65159SKalle Valo {
343d5c65159SKalle Valo struct ieee80211_sta *sta = inode->i_private;
344d5c65159SKalle Valo struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
345d5c65159SKalle Valo struct ath11k *ar = arsta->arvif->ar;
346d5c65159SKalle Valo struct debug_htt_stats_req *stats_req;
347ac83b603SVenkateswara Naralasetty int type = ar->debug.htt_stats.type;
348d5c65159SKalle Valo int ret;
349d5c65159SKalle Valo
350ac83b603SVenkateswara Naralasetty if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
351ac83b603SVenkateswara Naralasetty type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
352ac83b603SVenkateswara Naralasetty type == ATH11K_DBG_HTT_EXT_STATS_RESET)
353ac83b603SVenkateswara Naralasetty return -EPERM;
354ac83b603SVenkateswara Naralasetty
355d5c65159SKalle Valo stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
356d5c65159SKalle Valo if (!stats_req)
357d5c65159SKalle Valo return -ENOMEM;
358d5c65159SKalle Valo
359d5c65159SKalle Valo mutex_lock(&ar->conf_mutex);
360d5c65159SKalle Valo ar->debug.htt_stats.stats_req = stats_req;
361ac83b603SVenkateswara Naralasetty stats_req->type = type;
362d5c65159SKalle Valo memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
363568f0603SKalle Valo ret = ath11k_debugfs_htt_stats_req(ar);
364d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex);
365d5c65159SKalle Valo if (ret < 0)
366d5c65159SKalle Valo goto out;
367d5c65159SKalle Valo
368d5c65159SKalle Valo file->private_data = stats_req;
369d5c65159SKalle Valo return 0;
370d5c65159SKalle Valo out:
371d5c65159SKalle Valo vfree(stats_req);
37252f274b5SSowmiya Sree Elavalagan ar->debug.htt_stats.stats_req = NULL;
373d5c65159SKalle Valo return ret;
374d5c65159SKalle Valo }
375d5c65159SKalle Valo
376d5c65159SKalle Valo static int
ath11k_dbg_sta_release_htt_peer_stats(struct inode * inode,struct file * file)377d5c65159SKalle Valo ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
378d5c65159SKalle Valo {
37952f274b5SSowmiya Sree Elavalagan struct ieee80211_sta *sta = inode->i_private;
38052f274b5SSowmiya Sree Elavalagan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
38152f274b5SSowmiya Sree Elavalagan struct ath11k *ar = arsta->arvif->ar;
38252f274b5SSowmiya Sree Elavalagan
38352f274b5SSowmiya Sree Elavalagan mutex_lock(&ar->conf_mutex);
384d5c65159SKalle Valo vfree(file->private_data);
38552f274b5SSowmiya Sree Elavalagan ar->debug.htt_stats.stats_req = NULL;
38652f274b5SSowmiya Sree Elavalagan mutex_unlock(&ar->conf_mutex);
38752f274b5SSowmiya Sree Elavalagan
388d5c65159SKalle Valo return 0;
389d5c65159SKalle Valo }
390d5c65159SKalle Valo
ath11k_dbg_sta_read_htt_peer_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)391d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
392d5c65159SKalle Valo char __user *user_buf,
393d5c65159SKalle Valo size_t count, loff_t *ppos)
394d5c65159SKalle Valo {
395d5c65159SKalle Valo struct debug_htt_stats_req *stats_req = file->private_data;
396d5c65159SKalle Valo char *buf;
397d5c65159SKalle Valo u32 length = 0;
398d5c65159SKalle Valo
399d5c65159SKalle Valo buf = stats_req->buf;
400d5c65159SKalle Valo length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
401d5c65159SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, length);
402d5c65159SKalle Valo }
403d5c65159SKalle Valo
404d5c65159SKalle Valo static const struct file_operations fops_htt_peer_stats = {
405d5c65159SKalle Valo .open = ath11k_dbg_sta_open_htt_peer_stats,
406d5c65159SKalle Valo .release = ath11k_dbg_sta_release_htt_peer_stats,
407d5c65159SKalle Valo .read = ath11k_dbg_sta_read_htt_peer_stats,
408d5c65159SKalle Valo .owner = THIS_MODULE,
409d5c65159SKalle Valo .llseek = default_llseek,
410d5c65159SKalle Valo };
411d5c65159SKalle Valo
ath11k_dbg_sta_write_peer_pktlog(struct file * file,const char __user * buf,size_t count,loff_t * ppos)412d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
413d5c65159SKalle Valo const char __user *buf,
414d5c65159SKalle Valo size_t count, loff_t *ppos)
415d5c65159SKalle Valo {
416d5c65159SKalle Valo struct ieee80211_sta *sta = file->private_data;
417d5c65159SKalle Valo struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
418d5c65159SKalle Valo struct ath11k *ar = arsta->arvif->ar;
419d5c65159SKalle Valo int ret, enable;
420d5c65159SKalle Valo
421d5c65159SKalle Valo mutex_lock(&ar->conf_mutex);
422d5c65159SKalle Valo
423d5c65159SKalle Valo if (ar->state != ATH11K_STATE_ON) {
424d5c65159SKalle Valo ret = -ENETDOWN;
425d5c65159SKalle Valo goto out;
426d5c65159SKalle Valo }
427d5c65159SKalle Valo
428d5c65159SKalle Valo ret = kstrtoint_from_user(buf, count, 0, &enable);
429d5c65159SKalle Valo if (ret)
430d5c65159SKalle Valo goto out;
431d5c65159SKalle Valo
432d5c65159SKalle Valo ar->debug.pktlog_peer_valid = enable;
433d5c65159SKalle Valo memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
434d5c65159SKalle Valo
435d5c65159SKalle Valo /* Send peer based pktlog enable/disable */
436d5c65159SKalle Valo ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
437d5c65159SKalle Valo if (ret) {
438d5c65159SKalle Valo ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
439d5c65159SKalle Valo sta->addr, ret);
440d5c65159SKalle Valo goto out;
441d5c65159SKalle Valo }
442d5c65159SKalle Valo
443d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
444d5c65159SKalle Valo enable);
445d5c65159SKalle Valo ret = count;
446d5c65159SKalle Valo
447d5c65159SKalle Valo out:
448d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex);
449d5c65159SKalle Valo return ret;
450d5c65159SKalle Valo }
451d5c65159SKalle Valo
ath11k_dbg_sta_read_peer_pktlog(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)452d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
453d5c65159SKalle Valo char __user *ubuf,
454d5c65159SKalle Valo size_t count, loff_t *ppos)
455d5c65159SKalle Valo {
456d5c65159SKalle Valo struct ieee80211_sta *sta = file->private_data;
457d5c65159SKalle Valo struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
458d5c65159SKalle Valo struct ath11k *ar = arsta->arvif->ar;
459d5c65159SKalle Valo char buf[32] = {0};
460d5c65159SKalle Valo int len;
461d5c65159SKalle Valo
462d5c65159SKalle Valo mutex_lock(&ar->conf_mutex);
463d5c65159SKalle Valo len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
464d5c65159SKalle Valo ar->debug.pktlog_peer_valid,
465d5c65159SKalle Valo ar->debug.pktlog_peer_addr);
466d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex);
467d5c65159SKalle Valo
468d5c65159SKalle Valo return simple_read_from_buffer(ubuf, count, ppos, buf, len);
469d5c65159SKalle Valo }
470d5c65159SKalle Valo
471d5c65159SKalle Valo static const struct file_operations fops_peer_pktlog = {
472d5c65159SKalle Valo .write = ath11k_dbg_sta_write_peer_pktlog,
473d5c65159SKalle Valo .read = ath11k_dbg_sta_read_peer_pktlog,
474d5c65159SKalle Valo .open = simple_open,
475d5c65159SKalle Valo .owner = THIS_MODULE,
476d5c65159SKalle Valo .llseek = default_llseek,
477d5c65159SKalle Valo };
478d5c65159SKalle Valo
ath11k_dbg_sta_write_delba(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)4799556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
4809556dfa2SMaharaja Kennadyrajan const char __user *user_buf,
4819556dfa2SMaharaja Kennadyrajan size_t count, loff_t *ppos)
4829556dfa2SMaharaja Kennadyrajan {
4839556dfa2SMaharaja Kennadyrajan struct ieee80211_sta *sta = file->private_data;
4849556dfa2SMaharaja Kennadyrajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
4859556dfa2SMaharaja Kennadyrajan struct ath11k *ar = arsta->arvif->ar;
4869556dfa2SMaharaja Kennadyrajan u32 tid, initiator, reason;
4879556dfa2SMaharaja Kennadyrajan int ret;
4889556dfa2SMaharaja Kennadyrajan char buf[64] = {0};
4899556dfa2SMaharaja Kennadyrajan
4909556dfa2SMaharaja Kennadyrajan ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
4919556dfa2SMaharaja Kennadyrajan user_buf, count);
4929556dfa2SMaharaja Kennadyrajan if (ret <= 0)
4939556dfa2SMaharaja Kennadyrajan return ret;
4949556dfa2SMaharaja Kennadyrajan
4959556dfa2SMaharaja Kennadyrajan ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
4969556dfa2SMaharaja Kennadyrajan if (ret != 3)
4979556dfa2SMaharaja Kennadyrajan return -EINVAL;
4989556dfa2SMaharaja Kennadyrajan
4999556dfa2SMaharaja Kennadyrajan /* Valid TID values are 0 through 15 */
5009556dfa2SMaharaja Kennadyrajan if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
5019556dfa2SMaharaja Kennadyrajan return -EINVAL;
5029556dfa2SMaharaja Kennadyrajan
5039556dfa2SMaharaja Kennadyrajan mutex_lock(&ar->conf_mutex);
5049556dfa2SMaharaja Kennadyrajan if (ar->state != ATH11K_STATE_ON ||
5059556dfa2SMaharaja Kennadyrajan arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
5069556dfa2SMaharaja Kennadyrajan ret = count;
5079556dfa2SMaharaja Kennadyrajan goto out;
5089556dfa2SMaharaja Kennadyrajan }
5099556dfa2SMaharaja Kennadyrajan
5109556dfa2SMaharaja Kennadyrajan ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
5119556dfa2SMaharaja Kennadyrajan tid, initiator, reason);
5129556dfa2SMaharaja Kennadyrajan if (ret) {
5139556dfa2SMaharaja Kennadyrajan ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
5149556dfa2SMaharaja Kennadyrajan arsta->arvif->vdev_id, sta->addr, tid, initiator,
5159556dfa2SMaharaja Kennadyrajan reason);
5169556dfa2SMaharaja Kennadyrajan }
5179556dfa2SMaharaja Kennadyrajan ret = count;
5189556dfa2SMaharaja Kennadyrajan out:
5199556dfa2SMaharaja Kennadyrajan mutex_unlock(&ar->conf_mutex);
5209556dfa2SMaharaja Kennadyrajan return ret;
5219556dfa2SMaharaja Kennadyrajan }
5229556dfa2SMaharaja Kennadyrajan
5239556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_delba = {
5249556dfa2SMaharaja Kennadyrajan .write = ath11k_dbg_sta_write_delba,
5259556dfa2SMaharaja Kennadyrajan .open = simple_open,
5269556dfa2SMaharaja Kennadyrajan .owner = THIS_MODULE,
5279556dfa2SMaharaja Kennadyrajan .llseek = default_llseek,
5289556dfa2SMaharaja Kennadyrajan };
5299556dfa2SMaharaja Kennadyrajan
ath11k_dbg_sta_write_addba_resp(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)5309556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
5319556dfa2SMaharaja Kennadyrajan const char __user *user_buf,
5329556dfa2SMaharaja Kennadyrajan size_t count, loff_t *ppos)
5339556dfa2SMaharaja Kennadyrajan {
5349556dfa2SMaharaja Kennadyrajan struct ieee80211_sta *sta = file->private_data;
5359556dfa2SMaharaja Kennadyrajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5369556dfa2SMaharaja Kennadyrajan struct ath11k *ar = arsta->arvif->ar;
5379556dfa2SMaharaja Kennadyrajan u32 tid, status;
5389556dfa2SMaharaja Kennadyrajan int ret;
5399556dfa2SMaharaja Kennadyrajan char buf[64] = {0};
5409556dfa2SMaharaja Kennadyrajan
5419556dfa2SMaharaja Kennadyrajan ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
5429556dfa2SMaharaja Kennadyrajan user_buf, count);
5439556dfa2SMaharaja Kennadyrajan if (ret <= 0)
5449556dfa2SMaharaja Kennadyrajan return ret;
5459556dfa2SMaharaja Kennadyrajan
5469556dfa2SMaharaja Kennadyrajan ret = sscanf(buf, "%u %u", &tid, &status);
5479556dfa2SMaharaja Kennadyrajan if (ret != 2)
5489556dfa2SMaharaja Kennadyrajan return -EINVAL;
5499556dfa2SMaharaja Kennadyrajan
5509556dfa2SMaharaja Kennadyrajan /* Valid TID values are 0 through 15 */
5519556dfa2SMaharaja Kennadyrajan if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
5529556dfa2SMaharaja Kennadyrajan return -EINVAL;
5539556dfa2SMaharaja Kennadyrajan
5549556dfa2SMaharaja Kennadyrajan mutex_lock(&ar->conf_mutex);
5559556dfa2SMaharaja Kennadyrajan if (ar->state != ATH11K_STATE_ON ||
5569556dfa2SMaharaja Kennadyrajan arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
5579556dfa2SMaharaja Kennadyrajan ret = count;
5589556dfa2SMaharaja Kennadyrajan goto out;
5599556dfa2SMaharaja Kennadyrajan }
5609556dfa2SMaharaja Kennadyrajan
5619556dfa2SMaharaja Kennadyrajan ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
5629556dfa2SMaharaja Kennadyrajan tid, status);
5639556dfa2SMaharaja Kennadyrajan if (ret) {
5649556dfa2SMaharaja Kennadyrajan ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
5659556dfa2SMaharaja Kennadyrajan arsta->arvif->vdev_id, sta->addr, tid, status);
5669556dfa2SMaharaja Kennadyrajan }
5679556dfa2SMaharaja Kennadyrajan ret = count;
5689556dfa2SMaharaja Kennadyrajan out:
5699556dfa2SMaharaja Kennadyrajan mutex_unlock(&ar->conf_mutex);
5709556dfa2SMaharaja Kennadyrajan return ret;
5719556dfa2SMaharaja Kennadyrajan }
5729556dfa2SMaharaja Kennadyrajan
5739556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_addba_resp = {
5749556dfa2SMaharaja Kennadyrajan .write = ath11k_dbg_sta_write_addba_resp,
5759556dfa2SMaharaja Kennadyrajan .open = simple_open,
5769556dfa2SMaharaja Kennadyrajan .owner = THIS_MODULE,
5779556dfa2SMaharaja Kennadyrajan .llseek = default_llseek,
5789556dfa2SMaharaja Kennadyrajan };
5799556dfa2SMaharaja Kennadyrajan
ath11k_dbg_sta_write_addba(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)5809556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
5819556dfa2SMaharaja Kennadyrajan const char __user *user_buf,
5829556dfa2SMaharaja Kennadyrajan size_t count, loff_t *ppos)
5839556dfa2SMaharaja Kennadyrajan {
5849556dfa2SMaharaja Kennadyrajan struct ieee80211_sta *sta = file->private_data;
5859556dfa2SMaharaja Kennadyrajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5869556dfa2SMaharaja Kennadyrajan struct ath11k *ar = arsta->arvif->ar;
5879556dfa2SMaharaja Kennadyrajan u32 tid, buf_size;
5889556dfa2SMaharaja Kennadyrajan int ret;
5899556dfa2SMaharaja Kennadyrajan char buf[64] = {0};
5909556dfa2SMaharaja Kennadyrajan
5919556dfa2SMaharaja Kennadyrajan ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
5929556dfa2SMaharaja Kennadyrajan user_buf, count);
5939556dfa2SMaharaja Kennadyrajan if (ret <= 0)
5949556dfa2SMaharaja Kennadyrajan return ret;
5959556dfa2SMaharaja Kennadyrajan
5969556dfa2SMaharaja Kennadyrajan ret = sscanf(buf, "%u %u", &tid, &buf_size);
5979556dfa2SMaharaja Kennadyrajan if (ret != 2)
5989556dfa2SMaharaja Kennadyrajan return -EINVAL;
5999556dfa2SMaharaja Kennadyrajan
6009556dfa2SMaharaja Kennadyrajan /* Valid TID values are 0 through 15 */
6019556dfa2SMaharaja Kennadyrajan if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
6029556dfa2SMaharaja Kennadyrajan return -EINVAL;
6039556dfa2SMaharaja Kennadyrajan
6049556dfa2SMaharaja Kennadyrajan mutex_lock(&ar->conf_mutex);
6059556dfa2SMaharaja Kennadyrajan if (ar->state != ATH11K_STATE_ON ||
6069556dfa2SMaharaja Kennadyrajan arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
6079556dfa2SMaharaja Kennadyrajan ret = count;
6089556dfa2SMaharaja Kennadyrajan goto out;
6099556dfa2SMaharaja Kennadyrajan }
6109556dfa2SMaharaja Kennadyrajan
6119556dfa2SMaharaja Kennadyrajan ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
6129556dfa2SMaharaja Kennadyrajan tid, buf_size);
6139556dfa2SMaharaja Kennadyrajan if (ret) {
6149556dfa2SMaharaja Kennadyrajan ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
6159556dfa2SMaharaja Kennadyrajan arsta->arvif->vdev_id, sta->addr, tid, buf_size);
6169556dfa2SMaharaja Kennadyrajan }
6179556dfa2SMaharaja Kennadyrajan
6189556dfa2SMaharaja Kennadyrajan ret = count;
6199556dfa2SMaharaja Kennadyrajan out:
6209556dfa2SMaharaja Kennadyrajan mutex_unlock(&ar->conf_mutex);
6219556dfa2SMaharaja Kennadyrajan return ret;
6229556dfa2SMaharaja Kennadyrajan }
6239556dfa2SMaharaja Kennadyrajan
6249556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_addba = {
6259556dfa2SMaharaja Kennadyrajan .write = ath11k_dbg_sta_write_addba,
6269556dfa2SMaharaja Kennadyrajan .open = simple_open,
6279556dfa2SMaharaja Kennadyrajan .owner = THIS_MODULE,
6289556dfa2SMaharaja Kennadyrajan .llseek = default_llseek,
6299556dfa2SMaharaja Kennadyrajan };
6309556dfa2SMaharaja Kennadyrajan
ath11k_dbg_sta_read_aggr_mode(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)6319556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
6329556dfa2SMaharaja Kennadyrajan char __user *user_buf,
6339556dfa2SMaharaja Kennadyrajan size_t count, loff_t *ppos)
6349556dfa2SMaharaja Kennadyrajan {
6359556dfa2SMaharaja Kennadyrajan struct ieee80211_sta *sta = file->private_data;
6369556dfa2SMaharaja Kennadyrajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
6379556dfa2SMaharaja Kennadyrajan struct ath11k *ar = arsta->arvif->ar;
6389556dfa2SMaharaja Kennadyrajan char buf[64];
6399556dfa2SMaharaja Kennadyrajan int len = 0;
6409556dfa2SMaharaja Kennadyrajan
6419556dfa2SMaharaja Kennadyrajan mutex_lock(&ar->conf_mutex);
6429556dfa2SMaharaja Kennadyrajan len = scnprintf(buf, sizeof(buf) - len,
6439556dfa2SMaharaja Kennadyrajan "aggregation mode: %s\n\n%s\n%s\n",
6449556dfa2SMaharaja Kennadyrajan (arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
6459556dfa2SMaharaja Kennadyrajan "auto" : "manual", "auto = 0", "manual = 1");
6469556dfa2SMaharaja Kennadyrajan mutex_unlock(&ar->conf_mutex);
6479556dfa2SMaharaja Kennadyrajan
6489556dfa2SMaharaja Kennadyrajan return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6499556dfa2SMaharaja Kennadyrajan }
6509556dfa2SMaharaja Kennadyrajan
ath11k_dbg_sta_write_aggr_mode(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)6519556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
6529556dfa2SMaharaja Kennadyrajan const char __user *user_buf,
6539556dfa2SMaharaja Kennadyrajan size_t count, loff_t *ppos)
6549556dfa2SMaharaja Kennadyrajan {
6559556dfa2SMaharaja Kennadyrajan struct ieee80211_sta *sta = file->private_data;
6569556dfa2SMaharaja Kennadyrajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
6579556dfa2SMaharaja Kennadyrajan struct ath11k *ar = arsta->arvif->ar;
6589556dfa2SMaharaja Kennadyrajan u32 aggr_mode;
6599556dfa2SMaharaja Kennadyrajan int ret;
6609556dfa2SMaharaja Kennadyrajan
6619556dfa2SMaharaja Kennadyrajan if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
6629556dfa2SMaharaja Kennadyrajan return -EINVAL;
6639556dfa2SMaharaja Kennadyrajan
6649556dfa2SMaharaja Kennadyrajan if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
6659556dfa2SMaharaja Kennadyrajan return -EINVAL;
6669556dfa2SMaharaja Kennadyrajan
6679556dfa2SMaharaja Kennadyrajan mutex_lock(&ar->conf_mutex);
6689556dfa2SMaharaja Kennadyrajan if (ar->state != ATH11K_STATE_ON ||
6699556dfa2SMaharaja Kennadyrajan aggr_mode == arsta->aggr_mode) {
6709556dfa2SMaharaja Kennadyrajan ret = count;
6719556dfa2SMaharaja Kennadyrajan goto out;
6729556dfa2SMaharaja Kennadyrajan }
6739556dfa2SMaharaja Kennadyrajan
6749556dfa2SMaharaja Kennadyrajan ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
6759556dfa2SMaharaja Kennadyrajan if (ret) {
6769556dfa2SMaharaja Kennadyrajan ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
6779556dfa2SMaharaja Kennadyrajan ret);
6789556dfa2SMaharaja Kennadyrajan goto out;
6799556dfa2SMaharaja Kennadyrajan }
6809556dfa2SMaharaja Kennadyrajan
6819556dfa2SMaharaja Kennadyrajan arsta->aggr_mode = aggr_mode;
6829556dfa2SMaharaja Kennadyrajan out:
6839556dfa2SMaharaja Kennadyrajan mutex_unlock(&ar->conf_mutex);
6849556dfa2SMaharaja Kennadyrajan return ret;
6859556dfa2SMaharaja Kennadyrajan }
6869556dfa2SMaharaja Kennadyrajan
6879556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_aggr_mode = {
6889556dfa2SMaharaja Kennadyrajan .read = ath11k_dbg_sta_read_aggr_mode,
6899556dfa2SMaharaja Kennadyrajan .write = ath11k_dbg_sta_write_aggr_mode,
6909556dfa2SMaharaja Kennadyrajan .open = simple_open,
6919556dfa2SMaharaja Kennadyrajan .owner = THIS_MODULE,
6929556dfa2SMaharaja Kennadyrajan .llseek = default_llseek,
6939556dfa2SMaharaja Kennadyrajan };
6949556dfa2SMaharaja Kennadyrajan
695559ef68fSAshok Raj Nagarajan static ssize_t
ath11k_write_htt_peer_stats_reset(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)696559ef68fSAshok Raj Nagarajan ath11k_write_htt_peer_stats_reset(struct file *file,
697559ef68fSAshok Raj Nagarajan const char __user *user_buf,
698559ef68fSAshok Raj Nagarajan size_t count, loff_t *ppos)
699559ef68fSAshok Raj Nagarajan {
700559ef68fSAshok Raj Nagarajan struct ieee80211_sta *sta = file->private_data;
701559ef68fSAshok Raj Nagarajan struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
702559ef68fSAshok Raj Nagarajan struct ath11k *ar = arsta->arvif->ar;
703559ef68fSAshok Raj Nagarajan struct htt_ext_stats_cfg_params cfg_params = { 0 };
704559ef68fSAshok Raj Nagarajan int ret;
705559ef68fSAshok Raj Nagarajan u8 type;
706559ef68fSAshok Raj Nagarajan
707559ef68fSAshok Raj Nagarajan ret = kstrtou8_from_user(user_buf, count, 0, &type);
708559ef68fSAshok Raj Nagarajan if (ret)
709559ef68fSAshok Raj Nagarajan return ret;
710559ef68fSAshok Raj Nagarajan
711559ef68fSAshok Raj Nagarajan if (!type)
712559ef68fSAshok Raj Nagarajan return ret;
713559ef68fSAshok Raj Nagarajan
714559ef68fSAshok Raj Nagarajan mutex_lock(&ar->conf_mutex);
715559ef68fSAshok Raj Nagarajan cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
716559ef68fSAshok Raj Nagarajan cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
717559ef68fSAshok Raj Nagarajan HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
718559ef68fSAshok Raj Nagarajan
719559ef68fSAshok Raj Nagarajan cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
720559ef68fSAshok Raj Nagarajan
721559ef68fSAshok Raj Nagarajan cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
722559ef68fSAshok Raj Nagarajan cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
723559ef68fSAshok Raj Nagarajan cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
724559ef68fSAshok Raj Nagarajan cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
725559ef68fSAshok Raj Nagarajan
726559ef68fSAshok Raj Nagarajan cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
727559ef68fSAshok Raj Nagarajan cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
728559ef68fSAshok Raj Nagarajan
729559ef68fSAshok Raj Nagarajan cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
730559ef68fSAshok Raj Nagarajan
731559ef68fSAshok Raj Nagarajan ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
732559ef68fSAshok Raj Nagarajan ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
733559ef68fSAshok Raj Nagarajan &cfg_params,
734559ef68fSAshok Raj Nagarajan 0ULL);
735559ef68fSAshok Raj Nagarajan if (ret) {
736559ef68fSAshok Raj Nagarajan ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
737559ef68fSAshok Raj Nagarajan mutex_unlock(&ar->conf_mutex);
738559ef68fSAshok Raj Nagarajan return ret;
739559ef68fSAshok Raj Nagarajan }
740559ef68fSAshok Raj Nagarajan
741559ef68fSAshok Raj Nagarajan mutex_unlock(&ar->conf_mutex);
742559ef68fSAshok Raj Nagarajan
743559ef68fSAshok Raj Nagarajan ret = count;
744559ef68fSAshok Raj Nagarajan
745559ef68fSAshok Raj Nagarajan return ret;
746559ef68fSAshok Raj Nagarajan }
747559ef68fSAshok Raj Nagarajan
748559ef68fSAshok Raj Nagarajan static const struct file_operations fops_htt_peer_stats_reset = {
749559ef68fSAshok Raj Nagarajan .write = ath11k_write_htt_peer_stats_reset,
750559ef68fSAshok Raj Nagarajan .open = simple_open,
751559ef68fSAshok Raj Nagarajan .owner = THIS_MODULE,
752559ef68fSAshok Raj Nagarajan .llseek = default_llseek,
753559ef68fSAshok Raj Nagarajan };
754559ef68fSAshok Raj Nagarajan
ath11k_dbg_sta_read_peer_ps_state(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)755710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
756710a95f9SVenkateswara Naralasetty char __user *user_buf,
757710a95f9SVenkateswara Naralasetty size_t count, loff_t *ppos)
758710a95f9SVenkateswara Naralasetty {
759710a95f9SVenkateswara Naralasetty struct ieee80211_sta *sta = file->private_data;
760710a95f9SVenkateswara Naralasetty struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
761710a95f9SVenkateswara Naralasetty struct ath11k *ar = arsta->arvif->ar;
762710a95f9SVenkateswara Naralasetty char buf[20];
763710a95f9SVenkateswara Naralasetty int len;
764710a95f9SVenkateswara Naralasetty
765710a95f9SVenkateswara Naralasetty spin_lock_bh(&ar->data_lock);
766710a95f9SVenkateswara Naralasetty
767710a95f9SVenkateswara Naralasetty len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
768710a95f9SVenkateswara Naralasetty
769710a95f9SVenkateswara Naralasetty spin_unlock_bh(&ar->data_lock);
770710a95f9SVenkateswara Naralasetty
771710a95f9SVenkateswara Naralasetty return simple_read_from_buffer(user_buf, count, ppos, buf, len);
772710a95f9SVenkateswara Naralasetty }
773710a95f9SVenkateswara Naralasetty
774710a95f9SVenkateswara Naralasetty static const struct file_operations fops_peer_ps_state = {
775710a95f9SVenkateswara Naralasetty .open = simple_open,
776710a95f9SVenkateswara Naralasetty .read = ath11k_dbg_sta_read_peer_ps_state,
777710a95f9SVenkateswara Naralasetty .owner = THIS_MODULE,
778710a95f9SVenkateswara Naralasetty .llseek = default_llseek,
779710a95f9SVenkateswara Naralasetty };
780710a95f9SVenkateswara Naralasetty
ath11k_dbg_sta_read_current_ps_duration(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)781710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
782710a95f9SVenkateswara Naralasetty char __user *user_buf,
783710a95f9SVenkateswara Naralasetty size_t count,
784710a95f9SVenkateswara Naralasetty loff_t *ppos)
785710a95f9SVenkateswara Naralasetty {
786710a95f9SVenkateswara Naralasetty struct ieee80211_sta *sta = file->private_data;
787710a95f9SVenkateswara Naralasetty struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
788710a95f9SVenkateswara Naralasetty struct ath11k *ar = arsta->arvif->ar;
789710a95f9SVenkateswara Naralasetty u64 time_since_station_in_power_save;
790710a95f9SVenkateswara Naralasetty char buf[20];
791710a95f9SVenkateswara Naralasetty int len;
792710a95f9SVenkateswara Naralasetty
793710a95f9SVenkateswara Naralasetty spin_lock_bh(&ar->data_lock);
794710a95f9SVenkateswara Naralasetty
795710a95f9SVenkateswara Naralasetty if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
796710a95f9SVenkateswara Naralasetty arsta->peer_current_ps_valid)
797710a95f9SVenkateswara Naralasetty time_since_station_in_power_save = jiffies_to_msecs(jiffies
798710a95f9SVenkateswara Naralasetty - arsta->ps_start_jiffies);
799710a95f9SVenkateswara Naralasetty else
800710a95f9SVenkateswara Naralasetty time_since_station_in_power_save = 0;
801710a95f9SVenkateswara Naralasetty
802710a95f9SVenkateswara Naralasetty len = scnprintf(buf, sizeof(buf), "%llu\n",
803710a95f9SVenkateswara Naralasetty time_since_station_in_power_save);
804710a95f9SVenkateswara Naralasetty spin_unlock_bh(&ar->data_lock);
805710a95f9SVenkateswara Naralasetty
806710a95f9SVenkateswara Naralasetty return simple_read_from_buffer(user_buf, count, ppos, buf, len);
807710a95f9SVenkateswara Naralasetty }
808710a95f9SVenkateswara Naralasetty
809710a95f9SVenkateswara Naralasetty static const struct file_operations fops_current_ps_duration = {
810710a95f9SVenkateswara Naralasetty .open = simple_open,
811710a95f9SVenkateswara Naralasetty .read = ath11k_dbg_sta_read_current_ps_duration,
812710a95f9SVenkateswara Naralasetty .owner = THIS_MODULE,
813710a95f9SVenkateswara Naralasetty .llseek = default_llseek,
814710a95f9SVenkateswara Naralasetty };
815710a95f9SVenkateswara Naralasetty
ath11k_dbg_sta_read_total_ps_duration(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)816710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
817710a95f9SVenkateswara Naralasetty char __user *user_buf,
818710a95f9SVenkateswara Naralasetty size_t count, loff_t *ppos)
819710a95f9SVenkateswara Naralasetty {
820710a95f9SVenkateswara Naralasetty struct ieee80211_sta *sta = file->private_data;
821710a95f9SVenkateswara Naralasetty struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
822710a95f9SVenkateswara Naralasetty struct ath11k *ar = arsta->arvif->ar;
823710a95f9SVenkateswara Naralasetty char buf[20];
824710a95f9SVenkateswara Naralasetty u64 power_save_duration;
825710a95f9SVenkateswara Naralasetty int len;
826710a95f9SVenkateswara Naralasetty
827710a95f9SVenkateswara Naralasetty spin_lock_bh(&ar->data_lock);
828710a95f9SVenkateswara Naralasetty
829710a95f9SVenkateswara Naralasetty if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
830710a95f9SVenkateswara Naralasetty arsta->peer_current_ps_valid)
831710a95f9SVenkateswara Naralasetty power_save_duration = jiffies_to_msecs(jiffies
832710a95f9SVenkateswara Naralasetty - arsta->ps_start_jiffies)
833710a95f9SVenkateswara Naralasetty + arsta->ps_total_duration;
834710a95f9SVenkateswara Naralasetty else
835710a95f9SVenkateswara Naralasetty power_save_duration = arsta->ps_total_duration;
836710a95f9SVenkateswara Naralasetty
837710a95f9SVenkateswara Naralasetty len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
838710a95f9SVenkateswara Naralasetty
839710a95f9SVenkateswara Naralasetty spin_unlock_bh(&ar->data_lock);
840710a95f9SVenkateswara Naralasetty
841710a95f9SVenkateswara Naralasetty return simple_read_from_buffer(user_buf, count, ppos, buf, len);
842710a95f9SVenkateswara Naralasetty }
843710a95f9SVenkateswara Naralasetty
844710a95f9SVenkateswara Naralasetty static const struct file_operations fops_total_ps_duration = {
845710a95f9SVenkateswara Naralasetty .open = simple_open,
846710a95f9SVenkateswara Naralasetty .read = ath11k_dbg_sta_read_total_ps_duration,
847710a95f9SVenkateswara Naralasetty .owner = THIS_MODULE,
848710a95f9SVenkateswara Naralasetty .llseek = default_llseek,
849710a95f9SVenkateswara Naralasetty };
850710a95f9SVenkateswara Naralasetty
ath11k_debugfs_sta_op_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct dentry * dir)851568f0603SKalle Valo void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
852d5c65159SKalle Valo struct ieee80211_sta *sta, struct dentry *dir)
853d5c65159SKalle Valo {
854d5c65159SKalle Valo struct ath11k *ar = hw->priv;
855d5c65159SKalle Valo
856cb4e57dbSKalle Valo if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
857d5c65159SKalle Valo debugfs_create_file("tx_stats", 0400, dir, sta,
858d5c65159SKalle Valo &fops_tx_stats);
859cb4e57dbSKalle Valo if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
860d5c65159SKalle Valo debugfs_create_file("rx_stats", 0400, dir, sta,
861d5c65159SKalle Valo &fops_rx_stats);
862d5c65159SKalle Valo
863d5c65159SKalle Valo debugfs_create_file("htt_peer_stats", 0400, dir, sta,
864d5c65159SKalle Valo &fops_htt_peer_stats);
865d5c65159SKalle Valo
866d5c65159SKalle Valo debugfs_create_file("peer_pktlog", 0644, dir, sta,
867d5c65159SKalle Valo &fops_peer_pktlog);
8689556dfa2SMaharaja Kennadyrajan
8699556dfa2SMaharaja Kennadyrajan debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
8709556dfa2SMaharaja Kennadyrajan debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
8719556dfa2SMaharaja Kennadyrajan debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
8729556dfa2SMaharaja Kennadyrajan debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
873559ef68fSAshok Raj Nagarajan
874559ef68fSAshok Raj Nagarajan if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
875559ef68fSAshok Raj Nagarajan ar->ab->wmi_ab.svc_map))
876559ef68fSAshok Raj Nagarajan debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
877559ef68fSAshok Raj Nagarajan &fops_htt_peer_stats_reset);
878710a95f9SVenkateswara Naralasetty
879710a95f9SVenkateswara Naralasetty debugfs_create_file("peer_ps_state", 0400, dir, sta,
880710a95f9SVenkateswara Naralasetty &fops_peer_ps_state);
881710a95f9SVenkateswara Naralasetty
882710a95f9SVenkateswara Naralasetty if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
883710a95f9SVenkateswara Naralasetty ar->ab->wmi_ab.svc_map)) {
884710a95f9SVenkateswara Naralasetty debugfs_create_file("current_ps_duration", 0440, dir, sta,
885710a95f9SVenkateswara Naralasetty &fops_current_ps_duration);
886710a95f9SVenkateswara Naralasetty debugfs_create_file("total_ps_duration", 0440, dir, sta,
887710a95f9SVenkateswara Naralasetty &fops_total_ps_duration);
888710a95f9SVenkateswara Naralasetty }
889d5c65159SKalle Valo }
890