Skip to content

Commit 83f04b0

Browse files
Venkateswara NaralasettyRealzhq
authored andcommitted
FROMGIT: wifi: ath11k: Add support unassociated client CFR
Provide debugfs interfaces support to config unassociated client CFR from the user space. To enable CFR capture for unassociated clients, echo "<mac address> <val> <periodicity>" > /sys/kernel/debug/ieee80211/phyX/ath11k/cfr_unassoc Mac address: mac address of the client. Val: 0 - start CFR capture 1 - stop CFR capture 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) 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 92c4e91 commit 83f04b0

5 files changed

Lines changed: 290 additions & 4 deletions

File tree

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

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

17+
/* Helper function to check whether the given peer mac address
18+
* is in unassociated peer pool or not.
19+
*/
20+
bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac)
21+
{
22+
struct ath11k_cfr *cfr = &ar->cfr;
23+
struct cfr_unassoc_pool_entry *entry;
24+
int i;
25+
26+
if (!ar->cfr_enabled)
27+
return false;
28+
29+
spin_lock_bh(&cfr->lock);
30+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
31+
entry = &cfr->unassoc_pool[i];
32+
if (!entry->is_valid)
33+
continue;
34+
35+
if (ether_addr_equal(peer_mac, entry->peer_mac)) {
36+
spin_unlock_bh(&cfr->lock);
37+
return true;
38+
}
39+
}
40+
41+
spin_unlock_bh(&cfr->lock);
42+
43+
return false;
44+
}
45+
46+
void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
47+
const u8 *peer_mac)
48+
{
49+
struct ath11k_cfr *cfr = &ar->cfr;
50+
struct cfr_unassoc_pool_entry *entry;
51+
int i;
52+
53+
spin_lock_bh(&cfr->lock);
54+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
55+
entry = &cfr->unassoc_pool[i];
56+
if (!entry->is_valid)
57+
continue;
58+
59+
if (ether_addr_equal(peer_mac, entry->peer_mac) &&
60+
entry->period == 0) {
61+
memset(entry->peer_mac, 0, ETH_ALEN);
62+
entry->is_valid = false;
63+
cfr->cfr_enabled_peer_cnt--;
64+
break;
65+
}
66+
}
67+
68+
spin_unlock_bh(&cfr->lock);
69+
}
70+
1771
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
1872
struct ath11k_sta *arsta)
1973
{
@@ -130,6 +184,59 @@ int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
130184
return ret;
131185
}
132186

187+
void ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
188+
struct ath11k_per_peer_cfr_capture *params,
189+
u8 *peer_mac)
190+
{
191+
struct ath11k_cfr *cfr = &ar->cfr;
192+
struct cfr_unassoc_pool_entry *entry;
193+
int available_idx = -1;
194+
int i;
195+
196+
guard(spinlock_bh)(&cfr->lock);
197+
198+
if (!params->cfr_enable) {
199+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
200+
entry = &cfr->unassoc_pool[i];
201+
if (ether_addr_equal(peer_mac, entry->peer_mac)) {
202+
memset(entry->peer_mac, 0, ETH_ALEN);
203+
entry->is_valid = false;
204+
cfr->cfr_enabled_peer_cnt--;
205+
break;
206+
}
207+
}
208+
return;
209+
}
210+
211+
if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) {
212+
ath11k_info(ar->ab, "Max cfr peer threshold reached\n");
213+
return;
214+
}
215+
216+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
217+
entry = &cfr->unassoc_pool[i];
218+
219+
if (ether_addr_equal(peer_mac, entry->peer_mac)) {
220+
ath11k_info(ar->ab,
221+
"peer entry already present updating params\n");
222+
entry->period = params->cfr_period;
223+
available_idx = -1;
224+
break;
225+
}
226+
227+
if (available_idx < 0 && !entry->is_valid)
228+
available_idx = i;
229+
}
230+
231+
if (available_idx >= 0) {
232+
entry = &cfr->unassoc_pool[available_idx];
233+
ether_addr_copy(entry->peer_mac, peer_mac);
234+
entry->period = params->cfr_period;
235+
entry->is_valid = true;
236+
cfr->cfr_enabled_peer_cnt++;
237+
}
238+
}
239+
133240
static ssize_t ath11k_read_file_enable_cfr(struct file *file,
134241
char __user *user_buf,
135242
size_t count, loff_t *ppos)
@@ -188,17 +295,138 @@ static const struct file_operations fops_enable_cfr = {
188295
.llseek = default_llseek,
189296
};
190297

