Skip to content

Commit 6a3faa7

Browse files
Venkateswara NaralasettyRealzhq
authored andcommitted
FROMGIT: wifi: ath11k: Add initialization and deinitialization sequence for CFR module
Channel Frequency Response (CFR) module will be initialized only when the following criteria passes: * Enabled CFR support for the hardware through the hardware param 'cfr_support' * WMI service enabled for the CFR support 'WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT' Also, provide a configuration option CONFIG_ATH11K_CFR to enable CFR feature support during the compilation time. CFR module initialization includes Direct Buffer(DB) ring initialization where hardware uses the DB ring buffers to copy CFR data to host. Number of buffers and buffer size of the ring is based on the DB ring capabilities advertised by the firmware through WMI service ready. Also ring configurations are sent to firmware through ath11k_dbring_wmi_cfg_setup(). Predefine ath11k_cfr_dma_hdr, ath11k_look_up_table, and ath11k_cfr structs and fields for subsequent patches. 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-2-qian.zhang@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
1 parent c60e1a1 commit 6a3faa7

11 files changed

Lines changed: 353 additions & 15 deletions

File tree

drivers/net/wireless/ath/ath11k/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,14 @@ config ATH11K_SPECTRAL
5858
Enable ath11k spectral scan support
5959

6060
Say Y to enable access to the FFT/spectral data via debugfs.
61+
62+
config ATH11K_CFR
63+
bool "ath11k channel frequency response support"
64+
depends on ATH11K_DEBUGFS
65+
depends on RELAY
66+
help
67+
Enable ath11k channel frequency response dump support.
68+
This option exposes debugfs nodes that will allow the user
69+
to enable, disable, and dump data.
70+
71+
Say Y to enable CFR data dump collection via debugfs.

drivers/net/wireless/ath/ath11k/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ ath11k-$(CONFIG_THERMAL) += thermal.o
2828
ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
2929
ath11k-$(CONFIG_PM) += wow.o
3030
ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
31+
ath11k-$(CONFIG_ATH11K_CFR) += cfr.o
3132

