xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_nol.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2002-2010, Atheros Communications Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: This file contains NOL related functionality, NOL being the non
20  * occupancy list. After radar has been detected in a particular channel,
21  * the channel cannot be used for a period of 30 minutes which is called
22  * the non occupancy. The NOL is basically a list of all the channels that
23  * radar has been detected on. Each channel has a 30 minute timer associated
24  * with it. This file contains the functionality to add a channel to the NOL,
25  * the NOL timer  function and the functionality to remove a channel from the
26  * NOL when its time is up.
27  */
28 
29 #include "../dfs.h"
30 #include "../dfs_channel.h"
31 #include "../dfs_ioctl_private.h"
32 #include "../dfs_internal.h"
33 #include <qdf_time.h>
34 #include <wlan_dfs_mlme_api.h>
35 #include <wlan_objmgr_vdev_obj.h>
36 #include <wlan_dfs_utils_api.h>
37 #include <wlan_reg_services_api.h>
38 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
39 #include "../dfs_process_radar_found_ind.h"
40 #include "../dfs_partial_offload_radar.h"
41 #endif
42 #include <qdf_types.h>
43 
44 void dfs_set_update_nol_flag(struct wlan_dfs *dfs, bool val)
45 {
46 	dfs->update_nol = val;
47 }
48 
49 bool dfs_get_update_nol_flag(struct wlan_dfs *dfs)
50 {
51 	return dfs->update_nol;
52 }
53 
54 /**
55  * dfs_nol_timeout() - NOL timeout function.
56  *
57  * Clears the WLAN_CHAN_DFS_RADAR_FOUND flag for the NOL timeout channel.
58  */
59 /* Unused function */
60 #ifdef CONFIG_CHAN_FREQ_API
61 static os_timer_func(dfs_nol_timeout)
62 {
63 	struct dfs_channel *c = NULL, lc;
64 	unsigned long oldest, now;
65 	struct wlan_dfs *dfs = NULL;
66 	int i;
67 	int nchans = 0;
68 
69 	c = &lc;
70 
71 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
72 	dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans);
73 
74 	now = oldest = qdf_system_ticks();
75 	for (i = 0; i < nchans; i++) {
76 		dfs_mlme_get_dfs_channels_for_freq
77 			(dfs->dfs_pdev_obj,
78 			 &c->dfs_ch_freq,
79 			 &c->dfs_ch_flags,
80 			 &c->dfs_ch_flagext,
81 			 &c->dfs_ch_ieee,
82 			 &c->dfs_ch_vhtop_ch_freq_seg1,
83 			 &c->dfs_ch_vhtop_ch_freq_seg2,
84 			 &c->dfs_ch_mhz_freq_seg1,
85 			 &c->dfs_ch_mhz_freq_seg2,
86 			 i);
87 		if (WLAN_IS_CHAN_RADAR(c)) {
88 			if (qdf_system_time_after_eq(now,
89 						     dfs->dfs_nol_event[i] +
90 						     dfs_get_nol_timeout(dfs))) {
91 				c->dfs_ch_flagext &= ~WLAN_CHAN_DFS_RADAR_FOUND;
92 				if (c->dfs_ch_flags & WLAN_CHAN_DFS_RADAR) {
93 					/*
94 					 * NB: do this here so we get only one
95 					 * msg instead of one for every channel
96 					 * table entry.
97 					 */
98 					dfs_debug(dfs, WLAN_DEBUG_DFS,
99 						  "radar on channel %u (%u MHz) cleared after timeout",
100 						  c->dfs_ch_ieee,
101 						  c->dfs_ch_freq);
102 				}
103 			} else if (dfs->dfs_nol_event[i] < oldest) {
104 				oldest = dfs->dfs_nol_event[i];
105 			}
106 		}
107 	}
108 	if (oldest != now) {
109 		/* Arrange to process next channel up for a status change. */
110 		qdf_timer_mod(&dfs->dfs_nol_timer,
111 			      dfs_get_nol_timeout(dfs) -
112 			      qdf_system_ticks_to_msecs(qdf_system_ticks()));
113 	}
114 }
115 #else
116 #ifdef CONFIG_CHAN_NUM_API
117 static os_timer_func(dfs_nol_timeout)
118 {
119 	struct dfs_channel *c = NULL, lc;
120 	unsigned long oldest, now;
121 	struct wlan_dfs *dfs = NULL;
122 	int i;
123 	int nchans = 0;
124 
125 	c = &lc;
126 
127 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
128 	dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans);
129 
130 	now = oldest = qdf_system_ticks();
131 	for (i = 0; i < nchans; i++) {
132 		dfs_mlme_get_dfs_ch_channels(dfs->dfs_pdev_obj,
133 				&(c->dfs_ch_freq),
134 				&(c->dfs_ch_flags),
135 				&(c->dfs_ch_flagext),
136 				&(c->dfs_ch_ieee),
137 				&(c->dfs_ch_vhtop_ch_freq_seg1),
138 				&(c->dfs_ch_vhtop_ch_freq_seg2),
139 				i);
140 		if (WLAN_IS_CHAN_RADAR(c)) {
141 			if (qdf_system_time_after_eq(now,
142 						dfs->dfs_nol_event[i] +
143 						dfs_get_nol_timeout(dfs))) {
144 				c->dfs_ch_flagext &=
145 					~WLAN_CHAN_DFS_RADAR_FOUND;
146 				if (c->dfs_ch_flags &
147 						WLAN_CHAN_DFS_RADAR) {
148 					/*
149 					 * NB: do this here so we get only one
150 					 * msg instead of one for every channel
151 					 * table entry.
152 					 */
153 					dfs_debug(dfs, WLAN_DEBUG_DFS,
154 						"radar on channel %u (%u MHz) cleared after timeout",
155 
156 						c->dfs_ch_ieee,
157 						c->dfs_ch_freq);
158 				}
159 			} else if (dfs->dfs_nol_event[i] < oldest)
160 				oldest = dfs->dfs_nol_event[i];
161 		}
162 	}
163 	if (oldest != now) {
164 		/* Arrange to process next channel up for a status change. */
165 		qdf_timer_mod(&dfs->dfs_nol_timer,
166 				dfs_get_nol_timeout(dfs) -
167 				qdf_system_ticks_to_msecs(qdf_system_ticks()));
168 	}
169 }
170 #endif
171 #endif
172 
173 /**
174  * dfs_nol_elem_free_work_cb -  Free NOL element
175  *
176  * Free the NOL element memory
177  */
178 static void dfs_nol_elem_free_work_cb(void *context)
179 {
180 	struct wlan_dfs *dfs = (struct wlan_dfs *)context;
181 	struct dfs_nolelem *nol_head;
182 
183 	while (true) {
184 		WLAN_DFSNOL_LOCK(dfs);
185 
186 		nol_head = TAILQ_FIRST(&dfs->dfs_nol_free_list);
187 		if (nol_head) {
188 			TAILQ_REMOVE(&dfs->dfs_nol_free_list, nol_head,
189 				     nolelem_list);
190 			WLAN_DFSNOL_UNLOCK(dfs);
191 
192 			qdf_timer_free(&nol_head->nol_timer);
193 			qdf_mem_free(nol_head);
194 		} else {
195 			WLAN_DFSNOL_UNLOCK(dfs);
196 			break;
197 		}
198 	}
199 }
200 
201 void dfs_nol_timer_init(struct wlan_dfs *dfs)
202 {
203 	qdf_timer_init(NULL,
204 			&(dfs->dfs_nol_timer),
205 			dfs_nol_timeout,
206 			(void *)(dfs),
207 			QDF_TIMER_TYPE_WAKE_APPS);
208 }
209 
210 void dfs_nol_attach(struct wlan_dfs *dfs)
211 {
212 	dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
213 	dfs_nol_timer_init(dfs);
214 	qdf_create_work(NULL, &dfs->dfs_nol_elem_free_work,
215 			dfs_nol_elem_free_work_cb, dfs);
216 	TAILQ_INIT(&dfs->dfs_nol_free_list);
217 	dfs->dfs_use_nol = 1;
218 	WLAN_DFSNOL_LOCK_CREATE(dfs);
219 }
220 
221 void dfs_nol_detach(struct wlan_dfs *dfs)
222 {
223 	dfs_nol_timer_cleanup(dfs);
224 	qdf_flush_work(&dfs->dfs_nol_elem_free_work);
225 	qdf_destroy_work(NULL, &dfs->dfs_nol_elem_free_work);
226 	WLAN_DFSNOL_LOCK_DESTROY(dfs);
227 }
228 
229 void dfs_nol_timer_detach(struct wlan_dfs *dfs)
230 {
231 	qdf_timer_free(&dfs->dfs_nol_timer);
232 }
233 
234 /**
235  * dfs_nol_delete() - Delete the given frequency/chwidth from the NOL.
236  * @dfs: Pointer to wlan_dfs structure.
237  * @delfreq: Freq to delete.
238  * @delchwidth: Channel width to delete.
239  */
240 static void dfs_nol_delete(struct wlan_dfs *dfs,
241 		uint16_t delfreq,
242 		uint16_t delchwidth)
243 {
244 	struct dfs_nolelem *nol, **prev_next;
245 
246 	if (!dfs) {
247 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
248 		return;
249 	}
250 
251 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
252 		"remove channel=%d/%d MHz from NOL",
253 		 delfreq, delchwidth);
254 	prev_next = &(dfs->dfs_nol);
255 	nol = dfs->dfs_nol;
256 	while (nol) {
257 		if (nol->nol_freq == delfreq &&
258 			nol->nol_chwidth == delchwidth) {
259 			*prev_next = nol->nol_next;
260 			dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
261 				"removing channel %d/%dMHz from NOL tstamp=%d",
262 				 nol->nol_freq,
263 				nol->nol_chwidth,
264 				(qdf_system_ticks_to_msecs
265 				 (qdf_system_ticks()) / 1000));
266 			TAILQ_INSERT_TAIL(&dfs->dfs_nol_free_list,
267 						nol, nolelem_list);
268 			nol = *prev_next;
269 
270 			/* Update the NOL counter. */
271 			dfs->dfs_nol_count--;
272 
273 			/* Be paranoid! */
274 			if (dfs->dfs_nol_count < 0) {
275 				dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "dfs_nol_count < 0; eek!");
276 				dfs->dfs_nol_count = 0;
277 			}
278 
279 		} else {
280 			prev_next = &(nol->nol_next);
281 			nol = nol->nol_next;
282 		}
283 	}
284 }
285 
286 #ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
287 /**
288  * dfs_switch_to_postnol_chan_if_nol_expired() - Find if NOL is expired
289  * in the postNOL channel configured. If true, trigger channel change.
290  * @dfs: Pointer to DFS of wlan_dfs structure.
291  *
292  * Return: True, if channel change is triggered, else false.
293  */
294 static bool
295 dfs_switch_to_postnol_chan_if_nol_expired(struct wlan_dfs *dfs)
296 {
297 	struct dfs_channel chan;
298 	struct dfs_channel *curchan = dfs->dfs_curchan;
299 	bool is_curchan_11ac = false, is_curchan_11axa = false;
300 	enum wlan_phymode postnol_phymode;
301 
302 	if (!dfs->dfs_chan_postnol_freq)
303 		return false;
304 
305 	if (WLAN_IS_CHAN_11AC_VHT20(curchan) ||
306 	    WLAN_IS_CHAN_11AC_VHT40(curchan) ||
307 	    WLAN_IS_CHAN_11AC_VHT80(curchan) ||
308 	    WLAN_IS_CHAN_11AC_VHT160(curchan) ||
309 	    WLAN_IS_CHAN_11AC_VHT80_80(curchan))
310 		is_curchan_11ac = true;
311 	else if (WLAN_IS_CHAN_11AXA_HE20(curchan) ||
312 		 WLAN_IS_CHAN_11AXA_HE40PLUS(curchan) ||
313 		 WLAN_IS_CHAN_11AXA_HE40MINUS(curchan) ||
314 		 WLAN_IS_CHAN_11AXA_HE80(curchan) ||
315 		 WLAN_IS_CHAN_11AXA_HE160(curchan) ||
316 		 WLAN_IS_CHAN_11AXA_HE80_80(curchan))
317 		is_curchan_11axa = true;
318 
319 	switch (dfs->dfs_chan_postnol_mode) {
320 	case CH_WIDTH_20MHZ:
321 		if (is_curchan_11ac)
322 			postnol_phymode = WLAN_PHYMODE_11AC_VHT20;
323 		else if (is_curchan_11axa)
324 			postnol_phymode = WLAN_PHYMODE_11AXA_HE20;
325 		else
326 			return false;
327 		break;
328 	case CH_WIDTH_40MHZ:
329 		if (is_curchan_11ac)
330 			postnol_phymode = WLAN_PHYMODE_11AC_VHT40;
331 		else if (is_curchan_11axa)
332 			postnol_phymode = WLAN_PHYMODE_11AXA_HE40;
333 		else
334 			return false;
335 		break;
336 	case CH_WIDTH_80MHZ:
337 		if (is_curchan_11ac)
338 			postnol_phymode = WLAN_PHYMODE_11AC_VHT80;
339 		else if (is_curchan_11axa)
340 			postnol_phymode = WLAN_PHYMODE_11AXA_HE80;
341 		else
342 			return false;
343 		break;
344 	case CH_WIDTH_160MHZ:
345 		if (is_curchan_11ac)
346 			postnol_phymode = WLAN_PHYMODE_11AC_VHT160;
347 		else if (is_curchan_11axa)
348 			postnol_phymode = WLAN_PHYMODE_11AXA_HE160;
349 		else
350 			return false;
351 		break;
352 	default:
353 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
354 			"Invalid postNOL mode set. Cannot switch to the chan");
355 		return false;
356 	}
357 
358 	qdf_mem_zero(&chan, sizeof(struct dfs_channel));
359 	if (QDF_STATUS_SUCCESS !=
360 		dfs_mlme_find_dot11_chan_for_freq(
361 			dfs->dfs_pdev_obj,
362 			dfs->dfs_chan_postnol_freq,
363 			dfs->dfs_chan_postnol_cfreq2,
364 			postnol_phymode,
365 			&chan.dfs_ch_freq,
366 			&chan.dfs_ch_flags,
367 			&chan.dfs_ch_flagext,
368 			&chan.dfs_ch_ieee,
369 			&chan.dfs_ch_vhtop_ch_freq_seg1,
370 			&chan.dfs_ch_vhtop_ch_freq_seg2,
371 			&chan.dfs_ch_mhz_freq_seg1,
372 			&chan.dfs_ch_mhz_freq_seg2)) {
373 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
374 			"Channel %d not found for mode %d and cfreq2 %d",
375 			dfs->dfs_chan_postnol_freq,
376 			postnol_phymode,
377 			dfs->dfs_chan_postnol_cfreq2);
378 		return false;
379 	}
380 	if (WLAN_IS_CHAN_RADAR(&chan))
381 		return false;
382 
383 	if (global_dfs_to_mlme.mlme_postnol_chan_switch)
384 		global_dfs_to_mlme.mlme_postnol_chan_switch(
385 				dfs->dfs_pdev_obj,
386 				dfs->dfs_chan_postnol_freq,
387 				dfs->dfs_chan_postnol_cfreq2,
388 				postnol_phymode);
389 	return true;
390 }
391 #else
392 static inline bool
393 dfs_switch_to_postnol_chan_if_nol_expired(struct wlan_dfs *dfs)
394 {
395 	return false;
396 }
397 #endif
398 
399 /**
400  * dfs_remove_from_nol() - Remove the freq from NOL list.
401  *
402  * When NOL times out, this function removes the channel from NOL list.
403  */
404 #ifdef CONFIG_CHAN_FREQ_API
405 static os_timer_func(dfs_remove_from_nol)
406 {
407 	struct dfs_nolelem *nol_arg;
408 	struct wlan_dfs *dfs;
409 	uint16_t delfreq;
410 	uint16_t delchwidth;
411 	uint8_t chan;
412 
413 	OS_GET_TIMER_ARG(nol_arg, struct dfs_nolelem *);
414 
415 	dfs = nol_arg->nol_dfs;
416 	delfreq = nol_arg->nol_freq;
417 	delchwidth = nol_arg->nol_chwidth;
418 
419 	/* Delete the given NOL entry. */
420 	DFS_NOL_DELETE_CHAN_LOCKED(dfs, delfreq, delchwidth);
421 
422 	/* Update the wireless stack with the new NOL. */
423 	dfs_nol_update(dfs);
424 
425 	dfs_mlme_nol_timeout_notification(dfs->dfs_pdev_obj);
426 	chan = utils_dfs_freq_to_chan(delfreq);
427 	utils_dfs_deliver_event(dfs->dfs_pdev_obj, delfreq,
428 				WLAN_EV_NOL_FINISHED);
429 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
430 		  "remove channel %d from nol", chan);
431 	utils_dfs_unmark_precac_nol_for_freq(dfs->dfs_pdev_obj, delfreq);
432 
433 	utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
434 					     &delfreq, 1, DFS_NOL_RESET);
435 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
436 
437 	/*
438 	 * Check if a channel is configured by the user to which we have to
439 	 * switch after it's NOL expiry. If that is the case, change
440 	 * channel immediately.
441 	 *
442 	 * If a channel switch is required (indicated by the return value of
443 	 * dfs_switch_to_postnol_chan_if_nol_expired), return from this function
444 	 * without posting Start event to Agile SM. That will be taken care
445 	 * of, after VAP start.
446 	 */
447 	if (dfs_switch_to_postnol_chan_if_nol_expired(dfs))
448 		return;
449 
450 	utils_dfs_agile_sm_deliver_evt(dfs->dfs_pdev_obj,
451 				       DFS_AGILE_SM_EV_AGILE_START);
452 }
453 #else
454 #ifdef CONFIG_CHAN_NUM_API
455 static os_timer_func(dfs_remove_from_nol)
456 {
457 	struct dfs_nolelem *nol_arg;
458 	struct wlan_dfs *dfs;
459 	uint16_t delfreq;
460 	uint16_t delchwidth;
461 	uint8_t chan;
462 
463 	OS_GET_TIMER_ARG(nol_arg, struct dfs_nolelem *);
464 
465 	dfs = nol_arg->nol_dfs;
466 	delfreq = nol_arg->nol_freq;
467 	delchwidth = nol_arg->nol_chwidth;
468 
469 	/* Delete the given NOL entry. */
470 	DFS_NOL_DELETE_CHAN_LOCKED(dfs, delfreq, delchwidth);
471 
472 	/* Update the wireless stack with the new NOL. */
473 	dfs_nol_update(dfs);
474 
475 	dfs_mlme_nol_timeout_notification(dfs->dfs_pdev_obj);
476 	chan = utils_dfs_freq_to_chan(delfreq);
477 	utils_dfs_deliver_event(dfs->dfs_pdev_obj, delfreq,
478 				WLAN_EV_NOL_FINISHED);
479 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
480 		    "remove channel %d from nol", chan);
481 	utils_dfs_unmark_precac_nol(dfs->dfs_pdev_obj, chan);
482 	utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
483 				    &chan, 1, DFS_NOL_RESET);
484 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
485 }
486 #endif
487 #endif
488 
489 void dfs_print_nol(struct wlan_dfs *dfs)
490 {
491 	struct dfs_nolelem *nol;
492 	int i = 0;
493 	uint32_t diff_ms, remaining_sec;
494 
495 	if (!dfs) {
496 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
497 		return;
498 	}
499 
500 	nol = dfs->dfs_nol;
501 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, "NOL");
502 	while (nol) {
503 		diff_ms = qdf_do_div(qdf_get_monotonic_boottime() -
504 				     nol->nol_start_us, 1000);
505 		diff_ms = (nol->nol_timeout_ms - diff_ms);
506 		remaining_sec = diff_ms / 1000; /* Convert to seconds */
507 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
508 			"nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol start_us=%llu",
509 			i++, nol->nol_freq,
510 			nol->nol_chwidth,
511 			remaining_sec,
512 			nol->nol_start_us);
513 		nol = nol->nol_next;
514 	}
515 }
516 
517 void dfs_print_nolhistory(struct wlan_dfs *dfs)
518 {
519 	struct dfs_channel *chan_list;
520 	int i, j;
521 	int nchans;
522 
523 	if (!dfs) {
524 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
525 		return;
526 	}
527 
528 	nchans = dfs_get_num_chans();
529 
530 	chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list));
531 	if (!chan_list)
532 		return;
533 
534 	utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj,
535 					    (void *)chan_list, &nchans);
536 	if (!nchans) {
537 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans");
538 		qdf_mem_free(chan_list);
539 		return;
540 	}
541 
542 	for (i = 0, j = 0; i < nchans; i++, j++)
543 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
544 			 "nolhistory = %d channel = %d MHz",
545 			 j, chan_list[i].dfs_ch_freq);
546 
547 	qdf_mem_free(chan_list);
548 }
549 
550 void dfs_get_nol(struct wlan_dfs *dfs,
551 		struct dfsreq_nolelem *dfs_nol,
552 		int *nchan)
553 {
554 	struct dfs_nolelem *nol;
555 
556 	*nchan = 0;
557 
558 	if (!dfs) {
559 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
560 		return;
561 	}
562 
563 	nol = dfs->dfs_nol;
564 	while (nol) {
565 		dfs_nol[*nchan].nol_freq = nol->nol_freq;
566 		dfs_nol[*nchan].nol_chwidth = nol->nol_chwidth;
567 		dfs_nol[*nchan].nol_start_us = nol->nol_start_us;
568 		dfs_nol[*nchan].nol_timeout_ms = nol->nol_timeout_ms;
569 		++(*nchan);
570 		nol = nol->nol_next;
571 	}
572 }
573 
574 #ifdef CONFIG_CHAN_FREQ_API
575 void dfs_set_nol(struct wlan_dfs *dfs,
576 		 struct dfsreq_nolelem *dfs_nol,
577 		 int nchan)
578 {
579 #define TIME_IN_MS 1000
580 	uint32_t nol_time_lft_ms;
581 	struct dfs_channel chan;
582 	int i;
583 
584 	if (!dfs) {
585 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
586 		return;
587 	}
588 
589 	for (i = 0; i < nchan; i++) {
590 		nol_time_lft_ms = qdf_do_div(qdf_get_monotonic_boottime() -
591 					     dfs_nol[i].nol_start_us, 1000);
592 
593 		if (nol_time_lft_ms < dfs_nol[i].nol_timeout_ms) {
594 			chan.dfs_ch_freq = dfs_nol[i].nol_freq;
595 			chan.dfs_ch_flags = 0;
596 			chan.dfs_ch_flagext = 0;
597 			nol_time_lft_ms =
598 				(dfs_nol[i].nol_timeout_ms - nol_time_lft_ms);
599 
600 			DFS_NOL_ADD_CHAN_LOCKED(dfs, chan.dfs_ch_freq,
601 						(nol_time_lft_ms / TIME_IN_MS));
602 			utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
603 							     &chan.dfs_ch_freq,
604 							     1, DFS_NOL_SET);
605 		}
606 	}
607 #undef TIME_IN_MS
608 	dfs_nol_update(dfs);
609 }
610 #else
611 #ifdef CONFIG_CHAN_NUM_API
612 void dfs_set_nol(struct wlan_dfs *dfs,
613 		struct dfsreq_nolelem *dfs_nol,
614 		int nchan)
615 {
616 #define TIME_IN_MS 1000
617 	uint32_t nol_time_left_ms;
618 	struct dfs_channel chan;
619 	int i;
620 	uint8_t chan_num;
621 
622 	if (!dfs) {
623 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
624 		return;
625 	}
626 
627 	for (i = 0; i < nchan; i++) {
628 		nol_time_left_ms = qdf_do_div(qdf_get_monotonic_boottime() -
629 					      dfs_nol[i].nol_start_us, 1000);
630 
631 		if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) {
632 			chan.dfs_ch_freq = dfs_nol[i].nol_freq;
633 			chan.dfs_ch_flags = 0;
634 			chan.dfs_ch_flagext = 0;
635 			nol_time_left_ms =
636 				(dfs_nol[i].nol_timeout_ms - nol_time_left_ms);
637 
638 			DFS_NOL_ADD_CHAN_LOCKED(dfs, chan.dfs_ch_freq,
639 					(nol_time_left_ms / TIME_IN_MS));
640 			chan_num = utils_dfs_freq_to_chan(chan.dfs_ch_freq);
641 			utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
642 						&chan_num, 1, DFS_NOL_SET);
643 		}
644 	}
645 #undef TIME_IN_MS
646 	dfs_nol_update(dfs);
647 }
648 #endif
649 #endif
650 
651 void dfs_nol_addchan(struct wlan_dfs *dfs,
652 		uint16_t freq,
653 		uint32_t dfs_nol_timeout)
654 {
655 #define TIME_IN_MS 1000
656 #define TIME_IN_US (TIME_IN_MS * 1000)
657 	struct dfs_nolelem *nol, *elem, *prev;
658 	/* For now, assume all events are 20MHz wide. */
659 	int ch_width = 20;
660 
661 	if (!dfs) {
662 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
663 		return;
664 	}
665 	nol = dfs->dfs_nol;
666 	prev = dfs->dfs_nol;
667 	elem = NULL;
668 	while (nol) {
669 		if ((nol->nol_freq == freq) &&
670 				(nol->nol_chwidth == ch_width)) {
671 			nol->nol_start_us = qdf_get_monotonic_boottime();
672 			nol->nol_timeout_ms = dfs_nol_timeout * TIME_IN_MS;
673 
674 			dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
675 				"Update OS Ticks for NOL %d MHz / %d MHz",
676 				 nol->nol_freq, nol->nol_chwidth);
677 
678 			qdf_timer_stop(&nol->nol_timer);
679 			qdf_timer_mod(&nol->nol_timer,
680 					dfs_nol_timeout * TIME_IN_MS);
681 			return;
682 		}
683 		prev = nol;
684 		nol = nol->nol_next;
685 	}
686 
687 	/* Add a new element to the NOL. */
688 	elem = (struct dfs_nolelem *)qdf_mem_malloc(sizeof(struct dfs_nolelem));
689 	if (!elem)
690 		goto bad;
691 
692 	qdf_mem_zero(elem, sizeof(*elem));
693 	elem->nol_dfs = dfs;
694 	elem->nol_freq = freq;
695 	elem->nol_chwidth = ch_width;
696 	elem->nol_start_us = qdf_get_monotonic_boottime();
697 	elem->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS;
698 	elem->nol_next = NULL;
699 	if (prev) {
700 		prev->nol_next = elem;
701 	} else {
702 		/* This is the first element in the NOL. */
703 		dfs->dfs_nol = elem;
704 	}
705 
706 	qdf_timer_init(NULL,
707 		       &elem->nol_timer, dfs_remove_from_nol,
708 		       elem, QDF_TIMER_TYPE_WAKE_APPS);
709 
710 	qdf_timer_mod(&elem->nol_timer, dfs_nol_timeout * TIME_IN_MS);
711 
712 	/* Update the NOL counter. */
713 	dfs->dfs_nol_count++;
714 
715 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
716 		"new NOL channel %d MHz / %d MHz",
717 		 elem->nol_freq, elem->nol_chwidth);
718 	return;
719 
720 bad:
721 	dfs_debug(dfs, WLAN_DEBUG_DFS_NOL | WLAN_DEBUG_DFS,
722 		"failed to allocate memory for nol entry");
723 
724 #undef TIME_IN_MS
725 #undef TIME_IN_US
726 }
727 
728 void dfs_get_nol_chfreq_and_chwidth(struct dfsreq_nolelem *dfs_nol,
729 		uint32_t *nol_chfreq,
730 		uint32_t *nol_chwidth,
731 		int index)
732 {
733 	if (!dfs_nol)
734 		return;
735 
736 	*nol_chfreq = dfs_nol[index].nol_freq;
737 	*nol_chwidth = dfs_nol[index].nol_chwidth;
738 }
739 
740 void dfs_nol_update(struct wlan_dfs *dfs)
741 {
742 	struct dfsreq_nolelem *dfs_nol;
743 	int nlen;
744 
745 	if (!dfs->dfs_nol_count) {
746 		dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, "dfs_nol_count is zero");
747 		dfs_mlme_clist_update(dfs->dfs_pdev_obj, NULL, 0);
748 		return;
749 	}
750 
751 	/*
752 	 * Allocate enough entries to store the NOL. At least on Linux
753 	 * (don't ask why), if you allocate a 0 entry array, the
754 	 * returned pointer is 0x10.  Make sure you're aware of this
755 	 * when you start debugging.
756 	 */
757 	dfs_nol = (struct dfsreq_nolelem *)qdf_mem_malloc(
758 		sizeof(struct dfsreq_nolelem) * dfs->dfs_nol_count);
759 
760 	/*
761 	 * XXX TODO: if this fails, just schedule a task to retry
762 	 * updating the NOL at a later stage.  That way the NOL
763 	 * update _DOES_ happen - hopefully the failure was just
764 	 * temporary.
765 	 */
766 	if (!dfs_nol)
767 		return;
768 
769 	DFS_GET_NOL_LOCKED(dfs, dfs_nol, &nlen);
770 
771 	/* Be suitably paranoid for now. */
772 	if (nlen != dfs->dfs_nol_count)
773 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "nlen (%d) != dfs->dfs_nol_count (%d)!",
774 			 nlen, dfs->dfs_nol_count);
775 
776 	/*
777 	 * Call the driver layer to have it recalculate the NOL flags
778 	 * for each driver/umac channel. If the list is empty, pass
779 	 * NULL instead of dfs_nol. The operating system may have some
780 	 * special representation for "malloc a 0 byte memory region"
781 	 * - for example, Linux 2.6.38-13 (ubuntu) returns 0x10 rather
782 	 * than a valid allocation (and is likely not NULL so the
783 	 * pointer doesn't match NULL checks in any later code.
784 	 */
785 	dfs_mlme_clist_update(dfs->dfs_pdev_obj,
786 			(nlen > 0) ? dfs_nol : NULL,
787 			nlen);
788 
789 	qdf_mem_free(dfs_nol);
790 }
791 
792 void dfs_nol_free_list(struct wlan_dfs *dfs)
793 {
794 	struct dfs_nolelem *nol = dfs->dfs_nol, *prev;
795 
796 	while (nol) {
797 		prev = nol;
798 		nol = nol->nol_next;
799 		qdf_mem_free(prev);
800 		/* Update the NOL counter. */
801 		dfs->dfs_nol_count--;
802 
803 		if (dfs->dfs_nol_count < 0) {
804 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_nol_count < 0");
805 			ASSERT(0);
806 		}
807 	}
808 
809 	dfs->dfs_nol = NULL;
810 }
811 
812 #ifdef CONFIG_CHAN_FREQ_API
813 void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
814 {
815 	struct dfs_nolelem *nol;
816 	uint16_t nol_freq;
817 
818 	while (true) {
819 		WLAN_DFSNOL_LOCK(dfs);
820 
821 		nol = dfs->dfs_nol;
822 		if (nol) {
823 			dfs->dfs_nol = nol->nol_next;
824 			dfs->dfs_nol_count--;
825 			nol_freq = nol->nol_freq;
826 			WLAN_DFSNOL_UNLOCK(dfs);
827 			utils_dfs_reg_update_nol_chan_for_freq(
828 					dfs->dfs_pdev_obj,
829 					&nol_freq,
830 					1,
831 					DFS_NOL_RESET);
832 
833 			qdf_timer_free(&nol->nol_timer);
834 			qdf_mem_free(nol);
835 		} else {
836 			WLAN_DFSNOL_UNLOCK(dfs);
837 			break;
838 		}
839 	}
840 }
841 #else
842 #ifdef CONFIG_CHAN_NUM_API
843 void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
844 {
845 	struct dfs_nolelem *nol;
846 	uint8_t nol_chan;
847 
848 	while (true) {
849 		WLAN_DFSNOL_LOCK(dfs);
850 
851 		nol = dfs->dfs_nol;
852 		if (nol) {
853 			dfs->dfs_nol = nol->nol_next;
854 			dfs->dfs_nol_count--;
855 			nol_chan = utils_dfs_freq_to_chan(nol->nol_freq);
856 			WLAN_DFSNOL_UNLOCK(dfs);
857 			utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
858 						    &nol_chan,
859 						    1,
860 						    DFS_NOL_RESET);
861 
862 			qdf_timer_free(&nol->nol_timer);
863 			qdf_mem_free(nol);
864 		} else {
865 			WLAN_DFSNOL_UNLOCK(dfs);
866 			break;
867 		}
868 	}
869 }
870 #endif
871 #endif
872 
873 void dfs_nol_workqueue_cleanup(struct wlan_dfs *dfs)
874 {
875 	qdf_flush_work(&dfs->dfs_nol_elem_free_work);
876 }
877 
878 int dfs_get_use_nol(struct wlan_dfs *dfs)
879 {
880 	return dfs->dfs_use_nol;
881 }
882 
883 int dfs_get_nol_timeout(struct wlan_dfs *dfs)
884 {
885 	return dfs->wlan_dfs_nol_timeout;
886 }
887 
888 void dfs_getnol(struct wlan_dfs *dfs, void *dfs_nolinfo)
889 {
890 	struct dfsreq_nolinfo *nolinfo = (struct dfsreq_nolinfo *)dfs_nolinfo;
891 
892 	DFS_GET_NOL_LOCKED(dfs, nolinfo->dfs_nol, &(nolinfo->dfs_ch_nchans));
893 }
894 
895 #if !defined(QCA_MCL_DFS_SUPPORT)
896 #ifdef CONFIG_CHAN_FREQ_API
897 void dfs_clear_nolhistory(struct wlan_dfs *dfs)
898 {
899 	struct dfs_channel *chan_list;
900 	int nchans;
901 	bool sta_opmode;
902 	int i;
903 	qdf_freq_t *nol_freq_list = NULL;
904 	int num_nol_history_chans;
905 
906 	if (!dfs->dfs_is_stadfs_enabled)
907 		return;
908 
909 	sta_opmode = dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj);
910 	if (!sta_opmode)
911 		return;
912 
913 	nchans = dfs_get_num_chans();
914 
915 	if (!nchans) {
916 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans");
917 		return;
918 	}
919 
920 	chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list));
921 	if (!chan_list)
922 		return;
923 
924 	utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj,
925 					    (void *)chan_list,
926 					    &num_nol_history_chans);
927 
928 	if (!num_nol_history_chans) {
929 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans");
930 		qdf_mem_free(chan_list);
931 		return;
932 	}
933 
934 	if (num_nol_history_chans > nchans)
935 		num_nol_history_chans = nchans;
936 
937 	nol_freq_list =
938 		qdf_mem_malloc(num_nol_history_chans * sizeof(qdf_freq_t));
939 
940 	if (!nol_freq_list) {
941 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Unable to alloc memory for freq list");
942 		qdf_mem_free(chan_list);
943 		return;
944 	}
945 
946 	for (i = 0; i < num_nol_history_chans; i++)
947 		nol_freq_list[i] = chan_list[i].dfs_ch_freq;
948 
949 	utils_dfs_reg_update_nol_history_chan_for_freq(dfs->dfs_pdev_obj,
950 						       nol_freq_list,
951 						       num_nol_history_chans,
952 						       DFS_NOL_HISTORY_RESET);
953 	qdf_mem_free(chan_list);
954 	qdf_mem_free(nol_freq_list);
955 }
956 #else
957 #ifdef CONFIG_CHAN_NUM_API
958 void dfs_clear_nolhistory(struct wlan_dfs *dfs)
959 {
960 	struct dfs_channel *chan_list;
961 	int nchans;
962 	bool sta_opmode;
963 	int i;
964 	uint8_t *nol_chan_ieee_list = NULL;
965 	int num_nol_history_chans;
966 
967 	if (!dfs->dfs_is_stadfs_enabled)
968 		return;
969 
970 	sta_opmode = dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj);
971 	if (!sta_opmode)
972 		return;
973 
974 	nchans = dfs_get_num_chans();
975 
976 	if (!nchans) {
977 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans");
978 		return;
979 	}
980 
981 	chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list));
982 	if (!chan_list)
983 		return;
984 
985 	utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj,
986 					    (void *)chan_list,
987 					    &num_nol_history_chans);
988 
989 	if (!num_nol_history_chans) {
990 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans");
991 		qdf_mem_free(chan_list);
992 		return;
993 	}
994 
995 	if (num_nol_history_chans > nchans)
996 		num_nol_history_chans = nchans;
997 
998 	nol_chan_ieee_list =
999 		qdf_mem_malloc(num_nol_history_chans * sizeof(uint8_t));
1000 
1001 	if (!nol_chan_ieee_list) {
1002 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Unable to alloc memory for ieee list");
1003 		qdf_mem_free(chan_list);
1004 		return;
1005 	}
1006 
1007 	for (i = 0; i < num_nol_history_chans; i++)
1008 		nol_chan_ieee_list[i] = chan_list[i].dfs_ch_ieee;
1009 
1010 	utils_dfs_reg_update_nol_history_ch(dfs->dfs_pdev_obj,
1011 					    nol_chan_ieee_list,
1012 					    num_nol_history_chans,
1013 					    DFS_NOL_HISTORY_RESET);
1014 
1015 	qdf_mem_free(chan_list);
1016 	qdf_mem_free(nol_chan_ieee_list);
1017 }
1018 #endif
1019 #endif
1020 #endif
1021 
1022 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) && \
1023 	defined(CONFIG_CHAN_FREQ_API)
1024 void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs)
1025 {
1026 	struct dfs_nolelem *nol;
1027 	uint16_t freq_list[NUM_CHANNELS_160MHZ];
1028 	int i, nchans = 0;
1029 
1030 	nchans = dfs_get_bonding_channels_for_freq(dfs,
1031 						   &dfs->dfs_radar_found_chan,
1032 						   SEG_ID_PRIMARY,
1033 						   DETECTOR_ID_0,
1034 						   freq_list);
1035 
1036 	WLAN_DFSNOL_LOCK(dfs);
1037 	for (i = 0; i < nchans && i < NUM_CHANNELS_160MHZ; i++) {
1038 		nol = dfs->dfs_nol;
1039 		while (nol) {
1040 			if (nol->nol_freq == freq_list[i]) {
1041 				OS_SET_TIMER(&nol->nol_timer, 0);
1042 				break;
1043 			}
1044 			nol = nol->nol_next;
1045 		}
1046 	}
1047 	WLAN_DFSNOL_UNLOCK(dfs);
1048 
1049 	utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
1050 					     freq_list, nchans, DFS_NOL_RESET);
1051 }
1052 #else
1053 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) && \
1054 	defined(CONFIG_CHAN_NUM_API)
1055 void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs)
1056 {
1057 	struct dfs_nolelem *nol;
1058 	uint8_t channels[NUM_CHANNELS_160MHZ];
1059 	int i, nchans = 0;
1060 
1061 	nchans = dfs_get_bonding_channels(dfs,
1062 					  &dfs->dfs_radar_found_chan,
1063 					  SEG_ID_PRIMARY,
1064 					  DETECTOR_ID_0,
1065 					  channels);
1066 
1067 	WLAN_DFSNOL_LOCK(dfs);
1068 	for (i = 0; i < nchans && i < NUM_CHANNELS_160MHZ; i++) {
1069 		nol = dfs->dfs_nol;
1070 		while (nol) {
1071 			if (nol->nol_freq == (uint16_t)utils_dfs_chan_to_freq(
1072 				    channels[i])) {
1073 				OS_SET_TIMER(&nol->nol_timer, 0);
1074 				break;
1075 			}
1076 			nol = nol->nol_next;
1077 		}
1078 	}
1079 	WLAN_DFSNOL_UNLOCK(dfs);
1080 
1081 	utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
1082 				    channels, nchans, DFS_NOL_RESET);
1083 }
1084 #endif
1085 #endif
1086 
1087 void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios)
1088 {
1089 	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
1090 
1091 	if (WLAN_UMAC_MAX_PDEVS < num_radios) {
1092 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
1093 			"num_radios (%u) exceeds limit", num_radios);
1094 		return;
1095 	}
1096 
1097 	/* Allocate the temporary psoc NOL copy structure for the number
1098 	 * of radios provided.
1099 	 */
1100 	dfs_soc_obj->dfs_psoc_nolinfo =
1101 		qdf_mem_malloc(sizeof(struct dfsreq_nolinfo) * num_radios);
1102 }
1103 
1104 void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs)
1105 {
1106 	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
1107 
1108 	if (!dfs_soc_obj->dfs_psoc_nolinfo)
1109 		return;
1110 
1111 	qdf_mem_free(dfs_soc_obj->dfs_psoc_nolinfo);
1112 	dfs_soc_obj->dfs_psoc_nolinfo = NULL;
1113 }
1114 
1115 void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs,
1116 			      uint8_t pdev_id)
1117 {
1118 	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
1119 	struct dfsreq_nolinfo tmp_nolinfo, *nolinfo;
1120 	uint32_t i, num_chans = 0;
1121 
1122 	if (!dfs->dfs_nol_count)
1123 		return;
1124 
1125 	if (!dfs_soc_obj->dfs_psoc_nolinfo)
1126 		return;
1127 
1128 	nolinfo = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id];
1129 	/* Fetch the NOL entries for the DFS object. */
1130 	dfs_getnol(dfs, &tmp_nolinfo);
1131 
1132 	/* nolinfo might already have some data. Do not overwrite it */
1133 	num_chans = nolinfo->dfs_ch_nchans;
1134 	for (i = 0; i < tmp_nolinfo.dfs_ch_nchans; i++) {
1135 		/* Figure out the completed duration of each NOL. */
1136 		uint32_t nol_completed_ms = qdf_do_div(
1137 			qdf_get_monotonic_boottime() -
1138 			tmp_nolinfo.dfs_nol[i].nol_start_us, 1000);
1139 
1140 		nolinfo->dfs_nol[num_chans] = tmp_nolinfo.dfs_nol[i];
1141 		/* Remember the remaining NOL time in the timeout
1142 		 * variable.
1143 		 */
1144 		nolinfo->dfs_nol[num_chans++].nol_timeout_ms -=
1145 			nol_completed_ms;
1146 	}
1147 
1148 	nolinfo->dfs_ch_nchans = num_chans;
1149 }
1150 
1151 void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs,
1152 				   uint8_t pdev_id,
1153 				   uint16_t low_5ghz_freq,
1154 				   uint16_t high_5ghz_freq)
1155 {
1156 	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
1157 	struct dfsreq_nolinfo *nol, req_nol;
1158 	uint8_t i, j = 0;
1159 
1160 	if (!dfs_soc_obj->dfs_psoc_nolinfo)
1161 		return;
1162 
1163 	if (!dfs_soc_obj->dfs_psoc_nolinfo[pdev_id].dfs_ch_nchans)
1164 		return;
1165 
1166 	nol = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id];
1167 
1168 	for (i = 0; i < nol->dfs_ch_nchans; i++) {
1169 		uint16_t tmp_freq = nol->dfs_nol[i].nol_freq;
1170 
1171 		/* Add to nol only if within the tgt pdev's frequency range. */
1172 		if ((low_5ghz_freq < tmp_freq) && (high_5ghz_freq > tmp_freq)) {
1173 			/* The NOL timeout value in each entry points to the
1174 			 * remaining time of the NOL. This is to indicate that
1175 			 * the NOL entries are paused and are not left to
1176 			 * continue.
1177 			 * While adding these NOL, update the start ticks to
1178 			 * current time to avoid losing entries which might
1179 			 * have timed out during the pause and resume mechanism.
1180 			 */
1181 			nol->dfs_nol[i].nol_start_us =
1182 				qdf_get_monotonic_boottime();
1183 			req_nol.dfs_nol[j++] = nol->dfs_nol[i];
1184 		}
1185 	}
1186 	dfs_set_nol(dfs, req_nol.dfs_nol, j);
1187 }
1188