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