298+
static ssize_t ath11k_write_file_cfr_unassoc(struct file *file,
299+
const char __user *ubuf,
300+
size_t count, loff_t *ppos)
301+
{
302+
struct ath11k *ar = file->private_data;
303+
struct ath11k_cfr *cfr = &ar->cfr;
304+
struct cfr_unassoc_pool_entry *entry;
305+
char buf[64] = {};
306+
u8 peer_mac[6];
307+
u32 cfr_capture_enable;
308+
u32 cfr_capture_period;
309+
int available_idx = -1;
310+
int ret, i;
311+
312+
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
313+
314+
guard(mutex)(&ar->conf_mutex);
315+
guard(spinlock_bh)(&cfr->lock);
316+
317+
if (ar->state != ATH11K_STATE_ON)
318+
return -ENETDOWN;
319+
320+
if (!ar->cfr_enabled) {
321+
ath11k_err(ar->ab, "CFR is not enabled on this pdev %d\n",
322+
ar->pdev_idx);
323+
return -EINVAL;
324+
}
325+
326+
ret = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %u %u",
327+
&peer_mac[0], &peer_mac[1], &peer_mac[2], &peer_mac[3],
328+
&peer_mac[4], &peer_mac[5], &cfr_capture_enable,
329+
&cfr_capture_period);
330+
331+
if (ret < 1)
332+
return -EINVAL;
333+
334+
if (cfr_capture_enable && ret != 8)
335+
return -EINVAL;
336+
337+
if (!cfr_capture_enable) {
338+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
339+
entry = &cfr->unassoc_pool[i];
340+
if (ether_addr_equal(peer_mac, entry->peer_mac)) {
341+
memset(entry->peer_mac, 0, ETH_ALEN);
342+
entry->is_valid = false;
343+
cfr->cfr_enabled_peer_cnt--;
344+
}
345+
}
346+
347+
return count;
348+
}
349+
350+
if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) {
351+
ath11k_info(ar->ab, "Max cfr peer threshold reached\n");
352+
return count;
353+
}
354+
355+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
356+
entry = &cfr->unassoc_pool[i];
357+
358+
if (available_idx < 0 && !entry->is_valid)
359+
available_idx = i;
360+
361+
if (ether_addr_equal(peer_mac, entry->peer_mac)) {
362+
ath11k_info(ar->ab,
363+
"peer entry already present updating params\n");
364+
entry->period = cfr_capture_period;
365+
return count;
366+
}
367+
}
368+
369+
if (available_idx >= 0) {
370+
entry = &cfr->unassoc_pool[available_idx];
371+
ether_addr_copy(entry->peer_mac, peer_mac);
372+
entry->period = cfr_capture_period;
373+
entry->is_valid = true;
374+
cfr->cfr_enabled_peer_cnt++;
375+
}
376+
377+
return count;
378+
}
379+
380+
static ssize_t ath11k_read_file_cfr_unassoc(struct file *file,
381+
char __user *ubuf,
382+
size_t count, loff_t *ppos)
383+
{
384+
struct ath11k *ar = file->private_data;
385+
struct ath11k_cfr *cfr = &ar->cfr;
386+
struct cfr_unassoc_pool_entry *entry;
387+
char buf[512] = {};
388+
int len = 0, i;
389+
390+
spin_lock_bh(&cfr->lock);
391+
392+
for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) {
393+
entry = &cfr->unassoc_pool[i];
394+
if (entry->is_valid)
395+
len += scnprintf(buf + len, sizeof(buf) - len,
396+
"peer: %pM period: %u\n",
397+
entry->peer_mac, entry->period);
398+
}
399+
400+
spin_unlock_bh(&cfr->lock);
401+
402+
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
403+
}
404+
405+
static const struct file_operations fops_configure_cfr_unassoc = {
406+
.write = ath11k_write_file_cfr_unassoc,
407+
.read = ath11k_read_file_cfr_unassoc,
408+
.open = simple_open,
409+
.owner = THIS_MODULE,
410+
.llseek = default_llseek,
411+
};
412+
191413
static void ath11k_cfr_debug_unregister(struct ath11k *ar)
192414
{
193415
debugfs_remove(ar->cfr.enable_cfr);
194416
ar->cfr.enable_cfr = NULL;
417+
debugfs_remove(ar->cfr.cfr_unassoc);
418+
ar->cfr.cfr_unassoc = NULL;
195419
}
196420

