Skip to content

Commit d2caad5

Browse files
benzeajmberg-intel
authored andcommitted
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 <[email protected]> [add missing inlines if !CONFIG_MAC80211_DEBUGFS] Signed-off-by: Johannes Berg <[email protected]>
1 parent 1d9e4c9 commit d2caad5

File tree

7 files changed

+200
-23
lines changed

7 files changed

+200
-23
lines changed

include/net/mac80211.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3790,6 +3790,13 @@ struct ieee80211_prep_tx_info {
37903790
* should be within a CONFIG_MAC80211_DEBUGFS conditional. This
37913791
* callback can sleep.
37923792
*
3793+
* @link_sta_add_debugfs: Drivers can use this callback to add debugfs files
3794+
* when a link is added to a mac80211 station. This callback
3795+
* should be within a CPTCFG_MAC80211_DEBUGFS conditional. This
3796+
* callback can sleep.
3797+
* For non-MLO the callback will be called once for the deflink with the
3798+
* station's directory rather than a separate subdirectory.
3799+
*
37933800
* @sta_notify: Notifies low level driver about power state transition of an
37943801
* associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating
37953802
* in AP mode, this callback will not be called when the flag
@@ -4260,6 +4267,10 @@ struct ieee80211_ops {
42604267
struct ieee80211_vif *vif,
42614268
struct ieee80211_sta *sta,
42624269
struct dentry *dir);
4270+
void (*link_sta_add_debugfs)(struct ieee80211_hw *hw,
4271+
struct ieee80211_vif *vif,
4272+
struct ieee80211_link_sta *link_sta,
4273+
struct dentry *dir);
42634274
#endif
42644275
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
42654276
enum sta_notify_cmd, struct ieee80211_sta *sta);

net/mac80211/debugfs_sta.c

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Copyright 2007 Johannes Berg <[email protected]>
66
* Copyright 2013-2014 Intel Mobile Communications GmbH
77
* Copyright(c) 2016 Intel Deutschland GmbH
8-
* Copyright (C) 2018 - 2021 Intel Corporation
8+
* Copyright (C) 2018 - 2022 Intel Corporation
99
*/
1010

1111
#include <linux/debugfs.h>
@@ -435,8 +435,16 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
435435
}
436436
STA_OPS_RW(agg_status);
437437

438-
static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
439-
size_t count, loff_t *ppos)
438+
/* link sta attributes */
439+
#define LINK_STA_OPS(name) \
440+
static const struct file_operations link_sta_ ##name## _ops = { \
441+
.read = link_sta_##name##_read, \
442+
.open = simple_open, \
443+
.llseek = generic_file_llseek, \
444+
}
445+
446+
static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf,
447+
size_t count, loff_t *ppos)
440448
{
441449
#define PRINT_HT_CAP(_cond, _str) \
442450
do { \
@@ -446,8 +454,8 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
446454
char *buf, *p;
447455
int i;
448456
ssize_t bufsz = 512;
449-
struct sta_info *sta = file->private_data;
450-
struct ieee80211_sta_ht_cap *htc = &sta->sta.deflink.ht_cap;
457+
struct link_sta_info *link_sta = file->private_data;
458+
struct ieee80211_sta_ht_cap *htc = &link_sta->pub->ht_cap;
451459
ssize_t ret;
452460

453461
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -524,14 +532,14 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
524532
kfree(buf);
525533
return ret;
526534
}
527-
STA_OPS(ht_capa);
535+
LINK_STA_OPS(ht_capa);
528536

529-
static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
530-
size_t count, loff_t *ppos)
537+
static ssize_t link_sta_vht_capa_read(struct file *file, char __user *userbuf,
538+
size_t count, loff_t *ppos)
531539
{
532540
char *buf, *p;
533-
struct sta_info *sta = file->private_data;
534-
struct ieee80211_sta_vht_cap *vhtc = &sta->sta.deflink.vht_cap;
541+
struct link_sta_info *link_sta = file->private_data;
542+
struct ieee80211_sta_vht_cap *vhtc = &link_sta->pub->vht_cap;
535543
ssize_t ret;
536544
ssize_t bufsz = 512;
537545

@@ -638,15 +646,15 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
638646
kfree(buf);
639647
return ret;
640648
}
641-
STA_OPS(vht_capa);
649+
LINK_STA_OPS(vht_capa);
642650

643-
static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
644-
size_t count, loff_t *ppos)
651+
static ssize_t link_sta_he_capa_read(struct file *file, char __user *userbuf,
652+
size_t count, loff_t *ppos)
645653
{
646654
char *buf, *p;
647655
size_t buf_sz = PAGE_SIZE;
648-
struct sta_info *sta = file->private_data;
649-
struct ieee80211_sta_he_cap *hec = &sta->sta.deflink.he_cap;
656+
struct link_sta_info *link_sta = file->private_data;
657+
struct ieee80211_sta_he_cap *hec = &link_sta->pub->he_cap;
650658
struct ieee80211_he_mcs_nss_supp *nss = &hec->he_mcs_nss_supp;
651659
u8 ppe_size;
652660
u8 *cap;
@@ -1011,7 +1019,7 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
10111019
kfree(buf);
10121020
return ret;
10131021
}
1014-
STA_OPS(he_capa);
1022+
LINK_STA_OPS(he_capa);
10151023

