Skip to content

Commit 92c4e91

Browse files
Venkateswara NaralasettyRealzhq
authored andcommitted
FROMGIT: wifi: ath11k: Register debugfs for CFR configuration
Provide debugfs interfaces support to config CFR from the user space. To enable/disable cfr feature use command, echo <val> > /sys/kernel/debug/ieee80211/phyX/ath11k/enable_cfr where, val: 0 to disable CFR and 1 to enable CFR. To enable CFR capture for associated peers, echo "<val> <bw> <periodicity> <method>" > /sys/kernel/debug/ieee80211/phyX/netdev\:wlanx/stations/<mac>/cfr_capture val: 0 - stop CFR capture 1 - start CFR capture bw: CFR capture bandwidth 0 - 20MHZ 1 - 40MHZ 2 - 80MHZ Periodicity: Periodicity at which hardware is expected to collect CFR dump. 0 - single shot capture. non zero - for Periodic captures (value must be multiple of 10 ms) method: Method used by hardware to collect the CFR dump. 0 - from the ACKs of QOS NULL packets. Also, send the required WMI commands to the firmware based on the CFR configurations. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICONZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 Signed-off-by: Venkateswara Naralasetty <quic_vnaralas@quicinc.com> Co-developed-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com> Signed-off-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Signed-off-by: Qian Zhang <qian.zhang@oss.qualcomm.com> Link: https://patch.msgid.link/20251230082520.3401007-3-qian.zhang@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
1 parent 6a3faa7 commit 92c4e91

7 files changed

Lines changed: 475 additions & 3 deletions

File tree

drivers/net/wireless/ath/ath11k/cfr.c

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,193 @@ static int ath11k_cfr_process_data(struct ath11k *ar,
1414
return 0;
1515
}
1616

