Subject: [PATCH] ath10k: Add sta rx packet stats per tid

Added per tid sta counters for the following

- Total number MSDUs received from firmware
- Number of MSDUs received with errors like decryption, crc, mic ,etc.
- Number of MSDUs dropped in the driver
- A-MPDU/A-MSDU subframe stats
- Number of MSDUS passed to mac80211

All stats other than A-MPDU stats are only for received data frames.
A-MPDU stats might have stats for management frames when monitor
interface is active where management frames are notified both in wmi
and HTT interfaces.

These per tid stats can be enabled with tid bitmask through a debugfs
like below

echo <tid_bitmask> > /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask

tid 16 (tid_bitmask 0x10000) is used for non-qos data/management frames

The stats are read from
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/<sta_mac>/dump_tid_stats

Sample output:

To enable rx stats for tid 0, 5 and 6,

echo 0x00000061 > /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask

cat /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats

Driver Rx pkt stats per tid, ([tid] count)
------------------------------------------
MSDUs from FW [00] 2567 [05] 3178 [06] 1089
MSDUs unchained [00] 0 [05] 0 [06] 0
MSDUs locally dropped:chained [00] 0 [05] 0 [06] 0
MSDUs locally dropped:filtered [00] 0 [05] 0 [06] 0
MSDUs queued for mac80211 [00] 2567 [05] 3178 [06] 1089
MSDUs with error:fcs_err [00] 0 [05] 0 [06] 2
MSDUs with error:tkip_err [00] 0 [05] 0 [06] 0
MSDUs with error:crypt_err [00] 0 [05] 0 [06] 0
MSDUs with error:peer_idx_inval [00] 0 [05] 0 [06] 0

A-MPDU num subframes upto 10 [00] 2567 [05] 3178 [06] 1087
A-MPDU num subframes 11-20 [00] 0 [05] 0 [06] 0
A-MPDU num subframes 21-30 [00] 0 [05] 0 [06] 0
A-MPDU num subframes 31-40 [00] 0 [05] 0 [06] 0
A-MPDU num subframes 41-50 [00] 0 [05] 0 [06] 0
A-MPDU num subframes 51-60 [00] 0 [05] 0 [06] 0
A-MPDU num subframes >60 [00] 0 [05] 0 [06] 0

A-MSDU num subframes 1 [00] 2567 [05] 3178 [06] 1089
A-MSDU num subframes 2 [00] 0 [05] 0 [06] 0
A-MSDU num subframes 3 [00] 0 [05] 0 [06] 0
A-MSDU num subframes 4 [00] 0 [05] 0 [06] 0
A-MSDU num subframes >4 [00] 0 [05] 0 [06] 0

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath10k/core.h | 45 ++++
drivers/net/wireless/ath/ath10k/debug.c | 48 +++++
drivers/net/wireless/ath/ath10k/debug.h | 31 +++
drivers/net/wireless/ath/ath10k/debugfs_sta.c | 286 ++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/htt_rx.c | 71 ++++++-
5 files changed, 471 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fe6b30356d3b..c624b96f8b84 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -354,6 +355,45 @@ struct ath10k_txq {
unsigned long num_push_allowed;
};

+enum ath10k_pkt_rx_err {
+ ATH10K_PKT_RX_ERR_FCS,
+ ATH10K_PKT_RX_ERR_TKIP,
+ ATH10K_PKT_RX_ERR_CRYPT,
+ ATH10K_PKT_RX_ERR_PEER_IDX_INVAL,
+ ATH10K_PKT_RX_ERR_MAX,
+};
+
+enum ath10k_ampdu_subfrm_num {
+ ATH10K_AMPDU_SUBFRM_NUM_10,
+ ATH10K_AMPDU_SUBFRM_NUM_20,
+ ATH10K_AMPDU_SUBFRM_NUM_30,
+ ATH10K_AMPDU_SUBFRM_NUM_40,
+ ATH10K_AMPDU_SUBFRM_NUM_50,
+ ATH10K_AMPDU_SUBFRM_NUM_60,
+ ATH10K_AMPDU_SUBFRM_NUM_MORE,
+ ATH10K_AMPDU_SUBFRM_NUM_MAX,
+};
+
+enum ath10k_amsdu_subfrm_num {
+ ATH10K_AMSDU_SUBFRM_NUM_1,
+ ATH10K_AMSDU_SUBFRM_NUM_2,
+ ATH10K_AMSDU_SUBFRM_NUM_3,
+ ATH10K_AMSDU_SUBFRM_NUM_4,
+ ATH10K_AMSDU_SUBFRM_NUM_MORE,
+ ATH10K_AMSDU_SUBFRM_NUM_MAX,
+};
+
+struct ath10k_sta_tid_stats {
+ unsigned long int rx_pkt_from_fw;
+ unsigned long int rx_pkt_unchained;
+ unsigned long int rx_pkt_drop_chained;
+ unsigned long int rx_pkt_drop_filter;
+ unsigned long int rx_pkt_err[ATH10K_PKT_RX_ERR_MAX];
+ unsigned long int rx_pkt_queued_for_mac;
+ unsigned long int rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX];
+ unsigned long int rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX];
+};
+
struct ath10k_sta {
struct ath10k_vif *arvif;

@@ -371,6 +411,9 @@ struct ath10k_sta {
#ifdef CONFIG_MAC80211_DEBUGFS
/* protected by conf_mutex */
bool aggr_mode;
+
+ /* Protected with ar->data_lock */
+ struct ath10k_sta_tid_stats tid_stats[IEEE80211_NUM_TIDS + 1];
#endif
};

@@ -1019,6 +1062,8 @@ struct ath10k {

void *ce_priv;

+ u32 sta_tid_stats_mask;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 6d836a26272f..df253f8a7779 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -2135,6 +2136,48 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
.llseek = default_llseek,
};

+static ssize_t ath10k_sta_tid_stats_mask_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ char buf[32];
+ size_t len;
+
+ len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->sta_tid_stats_mask);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ char buf[32];
+ ssize_t len;
+ u32 mask;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (kstrtoint(buf, 0, &mask))
+ return -EINVAL;
+
+ ar->sta_tid_stats_mask = mask;
+
+ return len;
+}
+
+static const struct file_operations fops_sta_tid_stats_mask = {
+ .read = ath10k_sta_tid_stats_mask_read,
+ .write = ath10k_sta_tid_stats_mask_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2250,6 +2293,11 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
&fops_fw_checksums);

