xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
1 /*
2  * Copyright (c) 2016-2019 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 /**
21  * DOC: This file init/deint functions for DFS module.
22  */
23 
24 #include "wlan_dfs_ucfg_api.h"
25 #include "wlan_dfs_tgt_api.h"
26 #include <wlan_objmgr_vdev_obj.h>
27 #include "wlan_dfs_utils_api.h"
28 #ifndef QCA_MCL_DFS_SUPPORT
29 #include "ieee80211_mlme_dfs_interface.h"
30 #endif
31 #include "wlan_objmgr_global_obj.h"
32 #include "wlan_dfs_init_deinit_api.h"
33 #include "wlan_dfs_lmac_api.h"
34 #include "../../core/src/dfs.h"
35 #include "a_types.h"
36 #include "wlan_serialization_api.h"
37 #include <qdf_trace.h>
38 #include "wlan_scan_ucfg_api.h"
39 #include "wlan_dfs_mlme_api.h"
40 #include "../../core/src/dfs_zero_cac.h"
41 
42 struct dfs_to_mlme global_dfs_to_mlme;
43 
44 struct wlan_dfs *wlan_pdev_get_dfs_obj(struct wlan_objmgr_pdev *pdev)
45 {
46 	struct wlan_dfs *dfs;
47 	dfs = wlan_objmgr_pdev_get_comp_private_obj(pdev,
48 			WLAN_UMAC_COMP_DFS);
49 
50 	return dfs;
51 }
52 
53 #ifndef QCA_MCL_DFS_SUPPORT
54 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
55 static inline void
56 register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback)
57 {
58 	if (!mlme_callback)
59 		return;
60 
61 	mlme_callback->mlme_precac_chan_change_csa =
62 		mlme_dfs_precac_chan_change_csa;
63 }
64 #else
65 static inline void
66 register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback)
67 {
68 }
69 #endif
70 
71 void register_dfs_callbacks(void)
72 {
73 	struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme;
74 
75 	tmp_dfs_to_mlme->pdev_component_obj_attach =
76 		wlan_objmgr_pdev_component_obj_attach;
77 	tmp_dfs_to_mlme->pdev_component_obj_detach =
78 		wlan_objmgr_pdev_component_obj_detach;
79 
80 	tmp_dfs_to_mlme->dfs_start_rcsa = mlme_dfs_start_rcsa;
81 	tmp_dfs_to_mlme->mlme_mark_dfs = mlme_dfs_mark_dfs;
82 	tmp_dfs_to_mlme->mlme_start_csa = mlme_dfs_start_csa;
83 	tmp_dfs_to_mlme->mlme_proc_cac = mlme_dfs_proc_cac;
84 	tmp_dfs_to_mlme->mlme_deliver_event_up_after_cac =
85 		mlme_dfs_deliver_event_up_after_cac;
86 	tmp_dfs_to_mlme->mlme_get_dfs_ch_nchans = mlme_dfs_get_dfs_ch_nchans;
87 	tmp_dfs_to_mlme->mlme_get_extchan = mlme_dfs_get_extchan;
88 	tmp_dfs_to_mlme->mlme_set_no_chans_available =
89 		mlme_dfs_set_no_chans_available;
90 	tmp_dfs_to_mlme->mlme_ieee2mhz = mlme_dfs_ieee2mhz;
91 	tmp_dfs_to_mlme->mlme_find_dot11_channel = mlme_dfs_find_dot11_channel;
92 	tmp_dfs_to_mlme->mlme_get_dfs_ch_channels =
93 		mlme_dfs_get_dfs_ch_channels;
94 	tmp_dfs_to_mlme->mlme_dfs_ch_flags_ext = mlme_dfs_dfs_ch_flags_ext;
95 	tmp_dfs_to_mlme->mlme_channel_change_by_precac =
96 		mlme_dfs_channel_change_by_precac;
97 	tmp_dfs_to_mlme->mlme_nol_timeout_notification =
98 		mlme_dfs_nol_timeout_notification;
99 	tmp_dfs_to_mlme->mlme_clist_update = mlme_dfs_clist_update;
100 	tmp_dfs_to_mlme->mlme_get_cac_timeout = mlme_dfs_get_cac_timeout;
101 	tmp_dfs_to_mlme->mlme_rebuild_chan_list_with_non_dfs_channels =
102 		mlme_dfs_rebuild_chan_list_with_non_dfs_channels;
103 	tmp_dfs_to_mlme->mlme_restart_vaps_with_non_dfs_chan =
104 		mlme_dfs_restart_vaps_with_non_dfs_chan;
105 	tmp_dfs_to_mlme->mlme_is_opmode_sta =
106 		mlme_dfs_is_opmode_sta;
107 	tmp_dfs_to_mlme->mlme_check_allowed_prim_chanlist =
108 		mlme_dfs_check_allowed_prim_chanlist;
109 	tmp_dfs_to_mlme->mlme_update_scan_channel_list =
110 		mlme_dfs_update_scan_channel_list;
111 	tmp_dfs_to_mlme->mlme_bringdown_vaps =
112 		mlme_dfs_bringdown_vaps;
113 	tmp_dfs_to_mlme->mlme_dfs_deliver_event =
114 		mlme_dfs_deliver_event;
115 
116 	/*
117 	 * Register precac auto channel switch feature related callbacks
118 	 */
119 	register_dfs_precac_auto_chan_callbacks(tmp_dfs_to_mlme);
120 }
121 #else
122 void register_dfs_callbacks(void)
123 {
124 	struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme;
125 
126 	tmp_dfs_to_mlme->pdev_component_obj_attach =
127 		wlan_objmgr_pdev_component_obj_attach;
128 	tmp_dfs_to_mlme->pdev_component_obj_detach =
129 		wlan_objmgr_pdev_component_obj_detach;
130 }
131 #endif
132 
133 /**
134  * dfs_psoc_obj_create_notification() - dfs psoc create notification handler
135  * @psoc: psoc object
136  * @arg_list: Argument list
137  *
138  * Return: QDF_STATUS
139  */
140 static QDF_STATUS dfs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
141 					     void *arg_list)
142 {
143 	QDF_STATUS status;
144 	struct dfs_soc_priv_obj *dfs_soc_obj;
145 
146 	dfs_soc_obj = qdf_mem_malloc(sizeof(*dfs_soc_obj));
147 	if (!dfs_soc_obj)
148 		return QDF_STATUS_E_NOMEM;
149 
150 	dfs_soc_obj->psoc = psoc;
151 
152 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
153 						       WLAN_UMAC_COMP_DFS,
154 						       (void *)dfs_soc_obj,
155 						       QDF_STATUS_SUCCESS);
156 
157 	if (QDF_IS_STATUS_ERROR(status)) {
158 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
159 			"Failed to attach psoc dfs component");
160 		qdf_mem_free(dfs_soc_obj);
161 		return status;
162 	}
163 	/* Initialize precac timer here*/
164 	dfs_zero_cac_timer_init(dfs_soc_obj);
165 
166 	dfs_debug(NULL, WLAN_DEBUG_DFS1,
167 		"DFS obj attach to psoc successfully");
168 
169 	return status;
170 }
171 
172 /**
173  * dfs_psoc_obj_destroy_notification() - dfs psoc destroy notification handler
174  * @psoc: psoc object
175  * @arg_list: Argument list
176  *
177  * Return: QDF_STATUS
178  */
179 static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
180 					      void *arg_list)
181 {
182 	QDF_STATUS status;
183 	struct dfs_soc_priv_obj *dfs_soc_obj;
184 
185 	dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
186 						WLAN_UMAC_COMP_DFS);
187 	if (!dfs_soc_obj) {
188 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
189 			"Failed to get dfs obj in psoc");
190 		return QDF_STATUS_E_FAILURE;
191 	}
192 
193 	dfs_zero_cac_timer_detach(dfs_soc_obj);
194 
195 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
196 						       WLAN_UMAC_COMP_DFS,
197 						       dfs_soc_obj);
198 
199 	if (QDF_IS_STATUS_ERROR(status))
200 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
201 			"Failed to detach psoc dfs component");
202 
203 	qdf_mem_free(dfs_soc_obj);
204 
205 	return status;
206 }
207 
208 QDF_STATUS dfs_init(void)
209 {
210 	QDF_STATUS status;
211 
212 	status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_DFS,
213 			dfs_psoc_obj_create_notification,
214 			NULL);
215 
216 	if (QDF_IS_STATUS_ERROR(status)) {
217 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
218 			"Failed to register psoc create handler for dfs");
219 		goto err_psoc_create;
220 	}
221 
222 	status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
223 			dfs_psoc_obj_destroy_notification,
224 			NULL);
225 
226 	if (QDF_IS_STATUS_ERROR(status)) {
227 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
228 			"Failed to register psoc delete handler for dfs");
229 		goto err_psoc_delete;
230 	}
231 
232 	register_dfs_callbacks();
233 
234 	status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS,
235 			wlan_dfs_pdev_obj_create_notification,
236 			NULL);
237 
238 	if (QDF_IS_STATUS_ERROR(status)) {
239 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
240 			"Failed to register pdev create handler for dfs");
241 		goto err_pdev_create;
242 	}
243 
244 	status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
245 			wlan_dfs_pdev_obj_destroy_notification,
246 			NULL);
247 
248 	if (QDF_IS_STATUS_ERROR(status)) {
249 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
250 			"Failed to register pdev delete handler for dfs");
251 		goto err_pdev_delete;
252 	}
253 
254 	status = qdf_print_set_category_verbose(qdf_get_pidx(),
255 			QDF_MODULE_ID_DFS, QDF_TRACE_LEVEL_INFO, true);
256 
257 	if (QDF_IS_STATUS_ERROR(status)) {
258 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
259 			"Failed to set verbose for category");
260 		goto err_category_verbose;
261 	}
262 
263 	return QDF_STATUS_SUCCESS;
264 
265 err_category_verbose:
266 	wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
267 			wlan_dfs_pdev_obj_destroy_notification,
268 			NULL);
269 err_pdev_delete:
270 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS,
271 			wlan_dfs_pdev_obj_create_notification,
272 			NULL);
273 err_pdev_create:
274 	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
275 			dfs_psoc_obj_destroy_notification,
276 			NULL);
277 err_psoc_delete:
278 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS,
279 			dfs_psoc_obj_create_notification,
280 			NULL);
281 err_psoc_create:
282 	return status;
283 }
284 
285 QDF_STATUS dfs_deinit(void)
286 {
287 	QDF_STATUS status;
288 
289 	status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS,
290 			dfs_psoc_obj_create_notification,
291 			NULL);
292 
293 	if (QDF_IS_STATUS_ERROR(status))
294 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
295 			"Failed to deregister dfs psoc obj create");
296 
297 	status = wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
298 			dfs_psoc_obj_destroy_notification,
299 			NULL);
300 
301 	if (QDF_IS_STATUS_ERROR(status))
302 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
303 			"Failed to deregister dfs psoc obj destroy");
304 
305 	status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS,
306 			wlan_dfs_pdev_obj_create_notification,
307 			NULL);
308 
309 	if (QDF_IS_STATUS_ERROR(status))
310 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
311 			"Failed to deregister dfs pdev obj create");
312 
313 	status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
314 			wlan_dfs_pdev_obj_destroy_notification,
315 			NULL);
316 
317 	if (QDF_IS_STATUS_ERROR(status))
318 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
319 			"Failed to deregister dfs pdev obj destroy");
320 
321 	return QDF_STATUS_SUCCESS;
322 }
323 
324 QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
325 		void *arg)
326 {
327 	struct wlan_dfs *dfs = NULL;
328 	struct wlan_objmgr_psoc *psoc;
329 	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
330 	uint8_t pdev_id;
331 	QDF_STATUS status;
332 	bool is_5ghz = false;
333 
334 	if (!pdev) {
335 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null pdev");
336 		return QDF_STATUS_E_FAILURE;
337 	}
338 
339 	psoc = wlan_pdev_get_psoc(pdev);
340 	if (!psoc) {
341 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null psoc");
342 		return QDF_STATUS_E_FAILURE;
343 	}
344 
345 	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
346 	if (!(dfs_tx_ops && dfs_tx_ops->dfs_is_pdev_5ghz)) {
347 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_tx_ops is null");
348 		return QDF_STATUS_E_FAILURE;
349 	}
350 
351 	status = dfs_tx_ops->dfs_is_pdev_5ghz(pdev, &is_5ghz);
352 	if (QDF_IS_STATUS_ERROR(status)) {
353 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Failed to get is_5ghz value");
354 		return QDF_STATUS_E_FAILURE;
355 	}
356 
357 	if (!is_5ghz) {
358 		pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
359 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
360 				"Do not allocate DFS object for 2G, pdev_id = %d",
361 				pdev_id);
362 		return QDF_STATUS_SUCCESS;
363 	}
364 
365 	if (dfs_create_object(&dfs) == 1) {
366 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "failed to create object");
367 		return QDF_STATUS_E_FAILURE;
368 	}
369 
370 	status = global_dfs_to_mlme.pdev_component_obj_attach(pdev,
371 		WLAN_UMAC_COMP_DFS, (void *)dfs, QDF_STATUS_SUCCESS);
372 	if (QDF_IS_STATUS_ERROR(status)) {
373 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "obj attach failed");
374 		dfs_destroy_object(dfs);
375 		return QDF_STATUS_E_FAILURE;
376 	}
377 
378 	dfs->dfs_pdev_obj = pdev;
379 
380 	if (!dfs_tx_ops->dfs_is_tgt_offload) {
381 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
382 			"dfs_is_tgt_offload is null");
383 		dfs_destroy_object(dfs);
384 		return QDF_STATUS_E_FAILURE;
385 	}
386 
387 	dfs->dfs_is_offload_enabled = dfs_tx_ops->dfs_is_tgt_offload(psoc);
388 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_offload %d",
389 		 dfs->dfs_is_offload_enabled);
390 	dfs_agile_soc_obj_init(dfs, psoc);
391 
392 	if (dfs_attach(dfs) == 1) {
393 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_attch failed");
394 		dfs_destroy_object(dfs);
395 		return QDF_STATUS_E_FAILURE;
396 	}
397 
398 	return QDF_STATUS_SUCCESS;
399 }
400 
401 QDF_STATUS wlan_dfs_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
402 		void *arg)
403 {
404 	struct wlan_dfs *dfs = NULL;
405 
406 	if (!pdev) {
407 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "PDEV is NULL");
408 		return QDF_STATUS_E_FAILURE;
409 	}
410 
411 	dfs = wlan_pdev_get_dfs_obj(pdev);
412 
413 	/* DFS is NULL during unload. should we call this function before */
414 	if (dfs) {
415 		global_dfs_to_mlme.pdev_component_obj_detach(pdev,
416 				WLAN_UMAC_COMP_DFS,
417 				(void *)dfs);
418 
419 		dfs_detach(dfs);
420 		dfs->dfs_pdev_obj = NULL;
421 		dfs_destroy_object(dfs);
422 	}
423 
424 	return QDF_STATUS_SUCCESS;
425 }
426 
427 static void dfs_scan_serialization_comp_info_cb(
428 		struct wlan_objmgr_vdev *vdev,
429 		union wlan_serialization_rules_info *comp_info)
430 {
431 	struct wlan_dfs *dfs = NULL;
432 	struct wlan_objmgr_pdev *pdev;
433 
434 	if (!comp_info) {
435 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "comp_info is NULL");
436 		return;
437 	}
438 
439 	if (!vdev) {
440 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "vdev is NULL");
441 		return;
442 	}
443 
444 	pdev = wlan_vdev_get_pdev(vdev);
445 	if (!pdev) {
446 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "pdev is NULL");
447 		return;
448 	}
449 
450 	comp_info->scan_info.is_cac_in_progress = false;
451 
452 	if (!tgt_dfs_is_pdev_5ghz(pdev))
453 		return;
454 
455 	dfs = wlan_pdev_get_dfs_obj(pdev);
456 	if (!dfs) {
457 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
458 		return;
459 	}
460 
461 	if (dfs_is_ap_cac_timer_running(dfs))
462 		comp_info->scan_info.is_cac_in_progress = true;
463 }
464 
465 QDF_STATUS wifi_dfs_psoc_enable(struct wlan_objmgr_psoc *psoc)
466 {
467 	QDF_STATUS status;
468 
469 	status = tgt_dfs_reg_ev_handler(psoc);
470 	if (status != QDF_STATUS_SUCCESS) {
471 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "tgt_dfs_reg_ev_handler failed");
472 		return QDF_STATUS_E_FAILURE;
473 	}
474 
475 	status = wlan_serialization_register_comp_info_cb(psoc,
476 			WLAN_UMAC_COMP_DFS,
477 			WLAN_SER_CMD_SCAN,
478 			dfs_scan_serialization_comp_info_cb);
479 	if (status != QDF_STATUS_SUCCESS) {
480 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "Serialize scan cmd register failed");
481 		return status;
482 	}
483 
484 	return QDF_STATUS_SUCCESS;
485 }
486 
487 QDF_STATUS wifi_dfs_psoc_disable(struct wlan_objmgr_psoc *psoc)
488 {
489 	QDF_STATUS status;
490 
491 	status = wlan_serialization_deregister_comp_info_cb(psoc,
492 			WLAN_UMAC_COMP_DFS,
493 			WLAN_SER_CMD_SCAN);
494 	if (status != QDF_STATUS_SUCCESS) {
495 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "Serialize scan cmd deregister failed");
496 		return status;
497 	}
498 
499 	return QDF_STATUS_SUCCESS;
500 }
501