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