+ if (IS_ENABLED(CONFIG_MAC80211_DEBUGFS))
+ debugfs_create_file("sta_tid_stats_mask", 0600,
+ ar->debug.debugfs_phy,
+ ar, &fops_sta_tid_stats_mask);
+
return 0;
}

diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index e54308889e59..306796dcedae 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -191,12 +192,42 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
void ath10k_sta_update_rx_duration(struct ath10k *ar,
struct ath10k_fw_stats *stats);
+void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
+ unsigned long int num_msdus,
+ enum ath10k_pkt_rx_err err,
+ unsigned long int unchain_cnt,
+ unsigned long int drop_cnt,
+ unsigned long int drop_cnt_filter,
+ unsigned long int queued_msdus);
+void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
+ u16 peer_id, u8 tid,
+ struct htt_rx_indication_mpdu_range *mpdu_ranges,
+ int num_mpdu_rages);
#else
static inline
void ath10k_sta_update_rx_duration(struct ath10k *ar,
struct ath10k_fw_stats *stats)
{
}
+
+static inline
+void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
+ unsigned long int num_msdus,
+ enum ath10k_pkt_rx_err err,
+ unsigned long int unchain_cnt,
+ unsigned long int drop_cnt,
+ unsigned long int drop_cnt_filter,
+ unsigned long int queued_msdus)
+{
+}
+
+static inline
+void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
+ u16 peer_id, u8 tid,
+ struct htt_rx_indication_mpdu_range *mpdu_ranges,
+ int num_mpdu_rages)
+{
+}
#endif /* CONFIG_MAC80211_DEBUGFS */

#ifdef CONFIG_ATH10K_DEBUG
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index b260b09dd4d3..c6301324af82 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,8 +17,125 @@

#include "core.h"
#include "wmi-ops.h"
+#include "txrx.h"
#include "debug.h"

+static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
+ struct ath10k_sta_tid_stats *stats,
+ u32 msdu_count)
+{
+ if (msdu_count == 1)
+ stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
+ else if (msdu_count == 2)
+ stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
+ else if (msdu_count == 3)
+ stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
+ else if (msdu_count == 4)
+ stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
+ else if (msdu_count > 4)
+ stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
+}
+
+static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
+ struct ath10k_sta_tid_stats *stats,
+ u32 mpdu_count)
+{
+ if (mpdu_count <= 10)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
+ else if (mpdu_count <= 20)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
+ else if (mpdu_count <= 30)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
+ else if (mpdu_count <= 40)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
+ else if (mpdu_count <= 50)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
+ else if (mpdu_count <= 60)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
+ else if (mpdu_count > 60)
+ stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
+}
+
+void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
+ struct htt_rx_indication_mpdu_range *mpdu_ranges,
+ int num_mpdu_ranges)
+{
+ struct ath10k_sta *arsta;
+ struct ath10k_peer *peer;
+ int i;
+
+ if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
+ return;
+
+ rcu_read_lock();
+ spin_lock_bh(&ar->data_lock);
+
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer)
+ goto out;
+
+ arsta = (struct ath10k_sta *)peer->sta->drv_priv;
+
+ for (i = 0; i < num_mpdu_ranges; i++)
+ ath10k_rx_stats_update_ampdu_subfrm(ar,
+ &arsta->tid_stats[tid],
+ mpdu_ranges[i].mpdu_count);
+
+out:
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+}
+
+void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
+ unsigned long int num_msdus,
+ enum ath10k_pkt_rx_err err,
+ unsigned long int unchain_cnt,
+ unsigned long int drop_cnt,
+ unsigned long int drop_cnt_filter,
+ unsigned long int queued_msdus)
+{
+ struct ieee80211_sta *sta;
+ struct ath10k_sta *arsta;
+ struct ieee80211_hdr *hdr;
+ struct ath10k_sta_tid_stats *stats;
+ u8 tid = IEEE80211_NUM_TIDS;
+ bool non_data_frm = false;
+
+ hdr = (struct ieee80211_hdr *)first_hdr;
+ if (!ieee80211_is_data(hdr->frame_control))
+ non_data_frm = true;
+
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+
+ if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
+ return;
+
+ rcu_read_lock();
+
+ sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
+ if (!sta)
+ goto exit;
+
+ arsta = (struct ath10k_sta *)sta->drv_priv;
+
+ spin_lock_bh(&ar->data_lock);
+ stats = &arsta->tid_stats[tid];
+ stats->rx_pkt_from_fw += num_msdus;
+ stats->rx_pkt_unchained += unchain_cnt;
+ stats->rx_pkt_drop_chained += drop_cnt;
+ stats->rx_pkt_drop_filter += drop_cnt_filter;
+ if (err != ATH10K_PKT_RX_ERR_MAX)
+ stats->rx_pkt_err[err] += queued_msdus;
+ stats->rx_pkt_queued_for_mac += queued_msdus;
+ ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
+ num_msdus);
+ spin_unlock_bh(&ar->data_lock);
+
+exit:
+ rcu_read_unlock();
+}
+
static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
struct ath10k_fw_stats *stats)
{
@@ -342,6 +460,172 @@ static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
.llseek = default_llseek,
};