10161024
#define DEBUGFS_ADD(name) \
10171025
debugfs_create_file(#name, 0400, \
@@ -1048,12 +1056,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
10481056
DEBUGFS_ADD(num_ps_buf_frames);
10491057
DEBUGFS_ADD(last_seq_ctrl);
10501058
DEBUGFS_ADD(agg_status);
1051-
DEBUGFS_ADD(ht_capa);
1052-
DEBUGFS_ADD(vht_capa);
1053-
DEBUGFS_ADD(he_capa);
1054-
1055-
DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates);
1056-
DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
1059+
/* FIXME: Kept here as the statistics are only done on the deflink */
10571060
DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
10581061

10591062
if (local->ops->wake_tx_queue) {
@@ -1076,3 +1079,83 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
10761079
debugfs_remove_recursive(sta->debugfs_dir);
10771080
sta->debugfs_dir = NULL;
10781081
}
1082+
1083+
#undef DEBUGFS_ADD
1084+
#undef DEBUGFS_ADD_COUNTER
1085+
1086+
#define DEBUGFS_ADD(name) \
1087+
debugfs_create_file(#name, 0400, \
1088+
link_sta->debugfs_dir, link_sta, &link_sta_ ##name## _ops)
1089+
#define DEBUGFS_ADD_COUNTER(name, field) \
1090+
debugfs_create_ulong(#name, 0400, link_sta->debugfs_dir, &link_sta->field)
1091+
1092+
void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta)
1093+
{
1094+
if (WARN_ON(!link_sta->sta->debugfs_dir))
1095+
return;
1096+
1097+
/* For non-MLO, leave the files in the main directory. */
1098+
if (link_sta->sta->sta.valid_links) {
1099+
char link_dir_name[10];
1100+
1101+
snprintf(link_dir_name, sizeof(link_dir_name),
1102+
"link-%d", link_sta->link_id);
1103+
1104+
link_sta->debugfs_dir =
1105+
debugfs_create_dir(link_dir_name,
1106+
link_sta->sta->debugfs_dir);
1107+
} else {
1108+
if (WARN_ON(link_sta != &link_sta->sta->deflink))
1109+
return;
1110+
1111+
link_sta->debugfs_dir = link_sta->sta->debugfs_dir;
1112+
}
1113+
1114+
DEBUGFS_ADD(ht_capa);
1115+
DEBUGFS_ADD(vht_capa);
1116+
DEBUGFS_ADD(he_capa);
1117+
1118+
DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates);
1119+
DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
1120+
}
1121+
1122+
void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta)
1123+
{
1124+
if (!link_sta->debugfs_dir || !link_sta->sta->debugfs_dir) {
1125+
link_sta->debugfs_dir = NULL;
1126+
return;
1127+
}
1128+
1129+
if (link_sta->debugfs_dir == link_sta->sta->debugfs_dir) {
1130+
WARN_ON(link_sta != &link_sta->sta->deflink);
1131+
link_sta->sta->debugfs_dir = NULL;
1132+
return;
1133+
}
1134+
1135+
debugfs_remove_recursive(link_sta->debugfs_dir);
1136+
link_sta->debugfs_dir = NULL;
1137+
}
1138+
1139+
void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta)
1140+
{
1141+
if (WARN_ON(!link_sta->debugfs_dir))
1142+
return;
1143+
1144+
drv_link_sta_add_debugfs(link_sta->sta->local, link_sta->sta->sdata,
1145+
link_sta->pub, link_sta->debugfs_dir);
1146+
}
1147+
1148+
void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta)
1149+
{
1150+
if (!link_sta->debugfs_dir)
1151+
return;
1152+
1153+
if (WARN_ON(link_sta->debugfs_dir == link_sta->sta->debugfs_dir))
1154+
return;
1155+
1156+
/* Recreate the directory excluding the driver data */
1157+
debugfs_remove_recursive(link_sta->debugfs_dir);
1158+
link_sta->debugfs_dir = NULL;
1159+
1160+
ieee80211_link_sta_debugfs_add(link_sta);
1161+
}

net/mac80211/debugfs_sta.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,21 @@
77
#ifdef CONFIG_MAC80211_DEBUGFS
88
void ieee80211_sta_debugfs_add(struct sta_info *sta);
99
void ieee80211_sta_debugfs_remove(struct sta_info *sta);
10+
11+
void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta);
12+
void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta);
13+
14+
void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta);
15+
void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta);
1016
#else
1117
static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
1218
static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
19+
20+
static inline void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta) {}
21+
static inline void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta) {}
22+
23+
static inline void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta) {}
24+
static inline void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta) {}
1325
#endif
1426

1527
#endif /* __MAC80211_DEBUGFS_STA_H */

