Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: BSD-3-Clause-Clear
2/*
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5 */
6
7#include "core.h"
8#include "dp_tx.h"
9#include "debug.h"
10#include "debugfs.h"
11#include "debugfs_htt_stats.h"
12
13static ssize_t ath12k_write_simulate_radar(struct file *file,
14 const char __user *user_buf,
15 size_t count, loff_t *ppos)
16{
17 struct ath12k *ar = file->private_data;
18 int ret;
19
20 wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
21 ret = ath12k_wmi_simulate_radar(ar);
22 if (ret)
23 goto exit;
24
25 ret = count;
26exit:
27 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
28 return ret;
29}
30
31static const struct file_operations fops_simulate_radar = {
32 .write = ath12k_write_simulate_radar,
33 .open = simple_open
34};
35
36static ssize_t ath12k_read_simulate_fw_crash(struct file *file,
37 char __user *user_buf,
38 size_t count, loff_t *ppos)
39{
40 const char buf[] =
41 "To simulate firmware crash write one of the keywords to this file:\n"
42 "`assert` - send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n";
43
44 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
45}
46
47static ssize_t
48ath12k_write_simulate_fw_crash(struct file *file,
49 const char __user *user_buf,
50 size_t count, loff_t *ppos)
51{
52 struct ath12k_base *ab = file->private_data;
53 struct ath12k_pdev *pdev;
54 struct ath12k *ar = NULL;
55 char buf[32] = {};
56 int i, ret;
57 ssize_t rc;
58
59 /* filter partial writes and invalid commands */
60 if (*ppos != 0 || count >= sizeof(buf) || count == 0)
61 return -EINVAL;
62
63 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
64 if (rc < 0)
65 return rc;
66
67 /* drop the possible '\n' from the end */
68 if (buf[*ppos - 1] == '\n')
69 buf[*ppos - 1] = '\0';
70
71 for (i = 0; i < ab->num_radios; i++) {
72 pdev = &ab->pdevs[i];
73 ar = pdev->ar;
74 if (ar)
75 break;
76 }
77
78 if (!ar)
79 return -ENETDOWN;
80
81 if (!strcmp(buf, "assert")) {
82 ath12k_info(ab, "simulating firmware assert crash\n");
83 ret = ath12k_wmi_force_fw_hang_cmd(ar,
84 ATH12K_WMI_FW_HANG_ASSERT_TYPE,
85 ATH12K_WMI_FW_HANG_DELAY);
86 } else {
87 return -EINVAL;
88 }
89
90 if (ret) {
91 ath12k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
92 return ret;
93 }
94
95 return count;
96}
97
98static const struct file_operations fops_simulate_fw_crash = {
99 .read = ath12k_read_simulate_fw_crash,
100 .write = ath12k_write_simulate_fw_crash,
101 .open = simple_open,
102 .owner = THIS_MODULE,
103 .llseek = default_llseek,
104};
105
106static ssize_t ath12k_write_tpc_stats_type(struct file *file,
107 const char __user *user_buf,
108 size_t count, loff_t *ppos)
109{
110 struct ath12k *ar = file->private_data;
111 u8 type;
112 int ret;
113
114 ret = kstrtou8_from_user(user_buf, count, 0, &type);
115 if (ret)
116 return ret;
117
118 if (type >= WMI_HALPHY_PDEV_TX_STATS_MAX)
119 return -EINVAL;
120
121 spin_lock_bh(&ar->data_lock);
122 ar->debug.tpc_stats_type = type;
123 spin_unlock_bh(&ar->data_lock);
124
125 return count;
126}
127
128static int ath12k_debug_tpc_stats_request(struct ath12k *ar)
129{
130 enum wmi_halphy_ctrl_path_stats_id tpc_stats_sub_id;
131 struct ath12k_base *ab = ar->ab;
132 int ret;
133
134 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
135
136 reinit_completion(&ar->debug.tpc_complete);
137
138 spin_lock_bh(&ar->data_lock);
139 ar->debug.tpc_request = true;
140 tpc_stats_sub_id = ar->debug.tpc_stats_type;
141 spin_unlock_bh(&ar->data_lock);
142
143 ret = ath12k_wmi_send_tpc_stats_request(ar, tpc_stats_sub_id);
144 if (ret) {
145 ath12k_warn(ab, "failed to request pdev tpc stats: %d\n", ret);
146 spin_lock_bh(&ar->data_lock);
147 ar->debug.tpc_request = false;
148 spin_unlock_bh(&ar->data_lock);
149 return ret;
150 }
151
152 return 0;
153}
154
155static int ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg *tpc_stats,
156 enum wmi_tpc_pream_bw pream_bw, int *mode_idx)
157{
158 u32 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
159 u8 band;
160
161 band = ((chan_freq > ATH12K_MIN_6GHZ_FREQ) ? NL80211_BAND_6GHZ :
162 ((chan_freq > ATH12K_MIN_5GHZ_FREQ) ? NL80211_BAND_5GHZ :
163 NL80211_BAND_2GHZ));
164
165 if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
166 switch (pream_bw) {
167 case WMI_TPC_PREAM_HT20:
168 case WMI_TPC_PREAM_VHT20:
169 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT20_5GHZ_6GHZ;
170 break;
171 case WMI_TPC_PREAM_HE20:
172 case WMI_TPC_PREAM_EHT20:
173 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT20_5GHZ_6GHZ;
174 break;
175 case WMI_TPC_PREAM_HT40:
176 case WMI_TPC_PREAM_VHT40:
177 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT40_5GHZ_6GHZ;
178 break;
179 case WMI_TPC_PREAM_HE40:
180 case WMI_TPC_PREAM_EHT40:
181 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT40_5GHZ_6GHZ;
182 break;
183 case WMI_TPC_PREAM_VHT80:
184 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT80_5GHZ_6GHZ;
185 break;
186 case WMI_TPC_PREAM_EHT60:
187 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT80_SU_PUNC20;
188 break;
189 case WMI_TPC_PREAM_HE80:
190 case WMI_TPC_PREAM_EHT80:
191 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT80_5GHZ_6GHZ;
192 break;
193 case WMI_TPC_PREAM_VHT160:
194 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT160_5GHZ_6GHZ;
195 break;
196 case WMI_TPC_PREAM_EHT120:
197 case WMI_TPC_PREAM_EHT140:
198 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT160_SU_PUNC20;
199 break;
200 case WMI_TPC_PREAM_HE160:
201 case WMI_TPC_PREAM_EHT160:
202 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT160_5GHZ_6GHZ;
203 break;
204 case WMI_TPC_PREAM_EHT200:
205 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC120;
206 break;
207 case WMI_TPC_PREAM_EHT240:
208 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC80;
209 break;
210 case WMI_TPC_PREAM_EHT280:
211 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC40;
212 break;
213 case WMI_TPC_PREAM_EHT320:
214 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT320_5GHZ_6GHZ;
215 break;
216 default:
217 /* for 5GHZ and 6GHZ, default case will be for OFDM */
218 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_5GHZ_6GHZ;
219 break;
220 }
221 } else {
222 switch (pream_bw) {
223 case WMI_TPC_PREAM_OFDM:
224 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_2GHZ;
225 break;
226 case WMI_TPC_PREAM_HT20:
227 case WMI_TPC_PREAM_VHT20:
228 case WMI_TPC_PREAM_HE20:
229 case WMI_TPC_PREAM_EHT20:
230 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT20_2GHZ;
231 break;
232 case WMI_TPC_PREAM_HT40:
233 case WMI_TPC_PREAM_VHT40:
234 case WMI_TPC_PREAM_HE40:
235 case WMI_TPC_PREAM_EHT40:
236 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT40_2GHZ;
237 break;
238 default:
239 /* for 2GHZ, default case will be CCK */
240 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_CCK_2GHZ;
241 break;
242 }
243 }
244
245 return 0;
246}
247
248static s16 ath12k_tpc_get_rate(struct ath12k *ar,
249 struct wmi_tpc_stats_arg *tpc_stats,
250 u32 rate_idx, u32 num_chains, u32 rate_code,
251 enum wmi_tpc_pream_bw pream_bw,
252 enum wmi_halphy_ctrl_path_stats_id type,
253 u32 eht_rate_idx)
254{
255 u32 tot_nss, tot_modes, txbf_on_off, index_offset1, index_offset2, index_offset3;
256 u8 chain_idx, stm_idx, num_streams;
257 bool is_mu, txbf_enabled = 0;
258 s8 rates_ctl_min, tpc_ctl;
259 s16 rates, tpc, reg_pwr;
260 u16 rate1, rate2;
261 int mode, ret;
262
263 num_streams = 1 + ATH12K_HW_NSS(rate_code);
264 chain_idx = num_chains - 1;
265 stm_idx = num_streams - 1;
266 mode = -1;
267
268 ret = ath12k_get_tpc_ctl_mode_idx(tpc_stats, pream_bw, &mode);
269 if (ret) {
270 ath12k_warn(ar->ab, "Invalid mode index received\n");
271 tpc = TPC_INVAL;
272 goto out;
273 }
274
275 if (num_chains < num_streams) {
276 tpc = TPC_INVAL;
277 goto out;
278 }
279
280 if (le32_to_cpu(tpc_stats->tpc_config.num_tx_chain) <= 1) {
281 tpc = TPC_INVAL;
282 goto out;
283 }
284
285 if (type == WMI_HALPHY_PDEV_TX_SUTXBF_STATS ||
286 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS)
287 txbf_enabled = 1;
288
289 if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
290 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
291 is_mu = true;
292 } else {
293 is_mu = false;
294 }
295
296 /* Below is the min calculation of ctl array, rates array and
297 * regulator power table. tpc is minimum of all 3
298 */
299 if (pream_bw >= WMI_TPC_PREAM_EHT20 && pream_bw <= WMI_TPC_PREAM_EHT320) {
300 rate2 = tpc_stats->rates_array2.rate_array[eht_rate_idx];
301 if (is_mu)
302 rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_MU);
303 else
304 rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_SU);
305 } else {
306 rate1 = tpc_stats->rates_array1.rate_array[rate_idx];
307 if (is_mu)
308 rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_MU);
309 else
310 rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_SU);
311 }
312
313 if (tpc_stats->tlvs_rcvd & WMI_TPC_CTL_PWR_ARRAY) {
314 tot_nss = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d1);
315 tot_modes = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d2);
316 txbf_on_off = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d3);
317 index_offset1 = txbf_on_off * tot_modes * tot_nss;
318 index_offset2 = tot_modes * tot_nss;
319 index_offset3 = tot_nss;
320
321 tpc_ctl = *(tpc_stats->ctl_array.ctl_pwr_table +
322 chain_idx * index_offset1 + txbf_enabled * index_offset2
323 + mode * index_offset3 + stm_idx);
324 } else {
325 tpc_ctl = TPC_MAX;
326 ath12k_warn(ar->ab,
327 "ctl array for tpc stats not received from fw\n");
328 }
329
330 rates_ctl_min = min_t(s16, rates, tpc_ctl);
331
332 reg_pwr = tpc_stats->max_reg_allowed_power.reg_pwr_array[chain_idx];
333
334 if (reg_pwr < 0)
335 reg_pwr = TPC_INVAL;
336
337 tpc = min_t(s16, rates_ctl_min, reg_pwr);
338
339 /* MODULATION_LIMIT is the maximum power limit,tpc should not exceed
340 * modulation limit even if min tpc of all three array is greater
341 * modulation limit
342 */
343 tpc = min_t(s16, tpc, MODULATION_LIMIT);
344
345out:
346 return tpc;
347}
348
349static u16 ath12k_get_ratecode(u16 pream_idx, u16 nss, u16 mcs_rate)
350{
351 u16 mode_type = ~0;
352
353 /* Below assignments are just for printing purpose only */
354 switch (pream_idx) {
355 case WMI_TPC_PREAM_CCK:
356 mode_type = WMI_RATE_PREAMBLE_CCK;
357 break;
358 case WMI_TPC_PREAM_OFDM:
359 mode_type = WMI_RATE_PREAMBLE_OFDM;
360 break;
361 case WMI_TPC_PREAM_HT20:
362 case WMI_TPC_PREAM_HT40:
363 mode_type = WMI_RATE_PREAMBLE_HT;
364 break;
365 case WMI_TPC_PREAM_VHT20:
366 case WMI_TPC_PREAM_VHT40:
367 case WMI_TPC_PREAM_VHT80:
368 case WMI_TPC_PREAM_VHT160:
369 mode_type = WMI_RATE_PREAMBLE_VHT;
370 break;
371 case WMI_TPC_PREAM_HE20:
372 case WMI_TPC_PREAM_HE40:
373 case WMI_TPC_PREAM_HE80:
374 case WMI_TPC_PREAM_HE160:
375 mode_type = WMI_RATE_PREAMBLE_HE;
376 break;
377 case WMI_TPC_PREAM_EHT20:
378 case WMI_TPC_PREAM_EHT40:
379 case WMI_TPC_PREAM_EHT60:
380 case WMI_TPC_PREAM_EHT80:
381 case WMI_TPC_PREAM_EHT120:
382 case WMI_TPC_PREAM_EHT140:
383 case WMI_TPC_PREAM_EHT160:
384 case WMI_TPC_PREAM_EHT200:
385 case WMI_TPC_PREAM_EHT240:
386 case WMI_TPC_PREAM_EHT280:
387 case WMI_TPC_PREAM_EHT320:
388 mode_type = WMI_RATE_PREAMBLE_EHT;
389 if (mcs_rate == 0 || mcs_rate == 1)
390 mcs_rate += 14;
391 else
392 mcs_rate -= 2;
393 break;
394 default:
395 return mode_type;
396 }
397 return ((mode_type << 8) | ((nss & 0x7) << 5) | (mcs_rate & 0x1F));
398}
399
400static bool ath12k_he_supports_extra_mcs(struct ath12k *ar, int freq)
401{
402 struct ath12k_pdev_cap *cap = &ar->pdev->cap;
403 struct ath12k_band_cap *cap_band;
404 bool extra_mcs_supported;
405
406 if (freq <= ATH12K_2GHZ_MAX_FREQUENCY)
407 cap_band = &cap->band[NL80211_BAND_2GHZ];
408 else if (freq <= ATH12K_5GHZ_MAX_FREQUENCY)
409 cap_band = &cap->band[NL80211_BAND_5GHZ];
410 else
411 cap_band = &cap->band[NL80211_BAND_6GHZ];
412
413 extra_mcs_supported = u32_get_bits(cap_band->he_cap_info[1],
414 HE_EXTRA_MCS_SUPPORT);
415 return extra_mcs_supported;
416}
417
418static int ath12k_tpc_fill_pream(struct ath12k *ar, char *buf, int buf_len, int len,
419 enum wmi_tpc_pream_bw pream_bw, u32 max_rix,
420 int max_nss, int max_rates, int pream_type,
421 enum wmi_halphy_ctrl_path_stats_id tpc_type,
422 int rate_idx, int eht_rate_idx)
423{
424 struct wmi_tpc_stats_arg *tpc_stats = ar->debug.tpc_stats;
425 int nss, rates, chains;
426 u8 active_tx_chains;
427 u16 rate_code;
428 s16 tpc;
429
430 static const char *const pream_str[] = {
431 [WMI_TPC_PREAM_CCK] = "CCK",
432 [WMI_TPC_PREAM_OFDM] = "OFDM",
433 [WMI_TPC_PREAM_HT20] = "HT20",
434 [WMI_TPC_PREAM_HT40] = "HT40",
435 [WMI_TPC_PREAM_VHT20] = "VHT20",
436 [WMI_TPC_PREAM_VHT40] = "VHT40",
437 [WMI_TPC_PREAM_VHT80] = "VHT80",
438 [WMI_TPC_PREAM_VHT160] = "VHT160",
439 [WMI_TPC_PREAM_HE20] = "HE20",
440 [WMI_TPC_PREAM_HE40] = "HE40",
441 [WMI_TPC_PREAM_HE80] = "HE80",
442 [WMI_TPC_PREAM_HE160] = "HE160",
443 [WMI_TPC_PREAM_EHT20] = "EHT20",
444 [WMI_TPC_PREAM_EHT40] = "EHT40",
445 [WMI_TPC_PREAM_EHT60] = "EHT60",
446 [WMI_TPC_PREAM_EHT80] = "EHT80",
447 [WMI_TPC_PREAM_EHT120] = "EHT120",
448 [WMI_TPC_PREAM_EHT140] = "EHT140",
449 [WMI_TPC_PREAM_EHT160] = "EHT160",
450 [WMI_TPC_PREAM_EHT200] = "EHT200",
451 [WMI_TPC_PREAM_EHT240] = "EHT240",
452 [WMI_TPC_PREAM_EHT280] = "EHT280",
453 [WMI_TPC_PREAM_EHT320] = "EHT320"};
454
455 active_tx_chains = ar->num_tx_chains;
456
457 for (nss = 0; nss < max_nss; nss++) {
458 for (rates = 0; rates < max_rates; rates++, rate_idx++, max_rix++) {
459 /* FW send extra MCS(10&11) for VHT and HE rates,
460 * this is not used. Hence skipping it here
461 */
462 if (pream_type == WMI_RATE_PREAMBLE_VHT &&
463 rates > ATH12K_VHT_MCS_MAX)
464 continue;
465
466 if (pream_type == WMI_RATE_PREAMBLE_HE &&
467 rates > ATH12K_HE_MCS_MAX)
468 continue;
469
470 if (pream_type == WMI_RATE_PREAMBLE_EHT &&
471 rates > ATH12K_EHT_MCS_MAX)
472 continue;
473
474 rate_code = ath12k_get_ratecode(pream_bw, nss, rates);
475 len += scnprintf(buf + len, buf_len - len,
476 "%d\t %s\t 0x%03x\t", max_rix,
477 pream_str[pream_bw], rate_code);
478
479 for (chains = 0; chains < active_tx_chains; chains++) {
480 if (nss > chains) {
481 len += scnprintf(buf + len,
482 buf_len - len,
483 "\t%s", "NA");
484 } else {
485 tpc = ath12k_tpc_get_rate(ar, tpc_stats,
486 rate_idx, chains + 1,
487 rate_code, pream_bw,
488 tpc_type,
489 eht_rate_idx);
490
491 if (tpc == TPC_INVAL) {
492 len += scnprintf(buf + len,
493 buf_len - len, "\tNA");
494 } else {
495 len += scnprintf(buf + len,
496 buf_len - len, "\t%d",
497 tpc);
498 }
499 }
500 }
501 len += scnprintf(buf + len, buf_len - len, "\n");
502
503 if (pream_type == WMI_RATE_PREAMBLE_EHT)
504 /*For fetching the next eht rates pwr from rates array2*/
505 ++eht_rate_idx;
506 }
507 }
508
509 return len;
510}
511
512static int ath12k_tpc_stats_print(struct ath12k *ar,
513 struct wmi_tpc_stats_arg *tpc_stats,
514 char *buf, size_t len,
515 enum wmi_halphy_ctrl_path_stats_id type)
516{
517 u32 eht_idx = 0, pream_idx = 0, rate_pream_idx = 0, total_rates = 0, max_rix = 0;
518 u32 chan_freq, num_tx_chain, caps, i, j = 1;
519 size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
520 u8 nss, active_tx_chains;
521 bool he_ext_mcs;
522 static const char *const type_str[WMI_HALPHY_PDEV_TX_STATS_MAX] = {
523 [WMI_HALPHY_PDEV_TX_SU_STATS] = "SU",
524 [WMI_HALPHY_PDEV_TX_SUTXBF_STATS] = "SU WITH TXBF",
525 [WMI_HALPHY_PDEV_TX_MU_STATS] = "MU",
526 [WMI_HALPHY_PDEV_TX_MUTXBF_STATS] = "MU WITH TXBF"};
527
528 u8 max_rates[WMI_TPC_PREAM_MAX] = {
529 [WMI_TPC_PREAM_CCK] = ATH12K_CCK_RATES,
530 [WMI_TPC_PREAM_OFDM] = ATH12K_OFDM_RATES,
531 [WMI_TPC_PREAM_HT20] = ATH12K_HT_RATES,
532 [WMI_TPC_PREAM_HT40] = ATH12K_HT_RATES,
533 [WMI_TPC_PREAM_VHT20] = ATH12K_VHT_RATES,
534 [WMI_TPC_PREAM_VHT40] = ATH12K_VHT_RATES,
535 [WMI_TPC_PREAM_VHT80] = ATH12K_VHT_RATES,
536 [WMI_TPC_PREAM_VHT160] = ATH12K_VHT_RATES,
537 [WMI_TPC_PREAM_HE20] = ATH12K_HE_RATES,
538 [WMI_TPC_PREAM_HE40] = ATH12K_HE_RATES,
539 [WMI_TPC_PREAM_HE80] = ATH12K_HE_RATES,
540 [WMI_TPC_PREAM_HE160] = ATH12K_HE_RATES,
541 [WMI_TPC_PREAM_EHT20] = ATH12K_EHT_RATES,
542 [WMI_TPC_PREAM_EHT40] = ATH12K_EHT_RATES,
543 [WMI_TPC_PREAM_EHT60] = ATH12K_EHT_RATES,
544 [WMI_TPC_PREAM_EHT80] = ATH12K_EHT_RATES,
545 [WMI_TPC_PREAM_EHT120] = ATH12K_EHT_RATES,
546 [WMI_TPC_PREAM_EHT140] = ATH12K_EHT_RATES,
547 [WMI_TPC_PREAM_EHT160] = ATH12K_EHT_RATES,
548 [WMI_TPC_PREAM_EHT200] = ATH12K_EHT_RATES,
549 [WMI_TPC_PREAM_EHT240] = ATH12K_EHT_RATES,
550 [WMI_TPC_PREAM_EHT280] = ATH12K_EHT_RATES,
551 [WMI_TPC_PREAM_EHT320] = ATH12K_EHT_RATES};
552 static const u8 max_nss[WMI_TPC_PREAM_MAX] = {
553 [WMI_TPC_PREAM_CCK] = ATH12K_NSS_1,
554 [WMI_TPC_PREAM_OFDM] = ATH12K_NSS_1,
555 [WMI_TPC_PREAM_HT20] = ATH12K_NSS_4,
556 [WMI_TPC_PREAM_HT40] = ATH12K_NSS_4,
557 [WMI_TPC_PREAM_VHT20] = ATH12K_NSS_8,
558 [WMI_TPC_PREAM_VHT40] = ATH12K_NSS_8,
559 [WMI_TPC_PREAM_VHT80] = ATH12K_NSS_8,
560 [WMI_TPC_PREAM_VHT160] = ATH12K_NSS_4,
561 [WMI_TPC_PREAM_HE20] = ATH12K_NSS_8,
562 [WMI_TPC_PREAM_HE40] = ATH12K_NSS_8,
563 [WMI_TPC_PREAM_HE80] = ATH12K_NSS_8,
564 [WMI_TPC_PREAM_HE160] = ATH12K_NSS_4,
565 [WMI_TPC_PREAM_EHT20] = ATH12K_NSS_4,
566 [WMI_TPC_PREAM_EHT40] = ATH12K_NSS_4,
567 [WMI_TPC_PREAM_EHT60] = ATH12K_NSS_4,
568 [WMI_TPC_PREAM_EHT80] = ATH12K_NSS_4,
569 [WMI_TPC_PREAM_EHT120] = ATH12K_NSS_4,
570 [WMI_TPC_PREAM_EHT140] = ATH12K_NSS_4,
571 [WMI_TPC_PREAM_EHT160] = ATH12K_NSS_4,
572 [WMI_TPC_PREAM_EHT200] = ATH12K_NSS_4,
573 [WMI_TPC_PREAM_EHT240] = ATH12K_NSS_4,
574 [WMI_TPC_PREAM_EHT280] = ATH12K_NSS_4,
575 [WMI_TPC_PREAM_EHT320] = ATH12K_NSS_4};
576
577 u16 rate_idx[WMI_TPC_PREAM_MAX] = {}, eht_rate_idx[WMI_TPC_PREAM_MAX] = {};
578 static const u8 pream_type[WMI_TPC_PREAM_MAX] = {
579 [WMI_TPC_PREAM_CCK] = WMI_RATE_PREAMBLE_CCK,
580 [WMI_TPC_PREAM_OFDM] = WMI_RATE_PREAMBLE_OFDM,
581 [WMI_TPC_PREAM_HT20] = WMI_RATE_PREAMBLE_HT,
582 [WMI_TPC_PREAM_HT40] = WMI_RATE_PREAMBLE_HT,
583 [WMI_TPC_PREAM_VHT20] = WMI_RATE_PREAMBLE_VHT,
584 [WMI_TPC_PREAM_VHT40] = WMI_RATE_PREAMBLE_VHT,
585 [WMI_TPC_PREAM_VHT80] = WMI_RATE_PREAMBLE_VHT,
586 [WMI_TPC_PREAM_VHT160] = WMI_RATE_PREAMBLE_VHT,
587 [WMI_TPC_PREAM_HE20] = WMI_RATE_PREAMBLE_HE,
588 [WMI_TPC_PREAM_HE40] = WMI_RATE_PREAMBLE_HE,
589 [WMI_TPC_PREAM_HE80] = WMI_RATE_PREAMBLE_HE,
590 [WMI_TPC_PREAM_HE160] = WMI_RATE_PREAMBLE_HE,
591 [WMI_TPC_PREAM_EHT20] = WMI_RATE_PREAMBLE_EHT,
592 [WMI_TPC_PREAM_EHT40] = WMI_RATE_PREAMBLE_EHT,
593 [WMI_TPC_PREAM_EHT60] = WMI_RATE_PREAMBLE_EHT,
594 [WMI_TPC_PREAM_EHT80] = WMI_RATE_PREAMBLE_EHT,
595 [WMI_TPC_PREAM_EHT120] = WMI_RATE_PREAMBLE_EHT,
596 [WMI_TPC_PREAM_EHT140] = WMI_RATE_PREAMBLE_EHT,
597 [WMI_TPC_PREAM_EHT160] = WMI_RATE_PREAMBLE_EHT,
598 [WMI_TPC_PREAM_EHT200] = WMI_RATE_PREAMBLE_EHT,
599 [WMI_TPC_PREAM_EHT240] = WMI_RATE_PREAMBLE_EHT,
600 [WMI_TPC_PREAM_EHT280] = WMI_RATE_PREAMBLE_EHT,
601 [WMI_TPC_PREAM_EHT320] = WMI_RATE_PREAMBLE_EHT};
602
603 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
604 num_tx_chain = le32_to_cpu(tpc_stats->tpc_config.num_tx_chain);
605 caps = le32_to_cpu(tpc_stats->tpc_config.caps);
606
607 active_tx_chains = ar->num_tx_chains;
608 he_ext_mcs = ath12k_he_supports_extra_mcs(ar, chan_freq);
609
610 /* mcs 12&13 is sent by FW for certain HWs in rate array, skipping it as
611 * it is not supported
612 */
613 if (he_ext_mcs) {
614 for (i = WMI_TPC_PREAM_HE20; i <= WMI_TPC_PREAM_HE160; ++i)
615 max_rates[i] = ATH12K_HE_RATES;
616 }
617
618 if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
619 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
620 pream_idx = WMI_TPC_PREAM_VHT20;
621
622 for (i = WMI_TPC_PREAM_CCK; i <= WMI_TPC_PREAM_HT40; ++i)
623 max_rix += max_nss[i] * max_rates[i];
624 }
625 /* Enumerate all the rate indices */
626 for (i = rate_pream_idx + 1; i < WMI_TPC_PREAM_MAX; i++) {
627 nss = (max_nss[i - 1] < num_tx_chain ?
628 max_nss[i - 1] : num_tx_chain);
629
630 rate_idx[i] = rate_idx[i - 1] + max_rates[i - 1] * nss;
631
632 if (pream_type[i] == WMI_RATE_PREAMBLE_EHT) {
633 eht_rate_idx[j] = eht_rate_idx[j - 1] + max_rates[i] * nss;
634 ++j;
635 }
636 }
637
638 for (i = 0; i < WMI_TPC_PREAM_MAX; i++) {
639 nss = (max_nss[i] < num_tx_chain ?
640 max_nss[i] : num_tx_chain);
641 total_rates += max_rates[i] * nss;
642 }
643
644 len += scnprintf(buf + len, buf_len - len,
645 "No.of rates-%d\n", total_rates);
646
647 len += scnprintf(buf + len, buf_len - len,
648 "**************** %s ****************\n",
649 type_str[type]);
650 len += scnprintf(buf + len, buf_len - len,
651 "\t\t\t\tTPC values for Active chains\n");
652 len += scnprintf(buf + len, buf_len - len,
653 "Rate idx Preamble Rate code");
654
655 for (i = 1; i <= active_tx_chains; ++i) {
656 len += scnprintf(buf + len, buf_len - len,
657 "\t%d-Chain", i);
658 }
659
660 len += scnprintf(buf + len, buf_len - len, "\n");
661 for (i = pream_idx; i < WMI_TPC_PREAM_MAX; i++) {
662 if (chan_freq <= 2483) {
663 if (i == WMI_TPC_PREAM_VHT80 ||
664 i == WMI_TPC_PREAM_VHT160 ||
665 i == WMI_TPC_PREAM_HE80 ||
666 i == WMI_TPC_PREAM_HE160 ||
667 (i >= WMI_TPC_PREAM_EHT60 &&
668 i <= WMI_TPC_PREAM_EHT320)) {
669 max_rix += max_nss[i] * max_rates[i];
670 continue;
671 }
672 } else {
673 if (i == WMI_TPC_PREAM_CCK) {
674 max_rix += max_rates[i];
675 continue;
676 }
677 }
678
679 nss = (max_nss[i] < ar->num_tx_chains ? max_nss[i] : ar->num_tx_chains);
680
681 if (!(caps &
682 (1 << ATH12K_TPC_STATS_SUPPORT_BE_PUNC))) {
683 if (i == WMI_TPC_PREAM_EHT60 || i == WMI_TPC_PREAM_EHT120 ||
684 i == WMI_TPC_PREAM_EHT140 || i == WMI_TPC_PREAM_EHT200 ||
685 i == WMI_TPC_PREAM_EHT240 || i == WMI_TPC_PREAM_EHT280) {
686 max_rix += max_nss[i] * max_rates[i];
687 continue;
688 }
689 }
690
691 len = ath12k_tpc_fill_pream(ar, buf, buf_len, len, i, max_rix, nss,
692 max_rates[i], pream_type[i],
693 type, rate_idx[i], eht_rate_idx[eht_idx]);
694
695 if (pream_type[i] == WMI_RATE_PREAMBLE_EHT)
696 /*For fetch the next index eht rates from rates array2*/
697 ++eht_idx;
698
699 max_rix += max_nss[i] * max_rates[i];
700 }
701 return len;
702}
703
704static void ath12k_tpc_stats_fill(struct ath12k *ar,
705 struct wmi_tpc_stats_arg *tpc_stats,
706 char *buf)
707{
708 size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
709 struct wmi_tpc_config_params *tpc;
710 size_t len = 0;
711
712 if (!tpc_stats) {
713 ath12k_warn(ar->ab, "failed to find tpc stats\n");
714 return;
715 }
716
717 spin_lock_bh(&ar->data_lock);
718
719 tpc = &tpc_stats->tpc_config;
720 len += scnprintf(buf + len, buf_len - len, "\n");
721 len += scnprintf(buf + len, buf_len - len,
722 "*************** TPC config **************\n");
723 len += scnprintf(buf + len, buf_len - len,
724 "* powers are in 0.25 dBm steps\n");
725 len += scnprintf(buf + len, buf_len - len,
726 "reg domain-%d\t\tchan freq-%d\n",
727 tpc->reg_domain, tpc->chan_freq);
728 len += scnprintf(buf + len, buf_len - len,
729 "power limit-%d\t\tmax reg-domain Power-%d\n",
730 le32_to_cpu(tpc->twice_max_reg_power) / 2, tpc->power_limit);
731 len += scnprintf(buf + len, buf_len - len,
732 "No.of tx chain-%d\t",
733 ar->num_tx_chains);
734
735 ath12k_tpc_stats_print(ar, tpc_stats, buf, len,
736 ar->debug.tpc_stats_type);
737
738 spin_unlock_bh(&ar->data_lock);
739}
740
741static int ath12k_open_tpc_stats(struct inode *inode, struct file *file)
742{
743 struct ath12k *ar = inode->i_private;
744 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
745 int ret;
746
747 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
748
749 if (ah->state != ATH12K_HW_STATE_ON) {
750 ath12k_warn(ar->ab, "Interface not up\n");
751 return -ENETDOWN;
752 }
753
754 void *buf __free(kfree) = kzalloc(ATH12K_TPC_STATS_BUF_SIZE, GFP_KERNEL);
755 if (!buf)
756 return -ENOMEM;
757
758 ret = ath12k_debug_tpc_stats_request(ar);
759 if (ret) {
760 ath12k_warn(ar->ab, "failed to request tpc stats: %d\n",
761 ret);
762 return ret;
763 }
764
765 if (!wait_for_completion_timeout(&ar->debug.tpc_complete, TPC_STATS_WAIT_TIME)) {
766 spin_lock_bh(&ar->data_lock);
767 ath12k_wmi_free_tpc_stats_mem(ar);
768 ar->debug.tpc_request = false;
769 spin_unlock_bh(&ar->data_lock);
770 return -ETIMEDOUT;
771 }
772
773 ath12k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
774 file->private_data = no_free_ptr(buf);
775
776 spin_lock_bh(&ar->data_lock);
777 ath12k_wmi_free_tpc_stats_mem(ar);
778 spin_unlock_bh(&ar->data_lock);
779
780 return 0;
781}
782
783static ssize_t ath12k_read_tpc_stats(struct file *file,
784 char __user *user_buf,
785 size_t count, loff_t *ppos)
786{
787 const char *buf = file->private_data;
788 size_t len = strlen(buf);
789
790 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
791}
792
793static int ath12k_release_tpc_stats(struct inode *inode,
794 struct file *file)
795{
796 kfree(file->private_data);
797 return 0;
798}
799
800static const struct file_operations fops_tpc_stats = {
801 .open = ath12k_open_tpc_stats,
802 .release = ath12k_release_tpc_stats,
803 .read = ath12k_read_tpc_stats,
804 .owner = THIS_MODULE,
805 .llseek = default_llseek,
806};
807
808static const struct file_operations fops_tpc_stats_type = {
809 .write = ath12k_write_tpc_stats_type,
810 .open = simple_open,
811 .llseek = default_llseek,
812};
813
814static ssize_t ath12k_write_extd_rx_stats(struct file *file,
815 const char __user *ubuf,
816 size_t count, loff_t *ppos)
817{
818 struct ath12k *ar = file->private_data;
819 struct htt_rx_ring_tlv_filter tlv_filter = {};
820 u32 ring_id, rx_filter = 0;
821 bool enable;
822 int ret, i;
823
824 if (kstrtobool_from_user(ubuf, count, &enable))
825 return -EINVAL;
826
827 wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
828
829 if (!ar->ab->hw_params->rxdma1_enable) {
830 ret = count;
831 goto exit;
832 }
833
834 if (ar->ah->state != ATH12K_HW_STATE_ON) {
835 ret = -ENETDOWN;
836 goto exit;
837 }
838
839 if (enable == ar->debug.extd_rx_stats) {
840 ret = count;
841 goto exit;
842 }
843
844 if (enable) {
845 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
846 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
847 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
848 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
849 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
850 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
851 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO;
852
853 tlv_filter.rx_filter = rx_filter;
854 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
855 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
856 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
857 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
858 HTT_RX_FP_DATA_FILTER_FLASG3;
859 } else {
860 tlv_filter = ath12k_mac_mon_status_filter_default;
861 }
862
863 ar->debug.rx_filter = tlv_filter.rx_filter;
864
865 for (i = 0; i < ar->ab->hw_params->num_rxdma_per_pdev; i++) {
866 ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
867 ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i,
868 HAL_RXDMA_MONITOR_DST,
869 DP_RXDMA_REFILL_RING_SIZE,
870 &tlv_filter);
871 if (ret) {
872 ath12k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
873 goto exit;
874 }
875 }
876
877 ar->debug.extd_rx_stats = !!enable;
878 ret = count;
879exit:
880 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
881 return ret;
882}
883
884static ssize_t ath12k_read_extd_rx_stats(struct file *file,
885 char __user *ubuf,
886 size_t count, loff_t *ppos)
887{
888 struct ath12k *ar = file->private_data;
889 char buf[32];
890 int len = 0;
891
892 wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
893 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
894 ar->debug.extd_rx_stats);
895 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
896
897 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
898}
899
900static const struct file_operations fops_extd_rx_stats = {
901 .read = ath12k_read_extd_rx_stats,
902 .write = ath12k_write_extd_rx_stats,
903 .open = simple_open,
904};
905
906static int ath12k_open_link_stats(struct inode *inode, struct file *file)
907{
908 struct ath12k_vif *ahvif = inode->i_private;
909 size_t len = 0, buf_len = (PAGE_SIZE * 2);
910 struct ath12k_link_stats linkstat;
911 struct ath12k_link_vif *arvif;
912 unsigned long links_map;
913 struct wiphy *wiphy;
914 int link_id, i;
915 char *buf;
916
917 if (!ahvif)
918 return -EINVAL;
919
920 buf = kzalloc(buf_len, GFP_KERNEL);
921 if (!buf)
922 return -ENOMEM;
923
924 wiphy = ahvif->ah->hw->wiphy;
925 wiphy_lock(wiphy);
926
927 links_map = ahvif->links_map;
928 for_each_set_bit(link_id, &links_map,
929 IEEE80211_MLD_MAX_NUM_LINKS) {
930 arvif = rcu_dereference_protected(ahvif->link[link_id],
931 lockdep_is_held(&wiphy->mtx));
932
933 spin_lock_bh(&arvif->link_stats_lock);
934 linkstat = arvif->link_stats;
935 spin_unlock_bh(&arvif->link_stats_lock);
936
937 len += scnprintf(buf + len, buf_len - len,
938 "link[%d] Tx Unicast Frames Enqueued = %d\n",
939 link_id, linkstat.tx_enqueued);
940 len += scnprintf(buf + len, buf_len - len,
941 "link[%d] Tx Broadcast Frames Enqueued = %d\n",
942 link_id, linkstat.tx_bcast_mcast);
943 len += scnprintf(buf + len, buf_len - len,
944 "link[%d] Tx Frames Completed = %d\n",
945 link_id, linkstat.tx_completed);
946 len += scnprintf(buf + len, buf_len - len,
947 "link[%d] Tx Frames Dropped = %d\n",
948 link_id, linkstat.tx_dropped);
949
950 len += scnprintf(buf + len, buf_len - len,
951 "link[%d] Tx Frame descriptor Encap Type = ",
952 link_id);
953
954 len += scnprintf(buf + len, buf_len - len,
955 " raw:%d",
956 linkstat.tx_encap_type[0]);
957
958 len += scnprintf(buf + len, buf_len - len,
959 " native_wifi:%d",
960 linkstat.tx_encap_type[1]);
961
962 len += scnprintf(buf + len, buf_len - len,
963 " ethernet:%d",
964 linkstat.tx_encap_type[2]);
965
966 len += scnprintf(buf + len, buf_len - len,
967 "\nlink[%d] Tx Frame descriptor Encrypt Type = ",
968 link_id);
969
970 for (i = 0; i < DP_ENCRYPT_TYPE_MAX; i++) {
971 len += scnprintf(buf + len, buf_len - len,
972 " %d:%d", i,
973 linkstat.tx_encrypt_type[i]);
974 }
975 len += scnprintf(buf + len, buf_len - len,
976 "\nlink[%d] Tx Frame descriptor Type = buffer:%d extension:%d\n",
977 link_id, linkstat.tx_desc_type[0],
978 linkstat.tx_desc_type[1]);
979
980 len += scnprintf(buf + len, buf_len - len,
981 "------------------------------------------------------\n");
982 }
983
984 wiphy_unlock(wiphy);
985
986 file->private_data = buf;
987
988 return 0;
989}
990
991static int ath12k_release_link_stats(struct inode *inode, struct file *file)
992{
993 kfree(file->private_data);
994 return 0;
995}
996
997static ssize_t ath12k_read_link_stats(struct file *file,
998 char __user *user_buf,
999 size_t count, loff_t *ppos)
1000{
1001 const char *buf = file->private_data;
1002 size_t len = strlen(buf);
1003
1004 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1005}
1006
1007static const struct file_operations ath12k_fops_link_stats = {
1008 .open = ath12k_open_link_stats,
1009 .release = ath12k_release_link_stats,
1010 .read = ath12k_read_link_stats,
1011 .owner = THIS_MODULE,
1012 .llseek = default_llseek,
1013};
1014
1015void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
1016 struct ieee80211_vif *vif)
1017{
1018 struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
1019
1020 debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
1021 &ath12k_fops_link_stats);
1022}
1023EXPORT_SYMBOL(ath12k_debugfs_op_vif_add);
1024
1025static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
1026 char __user *user_buf,
1027 size_t count, loff_t *ppos)
1028{
1029 struct ath12k_base *ab = file->private_data;
1030 struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
1031 struct ath12k_device_dp_stats *device_stats = &dp->device_stats;
1032 int len = 0, i, j, ret;
1033 struct ath12k *ar;
1034 const int size = 4096;
1035 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
1036 [HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR] = "Overflow",
1037 [HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR] = "MPDU len",
1038 [HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR] = "FCS",
1039 [HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR] = "Decrypt",
1040 [HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR] = "TKIP MIC",
1041 [HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR] = "Unencrypt",
1042 [HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR] = "MSDU len",
1043 [HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR] = "MSDU limit",
1044 [HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR] = "WiFi parse",
1045 [HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR] = "AMSDU parse",
1046 [HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR] = "SA timeout",
1047 [HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR] = "DA timeout",
1048 [HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR] = "Flow timeout",
1049 [HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR] = "Flush req",
1050 [HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR] = "AMSDU frag",
1051 [HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR] = "Multicast echo",
1052 [HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR] = "AMSDU mismatch",
1053 [HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR] = "Unauth WDS",
1054 [HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR] = "AMSDU or WDS"};
1055
1056 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
1057 [HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO] = "Desc addr zero",
1058 [HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID] = "Desc inval",
1059 [HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA] = "AMPDU in non BA",
1060 [HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE] = "Non BA dup",
1061 [HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE] = "BA dup",
1062 [HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP] = "Frame 2k jump",
1063 [HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP] = "BAR 2k jump",
1064 [HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR] = "Frame OOR",
1065 [HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR] = "BAR OOR",
1066 [HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION] = "No BA session",
1067 [HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN] = "Frame SN equal SSN",
1068 [HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED] = "PN check fail",
1069 [HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET] = "2k err",
1070 [HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET] = "PN err",
1071 [HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED] = "Desc blocked"};
1072
1073 static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = {
1074 [HAL_WBM_REL_SRC_MODULE_TQM] = "TQM",
1075 [HAL_WBM_REL_SRC_MODULE_RXDMA] = "Rxdma",
1076 [HAL_WBM_REL_SRC_MODULE_REO] = "Reo",
1077 [HAL_WBM_REL_SRC_MODULE_FW] = "FW",
1078 [HAL_WBM_REL_SRC_MODULE_SW] = "SW"};
1079
1080 char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
1081
1082 if (!buf)
1083 return -ENOMEM;
1084
1085 len += scnprintf(buf + len, size - len, "DEVICE RX STATS:\n\n");
1086 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
1087 device_stats->err_ring_pkts);
1088 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
1089 device_stats->invalid_rbm);
1090 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
1091
1092 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
1093 len += scnprintf(buf + len, size - len, "%s: %u\n",
1094 rxdma_err[i], device_stats->rxdma_error[i]);
1095
1096 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
1097
1098 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
1099 len += scnprintf(buf + len, size - len, "%s: %u\n",
1100 reo_err[i], device_stats->reo_error[i]);
1101
1102 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
1103
1104 for (i = 0; i < DP_REO_DST_RING_MAX; i++)
1105 len += scnprintf(buf + len, size - len,
1106 "ring%d: %u\n", i,
1107 device_stats->hal_reo_error[i]);
1108
1109 len += scnprintf(buf + len, size - len, "\nDEVICE TX STATS:\n");
1110 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
1111
1112 for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1113 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
1114 i, device_stats->tx_err.desc_na[i]);
1115
1116 len += scnprintf(buf + len, size - len,
1117 "\nMisc Transmit Failures: %d\n",
1118 atomic_read(&device_stats->tx_err.misc_fail));
1119
1120 len += scnprintf(buf + len, size - len, "\ntx_wbm_rel_source:");
1121
1122 for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++)
1123 len += scnprintf(buf + len, size - len, " %d:%u",
1124 i, device_stats->tx_wbm_rel_source[i]);
1125
1126 len += scnprintf(buf + len, size - len, "\n");
1127
1128 len += scnprintf(buf + len, size - len, "\ntqm_rel_reason:");
1129
1130 for (i = 0; i < MAX_TQM_RELEASE_REASON; i++)
1131 len += scnprintf(buf + len, size - len, " %d:%u",
1132 i, device_stats->tqm_rel_reason[i]);
1133
1134 len += scnprintf(buf + len, size - len, "\n");
1135
1136 len += scnprintf(buf + len, size - len, "\nfw_tx_status:");
1137
1138 for (i = 0; i < MAX_FW_TX_STATUS; i++)
1139 len += scnprintf(buf + len, size - len, " %d:%u",
1140 i, device_stats->fw_tx_status[i]);
1141
1142 len += scnprintf(buf + len, size - len, "\n");
1143
1144 len += scnprintf(buf + len, size - len, "\ntx_enqueued:");
1145
1146 for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1147 len += scnprintf(buf + len, size - len, " %d:%u", i,
1148 device_stats->tx_enqueued[i]);
1149
1150 len += scnprintf(buf + len, size - len, "\n");
1151
1152 len += scnprintf(buf + len, size - len, "\ntx_completed:");
1153
1154 for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1155 len += scnprintf(buf + len, size - len, " %d:%u",
1156 i, device_stats->tx_completed[i]);
1157
1158 len += scnprintf(buf + len, size - len, "\n");
1159
1160 rcu_read_lock();
1161 for (i = 0; i < ab->num_radios; i++) {
1162 ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
1163 if (ar) {
1164 len += scnprintf(buf + len, size - len,
1165 "\nradio%d tx_pending: %u\n", i,
1166 atomic_read(&ar->dp.num_tx_pending));
1167 }
1168 }
1169 rcu_read_unlock();
1170
1171 len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
1172
1173 for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
1174 len += scnprintf(buf + len, size - len, "Ring%d:", i + 1);
1175
1176 for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
1177 len += scnprintf(buf + len, size - len,
1178 "\t%d:%u", j,
1179 device_stats->reo_rx[i][j]);
1180 }
1181
1182 len += scnprintf(buf + len, size - len, "\n");
1183 }
1184
1185 len += scnprintf(buf + len, size - len, "\nREO excep MSDU buf type:%u\n",
1186 device_stats->reo_excep_msdu_buf_type);
1187
1188 len += scnprintf(buf + len, size - len, "\nRx WBM REL SRC Errors:\n");
1189
1190 for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++) {
1191 len += scnprintf(buf + len, size - len, "%s:", wbm_rel_src[i]);
1192
1193 for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
1194 len += scnprintf(buf + len,
1195 size - len,
1196 "\t%d:%u", j,
1197 device_stats->rx_wbm_rel_source[i][j]);
1198 }
1199
1200 len += scnprintf(buf + len, size - len, "\n");
1201 }
1202
1203 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1204
1205 return ret;
1206}
1207
1208static const struct file_operations fops_device_dp_stats = {
1209 .read = ath12k_debugfs_dump_device_dp_stats,
1210 .open = simple_open,
1211 .owner = THIS_MODULE,
1212 .llseek = default_llseek,
1213};
1214
1215void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
1216{
1217 debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
1218 &fops_simulate_fw_crash);
1219
1220 debugfs_create_file("device_dp_stats", 0400, ab->debugfs_soc, ab,
1221 &fops_device_dp_stats);
1222}
1223
1224void ath12k_debugfs_soc_create(struct ath12k_base *ab)
1225{
1226 bool dput_needed;
1227 char soc_name[64] = {};
1228 struct dentry *debugfs_ath12k;
1229
1230 debugfs_ath12k = debugfs_lookup("ath12k", NULL);
1231 if (debugfs_ath12k) {
1232 /* a dentry from lookup() needs dput() after we don't use it */
1233 dput_needed = true;
1234 } else {
1235 debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
1236 if (IS_ERR_OR_NULL(debugfs_ath12k))
1237 return;
1238 dput_needed = false;
1239 }
1240
1241 scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
1242 dev_name(ab->dev));
1243
1244 ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
1245
1246 if (dput_needed)
1247 dput(debugfs_ath12k);
1248}
1249
1250void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
1251{
1252 debugfs_remove_recursive(ab->debugfs_soc);
1253 ab->debugfs_soc = NULL;
1254 /* We are not removing ath12k directory on purpose, even if it
1255 * would be empty. This simplifies the directory handling and it's
1256 * a minor cosmetic issue to leave an empty ath12k directory to
1257 * debugfs.
1258 */
1259}
1260
1261static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
1262{
1263 struct ath12k *ar = inode->i_private;
1264 struct ath12k_fw_stats_req_params param;
1265 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1266 int ret;
1267
1268 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1269
1270 if (!ah)
1271 return -ENETDOWN;
1272
1273 if (ah->state != ATH12K_HW_STATE_ON)
1274 return -ENETDOWN;
1275
1276 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1277 if (!buf)
1278 return -ENOMEM;
1279
1280 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1281 /* VDEV stats is always sent for all active VDEVs from FW */
1282 param.vdev_id = 0;
1283 param.stats_id = WMI_REQUEST_VDEV_STAT;
1284
1285 ret = ath12k_mac_get_fw_stats(ar, ¶m);
1286 if (ret) {
1287 ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
1288 return ret;
1289 }
1290
1291 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1292 buf);
1293 ath12k_fw_stats_reset(ar);
1294
1295 file->private_data = no_free_ptr(buf);
1296
1297 return 0;
1298}
1299
1300static int ath12k_release_vdev_stats(struct inode *inode, struct file *file)
1301{
1302 kfree(file->private_data);
1303
1304 return 0;
1305}
1306
1307static ssize_t ath12k_read_vdev_stats(struct file *file,
1308 char __user *user_buf,
1309 size_t count, loff_t *ppos)
1310{
1311 const char *buf = file->private_data;
1312 size_t len = strlen(buf);
1313
1314 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1315}
1316
1317static const struct file_operations fops_vdev_stats = {
1318 .open = ath12k_open_vdev_stats,
1319 .release = ath12k_release_vdev_stats,
1320 .read = ath12k_read_vdev_stats,
1321 .owner = THIS_MODULE,
1322 .llseek = default_llseek,
1323};
1324
1325static int ath12k_open_bcn_stats(struct inode *inode, struct file *file)
1326{
1327 struct ath12k *ar = inode->i_private;
1328 struct ath12k_link_vif *arvif;
1329 struct ath12k_fw_stats_req_params param;
1330 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1331 int ret;
1332
1333 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1334
1335 if (ah && ah->state != ATH12K_HW_STATE_ON)
1336 return -ENETDOWN;
1337
1338 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1339 if (!buf)
1340 return -ENOMEM;
1341
1342 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1343 param.stats_id = WMI_REQUEST_BCN_STAT;
1344
1345 /* loop all active VDEVs for bcn stats */
1346 list_for_each_entry(arvif, &ar->arvifs, list) {
1347 if (!arvif->is_up)
1348 continue;
1349
1350 param.vdev_id = arvif->vdev_id;
1351 ret = ath12k_mac_get_fw_stats(ar, ¶m);
1352 if (ret) {
1353 ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
1354 return ret;
1355 }
1356 }
1357
1358 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1359 buf);
1360 ath12k_fw_stats_reset(ar);
1361
1362 file->private_data = no_free_ptr(buf);
1363
1364 return 0;
1365}
1366
1367static int ath12k_release_bcn_stats(struct inode *inode, struct file *file)
1368{
1369 kfree(file->private_data);
1370
1371 return 0;
1372}
1373
1374static ssize_t ath12k_read_bcn_stats(struct file *file,
1375 char __user *user_buf,
1376 size_t count, loff_t *ppos)
1377{
1378 const char *buf = file->private_data;
1379 size_t len = strlen(buf);
1380
1381 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1382}
1383
1384static const struct file_operations fops_bcn_stats = {
1385 .open = ath12k_open_bcn_stats,
1386 .release = ath12k_release_bcn_stats,
1387 .read = ath12k_read_bcn_stats,
1388 .owner = THIS_MODULE,
1389 .llseek = default_llseek,
1390};
1391
1392static int ath12k_open_pdev_stats(struct inode *inode, struct file *file)
1393{
1394 struct ath12k *ar = inode->i_private;
1395 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1396 struct ath12k_base *ab = ar->ab;
1397 struct ath12k_fw_stats_req_params param;
1398 int ret;
1399
1400 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1401
1402 if (ah && ah->state != ATH12K_HW_STATE_ON)
1403 return -ENETDOWN;
1404
1405 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1406 if (!buf)
1407 return -ENOMEM;
1408
1409 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1410 param.vdev_id = 0;
1411 param.stats_id = WMI_REQUEST_PDEV_STAT;
1412
1413 ret = ath12k_mac_get_fw_stats(ar, ¶m);
1414 if (ret) {
1415 ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
1416 return ret;
1417 }
1418
1419 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1420 buf);
1421 ath12k_fw_stats_reset(ar);
1422
1423 file->private_data = no_free_ptr(buf);
1424
1425 return 0;
1426}
1427
1428static int ath12k_release_pdev_stats(struct inode *inode, struct file *file)
1429{
1430 kfree(file->private_data);
1431
1432 return 0;
1433}
1434
1435static ssize_t ath12k_read_pdev_stats(struct file *file,
1436 char __user *user_buf,
1437 size_t count, loff_t *ppos)
1438{
1439 const char *buf = file->private_data;
1440 size_t len = strlen(buf);
1441
1442 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1443}
1444
1445static const struct file_operations fops_pdev_stats = {
1446 .open = ath12k_open_pdev_stats,
1447 .release = ath12k_release_pdev_stats,
1448 .read = ath12k_read_pdev_stats,
1449 .owner = THIS_MODULE,
1450 .llseek = default_llseek,
1451};
1452
1453static
1454void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
1455{
1456 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1457 ar->debug.debugfs_pdev);
1458
1459 /* all stats debugfs files created are under "fw_stats" directory
1460 * created per PDEV
1461 */
1462 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1463 &fops_vdev_stats);
1464 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1465 &fops_bcn_stats);
1466 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1467 &fops_pdev_stats);
1468
1469 ath12k_fw_stats_init(ar);
1470}
1471
1472void ath12k_debugfs_register(struct ath12k *ar)
1473{
1474 struct ath12k_base *ab = ar->ab;
1475 struct ieee80211_hw *hw = ar->ah->hw;
1476 char pdev_name[5];
1477 char buf[100] = {};
1478
1479 scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1480
1481 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1482
1483 /* Create a symlink under ieee80211/phy* */
1484 scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
1485 ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
1486 hw->wiphy->debugfsdir,
1487 buf);
1488
1489 if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
1490 debugfs_create_file("dfs_simulate_radar", 0200,
1491 ar->debug.debugfs_pdev, ar,
1492 &fops_simulate_radar);
1493 }
1494
1495 debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_pdev, ar,
1496 &fops_tpc_stats);
1497 debugfs_create_file("tpc_stats_type", 0200, ar->debug.debugfs_pdev,
1498 ar, &fops_tpc_stats_type);
1499 init_completion(&ar->debug.tpc_complete);
1500
1501 ath12k_debugfs_htt_stats_register(ar);
1502 ath12k_debugfs_fw_stats_register(ar);
1503
1504 debugfs_create_file("ext_rx_stats", 0644,
1505 ar->debug.debugfs_pdev, ar,
1506 &fops_extd_rx_stats);
1507}
1508
1509void ath12k_debugfs_unregister(struct ath12k *ar)
1510{
1511 if (!ar->debug.debugfs_pdev)
1512 return;
1513
1514 /* Remove symlink under ieee80211/phy* */
1515 debugfs_remove(ar->debug.debugfs_pdev_symlink);
1516 debugfs_remove_recursive(ar->debug.debugfs_pdev);
1517 ar->debug.debugfs_pdev_symlink = NULL;
1518 ar->debug.debugfs_pdev = NULL;
1519}