+static char *get_err_str(enum ath10k_pkt_rx_err i)
+{
+ switch (i) {
+ case ATH10K_PKT_RX_ERR_FCS:
+ return "fcs_err";
+ case ATH10K_PKT_RX_ERR_TKIP:
+ return "tkip_err";
+ case ATH10K_PKT_RX_ERR_CRYPT:
+ return "crypt_err";
+ case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
+ return "peer_idx_inval";
+ case ATH10K_PKT_RX_ERR_MAX:
+ return "unknown";
+ }
+
+ return "unknown";
+}
+
+static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
+{
+ switch (i) {
+ case ATH10K_AMPDU_SUBFRM_NUM_10:
+ return "upto 10";
+ case ATH10K_AMPDU_SUBFRM_NUM_20:
+ return "11-20";
+ case ATH10K_AMPDU_SUBFRM_NUM_30:
+ return "21-30";
+ case ATH10K_AMPDU_SUBFRM_NUM_40:
+ return "31-40";
+ case ATH10K_AMPDU_SUBFRM_NUM_50:
+ return "41-50";
+ case ATH10K_AMPDU_SUBFRM_NUM_60:
+ return "51-60";
+ case ATH10K_AMPDU_SUBFRM_NUM_MORE:
+ return ">60";
+ case ATH10K_AMPDU_SUBFRM_NUM_MAX:
+ return "0";
+ }
+
+ return "0";
+}
+
+static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
+{
+ switch (i) {
+ case ATH10K_AMSDU_SUBFRM_NUM_1:
+ return "1";
+ case ATH10K_AMSDU_SUBFRM_NUM_2:
+ return "2";
+ case ATH10K_AMSDU_SUBFRM_NUM_3:
+ return "3";
+ case ATH10K_AMSDU_SUBFRM_NUM_4:
+ return "4";
+ case ATH10K_AMSDU_SUBFRM_NUM_MORE:
+ return ">4";
+ case ATH10K_AMSDU_SUBFRM_NUM_MAX:
+ return "0";
+ }
+
+ return "0";
+}
+
+#define PRINT_TID_STATS(_field, _tabs) \
+ do { \
+ int k = 0; \
+ for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
+ if (ar->sta_tid_stats_mask & BIT(j)) { \
+ len += scnprintf(buf + len, buf_len - len, \
+ "[%02d] %-10lu ", \
+ j, stats[j]._field); \
+ k++; \
+ if (k % 8 == 0) { \
+ len += scnprintf(buf + len, \
+ buf_len - len, "\n"); \
+ len += scnprintf(buf + len, \
+ buf_len - len, \
+ _tabs); \
+ } \
+ } \
+ } \
+ len += scnprintf(buf + len, buf_len - len, "\n"); \
+ } while (0)
+
+static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ struct ath10k *ar = arsta->arvif->ar;
+ struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
+ size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
+ char *buf;
+ int i, j;
+ ssize_t ret;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&ar->conf_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+
+ len += scnprintf(buf + len, buf_len - len,
+ "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "\t\t------------------------------------------\n");
+ len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
+ PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
+
+ len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
+ PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
+
+ len += scnprintf(buf + len, buf_len - len,
+ "MSDUs locally dropped:chained\t");
+ PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
+
+ len += scnprintf(buf + len, buf_len - len,
+ "MSDUs locally dropped:filtered\t");
+ PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
+
+ len += scnprintf(buf + len, buf_len - len,
+ "MSDUs queued for mac80211\t");
+ PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
+
+ for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "MSDUs with error:%s\t", get_err_str(i));
+ PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "A-MPDU num subframes %s\t",
+ get_num_ampdu_subfrm_str(i));
+ PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "A-MSDU num subframes %s\t\t",
+ get_num_amsdu_subfrm_str(i));
+ PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
+ }
+
+ spin_unlock_bh(&ar->data_lock);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+
+ mutex_unlock(&ar->conf_mutex);
+
+ return ret;
+}
+
+static const struct file_operations fops_tid_stats_dump = {
+ .open = simple_open,
+ .read = ath10k_dbg_sta_read_tid_stats,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir)
{
@@ -351,4 +635,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
&fops_peer_debug_trigger);
+ debugfs_create_file("dump_tid_stats", 0400, dir, sta,
+ &fops_tid_stats_dump);
}
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6d96f9560950..64996aba1485 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -1502,7 +1503,9 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
struct sk_buff_head *amsdu,
struct ieee80211_rx_status *status,
- bool fill_crypt_header)
+ bool fill_crypt_header,
+ u8 *rx_hdr,
+ enum ath10k_pkt_rx_err *err)
{
struct sk_buff *first;
struct sk_buff *last;
@@ -1538,6 +1541,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
hdr = (void *)rxd->rx_hdr_status;
memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN);

