Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause-Clear
0002 /*
0003  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/vmalloc.h>
0007 
0008 #include "debugfs_sta.h"
0009 #include "core.h"
0010 #include "peer.h"
0011 #include "debug.h"
0012 #include "dp_tx.h"
0013 #include "debugfs_htt_stats.h"
0014 
0015 void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
0016                      struct ath11k_per_peer_tx_stats *peer_stats,
0017                      u8 legacy_rate_idx)
0018 {
0019     struct rate_info *txrate = &arsta->txrate;
0020     struct ath11k_htt_tx_stats *tx_stats;
0021     int gi, mcs, bw, nss;
0022 
0023     if (!arsta->tx_stats)
0024         return;
0025 
0026     tx_stats = arsta->tx_stats;
0027     gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
0028     mcs = txrate->mcs;
0029     bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
0030     nss = txrate->nss - 1;
0031 
0032 #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
0033 
0034     if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
0035         STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
0036         STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
0037         STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
0038         STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
0039         STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
0040         STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
0041     } else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
0042         STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
0043         STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
0044         STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
0045         STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
0046         STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
0047         STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
0048     } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
0049         STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
0050         STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
0051         STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
0052         STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
0053         STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
0054         STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
0055     } else {
0056         mcs = legacy_rate_idx;
0057 
0058         STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
0059         STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
0060         STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
0061         STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
0062         STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
0063         STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
0064     }
0065 
0066     if (peer_stats->is_ampdu) {
0067         tx_stats->ba_fails += peer_stats->ba_fails;
0068 
0069         if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
0070             STATS_OP_FMT(AMPDU).he[0][mcs] +=
0071             peer_stats->succ_bytes + peer_stats->retry_bytes;
0072             STATS_OP_FMT(AMPDU).he[1][mcs] +=
0073             peer_stats->succ_pkts + peer_stats->retry_pkts;
0074         } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
0075             STATS_OP_FMT(AMPDU).ht[0][mcs] +=
0076             peer_stats->succ_bytes + peer_stats->retry_bytes;
0077             STATS_OP_FMT(AMPDU).ht[1][mcs] +=
0078             peer_stats->succ_pkts + peer_stats->retry_pkts;
0079         } else {
0080             STATS_OP_FMT(AMPDU).vht[0][mcs] +=
0081             peer_stats->succ_bytes + peer_stats->retry_bytes;
0082             STATS_OP_FMT(AMPDU).vht[1][mcs] +=
0083             peer_stats->succ_pkts + peer_stats->retry_pkts;
0084         }
0085         STATS_OP_FMT(AMPDU).bw[0][bw] +=
0086             peer_stats->succ_bytes + peer_stats->retry_bytes;
0087         STATS_OP_FMT(AMPDU).nss[0][nss] +=
0088             peer_stats->succ_bytes + peer_stats->retry_bytes;
0089         STATS_OP_FMT(AMPDU).gi[0][gi] +=
0090             peer_stats->succ_bytes + peer_stats->retry_bytes;
0091         STATS_OP_FMT(AMPDU).bw[1][bw] +=
0092             peer_stats->succ_pkts + peer_stats->retry_pkts;
0093         STATS_OP_FMT(AMPDU).nss[1][nss] +=
0094             peer_stats->succ_pkts + peer_stats->retry_pkts;
0095         STATS_OP_FMT(AMPDU).gi[1][gi] +=
0096             peer_stats->succ_pkts + peer_stats->retry_pkts;
0097     } else {
0098         tx_stats->ack_fails += peer_stats->ba_fails;
0099     }
0100 
0101     STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
0102     STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
0103     STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
0104 
0105     STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
0106     STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
0107     STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
0108 
0109     STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
0110     STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
0111     STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
0112 
0113     STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
0114     STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
0115     STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
0116 
0117     STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
0118     STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
0119     STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
0120 
0121     STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
0122     STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
0123     STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
0124 
0125     tx_stats->tx_duration += peer_stats->duration;
0126 }
0127 
0128 void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
0129                        struct hal_tx_status *ts)
0130 {
0131     ath11k_dp_tx_update_txcompl(ar, ts);
0132 }
0133 
0134 static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
0135                         char __user *user_buf,
0136                         size_t count, loff_t *ppos)
0137 {
0138     struct ieee80211_sta *sta = file->private_data;
0139     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0140     struct ath11k *ar = arsta->arvif->ar;
0141     struct ath11k_htt_data_stats *stats;
0142     static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
0143                                   "retry", "ampdu"};
0144     static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
0145     int len = 0, i, j, k, retval = 0;
0146     const int size = 2 * 4096;
0147     char *buf;
0148 
0149     if (!arsta->tx_stats)
0150         return -ENOENT;
0151 
0152     buf = kzalloc(size, GFP_KERNEL);
0153     if (!buf)
0154         return -ENOMEM;
0155 
0156     mutex_lock(&ar->conf_mutex);
0157 
0158     spin_lock_bh(&ar->data_lock);
0159     for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
0160         for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
0161             stats = &arsta->tx_stats->stats[k];
0162             len += scnprintf(buf + len, size - len, "%s_%s\n",
0163                      str_name[k],
0164                      str[j]);
0165             len += scnprintf(buf + len, size - len,
0166                      " HE MCS %s\n",
0167                      str[j]);
0168             for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
0169                 len += scnprintf(buf + len, size - len,
0170                          "  %llu ",
0171                          stats->he[j][i]);
0172             len += scnprintf(buf + len, size - len, "\n");
0173             len += scnprintf(buf + len, size - len,
0174                      " VHT MCS %s\n",
0175                      str[j]);
0176             for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
0177                 len += scnprintf(buf + len, size - len,
0178                          "  %llu ",
0179                          stats->vht[j][i]);
0180             len += scnprintf(buf + len, size - len, "\n");
0181             len += scnprintf(buf + len, size - len, " HT MCS %s\n",
0182                      str[j]);
0183             for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
0184                 len += scnprintf(buf + len, size - len,
0185                          "  %llu ", stats->ht[j][i]);
0186             len += scnprintf(buf + len, size - len, "\n");
0187             len += scnprintf(buf + len, size - len,
0188                     " BW %s (20,40,80,160 MHz)\n", str[j]);
0189             len += scnprintf(buf + len, size - len,
0190                      "  %llu %llu %llu %llu\n",
0191                      stats->bw[j][0], stats->bw[j][1],
0192                      stats->bw[j][2], stats->bw[j][3]);
0193             len += scnprintf(buf + len, size - len,
0194                      " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
0195             len += scnprintf(buf + len, size - len,
0196                      "  %llu %llu %llu %llu\n",
0197                      stats->nss[j][0], stats->nss[j][1],
0198                      stats->nss[j][2], stats->nss[j][3]);
0199             len += scnprintf(buf + len, size - len,
0200                      " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
0201                      str[j]);
0202             len += scnprintf(buf + len, size - len,
0203                      "  %llu %llu %llu %llu\n",
0204                      stats->gi[j][0], stats->gi[j][1],
0205                      stats->gi[j][2], stats->gi[j][3]);
0206             len += scnprintf(buf + len, size - len,
0207                      " legacy rate %s (1,2 ... Mbps)\n  ",
0208                      str[j]);
0209             for (i = 0; i < ATH11K_LEGACY_NUM; i++)
0210                 len += scnprintf(buf + len, size - len, "%llu ",
0211                          stats->legacy[j][i]);
0212             len += scnprintf(buf + len, size - len, "\n");
0213         }
0214     }
0215 
0216     len += scnprintf(buf + len, size - len,
0217              "\nTX duration\n %llu usecs\n",
0218              arsta->tx_stats->tx_duration);
0219     len += scnprintf(buf + len, size - len,
0220             "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
0221     len += scnprintf(buf + len, size - len,
0222             "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
0223     spin_unlock_bh(&ar->data_lock);
0224 
0225     if (len > size)
0226         len = size;
0227     retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0228     kfree(buf);
0229 
0230     mutex_unlock(&ar->conf_mutex);
0231     return retval;
0232 }
0233 
0234 static const struct file_operations fops_tx_stats = {
0235     .read = ath11k_dbg_sta_dump_tx_stats,
0236     .open = simple_open,
0237     .owner = THIS_MODULE,
0238     .llseek = default_llseek,
0239 };
0240 
0241 static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
0242                         char __user *user_buf,
0243                         size_t count, loff_t *ppos)
0244 {
0245     struct ieee80211_sta *sta = file->private_data;
0246     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0247     struct ath11k *ar = arsta->arvif->ar;
0248     struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
0249     int len = 0, i, retval = 0;
0250     const int size = 4096;
0251     char *buf;
0252 
0253     if (!rx_stats)
0254         return -ENOENT;
0255 
0256     buf = kzalloc(size, GFP_KERNEL);
0257     if (!buf)
0258         return -ENOMEM;
0259 
0260     mutex_lock(&ar->conf_mutex);
0261     spin_lock_bh(&ar->ab->base_lock);
0262 
0263     len += scnprintf(buf + len, size - len, "RX peer stats:\n");
0264     len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
0265              rx_stats->num_msdu);
0266     len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
0267              rx_stats->tcp_msdu_count);
0268     len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
0269              rx_stats->udp_msdu_count);
0270     len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
0271              rx_stats->ampdu_msdu_count);
0272     len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
0273              rx_stats->non_ampdu_msdu_count);
0274     len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
0275              rx_stats->stbc_count);
0276     len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
0277              rx_stats->beamformed_count);
0278     len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
0279              rx_stats->num_mpdu_fcs_ok);
0280     len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
0281              rx_stats->num_mpdu_fcs_err);
0282     len += scnprintf(buf + len, size - len,
0283              "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
0284              rx_stats->gi_count[0], rx_stats->gi_count[1],
0285              rx_stats->gi_count[2], rx_stats->gi_count[3]);
0286     len += scnprintf(buf + len, size - len,
0287              "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
0288              rx_stats->bw_count[0], rx_stats->bw_count[1],
0289              rx_stats->bw_count[2], rx_stats->bw_count[3]);
0290     len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
0291              rx_stats->coding_count[0], rx_stats->coding_count[1]);
0292     len += scnprintf(buf + len, size - len,
0293              "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
0294              rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
0295              rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
0296              rx_stats->pream_cnt[4]);
0297     len += scnprintf(buf + len, size - len,
0298              "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
0299              rx_stats->reception_type[0], rx_stats->reception_type[1],
0300              rx_stats->reception_type[2], rx_stats->reception_type[3]);
0301     len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
0302     for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
0303         len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
0304     len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
0305     for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
0306         len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
0307     len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
0308     for (i = 0; i < HAL_RX_MAX_NSS; i++)
0309         len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
0310     len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
0311              rx_stats->rx_duration);
0312     len += scnprintf(buf + len, size - len,
0313              "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
0314              rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
0315              rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
0316              rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
0317              rx_stats->ru_alloc_cnt[5]);
0318 
0319     len += scnprintf(buf + len, size - len, "\n");
0320 
0321     spin_unlock_bh(&ar->ab->base_lock);
0322 
0323     if (len > size)
0324         len = size;
0325     retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0326     kfree(buf);
0327 
0328     mutex_unlock(&ar->conf_mutex);
0329     return retval;
0330 }
0331 
0332 static const struct file_operations fops_rx_stats = {
0333     .read = ath11k_dbg_sta_dump_rx_stats,
0334     .open = simple_open,
0335     .owner = THIS_MODULE,
0336     .llseek = default_llseek,
0337 };
0338 
0339 static int
0340 ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
0341 {
0342     struct ieee80211_sta *sta = inode->i_private;
0343     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0344     struct ath11k *ar = arsta->arvif->ar;
0345     struct debug_htt_stats_req *stats_req;
0346     int type = ar->debug.htt_stats.type;
0347     int ret;
0348 
0349     if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
0350          type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
0351         type == ATH11K_DBG_HTT_EXT_STATS_RESET)
0352         return -EPERM;
0353 
0354     stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
0355     if (!stats_req)
0356         return -ENOMEM;
0357 
0358     mutex_lock(&ar->conf_mutex);
0359     ar->debug.htt_stats.stats_req = stats_req;
0360     stats_req->type = type;
0361     memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
0362     ret = ath11k_debugfs_htt_stats_req(ar);
0363     mutex_unlock(&ar->conf_mutex);
0364     if (ret < 0)
0365         goto out;
0366 
0367     file->private_data = stats_req;
0368     return 0;
0369 out:
0370     vfree(stats_req);
0371     ar->debug.htt_stats.stats_req = NULL;
0372     return ret;
0373 }
0374 
0375 static int
0376 ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
0377 {
0378     struct ieee80211_sta *sta = inode->i_private;
0379     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0380     struct ath11k *ar = arsta->arvif->ar;
0381 
0382     mutex_lock(&ar->conf_mutex);
0383     vfree(file->private_data);
0384     ar->debug.htt_stats.stats_req = NULL;
0385     mutex_unlock(&ar->conf_mutex);
0386 
0387     return 0;
0388 }
0389 
0390 static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
0391                           char __user *user_buf,
0392                           size_t count, loff_t *ppos)
0393 {
0394     struct debug_htt_stats_req *stats_req = file->private_data;
0395     char *buf;
0396     u32 length = 0;
0397 
0398     buf = stats_req->buf;
0399     length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
0400     return simple_read_from_buffer(user_buf, count, ppos, buf, length);
0401 }
0402 
0403 static const struct file_operations fops_htt_peer_stats = {
0404     .open = ath11k_dbg_sta_open_htt_peer_stats,
0405     .release = ath11k_dbg_sta_release_htt_peer_stats,
0406     .read = ath11k_dbg_sta_read_htt_peer_stats,
0407     .owner = THIS_MODULE,
0408     .llseek = default_llseek,
0409 };
0410 
0411 static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
0412                         const char __user *buf,
0413                         size_t count, loff_t *ppos)
0414 {
0415     struct ieee80211_sta *sta = file->private_data;
0416     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0417     struct ath11k *ar = arsta->arvif->ar;
0418     int ret, enable;
0419 
0420     mutex_lock(&ar->conf_mutex);
0421 
0422     if (ar->state != ATH11K_STATE_ON) {
0423         ret = -ENETDOWN;
0424         goto out;
0425     }
0426 
0427     ret = kstrtoint_from_user(buf, count, 0, &enable);
0428     if (ret)
0429         goto out;
0430 
0431     ar->debug.pktlog_peer_valid = enable;
0432     memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
0433 
0434     /* Send peer based pktlog enable/disable */
0435     ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
0436     if (ret) {
0437         ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
0438                 sta->addr, ret);
0439         goto out;
0440     }
0441 
0442     ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
0443            enable);
0444     ret = count;
0445 
0446 out:
0447     mutex_unlock(&ar->conf_mutex);
0448     return ret;
0449 }
0450 
0451 static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
0452                            char __user *ubuf,
0453                            size_t count, loff_t *ppos)
0454 {
0455     struct ieee80211_sta *sta = file->private_data;
0456     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0457     struct ath11k *ar = arsta->arvif->ar;
0458     char buf[32] = {0};
0459     int len;
0460 
0461     mutex_lock(&ar->conf_mutex);
0462     len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
0463             ar->debug.pktlog_peer_valid,
0464             ar->debug.pktlog_peer_addr);
0465     mutex_unlock(&ar->conf_mutex);
0466 
0467     return simple_read_from_buffer(ubuf, count, ppos, buf, len);
0468 }
0469 
0470 static const struct file_operations fops_peer_pktlog = {
0471     .write = ath11k_dbg_sta_write_peer_pktlog,
0472     .read = ath11k_dbg_sta_read_peer_pktlog,
0473     .open = simple_open,
0474     .owner = THIS_MODULE,
0475     .llseek = default_llseek,
0476 };
0477 
0478 static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
0479                       const char __user *user_buf,
0480                       size_t count, loff_t *ppos)
0481 {
0482     struct ieee80211_sta *sta = file->private_data;
0483     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0484     struct ath11k *ar = arsta->arvif->ar;
0485     u32 tid, initiator, reason;
0486     int ret;
0487     char buf[64] = {0};
0488 
0489     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0490                      user_buf, count);
0491     if (ret <= 0)
0492         return ret;
0493 
0494     ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
0495     if (ret != 3)
0496         return -EINVAL;
0497 
0498     /* Valid TID values are 0 through 15 */
0499     if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
0500         return -EINVAL;
0501 
0502     mutex_lock(&ar->conf_mutex);
0503     if (ar->state != ATH11K_STATE_ON ||
0504         arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
0505         ret = count;
0506         goto out;
0507     }
0508 
0509     ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
0510                     tid, initiator, reason);
0511     if (ret) {
0512         ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
0513                 arsta->arvif->vdev_id, sta->addr, tid, initiator,
0514                 reason);
0515     }
0516     ret = count;
0517 out:
0518     mutex_unlock(&ar->conf_mutex);
0519     return ret;
0520 }
0521 
0522 static const struct file_operations fops_delba = {
0523     .write = ath11k_dbg_sta_write_delba,
0524     .open = simple_open,
0525     .owner = THIS_MODULE,
0526     .llseek = default_llseek,
0527 };
0528 
0529 static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
0530                            const char __user *user_buf,
0531                            size_t count, loff_t *ppos)
0532 {
0533     struct ieee80211_sta *sta = file->private_data;
0534     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0535     struct ath11k *ar = arsta->arvif->ar;
0536     u32 tid, status;
0537     int ret;
0538     char buf[64] = {0};
0539 
0540     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0541                      user_buf, count);
0542     if (ret <= 0)
0543         return ret;
0544 
0545     ret = sscanf(buf, "%u %u", &tid, &status);
0546     if (ret != 2)
0547         return -EINVAL;
0548 
0549     /* Valid TID values are 0 through 15 */
0550     if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
0551         return -EINVAL;
0552 
0553     mutex_lock(&ar->conf_mutex);
0554     if (ar->state != ATH11K_STATE_ON ||
0555         arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
0556         ret = count;
0557         goto out;
0558     }
0559 
0560     ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
0561                     tid, status);
0562     if (ret) {
0563         ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
0564                 arsta->arvif->vdev_id, sta->addr, tid, status);
0565     }
0566     ret = count;
0567 out:
0568     mutex_unlock(&ar->conf_mutex);
0569     return ret;
0570 }
0571 
0572 static const struct file_operations fops_addba_resp = {
0573     .write = ath11k_dbg_sta_write_addba_resp,
0574     .open = simple_open,
0575     .owner = THIS_MODULE,
0576     .llseek = default_llseek,
0577 };
0578 
0579 static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
0580                       const char __user *user_buf,
0581                       size_t count, loff_t *ppos)
0582 {
0583     struct ieee80211_sta *sta = file->private_data;
0584     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0585     struct ath11k *ar = arsta->arvif->ar;
0586     u32 tid, buf_size;
0587     int ret;
0588     char buf[64] = {0};
0589 
0590     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0591                      user_buf, count);
0592     if (ret <= 0)
0593         return ret;
0594 
0595     ret = sscanf(buf, "%u %u", &tid, &buf_size);
0596     if (ret != 2)
0597         return -EINVAL;
0598 
0599     /* Valid TID values are 0 through 15 */
0600     if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
0601         return -EINVAL;
0602 
0603     mutex_lock(&ar->conf_mutex);
0604     if (ar->state != ATH11K_STATE_ON ||
0605         arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
0606         ret = count;
0607         goto out;
0608     }
0609 
0610     ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
0611                     tid, buf_size);
0612     if (ret) {
0613         ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
0614                 arsta->arvif->vdev_id, sta->addr, tid, buf_size);
0615     }
0616 
0617     ret = count;
0618 out:
0619     mutex_unlock(&ar->conf_mutex);
0620     return ret;
0621 }
0622 
0623 static const struct file_operations fops_addba = {
0624     .write = ath11k_dbg_sta_write_addba,
0625     .open = simple_open,
0626     .owner = THIS_MODULE,
0627     .llseek = default_llseek,
0628 };
0629 
0630 static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
0631                          char __user *user_buf,
0632                          size_t count, loff_t *ppos)
0633 {
0634     struct ieee80211_sta *sta = file->private_data;
0635     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0636     struct ath11k *ar = arsta->arvif->ar;
0637     char buf[64];
0638     int len = 0;
0639 
0640     mutex_lock(&ar->conf_mutex);
0641     len = scnprintf(buf, sizeof(buf) - len,
0642             "aggregation mode: %s\n\n%s\n%s\n",
0643             (arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
0644             "auto" : "manual", "auto = 0", "manual = 1");
0645     mutex_unlock(&ar->conf_mutex);
0646 
0647     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0648 }
0649 
0650 static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
0651                           const char __user *user_buf,
0652                           size_t count, loff_t *ppos)
0653 {
0654     struct ieee80211_sta *sta = file->private_data;
0655     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0656     struct ath11k *ar = arsta->arvif->ar;
0657     u32 aggr_mode;
0658     int ret;
0659 
0660     if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
0661         return -EINVAL;
0662 
0663     if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
0664         return -EINVAL;
0665 
0666     mutex_lock(&ar->conf_mutex);
0667     if (ar->state != ATH11K_STATE_ON ||
0668         aggr_mode == arsta->aggr_mode) {
0669         ret = count;
0670         goto out;
0671     }
0672 
0673     ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
0674     if (ret) {
0675         ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
0676                 ret);
0677         goto out;
0678     }
0679 
0680     arsta->aggr_mode = aggr_mode;
0681 out:
0682     mutex_unlock(&ar->conf_mutex);
0683     return ret;
0684 }
0685 
0686 static const struct file_operations fops_aggr_mode = {
0687     .read = ath11k_dbg_sta_read_aggr_mode,
0688     .write = ath11k_dbg_sta_write_aggr_mode,
0689     .open = simple_open,
0690     .owner = THIS_MODULE,
0691     .llseek = default_llseek,
0692 };
0693 
0694 static ssize_t
0695 ath11k_write_htt_peer_stats_reset(struct file *file,
0696                   const char __user *user_buf,
0697                   size_t count, loff_t *ppos)
0698 {
0699     struct ieee80211_sta *sta = file->private_data;
0700     struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
0701     struct ath11k *ar = arsta->arvif->ar;
0702     struct htt_ext_stats_cfg_params cfg_params = { 0 };
0703     int ret;
0704     u8 type;
0705 
0706     ret = kstrtou8_from_user(user_buf, count, 0, &type);
0707     if (ret)
0708         return ret;
0709 
0710     if (!type)
0711         return ret;
0712 
0713     mutex_lock(&ar->conf_mutex);
0714     cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
0715     cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
0716                 HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
0717 
0718     cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
0719 
0720     cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
0721     cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
0722     cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
0723     cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
0724 
0725     cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
0726     cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
0727 
0728     cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
0729 
0730     ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
0731                          ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
0732                          &cfg_params,
0733                          0ULL);
0734     if (ret) {
0735         ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
0736         mutex_unlock(&ar->conf_mutex);
0737         return ret;
0738     }
0739 
0740     mutex_unlock(&ar->conf_mutex);
0741 
0742     ret = count;
0743 
0744     return ret;
0745 }
0746 
0747 static const struct file_operations fops_htt_peer_stats_reset = {
0748     .write = ath11k_write_htt_peer_stats_reset,
0749     .open = simple_open,
0750     .owner = THIS_MODULE,
0751     .llseek = default_llseek,
0752 };
0753 
0754 void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0755                    struct ieee80211_sta *sta, struct dentry *dir)
0756 {
0757     struct ath11k *ar = hw->priv;
0758 
0759     if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
0760         debugfs_create_file("tx_stats", 0400, dir, sta,
0761                     &fops_tx_stats);
0762     if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
0763         debugfs_create_file("rx_stats", 0400, dir, sta,
0764                     &fops_rx_stats);
0765 
0766     debugfs_create_file("htt_peer_stats", 0400, dir, sta,
0767                 &fops_htt_peer_stats);
0768 
0769     debugfs_create_file("peer_pktlog", 0644, dir, sta,
0770                 &fops_peer_pktlog);
0771 
0772     debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
0773     debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
0774     debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
0775     debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
0776 
0777     if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
0778              ar->ab->wmi_ab.svc_map))
0779         debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
0780                     &fops_htt_peer_stats_reset);
0781 }