1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
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
ath12k_write_simulate_radar(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)13 static 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;
26 exit:
27 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
28 return ret;
29 }
30
31 static const struct file_operations fops_simulate_radar = {
32 .write = ath12k_write_simulate_radar,
33 .open = simple_open
34 };
35
ath12k_write_tpc_stats_type(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)36 static ssize_t ath12k_write_tpc_stats_type(struct file *file,
37 const char __user *user_buf,
38 size_t count, loff_t *ppos)
39 {
40 struct ath12k *ar = file->private_data;
41 u8 type;
42 int ret;
43
44 ret = kstrtou8_from_user(user_buf, count, 0, &type);
45 if (ret)
46 return ret;
47
48 if (type >= WMI_HALPHY_PDEV_TX_STATS_MAX)
49 return -EINVAL;
50
51 spin_lock_bh(&ar->data_lock);
52 ar->debug.tpc_stats_type = type;
53 spin_unlock_bh(&ar->data_lock);
54
55 return count;
56 }
57
ath12k_debug_tpc_stats_request(struct ath12k * ar)58 static int ath12k_debug_tpc_stats_request(struct ath12k *ar)
59 {
60 enum wmi_halphy_ctrl_path_stats_id tpc_stats_sub_id;
61 struct ath12k_base *ab = ar->ab;
62 int ret;
63
64 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
65
66 reinit_completion(&ar->debug.tpc_complete);
67
68 spin_lock_bh(&ar->data_lock);
69 ar->debug.tpc_request = true;
70 tpc_stats_sub_id = ar->debug.tpc_stats_type;
71 spin_unlock_bh(&ar->data_lock);
72
73 ret = ath12k_wmi_send_tpc_stats_request(ar, tpc_stats_sub_id);
74 if (ret) {
75 ath12k_warn(ab, "failed to request pdev tpc stats: %d\n", ret);
76 spin_lock_bh(&ar->data_lock);
77 ar->debug.tpc_request = false;
78 spin_unlock_bh(&ar->data_lock);
79 return ret;
80 }
81
82 return 0;
83 }
84
ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg * tpc_stats,enum wmi_tpc_pream_bw pream_bw,int * mode_idx)85 static int ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg *tpc_stats,
86 enum wmi_tpc_pream_bw pream_bw, int *mode_idx)
87 {
88 u32 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
89 u8 band;
90
91 band = ((chan_freq > ATH12K_MIN_6G_FREQ) ? NL80211_BAND_6GHZ :
92 ((chan_freq > ATH12K_MIN_5G_FREQ) ? NL80211_BAND_5GHZ :
93 NL80211_BAND_2GHZ));
94
95 if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
96 switch (pream_bw) {
97 case WMI_TPC_PREAM_HT20:
98 case WMI_TPC_PREAM_VHT20:
99 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT20_5GHZ_6GHZ;
100 break;
101 case WMI_TPC_PREAM_HE20:
102 case WMI_TPC_PREAM_EHT20:
103 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT20_5GHZ_6GHZ;
104 break;
105 case WMI_TPC_PREAM_HT40:
106 case WMI_TPC_PREAM_VHT40:
107 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT40_5GHZ_6GHZ;
108 break;
109 case WMI_TPC_PREAM_HE40:
110 case WMI_TPC_PREAM_EHT40:
111 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT40_5GHZ_6GHZ;
112 break;
113 case WMI_TPC_PREAM_VHT80:
114 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT80_5GHZ_6GHZ;
115 break;
116 case WMI_TPC_PREAM_EHT60:
117 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT80_SU_PUNC20;
118 break;
119 case WMI_TPC_PREAM_HE80:
120 case WMI_TPC_PREAM_EHT80:
121 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT80_5GHZ_6GHZ;
122 break;
123 case WMI_TPC_PREAM_VHT160:
124 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT160_5GHZ_6GHZ;
125 break;
126 case WMI_TPC_PREAM_EHT120:
127 case WMI_TPC_PREAM_EHT140:
128 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT160_SU_PUNC20;
129 break;
130 case WMI_TPC_PREAM_HE160:
131 case WMI_TPC_PREAM_EHT160:
132 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT160_5GHZ_6GHZ;
133 break;
134 case WMI_TPC_PREAM_EHT200:
135 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC120;
136 break;
137 case WMI_TPC_PREAM_EHT240:
138 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC80;
139 break;
140 case WMI_TPC_PREAM_EHT280:
141 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC40;
142 break;
143 case WMI_TPC_PREAM_EHT320:
144 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT320_5GHZ_6GHZ;
145 break;
146 default:
147 /* for 5GHZ and 6GHZ, default case will be for OFDM */
148 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_5GHZ_6GHZ;
149 break;
150 }
151 } else {
152 switch (pream_bw) {
153 case WMI_TPC_PREAM_OFDM:
154 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_2GHZ;
155 break;
156 case WMI_TPC_PREAM_HT20:
157 case WMI_TPC_PREAM_VHT20:
158 case WMI_TPC_PREAM_HE20:
159 case WMI_TPC_PREAM_EHT20:
160 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT20_2GHZ;
161 break;
162 case WMI_TPC_PREAM_HT40:
163 case WMI_TPC_PREAM_VHT40:
164 case WMI_TPC_PREAM_HE40:
165 case WMI_TPC_PREAM_EHT40:
166 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT40_2GHZ;
167 break;
168 default:
169 /* for 2GHZ, default case will be CCK */
170 *mode_idx = ATH12K_TPC_STATS_CTL_MODE_CCK_2GHZ;
171 break;
172 }
173 }
174
175 return 0;
176 }
177
ath12k_tpc_get_rate(struct ath12k * ar,struct wmi_tpc_stats_arg * tpc_stats,u32 rate_idx,u32 num_chains,u32 rate_code,enum wmi_tpc_pream_bw pream_bw,enum wmi_halphy_ctrl_path_stats_id type,u32 eht_rate_idx)178 static s16 ath12k_tpc_get_rate(struct ath12k *ar,
179 struct wmi_tpc_stats_arg *tpc_stats,
180 u32 rate_idx, u32 num_chains, u32 rate_code,
181 enum wmi_tpc_pream_bw pream_bw,
182 enum wmi_halphy_ctrl_path_stats_id type,
183 u32 eht_rate_idx)
184 {
185 u32 tot_nss, tot_modes, txbf_on_off, index_offset1, index_offset2, index_offset3;
186 u8 chain_idx, stm_idx, num_streams;
187 bool is_mu, txbf_enabled = 0;
188 s8 rates_ctl_min, tpc_ctl;
189 s16 rates, tpc, reg_pwr;
190 u16 rate1, rate2;
191 int mode, ret;
192
193 num_streams = 1 + ATH12K_HW_NSS(rate_code);
194 chain_idx = num_chains - 1;
195 stm_idx = num_streams - 1;
196 mode = -1;
197
198 ret = ath12k_get_tpc_ctl_mode_idx(tpc_stats, pream_bw, &mode);
199 if (ret) {
200 ath12k_warn(ar->ab, "Invalid mode index received\n");
201 tpc = TPC_INVAL;
202 goto out;
203 }
204
205 if (num_chains < num_streams) {
206 tpc = TPC_INVAL;
207 goto out;
208 }
209
210 if (le32_to_cpu(tpc_stats->tpc_config.num_tx_chain) <= 1) {
211 tpc = TPC_INVAL;
212 goto out;
213 }
214
215 if (type == WMI_HALPHY_PDEV_TX_SUTXBF_STATS ||
216 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS)
217 txbf_enabled = 1;
218
219 if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
220 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
221 is_mu = true;
222 } else {
223 is_mu = false;
224 }
225
226 /* Below is the min calculation of ctl array, rates array and
227 * regulator power table. tpc is minimum of all 3
228 */
229 if (pream_bw >= WMI_TPC_PREAM_EHT20 && pream_bw <= WMI_TPC_PREAM_EHT320) {
230 rate2 = tpc_stats->rates_array2.rate_array[eht_rate_idx];
231 if (is_mu)
232 rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_MU);
233 else
234 rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_SU);
235 } else {
236 rate1 = tpc_stats->rates_array1.rate_array[rate_idx];
237 if (is_mu)
238 rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_MU);
239 else
240 rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_SU);
241 }
242
243 if (tpc_stats->tlvs_rcvd & WMI_TPC_CTL_PWR_ARRAY) {
244 tot_nss = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d1);
245 tot_modes = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d2);
246 txbf_on_off = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d3);
247 index_offset1 = txbf_on_off * tot_modes * tot_nss;
248 index_offset2 = tot_modes * tot_nss;
249 index_offset3 = tot_nss;
250
251 tpc_ctl = *(tpc_stats->ctl_array.ctl_pwr_table +
252 chain_idx * index_offset1 + txbf_enabled * index_offset2
253 + mode * index_offset3 + stm_idx);
254 } else {
255 tpc_ctl = TPC_MAX;
256 ath12k_warn(ar->ab,
257 "ctl array for tpc stats not received from fw\n");
258 }
259
260 rates_ctl_min = min_t(s16, rates, tpc_ctl);
261
262 reg_pwr = tpc_stats->max_reg_allowed_power.reg_pwr_array[chain_idx];
263
264 if (reg_pwr < 0)
265 reg_pwr = TPC_INVAL;
266
267 tpc = min_t(s16, rates_ctl_min, reg_pwr);
268
269 /* MODULATION_LIMIT is the maximum power limit,tpc should not exceed
270 * modulation limit even if min tpc of all three array is greater
271 * modulation limit
272 */
273 tpc = min_t(s16, tpc, MODULATION_LIMIT);
274
275 out:
276 return tpc;
277 }
278
ath12k_get_ratecode(u16 pream_idx,u16 nss,u16 mcs_rate)279 static u16 ath12k_get_ratecode(u16 pream_idx, u16 nss, u16 mcs_rate)
280 {
281 u16 mode_type = ~0;
282
283 /* Below assignments are just for printing purpose only */
284 switch (pream_idx) {
285 case WMI_TPC_PREAM_CCK:
286 mode_type = WMI_RATE_PREAMBLE_CCK;
287 break;
288 case WMI_TPC_PREAM_OFDM:
289 mode_type = WMI_RATE_PREAMBLE_OFDM;
290 break;
291 case WMI_TPC_PREAM_HT20:
292 case WMI_TPC_PREAM_HT40:
293 mode_type = WMI_RATE_PREAMBLE_HT;
294 break;
295 case WMI_TPC_PREAM_VHT20:
296 case WMI_TPC_PREAM_VHT40:
297 case WMI_TPC_PREAM_VHT80:
298 case WMI_TPC_PREAM_VHT160:
299 mode_type = WMI_RATE_PREAMBLE_VHT;
300 break;
301 case WMI_TPC_PREAM_HE20:
302 case WMI_TPC_PREAM_HE40:
303 case WMI_TPC_PREAM_HE80:
304 case WMI_TPC_PREAM_HE160:
305 mode_type = WMI_RATE_PREAMBLE_HE;
306 break;
307 case WMI_TPC_PREAM_EHT20:
308 case WMI_TPC_PREAM_EHT40:
309 case WMI_TPC_PREAM_EHT60:
310 case WMI_TPC_PREAM_EHT80:
311 case WMI_TPC_PREAM_EHT120:
312 case WMI_TPC_PREAM_EHT140:
313 case WMI_TPC_PREAM_EHT160:
314 case WMI_TPC_PREAM_EHT200:
315 case WMI_TPC_PREAM_EHT240:
316 case WMI_TPC_PREAM_EHT280:
317 case WMI_TPC_PREAM_EHT320:
318 mode_type = WMI_RATE_PREAMBLE_EHT;
319 if (mcs_rate == 0 || mcs_rate == 1)
320 mcs_rate += 14;
321 else
322 mcs_rate -= 2;
323 break;
324 default:
325 return mode_type;
326 }
327 return ((mode_type << 8) | ((nss & 0x7) << 5) | (mcs_rate & 0x1F));
328 }
329
ath12k_he_supports_extra_mcs(struct ath12k * ar,int freq)330 static bool ath12k_he_supports_extra_mcs(struct ath12k *ar, int freq)
331 {
332 struct ath12k_pdev_cap *cap = &ar->pdev->cap;
333 struct ath12k_band_cap *cap_band;
334 bool extra_mcs_supported;
335
336 if (freq <= ATH12K_2GHZ_MAX_FREQUENCY)
337 cap_band = &cap->band[NL80211_BAND_2GHZ];
338 else if (freq <= ATH12K_5GHZ_MAX_FREQUENCY)
339 cap_band = &cap->band[NL80211_BAND_5GHZ];
340 else
341 cap_band = &cap->band[NL80211_BAND_6GHZ];
342
343 extra_mcs_supported = u32_get_bits(cap_band->he_cap_info[1],
344 HE_EXTRA_MCS_SUPPORT);
345 return extra_mcs_supported;
346 }
347
ath12k_tpc_fill_pream(struct ath12k * ar,char * buf,int buf_len,int len,enum wmi_tpc_pream_bw pream_bw,u32 max_rix,int max_nss,int max_rates,int pream_type,enum wmi_halphy_ctrl_path_stats_id tpc_type,int rate_idx,int eht_rate_idx)348 static int ath12k_tpc_fill_pream(struct ath12k *ar, char *buf, int buf_len, int len,
349 enum wmi_tpc_pream_bw pream_bw, u32 max_rix,
350 int max_nss, int max_rates, int pream_type,
351 enum wmi_halphy_ctrl_path_stats_id tpc_type,
352 int rate_idx, int eht_rate_idx)
353 {
354 struct wmi_tpc_stats_arg *tpc_stats = ar->debug.tpc_stats;
355 int nss, rates, chains;
356 u8 active_tx_chains;
357 u16 rate_code;
358 s16 tpc;
359
360 static const char *const pream_str[] = {
361 [WMI_TPC_PREAM_CCK] = "CCK",
362 [WMI_TPC_PREAM_OFDM] = "OFDM",
363 [WMI_TPC_PREAM_HT20] = "HT20",
364 [WMI_TPC_PREAM_HT40] = "HT40",
365 [WMI_TPC_PREAM_VHT20] = "VHT20",
366 [WMI_TPC_PREAM_VHT40] = "VHT40",
367 [WMI_TPC_PREAM_VHT80] = "VHT80",
368 [WMI_TPC_PREAM_VHT160] = "VHT160",
369 [WMI_TPC_PREAM_HE20] = "HE20",
370 [WMI_TPC_PREAM_HE40] = "HE40",
371 [WMI_TPC_PREAM_HE80] = "HE80",
372 [WMI_TPC_PREAM_HE160] = "HE160",
373 [WMI_TPC_PREAM_EHT20] = "EHT20",
374 [WMI_TPC_PREAM_EHT40] = "EHT40",
375 [WMI_TPC_PREAM_EHT60] = "EHT60",
376 [WMI_TPC_PREAM_EHT80] = "EHT80",
377 [WMI_TPC_PREAM_EHT120] = "EHT120",
378 [WMI_TPC_PREAM_EHT140] = "EHT140",
379 [WMI_TPC_PREAM_EHT160] = "EHT160",
380 [WMI_TPC_PREAM_EHT200] = "EHT200",
381 [WMI_TPC_PREAM_EHT240] = "EHT240",
382 [WMI_TPC_PREAM_EHT280] = "EHT280",
383 [WMI_TPC_PREAM_EHT320] = "EHT320"};
384
385 active_tx_chains = ar->num_tx_chains;
386
387 for (nss = 0; nss < max_nss; nss++) {
388 for (rates = 0; rates < max_rates; rates++, rate_idx++, max_rix++) {
389 /* FW send extra MCS(10&11) for VHT and HE rates,
390 * this is not used. Hence skipping it here
391 */
392 if (pream_type == WMI_RATE_PREAMBLE_VHT &&
393 rates > ATH12K_VHT_MCS_MAX)
394 continue;
395
396 if (pream_type == WMI_RATE_PREAMBLE_HE &&
397 rates > ATH12K_HE_MCS_MAX)
398 continue;
399
400 if (pream_type == WMI_RATE_PREAMBLE_EHT &&
401 rates > ATH12K_EHT_MCS_MAX)
402 continue;
403
404 rate_code = ath12k_get_ratecode(pream_bw, nss, rates);
405 len += scnprintf(buf + len, buf_len - len,
406 "%d\t %s\t 0x%03x\t", max_rix,
407 pream_str[pream_bw], rate_code);
408
409 for (chains = 0; chains < active_tx_chains; chains++) {
410 if (nss > chains) {
411 len += scnprintf(buf + len,
412 buf_len - len,
413 "\t%s", "NA");
414 } else {
415 tpc = ath12k_tpc_get_rate(ar, tpc_stats,
416 rate_idx, chains + 1,
417 rate_code, pream_bw,
418 tpc_type,
419 eht_rate_idx);
420
421 if (tpc == TPC_INVAL) {
422 len += scnprintf(buf + len,
423 buf_len - len, "\tNA");
424 } else {
425 len += scnprintf(buf + len,
426 buf_len - len, "\t%d",
427 tpc);
428 }
429 }
430 }
431 len += scnprintf(buf + len, buf_len - len, "\n");
432
433 if (pream_type == WMI_RATE_PREAMBLE_EHT)
434 /*For fetching the next eht rates pwr from rates array2*/
435 ++eht_rate_idx;
436 }
437 }
438
439 return len;
440 }
441
ath12k_tpc_stats_print(struct ath12k * ar,struct wmi_tpc_stats_arg * tpc_stats,char * buf,size_t len,enum wmi_halphy_ctrl_path_stats_id type)442 static int ath12k_tpc_stats_print(struct ath12k *ar,
443 struct wmi_tpc_stats_arg *tpc_stats,
444 char *buf, size_t len,
445 enum wmi_halphy_ctrl_path_stats_id type)
446 {
447 u32 eht_idx = 0, pream_idx = 0, rate_pream_idx = 0, total_rates = 0, max_rix = 0;
448 u32 chan_freq, num_tx_chain, caps, i, j = 1;
449 size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
450 u8 nss, active_tx_chains;
451 bool he_ext_mcs;
452 static const char *const type_str[WMI_HALPHY_PDEV_TX_STATS_MAX] = {
453 [WMI_HALPHY_PDEV_TX_SU_STATS] = "SU",
454 [WMI_HALPHY_PDEV_TX_SUTXBF_STATS] = "SU WITH TXBF",
455 [WMI_HALPHY_PDEV_TX_MU_STATS] = "MU",
456 [WMI_HALPHY_PDEV_TX_MUTXBF_STATS] = "MU WITH TXBF"};
457
458 u8 max_rates[WMI_TPC_PREAM_MAX] = {
459 [WMI_TPC_PREAM_CCK] = ATH12K_CCK_RATES,
460 [WMI_TPC_PREAM_OFDM] = ATH12K_OFDM_RATES,
461 [WMI_TPC_PREAM_HT20] = ATH12K_HT_RATES,
462 [WMI_TPC_PREAM_HT40] = ATH12K_HT_RATES,
463 [WMI_TPC_PREAM_VHT20] = ATH12K_VHT_RATES,
464 [WMI_TPC_PREAM_VHT40] = ATH12K_VHT_RATES,
465 [WMI_TPC_PREAM_VHT80] = ATH12K_VHT_RATES,
466 [WMI_TPC_PREAM_VHT160] = ATH12K_VHT_RATES,
467 [WMI_TPC_PREAM_HE20] = ATH12K_HE_RATES,
468 [WMI_TPC_PREAM_HE40] = ATH12K_HE_RATES,
469 [WMI_TPC_PREAM_HE80] = ATH12K_HE_RATES,
470 [WMI_TPC_PREAM_HE160] = ATH12K_HE_RATES,
471 [WMI_TPC_PREAM_EHT20] = ATH12K_EHT_RATES,
472 [WMI_TPC_PREAM_EHT40] = ATH12K_EHT_RATES,
473 [WMI_TPC_PREAM_EHT60] = ATH12K_EHT_RATES,
474 [WMI_TPC_PREAM_EHT80] = ATH12K_EHT_RATES,
475 [WMI_TPC_PREAM_EHT120] = ATH12K_EHT_RATES,
476 [WMI_TPC_PREAM_EHT140] = ATH12K_EHT_RATES,
477 [WMI_TPC_PREAM_EHT160] = ATH12K_EHT_RATES,
478 [WMI_TPC_PREAM_EHT200] = ATH12K_EHT_RATES,
479 [WMI_TPC_PREAM_EHT240] = ATH12K_EHT_RATES,
480 [WMI_TPC_PREAM_EHT280] = ATH12K_EHT_RATES,
481 [WMI_TPC_PREAM_EHT320] = ATH12K_EHT_RATES};
482 static const u8 max_nss[WMI_TPC_PREAM_MAX] = {
483 [WMI_TPC_PREAM_CCK] = ATH12K_NSS_1,
484 [WMI_TPC_PREAM_OFDM] = ATH12K_NSS_1,
485 [WMI_TPC_PREAM_HT20] = ATH12K_NSS_4,
486 [WMI_TPC_PREAM_HT40] = ATH12K_NSS_4,
487 [WMI_TPC_PREAM_VHT20] = ATH12K_NSS_8,
488 [WMI_TPC_PREAM_VHT40] = ATH12K_NSS_8,
489 [WMI_TPC_PREAM_VHT80] = ATH12K_NSS_8,
490 [WMI_TPC_PREAM_VHT160] = ATH12K_NSS_4,
491 [WMI_TPC_PREAM_HE20] = ATH12K_NSS_8,
492 [WMI_TPC_PREAM_HE40] = ATH12K_NSS_8,
493 [WMI_TPC_PREAM_HE80] = ATH12K_NSS_8,
494 [WMI_TPC_PREAM_HE160] = ATH12K_NSS_4,
495 [WMI_TPC_PREAM_EHT20] = ATH12K_NSS_4,
496 [WMI_TPC_PREAM_EHT40] = ATH12K_NSS_4,
497 [WMI_TPC_PREAM_EHT60] = ATH12K_NSS_4,
498 [WMI_TPC_PREAM_EHT80] = ATH12K_NSS_4,
499 [WMI_TPC_PREAM_EHT120] = ATH12K_NSS_4,
500 [WMI_TPC_PREAM_EHT140] = ATH12K_NSS_4,
501 [WMI_TPC_PREAM_EHT160] = ATH12K_NSS_4,
502 [WMI_TPC_PREAM_EHT200] = ATH12K_NSS_4,
503 [WMI_TPC_PREAM_EHT240] = ATH12K_NSS_4,
504 [WMI_TPC_PREAM_EHT280] = ATH12K_NSS_4,
505 [WMI_TPC_PREAM_EHT320] = ATH12K_NSS_4};
506
507 u16 rate_idx[WMI_TPC_PREAM_MAX] = {}, eht_rate_idx[WMI_TPC_PREAM_MAX] = {};
508 static const u8 pream_type[WMI_TPC_PREAM_MAX] = {
509 [WMI_TPC_PREAM_CCK] = WMI_RATE_PREAMBLE_CCK,
510 [WMI_TPC_PREAM_OFDM] = WMI_RATE_PREAMBLE_OFDM,
511 [WMI_TPC_PREAM_HT20] = WMI_RATE_PREAMBLE_HT,
512 [WMI_TPC_PREAM_HT40] = WMI_RATE_PREAMBLE_HT,
513 [WMI_TPC_PREAM_VHT20] = WMI_RATE_PREAMBLE_VHT,
514 [WMI_TPC_PREAM_VHT40] = WMI_RATE_PREAMBLE_VHT,
515 [WMI_TPC_PREAM_VHT80] = WMI_RATE_PREAMBLE_VHT,
516 [WMI_TPC_PREAM_VHT160] = WMI_RATE_PREAMBLE_VHT,
517 [WMI_TPC_PREAM_HE20] = WMI_RATE_PREAMBLE_HE,
518 [WMI_TPC_PREAM_HE40] = WMI_RATE_PREAMBLE_HE,
519 [WMI_TPC_PREAM_HE80] = WMI_RATE_PREAMBLE_HE,
520 [WMI_TPC_PREAM_HE160] = WMI_RATE_PREAMBLE_HE,
521 [WMI_TPC_PREAM_EHT20] = WMI_RATE_PREAMBLE_EHT,
522 [WMI_TPC_PREAM_EHT40] = WMI_RATE_PREAMBLE_EHT,
523 [WMI_TPC_PREAM_EHT60] = WMI_RATE_PREAMBLE_EHT,
524 [WMI_TPC_PREAM_EHT80] = WMI_RATE_PREAMBLE_EHT,
525 [WMI_TPC_PREAM_EHT120] = WMI_RATE_PREAMBLE_EHT,
526 [WMI_TPC_PREAM_EHT140] = WMI_RATE_PREAMBLE_EHT,
527 [WMI_TPC_PREAM_EHT160] = WMI_RATE_PREAMBLE_EHT,
528 [WMI_TPC_PREAM_EHT200] = WMI_RATE_PREAMBLE_EHT,
529 [WMI_TPC_PREAM_EHT240] = WMI_RATE_PREAMBLE_EHT,
530 [WMI_TPC_PREAM_EHT280] = WMI_RATE_PREAMBLE_EHT,
531 [WMI_TPC_PREAM_EHT320] = WMI_RATE_PREAMBLE_EHT};
532
533 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
534 num_tx_chain = le32_to_cpu(tpc_stats->tpc_config.num_tx_chain);
535 caps = le32_to_cpu(tpc_stats->tpc_config.caps);
536
537 active_tx_chains = ar->num_tx_chains;
538 he_ext_mcs = ath12k_he_supports_extra_mcs(ar, chan_freq);
539
540 /* mcs 12&13 is sent by FW for certain HWs in rate array, skipping it as
541 * it is not supported
542 */
543 if (he_ext_mcs) {
544 for (i = WMI_TPC_PREAM_HE20; i <= WMI_TPC_PREAM_HE160; ++i)
545 max_rates[i] = ATH12K_HE_RATES;
546 }
547
548 if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
549 type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
550 pream_idx = WMI_TPC_PREAM_VHT20;
551
552 for (i = WMI_TPC_PREAM_CCK; i <= WMI_TPC_PREAM_HT40; ++i)
553 max_rix += max_nss[i] * max_rates[i];
554 }
555 /* Enumerate all the rate indices */
556 for (i = rate_pream_idx + 1; i < WMI_TPC_PREAM_MAX; i++) {
557 nss = (max_nss[i - 1] < num_tx_chain ?
558 max_nss[i - 1] : num_tx_chain);
559
560 rate_idx[i] = rate_idx[i - 1] + max_rates[i - 1] * nss;
561
562 if (pream_type[i] == WMI_RATE_PREAMBLE_EHT) {
563 eht_rate_idx[j] = eht_rate_idx[j - 1] + max_rates[i] * nss;
564 ++j;
565 }
566 }
567
568 for (i = 0; i < WMI_TPC_PREAM_MAX; i++) {
569 nss = (max_nss[i] < num_tx_chain ?
570 max_nss[i] : num_tx_chain);
571 total_rates += max_rates[i] * nss;
572 }
573
574 len += scnprintf(buf + len, buf_len - len,
575 "No.of rates-%d\n", total_rates);
576
577 len += scnprintf(buf + len, buf_len - len,
578 "**************** %s ****************\n",
579 type_str[type]);
580 len += scnprintf(buf + len, buf_len - len,
581 "\t\t\t\tTPC values for Active chains\n");
582 len += scnprintf(buf + len, buf_len - len,
583 "Rate idx Preamble Rate code");
584
585 for (i = 1; i <= active_tx_chains; ++i) {
586 len += scnprintf(buf + len, buf_len - len,
587 "\t%d-Chain", i);
588 }
589
590 len += scnprintf(buf + len, buf_len - len, "\n");
591 for (i = pream_idx; i < WMI_TPC_PREAM_MAX; i++) {
592 if (chan_freq <= 2483) {
593 if (i == WMI_TPC_PREAM_VHT80 ||
594 i == WMI_TPC_PREAM_VHT160 ||
595 i == WMI_TPC_PREAM_HE80 ||
596 i == WMI_TPC_PREAM_HE160 ||
597 (i >= WMI_TPC_PREAM_EHT60 &&
598 i <= WMI_TPC_PREAM_EHT320)) {
599 max_rix += max_nss[i] * max_rates[i];
600 continue;
601 }
602 } else {
603 if (i == WMI_TPC_PREAM_CCK) {
604 max_rix += max_rates[i];
605 continue;
606 }
607 }
608
609 nss = (max_nss[i] < ar->num_tx_chains ? max_nss[i] : ar->num_tx_chains);
610
611 if (!(caps &
612 (1 << ATH12K_TPC_STATS_SUPPORT_BE_PUNC))) {
613 if (i == WMI_TPC_PREAM_EHT60 || i == WMI_TPC_PREAM_EHT120 ||
614 i == WMI_TPC_PREAM_EHT140 || i == WMI_TPC_PREAM_EHT200 ||
615 i == WMI_TPC_PREAM_EHT240 || i == WMI_TPC_PREAM_EHT280) {
616 max_rix += max_nss[i] * max_rates[i];
617 continue;
618 }
619 }
620
621 len = ath12k_tpc_fill_pream(ar, buf, buf_len, len, i, max_rix, nss,
622 max_rates[i], pream_type[i],
623 type, rate_idx[i], eht_rate_idx[eht_idx]);
624
625 if (pream_type[i] == WMI_RATE_PREAMBLE_EHT)
626 /*For fetch the next index eht rates from rates array2*/
627 ++eht_idx;
628
629 max_rix += max_nss[i] * max_rates[i];
630 }
631 return len;
632 }
633
ath12k_tpc_stats_fill(struct ath12k * ar,struct wmi_tpc_stats_arg * tpc_stats,char * buf)634 static void ath12k_tpc_stats_fill(struct ath12k *ar,
635 struct wmi_tpc_stats_arg *tpc_stats,
636 char *buf)
637 {
638 size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
639 struct wmi_tpc_config_params *tpc;
640 size_t len = 0;
641
642 if (!tpc_stats) {
643 ath12k_warn(ar->ab, "failed to find tpc stats\n");
644 return;
645 }
646
647 spin_lock_bh(&ar->data_lock);
648
649 tpc = &tpc_stats->tpc_config;
650 len += scnprintf(buf + len, buf_len - len, "\n");
651 len += scnprintf(buf + len, buf_len - len,
652 "*************** TPC config **************\n");
653 len += scnprintf(buf + len, buf_len - len,
654 "* powers are in 0.25 dBm steps\n");
655 len += scnprintf(buf + len, buf_len - len,
656 "reg domain-%d\t\tchan freq-%d\n",
657 tpc->reg_domain, tpc->chan_freq);
658 len += scnprintf(buf + len, buf_len - len,
659 "power limit-%d\t\tmax reg-domain Power-%d\n",
660 le32_to_cpu(tpc->twice_max_reg_power) / 2, tpc->power_limit);
661 len += scnprintf(buf + len, buf_len - len,
662 "No.of tx chain-%d\t",
663 ar->num_tx_chains);
664
665 ath12k_tpc_stats_print(ar, tpc_stats, buf, len,
666 ar->debug.tpc_stats_type);
667
668 spin_unlock_bh(&ar->data_lock);
669 }
670
ath12k_open_tpc_stats(struct inode * inode,struct file * file)671 static int ath12k_open_tpc_stats(struct inode *inode, struct file *file)
672 {
673 struct ath12k *ar = inode->i_private;
674 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
675 int ret;
676
677 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
678
679 if (ah->state != ATH12K_HW_STATE_ON) {
680 ath12k_warn(ar->ab, "Interface not up\n");
681 return -ENETDOWN;
682 }
683
684 void *buf __free(kfree) = kzalloc(ATH12K_TPC_STATS_BUF_SIZE, GFP_KERNEL);
685 if (!buf)
686 return -ENOMEM;
687
688 ret = ath12k_debug_tpc_stats_request(ar);
689 if (ret) {
690 ath12k_warn(ar->ab, "failed to request tpc stats: %d\n",
691 ret);
692 return ret;
693 }
694
695 if (!wait_for_completion_timeout(&ar->debug.tpc_complete, TPC_STATS_WAIT_TIME)) {
696 spin_lock_bh(&ar->data_lock);
697 ath12k_wmi_free_tpc_stats_mem(ar);
698 ar->debug.tpc_request = false;
699 spin_unlock_bh(&ar->data_lock);
700 return -ETIMEDOUT;
701 }
702
703 ath12k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
704 file->private_data = no_free_ptr(buf);
705
706 spin_lock_bh(&ar->data_lock);
707 ath12k_wmi_free_tpc_stats_mem(ar);
708 spin_unlock_bh(&ar->data_lock);
709
710 return 0;
711 }
712
ath12k_read_tpc_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)713 static ssize_t ath12k_read_tpc_stats(struct file *file,
714 char __user *user_buf,
715 size_t count, loff_t *ppos)
716 {
717 const char *buf = file->private_data;
718 size_t len = strlen(buf);
719
720 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
721 }
722
ath12k_release_tpc_stats(struct inode * inode,struct file * file)723 static int ath12k_release_tpc_stats(struct inode *inode,
724 struct file *file)
725 {
726 kfree(file->private_data);
727 return 0;
728 }
729
730 static const struct file_operations fops_tpc_stats = {
731 .open = ath12k_open_tpc_stats,
732 .release = ath12k_release_tpc_stats,
733 .read = ath12k_read_tpc_stats,
734 .owner = THIS_MODULE,
735 .llseek = default_llseek,
736 };
737
738 static const struct file_operations fops_tpc_stats_type = {
739 .write = ath12k_write_tpc_stats_type,
740 .open = simple_open,
741 .llseek = default_llseek,
742 };
743
ath12k_write_extd_rx_stats(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)744 static ssize_t ath12k_write_extd_rx_stats(struct file *file,
745 const char __user *ubuf,
746 size_t count, loff_t *ppos)
747 {
748 struct ath12k *ar = file->private_data;
749 struct htt_rx_ring_tlv_filter tlv_filter = {0};
750 u32 ring_id, rx_filter = 0;
751 bool enable;
752 int ret, i;
753
754 if (kstrtobool_from_user(ubuf, count, &enable))
755 return -EINVAL;
756
757 wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
758
759 if (!ar->ab->hw_params->rxdma1_enable) {
760 ret = count;
761 goto exit;
762 }
763
764 if (ar->ah->state != ATH12K_HW_STATE_ON) {
765 ret = -ENETDOWN;
766 goto exit;
767 }
768
769 if (enable == ar->debug.extd_rx_stats) {
770 ret = count;
771 goto exit;
772 }
773
774 if (enable) {
775 rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
776 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
777 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
778 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
779 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
780 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
781 rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO;
782
783 tlv_filter.rx_filter = rx_filter;
784 tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
785 tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
786 tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
787 tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
788 HTT_RX_FP_DATA_FILTER_FLASG3;
789 } else {
790 tlv_filter = ath12k_mac_mon_status_filter_default;
791 }
792
793 ar->debug.rx_filter = tlv_filter.rx_filter;
794
795 for (i = 0; i < ar->ab->hw_params->num_rxdma_per_pdev; i++) {
796 ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
797 ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i,
798 HAL_RXDMA_MONITOR_DST,
799 DP_RXDMA_REFILL_RING_SIZE,
800 &tlv_filter);
801 if (ret) {
802 ath12k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
803 goto exit;
804 }
805 }
806
807 ar->debug.extd_rx_stats = !!enable;
808 ret = count;
809 exit:
810 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
811 return ret;
812 }
813
ath12k_read_extd_rx_stats(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)814 static ssize_t ath12k_read_extd_rx_stats(struct file *file,
815 char __user *ubuf,
816 size_t count, loff_t *ppos)
817 {
818 struct ath12k *ar = file->private_data;
819 char buf[32];
820 int len = 0;
821
822 wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
823 len = scnprintf(buf, sizeof(buf) - len, "%d\n",
824 ar->debug.extd_rx_stats);
825 wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
826
827 return simple_read_from_buffer(ubuf, count, ppos, buf, len);
828 }
829
830 static const struct file_operations fops_extd_rx_stats = {
831 .read = ath12k_read_extd_rx_stats,
832 .write = ath12k_write_extd_rx_stats,
833 .open = simple_open,
834 };
835
ath12k_debugfs_soc_create(struct ath12k_base * ab)836 void ath12k_debugfs_soc_create(struct ath12k_base *ab)
837 {
838 bool dput_needed;
839 char soc_name[64] = { 0 };
840 struct dentry *debugfs_ath12k;
841
842 debugfs_ath12k = debugfs_lookup("ath12k", NULL);
843 if (debugfs_ath12k) {
844 /* a dentry from lookup() needs dput() after we don't use it */
845 dput_needed = true;
846 } else {
847 debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
848 if (IS_ERR_OR_NULL(debugfs_ath12k))
849 return;
850 dput_needed = false;
851 }
852
853 scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
854 dev_name(ab->dev));
855
856 ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
857
858 if (dput_needed)
859 dput(debugfs_ath12k);
860 }
861
ath12k_debugfs_soc_destroy(struct ath12k_base * ab)862 void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
863 {
864 debugfs_remove_recursive(ab->debugfs_soc);
865 ab->debugfs_soc = NULL;
866 /* We are not removing ath12k directory on purpose, even if it
867 * would be empty. This simplifies the directory handling and it's
868 * a minor cosmetic issue to leave an empty ath12k directory to
869 * debugfs.
870 */
871 }
872
ath12k_fw_stats_pdevs_free(struct list_head * head)873 static void ath12k_fw_stats_pdevs_free(struct list_head *head)
874 {
875 struct ath12k_fw_stats_pdev *i, *tmp;
876
877 list_for_each_entry_safe(i, tmp, head, list) {
878 list_del(&i->list);
879 kfree(i);
880 }
881 }
882
ath12k_fw_stats_bcn_free(struct list_head * head)883 static void ath12k_fw_stats_bcn_free(struct list_head *head)
884 {
885 struct ath12k_fw_stats_bcn *i, *tmp;
886
887 list_for_each_entry_safe(i, tmp, head, list) {
888 list_del(&i->list);
889 kfree(i);
890 }
891 }
892
ath12k_fw_stats_vdevs_free(struct list_head * head)893 static void ath12k_fw_stats_vdevs_free(struct list_head *head)
894 {
895 struct ath12k_fw_stats_vdev *i, *tmp;
896
897 list_for_each_entry_safe(i, tmp, head, list) {
898 list_del(&i->list);
899 kfree(i);
900 }
901 }
902
ath12k_debugfs_fw_stats_reset(struct ath12k * ar)903 void ath12k_debugfs_fw_stats_reset(struct ath12k *ar)
904 {
905 spin_lock_bh(&ar->data_lock);
906 ar->fw_stats.fw_stats_done = false;
907 ath12k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
908 ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn);
909 ath12k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
910 spin_unlock_bh(&ar->data_lock);
911 }
912
ath12k_debugfs_fw_stats_request(struct ath12k * ar,struct ath12k_fw_stats_req_params * param)913 static int ath12k_debugfs_fw_stats_request(struct ath12k *ar,
914 struct ath12k_fw_stats_req_params *param)
915 {
916 struct ath12k_base *ab = ar->ab;
917 unsigned long timeout, time_left;
918 int ret;
919
920 lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
921
922 /* FW stats can get split when exceeding the stats data buffer limit.
923 * In that case, since there is no end marking for the back-to-back
924 * received 'update stats' event, we keep a 3 seconds timeout in case,
925 * fw_stats_done is not marked yet
926 */
927 timeout = jiffies + msecs_to_jiffies(3 * 1000);
928
929 ath12k_debugfs_fw_stats_reset(ar);
930
931 reinit_completion(&ar->fw_stats_complete);
932
933 ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,
934 param->vdev_id, param->pdev_id);
935
936 if (ret) {
937 ath12k_warn(ab, "could not request fw stats (%d)\n",
938 ret);
939 return ret;
940 }
941
942 time_left = wait_for_completion_timeout(&ar->fw_stats_complete,
943 1 * HZ);
944 /* If the wait timed out, return -ETIMEDOUT */
945 if (!time_left)
946 return -ETIMEDOUT;
947
948 /* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back
949 * when stats data buffer limit is reached. fw_stats_complete
950 * is completed once host receives first event from firmware, but
951 * still end might not be marked in the TLV.
952 * Below loop is to confirm that firmware completed sending all the event
953 * and fw_stats_done is marked true when end is marked in the TLV
954 */
955 for (;;) {
956 if (time_after(jiffies, timeout))
957 break;
958
959 spin_lock_bh(&ar->data_lock);
960 if (ar->fw_stats.fw_stats_done) {
961 spin_unlock_bh(&ar->data_lock);
962 break;
963 }
964 spin_unlock_bh(&ar->data_lock);
965 }
966 return 0;
967 }
968
969 void
ath12k_debugfs_fw_stats_process(struct ath12k * ar,struct ath12k_fw_stats * stats)970 ath12k_debugfs_fw_stats_process(struct ath12k *ar,
971 struct ath12k_fw_stats *stats)
972 {
973 struct ath12k_base *ab = ar->ab;
974 struct ath12k_pdev *pdev;
975 bool is_end;
976 static unsigned int num_vdev, num_bcn;
977 size_t total_vdevs_started = 0;
978 int i;
979
980 if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
981 if (list_empty(&stats->vdevs)) {
982 ath12k_warn(ab, "empty vdev stats");
983 return;
984 }
985 /* FW sends all the active VDEV stats irrespective of PDEV,
986 * hence limit until the count of all VDEVs started
987 */
988 rcu_read_lock();
989 for (i = 0; i < ab->num_radios; i++) {
990 pdev = rcu_dereference(ab->pdevs_active[i]);
991 if (pdev && pdev->ar)
992 total_vdevs_started += pdev->ar->num_started_vdevs;
993 }
994 rcu_read_unlock();
995
996 is_end = ((++num_vdev) == total_vdevs_started);
997
998 list_splice_tail_init(&stats->vdevs,
999 &ar->fw_stats.vdevs);
1000
1001 if (is_end) {
1002 ar->fw_stats.fw_stats_done = true;
1003 num_vdev = 0;
1004 }
1005 return;
1006 }
1007 if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
1008 if (list_empty(&stats->bcn)) {
1009 ath12k_warn(ab, "empty beacon stats");
1010 return;
1011 }
1012 /* Mark end until we reached the count of all started VDEVs
1013 * within the PDEV
1014 */
1015 is_end = ((++num_bcn) == ar->num_started_vdevs);
1016
1017 list_splice_tail_init(&stats->bcn,
1018 &ar->fw_stats.bcn);
1019
1020 if (is_end) {
1021 ar->fw_stats.fw_stats_done = true;
1022 num_bcn = 0;
1023 }
1024 }
1025 if (stats->stats_id == WMI_REQUEST_PDEV_STAT) {
1026 list_splice_tail_init(&stats->pdevs, &ar->fw_stats.pdevs);
1027 ar->fw_stats.fw_stats_done = true;
1028 }
1029 }
1030
ath12k_open_vdev_stats(struct inode * inode,struct file * file)1031 static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
1032 {
1033 struct ath12k *ar = inode->i_private;
1034 struct ath12k_fw_stats_req_params param;
1035 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1036 int ret;
1037
1038 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1039
1040 if (!ah)
1041 return -ENETDOWN;
1042
1043 if (ah->state != ATH12K_HW_STATE_ON)
1044 return -ENETDOWN;
1045
1046 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1047 if (!buf)
1048 return -ENOMEM;
1049
1050 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1051 /* VDEV stats is always sent for all active VDEVs from FW */
1052 param.vdev_id = 0;
1053 param.stats_id = WMI_REQUEST_VDEV_STAT;
1054
1055 ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
1056 if (ret) {
1057 ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
1058 return ret;
1059 }
1060
1061 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1062 buf);
1063
1064 file->private_data = no_free_ptr(buf);
1065
1066 return 0;
1067 }
1068
ath12k_release_vdev_stats(struct inode * inode,struct file * file)1069 static int ath12k_release_vdev_stats(struct inode *inode, struct file *file)
1070 {
1071 kfree(file->private_data);
1072
1073 return 0;
1074 }
1075
ath12k_read_vdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1076 static ssize_t ath12k_read_vdev_stats(struct file *file,
1077 char __user *user_buf,
1078 size_t count, loff_t *ppos)
1079 {
1080 const char *buf = file->private_data;
1081 size_t len = strlen(buf);
1082
1083 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1084 }
1085
1086 static const struct file_operations fops_vdev_stats = {
1087 .open = ath12k_open_vdev_stats,
1088 .release = ath12k_release_vdev_stats,
1089 .read = ath12k_read_vdev_stats,
1090 .owner = THIS_MODULE,
1091 .llseek = default_llseek,
1092 };
1093
ath12k_open_bcn_stats(struct inode * inode,struct file * file)1094 static int ath12k_open_bcn_stats(struct inode *inode, struct file *file)
1095 {
1096 struct ath12k *ar = inode->i_private;
1097 struct ath12k_link_vif *arvif;
1098 struct ath12k_fw_stats_req_params param;
1099 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1100 int ret;
1101
1102 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1103
1104 if (ah && ah->state != ATH12K_HW_STATE_ON)
1105 return -ENETDOWN;
1106
1107 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1108 if (!buf)
1109 return -ENOMEM;
1110
1111 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1112 param.stats_id = WMI_REQUEST_BCN_STAT;
1113
1114 /* loop all active VDEVs for bcn stats */
1115 list_for_each_entry(arvif, &ar->arvifs, list) {
1116 if (!arvif->is_up)
1117 continue;
1118
1119 param.vdev_id = arvif->vdev_id;
1120 ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
1121 if (ret) {
1122 ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
1123 return ret;
1124 }
1125 }
1126
1127 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1128 buf);
1129 /* since beacon stats request is looped for all active VDEVs, saved fw
1130 * stats is not freed for each request until done for all active VDEVs
1131 */
1132 spin_lock_bh(&ar->data_lock);
1133 ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn);
1134 spin_unlock_bh(&ar->data_lock);
1135
1136 file->private_data = no_free_ptr(buf);
1137
1138 return 0;
1139 }
1140
ath12k_release_bcn_stats(struct inode * inode,struct file * file)1141 static int ath12k_release_bcn_stats(struct inode *inode, struct file *file)
1142 {
1143 kfree(file->private_data);
1144
1145 return 0;
1146 }
1147
ath12k_read_bcn_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1148 static ssize_t ath12k_read_bcn_stats(struct file *file,
1149 char __user *user_buf,
1150 size_t count, loff_t *ppos)
1151 {
1152 const char *buf = file->private_data;
1153 size_t len = strlen(buf);
1154
1155 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1156 }
1157
1158 static const struct file_operations fops_bcn_stats = {
1159 .open = ath12k_open_bcn_stats,
1160 .release = ath12k_release_bcn_stats,
1161 .read = ath12k_read_bcn_stats,
1162 .owner = THIS_MODULE,
1163 .llseek = default_llseek,
1164 };
1165
ath12k_open_pdev_stats(struct inode * inode,struct file * file)1166 static int ath12k_open_pdev_stats(struct inode *inode, struct file *file)
1167 {
1168 struct ath12k *ar = inode->i_private;
1169 struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1170 struct ath12k_base *ab = ar->ab;
1171 struct ath12k_fw_stats_req_params param;
1172 int ret;
1173
1174 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1175
1176 if (ah && ah->state != ATH12K_HW_STATE_ON)
1177 return -ENETDOWN;
1178
1179 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1180 if (!buf)
1181 return -ENOMEM;
1182
1183 param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1184 param.vdev_id = 0;
1185 param.stats_id = WMI_REQUEST_PDEV_STAT;
1186
1187 ret = ath12k_debugfs_fw_stats_request(ar, ¶m);
1188 if (ret) {
1189 ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
1190 return ret;
1191 }
1192
1193 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1194 buf);
1195
1196 file->private_data = no_free_ptr(buf);
1197
1198 return 0;
1199 }
1200
ath12k_release_pdev_stats(struct inode * inode,struct file * file)1201 static int ath12k_release_pdev_stats(struct inode *inode, struct file *file)
1202 {
1203 kfree(file->private_data);
1204
1205 return 0;
1206 }
1207
ath12k_read_pdev_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1208 static ssize_t ath12k_read_pdev_stats(struct file *file,
1209 char __user *user_buf,
1210 size_t count, loff_t *ppos)
1211 {
1212 const char *buf = file->private_data;
1213 size_t len = strlen(buf);
1214
1215 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1216 }
1217
1218 static const struct file_operations fops_pdev_stats = {
1219 .open = ath12k_open_pdev_stats,
1220 .release = ath12k_release_pdev_stats,
1221 .read = ath12k_read_pdev_stats,
1222 .owner = THIS_MODULE,
1223 .llseek = default_llseek,
1224 };
1225
1226 static
ath12k_debugfs_fw_stats_register(struct ath12k * ar)1227 void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
1228 {
1229 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1230 ar->debug.debugfs_pdev);
1231
1232 /* all stats debugfs files created are under "fw_stats" directory
1233 * created per PDEV
1234 */
1235 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1236 &fops_vdev_stats);
1237 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1238 &fops_bcn_stats);
1239 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1240 &fops_pdev_stats);
1241
1242 INIT_LIST_HEAD(&ar->fw_stats.vdevs);
1243 INIT_LIST_HEAD(&ar->fw_stats.bcn);
1244 INIT_LIST_HEAD(&ar->fw_stats.pdevs);
1245
1246 init_completion(&ar->fw_stats_complete);
1247 }
1248
ath12k_debugfs_register(struct ath12k * ar)1249 void ath12k_debugfs_register(struct ath12k *ar)
1250 {
1251 struct ath12k_base *ab = ar->ab;
1252 struct ieee80211_hw *hw = ar->ah->hw;
1253 char pdev_name[5];
1254 char buf[100] = {0};
1255
1256 scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1257
1258 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1259
1260 /* Create a symlink under ieee80211/phy* */
1261 scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
1262 ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
1263 hw->wiphy->debugfsdir,
1264 buf);
1265
1266 if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
1267 debugfs_create_file("dfs_simulate_radar", 0200,
1268 ar->debug.debugfs_pdev, ar,
1269 &fops_simulate_radar);
1270 }
1271
1272 debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_pdev, ar,
1273 &fops_tpc_stats);
1274 debugfs_create_file("tpc_stats_type", 0200, ar->debug.debugfs_pdev,
1275 ar, &fops_tpc_stats_type);
1276 init_completion(&ar->debug.tpc_complete);
1277
1278 ath12k_debugfs_htt_stats_register(ar);
1279 ath12k_debugfs_fw_stats_register(ar);
1280
1281 debugfs_create_file("ext_rx_stats", 0644,
1282 ar->debug.debugfs_pdev, ar,
1283 &fops_extd_rx_stats);
1284 }
1285
ath12k_debugfs_unregister(struct ath12k * ar)1286 void ath12k_debugfs_unregister(struct ath12k *ar)
1287 {
1288 if (!ar->debug.debugfs_pdev)
1289 return;
1290
1291 /* Remove symlink under ieee80211/phy* */
1292 debugfs_remove(ar->debug.debugfs_pdev_symlink);
1293 debugfs_remove_recursive(ar->debug.debugfs_pdev);
1294 ar->debug.debugfs_pdev_symlink = NULL;
1295 ar->debug.debugfs_pdev = NULL;
1296 }
1297