xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c (revision dae10a5fbc53d54c53c4ba24fa018ad8b1e7c008)
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 has the DFS dispatcher API implementation which is exposed
22  * to outside of DFS component.
23  */
24 #include "wlan_dfs_utils_api.h"
25 #include "wlan_dfs_mlme_api.h"
26 #include "../../core/src/dfs.h"
27 #include "../../core/src/dfs_zero_cac.h"
28 #include "../../core/src/dfs_etsi_precac.h"
29 #include <wlan_reg_services_api.h>
30 #include "../../core/src/dfs_random_chan_sel.h"
31 #ifdef QCA_DFS_USE_POLICY_MANAGER
32 #include "wlan_policy_mgr_api.h"
33 #endif
34 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT
35 #include <pld_common.h>
36 #endif
37 #include <qdf_module.h>
38 
39 struct dfs_nol_info {
40 	uint16_t num_chans;
41 	struct dfsreq_nolelem dfs_nol[DFS_MAX_NOL_CHANNEL];
42 };
43 
44 QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev)
45 {
46 	struct wlan_dfs *dfs;
47 
48 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
49 	if (!dfs)
50 		return  QDF_STATUS_E_FAILURE;
51 
52 	dfs_reset(dfs);
53 	dfs_nol_update(dfs);
54 	dfs_reset_precaclists(dfs);
55 	dfs_reset_etsiprecaclists(dfs);
56 
57 	return QDF_STATUS_SUCCESS;
58 }
59 
60 bool utils_dfs_freq_is_in_nol(struct wlan_objmgr_pdev *pdev, uint32_t freq)
61 {
62 	struct wlan_dfs *dfs;
63 
64 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
65 	if (!dfs)
66 		return false;
67 
68 	return dfs_freq_is_in_nol(dfs, freq);
69 }
70 
71 QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev,
72 		uint8_t prevchan_ieee,
73 		uint32_t prevchan_flags)
74 {
75 	struct wlan_dfs *dfs;
76 
77 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
78 	if (!dfs)
79 		return  QDF_STATUS_E_FAILURE;
80 
81 	dfs_cac_valid_reset(dfs, prevchan_ieee, prevchan_flags);
82 
83 	return QDF_STATUS_SUCCESS;
84 }
85 qdf_export_symbol(utils_dfs_cac_valid_reset);
86 
87 QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev)
88 {
89 	struct wlan_dfs *dfs;
90 
91 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
92 	if (!dfs)
93 		return  QDF_STATUS_E_FAILURE;
94 
95 	dfs_reset_precaclists(dfs);
96 
97 	return QDF_STATUS_SUCCESS;
98 }
99 qdf_export_symbol(utils_dfs_reset_precaclists);
100 
101 #ifdef QCA_SUPPORT_ETSI_PRECAC_DFS
102 QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev)
103 {
104 	struct wlan_dfs *dfs;
105 
106 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
107 	if (!dfs)
108 		return  QDF_STATUS_E_FAILURE;
109 
110 	dfs_reset_etsiprecaclists(dfs);
111 
112 	return QDF_STATUS_SUCCESS;
113 }
114 
115 qdf_export_symbol(utils_dfs_reset_etsi_precaclists);
116 #endif
117 
118 QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev)
119 {
120 	struct wlan_dfs *dfs;
121 
122 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
123 	if (!dfs)
124 		return  QDF_STATUS_E_FAILURE;
125 
126 	dfs_cancel_precac_timer(dfs);
127 
128 	return QDF_STATUS_SUCCESS;
129 }
130 qdf_export_symbol(utils_dfs_cancel_precac_timer);
131 
132 QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev)
133 {
134 	struct wlan_dfs *dfs;
135 
136 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
137 	if (!dfs) {
138 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs");
139 		return  QDF_STATUS_E_FAILURE;
140 	}
141 	dfs_start_precac_timer(dfs, dfs->dfs_precac_secondary_freq);
142 	return QDF_STATUS_SUCCESS;
143 }
144 
145 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
146 QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev,
147 					     uint8_t *ch_ieee)
148 {
149 	struct wlan_dfs *dfs;
150 
151 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
152 	if (!dfs) {
153 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs");
154 		return  QDF_STATUS_E_FAILURE;
155 	}
156 	dfs_decide_precac_preferred_chan(dfs, ch_ieee);
157 
158 	return QDF_STATUS_SUCCESS;
159 }
160 #endif
161 
162 QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev,
163 		bool *is_precac_done)
164 {
165 	struct wlan_dfs *dfs;
166 
167 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
168 	if (!dfs)
169 		return  QDF_STATUS_E_FAILURE;
170 
171 	*is_precac_done = dfs_is_precac_done(dfs, dfs->dfs_curchan);
172 
173 	return QDF_STATUS_SUCCESS;
174 }
175 qdf_export_symbol(utils_dfs_is_precac_done);
176 
177 #ifdef QCA_SUPPORT_ETSI_PRECAC_DFS
178 QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev,
179 					 bool *is_etsi_precac_done)
180 {
181 	struct wlan_dfs *dfs;
182 
183 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
184 	if (!dfs)
185 		return  QDF_STATUS_E_FAILURE;
186 
187 	*is_etsi_precac_done = dfs_is_etsi_precac_done(dfs);
188 
189 	return QDF_STATUS_SUCCESS;
190 }
191 
192 qdf_export_symbol(utils_dfs_is_etsi_precac_done);
193 #endif
194 
195 QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev)
196 {
197 	struct wlan_dfs *dfs;
198 
199 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
200 	if (!dfs)
201 		return  QDF_STATUS_E_FAILURE;
202 
203 	dfs_cancel_cac_timer(dfs);
204 
205 	return QDF_STATUS_SUCCESS;
206 }
207 qdf_export_symbol(utils_dfs_cancel_cac_timer);
208 
209 QDF_STATUS utils_dfs_start_cac_timer(struct wlan_objmgr_pdev *pdev)
210 {
211 	struct wlan_dfs *dfs;
212 
213 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
214 	if (!dfs)
215 		return  QDF_STATUS_E_FAILURE;
216 
217 	dfs_start_cac_timer(dfs);
218 
219 	return QDF_STATUS_SUCCESS;
220 }
221 qdf_export_symbol(utils_dfs_start_cac_timer);
222 
223 QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev)
224 {
225 	struct wlan_dfs *dfs;
226 
227 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
228 	if (!dfs)
229 		return  QDF_STATUS_E_FAILURE;
230 
231 	dfs_cac_stop(dfs);
232 	return  QDF_STATUS_SUCCESS;
233 }
234 qdf_export_symbol(utils_dfs_cac_stop);
235 
236 QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev)
237 {
238 	struct wlan_dfs *dfs;
239 
240 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
241 	if (!dfs)
242 		return  QDF_STATUS_E_FAILURE;
243 
244 	dfs_stacac_stop(dfs);
245 
246 	return QDF_STATUS_SUCCESS;
247 }
248 qdf_export_symbol(utils_dfs_stacac_stop);
249 
250 bool utils_dfs_is_curchan_subset_of_cac_started_chan(
251 		struct wlan_objmgr_pdev *pdev)
252 {
253 	struct wlan_dfs *dfs;
254 
255 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
256 	if (!dfs)
257 		return false;
258 
259 	return dfs_is_curchan_subset_of_cac_started_chan(dfs);
260 }
261 
262 bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev)
263 {
264 	struct wlan_dfs *dfs;
265 
266 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
267 	if (!dfs)
268 		return false;
269 
270 	return dfs->dfs_cac_aborted;
271 }
272 
273 void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev)
274 {
275 	struct wlan_dfs *dfs;
276 
277 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
278 	if (!dfs)
279 		return;
280 
281 	dfs_clear_cac_started_chan(dfs);
282 }
283 
284 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol)
285 {
286 	struct wlan_dfs *dfs;
287 
288 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
289 	if (!dfs)
290 		return  QDF_STATUS_E_FAILURE;
291 
292 	*usenol = dfs_get_use_nol(dfs);
293 
294 	return QDF_STATUS_SUCCESS;
295 }
296 qdf_export_symbol(utils_dfs_get_usenol);
297 
298 QDF_STATUS utils_dfs_radar_disable(struct wlan_objmgr_pdev *pdev)
299 {
300 	struct wlan_dfs *dfs;
301 
302 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
303 	if (!dfs)
304 		return  QDF_STATUS_E_FAILURE;
305 
306 	dfs_radar_disable(dfs);
307 
308 	return QDF_STATUS_SUCCESS;
309 }
310 qdf_export_symbol(utils_dfs_radar_disable);
311 
312 QDF_STATUS utils_dfs_set_update_nol_flag(struct wlan_objmgr_pdev *pdev,
313 		bool val)
314 {
315 	struct wlan_dfs *dfs;
316 
317 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
318 	if (!dfs)
319 		return  QDF_STATUS_E_FAILURE;
320 
321 	dfs_set_update_nol_flag(dfs, val);
322 
323 	return QDF_STATUS_SUCCESS;
324 }
325 qdf_export_symbol(utils_dfs_set_update_nol_flag);
326 
327 QDF_STATUS utils_dfs_get_update_nol_flag(struct wlan_objmgr_pdev *pdev,
328 		bool *nol_flag)
329 {
330 	struct wlan_dfs *dfs;
331 
332 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
333 	if (!dfs)
334 		return  QDF_STATUS_E_FAILURE;
335 
336 	*nol_flag = dfs_get_update_nol_flag(dfs);
337 
338 	return QDF_STATUS_SUCCESS;
339 }
340 qdf_export_symbol(utils_dfs_get_update_nol_flag);
341 
342 QDF_STATUS utils_dfs_get_dfs_use_nol(struct wlan_objmgr_pdev *pdev,
343 		int *dfs_use_nol)
344 {
345 	struct wlan_dfs *dfs;
346 
347 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
348 	if (!dfs)
349 		return  QDF_STATUS_E_FAILURE;
350 
351 	*dfs_use_nol = dfs_get_use_nol(dfs);
352 
353 	return QDF_STATUS_SUCCESS;
354 }
355 qdf_export_symbol(utils_dfs_get_dfs_use_nol);
356 
357 QDF_STATUS utils_dfs_get_nol_timeout(struct wlan_objmgr_pdev *pdev,
358 		int *dfs_nol_timeout)
359 {
360 	struct wlan_dfs *dfs;
361 
362 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
363 	if (!dfs)
364 		return  QDF_STATUS_E_FAILURE;
365 
366 	*dfs_nol_timeout = dfs_get_nol_timeout(dfs);
367 
368 	return QDF_STATUS_SUCCESS;
369 }
370 qdf_export_symbol(utils_dfs_get_nol_timeout);
371 
372 QDF_STATUS utils_dfs_nol_addchan(struct wlan_objmgr_pdev *pdev,
373 		uint16_t freq,
374 		uint32_t dfs_nol_timeout)
375 {
376 	struct wlan_dfs *dfs;
377 
378 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
379 	if (!dfs)
380 		return  QDF_STATUS_E_FAILURE;
381 
382 	DFS_NOL_ADD_CHAN_LOCKED(dfs, freq, dfs_nol_timeout);
383 
384 	return QDF_STATUS_SUCCESS;
385 }
386 qdf_export_symbol(utils_dfs_nol_addchan);
387 
388 QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev)
389 {
390 	struct wlan_dfs *dfs;
391 
392 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
393 	if (!dfs)
394 		return  QDF_STATUS_E_FAILURE;
395 
396 	dfs_nol_update(dfs);
397 
398 	return QDF_STATUS_SUCCESS;
399 }
400 qdf_export_symbol(utils_dfs_nol_update);
401 
402 QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev)
403 {
404 	struct wlan_dfs *dfs;
405 
406 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
407 	if (!dfs)
408 		return  QDF_STATUS_E_FAILURE;
409 
410 	dfs_second_segment_radar_disable(dfs);
411 
412 	return QDF_STATUS_SUCCESS;
413 }
414 
415 QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev,
416 		bool *ignore_dfs)
417 {
418 	struct wlan_dfs *dfs;
419 
420 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
421 	if (!dfs)
422 		return  QDF_STATUS_E_FAILURE;
423 
424 	*ignore_dfs = dfs->dfs_ignore_dfs;
425 
426 	return QDF_STATUS_SUCCESS;
427 }
428 qdf_export_symbol(utils_dfs_is_ignore_dfs);
429 
430 QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev,
431 		bool *is_cac_valid)
432 {
433 	struct wlan_dfs *dfs;
434 
435 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
436 	if (!dfs)
437 		return  QDF_STATUS_E_FAILURE;
438 
439 	*is_cac_valid = dfs->dfs_cac_valid;
440 
441 	return QDF_STATUS_SUCCESS;
442 }
443 qdf_export_symbol(utils_dfs_is_cac_valid);
444 
445 QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev,
446 		bool *ignore_cac)
447 {
448 	struct wlan_dfs *dfs;
449 
450 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
451 	if (!dfs)
452 		return  QDF_STATUS_E_FAILURE;
453 
454 	*ignore_cac = dfs->dfs_ignore_cac;
455 
456 	/*
457 	 * This is needed as, if after channel bandwidth reduction, channel
458 	 * change occurs using dothchanswitch or chan commands, resetting.
459 	 * dfs->dfs_ignore_cac will make sure we not skip CAC on the new channel
460 	 */
461 
462 	if (dfs->dfs_bw_reduced)
463 		dfs->dfs_ignore_cac = 0;
464 
465 	return QDF_STATUS_SUCCESS;
466 }
467 qdf_export_symbol(utils_dfs_is_ignore_cac);
468 
469 QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev,
470 		int val)
471 {
472 	struct wlan_dfs *dfs;
473 
474 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
475 	if (!dfs)
476 		return  QDF_STATUS_E_FAILURE;
477 
478 	dfs->dfs_cac_timer_running = val;
479 
480 	return QDF_STATUS_SUCCESS;
481 }
482 qdf_export_symbol(utils_dfs_set_cac_timer_running);
483 
484 QDF_STATUS utils_dfs_get_nol_chfreq_and_chwidth(struct wlan_objmgr_pdev *pdev,
485 		void *nollist,
486 		uint32_t *nol_chfreq,
487 		uint32_t *nol_chwidth,
488 		int index)
489 {
490 	struct wlan_dfs *dfs;
491 
492 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
493 	if (!dfs)
494 		return  QDF_STATUS_E_FAILURE;
495 
496 	dfs_get_nol_chfreq_and_chwidth(nollist, nol_chfreq, nol_chwidth, index);
497 
498 	return QDF_STATUS_SUCCESS;
499 }
500 qdf_export_symbol(utils_dfs_get_nol_chfreq_and_chwidth);
501 
502 QDF_STATUS utils_dfs_update_cur_chan_flags(struct wlan_objmgr_pdev *pdev,
503 		uint64_t flags,
504 		uint16_t flagext)
505 {
506 	struct wlan_dfs *dfs;
507 
508 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
509 	if (!dfs)
510 		return  QDF_STATUS_E_FAILURE;
511 
512 	dfs_update_cur_chan_flags(dfs, flags, flagext);
513 
514 	return QDF_STATUS_SUCCESS;
515 }
516 
517 static void utils_dfs_get_max_phy_mode(struct wlan_objmgr_pdev *pdev,
518 		uint32_t *phy_mode)
519 {
520 	return;
521 }
522 
523 static void utils_dfs_get_max_sup_width(struct wlan_objmgr_pdev *pdev,
524 		uint8_t *ch_width)
525 {
526 	return;
527 }
528 
529 /**
530  * utils_dfs_get_chan_list() - Get channel list from regdb based on current
531  *                             operating channel.
532  * @pdev: Pointer to DFS pdev object.
533  * @chan_list: Pointer to current channel list
534  * @num_chan: number of channels in the current channel list.
535  */
536 #ifndef QCA_DFS_USE_POLICY_MANAGER
537 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev,
538 	struct dfs_channel *chan_list, uint32_t *num_chan)
539 {
540 	int i = 0, j = 0;
541 	enum channel_state state;
542 	struct regulatory_channel *cur_chan_list;
543 	struct wlan_dfs *dfs;
544 
545 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
546 	if (!dfs)
547 		return;
548 
549 	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
550 			sizeof(struct regulatory_channel));
551 	if (!cur_chan_list) {
552 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "fail to alloc");
553 		*num_chan = 0;
554 		return;
555 	}
556 
557 	if (wlan_reg_get_current_chan_list(
558 			pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
559 		*num_chan = 0;
560 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
561 				"failed to get curr channel list");
562 		return;
563 	}
564 
565 	for (i = 0; i < NUM_CHANNELS; i++) {
566 		state = cur_chan_list[i].state;
567 		if (state == CHANNEL_STATE_DFS ||
568 				state == CHANNEL_STATE_ENABLE) {
569 			chan_list[j].dfs_ch_ieee = cur_chan_list[i].chan_num;
570 			chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq;
571 			if (state == CHANNEL_STATE_DFS)
572 				chan_list[j].dfs_ch_flagext =
573 					WLAN_CHAN_DFS;
574 			j++;
575 		}
576 	}
577 	*num_chan = j;
578 	qdf_mem_free(cur_chan_list);
579 
580 	return;
581 }
582 
583 /**
584  * utils_dfs_get_channel_list() - Get channel list from regdb component based
585  * on current channel list.
586  * @pdev: Pointer to pdev structure.
587  * @chan_list: Pointer to regdb channel list.
588  * @num_chan: number of channels.
589  *
590  * Get regdb channel list based on dfs current channel.
591  * ex: When  AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels
592  * so that the random channel function does not select either 2.4GHz or 4.9GHz
593  * channel.
594  */
595 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev,
596 	struct dfs_channel *chan_list, uint32_t *num_chan)
597 {
598 	struct dfs_channel *tmp_chan_list = NULL;
599 	struct wlan_dfs *dfs;
600 	bool is_curchan_5g;
601 	bool is_curchan_24g;
602 	bool is_curchan_49g;
603 	uint32_t chan_num;
604 	uint32_t center_freq;
605 	uint16_t flagext;
606 	int i, j = 0;
607 
608 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
609 	if (!dfs) {
610 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
611 		return;
612 	}
613 
614 	tmp_chan_list = qdf_mem_malloc(*num_chan * sizeof(*tmp_chan_list));
615 	if (!tmp_chan_list) {
616 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed");
617 		return;
618 	}
619 
620 	utils_dfs_get_chan_list(pdev, tmp_chan_list, num_chan);
621 
622 	chan_num = dfs->dfs_curchan->dfs_ch_ieee;
623 	center_freq = dfs->dfs_curchan->dfs_ch_freq;
624 	is_curchan_5g = WLAN_REG_IS_5GHZ_CH(chan_num);
625 	is_curchan_24g = WLAN_REG_IS_24GHZ_CH(chan_num);
626 	is_curchan_49g = WLAN_REG_IS_49GHZ_FREQ(center_freq);
627 
628 	for (i = 0; i < *num_chan; i++) {
629 		chan_num = tmp_chan_list[i].dfs_ch_ieee;
630 		center_freq = tmp_chan_list[i].dfs_ch_freq;
631 		flagext = tmp_chan_list[i].dfs_ch_flagext;
632 
633 		if (!dfs_mlme_check_allowed_prim_chanlist(pdev, chan_num))
634 			continue;
635 
636 		if ((is_curchan_5g) && WLAN_REG_IS_5GHZ_CH(chan_num)) {
637 			chan_list[j].dfs_ch_ieee = chan_num;
638 			chan_list[j].dfs_ch_freq = center_freq;
639 			chan_list[j].dfs_ch_flagext = flagext;
640 			j++;
641 		} else if ((is_curchan_24g) &&
642 				WLAN_REG_IS_24GHZ_CH(chan_num)) {
643 			chan_list[j].dfs_ch_ieee = chan_num;
644 			chan_list[j].dfs_ch_freq = center_freq;
645 			j++;
646 		} else if ((is_curchan_49g) &&
647 				WLAN_REG_IS_49GHZ_FREQ(center_freq)) {
648 			chan_list[j].dfs_ch_ieee = chan_num;
649 			chan_list[j].dfs_ch_freq = center_freq;
650 			j++;
651 		}
652 	}
653 
654 	*num_chan = j;
655 
656 	qdf_mem_free(tmp_chan_list);
657 }
658 
659 #else
660 
661 static void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev,
662 	struct dfs_channel *chan_list, uint32_t *num_chan)
663 {
664 	uint8_t pcl_ch[QDF_MAX_NUM_CHAN] = {0};
665 	uint8_t weight_list[QDF_MAX_NUM_CHAN] = {0};
666 	uint32_t len;
667 	uint32_t weight_len;
668 	int i;
669 	struct wlan_objmgr_psoc *psoc;
670 	uint32_t conn_count = 0;
671 
672 	psoc = wlan_pdev_get_psoc(pdev);
673 	if (!psoc) {
674 		*num_chan = 0;
675 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "null psoc");
676 		return;
677 	}
678 
679 	len = QDF_ARRAY_SIZE(pcl_ch);
680 	weight_len = QDF_ARRAY_SIZE(weight_list);
681 	conn_count = policy_mgr_mode_specific_connection_count(
682 			psoc, PM_SAP_MODE, NULL);
683 	if (0 == conn_count)
684 		policy_mgr_get_pcl(psoc, PM_SAP_MODE, pcl_ch,
685 				&len, weight_list, weight_len);
686 	else
687 		policy_mgr_get_pcl_for_existing_conn(psoc, PM_SAP_MODE, pcl_ch,
688 				&len, weight_list, weight_len, true);
689 
690 	if (*num_chan < len) {
691 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
692 				"Invalid len src=%d, dst=%d",
693 				*num_chan, len);
694 		*num_chan = 0;
695 		return;
696 	}
697 
698 	for (i = 0; i < len; i++) {
699 		chan_list[i].dfs_ch_ieee  = pcl_ch[i];
700 		chan_list[i].dfs_ch_freq  =
701 			wlan_reg_chan_to_freq(pdev, pcl_ch[i]);
702 	}
703 	*num_chan = i;
704 	dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i);
705 }
706 
707 /**
708  * utils_dfs_get_channel_list() - Wrapper function to get channel list from
709  * regdb component.
710  * @pdev: Pointer to pdev structure.
711  * @chan_list: Pointer to regdb channel list.
712  * @num_chan: number of channels.
713  */
714 static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev,
715 	struct dfs_channel *chan_list, uint32_t *num_chan)
716 {
717 	utils_dfs_get_chan_list(pdev, chan_list, num_chan);
718 }
719 #endif
720 
721 QDF_STATUS utils_dfs_get_random_channel(
722 	struct wlan_objmgr_pdev *pdev,
723 	uint16_t flags,
724 	struct ch_params *ch_params,
725 	uint32_t *hw_mode,
726 	uint8_t *target_chan,
727 	struct dfs_acs_info *acs_info)
728 {
729 	uint32_t dfs_reg;
730 	uint32_t num_chan = NUM_CHANNELS;
731 	struct wlan_dfs *dfs = NULL;
732 	struct wlan_objmgr_psoc *psoc;
733 	struct dfs_channel *chan_list = NULL;
734 	struct dfs_channel cur_chan;
735 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
736 
737 	*target_chan = 0;
738 	psoc = wlan_pdev_get_psoc(pdev);
739 	if (!psoc) {
740 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null psoc");
741 		goto random_chan_error;
742 	}
743 
744 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
745 	if (!dfs) {
746 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
747 		goto random_chan_error;
748 	}
749 
750 	wlan_reg_get_dfs_region(pdev, &dfs_reg);
751 	chan_list = qdf_mem_malloc(num_chan * sizeof(*chan_list));
752 	if (!chan_list) {
753 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "mem alloc failed");
754 		goto random_chan_error;
755 	}
756 
757 	utils_dfs_get_channel_list(pdev, chan_list, &num_chan);
758 	if (!num_chan) {
759 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "zero channels");
760 		goto random_chan_error;
761 	}
762 
763 	cur_chan.dfs_ch_vhtop_ch_freq_seg1 = ch_params->center_freq_seg0;
764 	cur_chan.dfs_ch_vhtop_ch_freq_seg2 = ch_params->center_freq_seg1;
765 
766 	if (!ch_params->ch_width)
767 		utils_dfs_get_max_sup_width(pdev,
768 				(uint8_t *)&ch_params->ch_width);
769 
770 	*target_chan = dfs_prepare_random_channel(dfs, chan_list,
771 		num_chan, flags, (uint8_t *)&ch_params->ch_width,
772 		&cur_chan, (uint8_t)dfs_reg, acs_info);
773 
774 	ch_params->center_freq_seg0 = cur_chan.dfs_ch_vhtop_ch_freq_seg1;
775 	ch_params->center_freq_seg1 = cur_chan.dfs_ch_vhtop_ch_freq_seg2;
776 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
777 			"input width=%d", ch_params->ch_width);
778 
779 	if (*target_chan) {
780 		wlan_reg_set_channel_params(pdev,
781 				*target_chan, 0, ch_params);
782 		utils_dfs_get_max_phy_mode(pdev, hw_mode);
783 		status = QDF_STATUS_SUCCESS;
784 	}
785 
786 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
787 			"ch=%d, seg0=%d, seg1=%d, width=%d",
788 			*target_chan, ch_params->center_freq_seg0,
789 			ch_params->center_freq_seg1, ch_params->ch_width);
790 
791 random_chan_error:
792 	qdf_mem_free(chan_list);
793 
794 	return status;
795 }
796 qdf_export_symbol(utils_dfs_get_random_channel);
797 
798 QDF_STATUS utils_dfs_bw_reduced_channel(
799 	struct wlan_objmgr_pdev *pdev,
800 	uint16_t flags,
801 	struct ch_params *ch_params,
802 	uint32_t *hw_mode,
803 	uint8_t *target_chan)
804 {
805 	struct wlan_dfs *dfs = NULL;
806 	struct wlan_objmgr_psoc *psoc;
807 	enum channel_state ch_state;
808 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
809 
810 	*target_chan = 0;
811 	psoc = wlan_pdev_get_psoc(pdev);
812 	if (!psoc) {
813 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null psoc");
814 		return status;
815 	}
816 
817 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
818 	if (!dfs) {
819 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
820 		return status;
821 	}
822 
823 	ch_state = reg_get_channel_state(pdev, dfs->dfs_curchan->dfs_ch_ieee);
824 
825 	if (ch_state == CHANNEL_STATE_DFS ||
826 	    ch_state == CHANNEL_STATE_ENABLE) {
827 		ch_params->center_freq_seg0 =
828 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1;
829 		ch_params->center_freq_seg1 =
830 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2;
831 		dfs->dfs_bw_reduced = 1;
832 		wlan_reg_set_channel_params(pdev,
833 					    dfs->dfs_curchan->dfs_ch_ieee,
834 					    0, ch_params);
835 
836 		*target_chan = dfs->dfs_curchan->dfs_ch_ieee;
837 		utils_dfs_get_max_phy_mode(pdev, hw_mode);
838 
839 		return QDF_STATUS_SUCCESS;
840 	}
841 
842 	return status;
843 }
844 
845 #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT
846 void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev)
847 {
848 	struct wlan_dfs *dfs;
849 	struct wlan_objmgr_psoc *psoc;
850 	qdf_device_t qdf_dev;
851 	struct dfs_nol_info *dfs_nolinfo;
852 	int len;
853 
854 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
855 	psoc = wlan_pdev_get_psoc(pdev);
856 	if (!dfs || !psoc) {
857 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
858 				"dfs %pK, psoc %pK", dfs, psoc);
859 		return;
860 	}
861 
862 	qdf_dev = psoc->soc_objmgr.qdf_dev;
863 	if (!qdf_dev->dev) {
864 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null device");
865 		return;
866 	}
867 
868 	dfs_nolinfo = qdf_mem_malloc(sizeof(*dfs_nolinfo));
869 	if (!dfs_nolinfo) {
870 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_nolinfo alloc fail");
871 		return;
872 	}
873 
874 	qdf_mem_zero(dfs_nolinfo, sizeof(*dfs_nolinfo));
875 	len = pld_wlan_get_dfs_nol(qdf_dev->dev, (void *)dfs_nolinfo,
876 				   (uint16_t)sizeof(*dfs_nolinfo));
877 	if (len > 0) {
878 		dfs_set_nol(dfs, dfs_nolinfo->dfs_nol, dfs_nolinfo->num_chans);
879 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol channels in pld");
880 		DFS_PRINT_NOL_LOCKED(dfs);
881 	} else {
882 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "no nol in pld");
883 	}
884 	qdf_mem_free(dfs_nolinfo);
885 }
886 #endif
887 qdf_export_symbol(utils_dfs_init_nol);
888 
889 #ifndef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT
890 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev)
891 {
892 }
893 #else
894 void utils_dfs_save_nol(struct wlan_objmgr_pdev *pdev)
895 {
896 	struct dfs_nol_info *dfs_nolinfo;
897 	struct wlan_dfs *dfs = NULL;
898 	struct wlan_objmgr_psoc *psoc;
899 	qdf_device_t qdf_dev;
900 	int num_chans = 0;
901 
902 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
903 	if (!dfs) {
904 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
905 		return;
906 	}
907 
908 	psoc = wlan_pdev_get_psoc(pdev);
909 	if (!psoc) {
910 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null psoc");
911 		return;
912 	}
913 
914 	qdf_dev = psoc->soc_objmgr.qdf_dev;
915 	if (!qdf_dev->dev) {
916 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null device");
917 		return;
918 	}
919 
920 	dfs_nolinfo = qdf_mem_malloc(sizeof(*dfs_nolinfo));
921 	if (!dfs_nolinfo) {
922 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_nolinfo alloc fail");
923 		return;
924 	}
925 
926 	qdf_mem_zero(dfs_nolinfo, sizeof(*dfs_nolinfo));
927 	DFS_GET_NOL_LOCKED(dfs, dfs_nolinfo->dfs_nol, &num_chans);
928 	if (num_chans > 0) {
929 
930 		if (num_chans > DFS_MAX_NOL_CHANNEL)
931 			dfs_nolinfo->num_chans = DFS_MAX_NOL_CHANNEL;
932 		else
933 			dfs_nolinfo->num_chans = num_chans;
934 
935 		pld_wlan_set_dfs_nol(qdf_dev->dev, (void *)dfs_nolinfo,
936 				     (uint16_t)sizeof(*dfs_nolinfo));
937 	}
938 	qdf_mem_free(dfs_nolinfo);
939 }
940 #endif
941 qdf_export_symbol(utils_dfs_save_nol);
942 
943 void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev)
944 {
945 	struct wlan_dfs *dfs = NULL;
946 
947 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
948 	if (!dfs) {
949 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
950 		return;
951 	}
952 
953 	DFS_PRINT_NOL_LOCKED(dfs);
954 }
955 qdf_export_symbol(utils_dfs_print_nol_channels);
956 
957 void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev)
958 {
959 	struct wlan_dfs *dfs = NULL;
960 
961 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
962 	if (!dfs) {
963 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
964 		return;
965 	}
966 
967 	/* First print list */
968 	DFS_PRINT_NOL_LOCKED(dfs);
969 
970 	/* clear local cache first */
971 	dfs_nol_timer_cleanup(dfs);
972 	dfs_nol_update(dfs);
973 
974 	/*
975 	 * update platform driver nol list with local cache which is zero,
976 	 * cleared in above step, so this will clear list in platform driver.
977 	 */
978 	utils_dfs_save_nol(pdev);
979 }
980 qdf_export_symbol(utils_dfs_clear_nol_channels);
981 
982 void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev,
983 		uint8_t *ch_list,
984 		uint8_t num_ch,
985 		bool nol_ch)
986 {
987 	/* TODO : Need locking?*/
988 	wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch);
989 }
990 qdf_export_symbol(utils_dfs_reg_update_nol_ch);
991 
992 uint8_t utils_dfs_freq_to_chan(uint32_t freq)
993 {
994 	uint8_t chan;
995 
996 	if (freq == 0)
997 		return 0;
998 
999 	if (freq > DFS_24_GHZ_BASE_FREQ && freq < DFS_CHAN_14_FREQ)
1000 		chan = ((freq - DFS_24_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ);
1001 	else if (freq == DFS_CHAN_14_FREQ)
1002 		chan = DFS_24_GHZ_CHANNEL_14;
1003 	else if ((freq > DFS_24_GHZ_BASE_FREQ) && (freq < DFS_5_GHZ_BASE_FREQ))
1004 		chan = (((freq - DFS_CHAN_15_FREQ) / DFS_CHAN_SPACING_20MHZ) +
1005 			DFS_24_GHZ_CHANNEL_15);
1006 	else
1007 		chan = (freq - DFS_5_GHZ_BASE_FREQ) / DFS_CHAN_SPACING_5MHZ;
1008 
1009 	return chan;
1010 }
1011 qdf_export_symbol(utils_dfs_freq_to_chan);
1012 
1013 uint32_t utils_dfs_chan_to_freq(uint8_t chan)
1014 {
1015 	if (chan == 0)
1016 		return 0;
1017 
1018 	if (chan < DFS_24_GHZ_CHANNEL_14)
1019 		return DFS_24_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ);
1020 	else if (chan == DFS_24_GHZ_CHANNEL_14)
1021 		return DFS_CHAN_14_FREQ;
1022 	else if (chan < DFS_24_GHZ_CHANNEL_27)
1023 		return DFS_CHAN_15_FREQ + ((chan - DFS_24_GHZ_CHANNEL_15) *
1024 				DFS_CHAN_SPACING_20MHZ);
1025 	else if (chan == DFS_5_GHZ_CHANNEL_170)
1026 		return DFS_CHAN_170_FREQ;
1027 	else
1028 		return DFS_5_GHZ_BASE_FREQ + (chan * DFS_CHAN_SPACING_5MHZ);
1029 }
1030 qdf_export_symbol(utils_dfs_chan_to_freq);
1031 
1032 #ifdef QCA_MCL_DFS_SUPPORT
1033 QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev,
1034 	enum phy_ch_width ch_width,
1035 	uint8_t temp_ch_lst_sz,
1036 	uint8_t *temp_ch_lst)
1037 {
1038 	struct wlan_dfs *dfs = NULL;
1039 
1040 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
1041 	if (!dfs) {
1042 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
1043 		return  QDF_STATUS_E_FAILURE;
1044 	}
1045 
1046 	return dfs_mark_leaking_ch(dfs, ch_width, temp_ch_lst_sz, temp_ch_lst);
1047 }
1048 qdf_export_symbol(utils_dfs_mark_leaking_ch);
1049 #endif
1050 
1051 int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev)
1052 {
1053 	enum dfs_reg dfsdomain;
1054 
1055 	wlan_reg_get_dfs_region(pdev, &dfsdomain);
1056 
1057 	return dfsdomain;
1058 }
1059 
1060 uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev)
1061 {
1062 	struct cur_regdmn_info cur_regdmn;
1063 
1064 	wlan_reg_get_curr_regdomain(pdev, &cur_regdmn);
1065 
1066 	return cur_regdmn.regdmn_pair_id;
1067 }
1068 
1069 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
1070 QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev,
1071 					   bool *is_spoof_check_failed)
1072 {
1073 	struct wlan_dfs *dfs;
1074 
1075 	if (!tgt_dfs_is_pdev_5ghz(pdev))
1076 		return QDF_STATUS_SUCCESS;
1077 
1078 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
1079 	if (!dfs) {
1080 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is null");
1081 		return  QDF_STATUS_E_FAILURE;
1082 	}
1083 
1084 	*is_spoof_check_failed = dfs->dfs_spoof_check_failed;
1085 
1086 	return QDF_STATUS_SUCCESS;
1087 }
1088 
1089 qdf_export_symbol(utils_dfs_is_spoof_check_failed);
1090 #endif
1091