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