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