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