xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_cac.c (revision f28396d060cff5c6519f883cb28ae0116ce479f1)
1 /*
2  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /**
28  * DOC: This file has the functions related to DFS CAC.
29  */
30 
31 #include "../dfs_channel.h"
32 #include "../dfs_zero_cac.h"
33 #include <wlan_objmgr_vdev_obj.h>
34 #include "wlan_dfs_utils_api.h"
35 #include "wlan_dfs_mlme_api.h"
36 #include "../dfs_internal.h"
37 #include "../dfs_process_radar_found_ind.h"
38 
39 #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650))
40 #define ADJACENT_WEATHER_RADAR_CHANNEL   5580
41 #define CH100_START_FREQ                 5490
42 #define CH100                            100
43 
44 int dfs_override_cac_timeout(struct wlan_dfs *dfs, int cac_timeout)
45 {
46 	if (!dfs)
47 		return -EIO;
48 
49 	dfs->dfs_cac_timeout_override = cac_timeout;
50 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "CAC timeout is now %s %d",
51 		(cac_timeout == -1) ? "default" : "overridden",
52 		cac_timeout);
53 
54 	return 0;
55 }
56 
57 int dfs_get_override_cac_timeout(struct wlan_dfs *dfs, int *cac_timeout)
58 {
59 	if (!dfs)
60 		return -EIO;
61 
62 	(*cac_timeout) = dfs->dfs_cac_timeout_override;
63 
64 	return 0;
65 }
66 
67 #ifdef CONFIG_CHAN_NUM_API
68 void dfs_cac_valid_reset(struct wlan_dfs *dfs,
69 		uint8_t prevchan_ieee,
70 		uint32_t prevchan_flags)
71 {
72 	if (dfs->dfs_cac_valid_time) {
73 		if ((prevchan_ieee != dfs->dfs_curchan->dfs_ch_ieee) ||
74 			(prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) {
75 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
76 					"Cancelling timer & clearing cac_valid"
77 					);
78 			qdf_timer_stop(&dfs->dfs_cac_valid_timer);
79 			dfs->dfs_cac_valid = 0;
80 		}
81 	}
82 }
83 #endif
84 
85 #ifdef CONFIG_CHAN_FREQ_API
86 void dfs_cac_valid_reset_for_freq(struct wlan_dfs *dfs,
87 				  uint16_t prevchan_freq,
88 				  uint32_t prevchan_flags)
89 {
90 	if (dfs->dfs_cac_valid_time) {
91 		if ((prevchan_freq != dfs->dfs_curchan->dfs_ch_freq) ||
92 		    (prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) {
93 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
94 				"Cancelling timer & clearing cac_valid");
95 			qdf_timer_stop(&dfs->dfs_cac_valid_timer);
96 			dfs->dfs_cac_valid = 0;
97 		}
98 	}
99 }
100 #endif
101 
102 /**
103  * dfs_cac_valid_timeout() - Timeout function for dfs_cac_valid_timer
104  *                           cac_valid bit will be reset in this function.
105  */
106 static os_timer_func(dfs_cac_valid_timeout)
107 {
108 	struct wlan_dfs *dfs = NULL;
109 
110 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
111 	dfs->dfs_cac_valid = 0;
112 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!");
113 }
114 
115 /**
116  * dfs_clear_cac_started_chan() - Clear dfs cac started channel.
117  * @dfs: Pointer to wlan_dfs structure.
118  */
119 static void dfs_clear_cac_started_chan(struct wlan_dfs *dfs)
120 {
121 	qdf_mem_zero(&dfs->dfs_cac_started_chan,
122 		     sizeof(dfs->dfs_cac_started_chan));
123 }
124 
125 void dfs_process_cac_completion(struct wlan_dfs *dfs)
126 {
127 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
128 	uint16_t primary_chan_freq = 0, secondary_chan_freq = 0;
129 	struct dfs_channel *dfs_curchan;
130 
131 	dfs->dfs_cac_timer_running = 0;
132 	dfs_curchan = dfs->dfs_curchan;
133 
134 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d cur time %d",
135 		 dfs->dfs_curchan->dfs_ch_freq,
136 		 (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000));
137 
138 	/*
139 	 * When radar is detected during a CAC we are woken up prematurely to
140 	 * switch to a new channel. Check the channel to decide how to act.
141 	 */
142 	if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) {
143 		dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj,
144 					   dfs_curchan->dfs_ch_ieee,
145 					   dfs_curchan->dfs_ch_freq,
146 					   dfs_curchan->dfs_ch_mhz_freq_seg2,
147 					   dfs_curchan->dfs_ch_flags);
148 		dfs_debug(dfs, WLAN_DEBUG_DFS,
149 			  "CAC timer on chan %u (%u MHz) stopped due to radar",
150 			  dfs_curchan->dfs_ch_ieee,
151 			  dfs_curchan->dfs_ch_freq);
152 	} else {
153 		dfs_debug(dfs, WLAN_DEBUG_DFS,
154 			  "CAC timer on channel %u (%u MHz) expired;"
155 			  "no radar detected",
156 			  dfs_curchan->dfs_ch_ieee,
157 			  dfs_curchan->dfs_ch_freq);
158 
159 		/* On CAC completion, set the bit 'cac_valid'.
160 		 * CAC will not be re-done if this bit is reset.
161 		 * The flag will be reset when dfs_cac_valid_timer
162 		 * timesout.
163 		 */
164 		if (dfs->dfs_cac_valid_time) {
165 			dfs->dfs_cac_valid = 1;
166 			qdf_timer_mod(&dfs->dfs_cac_valid_timer,
167 				      dfs->dfs_cac_valid_time * 1000);
168 		}
169 
170 		dfs_find_chwidth_and_center_chan_for_freq(dfs,
171 							  &ch_width,
172 							  &primary_chan_freq,
173 							  &secondary_chan_freq);
174 		/* Mark the current channel as preCAC done */
175 		dfs_mark_precac_done_for_freq(dfs, primary_chan_freq,
176 					      secondary_chan_freq, ch_width);
177 	}
178 
179 	dfs_clear_cac_started_chan(dfs);
180 	/* Iterate over the nodes, processing the CAC completion event. */
181 	dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0);
182 
183 	/* Send a CAC timeout, VAP up event to user space */
184 	dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj);
185 
186 	if (dfs->dfs_defer_precac_channel_change == 1) {
187 		dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj);
188 		dfs->dfs_defer_precac_channel_change = 0;
189 	}
190 }
191 
192 /**
193  * dfs_cac_timeout() - DFS cactimeout function.
194  *
195  * Sets dfs_cac_timer_running to 0  and dfs_cac_valid_timer.
196  */
197 #ifdef CONFIG_CHAN_FREQ_API
198 static os_timer_func(dfs_cac_timeout)
199 {
200 	struct wlan_dfs *dfs = NULL;
201 
202 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
203 
204 	if (dfs_is_hw_mode_switch_in_progress(dfs))
205 		dfs->dfs_defer_params.is_cac_completed = true;
206 	else
207 		dfs_process_cac_completion(dfs);
208 }
209 #else
210 #ifdef CONFIG_CHAN_NUM_API
211 static os_timer_func(dfs_cac_timeout)
212 {
213 	struct wlan_dfs *dfs = NULL;
214 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
215 	uint8_t primary_chan_ieee = 0, secondary_chan_ieee = 0;
216 
217 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
218 	dfs->dfs_cac_timer_running = 0;
219 
220 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d curr time %d",
221 		dfs->dfs_curchan->dfs_ch_freq,
222 		(qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000));
223 
224 	/*
225 	 * When radar is detected during a CAC we are woken up prematurely to
226 	 * switch to a new channel. Check the channel to decide how to act.
227 	 */
228 	if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) {
229 		dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
230 				dfs->dfs_curchan->dfs_ch_ieee,
231 				dfs->dfs_curchan->dfs_ch_freq,
232 				dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
233 				dfs->dfs_curchan->dfs_ch_flags);
234 		dfs_debug(dfs, WLAN_DEBUG_DFS,
235 			"CAC timer on channel %u (%u MHz) stopped due to radar",
236 			dfs->dfs_curchan->dfs_ch_ieee,
237 			dfs->dfs_curchan->dfs_ch_freq);
238 	} else {
239 		dfs_debug(dfs, WLAN_DEBUG_DFS,
240 			"CAC timer on channel %u (%u MHz) expired; no radar detected",
241 			dfs->dfs_curchan->dfs_ch_ieee,
242 			dfs->dfs_curchan->dfs_ch_freq);
243 
244 		/* On CAC completion, set the bit 'cac_valid'.
245 		 * CAC will not be re-done if this bit is reset.
246 		 * The flag will be reset when dfs_cac_valid_timer
247 		 * timesout.
248 		 */
249 		if (dfs->dfs_cac_valid_time) {
250 			dfs->dfs_cac_valid = 1;
251 			qdf_timer_mod(&dfs->dfs_cac_valid_timer,
252 					dfs->dfs_cac_valid_time * 1000);
253 		}
254 
255 		dfs_find_chwidth_and_center_chan(dfs,
256 						 &ch_width,
257 						 &primary_chan_ieee,
258 						 &secondary_chan_ieee);
259 		/* Mark the current channel as preCAC done */
260 		dfs_mark_precac_done(dfs, primary_chan_ieee,
261 				     secondary_chan_ieee, ch_width);
262 	}
263 
264 	dfs_clear_cac_started_chan(dfs);
265 	/* Iterate over the nodes, processing the CAC completion event. */
266 	dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0);
267 
268 	/* Send a CAC timeout, VAP up event to user space */
269 	dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj);
270 
271 	if (dfs->dfs_defer_precac_channel_change == 1) {
272 		dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj);
273 		dfs->dfs_defer_precac_channel_change = 0;
274 	}
275 }
276 #endif
277 #endif
278 
279 void dfs_cac_timer_attach(struct wlan_dfs *dfs)
280 {
281 	dfs->dfs_cac_timeout_override = -1;
282 	dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS;
283 	qdf_timer_init(NULL,
284 			&(dfs->dfs_cac_timer),
285 			dfs_cac_timeout,
286 			(void *)(dfs),
287 			QDF_TIMER_TYPE_WAKE_APPS);
288 
289 	qdf_timer_init(NULL,
290 			&(dfs->dfs_cac_valid_timer),
291 			dfs_cac_valid_timeout,
292 			(void *)(dfs),
293 			QDF_TIMER_TYPE_WAKE_APPS);
294 }
295 
296 void dfs_cac_timer_reset(struct wlan_dfs *dfs)
297 {
298 	qdf_timer_stop(&dfs->dfs_cac_timer);
299 	dfs_get_override_cac_timeout(dfs,
300 			&(dfs->dfs_cac_timeout_override));
301 	dfs_clear_cac_started_chan(dfs);
302 }
303 
304 void dfs_cac_timer_detach(struct wlan_dfs *dfs)
305 {
306 	qdf_timer_free(&dfs->dfs_cac_timer);
307 
308 	qdf_timer_free(&dfs->dfs_cac_valid_timer);
309 	dfs->dfs_cac_valid = 0;
310 }
311 
312 int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs)
313 {
314 	return dfs->dfs_cac_timer_running;
315 }
316 
317 #ifdef CONFIG_CHAN_FREQ_API
318 void dfs_start_cac_timer(struct wlan_dfs *dfs)
319 {
320 	int cac_timeout = 0;
321 	struct dfs_channel *chan = dfs->dfs_curchan;
322 
323 	cac_timeout =
324 	    dfs_mlme_get_cac_timeout_for_freq(dfs->dfs_pdev_obj,
325 					      chan->dfs_ch_freq,
326 					      chan->dfs_ch_mhz_freq_seg2,
327 					      chan->dfs_ch_flags);
328 
329 	dfs->dfs_cac_started_chan = *chan;
330 
331 	dfs_debug(dfs, WLAN_DEBUG_DFS,
332 		  "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec",
333 		  chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2,
334 		  cac_timeout,
335 		  qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
336 
337 	qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000);
338 	dfs->dfs_cac_aborted = 0;
339 }
340 #else
341 #ifdef CONFIG_CHAN_NUM_API
342 void dfs_start_cac_timer(struct wlan_dfs *dfs)
343 {
344 	int cac_timeout = 0;
345 	struct dfs_channel *chan = dfs->dfs_curchan;
346 
347 	cac_timeout = dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj,
348 					       chan->dfs_ch_freq,
349 					       chan->dfs_ch_vhtop_ch_freq_seg2,
350 					       chan->dfs_ch_flags);
351 
352 	dfs->dfs_cac_started_chan = *chan;
353 
354 	dfs_debug(dfs, WLAN_DEBUG_DFS,
355 		  "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec",
356 		  chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2,
357 		  cac_timeout,
358 		  qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
359 
360 	qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000);
361 	dfs->dfs_cac_aborted = 0;
362 }
363 #endif
364 #endif
365 
366 void dfs_cancel_cac_timer(struct wlan_dfs *dfs)
367 {
368 	qdf_timer_stop(&dfs->dfs_cac_timer);
369 	dfs_clear_cac_started_chan(dfs);
370 }
371 
372 void dfs_cac_stop(struct wlan_dfs *dfs)
373 {
374 	uint32_t phyerr;
375 
376 	dfs_get_debug_info(dfs, (void *)&phyerr);
377 	dfs_debug(dfs, WLAN_DEBUG_DFS,
378 		"Stopping CAC Timer %d procphyerr 0x%08x",
379 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
380 	qdf_timer_stop(&dfs->dfs_cac_timer);
381 	if (dfs->dfs_cac_timer_running)
382 		dfs->dfs_cac_aborted = 1;
383 	dfs_clear_cac_started_chan(dfs);
384 	dfs->dfs_cac_timer_running = 0;
385 }
386 
387 void dfs_stacac_stop(struct wlan_dfs *dfs)
388 {
389 	uint32_t phyerr;
390 
391 	dfs_get_debug_info(dfs, (void *)&phyerr);
392 	dfs_debug(dfs, WLAN_DEBUG_DFS,
393 		"Stopping STA CAC Timer %d procphyerr 0x%08x",
394 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
395 	dfs_clear_cac_started_chan(dfs);
396 }
397 
398 /*
399  * dfs_is_subset_channel_for_freq() - Find out if prev channel and current
400  * channel are subsets of each other.
401  * @old_subchans_freq: Pointer to previous sub-channels freq.
402  * @old_n_chans: Number of previous sub-channels.
403  * @new_subchans_freq: Pointer to new sub-channels freq.
404  * @new_n_chans:  Number of new sub-channels
405  */
406 #ifdef CONFIG_CHAN_FREQ_API
407 static bool
408 dfs_is_subset_channel_for_freq(uint16_t *old_subchans_freq,
409 			       uint8_t old_n_chans,
410 			       uint16_t *new_subchans_freq,
411 			       uint8_t new_n_chans)
412 {
413 	bool is_found;
414 	int i, j;
415 
416 	if (!new_n_chans)
417 		return true;
418 
419 	if (new_n_chans > old_n_chans)
420 		return false;
421 
422 	for (i = 0; i < new_n_chans; i++) {
423 		is_found = false;
424 		for (j = 0; j < old_n_chans; j++) {
425 			if (new_subchans_freq[i] == old_subchans_freq[j]) {
426 				is_found = true;
427 				break;
428 			}
429 		}
430 
431 		/* If new_subchans[i] is not found in old_subchans, then,
432 		 * new_chan is not subset of old_chan.
433 		 */
434 		if (!is_found)
435 			break;
436 	}
437 
438 	return is_found;
439 }
440 #endif
441 
442 #ifdef CONFIG_CHAN_FREQ_API
443 static uint8_t
444 dfs_find_dfs_sub_channels_for_freq(struct wlan_dfs *dfs,
445 				   struct dfs_channel *chan,
446 				   uint16_t *subchan_arr)
447 {
448 	if (WLAN_IS_CHAN_MODE_160(chan) || WLAN_IS_CHAN_MODE_80_80(chan)) {
449 		if (WLAN_IS_CHAN_DFS(chan) && WLAN_IS_CHAN_DFS_CFREQ2(chan))
450 			return dfs_get_bonding_channel_without_seg_info_for_freq
451 				(chan, subchan_arr);
452 		if (WLAN_IS_CHAN_DFS(chan))
453 			return dfs_get_bonding_channels_for_freq(dfs,
454 								 chan,
455 								 SEG_ID_PRIMARY,
456 								 DETECTOR_ID_0,
457 								 subchan_arr);
458 		if (WLAN_IS_CHAN_DFS_CFREQ2(chan))
459 			return dfs_get_bonding_channels_for_freq
460 				(dfs, chan, SEG_ID_SECONDARY,
461 				 DETECTOR_ID_0, subchan_arr);
462 		/* All channels in 160/80_80 BW are non DFS, return 0
463 		 * as number of subchannels
464 		 */
465 		return 0;
466 	} else if (WLAN_IS_CHAN_DFS(chan)) {
467 		return dfs_get_bonding_channel_without_seg_info_for_freq
468 			(chan, subchan_arr);
469 	}
470 	/* All channels are non DFS, return 0 as number of subchannels*/
471 	return 0;
472 }
473 #endif
474 
475 /* dfs_is_new_chan_subset_of_old_chan() - Find if new channel is subset of
476  * old channel.
477  * @dfs: Pointer to wlan_dfs structure.
478  * @new_chan: Pointer to new channel of dfs_channel structure.
479  * @old_chan: Pointer to old channel of dfs_channel structure.
480  *
481  * Return: True if new channel is subset of old channel, else false.
482  */
483 #ifdef CONFIG_CHAN_FREQ_API
484 static bool
485 dfs_is_new_chan_subset_of_old_chan(struct wlan_dfs *dfs,
486 				   struct dfs_channel *new_chan,
487 				   struct dfs_channel *old_chan)
488 {
489 	uint16_t new_subchans[NUM_CHANNELS_160MHZ];
490 	uint16_t old_subchans[NUM_CHANNELS_160MHZ];
491 	uint8_t n_new_subchans = 0;
492 	uint8_t n_old_subchans = 0;
493 
494 	/* Given channel is the old channel. i.e. The channel which
495 	 * should have the new channel as subset.
496 	 */
497 	n_old_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, old_chan,
498 							    old_subchans);
499 	/* cur_chan is the new channel to be check if subset of old channel */
500 	n_new_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, new_chan,
501 							    new_subchans);
502 
503 	return dfs_is_subset_channel_for_freq(old_subchans,
504 					      n_old_subchans,
505 					      new_subchans,
506 					      n_new_subchans);
507 }
508 #endif
509 
510 bool dfs_is_cac_required(struct wlan_dfs *dfs,
511 			 struct dfs_channel *cur_chan,
512 			 struct dfs_channel *prev_chan,
513 			 bool *continue_current_cac)
514 {
515 	struct dfs_channel *cac_started_chan = &dfs->dfs_cac_started_chan;
516 
517 	if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) {
518 		dfs_debug(dfs, WLAN_DEBUG_DFS,
519 			  "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d",
520 			  dfs->dfs_ignore_dfs, dfs->dfs_cac_valid,
521 			  dfs->dfs_ignore_cac);
522 		return false;
523 	}
524 
525 	/* If the channel has completed PRE-CAC then CAC can be skipped here. */
526 	if (dfs_is_precac_done(dfs, cur_chan)) {
527 		dfs_debug(dfs, WLAN_DEBUG_DFS,
528 			  "PRE-CAC alreay done on this channel %d",
529 			  cur_chan->dfs_ch_ieee);
530 		return false;
531 	}
532 
533 	if (dfs_is_ap_cac_timer_running(dfs)) {
534 		/* Check if we should continue the existing CAC or
535 		 * cancel the existing CAC.
536 		 * For example: - if an existing VAP(0) is already in
537 		 * DFS wait state (which means the radio(wifi) is
538 		 * running the CAC) and it is in channel A and another
539 		 * VAP(1) comes up in the same channel then instead of
540 		 * cancelling the CAC we can let the CAC continue.
541 		 */
542 		if (dfs_is_new_chan_subset_of_old_chan(dfs,
543 						       cur_chan,
544 						       cac_started_chan)) {
545 			*continue_current_cac = true;
546 		} else {
547 			/* New CAC is needed, cancel the running CAC
548 			 * timer.
549 			 * 1) When AP is in DFS_WAIT state and it is in
550 			 *    channel A and user restarts the AP vap in
551 			 *    channel B, then cancel the running CAC in
552 			 *    channel A and start new CAC in channel B.
553 			 *
554 			 * 2) When AP detects the RADAR during CAC in
555 			 *    channel A, it cancels the running CAC and
556 			 *    tries to find channel B with the reduced
557 			 *    bandwidth with of channel A.
558 			 *    In this case, since the CAC is aborted by
559 			 *    the RADAR, AP should start the CAC again.
560 			 */
561 			dfs_cancel_cac_timer(dfs);
562 		}
563 	} else { /* CAC timer is not running. */
564 		if (dfs_is_new_chan_subset_of_old_chan(dfs,
565 						       cur_chan,
566 						       prev_chan)) {
567 			/* AP bandwidth reduce case:
568 			 * When AP detects the RADAR in in-service monitoring
569 			 * mode in channel A, it cancels the running CAC and
570 			 * tries to find the channel B with the reduced
571 			 * bandwidth of channel A.
572 			 * If the new channel B is subset of the channel A
573 			 * then AP skips the CAC.
574 			 */
575 			if (!dfs->dfs_cac_aborted) {
576 				dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC");
577 				return false;
578 			}
579 		}
580 	}
581 
582 	return true;
583 }
584