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