GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / net / wireless / ath / ath11k / debugfs_sta.c
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/vmalloc.h>
7
8 #include "debugfs_sta.h"
9 #include "core.h"
10 #include "peer.h"
11 #include "debug.h"
12 #include "dp_tx.h"
13 #include "debugfs_htt_stats.h"
14
15 void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
16                                      struct ath11k_per_peer_tx_stats *peer_stats,
17                                      u8 legacy_rate_idx)
18 {
19         struct rate_info *txrate = &arsta->txrate;
20         struct ath11k_htt_tx_stats *tx_stats;
21         int gi, mcs, bw, nss;
22
23         if (!arsta->tx_stats)
24                 return;
25
26         tx_stats = arsta->tx_stats;
27         gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
28         mcs = txrate->mcs;
29         bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
30         nss = txrate->nss - 1;
31
32 #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
33
34         if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
35                 STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
36                 STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
37                 STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
38                 STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
39                 STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
40                 STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
41         } else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
42                 STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
43                 STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
44                 STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
45                 STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
46                 STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
47                 STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
48         } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
49                 STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
50                 STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
51                 STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
52                 STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
53                 STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
54                 STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
55         } else {
56                 mcs = legacy_rate_idx;
57
58                 STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
59                 STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
60                 STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
61                 STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
62                 STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
63                 STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
64         }
65
66         if (peer_stats->is_ampdu) {
67                 tx_stats->ba_fails += peer_stats->ba_fails;
68
69                 if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
70                         STATS_OP_FMT(AMPDU).he[0][mcs] +=
71                         peer_stats->succ_bytes + peer_stats->retry_bytes;
72                         STATS_OP_FMT(AMPDU).he[1][mcs] +=
73                         peer_stats->succ_pkts + peer_stats->retry_pkts;
74                 } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
75                         STATS_OP_FMT(AMPDU).ht[0][mcs] +=
76                         peer_stats->succ_bytes + peer_stats->retry_bytes;
77                         STATS_OP_FMT(AMPDU).ht[1][mcs] +=
78                         peer_stats->succ_pkts + peer_stats->retry_pkts;
79                 } else {
80                         STATS_OP_FMT(AMPDU).vht[0][mcs] +=
81                         peer_stats->succ_bytes + peer_stats->retry_bytes;
82                         STATS_OP_FMT(AMPDU).vht[1][mcs] +=
83                         peer_stats->succ_pkts + peer_stats->retry_pkts;
84                 }
85                 STATS_OP_FMT(AMPDU).bw[0][bw] +=
86                         peer_stats->succ_bytes + peer_stats->retry_bytes;
87                 STATS_OP_FMT(AMPDU).nss[0][nss] +=
88                         peer_stats->succ_bytes + peer_stats->retry_bytes;
89                 STATS_OP_FMT(AMPDU).gi[0][gi] +=
90                         peer_stats->succ_bytes + peer_stats->retry_bytes;
91                 STATS_OP_FMT(AMPDU).bw[1][bw] +=
92                         peer_stats->succ_pkts + peer_stats->retry_pkts;
93                 STATS_OP_FMT(AMPDU).nss[1][nss] +=
94                         peer_stats->succ_pkts + peer_stats->retry_pkts;
95                 STATS_OP_FMT(AMPDU).gi[1][gi] +=
96                         peer_stats->succ_pkts + peer_stats->retry_pkts;
97         } else {
98                 tx_stats->ack_fails += peer_stats->ba_fails;
99         }
100
101         STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
102         STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
103         STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
104
105         STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
106         STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
107         STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
108
109         STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
110         STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
111         STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
112
113         STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
114         STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
115         STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
116
117         STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
118         STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
119         STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
120
121         STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
122         STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
123         STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
124
125         tx_stats->tx_duration += peer_stats->duration;
126 }
127
128 void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
129                                        struct hal_tx_status *ts)
130 {
131         ath11k_dp_tx_update_txcompl(ar, ts);
132 }
133
134 static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
135                                             char __user *user_buf,
136                                             size_t count, loff_t *ppos)
137 {
138         struct ieee80211_sta *sta = file->private_data;
139         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
140         struct ath11k *ar = arsta->arvif->ar;
141         struct ath11k_htt_data_stats *stats;
142         static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
143                                                               "retry", "ampdu"};
144         static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
145         int len = 0, i, j, k, retval = 0;
146         const int size = 2 * 4096;
147         char *buf;
148
149         if (!arsta->tx_stats)
150                 return -ENOENT;
151
152         buf = kzalloc(size, GFP_KERNEL);
153         if (!buf)
154                 return -ENOMEM;
155
156         mutex_lock(&ar->conf_mutex);
157
158         spin_lock_bh(&ar->data_lock);
159         for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
160                 for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
161                         stats = &arsta->tx_stats->stats[k];
162                         len += scnprintf(buf + len, size - len, "%s_%s\n",
163                                          str_name[k],
164                                          str[j]);
165                         len += scnprintf(buf + len, size - len,
166                                          " HE MCS %s\n",
167                                          str[j]);
168                         for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
169                                 len += scnprintf(buf + len, size - len,
170                                                  "  %llu ",
171                                                  stats->he[j][i]);
172                         len += scnprintf(buf + len, size - len, "\n");
173                         len += scnprintf(buf + len, size - len,
174                                          " VHT MCS %s\n",
175                                          str[j]);
176                         for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
177                                 len += scnprintf(buf + len, size - len,
178                                                  "  %llu ",
179                                                  stats->vht[j][i]);
180                         len += scnprintf(buf + len, size - len, "\n");
181                         len += scnprintf(buf + len, size - len, " HT MCS %s\n",
182                                          str[j]);
183                         for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
184                                 len += scnprintf(buf + len, size - len,
185                                                  "  %llu ", stats->ht[j][i]);
186                         len += scnprintf(buf + len, size - len, "\n");
187                         len += scnprintf(buf + len, size - len,
188                                         " BW %s (20,40,80,160 MHz)\n", str[j]);
189                         len += scnprintf(buf + len, size - len,
190                                          "  %llu %llu %llu %llu\n",
191                                          stats->bw[j][0], stats->bw[j][1],
192                                          stats->bw[j][2], stats->bw[j][3]);
193                         len += scnprintf(buf + len, size - len,
194                                          " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
195                         len += scnprintf(buf + len, size - len,
196                                          "  %llu %llu %llu %llu\n",
197                                          stats->nss[j][0], stats->nss[j][1],
198                                          stats->nss[j][2], stats->nss[j][3]);
199                         len += scnprintf(buf + len, size - len,
200                                          " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
201                                          str[j]);
202                         len += scnprintf(buf + len, size - len,
203                                          "  %llu %llu %llu %llu\n",
204                                          stats->gi[j][0], stats->gi[j][1],
205                                          stats->gi[j][2], stats->gi[j][3]);
206                         len += scnprintf(buf + len, size - len,
207                                          " legacy rate %s (1,2 ... Mbps)\n  ",
208                                          str[j]);
209                         for (i = 0; i < ATH11K_LEGACY_NUM; i++)
210                                 len += scnprintf(buf + len, size - len, "%llu ",
211                                                  stats->legacy[j][i]);
212                         len += scnprintf(buf + len, size - len, "\n");
213                 }
214         }
215
216         len += scnprintf(buf + len, size - len,
217                          "\nTX duration\n %llu usecs\n",
218                          arsta->tx_stats->tx_duration);
219         len += scnprintf(buf + len, size - len,
220                         "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
221         len += scnprintf(buf + len, size - len,
222                         "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
223         spin_unlock_bh(&ar->data_lock);
224
225         if (len > size)
226                 len = size;
227         retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
228         kfree(buf);
229
230         mutex_unlock(&ar->conf_mutex);
231         return retval;
232 }
233
234 static const struct file_operations fops_tx_stats = {
235         .read = ath11k_dbg_sta_dump_tx_stats,
236         .open = simple_open,
237         .owner = THIS_MODULE,
238         .llseek = default_llseek,
239 };
240
241 static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
242                                             char __user *user_buf,
243                                             size_t count, loff_t *ppos)
244 {
245         struct ieee80211_sta *sta = file->private_data;
246         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
247         struct ath11k *ar = arsta->arvif->ar;
248         struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
249         int len = 0, i, retval = 0;
250         const int size = 4096;
251         char *buf;
252
253         if (!rx_stats)
254                 return -ENOENT;
255
256         buf = kzalloc(size, GFP_KERNEL);
257         if (!buf)
258                 return -ENOMEM;
259
260         mutex_lock(&ar->conf_mutex);
261         spin_lock_bh(&ar->ab->base_lock);
262
263         len += scnprintf(buf + len, size - len, "RX peer stats:\n");
264         len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
265                          rx_stats->num_msdu);
266         len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
267                          rx_stats->tcp_msdu_count);
268         len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
269                          rx_stats->udp_msdu_count);
270         len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
271                          rx_stats->ampdu_msdu_count);
272         len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
273                          rx_stats->non_ampdu_msdu_count);
274         len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
275                          rx_stats->stbc_count);
276         len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
277                          rx_stats->beamformed_count);
278         len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
279                          rx_stats->num_mpdu_fcs_ok);
280         len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
281                          rx_stats->num_mpdu_fcs_err);
282         len += scnprintf(buf + len, size - len,
283                          "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
284                          rx_stats->gi_count[0], rx_stats->gi_count[1],
285                          rx_stats->gi_count[2], rx_stats->gi_count[3]);
286         len += scnprintf(buf + len, size - len,
287                          "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
288                          rx_stats->bw_count[0], rx_stats->bw_count[1],
289                          rx_stats->bw_count[2], rx_stats->bw_count[3]);
290         len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
291                          rx_stats->coding_count[0], rx_stats->coding_count[1]);
292         len += scnprintf(buf + len, size - len,
293                          "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
294                          rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
295                          rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
296                          rx_stats->pream_cnt[4]);
297         len += scnprintf(buf + len, size - len,
298                          "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
299                          rx_stats->reception_type[0], rx_stats->reception_type[1],
300                          rx_stats->reception_type[2], rx_stats->reception_type[3]);
301         len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
302         for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
303                 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
304         len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
305         for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
306                 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
307         len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
308         for (i = 0; i < HAL_RX_MAX_NSS; i++)
309                 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
310         len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
311                          rx_stats->rx_duration);
312         len += scnprintf(buf + len, size - len,
313                          "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
314                          rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
315                          rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
316                          rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
317                          rx_stats->ru_alloc_cnt[5]);
318
319         len += scnprintf(buf + len, size - len, "\n");
320
321         spin_unlock_bh(&ar->ab->base_lock);
322
323         if (len > size)
324                 len = size;
325         retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
326         kfree(buf);
327
328         mutex_unlock(&ar->conf_mutex);
329         return retval;
330 }
331
332 static const struct file_operations fops_rx_stats = {
333         .read = ath11k_dbg_sta_dump_rx_stats,
334         .open = simple_open,
335         .owner = THIS_MODULE,
336         .llseek = default_llseek,
337 };
338
339 static int
340 ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
341 {
342         struct ieee80211_sta *sta = inode->i_private;
343         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
344         struct ath11k *ar = arsta->arvif->ar;
345         struct debug_htt_stats_req *stats_req;
346         int type = ar->debug.htt_stats.type;
347         int ret;
348
349         if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
350              type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
351             type == ATH11K_DBG_HTT_EXT_STATS_RESET)
352                 return -EPERM;
353
354         stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
355         if (!stats_req)
356                 return -ENOMEM;
357
358         mutex_lock(&ar->conf_mutex);
359         ar->debug.htt_stats.stats_req = stats_req;
360         stats_req->type = type;
361         memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
362         ret = ath11k_debugfs_htt_stats_req(ar);
363         mutex_unlock(&ar->conf_mutex);
364         if (ret < 0)
365                 goto out;
366
367         file->private_data = stats_req;
368         return 0;
369 out:
370         vfree(stats_req);
371         ar->debug.htt_stats.stats_req = NULL;
372         return ret;
373 }
374
375 static int
376 ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
377 {
378         struct ieee80211_sta *sta = inode->i_private;
379         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
380         struct ath11k *ar = arsta->arvif->ar;
381
382         mutex_lock(&ar->conf_mutex);
383         vfree(file->private_data);
384         ar->debug.htt_stats.stats_req = NULL;
385         mutex_unlock(&ar->conf_mutex);
386
387         return 0;
388 }
389
390 static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
391                                                   char __user *user_buf,
392                                                   size_t count, loff_t *ppos)
393 {
394         struct debug_htt_stats_req *stats_req = file->private_data;
395         char *buf;
396         u32 length = 0;
397
398         buf = stats_req->buf;
399         length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
400         return simple_read_from_buffer(user_buf, count, ppos, buf, length);
401 }
402
403 static const struct file_operations fops_htt_peer_stats = {
404         .open = ath11k_dbg_sta_open_htt_peer_stats,
405         .release = ath11k_dbg_sta_release_htt_peer_stats,
406         .read = ath11k_dbg_sta_read_htt_peer_stats,
407         .owner = THIS_MODULE,
408         .llseek = default_llseek,
409 };
410
411 static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
412                                                 const char __user *buf,
413                                                 size_t count, loff_t *ppos)
414 {
415         struct ieee80211_sta *sta = file->private_data;
416         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
417         struct ath11k *ar = arsta->arvif->ar;
418         int ret, enable;
419
420         mutex_lock(&ar->conf_mutex);
421
422         if (ar->state != ATH11K_STATE_ON) {
423                 ret = -ENETDOWN;
424                 goto out;
425         }
426
427         ret = kstrtoint_from_user(buf, count, 0, &enable);
428         if (ret)
429                 goto out;
430
431         ar->debug.pktlog_peer_valid = enable;
432         memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
433
434         /* Send peer based pktlog enable/disable */
435         ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
436         if (ret) {
437                 ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
438                             sta->addr, ret);
439                 goto out;
440         }
441
442         ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
443                    enable);
444         ret = count;
445
446 out:
447         mutex_unlock(&ar->conf_mutex);
448         return ret;
449 }
450
451 static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
452                                                char __user *ubuf,
453                                                size_t count, loff_t *ppos)
454 {
455         struct ieee80211_sta *sta = file->private_data;
456         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
457         struct ath11k *ar = arsta->arvif->ar;
458         char buf[32] = {0};
459         int len;
460
461         mutex_lock(&ar->conf_mutex);
462         len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
463                         ar->debug.pktlog_peer_valid,
464                         ar->debug.pktlog_peer_addr);
465         mutex_unlock(&ar->conf_mutex);
466
467         return simple_read_from_buffer(ubuf, count, ppos, buf, len);
468 }
469
470 static const struct file_operations fops_peer_pktlog = {
471         .write = ath11k_dbg_sta_write_peer_pktlog,
472         .read = ath11k_dbg_sta_read_peer_pktlog,
473         .open = simple_open,
474         .owner = THIS_MODULE,
475         .llseek = default_llseek,
476 };
477
478 static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
479                                           const char __user *user_buf,
480                                           size_t count, loff_t *ppos)
481 {
482         struct ieee80211_sta *sta = file->private_data;
483         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
484         struct ath11k *ar = arsta->arvif->ar;
485         u32 tid, initiator, reason;
486         int ret;
487         char buf[64] = {0};
488
489         ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
490                                      user_buf, count);
491         if (ret <= 0)
492                 return ret;
493
494         ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
495         if (ret != 3)
496                 return -EINVAL;
497
498         /* Valid TID values are 0 through 15 */
499         if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
500                 return -EINVAL;
501
502         mutex_lock(&ar->conf_mutex);
503         if (ar->state != ATH11K_STATE_ON ||
504             arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
505                 ret = count;
506                 goto out;
507         }
508
509         ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
510                                     tid, initiator, reason);
511         if (ret) {
512                 ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
513                             arsta->arvif->vdev_id, sta->addr, tid, initiator,
514                             reason);
515         }
516         ret = count;
517 out:
518         mutex_unlock(&ar->conf_mutex);
519         return ret;
520 }
521
522 static const struct file_operations fops_delba = {
523         .write = ath11k_dbg_sta_write_delba,
524         .open = simple_open,
525         .owner = THIS_MODULE,
526         .llseek = default_llseek,
527 };
528
529 static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
530                                                const char __user *user_buf,
531                                                size_t count, loff_t *ppos)
532 {
533         struct ieee80211_sta *sta = file->private_data;
534         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
535         struct ath11k *ar = arsta->arvif->ar;
536         u32 tid, status;
537         int ret;
538         char buf[64] = {0};
539
540         ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
541                                      user_buf, count);
542         if (ret <= 0)
543                 return ret;
544
545         ret = sscanf(buf, "%u %u", &tid, &status);
546         if (ret != 2)
547                 return -EINVAL;
548
549         /* Valid TID values are 0 through 15 */
550         if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
551                 return -EINVAL;
552
553         mutex_lock(&ar->conf_mutex);
554         if (ar->state != ATH11K_STATE_ON ||
555             arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
556                 ret = count;
557                 goto out;
558         }
559
560         ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
561                                         tid, status);
562         if (ret) {
563                 ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
564                             arsta->arvif->vdev_id, sta->addr, tid, status);
565         }
566         ret = count;
567 out:
568         mutex_unlock(&ar->conf_mutex);
569         return ret;
570 }
571
572 static const struct file_operations fops_addba_resp = {
573         .write = ath11k_dbg_sta_write_addba_resp,
574         .open = simple_open,
575         .owner = THIS_MODULE,
576         .llseek = default_llseek,
577 };
578
579 static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
580                                           const char __user *user_buf,
581                                           size_t count, loff_t *ppos)
582 {
583         struct ieee80211_sta *sta = file->private_data;
584         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
585         struct ath11k *ar = arsta->arvif->ar;
586         u32 tid, buf_size;
587         int ret;
588         char buf[64] = {0};
589
590         ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
591                                      user_buf, count);
592         if (ret <= 0)
593                 return ret;
594
595         ret = sscanf(buf, "%u %u", &tid, &buf_size);
596         if (ret != 2)
597                 return -EINVAL;
598
599         /* Valid TID values are 0 through 15 */
600         if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
601                 return -EINVAL;
602
603         mutex_lock(&ar->conf_mutex);
604         if (ar->state != ATH11K_STATE_ON ||
605             arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
606                 ret = count;
607                 goto out;
608         }
609
610         ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
611                                     tid, buf_size);
612         if (ret) {
613                 ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
614                             arsta->arvif->vdev_id, sta->addr, tid, buf_size);
615         }
616
617         ret = count;
618 out:
619         mutex_unlock(&ar->conf_mutex);
620         return ret;
621 }
622
623 static const struct file_operations fops_addba = {
624         .write = ath11k_dbg_sta_write_addba,
625         .open = simple_open,
626         .owner = THIS_MODULE,
627         .llseek = default_llseek,
628 };
629
630 static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
631                                              char __user *user_buf,
632                                              size_t count, loff_t *ppos)
633 {
634         struct ieee80211_sta *sta = file->private_data;
635         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
636         struct ath11k *ar = arsta->arvif->ar;
637         char buf[64];
638         int len = 0;
639
640         mutex_lock(&ar->conf_mutex);
641         len = scnprintf(buf, sizeof(buf) - len,
642                         "aggregation mode: %s\n\n%s\n%s\n",
643                         (arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
644                         "auto" : "manual", "auto = 0", "manual = 1");
645         mutex_unlock(&ar->conf_mutex);
646
647         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
648 }
649
650 static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
651                                               const char __user *user_buf,
652                                               size_t count, loff_t *ppos)
653 {
654         struct ieee80211_sta *sta = file->private_data;
655         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
656         struct ath11k *ar = arsta->arvif->ar;
657         u32 aggr_mode;
658         int ret;
659
660         if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
661                 return -EINVAL;
662
663         if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
664                 return -EINVAL;
665
666         mutex_lock(&ar->conf_mutex);
667         if (ar->state != ATH11K_STATE_ON ||
668             aggr_mode == arsta->aggr_mode) {
669                 ret = count;
670                 goto out;
671         }
672
673         ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
674         if (ret) {
675                 ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
676                             ret);
677                 goto out;
678         }
679
680         arsta->aggr_mode = aggr_mode;
681 out:
682         mutex_unlock(&ar->conf_mutex);
683         return ret;
684 }
685
686 static const struct file_operations fops_aggr_mode = {
687         .read = ath11k_dbg_sta_read_aggr_mode,
688         .write = ath11k_dbg_sta_write_aggr_mode,
689         .open = simple_open,
690         .owner = THIS_MODULE,
691         .llseek = default_llseek,
692 };
693
694 static ssize_t
695 ath11k_write_htt_peer_stats_reset(struct file *file,
696                                   const char __user *user_buf,
697                                   size_t count, loff_t *ppos)
698 {
699         struct ieee80211_sta *sta = file->private_data;
700         struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
701         struct ath11k *ar = arsta->arvif->ar;
702         struct htt_ext_stats_cfg_params cfg_params = { 0 };
703         int ret;
704         u8 type;
705
706         ret = kstrtou8_from_user(user_buf, count, 0, &type);
707         if (ret)
708                 return ret;
709
710         if (!type)
711                 return ret;
712
713         mutex_lock(&ar->conf_mutex);
714         cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
715         cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
716                                 HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
717
718         cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
719
720         cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
721         cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
722         cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
723         cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
724
725         cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
726         cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
727
728         cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
729
730         ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
731                                                  ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
732                                                  &cfg_params,
733                                                  0ULL);
734         if (ret) {
735                 ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
736                 mutex_unlock(&ar->conf_mutex);
737                 return ret;
738         }
739
740         mutex_unlock(&ar->conf_mutex);
741
742         ret = count;
743
744         return ret;
745 }
746
747 static const struct file_operations fops_htt_peer_stats_reset = {
748         .write = ath11k_write_htt_peer_stats_reset,
749         .open = simple_open,
750         .owner = THIS_MODULE,
751         .llseek = default_llseek,
752 };
753
754 void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
755                                struct ieee80211_sta *sta, struct dentry *dir)
756 {
757         struct ath11k *ar = hw->priv;
758
759         if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
760                 debugfs_create_file("tx_stats", 0400, dir, sta,
761                                     &fops_tx_stats);
762         if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
763                 debugfs_create_file("rx_stats", 0400, dir, sta,
764                                     &fops_rx_stats);
765
766         debugfs_create_file("htt_peer_stats", 0400, dir, sta,
767                             &fops_htt_peer_stats);
768
769         debugfs_create_file("peer_pktlog", 0644, dir, sta,
770                             &fops_peer_pktlog);
771
772         debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
773         debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
774         debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
775         debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
776
777         if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
778                      ar->ab->wmi_ab.svc_map))
779                 debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
780                                     &fops_htt_peer_stats_reset);
781 }