17+
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
18+
struct ath11k_sta *arsta)
19+
{
20+
struct ath11k_cfr *cfr = &ar->cfr;
21+
22+
spin_lock_bh(&cfr->lock);
23+
24+
if (arsta->cfr_capture.cfr_enable)
25+
cfr->cfr_enabled_peer_cnt--;
26+
27+
spin_unlock_bh(&cfr->lock);
28+
}
29+
30+
static enum ath11k_wmi_cfr_capture_bw
31+
ath11k_cfr_bw_to_fw_cfr_bw(enum ath11k_cfr_capture_bw bw)
32+
{
33+
switch (bw) {
34+
case ATH11K_CFR_CAPTURE_BW_20:
35+
return WMI_PEER_CFR_CAPTURE_BW_20;
36+
case ATH11K_CFR_CAPTURE_BW_40:
37+
return WMI_PEER_CFR_CAPTURE_BW_40;
38+
case ATH11K_CFR_CAPTURE_BW_80:
39+
return WMI_PEER_CFR_CAPTURE_BW_80;
40+
default:
41+
return WMI_PEER_CFR_CAPTURE_BW_MAX;
42+
}
43+
}
44+
45+
static enum ath11k_wmi_cfr_capture_method
46+
ath11k_cfr_method_to_fw_cfr_method(enum ath11k_cfr_capture_method method)
47+
{
48+
switch (method) {
49+
case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME:
50+
return WMI_CFR_CAPTURE_METHOD_NULL_FRAME;
51+
case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE:
52+
return WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE;
53+
case ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP:
54+
return WMI_CFR_CAPTURE_METHOD_PROBE_RESP;
55+
default:
56+
return WMI_CFR_CAPTURE_METHOD_MAX;
57+
}
58+
}
59+
60+
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
61+
struct ath11k_sta *arsta,
62+
struct ath11k_per_peer_cfr_capture *params,
63+
const u8 *peer_mac)
64+
{
65+
struct ath11k_cfr *cfr = &ar->cfr;
66+
struct wmi_peer_cfr_capture_conf_arg arg;
67+
enum ath11k_wmi_cfr_capture_bw bw;
68+
enum ath11k_wmi_cfr_capture_method method;
69+
int ret = 0;
70+
71+
if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS &&
72+
!arsta->cfr_capture.cfr_enable) {
73+
ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n",
74+
cfr->cfr_enabled_peer_cnt);
75+
return -ENOSPC;
76+
}
77+
78+
if (params->cfr_enable == arsta->cfr_capture.cfr_enable &&
79+
params->cfr_period == arsta->cfr_capture.cfr_period &&
80+
params->cfr_method == arsta->cfr_capture.cfr_method &&
81+
params->cfr_bw == arsta->cfr_capture.cfr_bw)
82+
return ret;
83+
84+
if (!params->cfr_enable && !arsta->cfr_capture.cfr_enable)
85+
return ret;
86+
87+
bw = ath11k_cfr_bw_to_fw_cfr_bw(params->cfr_bw);
88+
if (bw >= WMI_PEER_CFR_CAPTURE_BW_MAX) {
89+
ath11k_warn(ar->ab, "FW doesn't support configured bw %d\n",
90+
params->cfr_bw);
91+
return -EINVAL;
92+
}
93+
94+
method = ath11k_cfr_method_to_fw_cfr_method(params->cfr_method);
95+
if (method >= WMI_CFR_CAPTURE_METHOD_MAX) {
96+
ath11k_warn(ar->ab, "FW doesn't support configured method %d\n",
97+
params->cfr_method);
98+
return -EINVAL;
99+
}
100+
101+
arg.request = params->cfr_enable;
102+
arg.periodicity = params->cfr_period;
103+
arg.bw = bw;
104+
arg.method = method;
105+
106+
ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id,
107+
peer_mac, &arg);
108+
if (ret) {
109+
ath11k_warn(ar->ab,
110+
"failed to send cfr capture info: vdev_id %u peer %pM: %d\n",
111+
arsta->arvif->vdev_id, peer_mac, ret);
112+
return ret;
113+
}
114+
115+
spin_lock_bh(&cfr->lock);
116+
117+
if (params->cfr_enable &&
118+
params->cfr_enable != arsta->cfr_capture.cfr_enable)
119+
cfr->cfr_enabled_peer_cnt++;
120+
else if (!params->cfr_enable)
121+
cfr->cfr_enabled_peer_cnt--;
122+
123+
spin_unlock_bh(&cfr->lock);
124+
125+
arsta->cfr_capture.cfr_enable = params->cfr_enable;
126+
arsta->cfr_capture.cfr_period = params->cfr_period;
127+
arsta->cfr_capture.cfr_method = params->cfr_method;
128+
arsta->cfr_capture.cfr_bw = params->cfr_bw;
129+
130+
return ret;
131+
}
132+
133+
static ssize_t ath11k_read_file_enable_cfr(struct file *file,
134+
char __user *user_buf,
135+
size_t count, loff_t *ppos)
136+
{
137+
struct ath11k *ar = file->private_data;
138+
char buf[32] = {};
139+
size_t len;
140+
141+
mutex_lock(&ar->conf_mutex);
142+
len = scnprintf(buf, sizeof(buf), "%d\n", ar->cfr_enabled);
143+
mutex_unlock(&ar->conf_mutex);
144+
145+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
146+
}
147+
148+
static ssize_t ath11k_write_file_enable_cfr(struct file *file,
149+
const char __user *ubuf,
150+
size_t count, loff_t *ppos)
151+
{
152+
struct ath11k *ar = file->private_data;
153+
u32 enable_cfr;
154+
int ret;
155+
156+
if (kstrtouint_from_user(ubuf, count, 0, &enable_cfr))
157+
return -EINVAL;
158+
159+
guard(mutex)(&ar->conf_mutex);
160+
161+
if (ar->state != ATH11K_STATE_ON)
162+
return -ENETDOWN;
163+
164+
if (enable_cfr > 1)
165+
return -EINVAL;
166+
167+
if (ar->cfr_enabled == enable_cfr)
168+
return count;
169+
170+
ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE,
171+
enable_cfr, ar->pdev->pdev_id);
172+
if (ret) {
173+
ath11k_warn(ar->ab,
174+
"Failed to enable/disable per peer cfr %d\n", ret);
175+
return ret;
176+
}
177+
178+
ar->cfr_enabled = enable_cfr;
179+
180+
return count;
181+
}
182+
183+
static const struct file_operations fops_enable_cfr = {
184+
.read = ath11k_read_file_enable_cfr,
185+
.write = ath11k_write_file_enable_cfr,
186+
.open = simple_open,
187+
.owner = THIS_MODULE,
188+
.llseek = default_llseek,
189+
};
190+
191+
static void ath11k_cfr_debug_unregister(struct ath11k *ar)
192+
{
193+
debugfs_remove(ar->cfr.enable_cfr);
194+
ar->cfr.enable_cfr = NULL;
195+
}
196+
197+
static void ath11k_cfr_debug_register(struct ath11k *ar)
198+
{
199+
ar->cfr.enable_cfr = debugfs_create_file("enable_cfr", 0600,
200+
ar->debug.debugfs_pdev, ar,
201+
&fops_enable_cfr);
202+
}
203+
17204
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
18205
u32 buf_id)
19206
{
@@ -88,6 +275,7 @@ void ath11k_cfr_deinit(struct ath11k_base *ab)
88275
if (!cfr->enabled)
89276
continue;
90277

278+
ath11k_cfr_debug_unregister(ar);
91279
ath11k_cfr_ring_free(ar);
92280

93281
spin_lock_bh(&cfr->lut_lock);
@@ -146,6 +334,8 @@ int ath11k_cfr_init(struct ath11k_base *ab)
146334

147335
cfr->lut_num = num_lut_entries;
148336
cfr->enabled = true;
337+
338+
ath11k_cfr_debug_register(ar);
149339
}
150340

