aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c267
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c379
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h10
6 files changed, 414 insertions, 259 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index eab71e2eb4d7..6cc1aa3449c8 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -291,28 +291,6 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
291 spin_unlock_bh(&ar->data_lock); 291 spin_unlock_bh(&ar->data_lock);
292} 292}
293 293
294static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
295{
296 struct ath10k_fw_stats_peer *i;
297 size_t num = 0;
298
299 list_for_each_entry(i, head, list)
300 ++num;
301
302 return num;
303}
304
305static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
306{
307 struct ath10k_fw_stats_vdev *i;
308 size_t num = 0;
309
310 list_for_each_entry(i, head, list)
311 ++num;
312
313 return num;
314}
315
316void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) 294void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
317{ 295{
318 struct ath10k_fw_stats stats = {}; 296 struct ath10k_fw_stats stats = {};
@@ -349,8 +327,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
349 goto free; 327 goto free;
350 } 328 }
351 329
352 num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); 330 num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
353 num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); 331 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
354 is_start = (list_empty(&ar->debug.fw_stats.pdevs) && 332 is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
355 !list_empty(&stats.pdevs)); 333 !list_empty(&stats.pdevs));
356 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && 334 is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
@@ -435,240 +413,6 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)
435 return 0; 413 return 0;
436} 414}
437 415
438/* FIXME: How to calculate the buffer size sanely? */
439#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
440
441static void ath10k_fw_stats_fill(struct ath10k *ar,
442 struct ath10k_fw_stats *fw_stats,
443 char *buf)
444{
445 unsigned int len = 0;
446 unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
447 const struct ath10k_fw_stats_pdev *pdev;
448 const struct ath10k_fw_stats_vdev *vdev;
449 const struct ath10k_fw_stats_peer *peer;
450 size_t num_peers;
451 size_t num_vdevs;
452 int i;
453
454 spin_lock_bh(&ar->data_lock);
455
456 pdev = list_first_entry_or_null(&fw_stats->pdevs,
457 struct ath10k_fw_stats_pdev, list);
458 if (!pdev) {
459 ath10k_warn(ar, "failed to get pdev stats\n");
460 goto unlock;
461 }
462
463 num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
464 num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
465
466 len += scnprintf(buf + len, buf_len - len, "\n");
467 len += scnprintf(buf + len, buf_len - len, "%30s\n",
468 "ath10k PDEV stats");
469 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
470 "=================");
471
472 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
473 "Channel noise floor", pdev->ch_noise_floor);
474 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
475 "Channel TX power", pdev->chan_tx_power);
476 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
477 "TX frame count", pdev->tx_frame_count);
478 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
479 "RX frame count", pdev->rx_frame_count);
480 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
481 "RX clear count", pdev->rx_clear_count);
482 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
483 "Cycle count", pdev->cycle_count);
484 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
485 "PHY error count", pdev->phy_err_count);
486 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
487 "RTS bad count", pdev->rts_bad);
488 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
489 "RTS good count", pdev->rts_good);
490 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
491 "FCS bad count", pdev->fcs_bad);
492 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
493 "No beacon count", pdev->no_beacons);
494 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
495 "MIB int count", pdev->mib_int_count);
496
497 len += scnprintf(buf + len, buf_len - len, "\n");
498 len += scnprintf(buf + len, buf_len - len, "%30s\n",
499 "ath10k PDEV TX stats");
500 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
501 "=================");
502
503 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
504 "HTT cookies queued", pdev->comp_queued);
505 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
506 "HTT cookies disp.", pdev->comp_delivered);
507 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
508 "MSDU queued", pdev->msdu_enqued);
509 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
510 "MPDU queued", pdev->mpdu_enqued);
511 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
512 "MSDUs dropped", pdev->wmm_drop);
513 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
514 "Local enqued", pdev->local_enqued);
515 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
516 "Local freed", pdev->local_freed);
517 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
518 "HW queued", pdev->hw_queued);
519 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
520 "PPDUs reaped", pdev->hw_reaped);
521 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
522 "Num underruns", pdev->underrun);
523 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
524 "PPDUs cleaned", pdev->tx_abort);
525 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
526 "MPDUs requed", pdev->mpdus_requed);
527 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
528 "Excessive retries", pdev->tx_ko);
529 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
530 "HW rate", pdev->data_rc);
531 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
532 "Sched self tiggers", pdev->self_triggers);
533 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
534 "Dropped due to SW retries",
535 pdev->sw_retry_failure);
536 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
537 "Illegal rate phy errors",
538 pdev->illgl_rate_phy_err);
539 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
540 "Pdev continous xretry", pdev->pdev_cont_xretry);
541 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
542 "TX timeout", pdev->pdev_tx_timeout);
543 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
544 "PDEV resets", pdev->pdev_resets);
545 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
546 "PHY underrun", pdev->phy_underrun);
547 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
548 "MPDU is more than txop limit", pdev->txop_ovf);
549
550 len += scnprintf(buf + len, buf_len - len, "\n");
551 len += scnprintf(buf + len, buf_len - len, "%30s\n",
552 "ath10k PDEV RX stats");
553 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
554 "=================");
555
556 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
557 "Mid PPDU route change",
558 pdev->mid_ppdu_route_change);
559 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
560 "Tot. number of statuses", pdev->status_rcvd);
561 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
562 "Extra frags on rings 0", pdev->r0_frags);
563 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
564 "Extra frags on rings 1", pdev->r1_frags);
565 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
566 "Extra frags on rings 2", pdev->r2_frags);
567 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
568 "Extra frags on rings 3", pdev->r3_frags);
569 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
570 "MSDUs delivered to HTT", pdev->htt_msdus);
571 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
572 "MPDUs delivered to HTT", pdev->htt_mpdus);
573 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
574 "MSDUs delivered to stack", pdev->loc_msdus);
575 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
576 "MPDUs delivered to stack", pdev->loc_mpdus);
577 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
578 "Oversized AMSUs", pdev->oversize_amsdu);
579 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
580 "PHY errors", pdev->phy_errs);
581 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
582 "PHY errors drops", pdev->phy_err_drop);
583 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
584 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
585
586 len += scnprintf(buf + len, buf_len - len, "\n");
587 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
588 "ath10k VDEV stats", num_vdevs);
589 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
590 "=================");
591
592 list_for_each_entry(vdev, &fw_stats->vdevs, list) {
593 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
594 "vdev id", vdev->vdev_id);
595 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
596 "beacon snr", vdev->beacon_snr);
597 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
598 "data snr", vdev->data_snr);
599 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
600 "num rx frames", vdev->num_rx_frames);
601 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
602 "num rts fail", vdev->num_rts_fail);
603 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
604 "num rts success", vdev->num_rts_success);
605 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
606 "num rx err", vdev->num_rx_err);
607 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
608 "num rx discard", vdev->num_rx_discard);
609 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
610 "num tx not acked", vdev->num_tx_not_acked);
611
612 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
613 len += scnprintf(buf + len, buf_len - len,
614 "%25s [%02d] %u\n",
615 "num tx frames", i,
616 vdev->num_tx_frames[i]);
617
618 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
619 len += scnprintf(buf + len, buf_len - len,
620 "%25s [%02d] %u\n",
621 "num tx frames retries", i,
622 vdev->num_tx_frames_retries[i]);
623
624 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
625 len += scnprintf(buf + len, buf_len - len,
626 "%25s [%02d] %u\n",
627 "num tx frames failures", i,
628 vdev->num_tx_frames_failures[i]);
629
630 for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
631 len += scnprintf(buf + len, buf_len - len,
632 "%25s [%02d] 0x%08x\n",
633 "tx rate history", i,
634 vdev->tx_rate_history[i]);
635
636 for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
637 len += scnprintf(buf + len, buf_len - len,
638 "%25s [%02d] %u\n",
639 "beacon rssi history", i,
640 vdev->beacon_rssi_history[i]);
641
642 len += scnprintf(buf + len, buf_len - len, "\n");
643 }
644
645 len += scnprintf(buf + len, buf_len - len, "\n");
646 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
647 "ath10k PEER stats", num_peers);
648 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
649 "=================");
650
651 list_for_each_entry(peer, &fw_stats->peers, list) {
652 len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
653 "Peer MAC address", peer->peer_macaddr);
654 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
655 "Peer RSSI", peer->peer_rssi);
656 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
657 "Peer TX rate", peer->peer_tx_rate);
658 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
659 "Peer RX rate", peer->peer_rx_rate);
660 len += scnprintf(buf + len, buf_len - len, "\n");
661 }
662
663unlock:
664 spin_unlock_bh(&ar->data_lock);
665
666 if (len >= buf_len)
667 buf[len - 1] = 0;
668 else
669 buf[len] = 0;
670}
671
672static int ath10k_fw_stats_open(struct inode *inode, struct file *file) 416static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
673{ 417{
674 struct ath10k *ar = inode->i_private; 418 struct ath10k *ar = inode->i_private;
@@ -694,7 +438,12 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
694 goto err_free; 438 goto err_free;
695 } 439 }
696 440
697 ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf); 441 ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
442 if (ret) {
443 ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
444 goto err_free;
445 }
446
698 file->private_data = buf; 447 file->private_data = buf;
699 448
700 mutex_unlock(&ar->conf_mutex); 449 mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index b07639e9b082..7de780c4ec8d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -55,6 +55,9 @@ enum ath10k_dbg_aggr_mode {
55 ATH10K_DBG_AGGR_MODE_MAX, 55 ATH10K_DBG_AGGR_MODE_MAX,
56}; 56};
57 57
58/* FIXME: How to calculate the buffer size sanely? */
59#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
60
58extern unsigned int ath10k_debug_mask; 61extern unsigned int ath10k_debug_mask;
59 62
60__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); 63__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index d3bc6df861e4..b54aa08cb25c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -179,6 +179,9 @@ struct wmi_ops {
179 struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); 179 struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable);
180 struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar, 180 struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar,
181 u32 param); 181 u32 param);
182 void (*fw_stats_fill)(struct ath10k *ar,
183 struct ath10k_fw_stats *fw_stats,
184 char *buf);
182}; 185};
183 186
184int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); 187int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
@@ -1289,4 +1292,14 @@ ath10k_wmi_pdev_get_tpc_config(struct ath10k *ar, u32 param)
1289 ar->wmi.cmd->pdev_get_tpc_config_cmdid); 1292 ar->wmi.cmd->pdev_get_tpc_config_cmdid);
1290} 1293}
1291 1294
1295static inline int
1296ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats,
1297 char *buf)
1298{
1299 if (!ar->wmi.ops->fw_stats_fill)
1300 return -EOPNOTSUPP;
1301
1302 ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf);
1303 return 0;
1304}
1292#endif 1305#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index b5849b3fd2f0..8f835480a62c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3468,6 +3468,7 @@ static const struct wmi_ops wmi_tlv_ops = {
3468 .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, 3468 .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
3469 .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, 3469 .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
3470 .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, 3470 .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
3471 .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
3471}; 3472};
3472 3473
3473/************/ 3474/************/
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 063469b69d5f..6e7d7a7f6a97 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -6621,6 +6621,381 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
6621 return skb; 6621 return skb;
6622} 6622}
6623 6623
6624size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
6625{
6626 struct ath10k_fw_stats_peer *i;
6627 size_t num = 0;
6628
6629 list_for_each_entry(i, head, list)
6630 ++num;
6631
6632 return num;
6633}
6634
6635size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
6636{
6637 struct ath10k_fw_stats_vdev *i;
6638 size_t num = 0;
6639
6640 list_for_each_entry(i, head, list)
6641 ++num;
6642
6643 return num;
6644}
6645
6646static void
6647ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
6648 char *buf, u32 *length)
6649{
6650 u32 len = *length;
6651 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6652
6653 len += scnprintf(buf + len, buf_len - len, "\n");
6654 len += scnprintf(buf + len, buf_len - len, "%30s\n",
6655 "ath10k PDEV stats");
6656 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6657 "=================");
6658
6659 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6660 "Channel noise floor", pdev->ch_noise_floor);
6661 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6662 "Channel TX power", pdev->chan_tx_power);
6663 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6664 "TX frame count", pdev->tx_frame_count);
6665 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6666 "RX frame count", pdev->rx_frame_count);
6667 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6668 "RX clear count", pdev->rx_clear_count);
6669 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6670 "Cycle count", pdev->cycle_count);
6671 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6672 "PHY error count", pdev->phy_err_count);
6673
6674 *length = len;
6675}
6676
6677static void
6678ath10k_wmi_fw_pdev_extra_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
6679 char *buf, u32 *length)
6680{
6681 u32 len = *length;
6682 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6683
6684 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6685 "RTS bad count", pdev->rts_bad);
6686 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6687 "RTS good count", pdev->rts_good);
6688 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6689 "FCS bad count", pdev->fcs_bad);
6690 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6691 "No beacon count", pdev->no_beacons);
6692 len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
6693 "MIB int count", pdev->mib_int_count);
6694
6695 len += scnprintf(buf + len, buf_len - len, "\n");
6696 *length = len;
6697}
6698
6699static void
6700ath10k_wmi_fw_pdev_tx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
6701 char *buf, u32 *length)
6702{
6703 u32 len = *length;
6704 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6705
6706 len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
6707 "ath10k PDEV TX stats");
6708 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6709 "=================");
6710
6711 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6712 "HTT cookies queued", pdev->comp_queued);
6713 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6714 "HTT cookies disp.", pdev->comp_delivered);
6715 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6716 "MSDU queued", pdev->msdu_enqued);
6717 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6718 "MPDU queued", pdev->mpdu_enqued);
6719 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6720 "MSDUs dropped", pdev->wmm_drop);
6721 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6722 "Local enqued", pdev->local_enqued);
6723 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6724 "Local freed", pdev->local_freed);
6725 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6726 "HW queued", pdev->hw_queued);
6727 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6728 "PPDUs reaped", pdev->hw_reaped);
6729 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6730 "Num underruns", pdev->underrun);
6731 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6732 "PPDUs cleaned", pdev->tx_abort);
6733 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6734 "MPDUs requed", pdev->mpdus_requed);
6735 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6736 "Excessive retries", pdev->tx_ko);
6737 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6738 "HW rate", pdev->data_rc);
6739 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6740 "Sched self tiggers", pdev->self_triggers);
6741 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6742 "Dropped due to SW retries",
6743 pdev->sw_retry_failure);
6744 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6745 "Illegal rate phy errors",
6746 pdev->illgl_rate_phy_err);
6747 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6748 "Pdev continuous xretry", pdev->pdev_cont_xretry);
6749 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6750 "TX timeout", pdev->pdev_tx_timeout);
6751 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6752 "PDEV resets", pdev->pdev_resets);
6753 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6754 "PHY underrun", pdev->phy_underrun);
6755 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6756 "MPDU is more than txop limit", pdev->txop_ovf);
6757 *length = len;
6758}
6759
6760static void
6761ath10k_wmi_fw_pdev_rx_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
6762 char *buf, u32 *length)
6763{
6764 u32 len = *length;
6765 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6766
6767 len += scnprintf(buf + len, buf_len - len, "\n%30s\n",
6768 "ath10k PDEV RX stats");
6769 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6770 "=================");
6771
6772 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6773 "Mid PPDU route change",
6774 pdev->mid_ppdu_route_change);
6775 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6776 "Tot. number of statuses", pdev->status_rcvd);
6777 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6778 "Extra frags on rings 0", pdev->r0_frags);
6779 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6780 "Extra frags on rings 1", pdev->r1_frags);
6781 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6782 "Extra frags on rings 2", pdev->r2_frags);
6783 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6784 "Extra frags on rings 3", pdev->r3_frags);
6785 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6786 "MSDUs delivered to HTT", pdev->htt_msdus);
6787 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6788 "MPDUs delivered to HTT", pdev->htt_mpdus);
6789 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6790 "MSDUs delivered to stack", pdev->loc_msdus);
6791 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6792 "MPDUs delivered to stack", pdev->loc_mpdus);
6793 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6794 "Oversized AMSUs", pdev->oversize_amsdu);
6795 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6796 "PHY errors", pdev->phy_errs);
6797 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6798 "PHY errors drops", pdev->phy_err_drop);
6799 len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
6800 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
6801 *length = len;
6802}
6803
6804static void
6805ath10k_wmi_fw_vdev_stats_fill(const struct ath10k_fw_stats_vdev *vdev,
6806 char *buf, u32 *length)
6807{
6808 u32 len = *length;
6809 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6810 int i;
6811
6812 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6813 "vdev id", vdev->vdev_id);
6814 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6815 "beacon snr", vdev->beacon_snr);
6816 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6817 "data snr", vdev->data_snr);
6818 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6819 "num rx frames", vdev->num_rx_frames);
6820 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6821 "num rts fail", vdev->num_rts_fail);
6822 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6823 "num rts success", vdev->num_rts_success);
6824 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6825 "num rx err", vdev->num_rx_err);
6826 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6827 "num rx discard", vdev->num_rx_discard);
6828 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6829 "num tx not acked", vdev->num_tx_not_acked);
6830
6831 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
6832 len += scnprintf(buf + len, buf_len - len,
6833 "%25s [%02d] %u\n",
6834 "num tx frames", i,
6835 vdev->num_tx_frames[i]);
6836
6837 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
6838 len += scnprintf(buf + len, buf_len - len,
6839 "%25s [%02d] %u\n",
6840 "num tx frames retries", i,
6841 vdev->num_tx_frames_retries[i]);
6842
6843 for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
6844 len += scnprintf(buf + len, buf_len - len,
6845 "%25s [%02d] %u\n",
6846 "num tx frames failures", i,
6847 vdev->num_tx_frames_failures[i]);
6848
6849 for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
6850 len += scnprintf(buf + len, buf_len - len,
6851 "%25s [%02d] 0x%08x\n",
6852 "tx rate history", i,
6853 vdev->tx_rate_history[i]);
6854
6855 for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
6856 len += scnprintf(buf + len, buf_len - len,
6857 "%25s [%02d] %u\n",
6858 "beacon rssi history", i,
6859 vdev->beacon_rssi_history[i]);
6860
6861 len += scnprintf(buf + len, buf_len - len, "\n");
6862 *length = len;
6863}
6864
6865static void
6866ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer,
6867 char *buf, u32 *length)
6868{
6869 u32 len = *length;
6870 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6871
6872 len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
6873 "Peer MAC address", peer->peer_macaddr);
6874 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6875 "Peer RSSI", peer->peer_rssi);
6876 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6877 "Peer TX rate", peer->peer_tx_rate);
6878 len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
6879 "Peer RX rate", peer->peer_rx_rate);
6880 len += scnprintf(buf + len, buf_len - len, "\n");
6881 *length = len;
6882}
6883
6884void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
6885 struct ath10k_fw_stats *fw_stats,
6886 char *buf)
6887{
6888 u32 len = 0;
6889 u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
6890 const struct ath10k_fw_stats_pdev *pdev;
6891 const struct ath10k_fw_stats_vdev *vdev;
6892 const struct ath10k_fw_stats_peer *peer;
6893 size_t num_peers;
6894 size_t num_vdevs;
6895
6896 spin_lock_bh(&ar->data_lock);
6897
6898 pdev = list_first_entry_or_null(&fw_stats->pdevs,
6899 struct ath10k_fw_stats_pdev, list);
6900 if (!pdev) {
6901 ath10k_warn(ar, "failed to get pdev stats\n");
6902 goto unlock;
6903 }
6904
6905 num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
6906 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
6907
6908 ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
6909 ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
6910 ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
6911
6912 len += scnprintf(buf + len, buf_len - len, "\n");
6913 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
6914 "ath10k VDEV stats", num_vdevs);
6915 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6916 "=================");
6917
6918 list_for_each_entry(vdev, &fw_stats->vdevs, list) {
6919 ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
6920 }
6921
6922 len += scnprintf(buf + len, buf_len - len, "\n");
6923 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
6924 "ath10k PEER stats", num_peers);
6925 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6926 "=================");
6927
6928 list_for_each_entry(peer, &fw_stats->peers, list) {
6929 ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
6930 }
6931
6932unlock:
6933 spin_unlock_bh(&ar->data_lock);
6934
6935 if (len >= buf_len)
6936 buf[len - 1] = 0;
6937 else
6938 buf[len] = 0;
6939}
6940
6941void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
6942 struct ath10k_fw_stats *fw_stats,
6943 char *buf)
6944{
6945 unsigned int len = 0;
6946 unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
6947 const struct ath10k_fw_stats_pdev *pdev;
6948 const struct ath10k_fw_stats_vdev *vdev;
6949 const struct ath10k_fw_stats_peer *peer;
6950 size_t num_peers;
6951 size_t num_vdevs;
6952
6953 spin_lock_bh(&ar->data_lock);
6954
6955 pdev = list_first_entry_or_null(&fw_stats->pdevs,
6956 struct ath10k_fw_stats_pdev, list);
6957 if (!pdev) {
6958 ath10k_warn(ar, "failed to get pdev stats\n");
6959 goto unlock;
6960 }
6961
6962 num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
6963 num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
6964
6965 ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
6966 ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
6967 ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
6968 ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
6969
6970 len += scnprintf(buf + len, buf_len - len, "\n");
6971 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
6972 "ath10k VDEV stats", num_vdevs);
6973 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6974 "=================");
6975
6976 list_for_each_entry(vdev, &fw_stats->vdevs, list) {
6977 ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
6978 }
6979
6980 len += scnprintf(buf + len, buf_len - len, "\n");
6981 len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
6982 "ath10k PEER stats", num_peers);
6983 len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
6984 "=================");
6985
6986 list_for_each_entry(peer, &fw_stats->peers, list) {
6987 ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
6988 }
6989
6990unlock:
6991 spin_unlock_bh(&ar->data_lock);
6992
6993 if (len >= buf_len)
6994 buf[len - 1] = 0;
6995 else
6996 buf[len] = 0;
6997}
6998
6624static const struct wmi_ops wmi_ops = { 6999static const struct wmi_ops wmi_ops = {
6625 .rx = ath10k_wmi_op_rx, 7000 .rx = ath10k_wmi_op_rx,
6626 .map_svc = wmi_main_svc_map, 7001 .map_svc = wmi_main_svc_map,
@@ -6679,6 +7054,7 @@ static const struct wmi_ops wmi_ops = {
6679 .gen_addba_send = ath10k_wmi_op_gen_addba_send, 7054 .gen_addba_send = ath10k_wmi_op_gen_addba_send,
6680 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, 7055 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
6681 .gen_delba_send = ath10k_wmi_op_gen_delba_send, 7056 .gen_delba_send = ath10k_wmi_op_gen_delba_send,
7057 .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
6682 /* .gen_bcn_tmpl not implemented */ 7058 /* .gen_bcn_tmpl not implemented */
6683 /* .gen_prb_tmpl not implemented */ 7059 /* .gen_prb_tmpl not implemented */
6684 /* .gen_p2p_go_bcn_ie not implemented */ 7060 /* .gen_p2p_go_bcn_ie not implemented */
@@ -6744,6 +7120,7 @@ static const struct wmi_ops wmi_10_1_ops = {
6744 .gen_addba_send = ath10k_wmi_op_gen_addba_send, 7120 .gen_addba_send = ath10k_wmi_op_gen_addba_send,
6745 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, 7121 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
6746 .gen_delba_send = ath10k_wmi_op_gen_delba_send, 7122 .gen_delba_send = ath10k_wmi_op_gen_delba_send,
7123 .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
6747 /* .gen_bcn_tmpl not implemented */ 7124 /* .gen_bcn_tmpl not implemented */
6748 /* .gen_prb_tmpl not implemented */ 7125 /* .gen_prb_tmpl not implemented */
6749 /* .gen_p2p_go_bcn_ie not implemented */ 7126 /* .gen_p2p_go_bcn_ie not implemented */
@@ -6810,6 +7187,7 @@ static const struct wmi_ops wmi_10_2_ops = {
6810 .gen_addba_send = ath10k_wmi_op_gen_addba_send, 7187 .gen_addba_send = ath10k_wmi_op_gen_addba_send,
6811 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, 7188 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
6812 .gen_delba_send = ath10k_wmi_op_gen_delba_send, 7189 .gen_delba_send = ath10k_wmi_op_gen_delba_send,
7190 .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
6813}; 7191};
6814 7192
6815static const struct wmi_ops wmi_10_2_4_ops = { 7193static const struct wmi_ops wmi_10_2_4_ops = {
@@ -6872,6 +7250,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
6872 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, 7250 .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
6873 .gen_delba_send = ath10k_wmi_op_gen_delba_send, 7251 .gen_delba_send = ath10k_wmi_op_gen_delba_send,
6874 .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, 7252 .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
7253 .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
6875 /* .gen_bcn_tmpl not implemented */ 7254 /* .gen_bcn_tmpl not implemented */
6876 /* .gen_prb_tmpl not implemented */ 7255 /* .gen_prb_tmpl not implemented */
6877 /* .gen_p2p_go_bcn_ie not implemented */ 7256 /* .gen_p2p_go_bcn_ie not implemented */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4c373b27c1a6..6e84d1c1a6ca 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6098,6 +6098,7 @@ struct ath10k;
6098struct ath10k_vif; 6098struct ath10k_vif;
6099struct ath10k_fw_stats_pdev; 6099struct ath10k_fw_stats_pdev;
6100struct ath10k_fw_stats_peer; 6100struct ath10k_fw_stats_peer;
6101struct ath10k_fw_stats;
6101 6102
6102int ath10k_wmi_attach(struct ath10k *ar); 6103int ath10k_wmi_attach(struct ath10k *ar);
6103void ath10k_wmi_detach(struct ath10k *ar); 6104void ath10k_wmi_detach(struct ath10k *ar);
@@ -6179,4 +6180,13 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
6179int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb); 6180int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
6180int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf, 6181int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf,
6181 int left_len, struct wmi_phyerr_ev_arg *arg); 6182 int left_len, struct wmi_phyerr_ev_arg *arg);
6183void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
6184 struct ath10k_fw_stats *fw_stats,
6185 char *buf);
6186void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
6187 struct ath10k_fw_stats *fw_stats,
6188 char *buf);
6189size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
6190size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
6191
6182#endif /* _WMI_H_ */ 6192#endif /* _WMI_H_ */