3233
obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
3334
ath11k_ahb-y += ahb.o
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// SPDX-License-Identifier: BSD-3-Clause-Clear
2+
/*
3+
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
4+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5+
*/
6+
7+
#include <linux/relay.h>
8+
#include "core.h"
9+
#include "debug.h"
10+
11+
static int ath11k_cfr_process_data(struct ath11k *ar,
12+
struct ath11k_dbring_data *param)
13+
{
14+
return 0;
15+
}
16+
17+
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
18+
u32 buf_id)
19+
{
20+
struct ath11k_cfr *cfr = &ar->cfr;
21+
22+
if (cfr->lut)
23+
cfr->lut[buf_id].dbr_address = paddr;
24+
}
25+
26+
static void ath11k_cfr_ring_free(struct ath11k *ar)
27+
{
28+
struct ath11k_cfr *cfr = &ar->cfr;
29+
30+
ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring);
31+
ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring);
32+
}
33+
34+
static int ath11k_cfr_ring_alloc(struct ath11k *ar,
35+
struct ath11k_dbring_cap *db_cap)
36+
{
37+
struct ath11k_cfr *cfr = &ar->cfr;
38+
int ret;
39+
40+
ret = ath11k_dbring_srng_setup(ar, &cfr->rx_ring,
41+
ATH11K_CFR_NUM_RING_ENTRIES,
42+
db_cap->min_elem);
43+
if (ret) {
44+
ath11k_warn(ar->ab, "failed to setup db ring: %d\n", ret);
45+
return ret;
46+
}
47+
48+
ath11k_dbring_set_cfg(ar, &cfr->rx_ring,
49+
ATH11K_CFR_NUM_RESP_PER_EVENT,
50+
ATH11K_CFR_EVENT_TIMEOUT_MS,
51+
ath11k_cfr_process_data);
52+
53+
ret = ath11k_dbring_buf_setup(ar, &cfr->rx_ring, db_cap);
54+
if (ret) {
55+
ath11k_warn(ar->ab, "failed to setup db ring buffer: %d\n", ret);
56+
goto srng_cleanup;
57+
}
58+
59+
ret = ath11k_dbring_wmi_cfg_setup(ar, &cfr->rx_ring, WMI_DIRECT_BUF_CFR);
60+
if (ret) {
61+
ath11k_warn(ar->ab, "failed to setup db ring cfg: %d\n", ret);
62+
goto buffer_cleanup;
63+
}
64+
65+
return 0;
66+
67+
buffer_cleanup:
68+
ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring);
69+
srng_cleanup:
70+
ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring);
71+
return ret;
72+
}
73+
74+
void ath11k_cfr_deinit(struct ath11k_base *ab)
75+
{
76+
struct ath11k_cfr *cfr;
77+
struct ath11k *ar;
78+
int i;
79+
80+
if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) ||
81+
!ab->hw_params.cfr_support)
82+
return;
83+
84+
for (i = 0; i < ab->num_radios; i++) {
85+
ar = ab->pdevs[i].ar;
86+
cfr = &ar->cfr;
87+
88+
if (!cfr->enabled)
89+
continue;
90+
91+
ath11k_cfr_ring_free(ar);
92+
93+
spin_lock_bh(&cfr->lut_lock);
94+
kfree(cfr->lut);
95+
cfr->lut = NULL;
96+
cfr->enabled = false;
97+
spin_unlock_bh(&cfr->lut_lock);
98+
}
99+
}
100+
101+
int ath11k_cfr_init(struct ath11k_base *ab)
102+
{
103+
struct ath11k_dbring_cap db_cap;
104+
struct ath11k_cfr *cfr;
105+
u32 num_lut_entries;
106+
struct ath11k *ar;
107+
int i, ret;
108+
109+
if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) ||
110+
!ab->hw_params.cfr_support)
111+
return 0;
112+
113+
for (i = 0; i < ab->num_radios; i++) {
114+
ar = ab->pdevs[i].ar;
115+
cfr = &ar->cfr;
116+
117+
ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
118+
WMI_DIRECT_BUF_CFR, &db_cap);
119+
if (ret)
120+
continue;
121+
122+
idr_init(&cfr->rx_ring.bufs_idr);
123+
spin_lock_init(&cfr->rx_ring.idr_lock);
124+
spin_lock_init(&cfr->lock);
125+
spin_lock_init(&cfr->lut_lock);
126+
127+
num_lut_entries = min_t(u32, CFR_MAX_LUT_ENTRIES, db_cap.min_elem);
128+
cfr->lut = kcalloc(num_lut_entries, sizeof(*cfr->lut),
129+
GFP_KERNEL);
130+
if (!cfr->lut) {
131+
ret = -ENOMEM;
132+
goto err;
133+
}
134+
135+
ret = ath11k_cfr_ring_alloc(ar, &db_cap);
136+
if (ret) {
137+
ath11k_warn(ab, "failed to init cfr ring for pdev %d: %d\n",
138+
i, ret);
139+
spin_lock_bh(&cfr->lut_lock);
140+
kfree(cfr->lut);
141+
cfr->lut = NULL;
142+
cfr->enabled = false;
143+
spin_unlock_bh(&cfr->lut_lock);
144+
goto err;
145+
}
146+
147+
cfr->lut_num = num_lut_entries;
148+
cfr->enabled = true;
149+
}
150+
151+
return 0;
152+
153+
err:
154+
for (i = i - 1; i >= 0; i--) {
155+
ar = ab->pdevs[i].ar;
156+
cfr = &ar->cfr;
157+
158+
if (!cfr->enabled)
159+
continue;
160+
161+
ath11k_cfr_ring_free(ar);
162+
163+
spin_lock_bh(&cfr->lut_lock);
164+
kfree(cfr->lut);
165+
cfr->lut = NULL;
166+
cfr->enabled = false;
167+
spin_unlock_bh(&cfr->lut_lock);
168+
}
169+
return ret;
170+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
2+
/*
3+
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
4+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5+
*/
6+
7+
#ifndef ATH11K_CFR_H
8+
#define ATH11K_CFR_H
9+
10+
#include "dbring.h"
11+
#include "wmi.h"
12+
13+
#define ATH11K_CFR_NUM_RESP_PER_EVENT 1
14+
#define ATH11K_CFR_EVENT_TIMEOUT_MS 1
15+
#define ATH11K_CFR_NUM_RING_ENTRIES 1
16+
17+
#define CFR_MAX_LUT_ENTRIES 136
18+
19+
#define HOST_MAX_CHAINS 8
20+
21+
struct ath11k_cfr_dma_hdr {
22+
u16 info0;
23+
u16 info1;
24+
u16 sw_peer_id;
25+
u16 phy_ppdu_id;
26+
};
27+
28+
struct ath11k_look_up_table {
29+
bool dbr_recv;
30+
bool tx_recv;
31+
u8 *data;
32+
u32 data_len;
33+
u16 dbr_ppdu_id;
34+
u16 tx_ppdu_id;
35+
dma_addr_t dbr_address;
36+
struct ath11k_cfr_dma_hdr hdr;
37+
u64 txrx_tstamp;
38+
u64 dbr_tstamp;
39+
u32 header_length;
40+
u32 payload_length;
41+
struct ath11k_dbring_element *buff;
42+
};
43+
44+
struct ath11k_cfr {
45+
struct ath11k_dbring rx_ring;
46+
/* Protects cfr data */
47+
spinlock_t lock;
48+
/* Protect for lut entries */
49+
spinlock_t lut_lock;
50+
struct ath11k_look_up_table *lut;
51+
u32 lut_num;
52+
u64 tx_evt_cnt;
53+
u64 dbr_evt_cnt;
54+
u64 release_cnt;
55+
u64 tx_peer_status_cfr_fail;
56+
u64 tx_evt_status_cfr_fail;
57+
u64 tx_dbr_lookup_fail;
58+
u64 last_success_tstamp;
59+
u64 flush_dbr_cnt;
60+
u64 clear_txrx_event;
61+
u64 cfr_dma_aborts;
62+
bool enabled;
63+
};
64+
65+
#ifdef CONFIG_ATH11K_CFR
66+
int ath11k_cfr_init(struct ath11k_base *ab);
67+
void ath11k_cfr_deinit(struct ath11k_base *ab);
68+
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
69+
u32 buf_id);
70+
#else
71+
static inline int ath11k_cfr_init(struct ath11k_base *ab)
72+
{
73+
return 0;
74+
}
75+
76+
static inline void ath11k_cfr_deinit(struct ath11k_base *ab)
77+
{
78+
}
79+
80+
static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar,
81+
dma_addr_t paddr, u32 buf_id)
82+
{
83+
}
84+
#endif /* CONFIG_ATH11K_CFR */
85+
#endif /* ATH11K_CFR_H */

0 commit comments

Comments
 (0)