Path: blob/main/sys/contrib/dev/athk/ath12k/debugfs_sta.c
178701 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/*2* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.3*/45#include <linux/vmalloc.h>67#include "debugfs_sta.h"8#include "core.h"9#include "peer.h"10#include "debug.h"11#include "debugfs_htt_stats.h"12#include "debugfs.h"1314static15u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,16bool he_rates_avail,17const struct ath12k_rx_peer_rate_stats *stats)18{19static const char *legacy_rate_str[HAL_RX_MAX_NUM_LEGACY_RATES] = {20"1 Mbps", "2 Mbps", "5.5 Mbps", "6 Mbps",21"9 Mbps", "11 Mbps", "12 Mbps", "18 Mbps",22"24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"};23u8 max_bw = HAL_RX_BW_MAX, max_gi = HAL_RX_GI_MAX, max_mcs = HAL_RX_MAX_NSS;24int mcs = 0, bw = 0, nss = 0, gi = 0, bw_num = 0;25u32 i, len = offset, max = max_bw * max_gi * max_mcs;26bool found;2728len += scnprintf(buf + len, size - len, "\nEHT stats:\n");29for (i = 0; i <= HAL_RX_MAX_MCS_BE; i++)30len += scnprintf(buf + len, size - len,31"MCS %d: %llu%s", i, stats->be_mcs_count[i],32(i + 1) % 8 ? "\t" : "\n");3334len += scnprintf(buf + len, size - len, "\nHE stats:\n");35for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++)36len += scnprintf(buf + len, size - len,37"MCS %d: %llu%s", i, stats->he_mcs_count[i],38(i + 1) % 6 ? "\t" : "\n");3940len += scnprintf(buf + len, size - len, "\nVHT stats:\n");41for (i = 0; i <= HAL_RX_MAX_MCS_VHT; i++)42len += scnprintf(buf + len, size - len,43"MCS %d: %llu%s", i, stats->vht_mcs_count[i],44(i + 1) % 5 ? "\t" : "\n");4546len += scnprintf(buf + len, size - len, "\nHT stats:\n");47for (i = 0; i <= HAL_RX_MAX_MCS_HT; i++)48len += scnprintf(buf + len, size - len,49"MCS %d: %llu%s", i, stats->ht_mcs_count[i],50(i + 1) % 8 ? "\t" : "\n");5152len += scnprintf(buf + len, size - len, "\nLegacy stats:\n");53for (i = 0; i < HAL_RX_MAX_NUM_LEGACY_RATES; i++)54len += scnprintf(buf + len, size - len,55"%s: %llu%s", legacy_rate_str[i],56stats->legacy_count[i],57(i + 1) % 4 ? "\t" : "\n");5859len += scnprintf(buf + len, size - len, "\nNSS stats:\n");60for (i = 0; i < HAL_RX_MAX_NSS; i++)61len += scnprintf(buf + len, size - len,62"%dx%d: %llu ", i + 1, i + 1,63stats->nss_count[i]);6465len += scnprintf(buf + len, size - len,66"\n\nGI: 0.8 us %llu 0.4 us %llu 1.6 us %llu 3.2 us %llu\n",67stats->gi_count[0],68stats->gi_count[1],69stats->gi_count[2],70stats->gi_count[3]);7172len += scnprintf(buf + len, size - len,73"BW: 20 MHz %llu 40 MHz %llu 80 MHz %llu 160 MHz %llu 320 MHz %llu\n",74stats->bw_count[0],75stats->bw_count[1],76stats->bw_count[2],77stats->bw_count[3],78stats->bw_count[4]);7980for (i = 0; i < max; i++) {81found = false;8283for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {84if (stats->rx_rate[bw][gi][nss][mcs]) {85found = true;86break;87}88}8990if (!found)91goto skip_report;9293switch (bw) {94case HAL_RX_BW_20MHZ:95bw_num = 20;96break;97case HAL_RX_BW_40MHZ:98bw_num = 40;99break;100case HAL_RX_BW_80MHZ:101bw_num = 80;102break;103case HAL_RX_BW_160MHZ:104bw_num = 160;105break;106case HAL_RX_BW_320MHZ:107bw_num = 320;108break;109}110111len += scnprintf(buf + len, size - len, "\n%d Mhz gi %d us %dx%d : ",112bw_num, gi, nss + 1, nss + 1);113114for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {115if (stats->rx_rate[bw][gi][nss][mcs])116len += scnprintf(buf + len, size - len,117" %d:%llu", mcs,118stats->rx_rate[bw][gi][nss][mcs]);119}120121skip_report:122if (nss++ >= max_mcs - 1) {123nss = 0;124if (gi++ >= max_gi - 1) {125gi = 0;126if (bw < max_bw - 1)127bw++;128}129}130}131132len += scnprintf(buf + len, size - len, "\n");133134return len - offset;135}136137static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,138char __user *user_buf,139size_t count, loff_t *ppos)140{141struct ieee80211_link_sta *link_sta = file->private_data;142struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);143const int size = ATH12K_STA_RX_STATS_BUF_SIZE;144struct ath12k_hw *ah = ahsta->ahvif->ah;145struct ath12k_rx_peer_stats *rx_stats;146struct ath12k_link_sta *arsta;147u8 link_id = link_sta->link_id;148int len = 0, i, ret = 0;149bool he_rates_avail;150struct ath12k *ar;151152wiphy_lock(ah->hw->wiphy);153154if (!(BIT(link_id) & ahsta->links_map)) {155wiphy_unlock(ah->hw->wiphy);156return -ENOENT;157}158159arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);160if (!arsta || !arsta->arvif->ar) {161wiphy_unlock(ah->hw->wiphy);162return -ENOENT;163}164165ar = arsta->arvif->ar;166167u8 *buf __free(kfree) = kzalloc(size, GFP_KERNEL);168if (!buf) {169ret = -ENOENT;170goto out;171}172173spin_lock_bh(&ar->ab->base_lock);174175rx_stats = arsta->rx_stats;176if (!rx_stats) {177ret = -ENOENT;178goto unlock;179}180181len += scnprintf(buf + len, size - len, "RX peer stats:\n\n");182len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",183rx_stats->num_msdu);184len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",185rx_stats->tcp_msdu_count);186len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",187rx_stats->udp_msdu_count);188len += scnprintf(buf + len, size - len, "Num of other MSDUs: %llu\n",189rx_stats->other_msdu_count);190len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",191rx_stats->ampdu_msdu_count);192len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",193rx_stats->non_ampdu_msdu_count);194len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",195rx_stats->stbc_count);196len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",197rx_stats->beamformed_count);198len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",199rx_stats->num_mpdu_fcs_ok);200len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",201rx_stats->num_mpdu_fcs_err);202203he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? true : false;204205len += scnprintf(buf + len, size - len,206"preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu 11BE %llu\n",207rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],208rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],209rx_stats->pream_cnt[4], rx_stats->pream_cnt[6]);210len += scnprintf(buf + len, size - len,211"reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",212rx_stats->reception_type[0], rx_stats->reception_type[1],213rx_stats->reception_type[2], rx_stats->reception_type[3]);214215len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");216for (i = 0; i <= IEEE80211_NUM_TIDS; i++)217len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);218219len += scnprintf(buf + len, size - len, "\nRX Duration:%llu\n",220rx_stats->rx_duration);221222len += scnprintf(buf + len, size - len,223"\nDCM: %llu\nRU26: %llu\nRU52: %llu\nRU106: %llu\nRU242: %llu\nRU484: %llu\nRU996: %llu\nRU996x2: %llu\n",224rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],225rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],226rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],227rx_stats->ru_alloc_cnt[5], rx_stats->ru_alloc_cnt[6]);228229len += scnprintf(buf + len, size - len, "\nRX success packet stats:\n");230len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,231&rx_stats->pkt_stats);232233len += scnprintf(buf + len, size - len, "\n");234235len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n");236len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,237&rx_stats->byte_stats);238239unlock:240spin_unlock_bh(&ar->ab->base_lock);241242if (len)243ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);244out:245wiphy_unlock(ah->hw->wiphy);246return ret;247}248249static const struct file_operations fops_rx_stats = {250.read = ath12k_dbg_sta_dump_rx_stats,251.open = simple_open,252.owner = THIS_MODULE,253.llseek = default_llseek,254};255256static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,257const char __user *buf,258size_t count, loff_t *ppos)259{260struct ieee80211_link_sta *link_sta = file->private_data;261struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);262struct ath12k_hw *ah = ahsta->ahvif->ah;263struct ath12k_rx_peer_stats *rx_stats;264struct ath12k_link_sta *arsta;265u8 link_id = link_sta->link_id;266struct ath12k *ar;267bool reset;268int ret;269270ret = kstrtobool_from_user(buf, count, &reset);271if (ret)272return ret;273274if (!reset)275return -EINVAL;276277wiphy_lock(ah->hw->wiphy);278279if (!(BIT(link_id) & ahsta->links_map)) {280ret = -ENOENT;281goto out;282}283284arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);285if (!arsta || !arsta->arvif->ar) {286ret = -ENOENT;287goto out;288}289290ar = arsta->arvif->ar;291292spin_lock_bh(&ar->ab->base_lock);293294rx_stats = arsta->rx_stats;295if (!rx_stats) {296spin_unlock_bh(&ar->ab->base_lock);297ret = -ENOENT;298goto out;299}300301memset(rx_stats, 0, sizeof(*rx_stats));302spin_unlock_bh(&ar->ab->base_lock);303304ret = count;305out:306wiphy_unlock(ah->hw->wiphy);307return ret;308}309310static const struct file_operations fops_reset_rx_stats = {311.write = ath12k_dbg_sta_reset_rx_stats,312.open = simple_open,313.owner = THIS_MODULE,314.llseek = default_llseek,315};316317void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,318struct ieee80211_vif *vif,319struct ieee80211_link_sta *link_sta,320struct dentry *dir)321{322struct ath12k *ar;323324lockdep_assert_wiphy(hw->wiphy);325326ar = ath12k_get_ar_by_vif(hw, vif, link_sta->link_id);327if (!ar)328return;329330if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {331debugfs_create_file("rx_stats", 0400, dir, link_sta,332&fops_rx_stats);333debugfs_create_file("reset_rx_stats", 0200, dir, link_sta,334&fops_reset_rx_stats);335}336}337338339