wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Add-missing-per-peer-parameters.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

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)