debugfs_sta.c (21470B)
1// SPDX-License-Identifier: ISC 2/* 3 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. 4 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 5 */ 6 7#include "core.h" 8#include "wmi-ops.h" 9#include "txrx.h" 10#include "debug.h" 11 12static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar, 13 struct ath10k_sta_tid_stats *stats, 14 u32 msdu_count) 15{ 16 if (msdu_count == 1) 17 stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++; 18 else if (msdu_count == 2) 19 stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++; 20 else if (msdu_count == 3) 21 stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++; 22 else if (msdu_count == 4) 23 stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++; 24 else if (msdu_count > 4) 25 stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++; 26} 27 28static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar, 29 struct ath10k_sta_tid_stats *stats, 30 u32 mpdu_count) 31{ 32 if (mpdu_count <= 10) 33 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++; 34 else if (mpdu_count <= 20) 35 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++; 36 else if (mpdu_count <= 30) 37 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++; 38 else if (mpdu_count <= 40) 39 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++; 40 else if (mpdu_count <= 50) 41 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++; 42 else if (mpdu_count <= 60) 43 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++; 44 else if (mpdu_count > 60) 45 stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++; 46} 47 48void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid, 49 struct htt_rx_indication_mpdu_range *ranges, 50 int num_ranges) 51{ 52 struct ath10k_sta *arsta; 53 struct ath10k_peer *peer; 54 int i; 55 56 if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid))) 57 return; 58 59 rcu_read_lock(); 60 spin_lock_bh(&ar->data_lock); 61 62 peer = ath10k_peer_find_by_id(ar, peer_id); 63 if (!peer || !peer->sta) 64 goto out; 65 66 arsta = (struct ath10k_sta *)peer->sta->drv_priv; 67 68 for (i = 0; i < num_ranges; i++) 69 ath10k_rx_stats_update_ampdu_subfrm(ar, 70 &arsta->tid_stats[tid], 71 ranges[i].mpdu_count); 72 73out: 74 spin_unlock_bh(&ar->data_lock); 75 rcu_read_unlock(); 76} 77 78void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, 79 unsigned long num_msdus, 80 enum ath10k_pkt_rx_err err, 81 unsigned long unchain_cnt, 82 unsigned long drop_cnt, 83 unsigned long drop_cnt_filter, 84 unsigned long queued_msdus) 85{ 86 struct ieee80211_sta *sta; 87 struct ath10k_sta *arsta; 88 struct ieee80211_hdr *hdr; 89 struct ath10k_sta_tid_stats *stats; 90 u8 tid = IEEE80211_NUM_TIDS; 91 bool non_data_frm = false; 92 93 hdr = (struct ieee80211_hdr *)first_hdr; 94 if (!ieee80211_is_data(hdr->frame_control)) 95 non_data_frm = true; 96 97 if (ieee80211_is_data_qos(hdr->frame_control)) 98 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; 99 100 if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm) 101 return; 102 103 rcu_read_lock(); 104 105 sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL); 106 if (!sta) 107 goto exit; 108 109 arsta = (struct ath10k_sta *)sta->drv_priv; 110 111 spin_lock_bh(&ar->data_lock); 112 stats = &arsta->tid_stats[tid]; 113 stats->rx_pkt_from_fw += num_msdus; 114 stats->rx_pkt_unchained += unchain_cnt; 115 stats->rx_pkt_drop_chained += drop_cnt; 116 stats->rx_pkt_drop_filter += drop_cnt_filter; 117 if (err != ATH10K_PKT_RX_ERR_MAX) 118 stats->rx_pkt_err[err] += queued_msdus; 119 stats->rx_pkt_queued_for_mac += queued_msdus; 120 ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid], 121 num_msdus); 122 spin_unlock_bh(&ar->data_lock); 123 124exit: 125 rcu_read_unlock(); 126} 127 128static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar, 129 struct ath10k_fw_stats *stats) 130{ 131 struct ath10k_fw_extd_stats_peer *peer; 132 struct ieee80211_sta *sta; 133 struct ath10k_sta *arsta; 134 135 rcu_read_lock(); 136 list_for_each_entry(peer, &stats->peers_extd, list) { 137 sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, 138 NULL); 139 if (!sta) 140 continue; 141 arsta = (struct ath10k_sta *)sta->drv_priv; 142 arsta->rx_duration += (u64)peer->rx_duration; 143 } 144 rcu_read_unlock(); 145} 146 147static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar, 148 struct ath10k_fw_stats *stats) 149{ 150 struct ath10k_fw_stats_peer *peer; 151 struct ieee80211_sta *sta; 152 struct ath10k_sta *arsta; 153 154 rcu_read_lock(); 155 list_for_each_entry(peer, &stats->peers, list) { 156 sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, 157 NULL); 158 if (!sta) 159 continue; 160 arsta = (struct ath10k_sta *)sta->drv_priv; 161 arsta->rx_duration += (u64)peer->rx_duration; 162 } 163 rcu_read_unlock(); 164} 165 166void ath10k_sta_update_rx_duration(struct ath10k *ar, 167 struct ath10k_fw_stats *stats) 168{ 169 if (stats->extended) 170 ath10k_sta_update_extd_stats_rx_duration(ar, stats); 171 else 172 ath10k_sta_update_stats_rx_duration(ar, stats); 173} 174 175static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, 176 char __user *user_buf, 177 size_t count, loff_t *ppos) 178{ 179 struct ieee80211_sta *sta = file->private_data; 180 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 181 struct ath10k *ar = arsta->arvif->ar; 182 char buf[32]; 183 int len = 0; 184 185 mutex_lock(&ar->conf_mutex); 186 len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n", 187 (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ? 188 "auto" : "manual"); 189 mutex_unlock(&ar->conf_mutex); 190 191 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 192} 193 194static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file, 195 const char __user *user_buf, 196 size_t count, loff_t *ppos) 197{ 198 struct ieee80211_sta *sta = file->private_data; 199 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 200 struct ath10k *ar = arsta->arvif->ar; 201 u32 aggr_mode; 202 int ret; 203 204 if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode)) 205 return -EINVAL; 206 207 if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX) 208 return -EINVAL; 209 210 mutex_lock(&ar->conf_mutex); 211 if ((ar->state != ATH10K_STATE_ON) || 212 (aggr_mode == arsta->aggr_mode)) { 213 ret = count; 214 goto out; 215 } 216 217 ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr); 218 if (ret) { 219 ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret); 220 goto out; 221 } 222 223 arsta->aggr_mode = aggr_mode; 224out: 225 mutex_unlock(&ar->conf_mutex); 226 return ret; 227} 228 229static const struct file_operations fops_aggr_mode = { 230 .read = ath10k_dbg_sta_read_aggr_mode, 231 .write = ath10k_dbg_sta_write_aggr_mode, 232 .open = simple_open, 233 .owner = THIS_MODULE, 234 .llseek = default_llseek, 235}; 236 237static ssize_t ath10k_dbg_sta_write_addba(struct file *file, 238 const char __user *user_buf, 239 size_t count, loff_t *ppos) 240{ 241 struct ieee80211_sta *sta = file->private_data; 242 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 243 struct ath10k *ar = arsta->arvif->ar; 244 u32 tid, buf_size; 245 int ret; 246 char buf[64] = {0}; 247 248 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 249 user_buf, count); 250 if (ret <= 0) 251 return ret; 252 253 ret = sscanf(buf, "%u %u", &tid, &buf_size); 254 if (ret != 2) 255 return -EINVAL; 256 257 /* Valid TID values are 0 through 15 */ 258 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 259 return -EINVAL; 260 261 mutex_lock(&ar->conf_mutex); 262 if ((ar->state != ATH10K_STATE_ON) || 263 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 264 ret = count; 265 goto out; 266 } 267 268 ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr, 269 tid, buf_size); 270 if (ret) { 271 ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n", 272 arsta->arvif->vdev_id, sta->addr, tid, buf_size); 273 } 274 275 ret = count; 276out: 277 mutex_unlock(&ar->conf_mutex); 278 return ret; 279} 280 281static const struct file_operations fops_addba = { 282 .write = ath10k_dbg_sta_write_addba, 283 .open = simple_open, 284 .owner = THIS_MODULE, 285 .llseek = default_llseek, 286}; 287 288static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file, 289 const char __user *user_buf, 290 size_t count, loff_t *ppos) 291{ 292 struct ieee80211_sta *sta = file->private_data; 293 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 294 struct ath10k *ar = arsta->arvif->ar; 295 u32 tid, status; 296 int ret; 297 char buf[64] = {0}; 298 299 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 300 user_buf, count); 301 if (ret <= 0) 302 return ret; 303 304 ret = sscanf(buf, "%u %u", &tid, &status); 305 if (ret != 2) 306 return -EINVAL; 307 308 /* Valid TID values are 0 through 15 */ 309 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 310 return -EINVAL; 311 312 mutex_lock(&ar->conf_mutex); 313 if ((ar->state != ATH10K_STATE_ON) || 314 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 315 ret = count; 316 goto out; 317 } 318 319 ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr, 320 tid, status); 321 if (ret) { 322 ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n", 323 arsta->arvif->vdev_id, sta->addr, tid, status); 324 } 325 ret = count; 326out: 327 mutex_unlock(&ar->conf_mutex); 328 return ret; 329} 330 331static const struct file_operations fops_addba_resp = { 332 .write = ath10k_dbg_sta_write_addba_resp, 333 .open = simple_open, 334 .owner = THIS_MODULE, 335 .llseek = default_llseek, 336}; 337 338static ssize_t ath10k_dbg_sta_write_delba(struct file *file, 339 const char __user *user_buf, 340 size_t count, loff_t *ppos) 341{ 342 struct ieee80211_sta *sta = file->private_data; 343 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 344 struct ath10k *ar = arsta->arvif->ar; 345 u32 tid, initiator, reason; 346 int ret; 347 char buf[64] = {0}; 348 349 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, 350 user_buf, count); 351 if (ret <= 0) 352 return ret; 353 354 ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); 355 if (ret != 3) 356 return -EINVAL; 357 358 /* Valid TID values are 0 through 15 */ 359 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 360 return -EINVAL; 361 362 mutex_lock(&ar->conf_mutex); 363 if ((ar->state != ATH10K_STATE_ON) || 364 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 365 ret = count; 366 goto out; 367 } 368 369 ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr, 370 tid, initiator, reason); 371 if (ret) { 372 ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n", 373 arsta->arvif->vdev_id, sta->addr, tid, initiator, 374 reason); 375 } 376 ret = count; 377out: 378 mutex_unlock(&ar->conf_mutex); 379 return ret; 380} 381 382static const struct file_operations fops_delba = { 383 .write = ath10k_dbg_sta_write_delba, 384 .open = simple_open, 385 .owner = THIS_MODULE, 386 .llseek = default_llseek, 387}; 388 389static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file, 390 char __user *user_buf, 391 size_t count, 392 loff_t *ppos) 393{ 394 struct ieee80211_sta *sta = file->private_data; 395 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 396 struct ath10k *ar = arsta->arvif->ar; 397 char buf[8]; 398 int len = 0; 399 400 mutex_lock(&ar->conf_mutex); 401 len = scnprintf(buf, sizeof(buf) - len, 402 "Write 1 to once trigger the debug logs\n"); 403 mutex_unlock(&ar->conf_mutex); 404 405 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 406} 407 408static ssize_t 409ath10k_dbg_sta_write_peer_debug_trigger(struct file *file, 410 const char __user *user_buf, 411 size_t count, loff_t *ppos) 412{ 413 struct ieee80211_sta *sta = file->private_data; 414 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 415 struct ath10k *ar = arsta->arvif->ar; 416 u8 peer_debug_trigger; 417 int ret; 418 419 if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger)) 420 return -EINVAL; 421 422 if (peer_debug_trigger != 1) 423 return -EINVAL; 424 425 mutex_lock(&ar->conf_mutex); 426 427 if (ar->state != ATH10K_STATE_ON) { 428 ret = -ENETDOWN; 429 goto out; 430 } 431 432 ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr, 433 ar->wmi.peer_param->debug, peer_debug_trigger); 434 if (ret) { 435 ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n", 436 ret); 437 goto out; 438 } 439out: 440 mutex_unlock(&ar->conf_mutex); 441 return count; 442} 443 444static const struct file_operations fops_peer_debug_trigger = { 445 .open = simple_open, 446 .read = ath10k_dbg_sta_read_peer_debug_trigger, 447 .write = ath10k_dbg_sta_write_peer_debug_trigger, 448 .owner = THIS_MODULE, 449 .llseek = default_llseek, 450}; 451 452static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file, 453 char __user *user_buf, 454 size_t count, loff_t *ppos) 455{ 456 struct ieee80211_sta *sta = file->private_data; 457 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 458 struct ath10k *ar = arsta->arvif->ar; 459 char buf[20]; 460 int len = 0; 461 462 spin_lock_bh(&ar->data_lock); 463 464 len = scnprintf(buf, sizeof(buf) - len, "%d\n", 465 arsta->peer_ps_state); 466 467 spin_unlock_bh(&ar->data_lock); 468 469 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 470} 471 472static const struct file_operations fops_peer_ps_state = { 473 .open = simple_open, 474 .read = ath10k_dbg_sta_read_peer_ps_state, 475 .owner = THIS_MODULE, 476 .llseek = default_llseek, 477}; 478 479static char *get_err_str(enum ath10k_pkt_rx_err i) 480{ 481 switch (i) { 482 case ATH10K_PKT_RX_ERR_FCS: 483 return "fcs_err"; 484 case ATH10K_PKT_RX_ERR_TKIP: 485 return "tkip_err"; 486 case ATH10K_PKT_RX_ERR_CRYPT: 487 return "crypt_err"; 488 case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL: 489 return "peer_idx_inval"; 490 case ATH10K_PKT_RX_ERR_MAX: 491 return "unknown"; 492 } 493 494 return "unknown"; 495} 496 497static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i) 498{ 499 switch (i) { 500 case ATH10K_AMPDU_SUBFRM_NUM_10: 501 return "upto 10"; 502 case ATH10K_AMPDU_SUBFRM_NUM_20: 503 return "11-20"; 504 case ATH10K_AMPDU_SUBFRM_NUM_30: 505 return "21-30"; 506 case ATH10K_AMPDU_SUBFRM_NUM_40: 507 return "31-40"; 508 case ATH10K_AMPDU_SUBFRM_NUM_50: 509 return "41-50"; 510 case ATH10K_AMPDU_SUBFRM_NUM_60: 511 return "51-60"; 512 case ATH10K_AMPDU_SUBFRM_NUM_MORE: 513 return ">60"; 514 case ATH10K_AMPDU_SUBFRM_NUM_MAX: 515 return "0"; 516 } 517 518 return "0"; 519} 520 521static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i) 522{ 523 switch (i) { 524 case ATH10K_AMSDU_SUBFRM_NUM_1: 525 return "1"; 526 case ATH10K_AMSDU_SUBFRM_NUM_2: 527 return "2"; 528 case ATH10K_AMSDU_SUBFRM_NUM_3: 529 return "3"; 530 case ATH10K_AMSDU_SUBFRM_NUM_4: 531 return "4"; 532 case ATH10K_AMSDU_SUBFRM_NUM_MORE: 533 return ">4"; 534 case ATH10K_AMSDU_SUBFRM_NUM_MAX: 535 return "0"; 536 } 537 538 return "0"; 539} 540 541#define PRINT_TID_STATS(_field, _tabs) \ 542 do { \ 543 int k = 0; \ 544 for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \ 545 if (ar->sta_tid_stats_mask & BIT(j)) { \ 546 len += scnprintf(buf + len, buf_len - len, \ 547 "[%02d] %-10lu ", \ 548 j, stats[j]._field); \ 549 k++; \ 550 if (k % 8 == 0) { \ 551 len += scnprintf(buf + len, \ 552 buf_len - len, "\n"); \ 553 len += scnprintf(buf + len, \ 554 buf_len - len, \ 555 _tabs); \ 556 } \ 557 } \ 558 } \ 559 len += scnprintf(buf + len, buf_len - len, "\n"); \ 560 } while (0) 561 562static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file, 563 char __user *user_buf, 564 size_t count, loff_t *ppos) 565{ 566 struct ieee80211_sta *sta = file->private_data; 567 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 568 struct ath10k *ar = arsta->arvif->ar; 569 struct ath10k_sta_tid_stats *stats = arsta->tid_stats; 570 size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS; 571 char *buf; 572 int i, j; 573 ssize_t ret; 574 575 buf = kzalloc(buf_len, GFP_KERNEL); 576 if (!buf) 577 return -ENOMEM; 578 579 mutex_lock(&ar->conf_mutex); 580 581 spin_lock_bh(&ar->data_lock); 582 583 len += scnprintf(buf + len, buf_len - len, 584 "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n"); 585 len += scnprintf(buf + len, buf_len - len, 586 "\t\t------------------------------------------\n"); 587 len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t"); 588 PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t"); 589 590 len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t"); 591 PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t"); 592 593 len += scnprintf(buf + len, buf_len - len, 594 "MSDUs locally dropped:chained\t"); 595 PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t"); 596 597 len += scnprintf(buf + len, buf_len - len, 598 "MSDUs locally dropped:filtered\t"); 599 PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t"); 600 601 len += scnprintf(buf + len, buf_len - len, 602 "MSDUs queued for mac80211\t"); 603 PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t"); 604 605 for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) { 606 len += scnprintf(buf + len, buf_len - len, 607 "MSDUs with error:%s\t", get_err_str(i)); 608 PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t"); 609 } 610 611 len += scnprintf(buf + len, buf_len - len, "\n"); 612 for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) { 613 len += scnprintf(buf + len, buf_len - len, 614 "A-MPDU num subframes %s\t", 615 get_num_ampdu_subfrm_str(i)); 616 PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t"); 617 } 618 619 len += scnprintf(buf + len, buf_len - len, "\n"); 620 for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) { 621 len += scnprintf(buf + len, buf_len - len, 622 "A-MSDU num subframes %s\t\t", 623 get_num_amsdu_subfrm_str(i)); 624 PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t"); 625 } 626 627 spin_unlock_bh(&ar->data_lock); 628 629 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); 630 631 kfree(buf); 632 633 mutex_unlock(&ar->conf_mutex); 634 635 return ret; 636} 637 638static const struct file_operations fops_tid_stats_dump = { 639 .open = simple_open, 640 .read = ath10k_dbg_sta_read_tid_stats, 641 .owner = THIS_MODULE, 642 .llseek = default_llseek, 643}; 644 645static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file, 646 char __user *user_buf, 647 size_t count, loff_t *ppos) 648{ 649 struct ieee80211_sta *sta = file->private_data; 650 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 651 struct ath10k *ar = arsta->arvif->ar; 652 struct ath10k_htt_data_stats *stats; 653 const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail", 654 "retry", "ampdu"}; 655 const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"}; 656 int len = 0, i, j, k, retval = 0; 657 const int size = 16 * 4096; 658 char *buf; 659 660 buf = kzalloc(size, GFP_KERNEL); 661 if (!buf) 662 return -ENOMEM; 663 664 mutex_lock(&ar->conf_mutex); 665 666 if (!arsta->tx_stats) { 667 ath10k_warn(ar, "failed to get tx stats"); 668 mutex_unlock(&ar->conf_mutex); 669 kfree(buf); 670 return 0; 671 } 672 673 spin_lock_bh(&ar->data_lock); 674 for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) { 675 for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) { 676 stats = &arsta->tx_stats->stats[k]; 677 len += scnprintf(buf + len, size - len, "%s_%s\n", 678 str_name[k], 679 str[j]); 680 len += scnprintf(buf + len, size - len, 681 " VHT MCS %s\n", 682 str[j]); 683 for (i = 0; i < ATH10K_VHT_MCS_NUM; i++) 684 len += scnprintf(buf + len, size - len, 685 " %llu ", 686 stats->vht[j][i]); 687 len += scnprintf(buf + len, size - len, "\n"); 688 len += scnprintf(buf + len, size - len, " HT MCS %s\n", 689 str[j]); 690 for (i = 0; i < ATH10K_HT_MCS_NUM; i++) 691 len += scnprintf(buf + len, size - len, 692 " %llu ", stats->ht[j][i]); 693 len += scnprintf(buf + len, size - len, "\n"); 694 len += scnprintf(buf + len, size - len, 695 " BW %s (20,5,10,40,80,160 MHz)\n", str[j]); 696 len += scnprintf(buf + len, size - len, 697 " %llu %llu %llu %llu %llu %llu\n", 698 stats->bw[j][0], stats->bw[j][1], 699 stats->bw[j][2], stats->bw[j][3], 700 stats->bw[j][4], stats->bw[j][5]); 701 len += scnprintf(buf + len, size - len, 702 " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]); 703 len += scnprintf(buf + len, size - len, 704 " %llu %llu %llu %llu\n", 705 stats->nss[j][0], stats->nss[j][1], 706 stats->nss[j][2], stats->nss[j][3]); 707 len += scnprintf(buf + len, size - len, 708 " GI %s (LGI,SGI)\n", 709 str[j]); 710 len += scnprintf(buf + len, size - len, " %llu %llu\n", 711 stats->gi[j][0], stats->gi[j][1]); 712 len += scnprintf(buf + len, size - len, 713 " legacy rate %s (1,2 ... Mbps)\n ", 714 str[j]); 715 for (i = 0; i < ATH10K_LEGACY_NUM; i++) 716 len += scnprintf(buf + len, size - len, "%llu ", 717 stats->legacy[j][i]); 718 len += scnprintf(buf + len, size - len, "\n"); 719 len += scnprintf(buf + len, size - len, 720 " Rate table %s (1,2 ... Mbps)\n ", 721 str[j]); 722 for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) { 723 len += scnprintf(buf + len, size - len, "%llu ", 724 stats->rate_table[j][i]); 725 if (!((i + 1) % 8)) 726 len += 727 scnprintf(buf + len, size - len, "\n "); 728 } 729 } 730 } 731 732 len += scnprintf(buf + len, size - len, 733 "\nTX duration\n %llu usecs\n", 734 arsta->tx_stats->tx_duration); 735 len += scnprintf(buf + len, size - len, 736 "BA fails\n %llu\n", arsta->tx_stats->ba_fails); 737 len += scnprintf(buf + len, size - len, 738 "ack fails\n %llu\n", arsta->tx_stats->ack_fails); 739 spin_unlock_bh(&ar->data_lock); 740 741 if (len > size) 742 len = size; 743 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); 744 kfree(buf); 745 746 mutex_unlock(&ar->conf_mutex); 747 return retval; 748} 749 750static const struct file_operations fops_tx_stats = { 751 .read = ath10k_dbg_sta_dump_tx_stats, 752 .open = simple_open, 753 .owner = THIS_MODULE, 754 .llseek = default_llseek, 755}; 756 757void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 758 struct ieee80211_sta *sta, struct dentry *dir) 759{ 760 struct ath10k *ar = hw->priv; 761 762 debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode); 763 debugfs_create_file("addba", 0200, dir, sta, &fops_addba); 764 debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp); 765 debugfs_create_file("delba", 0200, dir, sta, &fops_delba); 766 debugfs_create_file("peer_debug_trigger", 0600, dir, sta, 767 &fops_peer_debug_trigger); 768 debugfs_create_file("dump_tid_stats", 0400, dir, sta, 769 &fops_tid_stats_dump); 770 771 if (ath10k_peer_stats_enabled(ar) && 772 ath10k_debug_is_extd_tx_stats_enabled(ar)) 773 debugfs_create_file("tx_stats", 0400, dir, sta, 774 &fops_tx_stats); 775 debugfs_create_file("peer_ps_state", 0400, dir, sta, 776 &fops_peer_ps_state); 777}