mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
430 lines
13 KiB
Diff
430 lines
13 KiB
Diff
From 1c29f6fcfc24520277b7401557373fbebee9c17b Mon Sep 17 00:00:00 2001
|
|
From: Dinesh Karthikeyan <quic_dinek@quicinc.com>
|
|
Date: Thu, 23 Jun 2022 17:58:38 +0530
|
|
Subject: [PATCH] ath12k: Add missing per peer parameters
|
|
|
|
Add driver_rx_pkts_flow, driver_tx_pkts_flow, reset_tx_stats,
|
|
reset_rx_stats paramters to display stats for each peer associated.
|
|
|
|
Command to dump the Tx pkts flow in driver:
|
|
cat
|
|
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/
|
|
XX\:XX\:XX\:XX\:XX\:XX/driver_tx_pkts_flow
|
|
|
|
Command to dump the Rx pkts flow in driver:
|
|
cat
|
|
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/
|
|
XX\:XX\:XX\:XX\:XX\:XX/driver_rx_pkts_flow
|
|
|
|
Commands to reset the Tx/Rx pkts flow in driver:
|
|
echo 1 >
|
|
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/
|
|
XX\:XX\:XX\:XX\:XX\:XX/reset_tx_stats
|
|
|
|
echo 1 >
|
|
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/
|
|
XX\:XX\:XX\:XX\:XX\:XX/reset_rx_stats
|
|
|
|
Sample output for Tx/Rx packet flow count:
|
|
|
|
cat sys/kernel/debug/ieee80211/phy0/netdev\:wlan0/stations/00\:0
|
|
3\:7f\:08\:52\:00/driver_rx_pkts_flow
|
|
Rx packets inflow from HW: 899
|
|
Rx packets outflow from driver: 899
|
|
|
|
cat sys/kernel/debug/ieee80211/phy0/netdev\:wlan0/stations/00\:0
|
|
3\:7f\:08\:52\:00/driver_tx_pkts_flow
|
|
Tx packets inflow from mac80211: 1797
|
|
Tx packets outflow to HW: 1797
|
|
|
|
Signed-off-by: Dinesh Karthikeyan <quic_dinek@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/core.h | 12 ++
|
|
drivers/net/wireless/ath/ath12k/debugfs.h | 2 +
|
|
drivers/net/wireless/ath/ath12k/debugfs_sta.c | 185 +++++++++++++++++-
|
|
drivers/net/wireless/ath/ath12k/dp_rx.c | 45 +++++
|
|
drivers/net/wireless/ath/ath12k/mac.c | 11 ++
|
|
5 files changed, 253 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/core.h
|
|
@@ -498,6 +498,16 @@ struct ath12k_wbm_tx_stats {
|
|
u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
|
|
};
|
|
|
|
+struct ath12k_driver_tx_pkts_flow {
|
|
+ atomic_t pkts_in;
|
|
+ atomic_t pkts_out;
|
|
+};
|
|
+
|
|
+struct ath12k_driver_rx_pkts_flow {
|
|
+ atomic_t pkts_frm_hw;
|
|
+ atomic_t pkts_out;
|
|
+};
|
|
+
|
|
struct ath12k_sta {
|
|
struct ath12k_vif *arvif;
|
|
|
|
@@ -528,6 +538,8 @@ struct ath12k_sta {
|
|
bool use_4addr_set;
|
|
u16 tcl_metadata;
|
|
u32 bw_prev;
|
|
+ struct ath12k_driver_tx_pkts_flow drv_tx_pkts;
|
|
+ struct ath12k_driver_rx_pkts_flow drv_rx_pkts;
|
|
};
|
|
|
|
#define ATH12K_HALF_20MHZ_BW 10
|
|
--- a/drivers/net/wireless/ath/ath12k/debugfs.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/debugfs.h
|
|
@@ -12,6 +12,8 @@
|
|
#define ATH12K_TX_POWER_MAX_VAL 70
|
|
#define ATH12K_TX_POWER_MIN_VAL 0
|
|
|
|
+#define ATH12K_DRV_TX_STATS_SIZE 1024
|
|
+
|
|
/* htt_dbg_ext_stats_type */
|
|
enum ath12k_dbg_htt_ext_stats_type {
|
|
ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
|
|
--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c
|
|
@@ -12,6 +12,7 @@
|
|
#include "debug.h"
|
|
#include "dp_tx.h"
|
|
#include "debugfs_htt_stats.h"
|
|
+#include "debugfs.h"
|
|
|
|
void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta,
|
|
struct ath12k_per_peer_tx_stats *peer_stats,
|
|
@@ -1056,6 +1057,176 @@ static const struct file_operations fops
|
|
.llseek = default_llseek,
|
|
};
|
|
|
|
+static ssize_t
|
|
+ath12k_dbg_sta_dump_driver_tx_pkts_flow(struct file *file,
|
|
+ const char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ieee80211_sta *sta = file->private_data;
|
|
+ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
+ struct ath12k *ar = arsta->arvif->ar;
|
|
+ int len = 0, ret_val;
|
|
+ const int size = ATH12K_DRV_TX_STATS_SIZE;
|
|
+ char *buf;
|
|
+
|
|
+ if (!arsta->tx_stats)
|
|
+ return -ENOENT;
|
|
+
|
|
+ buf = kzalloc(ATH12K_DRV_TX_STATS_SIZE, GFP_KERNEL);
|
|
+ if (!buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "Tx packets inflow from mac80211: %u\n",
|
|
+ atomic_read(&arsta->drv_tx_pkts.pkts_in));
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "Tx packets outflow to HW: %u\n",
|
|
+ atomic_read(&arsta->drv_tx_pkts.pkts_out));
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ if (len > size)
|
|
+ len = size;
|
|
+
|
|
+ ret_val = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
+ kfree(buf);
|
|
+
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret_val;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_driver_tx_pkts_flow = {
|
|
+ .read = ath12k_dbg_sta_dump_driver_tx_pkts_flow,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
+static ssize_t ath12k_dbg_sta_reset_tx_stats(struct file *file,
|
|
+ const char __user *buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ieee80211_sta *sta = file->private_data;
|
|
+ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
+ struct ath12k *ar = arsta->arvif->ar;
|
|
+ int ret, reset;
|
|
+
|
|
+ if (!arsta->tx_stats || !arsta->wbm_tx_stats)
|
|
+ return -ENOENT;
|
|
+
|
|
+ ret = kstrtoint_from_user(buf, count, 0, &reset);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (!reset || reset > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ memset(arsta->tx_stats, 0, sizeof(*arsta->tx_stats));
|
|
+ atomic_set(&arsta->drv_tx_pkts.pkts_in, 0);
|
|
+ atomic_set(&arsta->drv_tx_pkts.pkts_out, 0);
|
|
+ memset(arsta->wbm_tx_stats->wbm_tx_comp_stats, 0, sizeof(*arsta->wbm_tx_stats));
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ ret = count;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_reset_tx_stats = {
|
|
+ .write = ath12k_dbg_sta_reset_tx_stats,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
+static ssize_t
|
|
+ath12k_dbg_sta_dump_driver_rx_pkts_flow(struct file *file,
|
|
+ char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ieee80211_sta *sta = file->private_data;
|
|
+ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
+ struct ath12k *ar = arsta->arvif->ar;
|
|
+ struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
|
+ int len = 0, ret_val = 0;
|
|
+ const int size = 1024;
|
|
+ char *buf;
|
|
+
|
|
+ if (!rx_stats)
|
|
+ return -ENOENT;
|
|
+
|
|
+ buf = kzalloc(size, GFP_KERNEL);
|
|
+ if (!buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "Rx packets inflow from HW: %u\n",
|
|
+ atomic_read(&arsta->drv_rx_pkts.pkts_frm_hw));
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "Rx packets outflow from driver: %u\n",
|
|
+ atomic_read(&arsta->drv_rx_pkts.pkts_out));
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, "\n");
|
|
+
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ if (len > size)
|
|
+ len = size;
|
|
+
|
|
+ ret_val = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
+ kfree(buf);
|
|
+
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret_val;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_driver_rx_pkts_flow = {
|
|
+ .read = ath12k_dbg_sta_dump_driver_rx_pkts_flow,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
+static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
|
|
+ const char __user *buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ieee80211_sta *sta = file->private_data;
|
|
+ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
+ struct ath12k *ar = arsta->arvif->ar;
|
|
+ int ret, reset;
|
|
+
|
|
+ if (!arsta->rx_stats)
|
|
+ return -ENOENT;
|
|
+
|
|
+ ret = kstrtoint_from_user(buf, count, 0, &reset);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (!reset || reset > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ memset(arsta->rx_stats, 0, sizeof(*arsta->rx_stats));
|
|
+ atomic_set(&arsta->drv_rx_pkts.pkts_frm_hw, 0);
|
|
+ atomic_set(&arsta->drv_rx_pkts.pkts_out, 0);
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ ret = count;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_reset_rx_stats = {
|
|
+ .write = ath12k_dbg_sta_reset_rx_stats,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta, struct dentry *dir)
|
|
{
|
|
@@ -1070,12 +1241,22 @@ void ath12k_debugfs_sta_op_add(struct ie
|
|
return;
|
|
}
|
|
|
|
- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar))
|
|
+ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) {
|
|
debugfs_create_file("tx_stats", 0400, dir, sta,
|
|
&fops_tx_stats);
|
|
- if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))
|
|
+ debugfs_create_file("reset_tx_stats", 0600, dir, sta,
|
|
+ &fops_reset_tx_stats);
|
|
+ debugfs_create_file("driver_tx_pkts_flow", 0400, dir, sta,
|
|
+ &fops_driver_tx_pkts_flow);
|
|
+ }
|
|
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
|
|
debugfs_create_file("rx_stats", 0400, dir, sta,
|
|
&fops_rx_stats);
|
|
+ debugfs_create_file("reset_rx_stats", 0600, dir, sta,
|
|
+ &fops_reset_rx_stats);
|
|
+ debugfs_create_file("driver_rx_pkts_flow", 0400, dir, sta,
|
|
+ &fops_driver_rx_pkts_flow);
|
|
+ }
|
|
|
|
debugfs_create_file("htt_peer_stats", 0400, dir, sta,
|
|
&fops_htt_peer_stats);
|
|
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
|
|
@@ -2766,6 +2766,7 @@ static void ath12k_dp_rx_deliver_msdu(st
|
|
u8 decap = DP_RX_DECAP_TYPE_RAW;
|
|
bool is_mcbc = rxcb->is_mcbc;
|
|
bool is_eapol = rxcb->is_eapol;
|
|
+ struct ath12k_sta *arsta = NULL;
|
|
|
|
if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) &&
|
|
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
|
|
@@ -2827,6 +2828,18 @@ static void ath12k_dp_rx_deliver_msdu(st
|
|
rx_status->flag |= RX_FLAG_8023;
|
|
|
|
ieee80211_rx_napi(ar->ah->hw, pubsta, msdu, napi);
|
|
+
|
|
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
|
|
+ if (!(status->flag & RX_FLAG_ONLY_MONITOR)) {
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ if (peer && peer->sta)
|
|
+ arsta =
|
|
+ (struct ath12k_sta *)peer->sta->drv_priv;
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+ if (arsta)
|
|
+ atomic_inc(&arsta->drv_rx_pkts.pkts_out);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
|
|
@@ -2971,6 +2984,9 @@ int ath12k_dp_rx_process(struct ath12k_b
|
|
u32 *rx_desc;
|
|
int i;
|
|
u64 desc_va;
|
|
+ struct ath12k_sta *arsta = NULL;
|
|
+ struct ath12k_peer *peer = NULL;
|
|
+ struct ath12k *ar;
|
|
|
|
__skb_queue_head_init(&msdu_list);
|
|
|
|
@@ -2992,6 +3008,8 @@ try_again:
|
|
mac_id = u32_get_bits(desc.info0,
|
|
HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
|
|
|
|
+ ar = ab->pdevs[mac_id].ar;
|
|
+
|
|
desc_va = ((u64)desc.buf_va_hi << 32 | desc.buf_va_lo);
|
|
desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
|
|
|
|
@@ -3037,6 +3055,19 @@ try_again:
|
|
rxcb->tid = u32_get_bits(desc.rx_mpdu_info.info0,
|
|
RX_MPDU_DESC_INFO0_TID);
|
|
|
|
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) {
|
|
+ rcu_read_lock();
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+ peer = ath12k_peer_find_by_id(ab, rxcb->peer_id);
|
|
+ if (peer && peer->sta)
|
|
+ arsta =
|
|
+ (struct ath12k_sta *)peer->sta->drv_priv;
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ if (arsta)
|
|
+ atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw);
|
|
+ rcu_read_unlock();
|
|
+ }
|
|
+
|
|
__skb_queue_tail(&msdu_list, msdu);
|
|
|
|
if (!rxcb->is_continuation) {
|
|
@@ -3874,6 +3905,8 @@ static int ath12k_dp_rx_h_null_q_desc(st
|
|
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
|
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
|
bool fast_rx;
|
|
+ struct ath12k_sta *arsta = NULL;
|
|
+ struct ath12k_peer *peer = NULL;
|
|
|
|
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
|
peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
|
|
@@ -3935,6 +3968,18 @@ static int ath12k_dp_rx_h_null_q_desc(st
|
|
* rx with mac80211. Need not worry about cleaning up amsdu_list.
|
|
*/
|
|
|
|
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
|
|
+ peer_id = ath12k_dp_rx_h_peer_id(ar->ab, desc);
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ if (peer_id)
|
|
+ peer = ath12k_peer_find_by_id(ar->ab, rxcb->peer_id);
|
|
+ if (peer && peer->sta)
|
|
+ arsta = (struct ath12k_sta *)peer->sta->drv_priv;
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+ if (arsta)
|
|
+ atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.c
|
|
@@ -6469,6 +6469,7 @@ static void ath12k_mac_setup_he_eht_cap(
|
|
band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
|
|
band->n_iftype_data = count;
|
|
}
|
|
+
|
|
}
|
|
|
|
static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
|
|
@@ -6726,6 +6727,7 @@ static void ath12k_mac_op_tx(struct ieee
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
struct ieee80211_key_conf *key = info->control.hw_key;
|
|
struct ath12k_sta *arsta = NULL;
|
|
+ struct ieee80211_sta *sta = control->sta;
|
|
u32 info_flags = info->flags;
|
|
bool is_prb_rsp;
|
|
int ret;
|
|
@@ -6763,6 +6765,15 @@ static void ath12k_mac_op_tx(struct ieee
|
|
ret);
|
|
ieee80211_free_txskb(ah->hw, skb);
|
|
}
|
|
+
|
|
+ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && sta) {
|
|
+ arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
+ if (arsta) {
|
|
+ atomic_inc(&arsta->drv_tx_pkts.pkts_in);
|
|
+ if (!ret)
|
|
+ atomic_inc(&arsta->drv_tx_pkts.pkts_out);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
void ath12k_mac_drain_tx(struct ath12k *ar)
|