197421
static void ath11k_cfr_debug_register(struct ath11k *ar)
198422
{
199423
ar->cfr.enable_cfr = debugfs_create_file("enable_cfr", 0600,
200424
ar->debug.debugfs_pdev, ar,
201425
&fops_enable_cfr);
426+
427+
ar->cfr.cfr_unassoc = debugfs_create_file("cfr_unassoc", 0600,
428+
ar->debug.debugfs_pdev, ar,
429+
&fops_configure_cfr_unassoc);
202430
}
203431

204432
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ struct ath11k_look_up_table {
4545
struct ath11k_dbring_element *buff;
4646
};
4747

48+
struct cfr_unassoc_pool_entry {
49+
u8 peer_mac[ETH_ALEN];
50+
u32 period;
51+
bool is_valid;
52+
};
53+
4854
struct ath11k_cfr {
4955
struct ath11k_dbring rx_ring;
5056
/* Protects cfr data */
@@ -53,6 +59,7 @@ struct ath11k_cfr {
5359
spinlock_t lut_lock;
5460
struct ath11k_look_up_table *lut;
5561
struct dentry *enable_cfr;
62+
struct dentry *cfr_unassoc;
5663
u8 cfr_enabled_peer_cnt;
5764
u32 lut_num;
5865
u64 tx_evt_cnt;
@@ -66,6 +73,7 @@ struct ath11k_cfr {
6673
u64 clear_txrx_event;
6774
u64 cfr_dma_aborts;
6875
bool enabled;
76+
struct cfr_unassoc_pool_entry unassoc_pool[ATH11K_MAX_CFR_ENABLED_CLIENTS];
6977
};
7078

7179
enum ath11k_cfr_capture_method {
@@ -89,6 +97,13 @@ void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
8997
u32 buf_id);
9098
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
9199
struct ath11k_sta *arsta);
100+
void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
101+
const u8 *peer_mac);
102+
bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar,
103+
const u8 *peer_mac);
104+
void ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
105+
struct ath11k_per_peer_cfr_capture *params,
106+
u8 *peer_mac);
92107
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
93108
struct ath11k_sta *arsta,
94109
struct ath11k_per_peer_cfr_capture *params,
@@ -114,6 +129,24 @@ static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
114129
{
115130
}
116131

132+
static inline void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
133+
const u8 *peer_mac)
134+
{
135+
}
136+
137+
static inline bool
138+
ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac)
139+
{
140+
return false;
141+
}
142+
143+
static inline void
144+
ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
145+
struct ath11k_per_peer_cfr_capture *params,
146+
u8 *peer_mac)
147+
{
148+
}
149+
117150
static inline int
118151
ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
119152
struct ath11k_sta *arsta,

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6042,6 +6042,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
60426042
dma_addr_t paddr;
60436043
int buf_id;
60446044
int ret;
6045+
bool tx_params_valid = false;
6046+
bool peer_in_unassoc_pool;
60456047

60466048
ATH11K_SKB_CB(skb)->ar = ar;
60476049

@@ -6080,7 +6082,18 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
60806082

60816083
ATH11K_SKB_CB(skb)->paddr = paddr;
60826084

6083-
ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
6085+
peer_in_unassoc_pool = ath11k_cfr_peer_is_in_cfr_unassoc_pool(ar, hdr->addr1);
6086+
6087+
if (ar->cfr_enabled &&
6088+
ieee80211_is_probe_resp(hdr->frame_control) &&
6089+
peer_in_unassoc_pool)
6090+
tx_params_valid = true;
6091+
6092+
if (peer_in_unassoc_pool)
6093+
ath11k_cfr_update_unassoc_pool_entry(ar, hdr->addr1);
6094+
6095+
ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb,
6096+
tx_params_valid);
60846097
if (ret) {
60856098
ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
60866099
goto err_unmap_buf;

0 commit comments

Comments
 (0)