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