mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 01:41:24 +00:00
277 lines
8.7 KiB
Diff
277 lines
8.7 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -189,6 +189,16 @@ enum ath11k_dev_flags {
|
|
ATH11K_FLAG_FW_RESTART_FOR_HOST,
|
|
};
|
|
|
|
+#define ATH11K_STATS_MGMT_FRM_TYPE_MAX 16
|
|
+
|
|
+struct ath11k_mgmt_frame_stats {
|
|
+ u32 tx_succ_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_fail_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 rx_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_compl_succ[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_compl_fail[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+};
|
|
+
|
|
struct ath11k_vif {
|
|
u32 vdev_id;
|
|
enum wmi_vdev_type vdev_type;
|
|
@@ -236,6 +246,7 @@ struct ath11k_vif {
|
|
bool wpaie_present;
|
|
struct ieee80211_chanctx_conf chanctx;
|
|
struct dentry *debugfs_twt;
|
|
+ struct ath11k_mgmt_frame_stats mgmt_stats;
|
|
};
|
|
|
|
struct ath11k_vif_iter {
|
|
--- a/drivers/net/wireless/ath/ath11k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/debug.c
|
|
@@ -1611,6 +1611,87 @@ static const struct file_operations fops
|
|
.open = simple_open
|
|
};
|
|
|
|
+static ssize_t ath11k_dump_mgmt_stats(struct file *file, char __user *ubuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath11k *ar = file->private_data;
|
|
+ struct ath11k_vif *arvif = NULL;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ int len = 0, ret, i;
|
|
+ int size = (TARGET_NUM_VDEVS - 1) * 1500;
|
|
+ char *buf;
|
|
+ const char *mgmt_frm_type[ATH11K_STATS_MGMT_FRM_TYPE_MAX-1] = {"assoc_req", "assoc_resp",
|
|
+ "reassoc_req", "reassoc_resp",
|
|
+ "probe_req", "probe_resp",
|
|
+ "timing_advertisement", "reserved",
|
|
+ "beacon", "atim", "disassoc",
|
|
+ "auth", "deauth", "action", "action_no_ack"};
|
|
+
|
|
+ if (ar->state != ATH11K_STATE_ON)
|
|
+ return -ENETDOWN;
|
|
+
|
|
+ buf = kzalloc(size, GFP_KERNEL);
|
|
+ if (!buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ list_for_each_entry (arvif, &ar->arvifs, list) {
|
|
+ if (!arvif)
|
|
+ break;
|
|
+
|
|
+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
|
+ continue;
|
|
+
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+ len += scnprintf(buf + len, size - len, "MGMT frame stats for vdev %u :\n",
|
|
+ arvif->vdev_id);
|
|
+ len += scnprintf(buf + len, size - len, " TX stats :\n ");
|
|
+ len += scnprintf(buf + len, size - len, " Success frames:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_succ_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " Failed frames:\n");
|
|
+
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_fail_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " RX stats :\n");
|
|
+ len += scnprintf(buf + len, size - len, " Success frames:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->rx_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " Tx completion stats :\n");
|
|
+ len += scnprintf(buf + len, size - len, " success completions:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_compl_succ[i]);
|
|
+ len += scnprintf(buf + len, size - len, " failure completions:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_compl_fail[i]);
|
|
+ }
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+ if (len > size)
|
|
+ len = size;
|
|
+
|
|
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ kfree(buf);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_dump_mgmt_stats = {
|
|
+ .read = ath11k_dump_mgmt_stats,
|
|
+ .open = simple_open
|
|
+};
|
|
+
|
|
int ath11k_debug_register(struct ath11k *ar)
|
|
{
|
|
struct ath11k_base *ab = ar->ab;
|
|
@@ -1655,6 +1736,8 @@ int ath11k_debug_register(struct ath11k
|
|
debugfs_create_file("btcoex_duty_cycle", 0644,
|
|
ar->debug.debugfs_pdev, ar,
|
|
&fops__btcoex_duty_cycle);
|
|
+ debugfs_create_file("dump_mgmt_stats", 0644, ar->debug.debugfs_pdev,
|
|
+ ar, &fops_dump_mgmt_stats);
|
|
|
|
if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
|
|
debugfs_create_file("dfs_simulate_radar", 0200,
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -4822,20 +4822,35 @@ static void ath11k_mac_op_tx(struct ieee
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats;
|
|
bool is_prb_rsp;
|
|
int ret;
|
|
+ u16 frm_type = 0;
|
|
|
|
if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
|
|
skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
|
|
} else if (ieee80211_is_mgmt(hdr->frame_control)) {
|
|
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
|
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
|
|
ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
|
|
if (ret) {
|
|
- if (ret != -EBUSY) {
|
|
+ if (ret != -EBUSY)
|
|
ath11k_warn(ar->ab, "failed to queue management frame %d\n",
|
|
ret);
|
|
- }
|
|
ieee80211_free_txskb(ar->hw, skb);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ mgmt_stats->tx_fail_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+ } else {
|
|
+
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ mgmt_stats->tx_succ_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
}
|
|
return;
|
|
}
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
|
@@ -310,6 +310,7 @@ int ath11k_peer_create(struct ath11k *ar
|
|
|
|
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
|
|
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
|
|
+ peer->vif = arvif->vif;
|
|
|
|
ar->num_peers++;
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
|
@@ -20,6 +20,7 @@ struct ppdu_user_delayba {
|
|
struct ath11k_peer {
|
|
struct list_head list;
|
|
struct ieee80211_sta *sta;
|
|
+ struct ieee80211_vif *vif;
|
|
int vdev_id;
|
|
u8 addr[ETH_ALEN];
|
|
int peer_id;
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -4846,6 +4846,12 @@ static int wmi_process_mgmt_tx_comp(stru
|
|
struct sk_buff *msdu;
|
|
struct ieee80211_tx_info *info;
|
|
struct ath11k_skb_cb *skb_cb;
|
|
+ struct ieee80211_hdr *hdr;
|
|
+ struct ath11k_peer *peer;
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ u16 frm_type;
|
|
|
|
spin_lock_bh(&ar->txmgmt_idr_lock);
|
|
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
|
@@ -4867,6 +4873,31 @@ static int wmi_process_mgmt_tx_comp(stru
|
|
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)
|
|
info->flags |= IEEE80211_TX_STAT_ACK;
|
|
|
|
+ hdr = (struct ieee80211_hdr *)msdu->data;
|
|
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
|
+
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
|
|
+ if (!peer) {
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+ ath11k_warn(ar->ab, "failed to find peer to update txcompl mgmt stats\n");
|
|
+ goto skip_mgmt_stats;
|
|
+ }
|
|
+
|
|
+ vif = peer->vif;
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+ arvif = ath11k_vif_to_arvif(vif);
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+
|
|
+ if (!status)
|
|
+ mgmt_stats->tx_compl_succ[frm_type]++;
|
|
+ else
|
|
+ mgmt_stats->tx_compl_fail[frm_type]++;
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+skip_mgmt_stats:
|
|
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
|
|
|
/* WARN when we received this event without doing any mgmt tx */
|
|
@@ -6199,6 +6230,11 @@ static void ath11k_mgmt_rx_event(struct
|
|
struct ieee80211_hdr *hdr;
|
|
u16 fc;
|
|
struct ieee80211_supported_band *sband;
|
|
+ struct ath11k_peer *peer;
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ u16 frm_type = 0;
|
|
|
|
if (ath11k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) {
|
|
ath11k_warn(ab, "failed to extract mgmt rx event");
|
|
@@ -6260,7 +6296,30 @@ static void ath11k_mgmt_rx_event(struct
|
|
|
|
hdr = (struct ieee80211_hdr *)skb->data;
|
|
fc = le16_to_cpu(hdr->frame_control);
|
|
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, fc);
|
|
+
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+
|
|
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr1);
|
|
+ if(!peer)
|
|
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr3);
|
|
+ if (!peer) {
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ goto skip_mgmt_stats;
|
|
+ }
|
|
+
|
|
+ vif = peer->vif;
|
|
+
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ arvif = ath11k_vif_to_arvif(vif);
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+ mgmt_stats->rx_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
|
+skip_mgmt_stats:
|
|
/* Firmware is guaranteed to report all essential management frames via
|
|
* WMI while it can deliver some extra via HTT. Since there can be
|
|
* duplicates split the reporting wrt monitor/sniffing.
|