xref: /wlan-dirver/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_enh.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <target_if_cfr.h>
20 #include <wlan_tgt_def_config.h>
21 #include <target_type.h>
22 #include <hif_hw_version.h>
23 #include <target_if.h>
24 #include <wlan_lmac_if_def.h>
25 #include <wlan_osif_priv.h>
26 #include <init_deinit_lmac.h>
27 #include <wlan_cfr_utils_api.h>
28 #ifdef DIRECT_BUF_RX_ENABLE
29 #include <target_if_direct_buf_rx_api.h>
30 #endif
31 #include <target_if_cfr_enh.h>
32 #include "cdp_txrx_ctrl.h"
33 
34 #define CMN_NOISE_FLOOR       (-96)
35 #define NUM_CHAINS_FW_TO_HOST(n) ((1 << ((n) + 1)) - 1)
36 
37 #define CFR_INVALID_SNR 0x80
38 
39 static u_int32_t end_magic = 0xBEAFDEAD;
40 
41 /**
42  * snr_to_signal_strength() - Convert SNR(dB) to signal strength(dBm)
43  * @snr: SNR in dB
44  *
45  * Return: signal strength in dBm
46  */
47 static inline
48 u_int32_t snr_to_signal_strength(uint8_t snr)
49 {
50 	/* SNR value 0x80 indicates -128dB which is not a valid value */
51 	return (snr != CFR_INVALID_SNR) ?
52 		(((int8_t)snr) + CMN_NOISE_FLOOR) :
53 		((int8_t)snr);
54 }
55 
56 /**
57  * get_lut_entry() - Retrieve LUT entry using cookie number
58  * @pcfr: PDEV CFR object
59  * @offset: cookie number
60  *
61  * Return: look up table entry
62  */
63 static struct look_up_table *get_lut_entry(struct pdev_cfr *pcfr,
64 					   int offset)
65 {
66 	if (offset >= pcfr->lut_num) {
67 		cfr_err("Invalid offset %d, lut_num %d",
68 			offset, pcfr->lut_num);
69 		return NULL;
70 	}
71 
72 	return pcfr->lut[offset];
73 }
74 
75 /**
76  * release_lut_entry_enh() - Clear all params in an LUT entry
77  * @pdev: objmgr PDEV
78  * @lut: pointer to LUT
79  *
80  * Return: status
81  */
82 static int release_lut_entry_enh(struct wlan_objmgr_pdev *pdev,
83 				 struct look_up_table *lut)
84 {
85 	lut->dbr_recv = false;
86 	lut->tx_recv = false;
87 	lut->data = NULL;
88 	lut->data_len = 0;
89 	lut->dbr_ppdu_id = 0;
90 	lut->tx_ppdu_id = 0;
91 	lut->dbr_tstamp = 0;
92 	lut->txrx_tstamp = 0;
93 	lut->tx_address1 = 0;
94 	lut->tx_address2 = 0;
95 	lut->dbr_address = 0;
96 	qdf_mem_zero(&lut->header, sizeof(struct csi_cfr_header));
97 
98 	return 0;
99 }
100 
101 /**
102  * target_if_cfr_dump_lut_enh() - dump all valid lut entries
103  * @pdev: objmgr pdev
104  *
105  * return: none
106  */
107 void target_if_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
108 {
109 	struct pdev_cfr *pcfr;
110 	struct look_up_table *lut = NULL;
111 	int i = 0;
112 	uint64_t diff;
113 	QDF_STATUS retval = 0;
114 
115 	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
116 	if (retval != QDF_STATUS_SUCCESS) {
117 		cfr_err("failed to get pdev reference");
118 		return;
119 	}
120 
121 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
122 						     WLAN_UMAC_COMP_CFR);
123 	if (!pcfr) {
124 		cfr_err("pdev object for CFR is null");
125 		wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
126 		return;
127 	}
128 
129 	qdf_spin_lock_bh(&pcfr->lut_lock);
130 
131 	for (i = 0; i < pcfr->lut_num; i++) {
132 		lut = get_lut_entry(pcfr, i);
133 		if (!lut)
134 			continue;
135 		if (lut->dbr_recv ^ lut->tx_recv) {
136 			diff = (lut->dbr_tstamp > lut->txrx_tstamp) ?
137 				(lut->dbr_tstamp - lut->txrx_tstamp) :
138 				(lut->txrx_tstamp - lut->dbr_tstamp);
139 		}
140 	}
141 
142 	qdf_spin_unlock_bh(&pcfr->lut_lock);
143 
144 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
145 }
146 
147 /**
148  * cfr_free_pending_dbr_events() - Flush all pending DBR events. This is useful
149  * in cases where for RXTLV drops in host monitor status ring is huge.
150  * @pdev: objmgr pdev
151  *
152  * return: none
153  */
154 static void cfr_free_pending_dbr_events(struct wlan_objmgr_pdev *pdev)
155 {
156 	struct pdev_cfr *pcfr;
157 	struct look_up_table *lut = NULL;
158 	int i = 0;
159 	QDF_STATUS retval = 0;
160 
161 	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
162 	if (retval != QDF_STATUS_SUCCESS) {
163 		cfr_err("failed to get pdev reference");
164 		return;
165 	}
166 
167 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
168 						     WLAN_UMAC_COMP_CFR);
169 	if (!pcfr) {
170 		cfr_err("pdev object for CFR is null");
171 		wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
172 		return;
173 	}
174 
175 	for (i = 0; i < pcfr->lut_num; i++) {
176 		lut = get_lut_entry(pcfr, i);
177 		if (!lut)
178 			continue;
179 
180 		if (lut->dbr_recv && !lut->tx_recv &&
181 		    (lut->dbr_tstamp < pcfr->last_success_tstamp)) {
182 			target_if_dbr_buf_release(pdev, DBR_MODULE_CFR,
183 						  lut->dbr_address,
184 						  i, 0);
185 			pcfr->flush_dbr_cnt++;
186 			release_lut_entry_enh(pdev, lut);
187 		}
188 	}
189 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
190 }
191 
192 /**
193  * dump_freeze_tlv() - Dump freeze TLV sent in enhanced DMA header
194  * @freeze_tlv: Freeze TLV sent from MAC to PHY
195  * @cookie: Index into lookup table
196  *
197  * Return: none
198  */
199 static void dump_freeze_tlv(void *freeze_tlv, uint32_t cookie)
200 {
201 	struct macrx_freeze_capture_channel *freeze =
202 		(struct macrx_freeze_capture_channel *)freeze_tlv;
203 
204 	cfr_debug("<DBRCOMP><FREEZE><%u>\n"
205 		  "freeze: %d capture_reason: %d packet_type: 0x%x\n"
206 		  "packet_subtype: 0x%x sw_peer_id_valid: %d sw_peer_id: %d\n"
207 		  "phy_ppdu_id: 0x%04x packet_ta_upper_16: 0x%04x\n"
208 		  "packet_ta_mid_16: 0x%04x packet_ta_lower_16: 0x%04x\n"
209 		  "packet_ra_upper_16: 0x%04x packet_ra_mid_16: 0x%04x\n"
210 		  "packet_ra_lower_16: 0x%04x tsf_timestamp_63_48: 0x%04x\n"
211 		  "tsf_timestamp_47_32: 0x%04x tsf_timestamp_31_16: 0x%04x\n"
212 		  "tsf_timestamp_15_0: 0x%04x user_index_or_user_mask_5_0: %d\n"
213 		  "directed: %d\n",
214 		  cookie,
215 		  freeze->freeze,
216 		  freeze->capture_reason,
217 		  freeze->packet_type,
218 		  freeze->packet_sub_type,
219 		  freeze->sw_peer_id_valid,
220 		  freeze->sw_peer_id,
221 		  freeze->phy_ppdu_id,
222 		  freeze->packet_ta_upper_16,
223 		  freeze->packet_ta_mid_16,
224 		  freeze->packet_ta_lower_16,
225 		  freeze->packet_ra_upper_16,
226 		  freeze->packet_ra_mid_16,
227 		  freeze->packet_ra_lower_16,
228 		  freeze->tsf_timestamp_63_48,
229 		  freeze->tsf_timestamp_47_32,
230 		  freeze->tsf_timestamp_31_16,
231 		  freeze->tsf_timestamp_15_0,
232 		  freeze->user_index_or_user_mask_5_0,
233 		  freeze->directed);
234 }
235 
236 /**
237  * dump_freeze_tlv_v3() - Dump freeze TLV v2 sent in enhanced DMA header
238  * @freeze_tlv: Freeze TLV sent from MAC to PHY
239  * @cookie: Index into lookup table
240  *
241  * Return: none
242  */
243 static void dump_freeze_tlv_v3(void *freeze_tlv, uint32_t cookie)
244 {
245 	struct macrx_freeze_capture_channel_v3 *freeze =
246 		(struct macrx_freeze_capture_channel_v3 *)freeze_tlv;
247 
248 	cfr_debug("<DBRCOMP><FREEZE><%u>\n"
249 		  "freeze: %d capture_reason: %d packet_type: 0x%x\n"
250 		  "packet_subtype: 0x%x sw_peer_id_valid: %d sw_peer_id: %d\n"
251 		  "phy_ppdu_id: 0x%04x packet_ta_upper_16: 0x%04x\n"
252 		  "packet_ta_mid_16: 0x%04x packet_ta_lower_16: 0x%04x\n"
253 		  "packet_ra_upper_16: 0x%04x packet_ra_mid_16: 0x%04x\n"
254 		  "packet_ra_lower_16: 0x%04x\n"
255 		  "tsf_63_48_or_user_mask_36_32: 0x%04x\n"
256 		  "tsf_timestamp_47_32: 0x%04x\n"
257 		  "tsf_timestamp_31_16: 0x%04x\n"
258 		  "tsf_timestamp_15_0: 0x%04x\n"
259 		  "user_index_or_user_mask_15_0: 0x%04x\n"
260 		  "user_mask_31_16: 0x%04x\n"
261 		  "directed: %d\n",
262 		  cookie,
263 		  freeze->freeze,
264 		  freeze->capture_reason,
265 		  freeze->packet_type,
266 		  freeze->packet_sub_type,
267 		  freeze->sw_peer_id_valid,
268 		  freeze->sw_peer_id,
269 		  freeze->phy_ppdu_id,
270 		  freeze->packet_ta_upper_16,
271 		  freeze->packet_ta_mid_16,
272 		  freeze->packet_ta_lower_16,
273 		  freeze->packet_ra_upper_16,
274 		  freeze->packet_ra_mid_16,
275 		  freeze->packet_ra_lower_16,
276 		  freeze->tsf_63_48_or_user_mask_36_32,
277 		  freeze->tsf_timestamp_47_32,
278 		  freeze->tsf_timestamp_31_16,
279 		  freeze->tsf_timestamp_15_0,
280 		  freeze->user_index_or_user_mask_15_0,
281 		  freeze->user_mask_31_16,
282 		  freeze->directed);
283 }
284 
285 /**
286  * dump_mu_rx_info() - Dump MU info in enhanced DMA header
287  * @mu_rx_user_info: MU info sent by ucode
288  * @mu_rx_num_users: Number of MU users in UL-MU-PPDU
289  * @cookie: Index into lookup table
290  *
291  * Return: none
292  */
293 static void dump_mu_rx_info(void *mu_rx_user_info,
294 			    uint8_t mu_rx_num_users,
295 			    uint32_t cookie)
296 {
297 	uint8_t i;
298 	struct uplink_user_setup_info *ul_mu_user_info =
299 		(struct uplink_user_setup_info *)mu_rx_user_info;
300 
301 	for (i = 0 ; i < mu_rx_num_users; i++) {
302 		cfr_debug("<DBRCOMP><MU><%u>\n"
303 			  "<user_id:%d>\n"
304 			  "bw_info_valid = %d\n"
305 			  "uplink_receive_type = %d\n"
306 			  "uplink_11ax_mcs = %d\n"
307 			  "ru_width = %d\n"
308 			  "nss = %d\n"
309 			  "stream_offset = %d\n"
310 			  "sta_dcm = %d\n"
311 			  "sta_coding = %d\n"
312 			  "ru_start_index = %d\n",
313 			  cookie,
314 			  i,
315 			  ul_mu_user_info->bw_info_valid,
316 			  ul_mu_user_info->uplink_receive_type,
317 			  ul_mu_user_info->uplink_11ax_mcs,
318 			  ul_mu_user_info->ru_width,
319 			  ul_mu_user_info->nss,
320 			  ul_mu_user_info->stream_offset,
321 			  ul_mu_user_info->sta_dcm,
322 			  ul_mu_user_info->sta_coding,
323 			  ul_mu_user_info->ru_start_index);
324 		ul_mu_user_info += sizeof(struct uplink_user_setup_info);
325 	}
326 }
327 
328 static void dump_metadata(struct csi_cfr_header *header, uint32_t cookie)
329 {
330 	uint8_t user_id, chain_id;
331 	struct cfr_metadata_version_3 *meta = &header->u.meta_v3;
332 	uint8_t *usermac = NULL;
333 
334 	cfr_debug("<METADATA><%u>\n"
335 		  "start_magic_num = 0x%x\n"
336 		  "vendorid = 0x%x\n"
337 		  "cfr_metadata_version = %d\n"
338 		  "cfr_data_version = %d\n"
339 		  "chip_type = %d\n"
340 		  "platform_type = %d\n"
341 		  "status = %d\n"
342 		  "capture_bw = %d\n"
343 		  "channel_bw = %d\n"
344 		  "phy_mode = %d\n"
345 		  "prim20_chan = %d\n"
346 		  "center_freq1 = %d\n"
347 		  "center_freq2 = %d\n"
348 		  "ack_capture_mode = %d\n"
349 		  "cfr_capture_type = %d\n"
350 		  "sts_count = %d\n"
351 		  "num_rx_chain = %d\n"
352 		  "timestamp = %llu\n"
353 		  "length = %d\n"
354 		  "is_mu_ppdu = %d\n"
355 		  "num_users = %d\n",
356 		cookie,
357 		header->start_magic_num,
358 		header->vendorid,
359 		header->cfr_metadata_version,
360 		header->cfr_data_version,
361 		header->chip_type,
362 		header->pltform_type,
363 		meta->status,
364 		meta->capture_bw,
365 		meta->channel_bw,
366 		meta->phy_mode,
367 		meta->prim20_chan,
368 		meta->center_freq1,
369 		meta->center_freq2,
370 		meta->capture_mode,
371 		meta->capture_type,
372 		meta->sts_count,
373 		meta->num_rx_chain,
374 		meta->timestamp,
375 		meta->length,
376 		meta->is_mu_ppdu,
377 		meta->num_mu_users);
378 
379 	if (meta->is_mu_ppdu) {
380 		for (user_id = 0; user_id < meta->num_mu_users; user_id++) {
381 			usermac = meta->peer_addr.mu_peer_addr[user_id];
382 			cfr_debug("peermac[%d]: " QDF_MAC_ADDR_FMT,
383 				  user_id, QDF_MAC_ADDR_REF(usermac));
384 		}
385 	} else {
386 		cfr_debug("peermac: " QDF_MAC_ADDR_FMT,
387 			  QDF_MAC_ADDR_REF(meta->peer_addr.su_peer_addr));
388 	}
389 
390 	for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) {
391 		cfr_debug("chain_rssi[%d] = %d\n",
392 			  chain_id,
393 			  meta->chain_rssi[chain_id]);
394 	}
395 
396 	for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) {
397 		cfr_debug("chain_phase[%d] = %d\n",
398 			  chain_id,
399 			  meta->chain_phase[chain_id]);
400 	}
401 }
402 
403 /**
404  * dump_enh_dma_hdr() - Dump enhanced DMA header populated by ucode
405  * @dma_hdr: pointer to enhanced DMA header
406  * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV
407  * @mu_rx_user_info: UPLINK_USER_SETUP_INFO TLV
408  * @header: pointer to metadata passed to userspace
409  * @error: Indicates whether it is an error
410  * @cookie: Index into lookup table
411  *
412  * Return: none
413  */
414 static void dump_enh_dma_hdr(struct whal_cfir_enhanced_hdr *dma_hdr,
415 			     void *freeze_tlv, void *mu_rx_user_info,
416 			     struct csi_cfr_header *header, int error,
417 			     uint32_t cookie)
418 {
419 	if (!error) {
420 		cfr_debug("<DBRCOMP><%u>\n"
421 			  "Tag: 0x%02x Length: %d udone: %d\n"
422 			  "ctype: %d preamble: %d Nss: %d\n"
423 			  "num_chains: %d bw: %d peervalid: %d\n"
424 			  "peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n"
425 			  "header_version: %d target_id: %d cfr_fmt: %d\n"
426 			  "mu_rx_data_incl: %d freeze_data_incl: %d\n"
427 			  "mu_rx_num_users: %d decimation_factor: %d\n"
428 			  "freeze_tlv_version: %d\n",
429 			  cookie,
430 			  dma_hdr->tag,
431 			  dma_hdr->length,
432 			  dma_hdr->upload_done,
433 			  dma_hdr->capture_type,
434 			  dma_hdr->preamble_type,
435 			  dma_hdr->nss,
436 			  dma_hdr->num_chains,
437 			  dma_hdr->upload_pkt_bw,
438 			  dma_hdr->sw_peer_id_valid,
439 			  dma_hdr->sw_peer_id,
440 			  dma_hdr->phy_ppdu_id,
441 			  dma_hdr->total_bytes,
442 			  dma_hdr->header_version,
443 			  dma_hdr->target_id,
444 			  dma_hdr->cfr_fmt,
445 			  dma_hdr->mu_rx_data_incl,
446 			  dma_hdr->freeze_data_incl,
447 			  dma_hdr->mu_rx_num_users,
448 			  dma_hdr->decimation_factor,
449 			  dma_hdr->freeze_tlv_version);
450 
451 		if (dma_hdr->freeze_data_incl) {
452 			if (dma_hdr->freeze_tlv_version ==
453 					MACRX_FREEZE_TLV_VERSION_3)
454 				dump_freeze_tlv_v3(freeze_tlv, cookie);
455 			else
456 				dump_freeze_tlv(freeze_tlv, cookie);
457 		}
458 
459 		if (dma_hdr->mu_rx_data_incl)
460 			dump_mu_rx_info(mu_rx_user_info,
461 					dma_hdr->mu_rx_num_users,
462 					cookie);
463 	} else {
464 		cfr_err("<DBRCOMP><%u>\n"
465 			"Tag: 0x%02x Length: %d udone: %d\n"
466 			"ctype: %d preamble: %d Nss: %d\n"
467 			"num_chains: %d bw: %d peervalid: %d\n"
468 			"peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n"
469 			"header_version: %d target_id: %d cfr_fmt: %d\n"
470 			"mu_rx_data_incl: %d freeze_data_incl: %d\n"
471 			"mu_rx_num_users: %d decimation_factor: %d\n"
472 			"freeze_tlv_version: %d\n",
473 			cookie,
474 			dma_hdr->tag,
475 			dma_hdr->length,
476 			dma_hdr->upload_done,
477 			dma_hdr->capture_type,
478 			dma_hdr->preamble_type,
479 			dma_hdr->nss,
480 			dma_hdr->num_chains,
481 			dma_hdr->upload_pkt_bw,
482 			dma_hdr->sw_peer_id_valid,
483 			dma_hdr->sw_peer_id,
484 			dma_hdr->phy_ppdu_id,
485 			dma_hdr->total_bytes,
486 			dma_hdr->header_version,
487 			dma_hdr->target_id,
488 			dma_hdr->cfr_fmt,
489 			dma_hdr->mu_rx_data_incl,
490 			dma_hdr->freeze_data_incl,
491 			dma_hdr->mu_rx_num_users,
492 			dma_hdr->decimation_factor,
493 			dma_hdr->freeze_tlv_version);
494 	}
495 }
496 
497 /**
498  * extract_peer_mac_from_freeze_tlv() - extract macaddr from freeze tlv
499  * @freeze_tlv: Freeze TLV sent from MAC to PHY
500  * @peermac: macaddr of the peer
501  *
502  * Return: none
503  */
504 static void
505 extract_peer_mac_from_freeze_tlv(void *freeze_tlv, uint8_t *peermac)
506 {
507 	/*
508 	 * Packet_ta fields position is common between freeze tlv v1
509 	 * and v2, hence typecasting to v1 is also fine
510 	 */
511 	struct macrx_freeze_capture_channel *freeze =
512 		(struct macrx_freeze_capture_channel *)freeze_tlv;
513 
514 	peermac[0] = freeze->packet_ta_lower_16 & 0x00FF;
515 	peermac[1] = (freeze->packet_ta_lower_16 & 0xFF00) >> 8;
516 	peermac[2] = freeze->packet_ta_mid_16 & 0x00FF;
517 	peermac[3] = (freeze->packet_ta_mid_16 & 0xFF00) >> 8;
518 	peermac[4] = freeze->packet_ta_upper_16 & 0x00FF;
519 	peermac[5] = (freeze->packet_ta_upper_16 & 0xFF00) >> 8;
520 }
521 
522 /**
523  * check_dma_length() - Sanity check DMA header and payload length
524  * @dma_hdr: pointer to enhanced DMA header
525  *
526  * Return: QDF_STATUS
527  */
528 static QDF_STATUS check_dma_length(struct look_up_table *lut,
529 				   uint32_t target_type)
530 {
531 	if (target_type == TARGET_TYPE_QCN9000) {
532 		if (lut->header_length <= PINE_MAX_HEADER_LENGTH_WORDS &&
533 		    lut->payload_length <= PINE_MAX_DATA_LENGTH_BYTES) {
534 			return QDF_STATUS_SUCCESS;
535 		}
536 	} else {
537 		if (lut->header_length <= CYP_MAX_HEADER_LENGTH_WORDS &&
538 		    lut->payload_length <= CYP_MAX_DATA_LENGTH_BYTES) {
539 			return QDF_STATUS_SUCCESS;
540 		}
541 	}
542 	return QDF_STATUS_E_FAILURE;
543 }
544 
545 /**
546  * correlate_and_relay_enh() - Correlate TXRX and DBR events and stream CFR
547  * data to userspace
548  * @pdev: objmgr PDEV
549  * @cookie: Index into lookup table
550  * @lut: pointer to lookup table
551  * @module_id: ID of the event received
552  *  0 - DBR event
553  *  1 - TXRX event
554  *
555  * Return:
556  *	- STATUS_ERROR
557  *	- STATUS_HOLD
558  *	- STATUS_STREAM_AND_RELEASE
559  */
560 static int correlate_and_relay_enh(struct wlan_objmgr_pdev *pdev,
561 				   uint32_t cookie,
562 				   struct look_up_table *lut,
563 				   uint8_t module_id)
564 {
565 	struct pdev_cfr *pcfr;
566 	uint64_t diff;
567 	int status = STATUS_ERROR;
568 	struct wlan_objmgr_psoc *psoc;
569 	uint32_t target_type;
570 
571 	if (module_id > 1) {
572 		cfr_err("Received request with invalid mod id. Investigate!!");
573 		QDF_ASSERT(0);
574 		status = STATUS_ERROR;
575 		goto done;
576 	}
577 
578 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
579 						     WLAN_UMAC_COMP_CFR);
580 
581 	psoc = wlan_pdev_get_psoc(pdev);
582 	if (qdf_unlikely(!psoc)) {
583 		cfr_err("psoc is null\n");
584 		status = STATUS_ERROR;
585 		goto done;
586 	}
587 
588 	target_type = target_if_cfr_get_target_type(psoc);
589 
590 	if (module_id == CORRELATE_TX_EV_MODULE_ID) {
591 		if (lut->tx_recv)
592 			pcfr->cfr_dma_aborts++;
593 		lut->tx_recv = true;
594 	} else if (module_id == CORRELATE_DBR_MODULE_ID) {
595 		pcfr->dbr_evt_cnt++;
596 		lut->dbr_recv = true;
597 	}
598 
599 	if ((lut->dbr_recv) && (lut->tx_recv)) {
600 		if (lut->dbr_ppdu_id == lut->tx_ppdu_id) {
601 			pcfr->last_success_tstamp = lut->dbr_tstamp;
602 			if (lut->dbr_tstamp > lut->txrx_tstamp) {
603 				diff = lut->dbr_tstamp - lut->txrx_tstamp;
604 				cfr_debug("<CORRELATE><%u>: "
605 					  "TXRX evt -> DBR evt"
606 					  "(delay = %llu ms)\n", cookie, diff);
607 			} else if (lut->txrx_tstamp > lut->dbr_tstamp) {
608 				diff = lut->txrx_tstamp - lut->dbr_tstamp;
609 				cfr_debug("<CORRELATE><%u>: "
610 					  "DBR evt -> TXRX evt"
611 					  "(delay = %llu ms)\n", cookie, diff);
612 			}
613 
614 			/*
615 			 * Flush pending dbr events, if newer PPDU TLV is
616 			 * received
617 			 */
618 			cfr_free_pending_dbr_events(pdev);
619 
620 			if (check_dma_length(lut, target_type) ==
621 					QDF_STATUS_SUCCESS) {
622 				pcfr->release_cnt++;
623 				cfr_debug("<CORRELATE><%u>:Stream and release "
624 					  "CFR data for "
625 					  "ppdu_id:0x%04x\n", cookie,
626 					  lut->tx_ppdu_id);
627 				status = STATUS_STREAM_AND_RELEASE;
628 				goto done;
629 			} else {
630 				pcfr->invalid_dma_length_cnt++;
631 				cfr_err("<CORRELATE><%u>:CFR buffers "
632 					"received with invalid length "
633 					"header_length_words = %d "
634 					"cfr_payload_length_bytes = %d "
635 					"ppdu_id:0x%04x\n",
636 					cookie,
637 					lut->header_length,
638 					lut->payload_length,
639 					lut->tx_ppdu_id);
640 				/*
641 				 * Assert here as length exceeding the allowed
642 				 * limit would anyway manifest as random crash
643 				 */
644 				QDF_ASSERT(0);
645 				status = STATUS_ERROR;
646 				goto done;
647 			}
648 		} else {
649 			/*
650 			 * When there is a ppdu id mismatch, discard the TXRX
651 			 * event since multiple PPDUs are likely to have same
652 			 * dma addr, due to ucode aborts
653 			 */
654 			cfr_debug("Received new dbr event for same "
655 				  "cookie %u",
656 				  cookie);
657 			lut->tx_recv = false;
658 			lut->tx_ppdu_id = 0;
659 			pcfr->clear_txrx_event++;
660 			pcfr->cfr_dma_aborts++;
661 			status = STATUS_HOLD;
662 		}
663 	} else {
664 		status = STATUS_HOLD;
665 	}
666 done:
667 	return status;
668 }
669 
670 /**
671  * target_if_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in
672  * lookup table
673  * @pdev_obj: PDEV object
674  * @nbuf: ppdu info
675  *
676  * Return: none
677  */
678 void target_if_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
679 {
680 	struct cdp_rx_indication_ppdu *cdp_rx_ppdu;
681 	struct cdp_rx_stats_ppdu_user *rx_stats_peruser;
682 	struct cdp_rx_ppdu_cfr_info *cfr_info;
683 	qdf_dma_addr_t buf_addr = 0, buf_addr_extn = 0;
684 	struct pdev_cfr *pcfr;
685 	struct look_up_table *lut = NULL;
686 	struct csi_cfr_header *header = NULL;
687 	uint32_t cookie;
688 	struct wlan_objmgr_psoc *psoc;
689 	struct wlan_channel *bss_chan;
690 	enum wlan_phymode ch_phymode;
691 	uint16_t ch_freq;
692 	uint32_t ch_cfreq1;
693 	uint32_t ch_cfreq2;
694 	struct wlan_objmgr_vdev *vdev = NULL;
695 	int i, status = 0;
696 	QDF_STATUS retval = 0;
697 	struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL;
698 	struct cfr_metadata_version_3 *meta = NULL;
699 	uint8_t srng_id = 0;
700 	struct wlan_lmac_if_rx_ops *rx_ops;
701 
702 	if (qdf_unlikely(!pdev)) {
703 		cfr_err("pdev is null\n");
704 		qdf_nbuf_free(nbuf);
705 		return;
706 	}
707 
708 	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
709 	if (qdf_unlikely(retval != QDF_STATUS_SUCCESS)) {
710 		cfr_err("failed to get pdev reference");
711 		qdf_nbuf_free(nbuf);
712 		return;
713 	}
714 
715 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
716 						     WLAN_UMAC_COMP_CFR);
717 	if (qdf_unlikely(!pcfr)) {
718 		cfr_err("pdev object for CFR is NULL");
719 		goto relref;
720 	}
721 
722 	cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)qdf_nbuf_data(nbuf);
723 	cfr_info = &cdp_rx_ppdu->cfr_info;
724 
725 	if (!cfr_info->bb_captured_channel)
726 		goto relref;
727 
728 	psoc = wlan_pdev_get_psoc(pdev);
729 	if (qdf_unlikely(!psoc)) {
730 		cfr_err("psoc is null\n");
731 		goto relref;
732 	}
733 
734 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
735 	if (!rx_ops) {
736 		cfr_err("rx_ops is NULL");
737 		goto relref;
738 	}
739 	cfr_rx_ops = &rx_ops->cfr_rx_ops;
740 	buf_addr_extn = cfr_info->rtt_che_buffer_pointer_high8 & 0xF;
741 	buf_addr = (cfr_info->rtt_che_buffer_pointer_low32 |
742 		    ((uint64_t)buf_addr_extn << 32));
743 
744 	srng_id = pcfr->rcc_param.srng_id;
745 	if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr,
746 					&cookie, srng_id)) {
747 		cfr_debug("Cookie lookup failure for addr: 0x%pK",
748 			  (void *)((uintptr_t)buf_addr));
749 		goto relref;
750 	}
751 
752 	cfr_debug("<RXTLV><%u>:buffer address: 0x%pK\n"
753 		  "<WIFIRX_PPDU_START_E> ppdu_id: 0x%04x\n"
754 		  "<WIFIRXPCU_PPDU_END_INFO_E> BB_CAPTURED_CHANNEL = %d\n"
755 		  "<WIFIPHYRX_PKT_END_E> RX_LOCATION_INFO_VALID = %d\n"
756 		  "<WIFIPHYRX_PKT_END_E> RTT_CHE_BUFFER_POINTER_LOW32 = %x\n"
757 		  "<WIFIPHYRX_PKT_END_E> RTT_CHE_BUFFER_POINTER_HIGH8 = %x\n"
758 		  "<WIFIPHYRX_PKT_END_E> CHAN_CAPTURE_STATUS = %d\n",
759 		  cookie,
760 		  (void *)((uintptr_t)buf_addr),
761 		  cdp_rx_ppdu->ppdu_id,
762 		  cfr_info->bb_captured_channel,
763 		  cfr_info->rx_location_info_valid,
764 		  cfr_info->rtt_che_buffer_pointer_low32,
765 		  cfr_info->rtt_che_buffer_pointer_high8,
766 		  cfr_info->chan_capture_status);
767 
768 	qdf_spin_lock_bh(&pcfr->lut_lock);
769 
770 	lut = get_lut_entry(pcfr, cookie);
771 	if (qdf_unlikely(!lut)) {
772 		cfr_err("lut is NULL");
773 		goto unlock;
774 	}
775 
776 	vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_CFR_ID);
777 	if (qdf_unlikely(!vdev)) {
778 		cfr_debug("vdev is null\n");
779 		goto unlock;
780 	}
781 
782 	bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
783 	ch_freq = bss_chan->ch_freq;
784 	ch_cfreq1 = bss_chan->ch_cfreq1;
785 	ch_cfreq2 = bss_chan->ch_cfreq2;
786 	ch_phymode = bss_chan->ch_phymode;
787 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
788 
789 	pcfr->rx_tlv_evt_cnt++;
790 	lut->tx_ppdu_id = cdp_rx_ppdu->ppdu_id;
791 	lut->tx_address1 = cfr_info->rtt_che_buffer_pointer_low32;
792 	lut->tx_address2 = cfr_info->rtt_che_buffer_pointer_high8;
793 	lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get());
794 	header = &lut->header;
795 	meta = &header->u.meta_v3;
796 
797 	header->start_magic_num        = 0xDEADBEAF;
798 	header->vendorid               = 0x8cfdf0;
799 	header->cfr_metadata_version   = CFR_META_VERSION_3;
800 	header->cfr_data_version       = CFR_DATA_VERSION_1;
801 	header->chip_type              = pcfr->chip_type;
802 	header->pltform_type           = CFR_PLATFORM_TYPE_ARM;
803 	header->Reserved               = 0;
804 
805 	meta->status       = 1;
806 	meta->phy_mode = ch_phymode;
807 	meta->prim20_chan  = ch_freq;
808 	meta->center_freq1 = ch_cfreq1;
809 	meta->center_freq2 = ch_cfreq2;
810 	meta->capture_mode = 0;
811 
812 	meta->timestamp = cdp_rx_ppdu->timestamp;
813 	meta->is_mu_ppdu = (cdp_rx_ppdu->u.ppdu_type == CDP_RX_TYPE_SU) ? 0 : 1;
814 	meta->num_mu_users = (meta->is_mu_ppdu) ? (cdp_rx_ppdu->num_users) : 0;
815 
816 	if (meta->num_mu_users > pcfr->max_mu_users)
817 		meta->num_mu_users = pcfr->max_mu_users;
818 
819 	for (i = 0; i < MAX_CHAIN; i++)
820 		meta->chain_rssi[i] =
821 			snr_to_signal_strength(cdp_rx_ppdu->per_chain_rssi[i]);
822 
823 	if (cdp_rx_ppdu->u.ppdu_type != CDP_RX_TYPE_SU) {
824 		for (i = 0 ; i < meta->num_mu_users; i++) {
825 			rx_stats_peruser = &cdp_rx_ppdu->user[i];
826 			qdf_mem_copy(meta->peer_addr.mu_peer_addr[i],
827 				     rx_stats_peruser->mac_addr,
828 				     QDF_MAC_ADDR_SIZE);
829 		}
830 	}
831 	status = correlate_and_relay_enh(pdev, cookie, lut,
832 					 CORRELATE_TX_EV_MODULE_ID);
833 	if (status == STATUS_STREAM_AND_RELEASE) {
834 		if (cfr_rx_ops->cfr_info_send)
835 			status = cfr_rx_ops->cfr_info_send(pdev,
836 							   &lut->header,
837 							   sizeof(struct
838 							   csi_cfr_header),
839 							   lut->data,
840 							   lut->data_len,
841 							   &end_magic, 4);
842 		dump_metadata(header, cookie);
843 		release_lut_entry_enh(pdev, lut);
844 		target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr,
845 					  cookie, srng_id);
846 	}
847 
848 unlock:
849 	qdf_spin_unlock_bh(&pcfr->lut_lock);
850 relref:
851 	qdf_nbuf_free(nbuf);
852 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
853 }
854 
855 /**
856  * freeze_reason_to_capture_type() - Convert capture type enum in freeze tlv
857  * to the cfr type enum shared with userspace
858  * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV
859  *
860  * Return: cfr type enum
861  */
862 static uint8_t freeze_reason_to_capture_type(void *freeze_tlv)
863 {
864 	/*
865 	 * Capture_reason field position is common between freeze_tlv v1
866 	 * and v2, hence typcasting to any one is fine
867 	 */
868 	struct macrx_freeze_capture_channel *freeze =
869 		(struct macrx_freeze_capture_channel *)freeze_tlv;
870 
871 	switch (freeze->capture_reason) {
872 	case FREEZE_REASON_TM:
873 		return CFR_TYPE_METHOD_TM;
874 	case FREEZE_REASON_FTM:
875 		return CFR_TYPE_METHOD_FTM;
876 	case FREEZE_REASON_TA_RA_TYPE_FILTER:
877 		return CFR_TYPE_METHOD_TA_RA_TYPE_FILTER;
878 	case FREEZE_REASON_NDPA_NDP:
879 		return CFR_TYPE_METHOD_NDPA_NDP;
880 	case FREEZE_REASON_ALL_PACKET:
881 		return CFR_TYPE_METHOD_ALL_PACKET;
882 	case FREEZE_REASON_ACK_RESP_TO_TM_FTM:
883 		return CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM;
884 	default:
885 		return CFR_TYPE_METHOD_AUTO;
886 	}
887 	return CFR_TYPE_METHOD_AUTO;
888 }
889 
890 #ifdef DIRECT_BUF_RX_ENABLE
891 /**
892  * enh_cfr_dbr_event_handler() - Process DBR event for CFR data DMA completion
893  * @pdev: PDEV object
894  * @payload: pointer to CFR data
895  *
896  * Return: status
897  */
898 static bool enh_cfr_dbr_event_handler(struct wlan_objmgr_pdev *pdev,
899 				      struct direct_buf_rx_data *payload)
900 {
901 	uint8_t *data = NULL;
902 	uint32_t cookie = 0;
903 	struct whal_cfir_enhanced_hdr dma_hdr = {0};
904 	int  length, status = 0;
905 	struct wlan_objmgr_psoc *psoc;
906 	struct pdev_cfr *pcfr;
907 	struct look_up_table *lut = NULL;
908 	struct csi_cfr_header *header = NULL;
909 	void *mu_rx_user_info = NULL, *freeze_tlv = NULL;
910 	uint8_t capture_type = CFR_TYPE_METHOD_AUTO;
911 	uint8_t *peer_macaddr = NULL;
912 	struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL;
913 	struct cfr_metadata_version_3 *meta = NULL;
914 	struct wlan_lmac_if_rx_ops *rx_ops;
915 
916 	if ((!pdev) || (!payload)) {
917 		cfr_err("pdev or payload is null");
918 		return true;
919 	}
920 
921 	psoc = wlan_pdev_get_psoc(pdev);
922 	if (!psoc) {
923 		cfr_err("psoc is null");
924 		return true;
925 	}
926 
927 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
928 	if (!rx_ops) {
929 		cfr_err("rx_ops is NULL");
930 		return true;
931 	}
932 	cfr_rx_ops = &rx_ops->cfr_rx_ops;
933 
934 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
935 						     WLAN_UMAC_COMP_CFR);
936 	if (!pcfr) {
937 		cfr_err("pdev object for CFR is null");
938 		return true;
939 	}
940 
941 	data = payload->vaddr;
942 	cookie = payload->cookie;
943 
944 	cfr_debug("<DBRCOMP><%u>:bufferaddr: 0x%pK cookie: %u\n", cookie,
945 		  (void *)((uintptr_t)payload->paddr), cookie);
946 
947 	qdf_mem_copy(&dma_hdr, &data[0],
948 		     sizeof(struct whal_cfir_enhanced_hdr));
949 
950 	if (dma_hdr.freeze_data_incl) {
951 		freeze_tlv = data + sizeof(struct whal_cfir_enhanced_hdr);
952 		capture_type = freeze_reason_to_capture_type(freeze_tlv);
953 	}
954 
955 	if (dma_hdr.mu_rx_data_incl) {
956 		uint8_t freeze_tlv_len;
957 
958 		if (dma_hdr.freeze_tlv_version == MACRX_FREEZE_TLV_VERSION_3) {
959 			freeze_tlv_len =
960 				sizeof(struct macrx_freeze_capture_channel_v3);
961 		} else {
962 			freeze_tlv_len =
963 				sizeof(struct macrx_freeze_capture_channel);
964 		}
965 		mu_rx_user_info = data +
966 			sizeof(struct whal_cfir_enhanced_hdr) +
967 			(dma_hdr.freeze_data_incl ? freeze_tlv_len : 0);
968 	}
969 
970 	length  = dma_hdr.length * 4;
971 	length += dma_hdr.total_bytes; /* size of cfr data */
972 
973 	qdf_spin_lock_bh(&pcfr->lut_lock);
974 
975 	lut = get_lut_entry(pcfr, cookie);
976 	if (!lut) {
977 		cfr_err("lut is NULL");
978 		qdf_spin_unlock_bh(&pcfr->lut_lock);
979 		return true;
980 	}
981 
982 	lut->data = data;
983 	lut->data_len = length;
984 	lut->dbr_ppdu_id = dma_hdr.phy_ppdu_id;
985 	lut->dbr_address = payload->paddr;
986 	lut->dbr_tstamp = qdf_ktime_to_ms(qdf_ktime_get());
987 	lut->header_length = dma_hdr.length;
988 	lut->payload_length = dma_hdr.total_bytes;
989 	qdf_mem_copy(&lut->dma_hdr, &dma_hdr,
990 		     sizeof(struct whal_cfir_dma_hdr));
991 
992 	header = &lut->header;
993 	header->chip_type = pcfr->chip_type;
994 	meta = &header->u.meta_v3;
995 	meta->channel_bw = dma_hdr.upload_pkt_bw;
996 	meta->num_rx_chain = NUM_CHAINS_FW_TO_HOST(dma_hdr.num_chains);
997 	meta->length = length;
998 	/* For Tx based captures, capture type is sent from FW */
999 	if (capture_type != CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM) {
1000 		meta->capture_type = capture_type;
1001 		meta->sts_count = (dma_hdr.nss + 1);
1002 		if (!dma_hdr.mu_rx_data_incl) {
1003 			/* extract peer addr from freeze tlv */
1004 			peer_macaddr = meta->peer_addr.su_peer_addr;
1005 			if (dma_hdr.freeze_data_incl) {
1006 				extract_peer_mac_from_freeze_tlv(freeze_tlv,
1007 								 peer_macaddr);
1008 			}
1009 		}
1010 	}
1011 
1012 	if (dma_hdr.freeze_data_incl) {
1013 		dump_enh_dma_hdr(&dma_hdr, freeze_tlv, mu_rx_user_info,
1014 				 header, 0, cookie);
1015 	}
1016 
1017 	status = correlate_and_relay_enh(pdev, cookie, lut,
1018 					 CORRELATE_DBR_MODULE_ID);
1019 	if (status == STATUS_STREAM_AND_RELEASE) {
1020 		/*
1021 		 * Message format
1022 		 *  Meta data Header + actual payload + trailer
1023 		 */
1024 		if (cfr_rx_ops->cfr_info_send)
1025 			status = cfr_rx_ops->cfr_info_send(pdev,
1026 							   &lut->header,
1027 							   sizeof(struct
1028 							   csi_cfr_header),
1029 							   lut->data,
1030 							   lut->data_len,
1031 							   &end_magic, 4);
1032 		dump_metadata(header, cookie);
1033 		release_lut_entry_enh(pdev, lut);
1034 		status = true;
1035 	} else if (status == STATUS_HOLD) {
1036 		status = false;
1037 	} else {
1038 		status = true;
1039 	}
1040 
1041 	qdf_spin_unlock_bh(&pcfr->lut_lock);
1042 	return status;
1043 }
1044 
1045 /**
1046  * target_if_register_to_dbr_enh() - Initialize DBR ring and register callback
1047  * for DBR events
1048  * @pdev: PDEV object
1049  *
1050  * Return: status
1051  */
1052 static QDF_STATUS
1053 target_if_register_to_dbr_enh(struct wlan_objmgr_pdev *pdev)
1054 {
1055 	struct wlan_objmgr_psoc *psoc;
1056 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
1057 	struct dbr_module_config dbr_config;
1058 	struct wlan_lmac_if_tx_ops *tx_ops;
1059 
1060 	psoc = wlan_pdev_get_psoc(pdev);
1061 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1062 	if (!tx_ops) {
1063 		cfr_err("tx_ops is NULL");
1064 		return QDF_STATUS_SUCCESS;
1065 	}
1066 	dbr_tx_ops = &tx_ops->dbr_tx_ops;
1067 	dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_CFR;
1068 	dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_CFR;
1069 	if (dbr_tx_ops->direct_buf_rx_module_register) {
1070 		return dbr_tx_ops->direct_buf_rx_module_register
1071 			(pdev, DBR_MODULE_CFR, &dbr_config,
1072 			 enh_cfr_dbr_event_handler);
1073 	}
1074 
1075 	return QDF_STATUS_SUCCESS;
1076 }
1077 
1078 /**
1079  * target_if_unregister_to_dbr_enh() - Unregister callback for DBR events
1080  * @pdev: PDEV object
1081  *
1082  * Return: status
1083  */
1084 static QDF_STATUS
1085 target_if_unregister_to_dbr_enh(struct wlan_objmgr_pdev *pdev)
1086 {
1087 	struct wlan_objmgr_psoc *psoc;
1088 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
1089 	struct wlan_lmac_if_tx_ops *tx_ops;
1090 
1091 	psoc = wlan_pdev_get_psoc(pdev);
1092 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1093 	if (!tx_ops) {
1094 		cfr_err("tx_ops is NULL");
1095 		return QDF_STATUS_SUCCESS;
1096 	}
1097 	dbr_tx_ops = &tx_ops->dbr_tx_ops;
1098 	if (dbr_tx_ops->direct_buf_rx_module_unregister) {
1099 		return dbr_tx_ops->direct_buf_rx_module_unregister
1100 			(pdev, DBR_MODULE_CFR);
1101 	}
1102 
1103 	return QDF_STATUS_SUCCESS;
1104 }
1105 #endif
1106 
1107 /**
1108  * dump_cfr_peer_tx_event_enh() - Dump TX completion event
1109  * @event: ptr to WMI TX completion event for QOS frames sent during
1110  * one-shot capture
1111  * @cookie: Index into lookup table
1112  *
1113  * Return: none
1114  */
1115 static void dump_cfr_peer_tx_event_enh(wmi_cfr_peer_tx_event_param *event,
1116 				       uint32_t cookie)
1117 {
1118 	cfr_debug("<TXCOMP><%u>CFR capture method: %d vdev_id: %d mac: "
1119 		  QDF_MAC_ADDR_FMT, cookie,
1120 		  event->capture_method, event->vdev_id,
1121 		  QDF_MAC_ADDR_REF(event->peer_mac_addr.bytes));
1122 
1123 	cfr_debug("<TXCOMP><%u>Chan: %d bw: %d phymode: %d cfreq1: %d cfrq2: %d "
1124 		  "nss: %d\n",
1125 		  cookie,
1126 		  event->primary_20mhz_chan, event->bandwidth,
1127 		  event->phy_mode, event->band_center_freq1,
1128 		  event->band_center_freq2, event->spatial_streams);
1129 
1130 	cfr_debug("<TXCOMP><%u>Correlation_info1: 0x%08x "
1131 		  "Correlation_info2: 0x%08x\n",
1132 		  cookie,
1133 		  event->correlation_info_1, event->correlation_info_2);
1134 
1135 	cfr_debug("<TXCOMP><%u>status: 0x%x ts: %d counter: %d rssi0: 0x%08x\n",
1136 		  cookie,
1137 		  event->status, event->timestamp_us, event->counter,
1138 		  event->chain_rssi[0]);
1139 }
1140 
1141 #ifdef DIRECT_BUF_RX_ENABLE
1142 /**
1143  * enh_prepare_cfr_header_txstatus() - Prepare CFR metadata for TX failures
1144  * @tx_evt_param: ptr to WMI TX completion event
1145  * @header: pointer to metadata
1146  *
1147  * Return: none
1148  */
1149 static void enh_prepare_cfr_header_txstatus(wmi_cfr_peer_tx_event_param
1150 					    *tx_evt_param,
1151 					    struct csi_cfr_header *header,
1152 					    uint32_t target_type)
1153 {
1154 	header->start_magic_num        = 0xDEADBEAF;
1155 	header->vendorid               = 0x8cfdf0;
1156 	header->cfr_metadata_version   = CFR_META_VERSION_3;
1157 	header->cfr_data_version       = CFR_DATA_VERSION_1;
1158 
1159 	if (target_type == TARGET_TYPE_QCN9000)
1160 		header->chip_type      = CFR_CAPTURE_RADIO_PINE;
1161 	else if (target_type == TARGET_TYPE_QCA5018)
1162 		header->chip_type      = CFR_CAPTURE_RADIO_MAPLE;
1163 	else
1164 		header->chip_type      = CFR_CAPTURE_RADIO_CYP;
1165 
1166 	header->pltform_type           = CFR_PLATFORM_TYPE_ARM;
1167 	header->Reserved               = 0;
1168 	header->u.meta_v3.status       = 0; /* failure */
1169 	header->u.meta_v3.length       = 0;
1170 
1171 	qdf_mem_copy(&header->u.meta_v3.peer_addr.su_peer_addr[0],
1172 		     &tx_evt_param->peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE);
1173 }
1174 
1175 /**
1176  * target_if_peer_capture_event() - WMI TX completion event for one-shot
1177  * capture
1178  * @sc: pointer to offload soc object
1179  * @data: WMI TX completion event buffer
1180  * @datalen: WMI Tx completion event buffer length
1181  *
1182  * Return: status
1183  */
1184 static int
1185 target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen)
1186 {
1187 	QDF_STATUS retval = 0;
1188 	struct wmi_unified *wmi_handle;
1189 	struct wlan_objmgr_psoc *psoc;
1190 	struct wlan_objmgr_pdev *pdev;
1191 	struct wlan_objmgr_vdev *vdev;
1192 	uint32_t cookie;
1193 	struct pdev_cfr *pcfr;
1194 	struct look_up_table *lut = NULL;
1195 	struct csi_cfr_header *header = NULL;
1196 	struct csi_cfr_header header_error = {0};
1197 	wmi_cfr_peer_tx_event_param tx_evt_param = {0};
1198 	qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0;
1199 	int status;
1200 	struct wlan_channel *bss_chan;
1201 	struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL;
1202 	struct wlan_lmac_if_rx_ops *rx_ops;
1203 	uint32_t target_type;
1204 
1205 	if (!sc || !data) {
1206 		cfr_err("sc or data is null");
1207 		return -EINVAL;
1208 	}
1209 
1210 	psoc = target_if_get_psoc_from_scn_hdl(sc);
1211 	if (!psoc) {
1212 		cfr_err("psoc is null");
1213 		return -EINVAL;
1214 	}
1215 
1216 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
1217 	if (!rx_ops) {
1218 		cfr_err("rx_ops is NULL");
1219 		return -EINVAL;
1220 	}
1221 	cfr_rx_ops = &rx_ops->cfr_rx_ops;
1222 
1223 	retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID);
1224 	if (QDF_IS_STATUS_ERROR(retval)) {
1225 		cfr_err("unable to get psoc reference");
1226 		return -EINVAL;
1227 	}
1228 
1229 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
1230 	if (!wmi_handle) {
1231 		cfr_err("wmi_handle is null");
1232 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1233 		return -EINVAL;
1234 	}
1235 
1236 	retval = wmi_extract_cfr_peer_tx_event_param(wmi_handle, data,
1237 						     &tx_evt_param);
1238 
1239 	if (retval != QDF_STATUS_SUCCESS) {
1240 		cfr_err("Failed to extract cfr tx event param");
1241 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1242 		return -EINVAL;
1243 	}
1244 
1245 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_evt_param.vdev_id,
1246 						    WLAN_CFR_ID);
1247 	if (!vdev) {
1248 		cfr_err("vdev is null");
1249 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1250 		return -EINVAL;
1251 	}
1252 
1253 	pdev = wlan_vdev_get_pdev(vdev);
1254 	if (!pdev) {
1255 		cfr_err("pdev is null");
1256 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1257 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
1258 		return -EINVAL;
1259 	}
1260 
1261 	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
1262 	if (retval != QDF_STATUS_SUCCESS) {
1263 		cfr_err("failed to get pdev reference");
1264 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1265 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
1266 		return -EINVAL;
1267 	}
1268 
1269 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1270 						     WLAN_UMAC_COMP_CFR);
1271 	if (!pcfr) {
1272 		cfr_err("pdev object for CFR is NULL");
1273 		retval = -EINVAL;
1274 		goto relref;
1275 	}
1276 
1277 	target_type = target_if_cfr_get_target_type(psoc);
1278 
1279 	if (tx_evt_param.status & PEER_CFR_CAPTURE_EVT_PS_STATUS_MASK) {
1280 		cfr_err("CFR capture failed as peer is in powersave: "
1281 			QDF_MAC_ADDR_FMT,
1282 			QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes));
1283 
1284 		enh_prepare_cfr_header_txstatus(&tx_evt_param,
1285 						&header_error,
1286 						target_type);
1287 		if (cfr_rx_ops->cfr_info_send)
1288 			cfr_rx_ops->cfr_info_send(pdev,
1289 						  &header_error,
1290 						  sizeof(struct
1291 							 csi_cfr_header),
1292 						  NULL, 0, &end_magic, 4);
1293 
1294 		retval = -EINVAL;
1295 		goto relref;
1296 	}
1297 
1298 	if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_STATUS_MASK) == 0) {
1299 		cfr_debug("CFR capture failed for peer: " QDF_MAC_ADDR_FMT,
1300 			  QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes));
1301 		pcfr->tx_peer_status_cfr_fail++;
1302 		retval = -EINVAL;
1303 		goto relref;
1304 	}
1305 
1306 	if (tx_evt_param.status & CFR_TX_EVT_STATUS_MASK) {
1307 		cfr_debug("TX packet returned status %d for peer: "
1308 			  QDF_MAC_ADDR_FMT,
1309 			  tx_evt_param.status & CFR_TX_EVT_STATUS_MASK,
1310 			  QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes));
1311 		pcfr->tx_evt_status_cfr_fail++;
1312 		retval = -EINVAL;
1313 		goto relref;
1314 	}
1315 
1316 	buf_addr_temp = (tx_evt_param.correlation_info_2 & 0x0f);
1317 	buf_addr = (tx_evt_param.correlation_info_1 |
1318 		    ((uint64_t)buf_addr_temp << 32));
1319 
1320 	if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr,
1321 					&cookie, 0)) {
1322 		cfr_debug("Cookie lookup failure for addr: 0x%pK status: 0x%x",
1323 			  (void *)((uintptr_t)buf_addr), tx_evt_param.status);
1324 		pcfr->tx_dbr_cookie_lookup_fail++;
1325 		retval = -EINVAL;
1326 		goto relref;
1327 	}
1328 
1329 	cfr_debug("buffer address: 0x%pK cookie: %u",
1330 		  (void *)((uintptr_t)buf_addr), cookie);
1331 
1332 	dump_cfr_peer_tx_event_enh(&tx_evt_param, cookie);
1333 
1334 	qdf_spin_lock_bh(&pcfr->lut_lock);
1335 
1336 	lut = get_lut_entry(pcfr, cookie);
1337 	if (!lut) {
1338 		cfr_err("lut is NULL\n");
1339 		retval = -EINVAL;
1340 		goto unlock;
1341 	}
1342 
1343 	pcfr->tx_evt_cnt++;
1344 	pcfr->total_tx_evt_cnt++;
1345 
1346 	lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16);
1347 	lut->tx_address1 = tx_evt_param.correlation_info_1;
1348 	lut->tx_address2 = tx_evt_param.correlation_info_2;
1349 	lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get());
1350 
1351 	header = &lut->header;
1352 	header->start_magic_num        = 0xDEADBEAF;
1353 	header->vendorid               = 0x8cfdf0;
1354 	header->cfr_metadata_version   = CFR_META_VERSION_3;
1355 	header->cfr_data_version       = CFR_DATA_VERSION_1;
1356 
1357 	if (target_type == TARGET_TYPE_QCN9000)
1358 		header->chip_type      = CFR_CAPTURE_RADIO_PINE;
1359 	else if (target_type == TARGET_TYPE_QCA5018)
1360 		header->chip_type      = CFR_CAPTURE_RADIO_MAPLE;
1361 	else
1362 		header->chip_type      = CFR_CAPTURE_RADIO_CYP;
1363 
1364 	header->pltform_type           = CFR_PLATFORM_TYPE_ARM;
1365 	header->Reserved               = 0;
1366 	header->u.meta_v3.status       = (tx_evt_param.status &
1367 					  PEER_CFR_CAPTURE_EVT_STATUS_MASK) ?
1368 					  1 : 0;
1369 	header->u.meta_v3.capture_bw   = tx_evt_param.bandwidth;
1370 
1371 	bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
1372 	header->u.meta_v3.phy_mode     = bss_chan->ch_phymode;
1373 
1374 	header->u.meta_v3.prim20_chan  = tx_evt_param.primary_20mhz_chan;
1375 	header->u.meta_v3.center_freq1 = tx_evt_param.band_center_freq1;
1376 	header->u.meta_v3.center_freq2 = tx_evt_param.band_center_freq2;
1377 
1378 	/* Currently CFR data is captured on ACK of a Qos NULL frame.
1379 	 * For 20 MHz, ACK is Legacy and for 40/80/160, ACK is DUP Legacy.
1380 	 */
1381 	header->u.meta_v3.capture_mode = tx_evt_param.bandwidth ?
1382 		CFR_DUP_LEGACY_ACK : CFR_LEGACY_ACK;
1383 	header->u.meta_v3.capture_type = tx_evt_param.capture_method;
1384 	header->u.meta_v3.num_rx_chain = wlan_vdev_mlme_get_rxchainmask(vdev);
1385 	header->u.meta_v3.sts_count    = tx_evt_param.spatial_streams;
1386 	header->u.meta_v3.timestamp    = tx_evt_param.timestamp_us;
1387 
1388 	qdf_mem_copy(&header->u.meta_v3.peer_addr.su_peer_addr[0],
1389 		     &tx_evt_param.peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE);
1390 	qdf_mem_copy(&header->u.meta_v3.chain_rssi[0],
1391 		     &tx_evt_param.chain_rssi[0],
1392 		     HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_rssi[0]));
1393 	qdf_mem_copy(&header->u.meta_v3.chain_phase[0],
1394 		     &tx_evt_param.chain_phase[0],
1395 		     HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_phase[0]));
1396 
1397 	status = correlate_and_relay_enh(pdev, cookie, lut,
1398 					 CORRELATE_TX_EV_MODULE_ID);
1399 	if (status == STATUS_STREAM_AND_RELEASE) {
1400 		if (cfr_rx_ops->cfr_info_send)
1401 			status = cfr_rx_ops->cfr_info_send(pdev,
1402 							   &lut->header,
1403 							   sizeof(
1404 							   struct
1405 							   csi_cfr_header),
1406 							   lut->data,
1407 							   lut->data_len,
1408 							   &end_magic, 4);
1409 		dump_metadata(header, cookie);
1410 		release_lut_entry_enh(pdev, lut);
1411 		target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr,
1412 					  cookie, 0);
1413 	} else {
1414 		retval = -EINVAL;
1415 	}
1416 
1417 unlock:
1418 	qdf_spin_unlock_bh(&pcfr->lut_lock);
1419 relref:
1420 
1421 	wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
1422 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
1423 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
1424 
1425 	return retval;
1426 }
1427 #else
1428 static int
1429 target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen)
1430 {
1431 	return 0;
1432 }
1433 #endif
1434 
1435 /**
1436  * target_if_register_tx_completion_enh_event_handler() - Register callback for
1437  * WMI TX completion event
1438  * @psoc: PSOC object
1439  *
1440  * Return: Success/Failure status
1441  */
1442 static QDF_STATUS
1443 target_if_register_tx_completion_enh_event_handler(struct wlan_objmgr_psoc
1444 						   *psoc)
1445 {
1446 	/* Register completion handler here */
1447 	wmi_unified_t wmi_hdl;
1448 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1449 
1450 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
1451 	if (!wmi_hdl) {
1452 		cfr_err("Unable to get wmi handle");
1453 		return QDF_STATUS_E_NULL_VALUE;
1454 	}
1455 
1456 	ret = wmi_unified_register_event_handler(wmi_hdl,
1457 						 wmi_peer_cfr_capture_event_id,
1458 						 target_if_peer_capture_event,
1459 						 WMI_RX_UMAC_CTX);
1460 	/*
1461 	 * Event registration is called per pdev
1462 	 * Ignore erorr if event is alreday registred.
1463 	 */
1464 	if (ret == QDF_STATUS_E_FAILURE)
1465 		ret = QDF_STATUS_SUCCESS;
1466 
1467 	return ret;
1468 }
1469 
1470 /**
1471  * target_if_unregister_tx_completion_enh_event_handler() - Unregister callback
1472  * for WMI TX completion event
1473  * @psoc: PSOC object
1474  *
1475  * Return: Success/Failure status
1476  */
1477 static QDF_STATUS
1478 target_if_unregister_tx_completion_enh_event_handler(struct wlan_objmgr_psoc
1479 						     *psoc)
1480 {
1481 	/* Unregister completion handler here */
1482 	wmi_unified_t wmi_hdl;
1483 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1484 
1485 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
1486 	if (!wmi_hdl) {
1487 		cfr_err("Unable to get wmi handle");
1488 		return QDF_STATUS_E_NULL_VALUE;
1489 	}
1490 
1491 	status = wmi_unified_unregister_event(wmi_hdl,
1492 					      wmi_peer_cfr_capture_event_id);
1493 	return status;
1494 }
1495 
1496 /**
1497  * lut_ageout_timer_task() - Timer to flush pending TXRX/DBR events
1498  *
1499  * Return: none
1500  */
1501 static os_timer_func(lut_ageout_timer_task)
1502 {
1503 	int i = 0;
1504 	struct pdev_cfr *pcfr = NULL;
1505 	struct wlan_objmgr_pdev *pdev = NULL;
1506 	struct look_up_table *lut = NULL;
1507 	uint64_t diff, cur_tstamp;
1508 	uint8_t srng_id = 0;
1509 
1510 	OS_GET_TIMER_ARG(pcfr, struct pdev_cfr*);
1511 
1512 	if (!pcfr) {
1513 		cfr_err("pdev object for CFR is null");
1514 		return;
1515 	}
1516 
1517 	pdev = pcfr->pdev_obj;
1518 	if (!pdev) {
1519 		cfr_err("pdev is null");
1520 		return;
1521 	}
1522 
1523 	srng_id = pcfr->rcc_param.srng_id;
1524 	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID)
1525 	    != QDF_STATUS_SUCCESS) {
1526 		cfr_err("failed to get pdev reference");
1527 		return;
1528 	}
1529 
1530 	cur_tstamp = qdf_ktime_to_ms(qdf_ktime_get());
1531 
1532 	qdf_spin_lock_bh(&pcfr->lut_lock);
1533 
1534 	for (i = 0; i < pcfr->lut_num; i++) {
1535 		lut = get_lut_entry(pcfr, i);
1536 		if (!lut)
1537 			continue;
1538 
1539 		if (lut->dbr_recv && !lut->tx_recv) {
1540 			diff = cur_tstamp - lut->dbr_tstamp;
1541 			if (diff > LUT_AGE_THRESHOLD) {
1542 				target_if_dbr_buf_release(pdev, DBR_MODULE_CFR,
1543 							  lut->dbr_address,
1544 							  i, srng_id);
1545 				pcfr->flush_timeout_dbr_cnt++;
1546 				release_lut_entry_enh(pdev, lut);
1547 			}
1548 		}
1549 	}
1550 
1551 	qdf_spin_unlock_bh(&pcfr->lut_lock);
1552 
1553 	if (pcfr->lut_timer_init)
1554 		qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER);
1555 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
1556 }
1557 
1558 /**
1559  * target_if_cfr_start_lut_age_timer() - Start timer to flush aged-out LUT
1560  * entries
1561  * @pdev: pointer to pdev object
1562  *
1563  * Return: None
1564  */
1565 void target_if_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
1566 {
1567 	struct pdev_cfr *pcfr;
1568 
1569 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1570 						     WLAN_UMAC_COMP_CFR);
1571 	if (pcfr->lut_timer_init)
1572 		qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER);
1573 }
1574 
1575 /**
1576  * target_if_cfr_stop_lut_age_timer() - Stop timer to flush aged-out LUT
1577  * entries
1578  * @pdev: pointer to pdev object
1579  *
1580  * Return: None
1581  */
1582 void target_if_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
1583 {
1584 	struct pdev_cfr *pcfr;
1585 
1586 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1587 						     WLAN_UMAC_COMP_CFR);
1588 	if (pcfr->lut_timer_init)
1589 		qdf_timer_stop(&pcfr->lut_age_timer);
1590 }
1591 
1592 /**
1593  * target_if_cfr_update_global_cfg() - Update global config after a successful
1594  * commit
1595  * @pdev: pointer to pdev object
1596  *
1597  * Return: None
1598  */
1599 void target_if_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev)
1600 {
1601 	int grp_id;
1602 	struct pdev_cfr *pcfr;
1603 	struct ta_ra_cfr_cfg *curr_cfg = NULL;
1604 	struct ta_ra_cfr_cfg *glbl_cfg = NULL;
1605 
1606 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1607 						     WLAN_UMAC_COMP_CFR);
1608 
1609 	for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
1610 		if (qdf_test_bit(grp_id,
1611 				 &pcfr->rcc_param.modified_in_curr_session)) {
1612 			/* Populating global config based on user's input */
1613 			glbl_cfg = &pcfr->global[grp_id];
1614 			curr_cfg = &pcfr->rcc_param.curr[grp_id];
1615 
1616 			if (curr_cfg->valid_ta)
1617 				qdf_mem_copy(glbl_cfg->tx_addr,
1618 					     curr_cfg->tx_addr,
1619 					     QDF_MAC_ADDR_SIZE);
1620 
1621 			if (curr_cfg->valid_ra)
1622 				qdf_mem_copy(glbl_cfg->rx_addr,
1623 					     curr_cfg->rx_addr,
1624 					     QDF_MAC_ADDR_SIZE);
1625 
1626 			if (curr_cfg->valid_ta_mask)
1627 				qdf_mem_copy(glbl_cfg->tx_addr_mask,
1628 					     curr_cfg->tx_addr_mask,
1629 					     QDF_MAC_ADDR_SIZE);
1630 
1631 			if (curr_cfg->valid_ra_mask)
1632 				qdf_mem_copy(glbl_cfg->rx_addr_mask,
1633 					     curr_cfg->rx_addr_mask,
1634 					     QDF_MAC_ADDR_SIZE);
1635 
1636 			if (curr_cfg->valid_bw_mask)
1637 				glbl_cfg->bw = curr_cfg->bw;
1638 
1639 			if (curr_cfg->valid_nss_mask)
1640 				glbl_cfg->nss = curr_cfg->nss;
1641 
1642 			if (curr_cfg->valid_mgmt_subtype)
1643 				glbl_cfg->mgmt_subtype_filter =
1644 					curr_cfg->mgmt_subtype_filter;
1645 
1646 			if (curr_cfg->valid_ctrl_subtype)
1647 				glbl_cfg->ctrl_subtype_filter =
1648 					curr_cfg->ctrl_subtype_filter;
1649 
1650 			if (curr_cfg->valid_data_subtype)
1651 				glbl_cfg->data_subtype_filter =
1652 					curr_cfg->data_subtype_filter;
1653 		}
1654 	}
1655 }
1656 
1657 /**
1658  * cfr_enh_init_pdev() - Inits cfr pdev and registers necessary handlers.
1659  * @psoc: pointer to psoc object
1660  * @pdev: pointer to pdev object
1661  *
1662  * Return: Registration status for necessary handlers
1663  */
1664 QDF_STATUS cfr_enh_init_pdev(struct wlan_objmgr_psoc *psoc,
1665 			     struct wlan_objmgr_pdev *pdev)
1666 {
1667 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1668 	struct pdev_cfr *pcfr;
1669 	uint32_t target_type;
1670 	struct psoc_cfr *cfr_sc;
1671 
1672 	if (!pdev) {
1673 		cfr_err("PDEV is NULL!");
1674 		return QDF_STATUS_E_NULL_VALUE;
1675 	}
1676 
1677 	if (!psoc) {
1678 		cfr_err("PSOC is NULL");
1679 		return QDF_STATUS_E_NULL_VALUE;
1680 	}
1681 
1682 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1683 						     WLAN_UMAC_COMP_CFR);
1684 	if (!pcfr) {
1685 		cfr_err("pcfr is NULL!");
1686 		return QDF_STATUS_E_NULL_VALUE;
1687 	}
1688 
1689 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
1690 						       WLAN_UMAC_COMP_CFR);
1691 
1692 	if (!cfr_sc) {
1693 		cfr_err("cfr_sc is NULL");
1694 		return QDF_STATUS_E_NULL_VALUE;
1695 	}
1696 
1697 	target_type = target_if_cfr_get_target_type(psoc);
1698 
1699 #if DIRECT_BUF_RX_ENABLE
1700 	status = target_if_register_to_dbr_enh(pdev);
1701 	if (status != QDF_STATUS_SUCCESS) {
1702 		cfr_err("Failed to register with dbr");
1703 		return status;
1704 	}
1705 #endif
1706 
1707 	status = target_if_register_tx_completion_enh_event_handler(psoc);
1708 	if (status != QDF_STATUS_SUCCESS) {
1709 		cfr_err("Failed to register with tx event handler");
1710 		return status;
1711 	}
1712 
1713 	pcfr->is_cfr_rcc_capable = 1;
1714 	pcfr->rcc_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1715 	pcfr->rcc_param.modified_in_curr_session = MAX_RESET_CFG_ENTRY;
1716 	pcfr->rcc_param.num_grp_tlvs = MAX_TA_RA_ENTRIES;
1717 	pcfr->rcc_param.vdev_id = CFR_INVALID_VDEV_ID;
1718 	pcfr->rcc_param.srng_id = DEFAULT_SRNGID_CFR;
1719 	pcfr->is_cap_interval_mode_sel_support =
1720 				cfr_sc->is_cap_interval_mode_sel_support;
1721 	pcfr->is_mo_marking_support = cfr_sc->is_mo_marking_support;
1722 
1723 	target_if_cfr_default_ta_ra_config(&pcfr->rcc_param,
1724 					   true, MAX_RESET_CFG_ENTRY);
1725 
1726 	status = target_if_cfr_config_rcc(pdev, &pcfr->rcc_param);
1727 	if (status == QDF_STATUS_SUCCESS) {
1728 		/* Update global configuration */
1729 		target_if_cfr_update_global_cfg(pdev);
1730 	} else {
1731 		cfr_err("Sending WMI to configure default has failed");
1732 		return status;
1733 	}
1734 
1735 	pcfr->rcc_param.modified_in_curr_session = 0;
1736 
1737 	pcfr->cfr_max_sta_count = MAX_CFR_ENABLED_CLIENTS;
1738 
1739 	if (target_type == TARGET_TYPE_QCN9000) {
1740 		pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_PINE;
1741 		pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_PINE;
1742 		pcfr->chip_type = CFR_CAPTURE_RADIO_PINE;
1743 		pcfr->max_mu_users = PINE_CFR_MU_USERS;
1744 	} else if (target_type == TARGET_TYPE_QCA5018) {
1745 		pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_MAPLE;
1746 		pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_MAPLE;
1747 		pcfr->chip_type = CFR_CAPTURE_RADIO_MAPLE;
1748 		pcfr->max_mu_users = MAPLE_CFR_MU_USERS;
1749 	} else {
1750 		pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_CYP;
1751 		pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_CYP;
1752 		pcfr->chip_type = CFR_CAPTURE_RADIO_CYP;
1753 		pcfr->max_mu_users = CYP_CFR_MU_USERS;
1754 	}
1755 
1756 	if (!pcfr->lut_timer_init) {
1757 		qdf_timer_init(NULL,
1758 			       &(pcfr->lut_age_timer),
1759 			       lut_ageout_timer_task, (void *)pcfr,
1760 			       QDF_TIMER_TYPE_WAKE_APPS);
1761 		pcfr->lut_timer_init = 1;
1762 	}
1763 
1764 	qdf_spinlock_create(&pcfr->lut_lock);
1765 
1766 	return status;
1767 }
1768 
1769 /**
1770  * cfr_enh_deinit_pdev() - De-inits corresponding pdev and handlers.
1771  * @psoc: pointer to psoc object
1772  * @pdev: pointer to pdev object
1773  *
1774  * Return: De-registration status for necessary handlers
1775  */
1776 QDF_STATUS cfr_enh_deinit_pdev(struct wlan_objmgr_psoc *psoc,
1777 			       struct wlan_objmgr_pdev *pdev)
1778 {
1779 	QDF_STATUS status;
1780 	struct pdev_cfr *pcfr;
1781 
1782 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1783 						     WLAN_UMAC_COMP_CFR);
1784 	if (!pcfr) {
1785 		cfr_err("pcfr is NULL");
1786 		return QDF_STATUS_E_NULL_VALUE;
1787 	}
1788 
1789 	if (pcfr->lut_timer_init) {
1790 		qdf_timer_stop(&pcfr->lut_age_timer);
1791 		qdf_timer_free(&(pcfr->lut_age_timer));
1792 		pcfr->lut_timer_init = 0;
1793 	}
1794 
1795 	pcfr->tx_evt_cnt = 0;
1796 	pcfr->dbr_evt_cnt = 0;
1797 	pcfr->release_cnt = 0;
1798 	pcfr->total_tx_evt_cnt = 0;
1799 	pcfr->rx_tlv_evt_cnt = 0;
1800 	pcfr->flush_dbr_cnt = 0;
1801 	pcfr->flush_timeout_dbr_cnt = 0;
1802 	pcfr->invalid_dma_length_cnt = 0;
1803 	pcfr->clear_txrx_event = 0;
1804 	pcfr->cfr_dma_aborts = 0;
1805 	pcfr->tx_peer_status_cfr_fail = 0;
1806 	pcfr->tx_evt_status_cfr_fail = 0;
1807 	pcfr->tx_dbr_cookie_lookup_fail = 0;
1808 	qdf_mem_zero(&pcfr->rcc_param, sizeof(struct cfr_rcc_param));
1809 	qdf_mem_zero(&pcfr->global, (sizeof(struct ta_ra_cfr_cfg) *
1810 				     MAX_TA_RA_ENTRIES));
1811 	pcfr->cfr_timer_enable = 0;
1812 
1813 #ifdef DIRECT_BUF_RX_ENABLE
1814 	status = target_if_unregister_to_dbr_enh(pdev);
1815 	if (status != QDF_STATUS_SUCCESS)
1816 		cfr_err("Failed to register with dbr");
1817 #endif
1818 
1819 	status = target_if_unregister_tx_completion_enh_event_handler(psoc);
1820 	if (status != QDF_STATUS_SUCCESS)
1821 		cfr_err("Failed to register with dbr");
1822 
1823 	qdf_spinlock_destroy(&pcfr->lut_lock);
1824 
1825 	return status;
1826 }
1827