Skip to content

Commit 3cf1875

Browse files
Venkateswara NaralasettyRealzhq
authored andcommitted
FROMGIT: wifi: ath11k: Register handler for CFR capture event
Firmware sends CFR meta data through the WMI event WMI_PEER_CFR_CAPTURE_EVENT. Parse the meta data coming from the firmware and invoke correlate_and_relay function to correlate the CFR meta data with the CFR payload coming from the other WMI event WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT. Release the buffer to user space once correlate and relay return success. 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 704c132 commit 3cf1875

5 files changed

Lines changed: 364 additions & 2 deletions

File tree

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

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,160 @@ static int ath11k_cfr_process_data(struct ath11k *ar,
252252
return status;
253253
}
254254

255+
static void ath11k_cfr_fill_hdr_info(struct ath11k *ar,
256+
struct ath11k_csi_cfr_header *header,
257+
struct ath11k_cfr_peer_tx_param *params)
258+
{
259+
struct ath11k_cfr *cfr;
260+
261+
cfr = &ar->cfr;
262+
header->cfr_metadata_version = ATH11K_CFR_META_VERSION_4;
263+
header->cfr_data_version = ATH11K_CFR_DATA_VERSION_1;
264+
header->cfr_metadata_len = sizeof(struct cfr_metadata);
265+
header->chip_type = ar->ab->hw_rev;
266+
header->meta_data.status = FIELD_GET(WMI_CFR_PEER_CAPTURE_STATUS,
267+
params->status);
268+
header->meta_data.capture_bw = params->bandwidth;
269+
270+
/*
271+
* FW reports phymode will always be HE mode.
272+
* Replace it with cached phy mode during peer assoc
273+
*/
274+
header->meta_data.phy_mode = cfr->phymode;
275+
276+
header->meta_data.prim20_chan = params->primary_20mhz_chan;
277+
header->meta_data.center_freq1 = params->band_center_freq1;
278+
header->meta_data.center_freq2 = params->band_center_freq2;
279+
280+
/*
281+
* CFR capture is triggered by the ACK of a QoS Null frame:
282+
* - 20 MHz: Legacy ACK
283+
* - 40/80/160 MHz: DUP Legacy ACK
284+
*/
285+
header->meta_data.capture_mode = params->bandwidth ?
286+
ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK : ATH11K_CFR_CAPTURE_LEGACY_ACK;
287+
header->meta_data.capture_type = params->capture_method;
288+
header->meta_data.num_rx_chain = ar->num_rx_chains;
289+
header->meta_data.sts_count = params->spatial_streams;
290+
header->meta_data.timestamp = params->timestamp_us;
291+
ether_addr_copy(header->meta_data.peer_addr, params->peer_mac_addr);
292+
memcpy(header->meta_data.chain_rssi, params->chain_rssi,
293+
sizeof(params->chain_rssi));
294+
memcpy(header->meta_data.chain_phase, params->chain_phase,
295+
sizeof(params->chain_phase));
296+
memcpy(header->meta_data.agc_gain, params->agc_gain,
297+
sizeof(params->agc_gain));
298+
}
299+
300+
int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
301+
struct ath11k_cfr_peer_tx_param *params)
302+
{
303+
struct ath11k_look_up_table *lut = NULL;
304+
u32 end_magic = ATH11K_CFR_END_MAGIC;
305+
struct ath11k_csi_cfr_header *header;
306+
struct ath11k_dbring_element *buff;
307+
struct ath11k_cfr *cfr;
308+
dma_addr_t buf_addr;
309+
struct ath11k *ar;
310+
u8 tx_status;
311+
int status;
312+
int i;
313+
314+
rcu_read_lock();
315+
ar = ath11k_mac_get_ar_by_vdev_id(ab, params->vdev_id);
316+
if (!ar) {
317+
rcu_read_unlock();
318+
ath11k_warn(ab, "Failed to get ar for vdev id %d\n",
319+
params->vdev_id);
320+
return -ENOENT;
321+
}
322+
323+
cfr = &ar->cfr;
324+
rcu_read_unlock();
325+
326+
if (WMI_CFR_CAPTURE_STATUS_PEER_PS & params->status) {
327+
ath11k_warn(ab, "CFR capture failed as peer %pM is in powersave",
328+
params->peer_mac_addr);
329+
return -EINVAL;
330+
}
331+
332+
if (!(WMI_CFR_PEER_CAPTURE_STATUS & params->status)) {
333+
ath11k_warn(ab, "CFR capture failed for the peer : %pM",
334+
params->peer_mac_addr);
335+
cfr->tx_peer_status_cfr_fail++;
336+
return -EINVAL;
337+
}
338+
339+
tx_status = FIELD_GET(WMI_CFR_FRAME_TX_STATUS, params->status);
340+
if (tx_status != WMI_FRAME_TX_STATUS_OK) {
341+
ath11k_warn(ab, "WMI tx status %d for the peer %pM",
342+
tx_status, params->peer_mac_addr);
343+
cfr->tx_evt_status_cfr_fail++;
344+
return -EINVAL;
345+
}
346+
347+
buf_addr = (((u64)FIELD_GET(WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH,
348+
params->correlation_info_2)) << 32) |
349+
params->correlation_info_1;
350+
351+
spin_lock_bh(&cfr->lut_lock);
352+
353+
if (!cfr->lut) {
354+
spin_unlock_bh(&cfr->lut_lock);
355+
return -EINVAL;
356+
}
357+
358+
for (i = 0; i < cfr->lut_num; i++) {
359+
struct ath11k_look_up_table *temp = &cfr->lut[i];
360+
361+
if (temp->dbr_address == buf_addr) {
362+
lut = &cfr->lut[i];
363+
break;
364+
}
365+
}
366+
367+
if (!lut) {
368+
spin_unlock_bh(&cfr->lut_lock);
369+
ath11k_warn(ab, "lut failure to process tx event\n");
370+
cfr->tx_dbr_lookup_fail++;
371+
return -EINVAL;
372+
}
373+
374+
lut->tx_ppdu_id = FIELD_GET(WMI_CFR_CORRELATION_INFO2_PPDU_ID,
375+
params->correlation_info_2);
376+
lut->txrx_tstamp = jiffies;
377+
378+
header = &lut->header;
379+
header->start_magic_num = ATH11K_CFR_START_MAGIC;
380+
header->vendorid = VENDOR_QCA;
381+
header->platform_type = PLATFORM_TYPE_ARM;
382+
383+
ath11k_cfr_fill_hdr_info(ar, header, params);
384+
385+
status = ath11k_cfr_correlate_and_relay(ar, lut,
386+
ATH11K_CORRELATE_TX_EVENT);
387+
if (status == ATH11K_CORRELATE_STATUS_RELEASE) {
388+
ath11k_dbg(ab, ATH11K_DBG_CFR,
389+
"Releasing CFR data to user space");
390+
ath11k_cfr_rfs_write(ar, &lut->header,
391+
sizeof(struct ath11k_csi_cfr_header),
392+
lut->data, lut->data_len,
393+
&end_magic, sizeof(u32));
394+
buff = lut->buff;
395+
ath11k_cfr_release_lut_entry(lut);
396+
397+
ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, buff,
398+
WMI_DIRECT_BUF_CFR);
399+
} else if (status == ATH11K_CORRELATE_STATUS_HOLD) {
400+
ath11k_dbg(ab, ATH11K_DBG_CFR,
401+
"dbr event is not yet received holding buf\n");
402+
}
403+
404+
spin_unlock_bh(&cfr->lut_lock);
405+
406+
return 0;
407+
}
408+
255409
/* Helper function to check whether the given peer mac address
256410
* is in unassociated peer pool or not.
257411
*/
@@ -711,6 +865,12 @@ void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
711865
cfr->lut[buf_id].dbr_address = paddr;
712866
}
713867