+ if (rx_hdr)
+ memcpy(rx_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
+
/* Each A-MSDU subframe will use the original header as the base and be
* reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
*/
@@ -1581,6 +1587,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
if (has_tkip_err)
status->flag |= RX_FLAG_MMIC_ERROR;

+ if (err) {
+ if (has_fcs_err)
+ *err = ATH10K_PKT_RX_ERR_FCS;
+ else if (has_tkip_err)
+ *err = ATH10K_PKT_RX_ERR_TKIP;
+ else if (has_crypto_err)
+ *err = ATH10K_PKT_RX_ERR_CRYPT;
+ else if (has_peer_idx_invalid)
+ *err = ATH10K_PKT_RX_ERR_PEER_IDX_INVAL;
+ }
+
/* Firmware reports all necessary management frames via WMI already.
* They are not reported to monitor interfaces at all so pass the ones
* coming via HTT to monitor interfaces instead. This simplifies
@@ -1651,11 +1668,13 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar,
}
}

-static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
+static int ath10k_unchain_msdu(struct sk_buff_head *amsdu,
+ unsigned long int *unchain_cnt)
{
struct sk_buff *skb, *first;
int space;
int total_len = 0;
+ int amsdu_len = skb_queue_len(amsdu);

/* TODO: Might could optimize this by using
* skb_try_coalesce or similar method to
@@ -1691,11 +1710,16 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
}

__skb_queue_head(amsdu, first);
+
+ *unchain_cnt += amsdu_len - 1;
+
return 0;
}

static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
- struct sk_buff_head *amsdu)
+ struct sk_buff_head *amsdu,
+ unsigned long int *drop_cnt,
+ unsigned long int *unchain_cnt)
{
struct sk_buff *first;
struct htt_rx_desc *rxd;
@@ -1713,11 +1737,12 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
*/
if (decap != RX_MSDU_DECAP_RAW ||
skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
+ *drop_cnt += skb_queue_len(amsdu);
__skb_queue_purge(amsdu);
return;
}

- ath10k_unchain_msdu(amsdu);
+ ath10k_unchain_msdu(amsdu, unchain_cnt);
}

static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
@@ -1743,7 +1768,8 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,

static void ath10k_htt_rx_h_filter(struct ath10k *ar,
struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *rx_status)
+ struct ieee80211_rx_status *rx_status,
+ unsigned long int *drop_cnt)
{
if (skb_queue_empty(amsdu))
return;
@@ -1751,6 +1777,9 @@ static void ath10k_htt_rx_h_filter(struct ath10k *ar,
if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status))
return;

+ if (drop_cnt)
+ *drop_cnt += skb_queue_len(amsdu);
+
__skb_queue_purge(amsdu);
}

@@ -1760,6 +1789,12 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct sk_buff_head amsdu;
int ret;
+ unsigned long int drop_cnt = 0;
+ unsigned long int unchain_cnt = 0;
+ unsigned long int drop_cnt_filter = 0;
+ unsigned long int msdus_to_queue, num_msdus;
+ enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX;
+ u8 first_hdr[RX_HTT_HDR_STATUS_LEN];

__skb_queue_head_init(&amsdu);

@@ -1781,16 +1816,23 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
return ret;
}

+ num_msdus = skb_queue_len(&amsdu);
+
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);

/* only for ret = 1 indicates chained msdus */
if (ret > 0)
- ath10k_htt_rx_h_unchain(ar, &amsdu);
+ ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);

- ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true);
+ ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
+ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
+ msdus_to_queue = skb_queue_len(&amsdu);
ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);

+ ath10k_sta_update_rx_tid_stats(ar, first_hdr, num_msdus, err,
+ unchain_cnt, drop_cnt, drop_cnt_filter,
+ msdus_to_queue);
+
return 0;
}

@@ -1801,9 +1843,14 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
struct htt_rx_indication_mpdu_range *mpdu_ranges;
int num_mpdu_ranges;
int i, mpdu_count = 0;
+ u16 peer_id;
+ u8 tid;

num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
+ peer_id = __le16_to_cpu(rx->hdr.peer_id);
+ tid = MS(rx->hdr.info0, HTT_RX_INDICATION_INFO0_EXT_TID);
+
mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);

ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
@@ -1815,6 +1862,9 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
mpdu_count += mpdu_ranges[i].mpdu_count;

atomic_add(mpdu_count, &htt->num_mpdus_ready);
+
+ ath10k_sta_update_rx_tid_stats_ampdu(ar, peer_id, tid, mpdu_ranges,
+ num_mpdu_ranges);
}

static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
@@ -2124,8 +2174,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
* should still give an idea about rx rate to the user.
*/
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
- ath10k_htt_rx_h_filter(ar, &amsdu, status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false);
+ ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
+ ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
+ NULL);
ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
break;
case -EAGAIN:
--
1.9.1


2018-02-28 13:17:28

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH] ath10k: Add sta rx packet stats per tid

Vasanthakumar Thiagarajan <[email protected]> writes:

> Added per tid sta counters for the following
>
> - Total number MSDUs received from firmware
> - Number of MSDUs received with errors like decryption, crc, mic ,etc.
> - Number of MSDUs dropped in the driver
> - A-MPDU/A-MSDU subframe stats
> - Number of MSDUS passed to mac80211
>
> All stats other than A-MPDU stats are only for received data frames.
> A-MPDU stats might have stats for management frames when monitor
> interface is active where management frames are notified both in wmi
> and HTT interfaces.
>
> These per tid stats can be enabled with tid bitmask through a debugfs
> like below
>
> echo <tid_bitmask> > /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask
>
> tid 16 (tid_bitmask 0x10000) is used for non-qos data/management frames
>
> The stats are read from
> /sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/<sta_mac>/dump_tid_stats
>
> Sample output:
>
> To enable rx stats for tid 0, 5 and 6,
>
> echo 0x00000061 > /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask
>
> cat /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats
>
> Driver Rx pkt stats per tid, ([tid] count)
> ------------------------------------------
> MSDUs from FW [00] 2567 [05] 3178 [06] 1089
> MSDUs unchained [00] 0 [05] 0 [06] 0
> MSDUs locally dropped:chained [00] 0 [05] 0 [06] 0
> MSDUs locally dropped:filtered [00] 0 [05] 0 [06] 0
> MSDUs queued for mac80211 [00] 2567 [05] 3178 [06] 1089
> MSDUs with error:fcs_err [00] 0 [05] 0 [06] 2
> MSDUs with error:tkip_err [00] 0 [05] 0 [06] 0
> MSDUs with error:crypt_err [00] 0 [05] 0 [06] 0
> MSDUs with error:peer_idx_inval [00] 0 [05] 0 [06] 0
>
> A-MPDU num subframes upto 10 [00] 2567 [05] 3178 [06] 1087
> A-MPDU num subframes 11-20 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 21-30 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 31-40 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 41-50 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 51-60 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes >60 [00] 0 [05] 0 [06] 0
>
> A-MSDU num subframes 1 [00] 2567 [05] 3178 [06] 1089
> A-MSDU num subframes 2 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes 3 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes 4 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes >4 [00] 0 [05] 0 [06] 0
>
> Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>

This added new ath10k-check warnings, I fixed those in the pending
branch:

drivers/net/wireless/ath/ath10k/debug.h:203: Alignment should match open parenthesis
drivers/net/wireless/ath/ath10k/debug.h:226: Alignment should match open parenthesis
drivers/net/wireless/ath/ath10k/debugfs_sta.c:24: Alignment should match open parenthesis
drivers/net/wireless/ath/ath10k/debugfs_sta.c:40: Alignment should match open parenthesis
drivers/net/wireless/ath/ath10k/debugfs_sta.c:60: Alignment should match open parenthesis

Also I fixed the typo "rages" in debug.h. My changes:

diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 306796dcedae..7ebb9b1e7e69 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -200,9 +200,9 @@ void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
unsigned long int drop_cnt_filter,
unsigned long int queued_msdus);
void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
- u16 peer_id, u8 tid,
- struct htt_rx_indication_mpdu_range *mpdu_ranges,
- int num_mpdu_rages);
+ u16 peer_id, u8 tid,
+ struct htt_rx_indication_mpdu_range *ranges,
+ int num_ranges);
#else
static inline
void ath10k_sta_update_rx_duration(struct ath10k *ar,
@@ -223,9 +223,9 @@ void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,

static inline
void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar,
- u16 peer_id, u8 tid,
- struct htt_rx_indication_mpdu_range *mpdu_ranges,
- int num_mpdu_rages)
+ u16 peer_id, u8 tid,
+ struct htt_rx_indication_mpdu_range *ranges,
+ int num_ranges)
{
}
#endif /* CONFIG_MAC80211_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index c6301324af82..8f688f136c22 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -21,8 +21,8 @@
#include "debug.h"

static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
- struct ath10k_sta_tid_stats *stats,
- u32 msdu_count)
+ struct ath10k_sta_tid_stats *stats,
+ u32 msdu_count)
{
if (msdu_count == 1)
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
@@ -37,8 +37,8 @@ static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
}

static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
- struct ath10k_sta_tid_stats *stats,
- u32 mpdu_count)
+ struct ath10k_sta_tid_stats *stats,
+ u32 mpdu_count)
{
if (mpdu_count <= 10)
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
@@ -57,8 +57,8 @@ static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
}

void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
- struct htt_rx_indication_mpdu_range *mpdu_ranges,
- int num_mpdu_ranges)
+ struct htt_rx_indication_mpdu_range *ranges,
+ int num_ranges)
{
struct ath10k_sta *arsta;
struct ath10k_peer *peer;
@@ -76,10 +76,10 @@ void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid

arsta = (struct ath10k_sta *)peer->sta->drv_priv;

- for (i = 0; i < num_mpdu_ranges; i++)
+ for (i = 0; i < num_ranges; i++)
ath10k_rx_stats_update_ampdu_subfrm(ar,
&arsta->tid_stats[tid],
- mpdu_ranges[i].mpdu_count);
+ ranges[i].mpdu_count);

out:
spin_unlock_bh(&ar->data_lock);

Subject: Re: [PATCH] ath10k: Add sta rx packet stats per tid

