Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
0004  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
0005  */
0006 
0007 #include "core.h"
0008 #include "wmi-ops.h"
0009 #include "txrx.h"
0010 #include "debug.h"
0011 
0012 static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
0013                         struct ath10k_sta_tid_stats *stats,
0014                         u32 msdu_count)
0015 {
0016     if (msdu_count == 1)
0017         stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
0018     else if (msdu_count == 2)
0019         stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
0020     else if (msdu_count == 3)
0021         stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
0022     else if (msdu_count == 4)
0023         stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
0024     else if (msdu_count > 4)
0025         stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
0026 }
0027 
0028 static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
0029                         struct ath10k_sta_tid_stats *stats,
0030                         u32 mpdu_count)
0031 {
0032     if (mpdu_count <= 10)
0033         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
0034     else if (mpdu_count <= 20)
0035         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
0036     else if (mpdu_count <= 30)
0037         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
0038     else if (mpdu_count <= 40)
0039         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
0040     else if (mpdu_count <= 50)
0041         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
0042     else if (mpdu_count <= 60)
0043         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
0044     else if (mpdu_count > 60)
0045         stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
0046 }
0047 
0048 void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
0049                       struct htt_rx_indication_mpdu_range *ranges,
0050                       int num_ranges)
0051 {
0052     struct ath10k_sta *arsta;
0053     struct ath10k_peer *peer;
0054     int i;
0055 
0056     if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
0057         return;
0058 
0059     rcu_read_lock();
0060     spin_lock_bh(&ar->data_lock);
0061 
0062     peer = ath10k_peer_find_by_id(ar, peer_id);
0063     if (!peer || !peer->sta)
0064         goto out;
0065 
0066     arsta = (struct ath10k_sta *)peer->sta->drv_priv;
0067 
0068     for (i = 0; i < num_ranges; i++)
0069         ath10k_rx_stats_update_ampdu_subfrm(ar,
0070                             &arsta->tid_stats[tid],
0071                             ranges[i].mpdu_count);
0072 
0073 out:
0074     spin_unlock_bh(&ar->data_lock);
0075     rcu_read_unlock();
0076 }
0077 
0078 void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
0079                     unsigned long num_msdus,
0080                     enum ath10k_pkt_rx_err err,
0081                     unsigned long unchain_cnt,
0082                     unsigned long drop_cnt,
0083                     unsigned long drop_cnt_filter,
0084                     unsigned long queued_msdus)
0085 {
0086     struct ieee80211_sta *sta;
0087     struct ath10k_sta *arsta;
0088     struct ieee80211_hdr *hdr;
0089     struct ath10k_sta_tid_stats *stats;
0090     u8 tid = IEEE80211_NUM_TIDS;
0091     bool non_data_frm = false;
0092 
0093     hdr = (struct ieee80211_hdr *)first_hdr;
0094     if (!ieee80211_is_data(hdr->frame_control))
0095         non_data_frm = true;
0096 
0097     if (ieee80211_is_data_qos(hdr->frame_control))
0098         tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
0099 
0100     if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
0101         return;
0102 
0103     rcu_read_lock();
0104 
0105     sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
0106     if (!sta)
0107         goto exit;
0108 
0109     arsta = (struct ath10k_sta *)sta->drv_priv;
0110 
0111     spin_lock_bh(&ar->data_lock);
0112     stats = &arsta->tid_stats[tid];
0113     stats->rx_pkt_from_fw += num_msdus;
0114     stats->rx_pkt_unchained += unchain_cnt;
0115     stats->rx_pkt_drop_chained += drop_cnt;
0116     stats->rx_pkt_drop_filter += drop_cnt_filter;
0117     if (err != ATH10K_PKT_RX_ERR_MAX)
0118         stats->rx_pkt_err[err] += queued_msdus;
0119     stats->rx_pkt_queued_for_mac += queued_msdus;
0120     ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
0121                         num_msdus);
0122     spin_unlock_bh(&ar->data_lock);
0123 
0124 exit:
0125     rcu_read_unlock();
0126 }
0127 
0128 static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
0129                              struct ath10k_fw_stats *stats)
0130 {
0131     struct ath10k_fw_extd_stats_peer *peer;
0132     struct ieee80211_sta *sta;
0133     struct ath10k_sta *arsta;
0134 
0135     rcu_read_lock();
0136     list_for_each_entry(peer, &stats->peers_extd, list) {
0137         sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
0138                            NULL);
0139         if (!sta)
0140             continue;
0141         arsta = (struct ath10k_sta *)sta->drv_priv;
0142         arsta->rx_duration += (u64)peer->rx_duration;
0143     }
0144     rcu_read_unlock();
0145 }
0146 
0147 static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
0148                         struct ath10k_fw_stats *stats)
0149 {
0150     struct ath10k_fw_stats_peer *peer;
0151     struct ieee80211_sta *sta;
0152     struct ath10k_sta *arsta;
0153 
0154     rcu_read_lock();
0155     list_for_each_entry(peer, &stats->peers, list) {
0156         sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
0157                            NULL);
0158         if (!sta)
0159             continue;
0160         arsta = (struct ath10k_sta *)sta->drv_priv;
0161         arsta->rx_duration += (u64)peer->rx_duration;
0162     }
0163     rcu_read_unlock();
0164 }
0165 
0166 void ath10k_sta_update_rx_duration(struct ath10k *ar,
0167                    struct ath10k_fw_stats *stats)
0168 {
0169     if (stats->extended)
0170         ath10k_sta_update_extd_stats_rx_duration(ar, stats);
0171     else
0172         ath10k_sta_update_stats_rx_duration(ar, stats);
0173 }
0174 
0175 static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
0176                          char __user *user_buf,
0177                          size_t count, loff_t *ppos)
0178 {
0179     struct ieee80211_sta *sta = file->private_data;
0180     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0181     struct ath10k *ar = arsta->arvif->ar;
0182     char buf[32];
0183     int len = 0;
0184 
0185     mutex_lock(&ar->conf_mutex);
0186     len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
0187             (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
0188             "auto" : "manual");
0189     mutex_unlock(&ar->conf_mutex);
0190 
0191     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0192 }
0193 
0194 static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
0195                           const char __user *user_buf,
0196                           size_t count, loff_t *ppos)
0197 {
0198     struct ieee80211_sta *sta = file->private_data;
0199     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0200     struct ath10k *ar = arsta->arvif->ar;
0201     u32 aggr_mode;
0202     int ret;
0203 
0204     if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
0205         return -EINVAL;
0206 
0207     if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
0208         return -EINVAL;
0209 
0210     mutex_lock(&ar->conf_mutex);
0211     if ((ar->state != ATH10K_STATE_ON) ||
0212         (aggr_mode == arsta->aggr_mode)) {
0213         ret = count;
0214         goto out;
0215     }
0216 
0217     ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
0218     if (ret) {
0219         ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
0220         goto out;
0221     }
0222 
0223     arsta->aggr_mode = aggr_mode;
0224 out:
0225     mutex_unlock(&ar->conf_mutex);
0226     return ret;
0227 }
0228 
0229 static const struct file_operations fops_aggr_mode = {
0230     .read = ath10k_dbg_sta_read_aggr_mode,
0231     .write = ath10k_dbg_sta_write_aggr_mode,
0232     .open = simple_open,
0233     .owner = THIS_MODULE,
0234     .llseek = default_llseek,
0235 };
0236 
0237 static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
0238                       const char __user *user_buf,
0239                       size_t count, loff_t *ppos)
0240 {
0241     struct ieee80211_sta *sta = file->private_data;
0242     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0243     struct ath10k *ar = arsta->arvif->ar;
0244     u32 tid, buf_size;
0245     int ret;
0246     char buf[64] = {0};
0247 
0248     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0249                      user_buf, count);
0250     if (ret <= 0)
0251         return ret;
0252 
0253     ret = sscanf(buf, "%u %u", &tid, &buf_size);
0254     if (ret != 2)
0255         return -EINVAL;
0256 
0257     /* Valid TID values are 0 through 15 */
0258     if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
0259         return -EINVAL;
0260 
0261     mutex_lock(&ar->conf_mutex);
0262     if ((ar->state != ATH10K_STATE_ON) ||
0263         (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
0264         ret = count;
0265         goto out;
0266     }
0267 
0268     ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
0269                     tid, buf_size);
0270     if (ret) {
0271         ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
0272                 arsta->arvif->vdev_id, sta->addr, tid, buf_size);
0273     }
0274 
0275     ret = count;
0276 out:
0277     mutex_unlock(&ar->conf_mutex);
0278     return ret;
0279 }
0280 
0281 static const struct file_operations fops_addba = {
0282     .write = ath10k_dbg_sta_write_addba,
0283     .open = simple_open,
0284     .owner = THIS_MODULE,
0285     .llseek = default_llseek,
0286 };
0287 
0288 static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
0289                            const char __user *user_buf,
0290                            size_t count, loff_t *ppos)
0291 {
0292     struct ieee80211_sta *sta = file->private_data;
0293     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0294     struct ath10k *ar = arsta->arvif->ar;
0295     u32 tid, status;
0296     int ret;
0297     char buf[64] = {0};
0298 
0299     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0300                      user_buf, count);
0301     if (ret <= 0)
0302         return ret;
0303 
0304     ret = sscanf(buf, "%u %u", &tid, &status);
0305     if (ret != 2)
0306         return -EINVAL;
0307 
0308     /* Valid TID values are 0 through 15 */
0309     if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
0310         return -EINVAL;
0311 
0312     mutex_lock(&ar->conf_mutex);
0313     if ((ar->state != ATH10K_STATE_ON) ||
0314         (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
0315         ret = count;
0316         goto out;
0317     }
0318 
0319     ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
0320                     tid, status);
0321     if (ret) {
0322         ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
0323                 arsta->arvif->vdev_id, sta->addr, tid, status);
0324     }
0325     ret = count;
0326 out:
0327     mutex_unlock(&ar->conf_mutex);
0328     return ret;
0329 }
0330 
0331 static const struct file_operations fops_addba_resp = {
0332     .write = ath10k_dbg_sta_write_addba_resp,
0333     .open = simple_open,
0334     .owner = THIS_MODULE,
0335     .llseek = default_llseek,
0336 };
0337 
0338 static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
0339                       const char __user *user_buf,
0340                       size_t count, loff_t *ppos)
0341 {
0342     struct ieee80211_sta *sta = file->private_data;
0343     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0344     struct ath10k *ar = arsta->arvif->ar;
0345     u32 tid, initiator, reason;
0346     int ret;
0347     char buf[64] = {0};
0348 
0349     ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
0350                      user_buf, count);
0351     if (ret <= 0)
0352         return ret;
0353 
0354     ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
0355     if (ret != 3)
0356         return -EINVAL;
0357 
0358     /* Valid TID values are 0 through 15 */
0359     if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
0360         return -EINVAL;
0361 
0362     mutex_lock(&ar->conf_mutex);
0363     if ((ar->state != ATH10K_STATE_ON) ||
0364         (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
0365         ret = count;
0366         goto out;
0367     }
0368 
0369     ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
0370                     tid, initiator, reason);
0371     if (ret) {
0372         ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
0373                 arsta->arvif->vdev_id, sta->addr, tid, initiator,
0374                 reason);
0375     }
0376     ret = count;
0377 out:
0378     mutex_unlock(&ar->conf_mutex);
0379     return ret;
0380 }
0381 
0382 static const struct file_operations fops_delba = {
0383     .write = ath10k_dbg_sta_write_delba,
0384     .open = simple_open,
0385     .owner = THIS_MODULE,
0386     .llseek = default_llseek,
0387 };
0388 
0389 static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
0390                               char __user *user_buf,
0391                               size_t count,
0392                               loff_t *ppos)
0393 {
0394     struct ieee80211_sta *sta = file->private_data;
0395     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0396     struct ath10k *ar = arsta->arvif->ar;
0397     char buf[8];
0398     int len = 0;
0399 
0400     mutex_lock(&ar->conf_mutex);
0401     len = scnprintf(buf, sizeof(buf) - len,
0402             "Write 1 to once trigger the debug logs\n");
0403     mutex_unlock(&ar->conf_mutex);
0404 
0405     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0406 }
0407 
0408 static ssize_t
0409 ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
0410                     const char __user *user_buf,
0411                     size_t count, loff_t *ppos)
0412 {
0413     struct ieee80211_sta *sta = file->private_data;
0414     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0415     struct ath10k *ar = arsta->arvif->ar;
0416     u8 peer_debug_trigger;
0417     int ret;
0418 
0419     if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
0420         return -EINVAL;
0421 
0422     if (peer_debug_trigger != 1)
0423         return -EINVAL;
0424 
0425     mutex_lock(&ar->conf_mutex);
0426 
0427     if (ar->state != ATH10K_STATE_ON) {
0428         ret = -ENETDOWN;
0429         goto out;
0430     }
0431 
0432     ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
0433                     ar->wmi.peer_param->debug, peer_debug_trigger);
0434     if (ret) {
0435         ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
0436                 ret);
0437         goto out;
0438     }
0439 out:
0440     mutex_unlock(&ar->conf_mutex);
0441     return count;
0442 }
0443 
0444 static const struct file_operations fops_peer_debug_trigger = {
0445     .open = simple_open,
0446     .read = ath10k_dbg_sta_read_peer_debug_trigger,
0447     .write = ath10k_dbg_sta_write_peer_debug_trigger,
0448     .owner = THIS_MODULE,
0449     .llseek = default_llseek,
0450 };
0451 
0452 static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
0453                          char __user *user_buf,
0454                          size_t count, loff_t *ppos)
0455 {
0456     struct ieee80211_sta *sta = file->private_data;
0457     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0458     struct ath10k *ar = arsta->arvif->ar;
0459     char buf[20];
0460     int len = 0;
0461 
0462     spin_lock_bh(&ar->data_lock);
0463 
0464     len = scnprintf(buf, sizeof(buf) - len, "%d\n",
0465             arsta->peer_ps_state);
0466 
0467     spin_unlock_bh(&ar->data_lock);
0468 
0469     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0470 }
0471 
0472 static const struct file_operations fops_peer_ps_state = {
0473     .open = simple_open,
0474     .read = ath10k_dbg_sta_read_peer_ps_state,
0475     .owner = THIS_MODULE,
0476     .llseek = default_llseek,
0477 };
0478 
0479 static char *get_err_str(enum ath10k_pkt_rx_err i)
0480 {
0481     switch (i) {
0482     case ATH10K_PKT_RX_ERR_FCS:
0483         return "fcs_err";
0484     case ATH10K_PKT_RX_ERR_TKIP:
0485         return "tkip_err";
0486     case ATH10K_PKT_RX_ERR_CRYPT:
0487         return "crypt_err";
0488     case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
0489         return "peer_idx_inval";
0490     case ATH10K_PKT_RX_ERR_MAX:
0491         return "unknown";
0492     }
0493 
0494     return "unknown";
0495 }
0496 
0497 static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
0498 {
0499     switch (i) {
0500     case ATH10K_AMPDU_SUBFRM_NUM_10:
0501         return "upto 10";
0502     case ATH10K_AMPDU_SUBFRM_NUM_20:
0503         return "11-20";
0504     case ATH10K_AMPDU_SUBFRM_NUM_30:
0505         return "21-30";
0506     case ATH10K_AMPDU_SUBFRM_NUM_40:
0507         return "31-40";
0508     case ATH10K_AMPDU_SUBFRM_NUM_50:
0509         return "41-50";
0510     case ATH10K_AMPDU_SUBFRM_NUM_60:
0511         return "51-60";
0512     case ATH10K_AMPDU_SUBFRM_NUM_MORE:
0513         return ">60";
0514     case ATH10K_AMPDU_SUBFRM_NUM_MAX:
0515         return "0";
0516     }
0517 
0518     return "0";
0519 }
0520 
0521 static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
0522 {
0523     switch (i) {
0524     case ATH10K_AMSDU_SUBFRM_NUM_1:
0525         return "1";
0526     case ATH10K_AMSDU_SUBFRM_NUM_2:
0527         return "2";
0528     case ATH10K_AMSDU_SUBFRM_NUM_3:
0529         return "3";
0530     case ATH10K_AMSDU_SUBFRM_NUM_4:
0531         return "4";
0532     case ATH10K_AMSDU_SUBFRM_NUM_MORE:
0533         return ">4";
0534     case ATH10K_AMSDU_SUBFRM_NUM_MAX:
0535         return "0";
0536     }
0537 
0538     return "0";
0539 }
0540 
0541 #define PRINT_TID_STATS(_field, _tabs) \
0542     do { \
0543         int k = 0; \
0544         for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
0545             if (ar->sta_tid_stats_mask & BIT(j))  { \
0546                 len += scnprintf(buf + len, buf_len - len, \
0547                          "[%02d] %-10lu  ", \
0548                          j, stats[j]._field); \
0549                 k++; \
0550                 if (k % 8 == 0)  { \
0551                     len += scnprintf(buf + len, \
0552                              buf_len - len, "\n"); \
0553                     len += scnprintf(buf + len, \
0554                              buf_len - len, \
0555                              _tabs); \
0556                 } \
0557             } \
0558         } \
0559         len += scnprintf(buf + len, buf_len - len, "\n"); \
0560     } while (0)
0561 
0562 static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
0563                          char __user *user_buf,
0564                          size_t count, loff_t *ppos)
0565 {
0566     struct ieee80211_sta *sta = file->private_data;
0567     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0568     struct ath10k *ar = arsta->arvif->ar;
0569     struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
0570     size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
0571     char *buf;
0572     int i, j;
0573     ssize_t ret;
0574 
0575     buf = kzalloc(buf_len, GFP_KERNEL);
0576     if (!buf)
0577         return -ENOMEM;
0578 
0579     mutex_lock(&ar->conf_mutex);
0580 
0581     spin_lock_bh(&ar->data_lock);
0582 
0583     len += scnprintf(buf + len, buf_len - len,
0584              "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
0585     len += scnprintf(buf + len, buf_len - len,
0586              "\t\t------------------------------------------\n");
0587     len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
0588     PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
0589 
0590     len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
0591     PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
0592 
0593     len += scnprintf(buf + len, buf_len - len,
0594              "MSDUs locally dropped:chained\t");
0595     PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
0596 
0597     len += scnprintf(buf + len, buf_len - len,
0598              "MSDUs locally dropped:filtered\t");
0599     PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
0600 
0601     len += scnprintf(buf + len, buf_len - len,
0602              "MSDUs queued for mac80211\t");
0603     PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
0604 
0605     for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
0606         len += scnprintf(buf + len, buf_len - len,
0607                  "MSDUs with error:%s\t", get_err_str(i));
0608         PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
0609     }
0610 
0611     len += scnprintf(buf + len, buf_len - len, "\n");
0612     for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
0613         len += scnprintf(buf + len, buf_len - len,
0614                  "A-MPDU num subframes %s\t",
0615                  get_num_ampdu_subfrm_str(i));
0616         PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
0617     }
0618 
0619     len += scnprintf(buf + len, buf_len - len, "\n");
0620     for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
0621         len += scnprintf(buf + len, buf_len - len,
0622                  "A-MSDU num subframes %s\t\t",
0623                  get_num_amsdu_subfrm_str(i));
0624         PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
0625     }
0626 
0627     spin_unlock_bh(&ar->data_lock);
0628 
0629     ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0630 
0631     kfree(buf);
0632 
0633     mutex_unlock(&ar->conf_mutex);
0634 
0635     return ret;
0636 }
0637 
0638 static const struct file_operations fops_tid_stats_dump = {
0639     .open = simple_open,
0640     .read = ath10k_dbg_sta_read_tid_stats,
0641     .owner = THIS_MODULE,
0642     .llseek = default_llseek,
0643 };
0644 
0645 static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
0646                         char __user *user_buf,
0647                         size_t count, loff_t *ppos)
0648 {
0649     struct ieee80211_sta *sta = file->private_data;
0650     struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
0651     struct ath10k *ar = arsta->arvif->ar;
0652     struct ath10k_htt_data_stats *stats;
0653     const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
0654                                "retry", "ampdu"};
0655     const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
0656     int len = 0, i, j, k, retval = 0;
0657     const int size = 16 * 4096;
0658     char *buf;
0659 
0660     buf = kzalloc(size, GFP_KERNEL);
0661     if (!buf)
0662         return -ENOMEM;
0663 
0664     mutex_lock(&ar->conf_mutex);
0665 
0666     if (!arsta->tx_stats) {
0667         ath10k_warn(ar, "failed to get tx stats");
0668         mutex_unlock(&ar->conf_mutex);
0669         kfree(buf);
0670         return 0;
0671     }
0672 
0673     spin_lock_bh(&ar->data_lock);
0674     for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
0675         for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
0676             stats = &arsta->tx_stats->stats[k];
0677             len += scnprintf(buf + len, size - len, "%s_%s\n",
0678                      str_name[k],
0679                      str[j]);
0680             len += scnprintf(buf + len, size - len,
0681                      " VHT MCS %s\n",
0682                      str[j]);
0683             for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
0684                 len += scnprintf(buf + len, size - len,
0685                          "  %llu ",
0686                          stats->vht[j][i]);
0687             len += scnprintf(buf + len, size - len, "\n");
0688             len += scnprintf(buf + len, size - len, " HT MCS %s\n",
0689                      str[j]);
0690             for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
0691                 len += scnprintf(buf + len, size - len,
0692                          "  %llu ", stats->ht[j][i]);
0693             len += scnprintf(buf + len, size - len, "\n");
0694             len += scnprintf(buf + len, size - len,
0695                     " BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
0696             len += scnprintf(buf + len, size - len,
0697                      "  %llu %llu %llu %llu %llu %llu\n",
0698                      stats->bw[j][0], stats->bw[j][1],
0699                      stats->bw[j][2], stats->bw[j][3],
0700                      stats->bw[j][4], stats->bw[j][5]);
0701             len += scnprintf(buf + len, size - len,
0702                      " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
0703             len += scnprintf(buf + len, size - len,
0704                      "  %llu %llu %llu %llu\n",
0705                      stats->nss[j][0], stats->nss[j][1],
0706                      stats->nss[j][2], stats->nss[j][3]);
0707             len += scnprintf(buf + len, size - len,
0708                      " GI %s (LGI,SGI)\n",
0709                      str[j]);
0710             len += scnprintf(buf + len, size - len, "  %llu %llu\n",
0711                      stats->gi[j][0], stats->gi[j][1]);
0712             len += scnprintf(buf + len, size - len,
0713                      " legacy rate %s (1,2 ... Mbps)\n  ",
0714                      str[j]);
0715             for (i = 0; i < ATH10K_LEGACY_NUM; i++)
0716                 len += scnprintf(buf + len, size - len, "%llu ",
0717                          stats->legacy[j][i]);
0718             len += scnprintf(buf + len, size - len, "\n");
0719             len += scnprintf(buf + len, size - len,
0720                      " Rate table %s (1,2 ... Mbps)\n  ",
0721                      str[j]);
0722             for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) {
0723                 len += scnprintf(buf + len, size - len, "%llu ",
0724                          stats->rate_table[j][i]);
0725                 if (!((i + 1) % 8))
0726                     len +=
0727                     scnprintf(buf + len, size - len, "\n  ");
0728             }
0729         }
0730     }
0731 
0732     len += scnprintf(buf + len, size - len,
0733              "\nTX duration\n %llu usecs\n",
0734              arsta->tx_stats->tx_duration);
0735     len += scnprintf(buf + len, size - len,
0736             "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
0737     len += scnprintf(buf + len, size - len,
0738             "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
0739     spin_unlock_bh(&ar->data_lock);
0740 
0741     if (len > size)
0742         len = size;
0743     retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0744     kfree(buf);
0745 
0746     mutex_unlock(&ar->conf_mutex);
0747     return retval;
0748 }
0749 
0750 static const struct file_operations fops_tx_stats = {
0751     .read = ath10k_dbg_sta_dump_tx_stats,
0752     .open = simple_open,
0753     .owner = THIS_MODULE,
0754     .llseek = default_llseek,
0755 };
0756 
0757 void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0758                 struct ieee80211_sta *sta, struct dentry *dir)
0759 {
0760     struct ath10k *ar = hw->priv;
0761 
0762     debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
0763     debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
0764     debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
0765     debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
0766     debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
0767                 &fops_peer_debug_trigger);
0768     debugfs_create_file("dump_tid_stats", 0400, dir, sta,
0769                 &fops_tid_stats_dump);
0770 
0771     if (ath10k_peer_stats_enabled(ar) &&
0772         ath10k_debug_is_extd_tx_stats_enabled(ar))
0773         debugfs_create_file("tx_stats", 0400, dir, sta,
0774                     &fops_tx_stats);
0775     debugfs_create_file("peer_ps_state", 0400, dir, sta,
0776                 &fops_peer_ps_state);
0777 }