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