T24gV2VkbmVzZGF5IDI4IEZlYnJ1YXJ5IDIwMTggMDY6NDcgUE0sIEthbGxlIFZhbG8gd3JvdGU6
DQo+IFZhc2FudGhha3VtYXIgVGhpYWdhcmFqYW4gPHZ0aGlhZ2FyQGNvZGVhdXJvcmEub3JnPiB3
cml0ZXM6DQo+IA0KPj4gQWRkZWQgcGVyIHRpZCBzdGEgY291bnRlcnMgZm9yIHRoZSBmb2xsb3dp
bmcNCj4+DQo+PiAtIFRvdGFsIG51bWJlciBNU0RVcyByZWNlaXZlZCBmcm9tIGZpcm13YXJlDQo+
PiAtIE51bWJlciBvZiBNU0RVcyByZWNlaXZlZCB3aXRoIGVycm9ycyBsaWtlIGRlY3J5cHRpb24s
IGNyYywgbWljICxldGMuDQo+PiAtIE51bWJlciBvZiBNU0RVcyBkcm9wcGVkIGluIHRoZSBkcml2
ZXINCj4+IC0gQS1NUERVL0EtTVNEVSBzdWJmcmFtZSBzdGF0cw0KPj4gLSBOdW1iZXIgb2YgTVNE
VVMgcGFzc2VkIHRvIG1hYzgwMjExDQo+Pg0KPj4gQWxsIHN0YXRzIG90aGVyIHRoYW4gQS1NUERV
IHN0YXRzIGFyZSBvbmx5IGZvciByZWNlaXZlZCBkYXRhIGZyYW1lcy4NCj4+IEEtTVBEVSBzdGF0
cyBtaWdodCBoYXZlIHN0YXRzIGZvciBtYW5hZ2VtZW50IGZyYW1lcyB3aGVuIG1vbml0b3INCj4+
IGludGVyZmFjZSBpcyBhY3RpdmUgd2hlcmUgbWFuYWdlbWVudCBmcmFtZXMgYXJlIG5vdGlmaWVk
IGJvdGggaW4gd21pDQo+PiBhbmQgSFRUIGludGVyZmFjZXMuDQo+Pg0KPj4gVGhlc2UgcGVyIHRp
ZCBzdGF0cyBjYW4gYmUgZW5hYmxlZCB3aXRoIHRpZCBiaXRtYXNrIHRocm91Z2ggYSBkZWJ1Z2Zz
DQo+PiBsaWtlIGJlbG93DQo+Pg0KPj4gICBlY2hvIDx0aWRfYml0bWFzaz4gPiAvc3lzL2tlcm5l
bC9kZWJ1Zy9pZWVlODAyMTEvcGh5WC9hdGgxMGsvc3RhX3RpZF9zdGF0c19tYXNrDQo+Pg0KPj4g
ICB0aWQgMTYgKHRpZF9iaXRtYXNrIDB4MTAwMDApIGlzIHVzZWQgZm9yIG5vbi1xb3MgZGF0YS9t
YW5hZ2VtZW50IGZyYW1lcw0KPj4NCj4+IFRoZSBzdGF0cyBhcmUgcmVhZCBmcm9tDQo+PiAvc3lz
L2tlcm5lbC9kZWJ1Zy9pZWVlODAyMTEvcGh5WC9uZXRkZXZcOndsYW5YL3N0YXRpb25zLzxzdGFf
bWFjPi9kdW1wX3RpZF9zdGF0cw0KPj4NCj4+IFNhbXBsZSBvdXRwdXQ6DQo+Pg0KPj4gICBUbyBl
bmFibGUgcnggc3RhdHMgZm9yIHRpZCAwLCA1IGFuZCA2LA0KPj4NCj4+ICAgZWNobyAweDAwMDAw
MDYxID4gL3N5cy9rZXJuZWwvZGVidWcvaWVlZTgwMjExL3BoeTAvYXRoMTBrL3N0YV90aWRfc3Rh
dHNfbWFzaw0KPj4NCj4+IGNhdCAvc3lzL2tlcm5lbC9kZWJ1Zy9pZWVlODAyMTEvcGh5MC9uZXRk
ZXZcOndsYW4xNS9zdGF0aW9ucy84Y1w6ZmRcOmYwXDowYVw6OGVcOmRmL2R1bXBfdGlkX3N0YXRz
DQo+Pg0KPj4gICAgCQlEcml2ZXIgUnggcGt0IHN0YXRzIHBlciB0aWQsIChbdGlkXSBjb3VudCkN
Cj4+ICAgICAgICAgICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tDQo+PiBNU0RVcyBmcm9tIEZXICAgICAgICAgICAgICAgICAgIFswMF0gMjU2NyAgICAg
ICAgWzA1XSAzMTc4ICAgICAgICBbMDZdIDEwODkNCj4+IE1TRFVzIHVuY2hhaW5lZCAgICAgICAg
ICAgICAgICAgWzAwXSAwICAgICAgICAgICBbMDVdIDAgICAgICAgICAgIFswNl0gMA0KPj4gTVNE
VXMgbG9jYWxseSBkcm9wcGVkOmNoYWluZWQgICBbMDBdIDAgICAgICAgICAgIFswNV0gMCAgICAg
ICAgICAgWzA2XSAwDQo+PiBNU0RVcyBsb2NhbGx5IGRyb3BwZWQ6ZmlsdGVyZWQgIFswMF0gMCAg
ICAgICAgICAgWzA1XSAwICAgICAgICAgICBbMDZdIDANCj4+IE1TRFVzIHF1ZXVlZCBmb3IgbWFj
ODAyMTEgICAgICAgWzAwXSAyNTY3ICAgICAgICBbMDVdIDMxNzggICAgICAgIFswNl0gMTA4OQ0K
Pj4gTVNEVXMgd2l0aCBlcnJvcjpmY3NfZXJyICAgICAgICBbMDBdIDAgICAgICAgICAgIFswNV0g
MCAgICAgICAgICAgWzA2XSAyDQo+PiBNU0RVcyB3aXRoIGVycm9yOnRraXBfZXJyICAgICAgIFsw
MF0gMCAgICAgICAgICAgWzA1XSAwICAgICAgICAgICBbMDZdIDANCj4+IE1TRFVzIHdpdGggZXJy
b3I6Y3J5cHRfZXJyICAgICAgWzAwXSAwICAgICAgICAgICBbMDVdIDAgICAgICAgICAgIFswNl0g
MA0KPj4gTVNEVXMgd2l0aCBlcnJvcjpwZWVyX2lkeF9pbnZhbCBbMDBdIDAgICAgICAgICAgIFsw
NV0gMCAgICAgICAgICAgWzA2XSAwDQo+Pg0KPj4gQS1NUERVIG51bSBzdWJmcmFtZXMgdXB0byAx
MCAgICBbMDBdIDI1NjcgICAgICAgIFswNV0gMzE3OCAgICAgICAgWzA2XSAxMDg3DQo+PiBBLU1Q
RFUgbnVtIHN1YmZyYW1lcyAxMS0yMCAgICAgIFswMF0gMCAgICAgICAgICAgWzA1XSAwICAgICAg
ICAgICBbMDZdIDANCj4+IEEtTVBEVSBudW0gc3ViZnJhbWVzIDIxLTMwICAgICAgWzAwXSAwICAg
ICAgICAgICBbMDVdIDAgICAgICAgICAgIFswNl0gMA0KPj4gQS1NUERVIG51bSBzdWJmcmFtZXMg
MzEtNDAgICAgICBbMDBdIDAgICAgICAgICAgIFswNV0gMCAgICAgICAgICAgWzA2XSAwDQo+PiBB
LU1QRFUgbnVtIHN1YmZyYW1lcyA0MS01MCAgICAgIFswMF0gMCAgICAgICAgICAgWzA1XSAwICAg
ICAgICAgICBbMDZdIDANCj4+IEEtTVBEVSBudW0gc3ViZnJhbWVzIDUxLTYwICAgICAgWzAwXSAw
ICAgICAgICAgICBbMDVdIDAgICAgICAgICAgIFswNl0gMA0KPj4gQS1NUERVIG51bSBzdWJmcmFt
ZXMgPjYwICAgICAgICBbMDBdIDAgICAgICAgICAgIFswNV0gMCAgICAgICAgICAgWzA2XSAwDQo+
Pg0KPj4gQS1NU0RVIG51bSBzdWJmcmFtZXMgMSAgICAgICAgICBbMDBdIDI1NjcgICAgICAgIFsw
NV0gMzE3OCAgICAgICAgWzA2XSAxMDg5DQo+PiBBLU1TRFUgbnVtIHN1YmZyYW1lcyAyICAgICAg
ICAgIFswMF0gMCAgICAgICAgICAgWzA1XSAwICAgICAgICAgICBbMDZdIDANCj4+IEEtTVNEVSBu
dW0gc3ViZnJhbWVzIDMgICAgICAgICAgWzAwXSAwICAgICAgICAgICBbMDVdIDAgICAgICAgICAg
IFswNl0gMA0KPj4gQS1NU0RVIG51bSBzdWJmcmFtZXMgNCAgICAgICAgICBbMDBdIDAgICAgICAg
ICAgIFswNV0gMCAgICAgICAgICAgWzA2XSAwDQo+PiBBLU1TRFUgbnVtIHN1YmZyYW1lcyA+NCAg
ICAgICAgIFswMF0gMCAgICAgICAgICAgWzA1XSAwICAgICAgICAgICBbMDZdIDANCj4+DQo+PiBT
aWduZWQtb2ZmLWJ5OiBWYXNhbnRoYWt1bWFyIFRoaWFnYXJhamFuIDx2dGhpYWdhckBjb2RlYXVy
b3JhLm9yZz4NCj4gDQo+IFRoaXMgYWRkZWQgbmV3IGF0aDEway1jaGVjayB3YXJuaW5ncywgSSBm
aXhlZCB0aG9zZSBpbiB0aGUgcGVuZGluZw0KPiBicmFuY2g6DQo+IA0KPiBkcml2ZXJzL25ldC93
aXJlbGVzcy9hdGgvYXRoMTBrL2RlYnVnLmg6MjAzOiBBbGlnbm1lbnQgc2hvdWxkIG1hdGNoIG9w
ZW4gcGFyZW50aGVzaXMNCj4gZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDEway9kZWJ1Zy5o
OjIyNjogQWxpZ25tZW50IHNob3VsZCBtYXRjaCBvcGVuIHBhcmVudGhlc2lzDQo+IGRyaXZlcnMv
bmV0L3dpcmVsZXNzL2F0aC9hdGgxMGsvZGVidWdmc19zdGEuYzoyNDogQWxpZ25tZW50IHNob3Vs
ZCBtYXRjaCBvcGVuIHBhcmVudGhlc2lzDQo+IGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGgx
MGsvZGVidWdmc19zdGEuYzo0MDogQWxpZ25tZW50IHNob3VsZCBtYXRjaCBvcGVuIHBhcmVudGhl
c2lzDQo+IGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGgxMGsvZGVidWdmc19zdGEuYzo2MDog
QWxpZ25tZW50IHNob3VsZCBtYXRjaCBvcGVuIHBhcmVudGhlc2lzDQo+IA0KPiBBbHNvIEkgZml4
ZWQgdGhlIHR5cG8gInJhZ2VzIiBpbiBkZWJ1Zy5oLiBNeSBjaGFuZ2VzOg0KDQpUaGFua3MgZm9y
IGZpeGluZyBpdC4gSW4gbW9zdCBvZiB0aGUgY2FzZXMsIGZpeGluZyBhYm92ZSB3YXJuaW5ncyB3
b3VsZCByZXN1bHQgaW4gbGluZXMgPiA4MCBjaGFycy4NCk1heSBiZSB3ZSBuZWVkIG5vdCBiZSB2
ZXJ5IHN0cmljdCBhYm91dCA+IDgwIGNoYXIgbGltaXQ/DQoNClZhc2FudGg=