net/mac80211/driver-ops.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "ieee80211_i.h"
88
#include "trace.h"
99
#include "driver-ops.h"
10+
#include "debugfs_sta.h"
1011

1112
int drv_start(struct ieee80211_local *local)
1213
{
@@ -497,6 +498,11 @@ int drv_change_sta_links(struct ieee80211_local *local,
497498
struct ieee80211_sta *sta,
498499
u16 old_links, u16 new_links)
499500
{
501+
struct sta_info *info = container_of(sta, struct sta_info, sta);
502+
struct link_sta_info *link_sta;
503+
unsigned long links_to_add;
504+
unsigned long links_to_rem;
505+
unsigned int link_id;
500506
int ret = -EOPNOTSUPP;
501507

502508
might_sleep();
@@ -510,11 +516,30 @@ int drv_change_sta_links(struct ieee80211_local *local,
510516
if (old_links == new_links)
511517
return 0;
512518

519+
links_to_add = ~old_links & new_links;
520+
links_to_rem = old_links & ~new_links;
521+
522+
for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) {
523+
link_sta = rcu_dereference_protected(info->link[link_id],
524+
lockdep_is_held(&local->sta_mtx));
525+
526+
ieee80211_link_sta_debugfs_drv_remove(link_sta);
527+
}
528+
513529
trace_drv_change_sta_links(local, sdata, sta, old_links, new_links);
514530
if (local->ops->change_sta_links)
515531
ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta,
516532
old_links, new_links);
517533
trace_drv_return_int(local, ret);
518534

519-
return ret;
535+
if (ret)
536+
return ret;
537+
538+
for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) {
539+
link_sta = rcu_dereference_protected(info->link[link_id],
540+
lockdep_is_held(&local->sta_mtx));
541+
ieee80211_link_sta_debugfs_drv_add(link_sta);
542+
}
543+
544+
return 0;
520545
}

net/mac80211/driver-ops.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,22 @@ static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
480480
local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
481481
sta, dir);
482482
}
483+
484+
static inline void drv_link_sta_add_debugfs(struct ieee80211_local *local,
485+
struct ieee80211_sub_if_data *sdata,
486+
struct ieee80211_link_sta *link_sta,
487+
struct dentry *dir)
488+
{
489+
might_sleep();
490+
491+
sdata = get_bss_sdata(sdata);
492+
if (!check_sdata_in_driver(sdata))
493+
return;
494+
495+
if (local->ops->link_sta_add_debugfs)
496+
local->ops->link_sta_add_debugfs(&local->hw, &sdata->vif,
497+
link_sta, dir);
498+
}
483499
#endif
484500

485501
static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,

net/mac80211/sta_info.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id,
366366
if (unhash)
367367
link_sta_info_hash_del(sta->local, link_sta);
368368

369+
if (test_sta_flag(sta, WLAN_STA_INSERTED))
370+
ieee80211_link_sta_debugfs_remove(link_sta);
371+
369372
if (link_sta != &sta->deflink)
370373
alloc = container_of(link_sta, typeof(*alloc), info);
371374

@@ -875,6 +878,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
875878

876879
ieee80211_sta_debugfs_add(sta);
877880
rate_control_add_sta_debugfs(sta);
881+
if (sta->sta.valid_links) {
882+
int i;
883+
884+
for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
885+
struct link_sta_info *link_sta;
886+
887+
link_sta = rcu_dereference_protected(sta->link[i],
888+
lockdep_is_held(&local->sta_mtx));
889+
890+
if (!link_sta)
891+
continue;
892+
893+
ieee80211_link_sta_debugfs_add(link_sta);
894+
if (sdata->vif.active_links & BIT(i))
895+
ieee80211_link_sta_debugfs_drv_add(link_sta);
896+
}
897+
} else {
898+
ieee80211_link_sta_debugfs_add(&sta->deflink);
899+
ieee80211_link_sta_debugfs_drv_add(&sta->deflink);
900+
}
878901

879902
sinfo->generation = local->sta_generation;
880903
cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
@@ -2824,6 +2847,8 @@ int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)
28242847

28252848
sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta);
28262849

2850+
ieee80211_link_sta_debugfs_add(&alloc->info);
2851+
28272852
return 0;
28282853
}
28292854

net/mac80211/sta_info.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ struct ieee80211_fragment_cache {
513513
* @status_stats.avg_ack_signal: average ACK signal
514514
* @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
515515
* taken from HT/VHT capabilities or VHT operating mode notification
516+
* @debugfs_dir: debug filesystem directory dentry
516517
* @pub: public (driver visible) link STA data
517518
* TODO Move other link params from sta_info as required for MLD operation
518519
*/
@@ -560,6 +561,10 @@ struct link_sta_info {
560561

561562
enum ieee80211_sta_rx_bandwidth cur_max_bandwidth;
562563

564+
#ifdef CONFIG_MAC80211_DEBUGFS
565+
struct dentry *debugfs_dir;
566+
#endif
567+
563568
struct ieee80211_link_sta *pub;
564569
};
565570

0 commit comments

Comments
 (0)