xref: /wlan-dirver/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_utils_api.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved
4  *
5  *
6  * Permission to use, copy, modify, and/or distribute this software for
7  * any purpose with or without fee is hereby granted, provided that the
8  * above copyright notice and this permission notice appear in all
9  * copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18  * PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <wlan_spectral_utils_api.h>
22 #include <qdf_module.h>
23 #include "../../core/spectral_cmn_api_i.h"
24 #include <wlan_spectral_tgt_api.h>
25 #include <cfg_ucfg_api.h>
26 
27 bool wlan_spectral_is_mode_disabled_pdev(struct wlan_objmgr_pdev *pdev,
28 					 enum spectral_scan_mode smode)
29 {
30 	bool spectral_mode_disable;
31 
32 	if (!pdev) {
33 		spectral_err("pdev is NULL!");
34 		return true;
35 	}
36 
37 	switch (smode) {
38 	case SPECTRAL_SCAN_MODE_NORMAL:
39 		spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get(
40 			pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
41 		break;
42 
43 	case SPECTRAL_SCAN_MODE_AGILE:
44 		spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get(
45 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS) &&
46 					wlan_pdev_nif_feat_ext_cap_get(
47 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS) &&
48 					wlan_pdev_nif_feat_ext_cap_get(
49 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS) &&
50 					wlan_pdev_nif_feat_ext_cap_get(
51 			pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
52 		break;
53 
54 	default:
55 		spectral_err("Invalid Spectral scan mode %d", smode);
56 		spectral_mode_disable = true;
57 		break;
58 	}
59 
60 	return spectral_mode_disable;
61 }
62 
63 bool
64 wlan_spectral_is_feature_disabled_ini(struct wlan_objmgr_psoc *psoc)
65 {
66 	if (!psoc) {
67 		spectral_err("PSOC is NULL!");
68 		return true;
69 	}
70 
71 	return wlan_psoc_nif_feat_cap_get(psoc,
72 					  WLAN_SOC_F_SPECTRAL_INI_DISABLE);
73 }
74 
75 bool
76 wlan_spectral_is_feature_disabled_psoc(struct wlan_objmgr_psoc *psoc)
77 {
78 	if (!psoc) {
79 		spectral_err("psoc is NULL!");
80 		return true;
81 	}
82 
83 	return wlan_spectral_is_feature_disabled_ini(psoc);
84 }
85 
86 bool
87 wlan_spectral_is_feature_disabled_pdev(struct wlan_objmgr_pdev *pdev)
88 {
89 	enum spectral_scan_mode smode;
90 
91 	if (!pdev) {
92 		spectral_err("pdev is NULL!");
93 		return true;
94 	}
95 
96 	smode = SPECTRAL_SCAN_MODE_NORMAL;
97 	for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
98 		if (!wlan_spectral_is_mode_disabled_pdev(pdev, smode))
99 			return false;
100 
101 	return true;
102 }
103 
104 QDF_STATUS
105 wlan_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev)
106 {
107 	return tgt_spectral_init_pdev_feature_caps(pdev);
108 }
109 
110 QDF_STATUS
111 wlan_spectral_init_psoc_feature_cap(struct wlan_objmgr_psoc *psoc)
112 {
113 	if (!psoc) {
114 		spectral_err("PSOC is NULL!");
115 		return QDF_STATUS_E_INVAL;
116 	}
117 
118 	if (cfg_get(psoc, CFG_SPECTRAL_DISABLE))
119 		wlan_psoc_nif_feat_cap_set(psoc,
120 					   WLAN_SOC_F_SPECTRAL_INI_DISABLE);
121 	else
122 		wlan_psoc_nif_feat_cap_clear(psoc,
123 					     WLAN_SOC_F_SPECTRAL_INI_DISABLE);
124 
125 	return QDF_STATUS_SUCCESS;
126 }
127 
128 QDF_STATUS
129 wlan_spectral_init(void)
130 {
131 	if (wlan_objmgr_register_psoc_create_handler(
132 		WLAN_UMAC_COMP_SPECTRAL,
133 		wlan_spectral_psoc_obj_create_handler,
134 		NULL) !=
135 	    QDF_STATUS_SUCCESS) {
136 		return QDF_STATUS_E_FAILURE;
137 	}
138 	if (wlan_objmgr_register_psoc_destroy_handler(
139 		WLAN_UMAC_COMP_SPECTRAL,
140 		wlan_spectral_psoc_obj_destroy_handler,
141 		NULL) !=
142 	    QDF_STATUS_SUCCESS) {
143 		return QDF_STATUS_E_FAILURE;
144 	}
145 	if (wlan_objmgr_register_pdev_create_handler(
146 		WLAN_UMAC_COMP_SPECTRAL,
147 		wlan_spectral_pdev_obj_create_handler,
148 		NULL) !=
149 	    QDF_STATUS_SUCCESS) {
150 		return QDF_STATUS_E_FAILURE;
151 	}
152 	if (wlan_objmgr_register_pdev_destroy_handler(
153 		WLAN_UMAC_COMP_SPECTRAL,
154 		wlan_spectral_pdev_obj_destroy_handler,
155 		NULL) !=
156 	    QDF_STATUS_SUCCESS) {
157 		return QDF_STATUS_E_FAILURE;
158 	}
159 
160 	return QDF_STATUS_SUCCESS;
161 }
162 
163 QDF_STATUS
164 wlan_spectral_deinit(void)
165 {
166 	if (wlan_objmgr_unregister_psoc_create_handler(
167 		WLAN_UMAC_COMP_SPECTRAL,
168 		wlan_spectral_psoc_obj_create_handler,
169 		NULL) !=
170 	    QDF_STATUS_SUCCESS) {
171 		return QDF_STATUS_E_FAILURE;
172 	}
173 	if (wlan_objmgr_unregister_psoc_destroy_handler(
174 		WLAN_UMAC_COMP_SPECTRAL,
175 		wlan_spectral_psoc_obj_destroy_handler,
176 		NULL) !=
177 	    QDF_STATUS_SUCCESS) {
178 		return QDF_STATUS_E_FAILURE;
179 	}
180 	if (wlan_objmgr_unregister_pdev_create_handler(
181 		WLAN_UMAC_COMP_SPECTRAL,
182 		wlan_spectral_pdev_obj_create_handler,
183 		NULL) !=
184 	    QDF_STATUS_SUCCESS) {
185 		return QDF_STATUS_E_FAILURE;
186 	}
187 	if (wlan_objmgr_unregister_pdev_destroy_handler(
188 		WLAN_UMAC_COMP_SPECTRAL,
189 		wlan_spectral_pdev_obj_destroy_handler,
190 		NULL) !=
191 	    QDF_STATUS_SUCCESS) {
192 		return QDF_STATUS_E_FAILURE;
193 	}
194 	return QDF_STATUS_SUCCESS;
195 }
196 
197 QDF_STATUS
198 spectral_register_legacy_cb(struct wlan_objmgr_psoc *psoc,
199 			    struct spectral_legacy_cbacks *legacy_cbacks)
200 {
201 	struct spectral_context *sc;
202 
203 	if (!psoc) {
204 		spectral_err("psoc is null");
205 		return QDF_STATUS_E_INVAL;
206 	}
207 
208 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
209 		spectral_info("Spectral feature is disabled");
210 		return QDF_STATUS_COMP_DISABLED;
211 	}
212 
213 	sc = spectral_get_spectral_ctx_from_psoc(psoc);
214 	if (!sc) {
215 		spectral_err("Invalid Context");
216 		return QDF_STATUS_E_FAILURE;
217 	}
218 
219 	sc->legacy_cbacks.vdev_get_chan_freq =
220 	    legacy_cbacks->vdev_get_chan_freq;
221 	sc->legacy_cbacks.vdev_get_chan_freq_seg2 =
222 	    legacy_cbacks->vdev_get_chan_freq_seg2;
223 	sc->legacy_cbacks.vdev_get_ch_width = legacy_cbacks->vdev_get_ch_width;
224 	sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz =
225 	    legacy_cbacks->vdev_get_sec20chan_freq_mhz;
226 
227 	return QDF_STATUS_SUCCESS;
228 }
229 qdf_export_symbol(spectral_register_legacy_cb);
230 
231 int16_t
232 spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev)
233 {
234 	struct spectral_context *sc;
235 
236 	sc = spectral_get_spectral_ctx_from_vdev(vdev);
237 	if (!sc) {
238 		spectral_err("spectral context is Null");
239 		return -EINVAL;
240 	}
241 
242 	if (!sc->legacy_cbacks.vdev_get_chan_freq) {
243 		spectral_err("vdev_get_chan_freq is not supported");
244 		return -ENOTSUPP;
245 	}
246 
247 	return sc->legacy_cbacks.vdev_get_chan_freq(vdev);
248 }
249 
250 int16_t
251 spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev)
252 {
253 	struct spectral_context *sc;
254 	struct wlan_channel *des_chan;
255 
256 	sc = spectral_get_spectral_ctx_from_vdev(vdev);
257 	if (!sc) {
258 		spectral_err("spectral context is null");
259 		return -EINVAL;
260 	}
261 
262 	if (!sc->legacy_cbacks.vdev_get_chan_freq_seg2) {
263 		des_chan = wlan_vdev_mlme_get_des_chan(vdev);
264 		if (des_chan->ch_width == CH_WIDTH_80P80MHZ)
265 			return des_chan->ch_freq_seg2;
266 		else
267 			return 0;
268 	}
269 
270 	return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev);
271 }
272 
273 enum phy_ch_width
274 spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev)
275 {
276 	struct spectral_context *sc;
277 
278 	sc = spectral_get_spectral_ctx_from_vdev(vdev);
279 	if (!sc) {
280 		spectral_err("spectral context is Null");
281 		return CH_WIDTH_INVALID;
282 	}
283 
284 	if (!sc->legacy_cbacks.vdev_get_ch_width) {
285 		spectral_err("vdev_get_ch_width is not supported");
286 		return -ENOTSUPP;
287 	}
288 
289 	return sc->legacy_cbacks.vdev_get_ch_width(vdev);
290 }
291 
292 int
293 spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev,
294 				     uint16_t *sec20chan_freq)
295 {
296 	struct spectral_context *sc;
297 
298 	sc = spectral_get_spectral_ctx_from_vdev(vdev);
299 	if (!sc) {
300 		spectral_err("spectral context is Null");
301 		return -EINVAL;
302 	}
303 
304 	if (!sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz) {
305 		spectral_err("vdev_get_sec20chan_freq_mhz is not supported");
306 		return -ENOTSUPP;
307 	}
308 
309 	return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev,
310 							     sec20chan_freq);
311 }
312 
313 void
314 wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
315 {
316 	struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops;
317 
318 	/* Spectral rx ops */
319 	sptrl_rx_ops->sptrlro_get_pdev_target_handle =
320 					tgt_get_pdev_target_handle;
321 	sptrl_rx_ops->sptrlro_get_psoc_target_handle =
322 					tgt_get_psoc_target_handle;
323 	sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq;
324 	sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 =
325 					spectral_vdev_get_chan_freq_seg2;
326 	sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width;
327 	sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz =
328 	    spectral_vdev_get_sec20chan_freq_mhz;
329 	sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_pdev =
330 		wlan_spectral_is_feature_disabled_pdev;
331 	sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_psoc =
332 		wlan_spectral_is_feature_disabled_psoc;
333 }
334 
335 QDF_STATUS
336 wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc,
337 			       struct spectral_wmi_ops *wmi_ops)
338 {
339 	struct spectral_context *sc;
340 
341 	if (!psoc) {
342 		spectral_err("psoc is NULL!");
343 		return QDF_STATUS_E_INVAL;
344 	}
345 
346 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
347 		spectral_info("Spectral feature is disabled");
348 		return QDF_STATUS_COMP_DISABLED;
349 	}
350 
351 	sc = spectral_get_spectral_ctx_from_psoc(psoc);
352 	if (!sc) {
353 		spectral_err("spectral context is NULL!");
354 		return QDF_STATUS_E_FAILURE;
355 	}
356 
357 	return sc->sptrlc_register_spectral_wmi_ops(psoc, wmi_ops);
358 }
359 
360 qdf_export_symbol(wlan_register_spectral_wmi_ops);
361 
362 QDF_STATUS
363 wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc,
364 			       struct spectral_tgt_ops *tgt_ops)
365 {
366 	struct spectral_context *sc;
367 
368 	if (!psoc) {
369 		spectral_err("psoc is NULL!");
370 		return QDF_STATUS_E_INVAL;
371 	}
372 
373 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
374 		spectral_info("Spectral feature is disabled");
375 		return QDF_STATUS_COMP_DISABLED;
376 	}
377 
378 	sc = spectral_get_spectral_ctx_from_psoc(psoc);
379 	if (!sc) {
380 		spectral_err("spectral context is NULL!");
381 		return QDF_STATUS_E_FAILURE;
382 	}
383 
384 	return sc->sptrlc_register_spectral_tgt_ops(psoc, tgt_ops);
385 }
386 
387 qdf_export_symbol(wlan_register_spectral_tgt_ops);
388 
389 /**
390  * wlan_spectral_psoc_target_attach() - Spectral psoc target attach
391  * @psoc:  pointer to psoc object
392  *
393  * API to initialize Spectral psoc target object
394  *
395  * Return: QDF_STATUS_SUCCESS upon successful registration,
396  *         QDF_STATUS_E_FAILURE upon failure
397  */
398 static QDF_STATUS
399 wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc *psoc)
400 {
401 	struct spectral_context *sc = NULL;
402 
403 	if (!psoc) {
404 		spectral_err("psoc is null");
405 		return QDF_STATUS_E_FAILURE;
406 	}
407 
408 	sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
409 						   WLAN_UMAC_COMP_SPECTRAL);
410 	if (!sc) {
411 		spectral_err("Spectral context is null");
412 		return QDF_STATUS_E_NOMEM;
413 	}
414 
415 	if (sc->sptrlc_psoc_spectral_init) {
416 		void *target_handle;
417 
418 		target_handle = sc->sptrlc_psoc_spectral_init(psoc);
419 		if (!target_handle) {
420 			spectral_err("Spectral psoc lmac object is NULL!");
421 			return QDF_STATUS_E_FAILURE;
422 		}
423 		sc->psoc_target_handle = target_handle;
424 	}
425 
426 	return QDF_STATUS_SUCCESS;
427 }
428 
429 /**
430  * wlan_spectral_psoc_target_detach() - Spectral psoc target detach
431  * @psoc:  pointer to psoc object
432  *
433  * API to destroy Spectral psoc target object
434  *
435  * Return: QDF_STATUS_SUCCESS upon successful registration,
436  *         QDF_STATUS_E_FAILURE upon failure
437  */
438 static QDF_STATUS
439 wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc *psoc)
440 {
441 	struct spectral_context *sc = NULL;
442 
443 	if (!psoc) {
444 		spectral_err("psoc is null");
445 		return QDF_STATUS_E_FAILURE;
446 	}
447 
448 	sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
449 						   WLAN_UMAC_COMP_SPECTRAL);
450 	if (!sc) {
451 		spectral_err("Spectral context is null");
452 		return QDF_STATUS_E_INVAL;
453 	}
454 
455 	if (sc->sptrlc_psoc_spectral_deinit)
456 		sc->sptrlc_psoc_spectral_deinit(psoc);
457 	sc->psoc_target_handle = NULL;
458 
459 	return QDF_STATUS_SUCCESS;
460 }
461 
462 #ifdef DIRECT_BUF_RX_ENABLE
463 bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev,
464 				struct direct_buf_rx_data *payload)
465 {
466 	struct spectral_context *sc;
467 
468 	if (!pdev) {
469 		spectral_err("PDEV is NULL!");
470 		return -EINVAL;
471 	}
472 	sc = spectral_get_spectral_ctx_from_pdev(pdev);
473 	if (!sc) {
474 		spectral_err("spectral context is NULL!");
475 		return -EINVAL;
476 	}
477 
478 	sc->sptrlc_process_spectral_report(pdev, payload);
479 
480 	return true;
481 }
482 #endif
483 
484 QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev)
485 {
486 	struct wlan_objmgr_psoc *psoc;
487 	QDF_STATUS status;
488 
489 	psoc = wlan_pdev_get_psoc(pdev);
490 
491 	if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
492 		spectral_info("Spectral feature is disabled");
493 		return QDF_STATUS_COMP_DISABLED;
494 	}
495 
496 	if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS))
497 		tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1);
498 
499 	status = spectral_register_dbr(pdev);
500 	return status;
501 }
502 
503 QDF_STATUS spectral_register_dbr(struct wlan_objmgr_pdev *pdev)
504 {
505 	if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
506 		spectral_info("spectral feature is disabled");
507 		return QDF_STATUS_COMP_DISABLED;
508 	}
509 
510 	return tgt_spectral_register_to_dbr(pdev);
511 }
512 
513 qdf_export_symbol(spectral_register_dbr);
514 
515 QDF_STATUS spectral_unregister_dbr(struct wlan_objmgr_pdev *pdev)
516 {
517 	QDF_STATUS status;
518 
519 	if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
520 		spectral_info("spectral feature is disabled");
521 		return QDF_STATUS_COMP_DISABLED;
522 	}
523 	status = tgt_spectral_unregister_to_dbr(pdev);
524 
525 	return status;
526 }
527 
528 qdf_export_symbol(spectral_unregister_dbr);
529 
530 QDF_STATUS wlan_spectral_psoc_open(struct wlan_objmgr_psoc *psoc)
531 {
532 	if (!psoc) {
533 		spectral_err("psoc is null");
534 		return QDF_STATUS_E_INVAL;
535 	}
536 
537 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
538 		spectral_info("Spectral feature is disabled");
539 		return QDF_STATUS_COMP_DISABLED;
540 	}
541 
542 	return wlan_spectral_psoc_target_attach(psoc);
543 }
544 
545 QDF_STATUS wlan_spectral_psoc_close(struct wlan_objmgr_psoc *psoc)
546 {
547 	if (!psoc) {
548 		spectral_err("psoc is null");
549 		return QDF_STATUS_E_INVAL;
550 	}
551 
552 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
553 		spectral_info("Spectral feature is disabled");
554 		return QDF_STATUS_COMP_DISABLED;
555 	}
556 
557 	return wlan_spectral_psoc_target_detach(psoc);
558 }
559 
560 QDF_STATUS wlan_spectral_psoc_enable(struct wlan_objmgr_psoc *psoc)
561 {
562 	if (!psoc) {
563 		spectral_err("psoc is null");
564 		return QDF_STATUS_E_INVAL;
565 	}
566 
567 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
568 		spectral_info("Spectral feature is disabled");
569 		return QDF_STATUS_COMP_DISABLED;
570 	}
571 
572 	return tgt_spectral_register_events(psoc);
573 }
574 
575 QDF_STATUS wlan_spectral_psoc_disable(struct wlan_objmgr_psoc *psoc)
576 {
577 	if (!psoc) {
578 		spectral_err("psoc is null");
579 		return QDF_STATUS_E_INVAL;
580 	}
581 
582 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
583 		spectral_info("Spectral feature is disabled");
584 		return QDF_STATUS_COMP_DISABLED;
585 	}
586 
587 	return tgt_spectral_unregister_events(psoc);
588 }
589 
590 struct wlan_lmac_if_sptrl_tx_ops *
591 wlan_spectral_pdev_get_lmac_if_txops(struct wlan_objmgr_pdev *pdev)
592 {
593 	struct wlan_objmgr_psoc *psoc;
594 	struct wlan_lmac_if_tx_ops *tx_ops;
595 
596 	if (!pdev) {
597 		spectral_err("pdev is NULL!");
598 		return NULL;
599 	}
600 
601 	psoc = wlan_pdev_get_psoc(pdev);
602 	if (!psoc) {
603 		spectral_err("psoc is NULL!");
604 		return NULL;
605 	}
606 
607 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
608 	if (!tx_ops) {
609 		spectral_err("tx_ops is NULL");
610 		return NULL;
611 	}
612 
613 	return &tx_ops->sptrl_tx_ops;
614 }
615