2018-03-26 15:08:00

by Kalle Valo

[permalink] [raw]
Subject: Re: ath10k: Add sta rx packet stats per tid

Vasanthakumar Thiagarajan <[email protected]> wrote:

> Added per tid sta counters for the following
>
> - Total number MSDUs received from firmware
> - Number of MSDUs received with errors like decryption, crc, mic ,etc.
> - Number of MSDUs dropped in the driver
> - A-MPDU/A-MSDU subframe stats
> - Number of MSDUS passed to mac80211
>
> All stats other than A-MPDU stats are only for received data frames.
> A-MPDU stats might have stats for management frames when monitor
> interface is active where management frames are notified both in wmi
> and HTT interfaces.
>
> These per tid stats can be enabled with tid bitmask through a debugfs
> like below
>
> echo <tid_bitmask> > /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask
>
> tid 16 (tid_bitmask 0x10000) is used for non-qos data/management frames
>
> The stats are read from
> /sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/<sta_mac>/dump_tid_stats
>
> Sample output:
>
> To enable rx stats for tid 0, 5 and 6,
>
> echo 0x00000061 > /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask
>
> cat /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats
>
> Driver Rx pkt stats per tid, ([tid] count)
> ------------------------------------------
> MSDUs from FW [00] 2567 [05] 3178 [06] 1089
> MSDUs unchained [00] 0 [05] 0 [06] 0
> MSDUs locally dropped:chained [00] 0 [05] 0 [06] 0
> MSDUs locally dropped:filtered [00] 0 [05] 0 [06] 0
> MSDUs queued for mac80211 [00] 2567 [05] 3178 [06] 1089
> MSDUs with error:fcs_err [00] 0 [05] 0 [06] 2
> MSDUs with error:tkip_err [00] 0 [05] 0 [06] 0
> MSDUs with error:crypt_err [00] 0 [05] 0 [06] 0
> MSDUs with error:peer_idx_inval [00] 0 [05] 0 [06] 0
>
> A-MPDU num subframes upto 10 [00] 2567 [05] 3178 [06] 1087
> A-MPDU num subframes 11-20 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 21-30 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 31-40 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 41-50 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes 51-60 [00] 0 [05] 0 [06] 0
> A-MPDU num subframes >60 [00] 0 [05] 0 [06] 0
>
> A-MSDU num subframes 1 [00] 2567 [05] 3178 [06] 1089
> A-MSDU num subframes 2 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes 3 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes 4 [00] 0 [05] 0 [06] 0
> A-MSDU num subframes >4 [00] 0 [05] 0 [06] 0
>
> Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>

