mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
435 lines
14 KiB
Diff
435 lines
14 KiB
Diff
From b308db4196622e2656bc7c8afd1a7ed345a2ec6d Mon Sep 17 00:00:00 2001
|
|
From: Benjamin Berg <benjamin.berg@intel.com>
|
|
Date: Wed, 1 Feb 2023 16:53:02 +0530
|
|
Subject: [PATCH] wifi: mac80211: add API to show the link STAs in debugfs
|
|
|
|
Create debugfs data per-link. For drivers, there is a new operation
|
|
link_sta_add_debugfs which will always be called.
|
|
|
|
For non-MLO, the station directory will be used directly rather than
|
|
creating a corresponding subdirectory. As such, non-MLO drivers can
|
|
simply continue to create the data from sta_debugfs_add.
|
|
|
|
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
|
|
[add missing inlines if !CONFIG_MAC80211_DEBUGFS]
|
|
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
|
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
|
|
---
|
|
include/net/mac80211.h | 4 ++
|
|
net/mac80211/debugfs_sta.c | 132 ++++++++++++++++++++++++++++++-------
|
|
net/mac80211/debugfs_sta.h | 12 ++++
|
|
net/mac80211/driver-ops.c | 27 +++++++-
|
|
net/mac80211/driver-ops.h | 16 +++++
|
|
net/mac80211/sta_info.c | 25 +++++++
|
|
net/mac80211/sta_info.h | 5 ++
|
|
7 files changed, 196 insertions(+), 25 deletions(-)
|
|
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -4376,6 +4376,10 @@ struct ieee80211_ops {
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta,
|
|
struct dentry *dir);
|
|
+ void (*link_sta_add_debugfs)(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_vif *vif,
|
|
+ struct ieee80211_link_sta *link_sta,
|
|
+ struct dentry *dir);
|
|
#endif
|
|
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
enum sta_notify_cmd, struct ieee80211_sta *sta);
|
|
--- a/net/mac80211/debugfs_sta.c
|
|
+++ b/net/mac80211/debugfs_sta.c
|
|
@@ -5,7 +5,7 @@
|
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
|
* Copyright(c) 2016 Intel Deutschland GmbH
|
|
- * Copyright (C) 2018 - 2021 Intel Corporation
|
|
+ * Copyright (C) 2018 - 2022 Intel Corporation
|
|
*/
|
|
|
|
#include <linux/debugfs.h>
|
|
@@ -435,8 +435,16 @@ static ssize_t sta_agg_status_write(stru
|
|
}
|
|
STA_OPS_RW(agg_status);
|
|
|
|
-static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
|
|
- size_t count, loff_t *ppos)
|
|
+/* link sta attributes */
|
|
+#define LINK_STA_OPS(name) \
|
|
+static const struct file_operations link_sta_ ##name## _ops = { \
|
|
+ .read = link_sta_##name##_read, \
|
|
+ .open = simple_open, \
|
|
+ .llseek = generic_file_llseek, \
|
|
+}
|
|
+
|
|
+static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
{
|
|
#define PRINT_HT_CAP(_cond, _str) \
|
|
do { \
|
|
@@ -446,8 +454,8 @@ static ssize_t sta_ht_capa_read(struct f
|
|
char *buf, *p;
|
|
int i;
|
|
ssize_t bufsz = 512;
|
|
- struct sta_info *sta = file->private_data;
|
|
- struct ieee80211_sta_ht_cap *htc = &sta->sta.deflink.ht_cap;
|
|
+ struct link_sta_info *link_sta = file->private_data;
|
|
+ struct ieee80211_sta_ht_cap *htc = &link_sta->pub->ht_cap;
|
|
ssize_t ret;
|
|
|
|
buf = kzalloc(bufsz, GFP_KERNEL);
|
|
@@ -524,7 +532,7 @@ static ssize_t sta_ht_capa_read(struct f
|
|
kfree(buf);
|
|
return ret;
|
|
}
|
|
-STA_OPS(ht_capa);
|
|
+LINK_STA_OPS(ht_capa);
|
|
|
|
static ssize_t sta_tx_fail_cnt_read(struct file *file, char __user *userbuf,
|
|
size_t count, loff_t *ppos)
|
|
@@ -569,12 +577,12 @@ static ssize_t sta_tx_fail_cnt_write(str
|
|
|
|
STA_OPS_RW(tx_fail_cnt);
|
|
|
|
-static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
|
|
- size_t count, loff_t *ppos)
|
|
+static ssize_t link_sta_vht_capa_read(struct file *file, char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
{
|
|
char *buf, *p;
|
|
- struct sta_info *sta = file->private_data;
|
|
- struct ieee80211_sta_vht_cap *vhtc = &sta->sta.deflink.vht_cap;
|
|
+ struct link_sta_info *link_sta = file->private_data;
|
|
+ struct ieee80211_sta_vht_cap *vhtc = &link_sta->pub->vht_cap;
|
|
ssize_t ret;
|
|
ssize_t bufsz = 512;
|
|
|
|
@@ -681,15 +689,15 @@ static ssize_t sta_vht_capa_read(struct
|
|
kfree(buf);
|
|
return ret;
|
|
}
|
|
-STA_OPS(vht_capa);
|
|
+LINK_STA_OPS(vht_capa);
|
|
|
|
-static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
|
|
- size_t count, loff_t *ppos)
|
|
+static ssize_t link_sta_he_capa_read(struct file *file, char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
{
|
|
char *buf, *p;
|
|
size_t buf_sz = PAGE_SIZE;
|
|
- struct sta_info *sta = file->private_data;
|
|
- struct ieee80211_sta_he_cap *hec = &sta->sta.deflink.he_cap;
|
|
+ struct link_sta_info *link_sta = file->private_data;
|
|
+ struct ieee80211_sta_he_cap *hec = &link_sta->pub->he_cap;
|
|
struct ieee80211_he_mcs_nss_supp *nss = &hec->he_mcs_nss_supp;
|
|
u8 ppe_size;
|
|
u8 *cap;
|
|
@@ -1054,15 +1062,15 @@ out:
|
|
kfree(buf);
|
|
return ret;
|
|
}
|
|
-STA_OPS(he_capa);
|
|
+LINK_STA_OPS(he_capa);
|
|
|
|
-static ssize_t sta_eht_capa_read(struct file *file, char __user *userbuf,
|
|
+static ssize_t link_sta_eht_capa_read(struct file *file, char __user *userbuf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
char *buf, *p;
|
|
size_t buf_sz = PAGE_SIZE;
|
|
- struct sta_info *sta = file->private_data;
|
|
- struct ieee80211_sta_eht_cap *ehtc = &sta->sta.deflink.eht_cap;
|
|
+ struct link_sta_info *link_sta = file->private_data;
|
|
+ struct ieee80211_sta_eht_cap *ehtc = &link_sta->pub->eht_cap;
|
|
struct ieee80211_eht_mcs_nss_supp *nss = &ehtc->eht_mcs_nss_supp;
|
|
u8 ppe_size;
|
|
u8 *cap;
|
|
@@ -1263,7 +1271,7 @@ out:
|
|
kfree(buf);
|
|
return ret;
|
|
}
|
|
-STA_OPS(eht_capa);
|
|
+LINK_STA_OPS(eht_capa);
|
|
|
|
static ssize_t
|
|
sta_reset_mac80211_tx_pkts_flow_read(struct file *file,
|
|
@@ -1470,10 +1478,6 @@ void ieee80211_sta_debugfs_add(struct st
|
|
DEBUGFS_ADD(num_ps_buf_frames);
|
|
DEBUGFS_ADD(last_seq_ctrl);
|
|
DEBUGFS_ADD(agg_status);
|
|
- DEBUGFS_ADD(ht_capa);
|
|
- DEBUGFS_ADD(vht_capa);
|
|
- DEBUGFS_ADD(he_capa);
|
|
- DEBUGFS_ADD(eht_capa);
|
|
DEBUGFS_ADD(reset_mac80211_tx_pkts_flow);
|
|
DEBUGFS_ADD(reset_mac80211_rx_pkts_flow);
|
|
DEBUGFS_ADD(mac80211_tx_pkts_flow);
|
|
@@ -1482,8 +1486,7 @@ void ieee80211_sta_debugfs_add(struct st
|
|
DEBUGFS_ADD(tx_fail_cnt);
|
|
#endif
|
|
|
|
- DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates);
|
|
- DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
|
|
+ /* FIXME: Kept here as the statistics are only done on the deflink */
|
|
DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
|
|
|
|
if (local->ops->wake_tx_queue) {
|
|
@@ -1506,3 +1509,84 @@ void ieee80211_sta_debugfs_remove(struct
|
|
debugfs_remove_recursive(sta->debugfs_dir);
|
|
sta->debugfs_dir = NULL;
|
|
}
|
|
+
|
|
+#undef DEBUGFS_ADD
|
|
+#undef DEBUGFS_ADD_COUNTER
|
|
+
|
|
+#define DEBUGFS_ADD(name) \
|
|
+ debugfs_create_file(#name, 0400, \
|
|
+ link_sta->debugfs_dir, link_sta, &link_sta_ ##name## _ops)
|
|
+#define DEBUGFS_ADD_COUNTER(name, field) \
|
|
+ debugfs_create_ulong(#name, 0400, link_sta->debugfs_dir, &link_sta->field)
|
|
+
|
|
+void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta)
|
|
+{
|
|
+ if (WARN_ON(!link_sta->sta->debugfs_dir))
|
|
+ return;
|
|
+
|
|
+ /* For non-MLO, leave the files in the main directory. */
|
|
+ if (link_sta->sta->sta.valid_links) {
|
|
+ char link_dir_name[10];
|
|
+
|
|
+ snprintf(link_dir_name, sizeof(link_dir_name),
|
|
+ "link-%d", link_sta->link_id);
|
|
+
|
|
+ link_sta->debugfs_dir =
|
|
+ debugfs_create_dir(link_dir_name,
|
|
+ link_sta->sta->debugfs_dir);
|
|
+ } else {
|
|
+ if (WARN_ON(link_sta != &link_sta->sta->deflink))
|
|
+ return;
|
|
+
|
|
+ link_sta->debugfs_dir = link_sta->sta->debugfs_dir;
|
|
+ }
|
|
+
|
|
+ DEBUGFS_ADD(ht_capa);
|
|
+ DEBUGFS_ADD(vht_capa);
|
|
+ DEBUGFS_ADD(he_capa);
|
|
+ DEBUGFS_ADD(eht_capa);
|
|
+
|
|
+ DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates);
|
|
+ DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
|
|
+}
|
|
+
|
|
+void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta)
|
|
+{
|
|
+ if (!link_sta->debugfs_dir || !link_sta->sta->debugfs_dir) {
|
|
+ link_sta->debugfs_dir = NULL;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (link_sta->debugfs_dir == link_sta->sta->debugfs_dir) {
|
|
+ WARN_ON(link_sta != &link_sta->sta->deflink);
|
|
+ link_sta->sta->debugfs_dir = NULL;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ debugfs_remove_recursive(link_sta->debugfs_dir);
|
|
+ link_sta->debugfs_dir = NULL;
|
|
+}
|
|
+
|
|
+void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta)
|
|
+{
|
|
+ if (WARN_ON(!link_sta->debugfs_dir))
|
|
+ return;
|
|
+
|
|
+ drv_link_sta_add_debugfs(link_sta->sta->local, link_sta->sta->sdata,
|
|
+ link_sta->pub, link_sta->debugfs_dir);
|
|
+}
|
|
+
|
|
+void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta)
|
|
+{
|
|
+ if (!link_sta->debugfs_dir)
|
|
+ return;
|
|
+
|
|
+ if (WARN_ON(link_sta->debugfs_dir == link_sta->sta->debugfs_dir))
|
|
+ return;
|
|
+
|
|
+ /* Recreate the directory excluding the driver data */
|
|
+ debugfs_remove_recursive(link_sta->debugfs_dir);
|
|
+ link_sta->debugfs_dir = NULL;
|
|
+
|
|
+ ieee80211_link_sta_debugfs_add(link_sta);
|
|
+}
|
|
--- a/net/mac80211/debugfs_sta.h
|
|
+++ b/net/mac80211/debugfs_sta.h
|
|
@@ -7,9 +7,21 @@
|
|
#ifdef CPTCFG_MAC80211_DEBUGFS
|
|
void ieee80211_sta_debugfs_add(struct sta_info *sta);
|
|
void ieee80211_sta_debugfs_remove(struct sta_info *sta);
|
|
+
|
|
+void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta);
|
|
+void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta);
|
|
+
|
|
+void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta);
|
|
+void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta);
|
|
#else
|
|
static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
|
|
static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
|
|
+
|
|
+static inline void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta) {}
|
|
+static inline void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta) {}
|
|
+
|
|
+static inline void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta) {}
|
|
+static inline void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta) {}
|
|
#endif
|
|
|
|
#endif /* __MAC80211_DEBUGFS_STA_H */
|
|
--- a/net/mac80211/driver-ops.c
|
|
+++ b/net/mac80211/driver-ops.c
|
|
@@ -7,6 +7,7 @@
|
|
#include "ieee80211_i.h"
|
|
#include "trace.h"
|
|
#include "driver-ops.h"
|
|
+#include "debugfs_sta.h"
|
|
|
|
int drv_start(struct ieee80211_local *local)
|
|
{
|
|
@@ -541,6 +542,11 @@ int drv_change_sta_links(struct ieee8021
|
|
struct ieee80211_sta *sta,
|
|
u16 old_links, u16 new_links)
|
|
{
|
|
+ struct sta_info *info = container_of(sta, struct sta_info, sta);
|
|
+ struct link_sta_info *link_sta;
|
|
+ unsigned long links_to_add;
|
|
+ unsigned long links_to_rem;
|
|
+ unsigned int link_id;
|
|
int ret = -EOPNOTSUPP;
|
|
|
|
might_sleep();
|
|
@@ -554,11 +560,30 @@ int drv_change_sta_links(struct ieee8021
|
|
if (old_links == new_links)
|
|
return 0;
|
|
|
|
+ links_to_add = ~old_links & new_links;
|
|
+ links_to_rem = old_links & ~new_links;
|
|
+
|
|
+ for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) {
|
|
+ link_sta = rcu_dereference_protected(info->link[link_id],
|
|
+ lockdep_is_held(&local->sta_mtx));
|
|
+
|
|
+ ieee80211_link_sta_debugfs_drv_remove(link_sta);
|
|
+ }
|
|
+
|
|
trace_drv_change_sta_links(local, sdata, sta, old_links, new_links);
|
|
if (local->ops->change_sta_links)
|
|
ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta,
|
|
old_links, new_links);
|
|
trace_drv_return_int(local, ret);
|
|
|
|
- return ret;
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
|
+ link_sta = rcu_dereference_protected(info->link[link_id],
|
|
+ lockdep_is_held(&local->sta_mtx));
|
|
+ ieee80211_link_sta_debugfs_drv_add(link_sta);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
}
|
|
--- a/net/mac80211/driver-ops.h
|
|
+++ b/net/mac80211/driver-ops.h
|
|
@@ -497,6 +497,22 @@ static inline void drv_sta_add_debugfs(s
|
|
local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
|
|
sta, dir);
|
|
}
|
|
+
|
|
+static inline void drv_link_sta_add_debugfs(struct ieee80211_local *local,
|
|
+ struct ieee80211_sub_if_data *sdata,
|
|
+ struct ieee80211_link_sta *link_sta,
|
|
+ struct dentry *dir)
|
|
+{
|
|
+ might_sleep();
|
|
+
|
|
+ sdata = get_bss_sdata(sdata);
|
|
+ if (!check_sdata_in_driver(sdata))
|
|
+ return;
|
|
+
|
|
+ if (local->ops->link_sta_add_debugfs)
|
|
+ local->ops->link_sta_add_debugfs(&local->hw, &sdata->vif,
|
|
+ link_sta, dir);
|
|
+}
|
|
#endif
|
|
|
|
static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
|
|
--- a/net/mac80211/sta_info.c
|
|
+++ b/net/mac80211/sta_info.c
|
|
@@ -329,6 +329,9 @@ static void sta_remove_link(struct sta_i
|
|
if (unhash)
|
|
link_sta_info_hash_del(sta->local, link_sta);
|
|
|
|
+ if (test_sta_flag(sta, WLAN_STA_INSERTED))
|
|
+ ieee80211_link_sta_debugfs_remove(link_sta);
|
|
+
|
|
if (link_sta != &sta->deflink)
|
|
alloc = container_of(link_sta, typeof(*alloc), info);
|
|
|
|
@@ -847,6 +850,26 @@ static int sta_info_insert_finish(struct
|
|
|
|
ieee80211_sta_debugfs_add(sta);
|
|
rate_control_add_sta_debugfs(sta);
|
|
+ if (sta->sta.valid_links) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
|
|
+ struct link_sta_info *link_sta;
|
|
+
|
|
+ link_sta = rcu_dereference_protected(sta->link[i],
|
|
+ lockdep_is_held(&local->sta_mtx));
|
|
+
|
|
+ if (!link_sta)
|
|
+ continue;
|
|
+
|
|
+ ieee80211_link_sta_debugfs_add(link_sta);
|
|
+ if (sdata->vif.active_links & BIT(i))
|
|
+ ieee80211_link_sta_debugfs_drv_add(link_sta);
|
|
+ }
|
|
+ } else {
|
|
+ ieee80211_link_sta_debugfs_add(&sta->deflink);
|
|
+ ieee80211_link_sta_debugfs_drv_add(&sta->deflink);
|
|
+ }
|
|
|
|
sinfo->generation = local->sta_generation;
|
|
cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
|
|
@@ -2788,6 +2811,8 @@ int ieee80211_sta_allocate_link(struct s
|
|
|
|
sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta);
|
|
|
|
+ ieee80211_link_sta_debugfs_add(&alloc->info);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--- a/net/mac80211/sta_info.h
|
|
+++ b/net/mac80211/sta_info.h
|
|
@@ -530,6 +530,7 @@ struct ieee80211_fragment_cache {
|
|
* @status_stats.avg_ack_signal: average ACK signal
|
|
* @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
|
|
* taken from HT/VHT capabilities or VHT operating mode notification
|
|
+ * @debugfs_dir: debug filesystem directory dentry
|
|
* @pub: public (driver visible) link STA data
|
|
* TODO Move other link params from sta_info as required for MLD operation
|
|
*/
|
|
@@ -577,6 +578,10 @@ struct link_sta_info {
|
|
|
|
enum ieee80211_sta_rx_bandwidth cur_max_bandwidth;
|
|
|
|
+#ifdef CPTCFG_MAC80211_DEBUGFS
|
|
+ struct dentry *debugfs_dir;
|
|
+#endif
|
|
+
|
|
struct ieee80211_link_sta *pub;
|
|
};
|
|
|