1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 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 16 void 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 129 void 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 135 static 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 235 static 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 static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, 243 char __user *user_buf, 244 size_t count, loff_t *ppos) 245 { 246 struct ieee80211_sta *sta = file->private_data; 247 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 248 struct ath11k *ar = arsta->arvif->ar; 249 struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats; 250 int len = 0, i, retval = 0; 251 const int size = 4096; 252 char *buf; 253 254 if (!rx_stats) 255 return -ENOENT; 256 257 buf = kzalloc(size, GFP_KERNEL); 258 if (!buf) 259 return -ENOMEM; 260 261 mutex_lock(&ar->conf_mutex); 262 spin_lock_bh(&ar->ab->base_lock); 263 264 len += scnprintf(buf + len, size - len, "RX peer stats:\n"); 265 len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n", 266 rx_stats->num_msdu); 267 len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n", 268 rx_stats->tcp_msdu_count); 269 len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n", 270 rx_stats->udp_msdu_count); 271 len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n", 272 rx_stats->ampdu_msdu_count); 273 len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n", 274 rx_stats->non_ampdu_msdu_count); 275 len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n", 276 rx_stats->stbc_count); 277 len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n", 278 rx_stats->beamformed_count); 279 len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n", 280 rx_stats->num_mpdu_fcs_ok); 281 len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n", 282 rx_stats->num_mpdu_fcs_err); 283 len += scnprintf(buf + len, size - len, 284 "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n", 285 rx_stats->gi_count[0], rx_stats->gi_count[1], 286 rx_stats->gi_count[2], rx_stats->gi_count[3]); 287 len += scnprintf(buf + len, size - len, 288 "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n", 289 rx_stats->bw_count[0], rx_stats->bw_count[1], 290 rx_stats->bw_count[2], rx_stats->bw_count[3]); 291 len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n", 292 rx_stats->coding_count[0], rx_stats->coding_count[1]); 293 len += scnprintf(buf + len, size - len, 294 "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n", 295 rx_stats->pream_cnt[0], rx_stats->pream_cnt[1], 296 rx_stats->pream_cnt[2], rx_stats->pream_cnt[3], 297 rx_stats->pream_cnt[4]); 298 len += scnprintf(buf + len, size - len, 299 "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n", 300 rx_stats->reception_type[0], rx_stats->reception_type[1], 301 rx_stats->reception_type[2], rx_stats->reception_type[3]); 302 len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):"); 303 for (i = 0; i <= IEEE80211_NUM_TIDS; i++) 304 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]); 305 len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):"); 306 for (i = 0; i < HAL_RX_MAX_MCS + 1; i++) 307 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]); 308 len += scnprintf(buf + len, size - len, "\nNSS(1-8):"); 309 for (i = 0; i < HAL_RX_MAX_NSS; i++) 310 len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]); 311 len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ", 312 rx_stats->rx_duration); 313 len += scnprintf(buf + len, size - len, 314 "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n", 315 rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0], 316 rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2], 317 rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4], 318 rx_stats->ru_alloc_cnt[5]); 319 320 len += scnprintf(buf + len, size - len, "\n"); 321 322 spin_unlock_bh(&ar->ab->base_lock); 323 324 if (len > size) 325 len = size; 326 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 327 kfree(buf); 328 329 mutex_unlock(&ar->conf_mutex); 330 return retval; 331 } 332 333 static const struct file_operations fops_rx_stats = { 334 .read = ath11k_dbg_sta_dump_rx_stats, 335 .open = simple_open, 336 .owner = THIS_MODULE, 337 .llseek = default_llseek, 338 }; 339 340 static int 341 ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file) 342 { 343 struct ieee80211_sta *sta = inode->i_private; 344 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 345 struct ath11k *ar = arsta->arvif->ar; 346 struct debug_htt_stats_req *stats_req; 347 int type = ar->debug.htt_stats.type; 348 int ret; 349 350 if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO && 351 type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) || 352 type == ATH11K_DBG_HTT_EXT_STATS_RESET) 353 return -EPERM; 354 355 stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE); 356 if (!stats_req) 357 return -ENOMEM; 358 359 mutex_lock(&ar->conf_mutex); 360 ar->debug.htt_stats.stats_req = stats_req; 361 stats_req->type = type; 362 memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN); 363 ret = ath11k_debugfs_htt_stats_req(ar); 364 mutex_unlock(&ar->conf_mutex); 365 if (ret < 0) 366 goto out; 367 368 file->private_data = stats_req; 369 return 0; 370 out: 371 vfree(stats_req); 372 ar->debug.htt_stats.stats_req = NULL; 373 return ret; 374 } 375 376 static int 377 ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file) 378 { 379 struct ieee80211_sta *sta = inode->i_private; 380 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 381 struct ath11k *ar = arsta->arvif->ar; 382 383 mutex_lock(&ar->conf_mutex); 384 vfree(file->private_data); 385 ar->debug.htt_stats.stats_req = NULL; 386 mutex_unlock(&ar->conf_mutex); 387 388 return 0; 389 } 390 391 static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file, 392 char __user *user_buf, 393 size_t count, loff_t *ppos) 394 { 395 struct debug_htt_stats_req *stats_req = file->private_data; 396 char *buf; 397 u32 length = 0; 398 399 buf = stats_req->buf; 400 length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE); 401 return simple_read_from_buffer(user_buf, count, ppos, buf, length); 402 } 403 404 static const struct file_operations fops_htt_peer_stats = { 405 .open = ath11k_dbg_sta_open_htt_peer_stats, 406 .release = ath11k_dbg_sta_release_htt_peer_stats, 407 .read = ath11k_dbg_sta_read_htt_peer_stats, 408 .owner = THIS_MODULE, 409 .llseek = default_llseek, 410 }; 411 412 static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file, 413 const char __user *buf, 414 size_t count, loff_t *ppos) 415 { 416 struct ieee80211_sta *sta = file->private_data; 417 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 418 struct ath11k *ar = arsta->arvif->ar; 419 int ret, enable; 420 421 mutex_lock(&ar->conf_mutex); 422 423 if (ar->state != ATH11K_STATE_ON) { 424 ret = -ENETDOWN; 425 goto out; 426 } 427 428 ret = kstrtoint_from_user(buf, count, 0, &enable); 429 if (ret) 430 goto out; 431 432 ar->debug.pktlog_peer_valid = enable; 433 memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN); 434 435 /* Send peer based pktlog enable/disable */ 436 ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable); 437 if (ret) { 438 ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n", 439 sta->addr, ret); 440 goto out; 441 } 442 443 ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n", 444 enable); 445 ret = count; 446 447 out: 448 mutex_unlock(&ar->conf_mutex); 449 return ret; 450 } 451 452 static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file, 453 char __user *ubuf, 454 size_t count, loff_t *ppos) 455 { 456 struct ieee80211_sta *sta = file->private_data; 457 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 458 struct ath11k *ar = arsta->arvif->ar; 459 char buf[32] = {0}; 460 int len; 461 462 mutex_lock(&ar->conf_mutex); 463 len = scnprintf(buf, sizeof(buf), "%08x %pM\n", 464 ar->debug.pktlog_peer_valid, 465 ar->debug.pktlog_peer_addr); 466 mutex_unlock(&ar->conf_mutex); 467 468 return simple_read_from_buffer(ubuf, count, ppos, buf, len); 469 } 470 471 static const struct file_operations fops_peer_pktlog = { 472 .write = ath11k_dbg_sta_write_peer_pktlog, 473 .read = ath11k_dbg_sta_read_peer_pktlog, 474 .open = simple_open, 475 .owner = THIS_MODULE, 476 .llseek = default_llseek, 477 }; 478 479 static ssize_t ath11k_dbg_sta_write_delba(struct file *file, 480 const char __user *user_buf, 481 size_t count, loff_t *ppos) 482 { 483 struct ieee80211_sta *sta = file->private_data; 484 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 485 struct ath11k *ar = arsta->arvif->ar; 486 u32 tid, initiator, reason; 487 int ret; 488 char buf[64] = {0}; 489 490 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 491 user_buf, count); 492 if (ret <= 0) 493 return ret; 494 495 ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); 496 if (ret != 3) 497 return -EINVAL; 498 499 /* Valid TID values are 0 through 15 */ 500 if (tid > HAL_DESC_REO_NON_QOS_TID - 1) 501 return -EINVAL; 502 503 mutex_lock(&ar->conf_mutex); 504 if (ar->state != ATH11K_STATE_ON || 505 arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) { 506 ret = count; 507 goto out; 508 } 509 510 ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr, 511 tid, initiator, reason); 512 if (ret) { 513 ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n", 514 arsta->arvif->vdev_id, sta->addr, tid, initiator, 515 reason); 516 } 517 ret = count; 518 out: 519 mutex_unlock(&ar->conf_mutex); 520 return ret; 521 } 522 523 static const struct file_operations fops_delba = { 524 .write = ath11k_dbg_sta_write_delba, 525 .open = simple_open, 526 .owner = THIS_MODULE, 527 .llseek = default_llseek, 528 }; 529 530 static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file, 531 const char __user *user_buf, 532 size_t count, loff_t *ppos) 533 { 534 struct ieee80211_sta *sta = file->private_data; 535 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 536 struct ath11k *ar = arsta->arvif->ar; 537 u32 tid, status; 538 int ret; 539 char buf[64] = {0}; 540 541 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 542 user_buf, count); 543 if (ret <= 0) 544 return ret; 545 546 ret = sscanf(buf, "%u %u", &tid, &status); 547 if (ret != 2) 548 return -EINVAL; 549 550 /* Valid TID values are 0 through 15 */ 551 if (tid > HAL_DESC_REO_NON_QOS_TID - 1) 552 return -EINVAL; 553 554 mutex_lock(&ar->conf_mutex); 555 if (ar->state != ATH11K_STATE_ON || 556 arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) { 557 ret = count; 558 goto out; 559 } 560 561 ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr, 562 tid, status); 563 if (ret) { 564 ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n", 565 arsta->arvif->vdev_id, sta->addr, tid, status); 566 } 567 ret = count; 568 out: 569 mutex_unlock(&ar->conf_mutex); 570 return ret; 571 } 572 573 static const struct file_operations fops_addba_resp = { 574 .write = ath11k_dbg_sta_write_addba_resp, 575 .open = simple_open, 576 .owner = THIS_MODULE, 577 .llseek = default_llseek, 578 }; 579 580 static ssize_t ath11k_dbg_sta_write_addba(struct file *file, 581 const char __user *user_buf, 582 size_t count, loff_t *ppos) 583 { 584 struct ieee80211_sta *sta = file->private_data; 585 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 586 struct ath11k *ar = arsta->arvif->ar; 587 u32 tid, buf_size; 588 int ret; 589 char buf[64] = {0}; 590 591 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 592 user_buf, count); 593 if (ret <= 0) 594 return ret; 595 596 ret = sscanf(buf, "%u %u", &tid, &buf_size); 597 if (ret != 2) 598 return -EINVAL; 599 600 /* Valid TID values are 0 through 15 */ 601 if (tid > HAL_DESC_REO_NON_QOS_TID - 1) 602 return -EINVAL; 603 604 mutex_lock(&ar->conf_mutex); 605 if (ar->state != ATH11K_STATE_ON || 606 arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) { 607 ret = count; 608 goto out; 609 } 610 611 ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr, 612 tid, buf_size); 613 if (ret) { 614 ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n", 615 arsta->arvif->vdev_id, sta->addr, tid, buf_size); 616 } 617 618 ret = count; 619 out: 620 mutex_unlock(&ar->conf_mutex); 621 return ret; 622 } 623 624 static const struct file_operations fops_addba = { 625 .write = ath11k_dbg_sta_write_addba, 626 .open = simple_open, 627 .owner = THIS_MODULE, 628 .llseek = default_llseek, 629 }; 630 631 static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file, 632 char __user *user_buf, 633 size_t count, loff_t *ppos) 634 { 635 struct ieee80211_sta *sta = file->private_data; 636 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 637 struct ath11k *ar = arsta->arvif->ar; 638 char buf[64]; 639 int len = 0; 640 641 mutex_lock(&ar->conf_mutex); 642 len = scnprintf(buf, sizeof(buf) - len, 643 "aggregation mode: %s\n\n%s\n%s\n", 644 (arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ? 645 "auto" : "manual", "auto = 0", "manual = 1"); 646 mutex_unlock(&ar->conf_mutex); 647 648 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 649 } 650 651 static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file, 652 const char __user *user_buf, 653 size_t count, loff_t *ppos) 654 { 655 struct ieee80211_sta *sta = file->private_data; 656 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 657 struct ath11k *ar = arsta->arvif->ar; 658 u32 aggr_mode; 659 int ret; 660 661 if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode)) 662 return -EINVAL; 663 664 if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX) 665 return -EINVAL; 666 667 mutex_lock(&ar->conf_mutex); 668 if (ar->state != ATH11K_STATE_ON || 669 aggr_mode == arsta->aggr_mode) { 670 ret = count; 671 goto out; 672 } 673 674 ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr); 675 if (ret) { 676 ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n", 677 ret); 678 goto out; 679 } 680 681 arsta->aggr_mode = aggr_mode; 682 out: 683 mutex_unlock(&ar->conf_mutex); 684 return ret; 685 } 686 687 static const struct file_operations fops_aggr_mode = { 688 .read = ath11k_dbg_sta_read_aggr_mode, 689 .write = ath11k_dbg_sta_write_aggr_mode, 690 .open = simple_open, 691 .owner = THIS_MODULE, 692 .llseek = default_llseek, 693 }; 694 695 static ssize_t 696 ath11k_write_htt_peer_stats_reset(struct file *file, 697 const char __user *user_buf, 698 size_t count, loff_t *ppos) 699 { 700 struct ieee80211_sta *sta = file->private_data; 701 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 702 struct ath11k *ar = arsta->arvif->ar; 703 struct htt_ext_stats_cfg_params cfg_params = { 0 }; 704 int ret; 705 u8 type; 706 707 ret = kstrtou8_from_user(user_buf, count, 0, &type); 708 if (ret) 709 return ret; 710 711 if (!type) 712 return ret; 713 714 mutex_lock(&ar->conf_mutex); 715 cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR; 716 cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1), 717 HTT_PEER_STATS_REQ_MODE_FLUSH_TQM); 718 719 cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE; 720 721 cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]); 722 cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]); 723 cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]); 724 cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]); 725 726 cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]); 727 cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]); 728 729 cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET; 730 731 ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar, 732 ATH11K_DBG_HTT_EXT_STATS_PEER_INFO, 733 &cfg_params, 734 0ULL); 735 if (ret) { 736 ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret); 737 mutex_unlock(&ar->conf_mutex); 738 return ret; 739 } 740 741 mutex_unlock(&ar->conf_mutex); 742 743 ret = count; 744 745 return ret; 746 } 747 748 static const struct file_operations fops_htt_peer_stats_reset = { 749 .write = ath11k_write_htt_peer_stats_reset, 750 .open = simple_open, 751 .owner = THIS_MODULE, 752 .llseek = default_llseek, 753 }; 754 755 static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file, 756 char __user *user_buf, 757 size_t count, loff_t *ppos) 758 { 759 struct ieee80211_sta *sta = file->private_data; 760 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 761 struct ath11k *ar = arsta->arvif->ar; 762 char buf[20]; 763 int len; 764 765 spin_lock_bh(&ar->data_lock); 766 767 len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state); 768 769 spin_unlock_bh(&ar->data_lock); 770 771 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 772 } 773 774 static const struct file_operations fops_peer_ps_state = { 775 .open = simple_open, 776 .read = ath11k_dbg_sta_read_peer_ps_state, 777 .owner = THIS_MODULE, 778 .llseek = default_llseek, 779 }; 780 781 static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file, 782 char __user *user_buf, 783 size_t count, 784 loff_t *ppos) 785 { 786 struct ieee80211_sta *sta = file->private_data; 787 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 788 struct ath11k *ar = arsta->arvif->ar; 789 u64 time_since_station_in_power_save; 790 char buf[20]; 791 int len; 792 793 spin_lock_bh(&ar->data_lock); 794 795 if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON && 796 arsta->peer_current_ps_valid) 797 time_since_station_in_power_save = jiffies_to_msecs(jiffies 798 - arsta->ps_start_jiffies); 799 else 800 time_since_station_in_power_save = 0; 801 802 len = scnprintf(buf, sizeof(buf), "%llu\n", 803 time_since_station_in_power_save); 804 spin_unlock_bh(&ar->data_lock); 805 806 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 807 } 808 809 static const struct file_operations fops_current_ps_duration = { 810 .open = simple_open, 811 .read = ath11k_dbg_sta_read_current_ps_duration, 812 .owner = THIS_MODULE, 813 .llseek = default_llseek, 814 }; 815 816 static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file, 817 char __user *user_buf, 818 size_t count, loff_t *ppos) 819 { 820 struct ieee80211_sta *sta = file->private_data; 821 struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); 822 struct ath11k *ar = arsta->arvif->ar; 823 char buf[20]; 824 u64 power_save_duration; 825 int len; 826 827 spin_lock_bh(&ar->data_lock); 828 829 if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON && 830 arsta->peer_current_ps_valid) 831 power_save_duration = jiffies_to_msecs(jiffies 832 - arsta->ps_start_jiffies) 833 + arsta->ps_total_duration; 834 else 835 power_save_duration = arsta->ps_total_duration; 836 837 len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration); 838 839 spin_unlock_bh(&ar->data_lock); 840 841 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 842 } 843 844 static const struct file_operations fops_total_ps_duration = { 845 .open = simple_open, 846 .read = ath11k_dbg_sta_read_total_ps_duration, 847 .owner = THIS_MODULE, 848 .llseek = default_llseek, 849 }; 850 851 void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 852 struct ieee80211_sta *sta, struct dentry *dir) 853 { 854 struct ath11k *ar = hw->priv; 855 856 if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) 857 debugfs_create_file("tx_stats", 0400, dir, sta, 858 &fops_tx_stats); 859 if (ath11k_debugfs_is_extd_rx_stats_enabled(ar)) 860 debugfs_create_file("rx_stats", 0400, dir, sta, 861 &fops_rx_stats); 862 863 debugfs_create_file("htt_peer_stats", 0400, dir, sta, 864 &fops_htt_peer_stats); 865 866 debugfs_create_file("peer_pktlog", 0644, dir, sta, 867 &fops_peer_pktlog); 868 869 debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode); 870 debugfs_create_file("addba", 0200, dir, sta, &fops_addba); 871 debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp); 872 debugfs_create_file("delba", 0200, dir, sta, &fops_delba); 873 874 if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET, 875 ar->ab->wmi_ab.svc_map)) 876 debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta, 877 &fops_htt_peer_stats_reset); 878 879 debugfs_create_file("peer_ps_state", 0400, dir, sta, 880 &fops_peer_ps_state); 881 882 if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT, 883 ar->ab->wmi_ab.svc_map)) { 884 debugfs_create_file("current_ps_duration", 0440, dir, sta, 885 &fops_current_ps_duration); 886 debugfs_create_file("total_ps_duration", 0440, dir, sta, 887 &fops_total_ps_duration); 888 } 889 } 890