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