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