868+
void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode)
869+
{
870+
struct ath11k_cfr *cfr = &ar->cfr;
871+
cfr->phymode = phymode;
872+
}
873+
714874
static void ath11k_cfr_ring_free(struct ath11k *ar)
715875
{
716876
struct ath11k_cfr *cfr = &ar->cfr;

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

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,37 @@ enum ath11k_cfr_correlate_event_type {
2727
struct ath11k_sta;
2828
struct ath11k_per_peer_cfr_capture;
2929

30+
#define ATH11K_CFR_START_MAGIC 0xDEADBEAF
3031
#define ATH11K_CFR_END_MAGIC 0xBEAFDEAD
3132

33+
#define VENDOR_QCA 0x8cfdf0
34+
#define PLATFORM_TYPE_ARM 2
35+
36+
enum ath11k_cfr_meta_version {
37+
ATH11K_CFR_META_VERSION_NONE,
38+
ATH11K_CFR_META_VERSION_1,
39+
ATH11K_CFR_META_VERSION_2,
40+
ATH11K_CFR_META_VERSION_3,
41+
ATH11K_CFR_META_VERSION_4,
42+
ATH11K_CFR_META_VERSION_MAX = 0xFF,
43+
};
44+
45+
enum ath11k_cfr_data_version {
46+
ATH11K_CFR_DATA_VERSION_NONE,
47+
ATH11K_CFR_DATA_VERSION_1,
48+
ATH11K_CFR_DATA_VERSION_MAX = 0xFF,
49+
};
50+
51+
enum ath11k_cfr_capture_ack_mode {
52+
ATH11K_CFR_CAPTURE_LEGACY_ACK,
53+
ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK,
54+
ATH11K_CFR_CAPTURE_HT_ACK,
55+
ATH11K_CFR_CAPTURE_VHT_ACK,
56+
57+
/*Always keep this at last*/
58+
ATH11K_CFR_CAPTURE_INVALID_ACK
59+
};
60+
3261
enum ath11k_cfr_correlate_status {
3362
ATH11K_CORRELATE_STATUS_RELEASE,
3463
ATH11K_CORRELATE_STATUS_HOLD,
@@ -41,6 +70,28 @@ enum ath11k_cfr_preamble_type {
4170
ATH11K_CFR_PREAMBLE_TYPE_VHT,
4271
};
4372

73+
struct ath11k_cfr_peer_tx_param {
74+
u32 capture_method;
75+
u32 vdev_id;
76+
u8 peer_mac_addr[ETH_ALEN];
77+
u32 primary_20mhz_chan;
78+
u32 bandwidth;
79+
u32 phy_mode;
80+
u32 band_center_freq1;
81+
u32 band_center_freq2;
82+
u32 spatial_streams;
83+
u32 correlation_info_1;
84+
u32 correlation_info_2;
85+
u32 status;
86+
u32 timestamp_us;
87+
u32 counter;
88+
u32 chain_rssi[WMI_MAX_CHAINS];
89+
u16 chain_phase[WMI_MAX_CHAINS];
90+
u32 cfo_measurement;
91+
u8 agc_gain[HOST_MAX_CHAINS];
92+
u32 rx_start_ts;
93+
};
94+
4495
struct cfr_metadata {
4596
u8 peer_addr[ETH_ALEN];
4697
u8 status;
@@ -70,7 +121,7 @@ struct ath11k_csi_cfr_header {
70121
u8 cfr_data_version;
71122
u8 chip_type;
72123
u8 platform_type;
73-
u32 reserved;
124+
u32 cfr_metadata_len;
74125
struct cfr_metadata meta_data;
75126
} __packed;
76127

@@ -144,6 +195,7 @@ struct ath11k_cfr {
144195
u64 clear_txrx_event;
145196
u64 cfr_dma_aborts;
146197
bool enabled;
198+
enum wmi_phy_mode phymode;
147199
struct cfr_unassoc_pool_entry unassoc_pool[ATH11K_MAX_CFR_ENABLED_CLIENTS];
148200
};
149201

@@ -181,8 +233,15 @@ int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
181233
const u8 *peer_mac);
182234
struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar);
183235
void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut);
184-
236+
int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
237+
struct ath11k_cfr_peer_tx_param *params);
238+
void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode);
185239
#else
240+
static inline void ath11k_cfr_update_phymode(struct ath11k *ar,
241+
enum wmi_phy_mode phymode)
242+
{
243+
}
244+
186245
static inline int ath11k_cfr_init(struct ath11k_base *ab)
187246
{
188247
return 0;
@@ -238,5 +297,12 @@ struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar)
238297
{
239298
return NULL;
240299
}
300+
301+
static inline
302+
int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
303+
struct ath11k_cfr_peer_tx_param *params)
304+
{
305+
return 0;
306+
}
241307
#endif /* CONFIG_ATH11K_CFR */
242308
#endif /* ATH11K_CFR_H */

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2911,6 +2911,8 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
29112911

29122912
arg->peer_phymode = phymode;
29132913
WARN_ON(phymode == MODE_UNKNOWN);
2914+
2915+
ath11k_cfr_update_phymode(ar, phymode);
29142916
}
29152917

29162918
static void ath11k_peer_assoc_prepare(struct ath11k *ar,

0 commit comments

Comments
 (0)