Patch applied to ath-next branch of ath.git, thanks.

caee728ab761 ath10k: add sta rx packet stats per tid

--
https://patchwork.kernel.org/patch/10193935/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2018-03-02 14:24:46

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH] ath10k: Add sta rx packet stats per tid

Vasanthakumar Thiagarajan <[email protected]> writes:

>> This added new ath10k-check warnings, I fixed those in the pending
>> branch:
>>
>> drivers/net/wireless/ath/ath10k/debug.h:203: Alignment should match open parenthesis
>> drivers/net/wireless/ath/ath10k/debug.h:226: Alignment should match open parenthesis
>> drivers/net/wireless/ath/ath10k/debugfs_sta.c:24: Alignment should
>> match open parenthesis
>> drivers/net/wireless/ath/ath10k/debugfs_sta.c:40: Alignment should
>> match open parenthesis
>> drivers/net/wireless/ath/ath10k/debugfs_sta.c:60: Alignment should
>> match open parenthesis
>>
>> Also I fixed the typo "rages" in debug.h. My changes:
>
> Thanks for fixing it. In most of the cases, fixing above warnings
> would result in lines > 80 chars.
> May be we need not be very strict about > 80 char limit?

In ath10k-check I set the limit to 90 chars, but I guess it could be
even higher than that. But on the other it shouldn't be too long, not
everyone like to have one huge window for editor :)

--
Kalle Valo