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