xref: /wlan-dirver/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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 
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 
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 *
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 
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 
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 		/* No additional check required for these targets */
159 		status = 1;
160 	} else {
161 		if (!(period % CFR_MOD_PRD)) {
162 			status = 1;
163 		} else {
164 			cfr_err("Invalid period value. Value must be mod of %d",
165 				CFR_MOD_PRD);
166 		}
167 	}
168 	return status;
169 }
170 
171 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev)
172 {
173 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
174 	QDF_STATUS status = QDF_STATUS_SUCCESS;
175 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
176 
177 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
178 
179 	if (cfr_tx_ops->cfr_init_pdev)
180 		status = cfr_tx_ops->cfr_init_pdev(psoc, pdev);
181 
182 	if (QDF_IS_STATUS_ERROR(status))
183 		cfr_err("Error occurred with exit code %d\n", status);
184 
185 	return status;
186 }
187 
188 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev)
189 {
190 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
191 	QDF_STATUS status = QDF_STATUS_SUCCESS;
192 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
193 
194 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
195 
196 	if (cfr_tx_ops->cfr_deinit_pdev)
197 		status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev);
198 
199 	if (QDF_IS_STATUS_ERROR(status))
200 		cfr_err("Error occurred with exit code %d\n", status);
201 
202 	return status;
203 }
204 
205 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev,
206 			  struct wlan_objmgr_peer *peer,
207 			  struct cfr_capture_params *cfr_params)
208 {
209 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
210 	int status = 0;
211 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
212 
213 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
214 
215 	if (cfr_tx_ops->cfr_start_capture)
216 		status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params);
217 
218 	if (status != 0)
219 		cfr_err("Error occurred with exit code %d\n", status);
220 
221 	return status;
222 }
223 
224 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev,
225 			 struct wlan_objmgr_peer *peer)
226 {
227 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
228 	int status = 0;
229 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
230 
231 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
232 
233 	if (cfr_tx_ops->cfr_stop_capture)
234 		status = cfr_tx_ops->cfr_stop_capture(pdev, peer);
235 
236 	if (status != 0)
237 		cfr_err("Error occurred with exit code %d\n", status);
238 
239 	return status;
240 }
241 
242 int
243 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer)
244 {
245 	int status = 0;
246 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
247 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
248 
249 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
250 
251 	if (cfr_tx_ops->cfr_enable_cfr_timer)
252 		status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer);
253 
254 	if (status != 0)
255 		cfr_err("Error occurred with exit code %d\n", status);
256 
257 	return status;
258 }
259 
260 #ifdef WLAN_ENH_CFR_ENABLE
261 QDF_STATUS
262 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
263 		   struct cfr_rcc_param *rcc_param)
264 {
265 	QDF_STATUS status = QDF_STATUS_SUCCESS;
266 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
267 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
268 
269 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
270 
271 	if (cfr_tx_ops->cfr_config_rcc)
272 		status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param);
273 
274 	if (status != QDF_STATUS_SUCCESS)
275 		cfr_err("Error occurred with exit code %d\n", status);
276 
277 	return status;
278 }
279 
280 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
281 {
282 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
283 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
284 
285 	if (!psoc) {
286 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n");
287 		return;
288 	}
289 
290 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
291 
292 	if (cfr_tx_ops->cfr_start_lut_timer)
293 		cfr_tx_ops->cfr_start_lut_timer(pdev);
294 }
295 
296 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
297 {
298 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
299 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
300 
301 	if (!psoc) {
302 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n");
303 		return;
304 	}
305 
306 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
307 
308 	if (cfr_tx_ops->cfr_stop_lut_timer)
309 		cfr_tx_ops->cfr_stop_lut_timer(pdev);
310 }
311 
312 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
313 			       struct cfr_rcc_param *rcc_param,
314 			       bool allvalid, uint16_t reset_cfg)
315 {
316 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
317 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
318 
319 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
320 
321 	if (cfr_tx_ops->cfr_default_ta_ra_cfg)
322 		cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param,
323 						 allvalid, reset_cfg);
324 }
325 
326 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
327 {
328 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
329 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
330 
331 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
332 
333 	if (cfr_tx_ops->cfr_dump_lut_enh)
334 		cfr_tx_ops->cfr_dump_lut_enh(pdev);
335 }
336 
337 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
338 {
339 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
340 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
341 
342 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
343 
344 	if (cfr_tx_ops->cfr_rx_tlv_process)
345 		cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf);
346 }
347 
348 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev)
349 {
350 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
351 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
352 
353 	if (!psoc) {
354 		cfr_err("Invalid PSOC:Cannot update global config.\n");
355 		return;
356 	}
357 
358 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
359 
360 	if (cfr_tx_ops->cfr_update_global_cfg)
361 		cfr_tx_ops->cfr_update_global_cfg(pdev);
362 }
363 
364 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev,
365 				       bool is_subscribe)
366 {
367 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
368 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
369 
370 	if (!psoc) {
371 		cfr_err("Invalid psoc\n");
372 		return QDF_STATUS_E_INVAL;
373 	}
374 
375 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
376 
377 	if (cfr_tx_ops->cfr_subscribe_ppdu_desc)
378 		return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev,
379 							   is_subscribe);
380 
381 	return QDF_STATUS_SUCCESS;
382 }
383 
384 QDF_STATUS
385 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
386 				  uint32_t value)
387 {
388 	struct psoc_cfr *cfr_sc;
389 
390 	if (!psoc) {
391 		cfr_err("CFR: NULL PSOC!!");
392 		return QDF_STATUS_E_INVAL;
393 	}
394 
395 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
396 						       WLAN_UMAC_COMP_CFR);
397 
398 	if (!cfr_sc) {
399 		cfr_err("Failed to get CFR component priv obj!!");
400 		return QDF_STATUS_E_INVAL;
401 	}
402 
403 	cfr_sc->is_cap_interval_mode_sel_support = !!value;
404 	cfr_debug("CFR: cap_interval_mode_sel_support is %s\n",
405 		  (cfr_sc->is_cap_interval_mode_sel_support) ?
406 		  "enabled" :
407 		  "disabled");
408 
409 	return QDF_STATUS_SUCCESS;
410 }
411 
412 QDF_STATUS
413 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
414 {
415 	struct psoc_cfr *cfr_sc;
416 
417 	if (!psoc) {
418 		cfr_err("CFR: NULL PSOC!!");
419 		return QDF_STATUS_E_INVAL;
420 	}
421 
422 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
423 						       WLAN_UMAC_COMP_CFR);
424 	if (!cfr_sc) {
425 		cfr_err("Failed to get CFR component priv obj!!");
426 		return QDF_STATUS_E_INVAL;
427 	}
428 
429 	cfr_sc->is_mo_marking_support = !!value;
430 	cfr_debug("CFR: mo_marking_support is %s\n",
431 		  (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled");
432 
433 	return QDF_STATUS_SUCCESS;
434 }
435 
436 QDF_STATUS
437 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
438 {
439 	struct psoc_cfr *cfr_sc;
440 
441 	if (!psoc) {
442 		cfr_err("CFR: NULL PSOC!!");
443 		return QDF_STATUS_E_INVAL;
444 	}
445 
446 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
447 						       WLAN_UMAC_COMP_CFR);
448 
449 	if (!cfr_sc) {
450 		cfr_err("Failed to get CFR component priv obj!!");
451 		return QDF_STATUS_E_INVAL;
452 	}
453 
454 	cfr_sc->is_aoa_for_rcc_support = !!value;
455 	cfr_debug("CFR: aoa_for_rcc_support is %s\n",
456 		  (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled");
457 
458 	return QDF_STATUS_SUCCESS;
459 }
460 #else
461 QDF_STATUS
462 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
463 				  uint32_t value)
464 {
465 	return QDF_STATUS_E_NOSUPPORT;
466 }
467 
468 QDF_STATUS
469 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc,
470 			       uint32_t value)
471 {
472 	return QDF_STATUS_E_NOSUPPORT;
473 }
474 
475 QDF_STATUS
476 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
477 {
478 	return QDF_STATUS_E_NOSUPPORT;
479 }
480 #endif
481