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_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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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