151341
return 0;
@@ -158,6 +348,7 @@ int ath11k_cfr_init(struct ath11k_base *ab)
158348
if (!cfr->enabled)
159349
continue;
160350

351+
ath11k_cfr_debug_unregister(ar);
161352
ath11k_cfr_ring_free(ar);
162353

163354
spin_lock_bh(&cfr->lut_lock);

drivers/net/wireless/ath/ath11k/cfr.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
#define ATH11K_CFR_EVENT_TIMEOUT_MS 1
1515
#define ATH11K_CFR_NUM_RING_ENTRIES 1
1616

17+
#define ATH11K_MAX_CFR_ENABLED_CLIENTS 10
1718
#define CFR_MAX_LUT_ENTRIES 136
1819

1920
#define HOST_MAX_CHAINS 8
2021

22+
struct ath11k_sta;
23+
struct ath11k_per_peer_cfr_capture;
24+
2125
struct ath11k_cfr_dma_hdr {
2226
u16 info0;
2327
u16 info1;
@@ -48,6 +52,8 @@ struct ath11k_cfr {
4852
/* Protect for lut entries */
4953
spinlock_t lut_lock;
5054
struct ath11k_look_up_table *lut;
55+
struct dentry *enable_cfr;
56+
u8 cfr_enabled_peer_cnt;
5157
u32 lut_num;
5258
u64 tx_evt_cnt;
5359
u64 dbr_evt_cnt;
@@ -62,11 +68,32 @@ struct ath11k_cfr {
6268
bool enabled;
6369
};
6470

71+
enum ath11k_cfr_capture_method {
72+
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME,
73+
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
74+
ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP,
75+
ATH11K_CFR_CAPTURE_METHOD_MAX,
76+
};
77+
78+
enum ath11k_cfr_capture_bw {
79+
ATH11K_CFR_CAPTURE_BW_20,
80+
ATH11K_CFR_CAPTURE_BW_40,
81+
ATH11K_CFR_CAPTURE_BW_80,
82+
ATH11K_CFR_CAPTURE_BW_MAX,
83+
};
84+
6585
#ifdef CONFIG_ATH11K_CFR
6686
int ath11k_cfr_init(struct ath11k_base *ab);
6787
void ath11k_cfr_deinit(struct ath11k_base *ab);
6888
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
6989
u32 buf_id);
90+
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
91+
struct ath11k_sta *arsta);
92+
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
93+
struct ath11k_sta *arsta,
94+
struct ath11k_per_peer_cfr_capture *params,
95+
const u8 *peer_mac);
96+
7097
#else
7198
static inline int ath11k_cfr_init(struct ath11k_base *ab)
7299
{
@@ -81,5 +108,19 @@ static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar,
81108
dma_addr_t paddr, u32 buf_id)
82109
{
83110
}
111+
112+
static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
113+
struct ath11k_sta *arsta)
114+
{
115+
}
116+
117+
static inline int
118+
ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
119+
struct ath11k_sta *arsta,
120+
struct ath11k_per_peer_cfr_capture *params,
121+
const u8 *peer_mac)
122+
{
123+
return 0;
124+
}
84125
#endif /* CONFIG_ATH11K_CFR */
85126
#endif /* ATH11K_CFR_H */

drivers/net/wireless/ath/ath11k/core.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,13 @@ struct ath11k_per_ppdu_tx_stats {
532532

533533
DECLARE_EWMA(avg_rssi, 10, 8)
534534

535+
struct ath11k_per_peer_cfr_capture {
536+
enum ath11k_cfr_capture_method cfr_method;
537+
enum ath11k_cfr_capture_bw cfr_bw;
538+
u32 cfr_enable;
539+
u32 cfr_period;
540+
};
541+
535542
struct ath11k_sta {
536543
struct ath11k_vif *arvif;
537544

@@ -572,6 +579,10 @@ struct ath11k_sta {
572579
bool peer_current_ps_valid;
573580

574581
u32 bw_prev;
582+
583+
#ifdef CONFIG_ATH11K_CFR
584+
struct ath11k_per_peer_cfr_capture cfr_capture;
585+
#endif
575586
};
576587

577588
#define ATH11K_MIN_5G_FREQ 4150

0 commit comments

Comments
 (0)