1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * Layer b/w umac and target_if (ol) txops
22  * It contains wrapers for txops
23  */
24 
25 #include <wlan_cfr_tgt_api.h>
26 #include <wlan_cfr_utils_api.h>
27 #include <target_type.h>
28 #include <cfr_defs_i.h>
29 
tgt_cfr_info_send(struct wlan_objmgr_pdev * pdev,void * head,size_t hlen,void * data,size_t dlen,void * tail,size_t tlen)30 uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head,
31 			   size_t hlen, void *data, size_t dlen, void *tail,
32 			   size_t tlen)
33 {
34 	struct pdev_cfr *pa;
35 	uint32_t status, total_len;
36 	uint8_t *nl_data = NULL;
37 
38 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
39 
40 	if (pa == NULL) {
41 		cfr_err("pdev_cfr is NULL\n");
42 		return -1;
43 	}
44 
45 	/* If CFR data transport mode is NL event then send single event*/
46 	if (pa->nl_cb.cfr_nl_cb) {
47 		total_len = hlen + dlen + tlen;
48 
49 		nl_data = qdf_mem_malloc(total_len);
50 		if (!nl_data) {
51 			cfr_err("failed to alloc memory, len %d, vdev_id %d",
52 				total_len, pa->nl_cb.vdev_id);
53 			return QDF_STATUS_E_FAILURE;
54 		}
55 
56 		if (hlen)
57 			qdf_mem_copy(nl_data, head, hlen);
58 
59 		if (dlen)
60 			qdf_mem_copy(nl_data + hlen, data, dlen);
61 
62 		if (tlen)
63 			qdf_mem_copy(nl_data + hlen + dlen, tail, tlen);
64 
65 		pa->nl_cb.cfr_nl_cb(pa->nl_cb.vdev_id, pa->nl_cb.pid,
66 				    (const void *)nl_data, total_len);
67 		qdf_mem_free(nl_data);
68 
69 		return QDF_STATUS_SUCCESS;
70 	}
71 
72 	if (head)
73 		status = cfr_streamfs_write(pa, (const void *)head, hlen);
74 
75 	if (data)
76 		status = cfr_streamfs_write(pa, (const void *)data, dlen);
77 
78 	if (tail)
79 		status = cfr_streamfs_write(pa, (const void *)tail, tlen);
80 
81 
82 	/* finalise the write */
83 	status = cfr_streamfs_flush(pa);
84 
85 	return status;
86 }
87 
tgt_cfr_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)88 void tgt_cfr_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
89 {
90 	struct psoc_cfr *cfr_sc;
91 
92 	if (psoc == NULL)
93 		return;
94 
95 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
96 					WLAN_UMAC_COMP_CFR);
97 	if (cfr_sc == NULL)
98 		return;
99 
100 	cfr_sc->is_cfr_capable = !!value;
101 	cfr_debug("CFR: FW support advert=%d", cfr_sc->is_cfr_capable);
102 }
103 
104 static inline struct wlan_lmac_if_cfr_tx_ops *
wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc * psoc)105 	wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc *psoc)
106 {
107 	struct wlan_lmac_if_tx_ops *tx_ops;
108 
109 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
110 	if (!tx_ops) {
111 		cfr_err("tx_ops is NULL");
112 		return NULL;
113 	}
114 	return &tx_ops->cfr_tx_ops;
115 }
116 
tgt_cfr_get_target_type(struct wlan_objmgr_psoc * psoc)117 int tgt_cfr_get_target_type(struct wlan_objmgr_psoc *psoc)
118 {
119 	uint32_t target_type = 0;
120 	struct wlan_lmac_if_target_tx_ops *target_type_tx_ops;
121 	struct wlan_lmac_if_tx_ops *tx_ops;
122 
123 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
124 	if (!tx_ops) {
125 		cfr_err("tx_ops is NULL");
126 		return target_type;
127 	}
128 	target_type_tx_ops = &tx_ops->target_tx_ops;
129 
130 	if (target_type_tx_ops->tgt_get_tgt_type)
131 		target_type = target_type_tx_ops->tgt_get_tgt_type(psoc);
132 
133 	return target_type;
134 }
135 
tgt_cfr_validate_period(struct wlan_objmgr_psoc * psoc,u_int32_t period)136 int tgt_cfr_validate_period(struct wlan_objmgr_psoc *psoc, u_int32_t period)
137 {
138 	uint32_t target_type = tgt_cfr_get_target_type(psoc);
139 	int status = 0;
140 
141 	if (target_type == TARGET_TYPE_UNKNOWN) {
142 		cfr_err("cfr period validation fail due to invalid target type");
143 		return status;
144 	}
145 
146 	/* Basic check is the period should be between 0 and MAX_CFR_PRD */
147 	if ((period < 0) || (period > MAX_CFR_PRD)) {
148 		cfr_err("Invalid period value: %d\n", period);
149 		return status;
150 	}
151 
152 	if (target_type == TARGET_TYPE_QCN9000 ||
153 	    target_type == TARGET_TYPE_QCA6018 ||
154 	    target_type == TARGET_TYPE_QCA8074V2 ||
155 	    target_type == TARGET_TYPE_QCA5018 ||
156 	    target_type == TARGET_TYPE_QCA5332 ||
157 	    target_type == TARGET_TYPE_QCN9224 ||
158 	    target_type == TARGET_TYPE_QCN6432) {
159 		/* No additional check required for these targets */
160 		status = 1;
161 	} else {
162 		if (!(period % CFR_MOD_PRD)) {
163 			status = 1;
164 		} else {
165 			cfr_err("Invalid period value. Value must be mod of %d",
166 				CFR_MOD_PRD);
167 		}
168 	}
169 	return status;
170 }
171 
tgt_cfr_init_pdev(struct wlan_objmgr_pdev * pdev)172 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev)
173 {
174 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
175 	QDF_STATUS status = QDF_STATUS_SUCCESS;
176 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
177 
178 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
179 
180 	if (cfr_tx_ops->cfr_init_pdev)
181 		status = cfr_tx_ops->cfr_init_pdev(psoc, pdev);
182 
183 	if (QDF_IS_STATUS_ERROR(status))
184 		cfr_err("Error occurred with exit code %d\n", status);
185 
186 	return status;
187 }
188 
tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev * pdev)189 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev)
190 {
191 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
192 	QDF_STATUS status = QDF_STATUS_SUCCESS;
193 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
194 
195 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
196 
197 	if (cfr_tx_ops->cfr_deinit_pdev)
198 		status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev);
199 
200 	if (QDF_IS_STATUS_ERROR(status))
201 		cfr_err("Error occurred with exit code %d\n", status);
202 
203 	return status;
204 }
205 
tgt_cfr_start_capture(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_peer * peer,struct cfr_capture_params * cfr_params)206 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev,
207 			  struct wlan_objmgr_peer *peer,
208 			  struct cfr_capture_params *cfr_params)
209 {
210 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
211 	int status = 0;
212 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
213 
214 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
215 
216 	if (cfr_tx_ops->cfr_start_capture)
217 		status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params);
218 
219 	if (status != 0)
220 		cfr_err("Error occurred with exit code %d\n", status);
221 
222 	return status;
223 }
224 
tgt_cfr_stop_capture(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_peer * peer)225 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev,
226 			 struct wlan_objmgr_peer *peer)
227 {
228 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
229 	int status = 0;
230 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
231 
232 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
233 
234 	if (cfr_tx_ops->cfr_stop_capture)
235 		status = cfr_tx_ops->cfr_stop_capture(pdev, peer);
236 
237 	if (status != 0)
238 		cfr_err("Error occurred with exit code %d\n", status);
239 
240 	return status;
241 }
242 
243 int
tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev * pdev,uint32_t cfr_timer)244 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer)
245 {
246 	int status = 0;
247 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
248 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
249 
250 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
251 
252 	if (cfr_tx_ops->cfr_enable_cfr_timer)
253 		status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer);
254 
255 	if (status != 0)
256 		cfr_err("Error occurred with exit code %d\n", status);
257 
258 	return status;
259 }
260 
261 #ifdef WLAN_ENH_CFR_ENABLE
262 QDF_STATUS
tgt_cfr_config_rcc(struct wlan_objmgr_pdev * pdev,struct cfr_rcc_param * rcc_param)263 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
264 		   struct cfr_rcc_param *rcc_param)
265 {
266 	QDF_STATUS status = QDF_STATUS_SUCCESS;
267 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
268 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
269 
270 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
271 
272 	if (cfr_tx_ops->cfr_config_rcc)
273 		status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param);
274 
275 	if (status != QDF_STATUS_SUCCESS)
276 		cfr_err("Error occurred with exit code %d\n", status);
277 
278 	return status;
279 }
280 
tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev * pdev)281 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
282 {
283 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
284 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
285 
286 	if (!psoc) {
287 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n");
288 		return;
289 	}
290 
291 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
292 
293 	if (cfr_tx_ops->cfr_start_lut_timer)
294 		cfr_tx_ops->cfr_start_lut_timer(pdev);
295 }
296 
tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev * pdev)297 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
298 {
299 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
300 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
301 
302 	if (!psoc) {
303 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n");
304 		return;
305 	}
306 
307 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
308 
309 	if (cfr_tx_ops->cfr_stop_lut_timer)
310 		cfr_tx_ops->cfr_stop_lut_timer(pdev);
311 }
312 
tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev * pdev,struct cfr_rcc_param * rcc_param,bool allvalid,uint16_t reset_cfg)313 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
314 			       struct cfr_rcc_param *rcc_param,
315 			       bool allvalid, uint16_t reset_cfg)
316 {
317 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
318 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
319 
320 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
321 
322 	if (cfr_tx_ops->cfr_default_ta_ra_cfg)
323 		cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param,
324 						 allvalid, reset_cfg);
325 }
326 
tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev * pdev)327 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
328 {
329 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
330 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
331 
332 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
333 
334 	if (cfr_tx_ops->cfr_dump_lut_enh)
335 		cfr_tx_ops->cfr_dump_lut_enh(pdev);
336 }
337 
tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev * pdev,void * nbuf)338 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
339 {
340 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
341 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
342 
343 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
344 
345 	if (cfr_tx_ops->cfr_rx_tlv_process)
346 		cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf);
347 }
348 
tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev * pdev)349 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev)
350 {
351 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
352 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
353 
354 	if (!psoc) {
355 		cfr_err("Invalid PSOC:Cannot update global config.\n");
356 		return;
357 	}
358 
359 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
360 
361 	if (cfr_tx_ops->cfr_update_global_cfg)
362 		cfr_tx_ops->cfr_update_global_cfg(pdev);
363 }
364 
tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev * pdev,bool is_subscribe)365 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev,
366 				       bool is_subscribe)
367 {
368 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
369 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
370 
371 	if (!psoc) {
372 		cfr_err("Invalid psoc\n");
373 		return QDF_STATUS_E_INVAL;
374 	}
375 
376 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
377 
378 	if (cfr_tx_ops->cfr_subscribe_ppdu_desc)
379 		return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev,
380 							   is_subscribe);
381 
382 	return QDF_STATUS_SUCCESS;
383 }
384 
385 QDF_STATUS
tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)386 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
387 				  uint32_t value)
388 {
389 	struct psoc_cfr *cfr_sc;
390 
391 	if (!psoc) {
392 		cfr_err("CFR: NULL PSOC!!");
393 		return QDF_STATUS_E_INVAL;
394 	}
395 
396 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
397 						       WLAN_UMAC_COMP_CFR);
398 
399 	if (!cfr_sc) {
400 		cfr_err("Failed to get CFR component priv obj!!");
401 		return QDF_STATUS_E_INVAL;
402 	}
403 
404 	cfr_sc->is_cap_interval_mode_sel_support = !!value;
405 	cfr_debug("CFR: cap_interval_mode_sel_support is %s\n",
406 		  (cfr_sc->is_cap_interval_mode_sel_support) ?
407 		  "enabled" :
408 		  "disabled");
409 
410 	return QDF_STATUS_SUCCESS;
411 }
412 
413 QDF_STATUS
tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)414 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
415 {
416 	struct psoc_cfr *cfr_sc;
417 
418 	if (!psoc) {
419 		cfr_err("CFR: NULL PSOC!!");
420 		return QDF_STATUS_E_INVAL;
421 	}
422 
423 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
424 						       WLAN_UMAC_COMP_CFR);
425 	if (!cfr_sc) {
426 		cfr_err("Failed to get CFR component priv obj!!");
427 		return QDF_STATUS_E_INVAL;
428 	}
429 
430 	cfr_sc->is_mo_marking_support = !!value;
431 	cfr_debug("CFR: mo_marking_support is %s\n",
432 		  (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled");
433 
434 	return QDF_STATUS_SUCCESS;
435 }
436 
437 QDF_STATUS
tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)438 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
439 {
440 	struct psoc_cfr *cfr_sc;
441 
442 	if (!psoc) {
443 		cfr_err("CFR: NULL PSOC!!");
444 		return QDF_STATUS_E_INVAL;
445 	}
446 
447 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
448 						       WLAN_UMAC_COMP_CFR);
449 
450 	if (!cfr_sc) {
451 		cfr_err("Failed to get CFR component priv obj!!");
452 		return QDF_STATUS_E_INVAL;
453 	}
454 
455 	cfr_sc->is_aoa_for_rcc_support = !!value;
456 	cfr_debug("CFR: aoa_for_rcc_support is %s\n",
457 		  (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled");
458 
459 	return QDF_STATUS_SUCCESS;
460 }
461 #else
462 QDF_STATUS
tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)463 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
464 				  uint32_t value)
465 {
466 	return QDF_STATUS_E_NOSUPPORT;
467 }
468 
469 QDF_STATUS
tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)470 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc,
471 			       uint32_t value)
472 {
473 	return QDF_STATUS_E_NOSUPPORT;
474 }
475 
476 QDF_STATUS
tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)477 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
478 {
479 	return QDF_STATUS_E_NOSUPPORT;
480 }
481 #endif
482