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