xref: /wlan-driver/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_dbr.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name #include <target_if_cfr.h>
21*5113495bSYour Name #include <wlan_tgt_def_config.h>
22*5113495bSYour Name #include <target_type.h>
23*5113495bSYour Name #include <hif_hw_version.h>
24*5113495bSYour Name #include <ol_if_athvar.h>
25*5113495bSYour Name #include <target_if.h>
26*5113495bSYour Name #include <wlan_lmac_if_def.h>
27*5113495bSYour Name #include <wlan_osif_priv.h>
28*5113495bSYour Name #include <init_deinit_lmac.h>
29*5113495bSYour Name #include <wlan_cfr_utils_api.h>
30*5113495bSYour Name #include <target_if_cfr_dbr.h>
31*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
32*5113495bSYour Name #include <target_if_direct_buf_rx_api.h>
33*5113495bSYour Name #endif
34*5113495bSYour Name 
35*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
36*5113495bSYour Name static u_int32_t end_magic = 0xBEAFDEAD;
37*5113495bSYour Name 
38*5113495bSYour Name /**
39*5113495bSYour Name  * dump_lut() - dump all valid lut entries
40*5113495bSYour Name  * @pdev: objmgr pdev
41*5113495bSYour Name  *
42*5113495bSYour Name  * return: none
43*5113495bSYour Name  */
dump_lut(struct wlan_objmgr_pdev * pdev)44*5113495bSYour Name static int dump_lut(struct wlan_objmgr_pdev *pdev)
45*5113495bSYour Name {
46*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
47*5113495bSYour Name 	struct look_up_table *lut = NULL;
48*5113495bSYour Name 	int i = 0;
49*5113495bSYour Name 
50*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
51*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
52*5113495bSYour Name 	if (!pdev_cfrobj) {
53*5113495bSYour Name 		cfr_err("pdev object for CFR is null");
54*5113495bSYour Name 		return -EINVAL;
55*5113495bSYour Name 	}
56*5113495bSYour Name 
57*5113495bSYour Name 	for (i = 0; i < pdev_cfrobj->lut_num; i++) {
58*5113495bSYour Name 		lut = pdev_cfrobj->lut[i];
59*5113495bSYour Name 		cfr_info("idx:%d dbrevnt: %d txevent: %d dbrppdu:0x%x txppdu:0x%x",
60*5113495bSYour Name 			 i, lut->dbr_recv, lut->tx_recv,
61*5113495bSYour Name 			 lut->dbr_ppdu_id, lut->tx_ppdu_id);
62*5113495bSYour Name 	}
63*5113495bSYour Name 
64*5113495bSYour Name 	return 0;
65*5113495bSYour Name }
66*5113495bSYour Name 
67*5113495bSYour Name /**
68*5113495bSYour Name  * dump_dma_hdr() - Dump DMA header populated by uCode
69*5113495bSYour Name  * @dma_hdr: pointer to the DMA header
70*5113495bSYour Name  * @error: Indicates whether it is an error
71*5113495bSYour Name  *
72*5113495bSYour Name  * Return: none
73*5113495bSYour Name  */
dump_dma_hdr(struct whal_cfir_dma_hdr * dma_hdr,int error)74*5113495bSYour Name static void dump_dma_hdr(struct whal_cfir_dma_hdr *dma_hdr, int error)
75*5113495bSYour Name {
76*5113495bSYour Name 	if (!error) {
77*5113495bSYour Name 		cfr_debug("Tag: 0x%02x Length: %d udone: %d ctype: %d preamble: %d",
78*5113495bSYour Name 			  dma_hdr->tag, dma_hdr->length, dma_hdr->upload_done,
79*5113495bSYour Name 			  dma_hdr->capture_type, dma_hdr->preamble_type);
80*5113495bSYour Name 
81*5113495bSYour Name 		cfr_debug("Nss: %d num_chains: %d bw: %d", dma_hdr->nss,
82*5113495bSYour Name 			  dma_hdr->num_chains, dma_hdr->upload_pkt_bw);
83*5113495bSYour Name 
84*5113495bSYour Name 		cfr_debug("peervalid: %d peer_id: %d ppdu_id: 0x%04x",
85*5113495bSYour Name 			  dma_hdr->sw_peer_id_valid, dma_hdr->sw_peer_id,
86*5113495bSYour Name 			  dma_hdr->phy_ppdu_id);
87*5113495bSYour Name 	} else {
88*5113495bSYour Name 		cfr_err("Tag: 0x%02x Length: %d udone: %d ctype: %d preamble: %d",
89*5113495bSYour Name 			dma_hdr->tag, dma_hdr->length, dma_hdr->upload_done,
90*5113495bSYour Name 			dma_hdr->capture_type,	dma_hdr->preamble_type);
91*5113495bSYour Name 
92*5113495bSYour Name 		cfr_err("Nss: %d num_chains: %d bw: %d", dma_hdr->nss,
93*5113495bSYour Name 			dma_hdr->num_chains, dma_hdr->upload_pkt_bw);
94*5113495bSYour Name 
95*5113495bSYour Name 		cfr_err("peervalid: %d peer_id: %d ppdu_id: 0x%04x",
96*5113495bSYour Name 			dma_hdr->sw_peer_id_valid, dma_hdr->sw_peer_id,
97*5113495bSYour Name 			dma_hdr->phy_ppdu_id);
98*5113495bSYour Name 	}
99*5113495bSYour Name }
100*5113495bSYour Name 
101*5113495bSYour Name /**
102*5113495bSYour Name  * compute_length() - Compute the number of tones based on BW
103*5113495bSYour Name  * @dma_hdr: DMA header from uCode
104*5113495bSYour Name  *
105*5113495bSYour Name  * Return: Computed number of tones based on BW
106*5113495bSYour Name  */
compute_length(struct whal_cfir_dma_hdr * dma_hdr)107*5113495bSYour Name static int compute_length(struct whal_cfir_dma_hdr *dma_hdr)
108*5113495bSYour Name {
109*5113495bSYour Name 	uint8_t bw = dma_hdr->upload_pkt_bw;
110*5113495bSYour Name 	uint8_t preamble = dma_hdr->preamble_type;
111*5113495bSYour Name 
112*5113495bSYour Name 	switch (preamble) {
113*5113495bSYour Name 	case 0:
114*5113495bSYour Name 	case 2:
115*5113495bSYour Name 		switch (bw) {
116*5113495bSYour Name 		case 0:
117*5113495bSYour Name 			return TONES_IN_20MHZ;
118*5113495bSYour Name 		case 1: /* DUP40/VHT40 */
119*5113495bSYour Name 			return TONES_IN_40MHZ;
120*5113495bSYour Name 		case 2: /* DUP80/VHT80 */
121*5113495bSYour Name 			return TONES_IN_80MHZ;
122*5113495bSYour Name 		case 3: /* DUP160/VHT160 */
123*5113495bSYour Name 			return TONES_IN_160MHZ;
124*5113495bSYour Name 		}
125*5113495bSYour Name 
126*5113495bSYour Name 	case 1:
127*5113495bSYour Name 		switch (bw) {
128*5113495bSYour Name 		case 0:
129*5113495bSYour Name 			return TONES_IN_20MHZ;
130*5113495bSYour Name 		case 1:
131*5113495bSYour Name 			return TONES_IN_40MHZ;
132*5113495bSYour Name 		}
133*5113495bSYour Name 	}
134*5113495bSYour Name 
135*5113495bSYour Name 	return TONES_INVALID;
136*5113495bSYour Name }
137*5113495bSYour Name 
138*5113495bSYour Name /**
139*5113495bSYour Name  * release_lut_entry() - Clear all params in an LUT entry
140*5113495bSYour Name  * @pdev: objmgr PDEV
141*5113495bSYour Name  * @lut: pointer to LUT
142*5113495bSYour Name  *
143*5113495bSYour Name  * Return: status
144*5113495bSYour Name  */
release_lut_entry(struct wlan_objmgr_pdev * pdev,struct look_up_table * lut)145*5113495bSYour Name static int release_lut_entry(struct wlan_objmgr_pdev *pdev,
146*5113495bSYour Name 			     struct look_up_table *lut)
147*5113495bSYour Name {
148*5113495bSYour Name 	lut->dbr_recv = false;
149*5113495bSYour Name 	lut->tx_recv = false;
150*5113495bSYour Name 	lut->data = NULL;
151*5113495bSYour Name 	lut->data_len = 0;
152*5113495bSYour Name 	lut->dbr_ppdu_id = 0;
153*5113495bSYour Name 	lut->tx_ppdu_id = 0;
154*5113495bSYour Name 	qdf_mem_zero(&lut->header, sizeof(struct csi_cfr_header));
155*5113495bSYour Name 
156*5113495bSYour Name 	return 0;
157*5113495bSYour Name }
158*5113495bSYour Name 
159*5113495bSYour Name /**
160*5113495bSYour Name  * correlate_and_relay() - Correlate TXRX and DBR events and stream CFR data to
161*5113495bSYour Name  * userspace
162*5113495bSYour Name  * @pdev: objmgr PDEV
163*5113495bSYour Name  * @cookie: Index into lookup table
164*5113495bSYour Name  * @lut: pointer to lookup table
165*5113495bSYour Name  * @module_id: ID of the event received
166*5113495bSYour Name  *  0 - DBR event
167*5113495bSYour Name  *  1 - TXRX event
168*5113495bSYour Name  *
169*5113495bSYour Name  * Return:
170*5113495bSYour Name  *  - STATUS_ERROR
171*5113495bSYour Name  *  - STATUS_HOLD
172*5113495bSYour Name  *  - STATUS_STREAM_AND_RELEASE
173*5113495bSYour Name  */
correlate_and_relay(struct wlan_objmgr_pdev * pdev,uint32_t cookie,struct look_up_table * lut,uint8_t module_id)174*5113495bSYour Name static int correlate_and_relay(struct wlan_objmgr_pdev *pdev, uint32_t cookie,
175*5113495bSYour Name 			       struct look_up_table *lut, uint8_t module_id)
176*5113495bSYour Name {
177*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
178*5113495bSYour Name 	int status = STATUS_ERROR;
179*5113495bSYour Name 
180*5113495bSYour Name 	if (module_id > 1) {
181*5113495bSYour Name 		cfr_err("Received request with invalid mod id. Investigate!!");
182*5113495bSYour Name 		QDF_ASSERT(0);
183*5113495bSYour Name 		return status;
184*5113495bSYour Name 	}
185*5113495bSYour Name 
186*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
187*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
188*5113495bSYour Name 
189*5113495bSYour Name 	if (module_id == CORRELATE_TX_EV_MODULE_ID) {
190*5113495bSYour Name 		pdev_cfrobj->tx_evt_cnt++;
191*5113495bSYour Name 		lut->tx_recv = true;
192*5113495bSYour Name 	} else if (module_id == CORRELATE_DBR_MODULE_ID) {
193*5113495bSYour Name 		pdev_cfrobj->dbr_evt_cnt++;
194*5113495bSYour Name 		lut->dbr_recv = true;
195*5113495bSYour Name 	}
196*5113495bSYour Name 
197*5113495bSYour Name 	if (lut->dbr_recv && lut->tx_recv) {
198*5113495bSYour Name 		if (lut->dbr_ppdu_id == lut->tx_ppdu_id) {
199*5113495bSYour Name 			pdev_cfrobj->release_cnt++;
200*5113495bSYour Name 			status = STATUS_STREAM_AND_RELEASE;
201*5113495bSYour Name 		} else {
202*5113495bSYour Name 			/*
203*5113495bSYour Name 			 * When there is a ppdu id mismatch, discard the other
204*5113495bSYour Name 			 * older event's data and wait hold for new event
205*5113495bSYour Name 			 */
206*5113495bSYour Name 			if (module_id == CORRELATE_TX_EV_MODULE_ID) {
207*5113495bSYour Name 				cfr_debug("Received new tx event for same cookie %u",
208*5113495bSYour Name 					  cookie);
209*5113495bSYour Name 				lut->dbr_recv = false;
210*5113495bSYour Name 				lut->data = NULL;
211*5113495bSYour Name 				lut->data_len = 0;
212*5113495bSYour Name 				lut->dbr_ppdu_id = 0;
213*5113495bSYour Name 				qdf_mem_zero(&lut->dbr_address,
214*5113495bSYour Name 					     sizeof(lut->dbr_address));
215*5113495bSYour Name 			} else if (module_id == CORRELATE_DBR_MODULE_ID) {
216*5113495bSYour Name 				cfr_debug("Received new dbr event for same cookie %u",
217*5113495bSYour Name 					  cookie);
218*5113495bSYour Name 				lut->tx_recv = false;
219*5113495bSYour Name 				lut->tx_ppdu_id = 0;
220*5113495bSYour Name 			}
221*5113495bSYour Name 
222*5113495bSYour Name 			/*
223*5113495bSYour Name 			 * This is condition can occur if DBR buffer did not get
224*5113495bSYour Name 			 * released, or leaked either by Host/Target.
225*5113495bSYour Name 			 * we may need to add recovery here.
226*5113495bSYour Name 			 *
227*5113495bSYour Name 			 * 1. Stop all captures
228*5113495bSYour Name 			 * 2. Flush/release DBR buffer and LUT
229*5113495bSYour Name 			 * 3. Start capture again
230*5113495bSYour Name 			 */
231*5113495bSYour Name 			if ((pdev_cfrobj->dbr_evt_cnt -
232*5113495bSYour Name 				pdev_cfrobj->release_cnt) >= MAX_LUT_ENTRIES) {
233*5113495bSYour Name 				cfr_err("cookie = %u dbr_cnt = %llu, release_cnt = %llu",
234*5113495bSYour Name 					cookie, pdev_cfrobj->dbr_evt_cnt,
235*5113495bSYour Name 					pdev_cfrobj->release_cnt);
236*5113495bSYour Name 				dump_lut(pdev);
237*5113495bSYour Name 				dump_dma_hdr(&lut->dma_hdr, 1);
238*5113495bSYour Name 				cfr_err("correlation_info1: 0x%08x correlation_info2 0x%08x",
239*5113495bSYour Name 					lut->tx_address1, lut->tx_address2);
240*5113495bSYour Name 			}
241*5113495bSYour Name 			status = STATUS_HOLD;
242*5113495bSYour Name 		}
243*5113495bSYour Name 	} else {
244*5113495bSYour Name 		status = STATUS_HOLD;
245*5113495bSYour Name 	}
246*5113495bSYour Name 
247*5113495bSYour Name 	return status;
248*5113495bSYour Name }
249*5113495bSYour Name 
250*5113495bSYour Name /**
251*5113495bSYour Name  * cfr_dbr_event_handler() - Process DBR event for CFR data DMA completion
252*5113495bSYour Name  * @pdev: PDEV object
253*5113495bSYour Name  * @payload: pointer to CFR data
254*5113495bSYour Name  *
255*5113495bSYour Name  * Return: status
256*5113495bSYour Name  */
cfr_dbr_event_handler(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_data * payload)257*5113495bSYour Name static bool cfr_dbr_event_handler(struct wlan_objmgr_pdev *pdev,
258*5113495bSYour Name 				  struct direct_buf_rx_data *payload)
259*5113495bSYour Name {
260*5113495bSYour Name 	uint8_t *data = NULL;
261*5113495bSYour Name 	uint32_t cookie = 0;
262*5113495bSYour Name 	struct whal_cfir_dma_hdr dma_hdr = {0};
263*5113495bSYour Name 	int  length = 8, tones = 0, status = 0;
264*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
265*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
266*5113495bSYour Name 	struct look_up_table *lut = NULL;
267*5113495bSYour Name 	struct csi_cfr_header *header = NULL;
268*5113495bSYour Name 	struct wlan_lmac_if_rx_ops *rx_ops;
269*5113495bSYour Name 	bool ret = true;
270*5113495bSYour Name 
271*5113495bSYour Name 	if ((!pdev) || (!payload)) {
272*5113495bSYour Name 		cfr_err("pdev or payload is null");
273*5113495bSYour Name 		return true;
274*5113495bSYour Name 	}
275*5113495bSYour Name 
276*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
277*5113495bSYour Name 	if (!psoc) {
278*5113495bSYour Name 		cfr_err("psoc is null");
279*5113495bSYour Name 		return true;
280*5113495bSYour Name 	}
281*5113495bSYour Name 
282*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
283*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
284*5113495bSYour Name 	if (!pdev_cfrobj) {
285*5113495bSYour Name 		cfr_err("pdev object for CFR is null");
286*5113495bSYour Name 		return true;
287*5113495bSYour Name 	}
288*5113495bSYour Name 
289*5113495bSYour Name 	data = payload->vaddr;
290*5113495bSYour Name 	cookie = payload->cookie;
291*5113495bSYour Name 
292*5113495bSYour Name 	cfr_debug("bufferaddr: 0x%pK cookie: %u",
293*5113495bSYour Name 		  (void *)((uintptr_t)payload->paddr), cookie);
294*5113495bSYour Name 	qdf_mem_copy(&dma_hdr, &data[0], sizeof(struct whal_cfir_dma_hdr));
295*5113495bSYour Name 
296*5113495bSYour Name 	dump_dma_hdr(&dma_hdr, 0);
297*5113495bSYour Name 	tones = compute_length(&dma_hdr);
298*5113495bSYour Name 	if (tones == TONES_INVALID) {
299*5113495bSYour Name 		cfr_err("Number of tones received is invalid. Investigate!");
300*5113495bSYour Name 		return true;
301*5113495bSYour Name 	}
302*5113495bSYour Name 
303*5113495bSYour Name 	length += tones * (dma_hdr.num_chains + 1);
304*5113495bSYour Name 
305*5113495bSYour Name 	lut = pdev_cfrobj->lut[cookie];
306*5113495bSYour Name 	lut->data = data;
307*5113495bSYour Name 	lut->data_len = length;
308*5113495bSYour Name 	lut->dbr_ppdu_id = dma_hdr.phy_ppdu_id;
309*5113495bSYour Name 	lut->dbr_address = payload->paddr;
310*5113495bSYour Name 	qdf_mem_copy(&lut->dma_hdr, &dma_hdr, sizeof(struct whal_cfir_dma_hdr));
311*5113495bSYour Name 
312*5113495bSYour Name 	header = &lut->header;
313*5113495bSYour Name 	header->u.meta_dbr.channel_bw = dma_hdr.upload_pkt_bw;
314*5113495bSYour Name 	header->u.meta_dbr.length = length;
315*5113495bSYour Name 	status = correlate_and_relay(pdev, cookie, lut,
316*5113495bSYour Name 				     CORRELATE_DBR_MODULE_ID);
317*5113495bSYour Name 	if (status == STATUS_STREAM_AND_RELEASE) {
318*5113495bSYour Name 		/*
319*5113495bSYour Name 		 * Message format
320*5113495bSYour Name 		 *  Meta data Header + actual payload + trailer
321*5113495bSYour Name 		 */
322*5113495bSYour Name 		rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
323*5113495bSYour Name 		if (!rx_ops) {
324*5113495bSYour Name 			cfr_err("rx_ops is NULL");
325*5113495bSYour Name 			return true;
326*5113495bSYour Name 		}
327*5113495bSYour Name 
328*5113495bSYour Name 		status = rx_ops->cfr_rx_ops.cfr_info_send
329*5113495bSYour Name 				(pdev, &lut->header,
330*5113495bSYour Name 				 sizeof(struct csi_cfr_header),
331*5113495bSYour Name 				 lut->data, lut->data_len,
332*5113495bSYour Name 				 &end_magic, 4);
333*5113495bSYour Name 		release_lut_entry(pdev, lut);
334*5113495bSYour Name 		cfr_debug("Data sent to upper layers, released look up table");
335*5113495bSYour Name 		ret = true;
336*5113495bSYour Name 	} else if (status == STATUS_HOLD) {
337*5113495bSYour Name 		cfr_debug("Tx event not received yet. Buffer is not released");
338*5113495bSYour Name 		ret = false;
339*5113495bSYour Name 	} else {
340*5113495bSYour Name 		cfr_err("Correlation returned invalid status!!");
341*5113495bSYour Name 		ret = true;
342*5113495bSYour Name 	}
343*5113495bSYour Name 
344*5113495bSYour Name 	return ret;
345*5113495bSYour Name }
346*5113495bSYour Name 
347*5113495bSYour Name /**
348*5113495bSYour Name  * dump_cfr_peer_tx_event() - Dump TX completion event
349*5113495bSYour Name  * @event: ptr to WMI TX completion event for QOS frames sent during
350*5113495bSYour Name  * one-shot capture.
351*5113495bSYour Name  *
352*5113495bSYour Name  * Return: none
353*5113495bSYour Name  */
dump_cfr_peer_tx_event(wmi_cfr_peer_tx_event_param * event)354*5113495bSYour Name static void dump_cfr_peer_tx_event(wmi_cfr_peer_tx_event_param *event)
355*5113495bSYour Name {
356*5113495bSYour Name 	cfr_debug("CFR capture method: %u vdev_id: %u mac: " QDF_MAC_ADDR_FMT,
357*5113495bSYour Name 		  event->capture_method, event->vdev_id,
358*5113495bSYour Name 		  QDF_MAC_ADDR_REF(&event->peer_mac_addr.bytes[0]));
359*5113495bSYour Name 
360*5113495bSYour Name 	cfr_debug("Chan: %u bw: %u phymode: %u cfreq1: %u cfrq2: %u nss: %u",
361*5113495bSYour Name 		  event->primary_20mhz_chan, event->bandwidth,
362*5113495bSYour Name 		  event->phy_mode, event->band_center_freq1,
363*5113495bSYour Name 		  event->band_center_freq2, event->spatial_streams);
364*5113495bSYour Name 
365*5113495bSYour Name 	cfr_debug("Correlation_info1: 0x%08x Correlation_info2: 0x%08x",
366*5113495bSYour Name 		  event->correlation_info_1, event->correlation_info_2);
367*5113495bSYour Name 
368*5113495bSYour Name 	cfr_debug("status: 0x%x ts: %u counter: %u rssi0: 0x%08x",
369*5113495bSYour Name 		  event->status, event->timestamp_us, event->counter,
370*5113495bSYour Name 		  event->chain_rssi[0]);
371*5113495bSYour Name 
372*5113495bSYour Name 	cfr_debug("phase0: 0x%04x phase1: 0x%04x phase2: 0x%04x phase3: 0x%04x\n"
373*5113495bSYour Name 		  "phase4: 0x%04x phase5: 0x%04x phase6: 0x%04x phase7: 0x%04x",
374*5113495bSYour Name 		  event->chain_phase[0], event->chain_phase[1],
375*5113495bSYour Name 		  event->chain_phase[2], event->chain_phase[3],
376*5113495bSYour Name 		  event->chain_phase[4], event->chain_phase[5],
377*5113495bSYour Name 		  event->chain_phase[6], event->chain_phase[7]);
378*5113495bSYour Name 
379*5113495bSYour Name 	cfr_debug("rtt_cfo_measurement: %d\n", event->cfo_measurement);
380*5113495bSYour Name 
381*5113495bSYour Name 	cfr_debug("rx_start_ts: %u\n", event->rx_start_ts);
382*5113495bSYour Name 
383*5113495bSYour Name 	cfr_debug("mcs_rate: %u\n", event->mcs_rate);
384*5113495bSYour Name 
385*5113495bSYour Name 	cfr_debug("gi_type: %u\n", event->gi_type);
386*5113495bSYour Name 
387*5113495bSYour Name 	cfr_debug("agc_gain0: %u agc_gain1: %u agc_gain2: %u agc_gain3: %u\n"
388*5113495bSYour Name 		  "agc_gain4: %u agc_gain5: %u agc_gain6: %u agc_gain7: %u\n",
389*5113495bSYour Name 		  event->agc_gain[0], event->agc_gain[1],
390*5113495bSYour Name 		  event->agc_gain[2], event->agc_gain[3],
391*5113495bSYour Name 		  event->agc_gain[4], event->agc_gain[5],
392*5113495bSYour Name 		  event->agc_gain[6], event->agc_gain[7]);
393*5113495bSYour Name 	cfr_debug("gain_tbl_idx0: %u gain_tbl_idx1: %u gain_tbl_idx2: %u\n"
394*5113495bSYour Name 		  "gain_tbl_idx3: %u gain_tbl_idx4: %u gain_tbl_idx5: %u\n"
395*5113495bSYour Name 		  "gain_tbl_idx6: %u gain_tbl_idx7: %u\n",
396*5113495bSYour Name 		  event->agc_gain_tbl_index[0], event->agc_gain_tbl_index[1],
397*5113495bSYour Name 		  event->agc_gain_tbl_index[2], event->agc_gain_tbl_index[3],
398*5113495bSYour Name 		  event->agc_gain_tbl_index[4], event->agc_gain_tbl_index[5],
399*5113495bSYour Name 		  event->agc_gain_tbl_index[6], event->agc_gain_tbl_index[7]);
400*5113495bSYour Name }
401*5113495bSYour Name 
402*5113495bSYour Name /**
403*5113495bSYour Name  * prepare_cfr_header_txstatus() - Prepare CFR metadata for TX failures
404*5113495bSYour Name  * @tx_evt_param: ptr to WMI TX completion event
405*5113495bSYour Name  * @header: pointer to metadata
406*5113495bSYour Name  * @target_type: target type
407*5113495bSYour Name  *
408*5113495bSYour Name  * Return: none
409*5113495bSYour Name  */
410*5113495bSYour Name static
prepare_cfr_header_txstatus(wmi_cfr_peer_tx_event_param * tx_evt_param,struct csi_cfr_header * header,uint32_t target_type)411*5113495bSYour Name void prepare_cfr_header_txstatus(wmi_cfr_peer_tx_event_param *tx_evt_param,
412*5113495bSYour Name 				 struct csi_cfr_header *header,
413*5113495bSYour Name 				 uint32_t target_type)
414*5113495bSYour Name {
415*5113495bSYour Name 	target_if_cfr_fill_header(header, false, target_type, false);
416*5113495bSYour Name 	header->u.meta_dbr.status = 0; /* failure */
417*5113495bSYour Name 	header->u.meta_dbr.length = 0;
418*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.peer_addr[0],
419*5113495bSYour Name 		     &tx_evt_param->peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE);
420*5113495bSYour Name }
421*5113495bSYour Name 
422*5113495bSYour Name /**
423*5113495bSYour Name  * target_if_peer_capture_event() - WMI TX completion event for one-shot
424*5113495bSYour Name  * capture
425*5113495bSYour Name  * @sc: pointer to offload soc object
426*5113495bSYour Name  * @data: WMI TX completion event buffer
427*5113495bSYour Name  * @datalen: WMI Tx completion event buffer length
428*5113495bSYour Name  *
429*5113495bSYour Name  * Return: status
430*5113495bSYour Name  */
431*5113495bSYour Name static int
target_if_peer_capture_event(ol_scn_t sc,uint8_t * data,uint32_t datalen)432*5113495bSYour Name target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen)
433*5113495bSYour Name {
434*5113495bSYour Name 	QDF_STATUS retval = 0;
435*5113495bSYour Name 	struct wmi_unified *wmi_handle;
436*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
437*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
438*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
439*5113495bSYour Name 	uint32_t cookie;
440*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
441*5113495bSYour Name 	struct look_up_table *lut = NULL;
442*5113495bSYour Name 	struct csi_cfr_header *header = NULL;
443*5113495bSYour Name 	struct csi_cfr_header header_error = {0};
444*5113495bSYour Name 	wmi_cfr_peer_tx_event_param tx_evt_param = {0};
445*5113495bSYour Name 	qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0;
446*5113495bSYour Name 	int status;
447*5113495bSYour Name 	struct wlan_lmac_if_rx_ops *rx_ops;
448*5113495bSYour Name 	uint32_t target_type;
449*5113495bSYour Name 
450*5113495bSYour Name 	psoc = target_if_get_psoc_from_scn_hdl(sc);
451*5113495bSYour Name 	if (!psoc) {
452*5113495bSYour Name 		cfr_err("psoc is null");
453*5113495bSYour Name 		return -EINVAL;
454*5113495bSYour Name 	}
455*5113495bSYour Name 
456*5113495bSYour Name 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
457*5113495bSYour Name 	if (!rx_ops) {
458*5113495bSYour Name 		cfr_err("rx_ops is NULL");
459*5113495bSYour Name 		return -EINVAL;
460*5113495bSYour Name 	}
461*5113495bSYour Name 
462*5113495bSYour Name 	retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID);
463*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(retval)) {
464*5113495bSYour Name 		cfr_err("unable to get psoc reference");
465*5113495bSYour Name 		return -EINVAL;
466*5113495bSYour Name 	}
467*5113495bSYour Name 
468*5113495bSYour Name 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
469*5113495bSYour Name 	if (!wmi_handle) {
470*5113495bSYour Name 		cfr_err("wmi_handle is null");
471*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
472*5113495bSYour Name 		return -EINVAL;
473*5113495bSYour Name 	}
474*5113495bSYour Name 
475*5113495bSYour Name 	retval = wmi_extract_cfr_peer_tx_event_param(wmi_handle, data,
476*5113495bSYour Name 						     &tx_evt_param);
477*5113495bSYour Name 
478*5113495bSYour Name 	if (retval != QDF_STATUS_SUCCESS) {
479*5113495bSYour Name 		cfr_err("Failed to extract cfr tx event param");
480*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
481*5113495bSYour Name 		return -EINVAL;
482*5113495bSYour Name 	}
483*5113495bSYour Name 
484*5113495bSYour Name 	dump_cfr_peer_tx_event(&tx_evt_param);
485*5113495bSYour Name 
486*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_evt_param.vdev_id,
487*5113495bSYour Name 						    WLAN_CFR_ID);
488*5113495bSYour Name 	if (!vdev) {
489*5113495bSYour Name 		cfr_err("vdev is null");
490*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
491*5113495bSYour Name 		return -EINVAL;
492*5113495bSYour Name 	}
493*5113495bSYour Name 
494*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
495*5113495bSYour Name 	if (!pdev) {
496*5113495bSYour Name 		cfr_err("pdev is null");
497*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
498*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
499*5113495bSYour Name 		return -EINVAL;
500*5113495bSYour Name 	}
501*5113495bSYour Name 
502*5113495bSYour Name 	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
503*5113495bSYour Name 	if (retval != QDF_STATUS_SUCCESS) {
504*5113495bSYour Name 		cfr_err("failed to get pdev reference");
505*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
506*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
507*5113495bSYour Name 		return -EINVAL;
508*5113495bSYour Name 	}
509*5113495bSYour Name 
510*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
511*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
512*5113495bSYour Name 	if (!pdev_cfrobj) {
513*5113495bSYour Name 		cfr_err("pdev object for CFR is NULL");
514*5113495bSYour Name 		status = -EINVAL;
515*5113495bSYour Name 		goto done;
516*5113495bSYour Name 	}
517*5113495bSYour Name 
518*5113495bSYour Name 	target_type = target_if_cfr_get_target_type(psoc);
519*5113495bSYour Name 
520*5113495bSYour Name 	if (tx_evt_param.status & PEER_CFR_CAPTURE_EVT_PS_STATUS_MASK) {
521*5113495bSYour Name 		cfr_debug("CFR capture failed as peer is in powersave : " QDF_MAC_ADDR_FMT,
522*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&tx_evt_param.peer_mac_addr.bytes[0]));
523*5113495bSYour Name 		status = -EINVAL;
524*5113495bSYour Name 		goto relay_failure;
525*5113495bSYour Name 	}
526*5113495bSYour Name 
527*5113495bSYour Name 	if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_STATUS_MASK) == 0) {
528*5113495bSYour Name 		cfr_debug("CFR capture failed for peer : " QDF_MAC_ADDR_FMT,
529*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&tx_evt_param.peer_mac_addr.bytes[0]));
530*5113495bSYour Name 		status = -EINVAL;
531*5113495bSYour Name 		pdev_cfrobj->tx_peer_status_cfr_fail++;
532*5113495bSYour Name 		goto relay_failure;
533*5113495bSYour Name 	}
534*5113495bSYour Name 
535*5113495bSYour Name 	if (tx_evt_param.status & CFR_TX_EVT_STATUS_MASK) {
536*5113495bSYour Name 		cfr_debug("TX packet returned status %d for peer: " QDF_MAC_ADDR_FMT,
537*5113495bSYour Name 			  tx_evt_param.status & CFR_TX_EVT_STATUS_MASK,
538*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&tx_evt_param.peer_mac_addr.bytes[0]));
539*5113495bSYour Name 		status = -EINVAL;
540*5113495bSYour Name 		pdev_cfrobj->tx_evt_status_cfr_fail++;
541*5113495bSYour Name 		goto relay_failure;
542*5113495bSYour Name 	}
543*5113495bSYour Name 
544*5113495bSYour Name 	buf_addr_temp = (tx_evt_param.correlation_info_2 & 0x0f);
545*5113495bSYour Name 	buf_addr = (tx_evt_param.correlation_info_1 |
546*5113495bSYour Name 		    ((uint64_t)buf_addr_temp << 32));
547*5113495bSYour Name 
548*5113495bSYour Name 	if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr,
549*5113495bSYour Name 					&cookie, 0)) {
550*5113495bSYour Name 		cfr_debug("Cookie lookup failure for addr: 0x%pK status: 0x%x",
551*5113495bSYour Name 			  (void *)((uintptr_t)buf_addr), tx_evt_param.status);
552*5113495bSYour Name 		status = -EINVAL;
553*5113495bSYour Name 		pdev_cfrobj->tx_dbr_cookie_lookup_fail++;
554*5113495bSYour Name 		goto done;
555*5113495bSYour Name 	}
556*5113495bSYour Name 
557*5113495bSYour Name 	cfr_debug("buffer address: 0x%pK cookie: %u",
558*5113495bSYour Name 		  (void *)((uintptr_t)buf_addr), cookie);
559*5113495bSYour Name 
560*5113495bSYour Name 	lut = pdev_cfrobj->lut[cookie];
561*5113495bSYour Name 	lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16);
562*5113495bSYour Name 	lut->tx_address1 = tx_evt_param.correlation_info_1;
563*5113495bSYour Name 	lut->tx_address2 = tx_evt_param.correlation_info_2;
564*5113495bSYour Name 	header = &lut->header;
565*5113495bSYour Name 
566*5113495bSYour Name 	target_if_cfr_fill_header(header, false, target_type, false);
567*5113495bSYour Name 
568*5113495bSYour Name 	header->u.meta_dbr.status        = (tx_evt_param.status &
569*5113495bSYour Name 					    PEER_CFR_CAPTURE_EVT_STATUS_MASK) ?
570*5113495bSYour Name 					    1 : 0;
571*5113495bSYour Name 	header->u.meta_dbr.capture_bw    = tx_evt_param.bandwidth;
572*5113495bSYour Name 	header->u.meta_dbr.phy_mode      = tx_evt_param.phy_mode;
573*5113495bSYour Name 	header->u.meta_dbr.prim20_chan   = tx_evt_param.primary_20mhz_chan;
574*5113495bSYour Name 	header->u.meta_dbr.center_freq1  = tx_evt_param.band_center_freq1;
575*5113495bSYour Name 	header->u.meta_dbr.center_freq2  = tx_evt_param.band_center_freq2;
576*5113495bSYour Name 	/* Currently CFR data is captured on ACK of a Qos NULL frame.
577*5113495bSYour Name 	 * For 20 MHz, ACK is Legacy and for 40/80/160, ACK is DUP Legacy.
578*5113495bSYour Name 	 */
579*5113495bSYour Name 	header->u.meta_dbr.capture_mode  = tx_evt_param.bandwidth ?
580*5113495bSYour Name 					   CFR_DUP_LEGACY_ACK : CFR_LEGACY_ACK;
581*5113495bSYour Name 	header->u.meta_dbr.capture_type  = tx_evt_param.capture_method;
582*5113495bSYour Name 	header->u.meta_dbr.num_rx_chain  = wlan_vdev_mlme_get_rxchainmask(vdev);
583*5113495bSYour Name 	header->u.meta_dbr.sts_count     = tx_evt_param.spatial_streams;
584*5113495bSYour Name 	header->u.meta_dbr.timestamp     = tx_evt_param.timestamp_us;
585*5113495bSYour Name 	header->u.meta_dbr.rx_start_ts   = tx_evt_param.rx_start_ts;
586*5113495bSYour Name 	header->u.meta_dbr.rtt_cfo_measurement = tx_evt_param.cfo_measurement;
587*5113495bSYour Name 	header->u.meta_dbr.mcs_rate      = tx_evt_param.mcs_rate;
588*5113495bSYour Name 	header->u.meta_dbr.gi_type       = tx_evt_param.gi_type;
589*5113495bSYour Name 
590*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.agc_gain[0],
591*5113495bSYour Name 		     &tx_evt_param.agc_gain[0],
592*5113495bSYour Name 		     HOST_MAX_CHAINS * sizeof(tx_evt_param.agc_gain[0]));
593*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.peer_addr[0],
594*5113495bSYour Name 		     &tx_evt_param.peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE);
595*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.chain_rssi[0],
596*5113495bSYour Name 		     &tx_evt_param.chain_rssi[0],
597*5113495bSYour Name 		     HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_rssi[0]));
598*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.chain_phase[0],
599*5113495bSYour Name 		     &tx_evt_param.chain_phase[0],
600*5113495bSYour Name 		     HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_phase[0]));
601*5113495bSYour Name 	qdf_mem_copy(&header->u.meta_dbr.agc_gain_tbl_index[0],
602*5113495bSYour Name 		     &tx_evt_param.agc_gain_tbl_index[0],
603*5113495bSYour Name 		     (HOST_MAX_CHAINS *
604*5113495bSYour Name 		      sizeof(tx_evt_param.agc_gain_tbl_index[0])));
605*5113495bSYour Name 
606*5113495bSYour Name 	status = correlate_and_relay(pdev, cookie, lut,
607*5113495bSYour Name 				     CORRELATE_TX_EV_MODULE_ID);
608*5113495bSYour Name 	if (status == STATUS_STREAM_AND_RELEASE) {
609*5113495bSYour Name 		status = rx_ops->cfr_rx_ops.cfr_info_send(pdev, &lut->header,
610*5113495bSYour Name 				sizeof(struct csi_cfr_header),
611*5113495bSYour Name 				lut->data, lut->data_len, &end_magic, 4);
612*5113495bSYour Name 		release_lut_entry(pdev, lut);
613*5113495bSYour Name 		target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr,
614*5113495bSYour Name 					  cookie, 0);
615*5113495bSYour Name 		cfr_debug("Data sent to upper layers, releasing look up table");
616*5113495bSYour Name 	} else if (status == STATUS_HOLD) {
617*5113495bSYour Name 		cfr_debug("HOLD for buffer address: 0x%pK cookie: %u",
618*5113495bSYour Name 			  (void *)((uintptr_t)buf_addr), cookie);
619*5113495bSYour Name 	} else {
620*5113495bSYour Name 		cfr_err("Correlation returned invalid status!!");
621*5113495bSYour Name 		status = -EINVAL;
622*5113495bSYour Name 		goto done;
623*5113495bSYour Name 	}
624*5113495bSYour Name 
625*5113495bSYour Name 	status = 0;
626*5113495bSYour Name 	goto done;
627*5113495bSYour Name 
628*5113495bSYour Name relay_failure:
629*5113495bSYour Name 	prepare_cfr_header_txstatus(&tx_evt_param, &header_error, target_type);
630*5113495bSYour Name 	rx_ops->cfr_rx_ops.cfr_info_send(pdev, &header_error,
631*5113495bSYour Name 					 sizeof(struct csi_cfr_header),
632*5113495bSYour Name 					 NULL, 0, &end_magic, 4);
633*5113495bSYour Name done:
634*5113495bSYour Name 	wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
635*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
636*5113495bSYour Name 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
637*5113495bSYour Name 	return status;
638*5113495bSYour Name }
639*5113495bSYour Name #else
640*5113495bSYour Name static int
target_if_peer_capture_event(ol_scn_t sc,uint8_t * data,uint32_t datalen)641*5113495bSYour Name target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen)
642*5113495bSYour Name {
643*5113495bSYour Name 	return 0;
644*5113495bSYour Name }
645*5113495bSYour Name #endif
646*5113495bSYour Name 
647*5113495bSYour Name /**
648*5113495bSYour Name  * target_if_register_tx_completion_event_handler() - register TX completion
649*5113495bSYour Name  *                                                    handler
650*5113495bSYour Name  * @psoc: pointer to psoc object
651*5113495bSYour Name  *
652*5113495bSYour Name  * Return: Status
653*5113495bSYour Name  */
654*5113495bSYour Name static QDF_STATUS
target_if_register_tx_completion_event_handler(struct wlan_objmgr_psoc * psoc)655*5113495bSYour Name target_if_register_tx_completion_event_handler(struct wlan_objmgr_psoc *psoc)
656*5113495bSYour Name {
657*5113495bSYour Name 	/* Register completion handler here */
658*5113495bSYour Name 	wmi_unified_t wmi_hdl;
659*5113495bSYour Name 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
660*5113495bSYour Name 
661*5113495bSYour Name 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
662*5113495bSYour Name 	if (!wmi_hdl) {
663*5113495bSYour Name 		cfr_err("Unable to get wmi handle");
664*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
665*5113495bSYour Name 	}
666*5113495bSYour Name 
667*5113495bSYour Name 	ret = wmi_unified_register_event_handler(wmi_hdl,
668*5113495bSYour Name 						 wmi_peer_cfr_capture_event_id,
669*5113495bSYour Name 						 target_if_peer_capture_event,
670*5113495bSYour Name 						 WMI_RX_UMAC_CTX);
671*5113495bSYour Name 	/*
672*5113495bSYour Name 	 * Event registration is called per pdev
673*5113495bSYour Name 	 * Ignore error if event is already registered.
674*5113495bSYour Name 	 */
675*5113495bSYour Name 	if (ret == QDF_STATUS_E_FAILURE)
676*5113495bSYour Name 		ret = QDF_STATUS_SUCCESS;
677*5113495bSYour Name 
678*5113495bSYour Name 	return ret;
679*5113495bSYour Name }
680*5113495bSYour Name 
681*5113495bSYour Name /**
682*5113495bSYour Name  * target_if_unregister_tx_completion_event_handler() - unregister TX
683*5113495bSYour Name  *                                                      completion handler
684*5113495bSYour Name  * @psoc: pointer to psoc object
685*5113495bSYour Name  *
686*5113495bSYour Name  * Return: Status
687*5113495bSYour Name  */
688*5113495bSYour Name static QDF_STATUS
target_if_unregister_tx_completion_event_handler(struct wlan_objmgr_psoc * psoc)689*5113495bSYour Name target_if_unregister_tx_completion_event_handler(struct wlan_objmgr_psoc *psoc)
690*5113495bSYour Name {
691*5113495bSYour Name 	/* Unregister completion handler here */
692*5113495bSYour Name 	wmi_unified_t wmi_hdl;
693*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
694*5113495bSYour Name 
695*5113495bSYour Name 	wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
696*5113495bSYour Name 	if (!wmi_hdl) {
697*5113495bSYour Name 		cfr_err("Unable to get wmi handle");
698*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
699*5113495bSYour Name 	}
700*5113495bSYour Name 
701*5113495bSYour Name 	status = wmi_unified_unregister_event(wmi_hdl,
702*5113495bSYour Name 					      wmi_peer_cfr_capture_event_id);
703*5113495bSYour Name 	return status;
704*5113495bSYour Name }
705*5113495bSYour Name 
706*5113495bSYour Name #ifdef DIRECT_BUF_RX_ENABLE
707*5113495bSYour Name /**
708*5113495bSYour Name  * target_if_register_to_dbr() - Register to Direct DMA handler
709*5113495bSYour Name  * @pdev: pointer to pdev object
710*5113495bSYour Name  *
711*5113495bSYour Name  * Return: Status
712*5113495bSYour Name  */
713*5113495bSYour Name static QDF_STATUS
target_if_register_to_dbr(struct wlan_objmgr_pdev * pdev)714*5113495bSYour Name target_if_register_to_dbr(struct wlan_objmgr_pdev *pdev)
715*5113495bSYour Name {
716*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
717*5113495bSYour Name 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
718*5113495bSYour Name 	struct dbr_module_config dbr_config;
719*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
720*5113495bSYour Name 
721*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
722*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
723*5113495bSYour Name 	if (!tx_ops) {
724*5113495bSYour Name 		cfr_err("tx_ops is NULL");
725*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
726*5113495bSYour Name 	}
727*5113495bSYour Name 
728*5113495bSYour Name 	dbr_tx_ops = &tx_ops->dbr_tx_ops;
729*5113495bSYour Name 	dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_CFR;
730*5113495bSYour Name 	dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_CFR;
731*5113495bSYour Name 	if (dbr_tx_ops->direct_buf_rx_module_register) {
732*5113495bSYour Name 		return dbr_tx_ops->direct_buf_rx_module_register
733*5113495bSYour Name 			(pdev, DBR_MODULE_CFR, &dbr_config,
734*5113495bSYour Name 			 cfr_dbr_event_handler);
735*5113495bSYour Name 	}
736*5113495bSYour Name 
737*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
738*5113495bSYour Name }
739*5113495bSYour Name 
740*5113495bSYour Name /**
741*5113495bSYour Name  * target_if_unregister_to_dbr() - Unregister callback for DBR events
742*5113495bSYour Name  * @pdev: PDEV object
743*5113495bSYour Name  *
744*5113495bSYour Name  * Return: status
745*5113495bSYour Name  */
746*5113495bSYour Name static QDF_STATUS
target_if_unregister_to_dbr(struct wlan_objmgr_pdev * pdev)747*5113495bSYour Name target_if_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
748*5113495bSYour Name {
749*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
750*5113495bSYour Name 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
751*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
752*5113495bSYour Name 
753*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
754*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
755*5113495bSYour Name 	if (!tx_ops) {
756*5113495bSYour Name 		cfr_err("tx_ops is NULL");
757*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
758*5113495bSYour Name 	}
759*5113495bSYour Name 
760*5113495bSYour Name 	dbr_tx_ops = &tx_ops->dbr_tx_ops;
761*5113495bSYour Name 	if (dbr_tx_ops->direct_buf_rx_module_unregister) {
762*5113495bSYour Name 		return dbr_tx_ops->direct_buf_rx_module_unregister
763*5113495bSYour Name 			(pdev, DBR_MODULE_CFR);
764*5113495bSYour Name 	}
765*5113495bSYour Name 
766*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
767*5113495bSYour Name }
768*5113495bSYour Name 
769*5113495bSYour Name #else
770*5113495bSYour Name static QDF_STATUS
target_if_cfr_register_to_dbr(struct wlan_objmgr_pdev * pdev)771*5113495bSYour Name target_if_cfr_register_to_dbr(struct wlan_objmgr_pdev *pdev)
772*5113495bSYour Name {
773*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
774*5113495bSYour Name }
775*5113495bSYour Name 
776*5113495bSYour Name static QDF_STATUS
target_if_unregister_to_dbr(struct wlan_objmgr_pdev * pdev)777*5113495bSYour Name target_if_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
778*5113495bSYour Name {
779*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
780*5113495bSYour Name }
781*5113495bSYour Name 
782*5113495bSYour Name #endif
783*5113495bSYour Name 
cfr_dbr_init_pdev(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)784*5113495bSYour Name QDF_STATUS cfr_dbr_init_pdev(struct wlan_objmgr_psoc *psoc,
785*5113495bSYour Name 			     struct wlan_objmgr_pdev *pdev)
786*5113495bSYour Name {
787*5113495bSYour Name 	QDF_STATUS status;
788*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
789*5113495bSYour Name 
790*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
791*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
792*5113495bSYour Name 	if (!pdev_cfrobj)
793*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
794*5113495bSYour Name 
795*5113495bSYour Name #if DIRECT_BUF_RX_ENABLE
796*5113495bSYour Name 	status = target_if_register_to_dbr(pdev);
797*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != status) {
798*5113495bSYour Name 		cfr_err("Failed to register with dbr");
799*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
800*5113495bSYour Name 	}
801*5113495bSYour Name #endif
802*5113495bSYour Name 
803*5113495bSYour Name 	status = target_if_register_tx_completion_event_handler(psoc);
804*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != status) {
805*5113495bSYour Name 		cfr_err("Failed to register with tx event handler");
806*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
807*5113495bSYour Name 	}
808*5113495bSYour Name 
809*5113495bSYour Name 	pdev_cfrobj->cfr_max_sta_count = MAX_CFR_ENABLED_CLIENTS;
810*5113495bSYour Name 	pdev_cfrobj->subbuf_size = STREAMFS_MAX_SUBBUF_8S;
811*5113495bSYour Name 	pdev_cfrobj->num_subbufs = STREAMFS_NUM_SUBBUF_8S;
812*5113495bSYour Name 
813*5113495bSYour Name 	return status;
814*5113495bSYour Name }
815*5113495bSYour Name 
cfr_dbr_deinit_pdev(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)816*5113495bSYour Name QDF_STATUS cfr_dbr_deinit_pdev(struct wlan_objmgr_psoc *psoc,
817*5113495bSYour Name 			       struct wlan_objmgr_pdev *pdev)
818*5113495bSYour Name {
819*5113495bSYour Name 	QDF_STATUS status;
820*5113495bSYour Name 	struct pdev_cfr *pdev_cfrobj;
821*5113495bSYour Name 
822*5113495bSYour Name 	pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
823*5113495bSYour Name 							    WLAN_UMAC_COMP_CFR);
824*5113495bSYour Name 	if (!pdev_cfrobj)
825*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
826*5113495bSYour Name 
827*5113495bSYour Name 	pdev_cfrobj->cfr_timer_enable = 0;
828*5113495bSYour Name 
829*5113495bSYour Name 	status = target_if_unregister_to_dbr(pdev);
830*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != status)
831*5113495bSYour Name 		cfr_err("Failed to register with dbr");
832*5113495bSYour Name 
833*5113495bSYour Name 	status = target_if_unregister_tx_completion_event_handler(psoc);
834*5113495bSYour Name 	return status;
835*5113495bSYour Name }
836