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 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 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 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 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_6GHZ_FREQ) ? NL80211_BAND_6GHZ : 92 ((chan_freq > ATH12K_MIN_5GHZ_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 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 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 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 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 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 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 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 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 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 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 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 836 static int ath12k_open_link_stats(struct inode *inode, struct file *file) 837 { 838 struct ath12k_vif *ahvif = inode->i_private; 839 size_t len = 0, buf_len = (PAGE_SIZE * 2); 840 struct ath12k_link_stats linkstat; 841 struct ath12k_link_vif *arvif; 842 unsigned long links_map; 843 struct wiphy *wiphy; 844 int link_id, i; 845 char *buf; 846 847 if (!ahvif) 848 return -EINVAL; 849 850 buf = kzalloc(buf_len, GFP_KERNEL); 851 if (!buf) 852 return -ENOMEM; 853 854 wiphy = ahvif->ah->hw->wiphy; 855 wiphy_lock(wiphy); 856 857 links_map = ahvif->links_map; 858 for_each_set_bit(link_id, &links_map, 859 IEEE80211_MLD_MAX_NUM_LINKS) { 860 arvif = rcu_dereference_protected(ahvif->link[link_id], 861 lockdep_is_held(&wiphy->mtx)); 862 863 spin_lock_bh(&arvif->link_stats_lock); 864 linkstat = arvif->link_stats; 865 spin_unlock_bh(&arvif->link_stats_lock); 866 867 len += scnprintf(buf + len, buf_len - len, 868 "link[%d] Tx Unicast Frames Enqueued = %d\n", 869 link_id, linkstat.tx_enqueued); 870 len += scnprintf(buf + len, buf_len - len, 871 "link[%d] Tx Broadcast Frames Enqueued = %d\n", 872 link_id, linkstat.tx_bcast_mcast); 873 len += scnprintf(buf + len, buf_len - len, 874 "link[%d] Tx Frames Completed = %d\n", 875 link_id, linkstat.tx_completed); 876 len += scnprintf(buf + len, buf_len - len, 877 "link[%d] Tx Frames Dropped = %d\n", 878 link_id, linkstat.tx_dropped); 879 880 len += scnprintf(buf + len, buf_len - len, 881 "link[%d] Tx Frame descriptor Encap Type = ", 882 link_id); 883 884 len += scnprintf(buf + len, buf_len - len, 885 " raw:%d", 886 linkstat.tx_encap_type[0]); 887 888 len += scnprintf(buf + len, buf_len - len, 889 " native_wifi:%d", 890 linkstat.tx_encap_type[1]); 891 892 len += scnprintf(buf + len, buf_len - len, 893 " ethernet:%d", 894 linkstat.tx_encap_type[2]); 895 896 len += scnprintf(buf + len, buf_len - len, 897 "\nlink[%d] Tx Frame descriptor Encrypt Type = ", 898 link_id); 899 900 for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) { 901 len += scnprintf(buf + len, buf_len - len, 902 " %d:%d", i, 903 linkstat.tx_encrypt_type[i]); 904 } 905 len += scnprintf(buf + len, buf_len - len, 906 "\nlink[%d] Tx Frame descriptor Type = buffer:%d extension:%d\n", 907 link_id, linkstat.tx_desc_type[0], 908 linkstat.tx_desc_type[1]); 909 910 len += scnprintf(buf + len, buf_len - len, 911 "------------------------------------------------------\n"); 912 } 913 914 wiphy_unlock(wiphy); 915 916 file->private_data = buf; 917 918 return 0; 919 } 920 921 static int ath12k_release_link_stats(struct inode *inode, struct file *file) 922 { 923 kfree(file->private_data); 924 return 0; 925 } 926 927 static ssize_t ath12k_read_link_stats(struct file *file, 928 char __user *user_buf, 929 size_t count, loff_t *ppos) 930 { 931 const char *buf = file->private_data; 932 size_t len = strlen(buf); 933 934 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 935 } 936 937 static const struct file_operations ath12k_fops_link_stats = { 938 .open = ath12k_open_link_stats, 939 .release = ath12k_release_link_stats, 940 .read = ath12k_read_link_stats, 941 .owner = THIS_MODULE, 942 .llseek = default_llseek, 943 }; 944 945 void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw, 946 struct ieee80211_vif *vif) 947 { 948 struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); 949 950 debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif, 951 &ath12k_fops_link_stats); 952 } 953 954 void ath12k_debugfs_soc_create(struct ath12k_base *ab) 955 { 956 bool dput_needed; 957 char soc_name[64] = { 0 }; 958 struct dentry *debugfs_ath12k; 959 960 debugfs_ath12k = debugfs_lookup("ath12k", NULL); 961 if (debugfs_ath12k) { 962 /* a dentry from lookup() needs dput() after we don't use it */ 963 dput_needed = true; 964 } else { 965 debugfs_ath12k = debugfs_create_dir("ath12k", NULL); 966 if (IS_ERR_OR_NULL(debugfs_ath12k)) 967 return; 968 dput_needed = false; 969 } 970 971 scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus), 972 dev_name(ab->dev)); 973 974 ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k); 975 976 if (dput_needed) 977 dput(debugfs_ath12k); 978 } 979 980 void ath12k_debugfs_soc_destroy(struct ath12k_base *ab) 981 { 982 debugfs_remove_recursive(ab->debugfs_soc); 983 ab->debugfs_soc = NULL; 984 /* We are not removing ath12k directory on purpose, even if it 985 * would be empty. This simplifies the directory handling and it's 986 * a minor cosmetic issue to leave an empty ath12k directory to 987 * debugfs. 988 */ 989 } 990 991 void 992 ath12k_debugfs_fw_stats_process(struct ath12k *ar, 993 struct ath12k_fw_stats *stats) 994 { 995 struct ath12k_base *ab = ar->ab; 996 struct ath12k_pdev *pdev; 997 bool is_end; 998 static unsigned int num_vdev, num_bcn; 999 size_t total_vdevs_started = 0; 1000 int i; 1001 1002 if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { 1003 if (list_empty(&stats->vdevs)) { 1004 ath12k_warn(ab, "empty vdev stats"); 1005 return; 1006 } 1007 /* FW sends all the active VDEV stats irrespective of PDEV, 1008 * hence limit until the count of all VDEVs started 1009 */ 1010 rcu_read_lock(); 1011 for (i = 0; i < ab->num_radios; i++) { 1012 pdev = rcu_dereference(ab->pdevs_active[i]); 1013 if (pdev && pdev->ar) 1014 total_vdevs_started += pdev->ar->num_started_vdevs; 1015 } 1016 rcu_read_unlock(); 1017 1018 is_end = ((++num_vdev) == total_vdevs_started); 1019 1020 list_splice_tail_init(&stats->vdevs, 1021 &ar->fw_stats.vdevs); 1022 1023 if (is_end) { 1024 ar->fw_stats.fw_stats_done = true; 1025 num_vdev = 0; 1026 } 1027 return; 1028 } 1029 if (stats->stats_id == WMI_REQUEST_BCN_STAT) { 1030 if (list_empty(&stats->bcn)) { 1031 ath12k_warn(ab, "empty beacon stats"); 1032 return; 1033 } 1034 /* Mark end until we reached the count of all started VDEVs 1035 * within the PDEV 1036 */ 1037 is_end = ((++num_bcn) == ar->num_started_vdevs); 1038 1039 list_splice_tail_init(&stats->bcn, 1040 &ar->fw_stats.bcn); 1041 1042 if (is_end) { 1043 ar->fw_stats.fw_stats_done = true; 1044 num_bcn = 0; 1045 } 1046 } 1047 } 1048 1049 static int ath12k_open_vdev_stats(struct inode *inode, struct file *file) 1050 { 1051 struct ath12k *ar = inode->i_private; 1052 struct ath12k_fw_stats_req_params param; 1053 struct ath12k_hw *ah = ath12k_ar_to_ah(ar); 1054 int ret; 1055 1056 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy); 1057 1058 if (!ah) 1059 return -ENETDOWN; 1060 1061 if (ah->state != ATH12K_HW_STATE_ON) 1062 return -ENETDOWN; 1063 1064 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC); 1065 if (!buf) 1066 return -ENOMEM; 1067 1068 param.pdev_id = ath12k_mac_get_target_pdev_id(ar); 1069 /* VDEV stats is always sent for all active VDEVs from FW */ 1070 param.vdev_id = 0; 1071 param.stats_id = WMI_REQUEST_VDEV_STAT; 1072 1073 ret = ath12k_mac_get_fw_stats(ar, ¶m); 1074 if (ret) { 1075 ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret); 1076 return ret; 1077 } 1078 1079 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1080 buf); 1081 1082 file->private_data = no_free_ptr(buf); 1083 1084 return 0; 1085 } 1086 1087 static int ath12k_release_vdev_stats(struct inode *inode, struct file *file) 1088 { 1089 kfree(file->private_data); 1090 1091 return 0; 1092 } 1093 1094 static ssize_t ath12k_read_vdev_stats(struct file *file, 1095 char __user *user_buf, 1096 size_t count, loff_t *ppos) 1097 { 1098 const char *buf = file->private_data; 1099 size_t len = strlen(buf); 1100 1101 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1102 } 1103 1104 static const struct file_operations fops_vdev_stats = { 1105 .open = ath12k_open_vdev_stats, 1106 .release = ath12k_release_vdev_stats, 1107 .read = ath12k_read_vdev_stats, 1108 .owner = THIS_MODULE, 1109 .llseek = default_llseek, 1110 }; 1111 1112 static int ath12k_open_bcn_stats(struct inode *inode, struct file *file) 1113 { 1114 struct ath12k *ar = inode->i_private; 1115 struct ath12k_link_vif *arvif; 1116 struct ath12k_fw_stats_req_params param; 1117 struct ath12k_hw *ah = ath12k_ar_to_ah(ar); 1118 int ret; 1119 1120 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy); 1121 1122 if (ah && ah->state != ATH12K_HW_STATE_ON) 1123 return -ENETDOWN; 1124 1125 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC); 1126 if (!buf) 1127 return -ENOMEM; 1128 1129 param.pdev_id = ath12k_mac_get_target_pdev_id(ar); 1130 param.stats_id = WMI_REQUEST_BCN_STAT; 1131 1132 /* loop all active VDEVs for bcn stats */ 1133 list_for_each_entry(arvif, &ar->arvifs, list) { 1134 if (!arvif->is_up) 1135 continue; 1136 1137 param.vdev_id = arvif->vdev_id; 1138 ret = ath12k_mac_get_fw_stats(ar, ¶m); 1139 if (ret) { 1140 ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret); 1141 return ret; 1142 } 1143 } 1144 1145 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1146 buf); 1147 /* since beacon stats request is looped for all active VDEVs, saved fw 1148 * stats is not freed for each request until done for all active VDEVs 1149 */ 1150 spin_lock_bh(&ar->data_lock); 1151 ath12k_fw_stats_bcn_free(&ar->fw_stats.bcn); 1152 spin_unlock_bh(&ar->data_lock); 1153 1154 file->private_data = no_free_ptr(buf); 1155 1156 return 0; 1157 } 1158 1159 static int ath12k_release_bcn_stats(struct inode *inode, struct file *file) 1160 { 1161 kfree(file->private_data); 1162 1163 return 0; 1164 } 1165 1166 static ssize_t ath12k_read_bcn_stats(struct file *file, 1167 char __user *user_buf, 1168 size_t count, loff_t *ppos) 1169 { 1170 const char *buf = file->private_data; 1171 size_t len = strlen(buf); 1172 1173 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1174 } 1175 1176 static const struct file_operations fops_bcn_stats = { 1177 .open = ath12k_open_bcn_stats, 1178 .release = ath12k_release_bcn_stats, 1179 .read = ath12k_read_bcn_stats, 1180 .owner = THIS_MODULE, 1181 .llseek = default_llseek, 1182 }; 1183 1184 static int ath12k_open_pdev_stats(struct inode *inode, struct file *file) 1185 { 1186 struct ath12k *ar = inode->i_private; 1187 struct ath12k_hw *ah = ath12k_ar_to_ah(ar); 1188 struct ath12k_base *ab = ar->ab; 1189 struct ath12k_fw_stats_req_params param; 1190 int ret; 1191 1192 guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy); 1193 1194 if (ah && ah->state != ATH12K_HW_STATE_ON) 1195 return -ENETDOWN; 1196 1197 void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC); 1198 if (!buf) 1199 return -ENOMEM; 1200 1201 param.pdev_id = ath12k_mac_get_target_pdev_id(ar); 1202 param.vdev_id = 0; 1203 param.stats_id = WMI_REQUEST_PDEV_STAT; 1204 1205 ret = ath12k_mac_get_fw_stats(ar, ¶m); 1206 if (ret) { 1207 ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret); 1208 return ret; 1209 } 1210 1211 ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id, 1212 buf); 1213 1214 file->private_data = no_free_ptr(buf); 1215 1216 return 0; 1217 } 1218 1219 static int ath12k_release_pdev_stats(struct inode *inode, struct file *file) 1220 { 1221 kfree(file->private_data); 1222 1223 return 0; 1224 } 1225 1226 static ssize_t ath12k_read_pdev_stats(struct file *file, 1227 char __user *user_buf, 1228 size_t count, loff_t *ppos) 1229 { 1230 const char *buf = file->private_data; 1231 size_t len = strlen(buf); 1232 1233 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1234 } 1235 1236 static const struct file_operations fops_pdev_stats = { 1237 .open = ath12k_open_pdev_stats, 1238 .release = ath12k_release_pdev_stats, 1239 .read = ath12k_read_pdev_stats, 1240 .owner = THIS_MODULE, 1241 .llseek = default_llseek, 1242 }; 1243 1244 static 1245 void ath12k_debugfs_fw_stats_register(struct ath12k *ar) 1246 { 1247 struct dentry *fwstats_dir = debugfs_create_dir("fw_stats", 1248 ar->debug.debugfs_pdev); 1249 1250 /* all stats debugfs files created are under "fw_stats" directory 1251 * created per PDEV 1252 */ 1253 debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar, 1254 &fops_vdev_stats); 1255 debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar, 1256 &fops_bcn_stats); 1257 debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar, 1258 &fops_pdev_stats); 1259 1260 ath12k_fw_stats_init(ar); 1261 } 1262 1263 void ath12k_debugfs_register(struct ath12k *ar) 1264 { 1265 struct ath12k_base *ab = ar->ab; 1266 struct ieee80211_hw *hw = ar->ah->hw; 1267 char pdev_name[5]; 1268 char buf[100] = {0}; 1269 1270 scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx); 1271 1272 ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc); 1273 1274 /* Create a symlink under ieee80211/phy* */ 1275 scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev); 1276 ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k", 1277 hw->wiphy->debugfsdir, 1278 buf); 1279 1280 if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) { 1281 debugfs_create_file("dfs_simulate_radar", 0200, 1282 ar->debug.debugfs_pdev, ar, 1283 &fops_simulate_radar); 1284 } 1285 1286 debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_pdev, ar, 1287 &fops_tpc_stats); 1288 debugfs_create_file("tpc_stats_type", 0200, ar->debug.debugfs_pdev, 1289 ar, &fops_tpc_stats_type); 1290 init_completion(&ar->debug.tpc_complete); 1291 1292 ath12k_debugfs_htt_stats_register(ar); 1293 ath12k_debugfs_fw_stats_register(ar); 1294 1295 debugfs_create_file("ext_rx_stats", 0644, 1296 ar->debug.debugfs_pdev, ar, 1297 &fops_extd_rx_stats); 1298 } 1299 1300 void ath12k_debugfs_unregister(struct ath12k *ar) 1301 { 1302 if (!ar->debug.debugfs_pdev) 1303 return; 1304 1305 /* Remove symlink under ieee80211/phy* */ 1306 debugfs_remove(ar->debug.debugfs_pdev_symlink); 1307 debugfs_remove_recursive(ar->debug.debugfs_pdev); 1308 ar->debug.debugfs_pdev_symlink = NULL; 1309 ar->debug.debugfs_pdev = NULL; 1310 } 1311