1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
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: API for processing radar found indication.
22 *
23 */
24
25 #include "../dfs.h"
26 #include "../dfs_zero_cac.h"
27 #include "../dfs_process_radar_found_ind.h"
28 #include <wlan_reg_services_api.h>
29 #include <wlan_objmgr_vdev_obj.h>
30 #include <wlan_dfs_utils_api.h>
31 #include <wlan_dfs_tgt_api.h>
32 #include "wlan_dfs_mlme_api.h"
33 #include "../dfs_internal.h"
34 /*
35 * TODO: The code is not according to the following description needs
36 * modification and correction. Code always adds left and right channels to
37 * NOL even if it is not a chirp radar.
38 *
39 * A) If chirp radar starts at boundary and ends at boundary then three channels
40 * will be affected.
41 * freq_offset.freq[0] = fn (Center frequency)
42 * freq_offset.freq[1] = fn-1 (Left of center)
43 * freq_offset.freq[2] = fn+1 (Right of center)
44 *
45 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
46 *
47 * Chirp start freq Chirp end freq
48 * | |
49 * | |
50 * V V
51 * _______________________________________________________________________
52 * | center freq | center freq | center freq |
53 * | ch(n-1) | ch(n) | ch(n+1) |
54 * | | | | | | |
55 * | | | | | | |
56 * | | | | | | |
57 * fn-1 fn boundary fn+1
58 * <-------- 20 Mhz ------>
59 *
60 * B) If chirp radar starts at one channel and continues up to another channel
61 * then two channels will be affected.
62 * freq_offset.freq[0] = fn
63 * freq_offset.freq[1] = 0
64 * freq_offset.freq[2] = fn+1
65 *
66 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
67 *
68 * Chirp start freq Chirp end freq
69 * | |
70 * | |
71 * V V
72 * _______________________________________________________________________
73 * | center freq | center freq | center freq |
74 * | ch(n-1) | ch(n) | ch(n+1) |
75 * | | | | | | |
76 * | | | | | | |
77 * | | | | | | |
78 * fn-1 fn boundary fn+1
79 * <-------- 20 Mhz ------>
80 *
81 * C) Radar found at boundary, two channels will be affected.
82 * freq_offset.freq[0] = fn
83 * freq_offset.freq[1] = 0
84 * freq_offset.freq[2] = fn+1
85 *
86 * Two channels, ch(n) and ch(n+1) will be added to NOL.
87 *
88 * dfs_freq_offset (radar found freq)
89 * |
90 * |
91 * V
92 * _______________________________________________________________________
93 * | center freq | center freq | center freq |
94 * | ch(n-1) | ch(n) | ch(n+1) |
95 * | | | | | | |
96 * | | | | | | |
97 * | | | | | | |
98 * fn-1 fn boundary fn+1
99 * <-------- 20 Mhz ------>
100 *
101 *
102 * D) Else only one channel will be affected.
103 * freq_offset.freq[0] = fn
104 * freq_offset.freq[1] = 0
105 * freq_offset.freq[2] = 0
106 *
107 * One channel ch(n) will be added to NOL.
108 *
109 *
110 * dfs_freq_offset (radar found freq)
111 * |
112 * |
113 * V
114 * _______________________________________________________________________
115 * | center freq | center freq | center freq |
116 * | ch(n-1) | ch(n) | ch(n+1) |
117 * | | | | | | |
118 * | | | | | | |
119 * | | | | | | |
120 * fn-1 fn boundary fn+1
121 * <-------- 20 Mhz ------>
122 */
123
dfs_set_nol_subchannel_marking(struct wlan_dfs * dfs,bool nol_subchannel_marking)124 int dfs_set_nol_subchannel_marking(struct wlan_dfs *dfs,
125 bool nol_subchannel_marking)
126 {
127 QDF_STATUS status = QDF_STATUS_SUCCESS;
128
129 if (!dfs)
130 return -EIO;
131
132 dfs->dfs_use_nol_subchannel_marking = nol_subchannel_marking;
133 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "NOL subchannel marking is %s ",
134 (nol_subchannel_marking) ? "set" : "disabled");
135 if (dfs->dfs_is_offload_enabled)
136 status = tgt_dfs_send_subchan_marking(dfs->dfs_pdev_obj,
137 nol_subchannel_marking);
138
139 return qdf_status_to_os_return(status);
140 }
141
dfs_get_nol_subchannel_marking(struct wlan_dfs * dfs,bool * nol_subchannel_marking)142 int dfs_get_nol_subchannel_marking(struct wlan_dfs *dfs,
143 bool *nol_subchannel_marking)
144 {
145 if (!dfs)
146 return -EIO;
147
148 (*nol_subchannel_marking) = dfs->dfs_use_nol_subchannel_marking;
149
150 return 0;
151 }
152
153 #ifdef CONFIG_CHAN_FREQ_API
154 QDF_STATUS
dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs * dfs,uint16_t * freq_list,uint16_t * nol_freq_list,uint8_t * num_channels)155 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs,
156 uint16_t *freq_list,
157 uint16_t *nol_freq_list,
158 uint8_t *num_channels)
159 {
160 int i;
161 uint16_t last_chan_freq = 0;
162 uint8_t num_ch = 0;
163
164 if (*num_channels > MAX_20MHZ_SUBCHANS) {
165 dfs_err(dfs, WLAN_DEBUG_DFS,
166 "Invalid num channels: %d", *num_channels);
167 return QDF_STATUS_E_FAILURE;
168 }
169
170 for (i = 0; i < *num_channels; i++) {
171 if (freq_list[i] == 0 ||
172 freq_list[i] == last_chan_freq)
173 continue;
174 if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj,
175 freq_list[i])) {
176 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip",
177 freq_list[i]);
178 continue;
179 }
180
181 last_chan_freq = freq_list[i];
182 DFS_NOL_ADD_CHAN_LOCKED(dfs,
183 freq_list[i],
184 dfs->wlan_dfs_nol_timeout);
185 nol_freq_list[num_ch++] = last_chan_freq;
186 utils_dfs_deliver_event(dfs->dfs_pdev_obj,
187 freq_list[i],
188 WLAN_EV_NOL_STARTED);
189 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL",
190 last_chan_freq);
191 }
192
193 if (!num_ch) {
194 dfs_err(dfs, WLAN_DEBUG_DFS,
195 "dfs channels not found in channel list");
196 return QDF_STATUS_E_FAILURE;
197 }
198 *num_channels = num_ch;
199
200 dfs_update_cac_elements(dfs, nol_freq_list, num_ch, NULL, WLAN_EV_NOL_STARTED);
201
202 if (!dfs_get_disable_radar_marking(dfs)) {
203 utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
204 nol_freq_list, num_ch,
205 DFS_NOL_SET);
206
207 if (dfs->dfs_is_stadfs_enabled)
208 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj))
209 utils_dfs_reg_update_nol_history_chan_for_freq(
210 dfs->dfs_pdev_obj, nol_freq_list,
211 num_ch, DFS_NOL_HISTORY_SET);
212 }
213
214 dfs_nol_update(dfs);
215 utils_dfs_save_nol(dfs->dfs_pdev_obj);
216
217 return QDF_STATUS_SUCCESS;
218 }
219 #endif
220
221 /**
222 * dfs_find_20mhz_subchans_from_offsets()- Find frequency offsets
223 * that aligns with 20MHz sub-channel centers.
224 *
225 * @freq_offset: freq offset
226 * @center_freq: center frequency
227 * @ch_width: Channel Width value: 20/40/80/160/320MHz.
228 * Find frequency offsets for 80MHz
229 *
230 * Return: None
231 */
232 static void
dfs_find_20mhz_subchans_from_offsets(struct freqs_offsets * freq_offset,uint32_t center_freq,uint16_t ch_width)233 dfs_find_20mhz_subchans_from_offsets(struct freqs_offsets *freq_offset,
234 uint32_t center_freq,
235 uint16_t ch_width)
236 {
237 uint16_t first_chan20_cen = center_freq - (ch_width / 2) + BW_10;
238 uint16_t i, j;
239 uint8_t num_20mhz_subchans = ch_width / BW_20;
240
241 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
242 uint16_t radar_found_freq =
243 center_freq + freq_offset->offset[i];
244 uint16_t chan20_cen = first_chan20_cen;
245
246 for (j = 0; j < num_20mhz_subchans; j++) {
247 if ((radar_found_freq > chan20_cen - BW_10) &&
248 (radar_found_freq < chan20_cen + BW_10)) {
249 freq_offset->freq[i] = chan20_cen;
250 break;
251 }
252 chan20_cen += BW_20;
253 }
254 }
255 }
256
257 #ifdef CONFIG_CHAN_FREQ_API
258 void
dfs_compute_radar_found_cfreq(struct wlan_dfs * dfs,struct radar_found_info * radar_found,uint32_t * freq_center)259 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs,
260 struct radar_found_info *radar_found,
261 uint32_t *freq_center)
262 {
263 struct dfs_channel *curchan = dfs->dfs_curchan;
264
265 /* In case of 11BE Chipsets, radar found center frequency is
266 * directly obtained from WMI.
267 */
268 if (dfs->dfs_is_radar_found_chan_freq_eq_center_freq) {
269 *freq_center = radar_found->chan_freq;
270 return;
271 }
272
273 /* Radar found on agile detector ID.
274 * Applicable to chips that have a separate agile radar detector
275 * engine.
276 */
277 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
278 *freq_center = dfs->dfs_agile_precac_freq_mhz;
279 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
280 if (radar_found->segment_id == PRIMARY_SEG)
281 *freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET;
282 else
283 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET;
284 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ &&
285 dfs->dfs_agile_precac_freq_mhz ==
286 RESTRICTED_80P80_CHAN_CENTER_FREQ) {
287 /*
288 * The reason why left and right offsets
289 * are different.
290 * Center of 165 is 5730MHz.
291 * Center of left 80 is 5690MHz.
292 * Center of right 80 is 5775MHz.
293 */
294 if (radar_found->segment_id == PRIMARY_SEG)
295 *freq_center -=
296 DFS_165MHZ_SECOND_SEG_OFFSET_LEFT;
297 else
298 *freq_center +=
299 DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT;
300 }
301 } else if (!radar_found->segment_id) {
302 *freq_center = curchan->dfs_ch_mhz_freq_seg1;
303 } else {
304 /* Radar found on secondary segment by the HW, when preCAC
305 * was not running in legacy chips or preCAC was running
306 * in Lithium chips.
307 */
308 *freq_center = curchan->dfs_ch_mhz_freq_seg2;
309 if (WLAN_IS_CHAN_MODE_160(curchan)) {
310 /* If center frequency of entire 160 band
311 * is less than center frequency of primary
312 * segment, then the center frequency of
313 * secondary segment is -40 of center
314 * frequency of entire 160 segment.
315 */
316 if (curchan->dfs_ch_mhz_freq_seg2 <
317 curchan->dfs_ch_mhz_freq_seg1)
318 *freq_center -=
319 DFS_160MHZ_SECOND_SEG_OFFSET;
320 else
321 *freq_center +=
322 DFS_160MHZ_SECOND_SEG_OFFSET;
323 }
324 }
325 }
326 #endif
327
328 /**
329 * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans.
330 * @dfs: Pointer to wlan_dfs structure.
331 * @radar_found: Pointer to radar_found structure.
332 * @freq_list: Pointer to save radar affected channels.
333 * @freq_center: Freq_center of the radar affected chan.
334 *
335 * Return: Number of channels.
336 */
337 #ifdef CONFIG_CHAN_FREQ_API
338 static uint8_t
dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs * dfs,struct radar_found_info * radar_found,uint16_t * freq_list,uint32_t freq_center)339 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs,
340 struct radar_found_info *radar_found,
341 uint16_t *freq_list,
342 uint32_t freq_center)
343 {
344 int i, j;
345 uint8_t num_radar_subchans;
346 uint32_t flag;
347 int32_t sidx;
348 uint16_t candidate_subchan_freq;
349 uint16_t cur_subchans[MAX_20MHZ_SUBCHANS];
350 uint8_t n_cur_subchans;
351 struct dfs_channel *curchan = dfs->dfs_curchan;
352 struct freqs_offsets freq_offset;
353 uint16_t ch_width;
354
355 qdf_mem_zero(&freq_offset, sizeof(freq_offset));
356 flag = curchan->dfs_ch_flags;
357
358 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
359 freq_offset.offset[i] = radar_found->freq_offset;
360
361 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
362
363 dfs_info(dfs, WLAN_DEBUG_DFS,
364 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
365 radar_found->segment_id, radar_found->detector_id, sidx,
366 radar_found->freq_offset, radar_found->is_chirp,
367 flag, freq_center);
368
369 ch_width = dfs_chan_to_ch_width(curchan);
370 if (ch_width == BW_INVALID) {
371 dfs_err(dfs, WLAN_DEBUG_DFS,
372 "channel flag=%d is invalid", flag);
373 return 0;
374 }
375
376 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
377 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
378 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
379 }
380
381 dfs_find_20mhz_subchans_from_offsets(&freq_offset, freq_center,
382 ch_width);
383
384 n_cur_subchans =
385 dfs_get_bonding_channels_for_freq(dfs, curchan,
386 radar_found->segment_id,
387 radar_found->detector_id,
388 cur_subchans);
389
390 for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
391 candidate_subchan_freq = freq_offset.freq[i];
392 for (j = 0; j < n_cur_subchans; j++) {
393 if (cur_subchans[j] == candidate_subchan_freq) {
394 freq_list[num_radar_subchans++] =
395 candidate_subchan_freq;
396 dfs_info(dfs, WLAN_DEBUG_DFS,
397 "offset=%d, channel=%d",
398 num_radar_subchans,
399 freq_list[num_radar_subchans - 1]);
400 break;
401 }
402 }
403 }
404 return num_radar_subchans;
405 }
406 #endif
407
408 /**
409 * dfs_calc_bonding_freqs() - Calculate bonding channel frequencies
410 * @center_freq: Center frequency of the channel width.
411 * @ch_width: Channel width.
412 * @freq_list: output array of sub-channel frequencies.
413 *
414 * Calculate bonding channel frequencies from the channel width's
415 * center frequency and channel width. It is assumed that the caller
416 * has allocated sufficient memory for @freq_list so that it can hold
417 * all the output subchannels.
418 *
419 * Return: void
420 */
421 static void
dfs_calc_bonding_freqs(qdf_freq_t center_freq,uint16_t ch_width,uint16_t * freq_list)422 dfs_calc_bonding_freqs(qdf_freq_t center_freq,
423 uint16_t ch_width,
424 uint16_t *freq_list)
425 {
426 #define CHAN_SPACING_MHZ_5G 20
427 #define SUB20CHAN_BW_MHZ_5G 20
428 uint8_t nchans = ch_width / CHAN_SPACING_MHZ_5G;
429 qdf_freq_t first_subchan_cfreq = center_freq - (ch_width / 2) +
430 (SUB20CHAN_BW_MHZ_5G / 2);
431 uint8_t i;
432
433 for (i = 0; i < nchans; ++i)
434 freq_list[i] = first_subchan_cfreq + (i * CHAN_SPACING_MHZ_5G);
435 }
436
437 /**
438 * dfs_get_20mhz_bonding_channels() - Get bonding frequency list of 20MHz
439 * channel.
440 * @center_freq: Center frequency of the 20MHz channel.
441 * @freq_list: Pointer to frequency list.
442 *
443 * Return: void
444 */
445 static
dfs_get_20mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list)446 void dfs_get_20mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
447 {
448 uint16_t chwidth = BW_20;
449
450 dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
451 }
452
453 /**
454 * dfs_get_40mhz_bonding_channels() - Get bonding frequency list of 40MHz
455 * channel.
456 * @center_freq: Center frequency of the 40MHz channel.
457 * @freq_list: Pointer to frequency list.
458 *
459 * Return: void
460 */
461 static
dfs_get_40mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list)462 void dfs_get_40mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
463 {
464 uint16_t chwidth = BW_40;
465
466 dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
467 }
468
469 /**
470 * dfs_get_80mhz_bonding_channels() - Get bonding frequency list of 80MHz
471 * channel.
472 * @center_freq: Center frequency of the 80MHz channel.
473 * @freq_list: Pointer to frequency list.
474 *
475 * Return: void
476 */
477 static
dfs_get_80mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list)478 void dfs_get_80mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
479 {
480 uint16_t chwidth = BW_80;
481
482 dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
483 }
484
485 /**
486 * dfs_get_160mhz_bonding_channels() - Get bonding frequency list of 160MHz
487 * channel.
488 * @center_freq: Center frequency of the 160MHz channel.
489 * @freq_list: Pointer to frequency list.
490 *
491 * Return: void
492 */
493 static
dfs_get_160mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list)494 void dfs_get_160mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
495 {
496 uint16_t chwidth = BW_160;
497
498 dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
499 }
500
501 /**
502 * dfs_get_320mhz_bonding_channels() - Get bonding frequency list of 320 MHz
503 * channel.
504 * @center_freq: Center frequency of the 320 MHz channel.
505 * @freq_list: Pointer to frequency list.
506 * @nchannels: Number of channels in @freq_list
507 *
508 * Return: void
509 */
510 #ifdef WLAN_FEATURE_11BE
511 static
dfs_get_320mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list,uint8_t * nchannels)512 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
513 uint8_t *nchannels)
514 {
515 uint16_t chwidth = 320;
516
517 /*
518 * In 5 GHz band, the 320 MHz channel is always 80 MHz punctured
519 * to the right. Therefore, it is actually a 240 MHz channel and
520 * has twelve 20 MHz subchannels.
521 */
522 *nchannels = NUM_CHANNELS_240MHZ;
523 dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
524 }
525 #else
526 static
dfs_get_320mhz_bonding_channels(uint16_t center_freq,uint16_t * freq_list,uint8_t * nchannels)527 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
528 uint8_t *nchannels)
529 {
530 *nchannels = 0;
531 dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
532 "320MHz chan width for non 11be");
533 }
534 #endif
535
536 /**
537 * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency
538 * list.
539 * @chan: Pointer to dfs_channel.
540 * @freq_list: Pointer to frequency list.
541 */
542 #ifdef CONFIG_CHAN_FREQ_API
543 uint8_t
dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel * chan,uint16_t * freq_list)544 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan,
545 uint16_t *freq_list)
546 {
547 uint16_t center_freq;
548 uint8_t nchannels = 0;
549
550 center_freq = chan->dfs_ch_mhz_freq_seg1;
551
552 if (WLAN_IS_CHAN_MODE_20(chan)) {
553 nchannels = 1;
554 dfs_get_20mhz_bonding_channels(center_freq,
555 freq_list);
556 } else if (WLAN_IS_CHAN_MODE_40(chan)) {
557 nchannels = 2;
558 dfs_get_40mhz_bonding_channels(center_freq,
559 freq_list);
560 } else if (WLAN_IS_CHAN_MODE_80(chan)) {
561 nchannels = 4;
562 dfs_get_80mhz_bonding_channels(center_freq,
563 freq_list);
564 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
565 nchannels = 8;
566 dfs_get_80mhz_bonding_channels(center_freq,
567 freq_list);
568 center_freq = chan->dfs_ch_mhz_freq_seg2;
569 dfs_get_80mhz_bonding_channels(center_freq,
570 freq_list + 4);
571 } else if (WLAN_IS_CHAN_MODE_160(chan)) {
572 nchannels = 8;
573 center_freq = chan->dfs_ch_mhz_freq_seg2;
574 dfs_get_160mhz_bonding_channels(center_freq, freq_list);
575 } else if (WLAN_IS_CHAN_MODE_320(chan)) {
576 center_freq = chan->dfs_ch_mhz_freq_seg2;
577 dfs_get_320mhz_bonding_channels(center_freq, freq_list,
578 &nchannels);
579 }
580
581 return nchannels;
582 }
583 #endif
584
585 #ifdef CONFIG_CHAN_FREQ_API
586 /**
587 * dfs_get_agile_subchans_for_curchan_160() - Get bonding frequency list of
588 * agile channels when current operating channel is 160MHz.
589 *
590 * @dfs: Pointer to DFS structure.
591 * @center_freq: Center frequency of the channel.
592 * @segment_id: Segment ID of interest. 0 for primary segment and 1 for
593 * secondary segment.
594 * @freq_list: Pointer to frequency list.
595 * @nchannels: Number of subchannel.
596 */
597 static void
dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs * dfs,uint16_t center_freq,uint32_t segment_id,uint16_t * freq_list,uint8_t * nchannels)598 dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs *dfs,
599 uint16_t center_freq,
600 uint32_t segment_id,
601 uint16_t *freq_list,
602 uint8_t *nchannels)
603 {
604 if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
605 /*
606 * The current operating channel is 160MHz and
607 * the agile channel is 80MHz. This can happen
608 * in HK only.
609 */
610 *nchannels = 4;
611 dfs_get_80mhz_bonding_channels(center_freq,
612 freq_list);
613 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ)
614 /*
615 * The current operating channel is 160MHz and
616 * the agile channel is 160MHz.
617 * Pine ADFS specific.
618 */
619 dfs_get_160mhz_bonding_channels(center_freq,
620 freq_list);
621 else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) {
622 /*
623 * The current operating channel is 160MHz and the agile channel
624 * is 165MHz(restricted 80P80MHZ). Pine ADFS specific.
625 * If the segment id is primary segment 0, shift the center
626 * frequency 5730MHz to the center of left 80MHz segment 5690MHz
627 * and add the subchannels of the left 80MHz segment.
628 * If the segment id is secondary segment 1, shift the center
629 * frequency 5730MHz to the center of right 80MHz segment
630 * 5775MHz and add the subchannels of the right 80MHz segment.
631 */
632 *nchannels = 4;
633 center_freq = (segment_id) ?
634 (center_freq + DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT) :
635 (center_freq - DFS_165MHZ_SECOND_SEG_OFFSET_LEFT);
636 dfs_get_80mhz_bonding_channels(center_freq,
637 freq_list);
638 }
639 }
640
641 /**
642 * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency.
643 * @dfs: Pointer to wlan_dfs.
644 * @curchan: Pointer to dfs_channel.
645 * @segment_id: Segment ID.
646 * @detector_id: Detector ID.
647 * @freq_list: Pointer to frequency list.
648 */
dfs_get_bonding_channels_for_freq(struct wlan_dfs * dfs,struct dfs_channel * curchan,uint32_t segment_id,uint8_t detector_id,uint16_t * freq_list)649 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs,
650 struct dfs_channel *curchan,
651 uint32_t segment_id,
652 uint8_t detector_id,
653 uint16_t *freq_list)
654 {
655 uint16_t center_freq;
656 uint8_t nchannels = 0;
657
658 /*
659 * For radar in agile detector, use the center of the channel
660 * configured to the agile detector.
661 * For radar on a 160MHz home channel, use the center of 160MHz.
662 * For radar on all other bandwidths, use the center of the segment
663 * affected.
664 */
665 if (detector_id == dfs_get_agile_detector_id(dfs))
666 center_freq = dfs->dfs_agile_precac_freq_mhz;
667 else if (WLAN_IS_CHAN_MODE_160(curchan) ||
668 WLAN_IS_CHAN_MODE_320(curchan))
669 center_freq = curchan->dfs_ch_mhz_freq_seg2;
670 else if (!segment_id)
671 center_freq = curchan->dfs_ch_mhz_freq_seg1;
672 else
673 center_freq = curchan->dfs_ch_mhz_freq_seg2;
674
675 if (WLAN_IS_CHAN_MODE_20(curchan)) {
676 nchannels = 1;
677 dfs_get_20mhz_bonding_channels(center_freq, freq_list);
678 } else if (WLAN_IS_CHAN_MODE_40(curchan)) {
679 nchannels = 2;
680 dfs_get_40mhz_bonding_channels(center_freq, freq_list);
681 } else if (WLAN_IS_CHAN_MODE_80(curchan)) {
682 nchannels = 4;
683 dfs_get_80mhz_bonding_channels(center_freq, freq_list);
684 } else if (WLAN_IS_CHAN_MODE_160(curchan)) {
685 nchannels = 8;
686 if (detector_id == dfs_get_agile_detector_id(dfs))
687 dfs_get_agile_subchans_for_curchan_160(dfs,
688 center_freq,
689 segment_id,
690 freq_list,
691 &nchannels);
692 else
693 dfs_get_160mhz_bonding_channels(center_freq, freq_list);
694 } else if (WLAN_IS_CHAN_MODE_320(curchan)) {
695 dfs_get_320mhz_bonding_channels(center_freq, freq_list,
696 &nchannels);
697 } else if (WLAN_IS_CHAN_MODE_80_80(curchan)) {
698 /*
699 * If the current channel's bandwidth is 80P80MHz,
700 * the corresponding agile Detector's bandwidth will be 160MHz
701 * in case of Pine ADFS.
702 */
703 if (detector_id == dfs_get_agile_detector_id(dfs)) {
704 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
705 nchannels = 8;
706 dfs_get_160mhz_bonding_channels(center_freq,
707 freq_list);
708 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
709 nchannels = 4;
710 dfs_get_80mhz_bonding_channels(center_freq,
711 freq_list);
712 } else {
713 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
714 "Incorrect precac width %u",
715 dfs->dfs_precac_chwidth);
716 }
717 } else {
718 /*
719 * If the radar is getting detected in 80P80MHz home
720 * channel, only the 80MHz segment that is infected with
721 * radar is of interest. The other 80MHz segment is
722 * ignored. The center frequency of the radar infected
723 * segment is dfs_ch_mhz_freq_seg1 if primary and
724 * dfs_ch_mhz_freq_seg2 in case of secondary.
725 */
726 nchannels = 4;
727 dfs_get_80mhz_bonding_channels(center_freq, freq_list);
728 }
729 }
730
731 return nchannels;
732 }
733 #endif
734
dfs_reset_bangradar(struct wlan_dfs * dfs)735 void dfs_reset_bangradar(struct wlan_dfs *dfs)
736 {
737 dfs->dfs_bangradar_type = DFS_NO_BANGRADAR;
738 }
739
740 /**
741 * dfs_radar_found_event_basic_sanity() - Check if radar event is received on a
742 * DFS channel.
743 * @dfs: Pointer to wlan_dfs structure.
744 * @chan: Current channel.
745 *
746 * Return: If a radar event found on NON-DFS channel return false. Otherwise,
747 * return true.
748 */
749 static
dfs_radar_found_event_basic_sanity(struct wlan_dfs * dfs,struct dfs_channel * chan)750 bool dfs_radar_found_event_basic_sanity(struct wlan_dfs *dfs,
751 struct dfs_channel *chan)
752 {
753 if (!chan) {
754 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
755 "dfs->dfs_curchan is NULL");
756 return false;
757 }
758
759 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
760 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
761 "radar event on non-DFS chan");
762 return false;
763 }
764
765 return true;
766 }
767
dfs_send_csa_to_current_chan(struct wlan_dfs * dfs)768 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
769 {
770 dfs->wlan_dfstest = 1;
771 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
772 dfs->wlan_dfstesttime = 1; /* 1ms */
773 qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
774 qdf_timer_start(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
775 }
776
dfs_second_segment_radar_disable(struct wlan_dfs * dfs)777 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
778 {
779 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
780
781 return 0;
782 }
783
784 #ifdef WLAN_DFS_FULL_OFFLOAD
dfs_inc_num_radar(struct wlan_dfs * dfs)785 void dfs_inc_num_radar(struct wlan_dfs *dfs)
786 {
787 dfs->wlan_dfs_stats.num_radar_detects++;
788 }
789 #endif /* WLAN_DFS_FULL_OFFLOAD */
790
791 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD)
dfs_translate_radar_params(struct wlan_dfs * dfs,struct radar_found_info * radar_found)792 void dfs_translate_radar_params(struct wlan_dfs *dfs,
793 struct radar_found_info *radar_found)
794 {
795 struct dfs_channel *curchan = dfs->dfs_curchan;
796 bool is_primary_ch_right_of_center = false;
797
798 if (!dfs_is_true_160mhz_supported(dfs))
799 return;
800
801 if (dfs->dfs_is_radar_found_chan_freq_eq_center_freq) {
802 dfs_debug(dfs, WLAN_DEBUG_DFS, "There is no radar translation required for chips where HALPHY reports the exact radar found chan's center freq\n");
803 return;
804 }
805
806 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
807 dfs_translate_radar_params_for_agile_chan(dfs, radar_found);
808 return;
809 }
810
811 /* Is the primary channel ( or primary 80 segment) to the right
812 * of the center of 160/165Mhz channel.
813 */
814 if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2)
815 is_primary_ch_right_of_center = true;
816
817 if (WLAN_IS_CHAN_MODE_160(curchan)) {
818 if (radar_found->freq_offset > 0) {
819 /* Offset positive: Equivalent to Upper IEEE
820 * 80Mhz chans Synthesizer.
821 */
822 if (!is_primary_ch_right_of_center)
823 radar_found->segment_id = SEG_ID_SECONDARY;
824 radar_found->freq_offset -=
825 DFS_160MHZ_SECOND_SEG_OFFSET;
826 } else {
827 /* Offset negative: Equivalent to Lower IEEE
828 * 80Mhz chans Synthesizer.
829 */
830 if (is_primary_ch_right_of_center)
831 radar_found->segment_id = SEG_ID_SECONDARY;
832 radar_found->freq_offset +=
833 DFS_160MHZ_SECOND_SEG_OFFSET;
834 }
835 } else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) {
836 /* If offset is greater than 40MHz, radar is found on the
837 * secondary segment.
838 */
839 if (abs(radar_found->freq_offset) > 40) {
840 radar_found->segment_id = SEG_ID_SECONDARY;
841 /* Update the freq. offset with respect to the
842 * secondary segment center freq.
843 */
844 if (is_primary_ch_right_of_center)
845 radar_found->freq_offset +=
846 DFS_80P80MHZ_SECOND_SEG_OFFSET;
847 else
848 radar_found->freq_offset -=
849 DFS_80P80MHZ_SECOND_SEG_OFFSET;
850 }
851 }
852 }
853 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */
854
855 /**
856 * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW
857 * switch is in progress. So save the radar found parameters for
858 * future processing.
859 * @dfs: Pointer to wlan_dfs structure.
860 * @radar_found: Pointer to radar found structure.
861 *
862 * Return: QDF_STATUS
863 */
864 static QDF_STATUS
dfs_radar_action_for_hw_mode_switch(struct wlan_dfs * dfs,struct radar_found_info * radar_found)865 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs,
866 struct radar_found_info *radar_found)
867 {
868 struct radar_found_info *radar_params = NULL;
869
870 radar_params = qdf_mem_malloc(sizeof(*radar_params));
871 if (!radar_params)
872 return QDF_STATUS_E_NOMEM;
873
874 /* If CAC timer is running, cancel it here rather than
875 * after processing to avoid handling unnecessary CAC timeouts.
876 */
877 if (dfs->dfs_cac_timer_running)
878 dfs_cac_stop(dfs);
879
880 /* If CAC timer is to be handled after mode switch and then
881 * we receive radar, no point in handling CAC completion.
882 */
883 if (dfs->dfs_defer_params.is_cac_completed)
884 dfs->dfs_defer_params.is_cac_completed = false;
885 qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params));
886 dfs->dfs_defer_params.radar_params = radar_params;
887 dfs->dfs_defer_params.is_radar_detected = true;
888
889 return QDF_STATUS_SUCCESS;
890 }
891
892 #ifdef CONFIG_CHAN_FREQ_API
893 #ifdef MOBILE_DFS_SUPPORT
894 static uint8_t
dfs_find_radar_full_bw_channels(struct wlan_dfs * dfs,struct radar_found_info * radar_found,uint16_t * freq_list)895 dfs_find_radar_full_bw_channels(struct wlan_dfs *dfs,
896 struct radar_found_info *radar_found,
897 uint16_t *freq_list)
898 {
899 uint8_t num_channels = 0;
900
901 if (radar_found->is_full_bw_nol)
902 num_channels =
903 dfs_get_bonding_channel_without_seg_info_for_freq
904 (dfs->dfs_curchan, freq_list);
905
906 return num_channels;
907 }
908 #else
909 static uint8_t
dfs_find_radar_full_bw_channels(struct wlan_dfs * dfs,struct radar_found_info * radar_found,uint16_t * freq_list)910 dfs_find_radar_full_bw_channels(struct wlan_dfs *dfs,
911 struct radar_found_info *radar_found,
912 uint16_t *freq_list)
913 {
914 return 0;
915 }
916 #endif
917
918 uint8_t
dfs_find_radar_affected_channels(struct wlan_dfs * dfs,struct radar_found_info * radar_found,uint16_t * freq_list,uint32_t freq_center)919 dfs_find_radar_affected_channels(struct wlan_dfs *dfs,
920 struct radar_found_info *radar_found,
921 uint16_t *freq_list,
922 uint32_t freq_center)
923 {
924 uint8_t num_channels;
925
926 num_channels = dfs_find_radar_full_bw_channels(dfs, radar_found,
927 freq_list);
928 if (num_channels)
929 return num_channels;
930
931 if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS)
932 num_channels =
933 dfs_get_bonding_channel_without_seg_info_for_freq
934 (dfs->dfs_curchan, freq_list);
935 /* BW reduction is dependent on subchannel marking */
936 else if ((dfs->dfs_use_nol_subchannel_marking) &&
937 (!(dfs->dfs_bangradar_type) ||
938 (dfs->dfs_bangradar_type ==
939 DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS)))
940 num_channels =
941 dfs_find_radar_affected_subchans_for_freq(dfs,
942 radar_found,
943 freq_list,
944 freq_center);
945 else
946 num_channels = dfs_get_bonding_channels_for_freq
947 (dfs,
948 dfs->dfs_curchan,
949 radar_found->segment_id,
950 radar_found->detector_id,
951 freq_list);
952
953 return num_channels;
954 }
955
956 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \
957 defined(QCA_SUPPORT_ADFS_RCAC)
958 /**
959 * dfs_is_radarsource_agile() - Indicates whether the radar event is received
960 * on the agile channel.
961 * @dfs: Pointer to wlan_dfs structure.
962 * @radar_found: Pointer to radar_found_info structure.
963 *
964 * Return: QDF_STATUS
965 */
966 static
dfs_is_radarsource_agile(struct wlan_dfs * dfs,struct radar_found_info * radar_found)967 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
968 struct radar_found_info *radar_found)
969 {
970 bool is_radar_from_agile_dfs =
971 ((dfs_is_agile_precac_enabled(dfs) &&
972 dfs_is_precac_timer_running(dfs)) ||
973 dfs_is_agile_rcac_enabled(dfs)) &&
974 (radar_found->detector_id == dfs_get_agile_detector_id(dfs));
975
976 dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE,
977 "radar on PreCAC segment: ADFS:%d",
978 is_radar_from_agile_dfs);
979
980 return is_radar_from_agile_dfs;
981 }
982 #else
983 static
dfs_is_radarsource_agile(struct wlan_dfs * dfs,struct radar_found_info * radar_found)984 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
985 struct radar_found_info *radar_found)
986 {
987 return false;
988 }
989 #endif
990
991 #ifdef QCA_DFS_BW_PUNCTURE
dfs_generate_radar_bitmap(struct wlan_dfs * dfs,uint16_t * radar_freq_list,uint8_t num_radar_channels)992 uint16_t dfs_generate_radar_bitmap(struct wlan_dfs *dfs,
993 uint16_t *radar_freq_list,
994 uint8_t num_radar_channels)
995 {
996 uint8_t n_cur_channels;
997 uint16_t dfs_radar_bitmap = 0x0;
998 uint16_t bits = 0x1;
999 uint8_t i, j;
1000 uint16_t cur_freq_list[MAX_20MHZ_SUBCHANS] = {0};
1001
1002 n_cur_channels =
1003 dfs_get_bonding_channel_without_seg_info_for_freq(dfs->dfs_curchan,
1004 cur_freq_list);
1005
1006 for (i = 0; i < n_cur_channels; i++) {
1007 for (j = 0; j < num_radar_channels; j++) {
1008 if (cur_freq_list[i] == radar_freq_list[j]) {
1009 dfs_radar_bitmap |= bits;
1010 break;
1011 }
1012 }
1013 bits <<= 1;
1014 }
1015
1016 if (!dfs_radar_bitmap)
1017 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar bitmap is zero");
1018
1019 return dfs_radar_bitmap;
1020 }
1021 #endif
1022
1023 QDF_STATUS
dfs_process_radar_ind(struct wlan_dfs * dfs,struct radar_found_info * radar_found)1024 dfs_process_radar_ind(struct wlan_dfs *dfs,
1025 struct radar_found_info *radar_found)
1026 {
1027 QDF_STATUS status;
1028
1029 /* Acquire a lock to avoid initiating mode switch till radar
1030 * processing is completed.
1031 */
1032 DFS_RADAR_MODE_SWITCH_LOCK(dfs);
1033
1034 if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) {
1035 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1036 return QDF_STATUS_SUCCESS;
1037 }
1038
1039 /* Before processing radar, check if HW mode switch is in progress.
1040 * If in progress, defer the processing of radar event received till
1041 * the mode switch is completed.
1042 */
1043 if (dfs_is_hw_mode_switch_in_progress(dfs))
1044 status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found);
1045 else if (dfs_is_radarsource_agile(dfs, radar_found))
1046 status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found);
1047 else
1048 status = dfs_process_radar_ind_on_home_chan(dfs, radar_found);
1049
1050 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1051
1052 return status;
1053 }
1054
1055 QDF_STATUS
dfs_process_radar_ind_on_home_chan(struct wlan_dfs * dfs,struct radar_found_info * radar_found)1056 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
1057 struct radar_found_info *radar_found)
1058 {
1059 bool wait_for_csa = false;
1060 uint16_t freq_list[MAX_20MHZ_SUBCHANS];
1061 uint16_t nol_freq_list[MAX_20MHZ_SUBCHANS];
1062 uint8_t num_channels;
1063 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1064 uint32_t freq_center;
1065 uint32_t radarfound_freq;
1066 struct dfs_channel *dfs_curchan;
1067 uint16_t dfs_radar_bitmap = 0;
1068
1069 dfs_curchan = dfs->dfs_curchan;
1070
1071 /* Check if the current channel is a non DFS channel
1072 * If the current channel is non-DFS and the radar is from Agile
1073 * Detector we need to process it since Agile Detector has a
1074 * different channel.
1075 */
1076 if (!dfs_radar_found_event_basic_sanity(dfs, dfs_curchan))
1077 goto exit;
1078
1079 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center);
1080 radarfound_freq = freq_center + radar_found->freq_offset;
1081
1082 if (radar_found->segment_id == SEG_ID_SECONDARY)
1083 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
1084 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.",
1085 radarfound_freq, freq_center);
1086 else
1087 dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
1088 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.",
1089 utils_dfs_freq_to_chan(radarfound_freq),
1090 radarfound_freq, dfs_curchan->dfs_ch_ieee,
1091 dfs_curchan->dfs_ch_freq);
1092
1093 num_channels = dfs_find_radar_affected_channels(dfs,
1094 radar_found,
1095 freq_list,
1096 freq_center);
1097
1098 if (!dfs->dfs_use_nol) {
1099 if (!dfs->dfs_is_offload_enabled)
1100 dfs_disable_radar_and_flush_pulses(dfs);
1101 dfs_reset_bangradar(dfs);
1102 dfs_send_csa_to_current_chan(dfs);
1103 status = QDF_STATUS_SUCCESS;
1104 goto exit;
1105 }
1106
1107 dfs_reset_bangradar(dfs);
1108
1109 if (dfs->dfs_use_puncture && !dfs->dfs_is_stadfs_enabled) {
1110 bool is_ignore_radar_puncture = false;
1111
1112 dfs_handle_radar_puncturing(dfs,
1113 &dfs_radar_bitmap,
1114 freq_list,
1115 num_channels,
1116 &is_ignore_radar_puncture);
1117 if (is_ignore_radar_puncture)
1118 goto exit;
1119 }
1120
1121 status = dfs_radar_add_channel_list_to_nol_for_freq(dfs,
1122 freq_list,
1123 nol_freq_list,
1124 &num_channels);
1125 if (QDF_IS_STATUS_ERROR(status)) {
1126 dfs_err(dfs, WLAN_DEBUG_DFS,
1127 "radar event received on invalid channel");
1128 goto exit;
1129 }
1130
1131 dfs_mlme_set_tx_flag(dfs->dfs_pdev_obj, false);
1132
1133 /*
1134 * If precac is running and the radar found in secondary
1135 * VHT80 mark the channel as radar and add to NOL list.
1136 * Otherwise random channel selection can choose this
1137 * channel.
1138 */
1139 dfs_debug(dfs, WLAN_DEBUG_DFS,
1140 "found_on_second=%d is_pre=%d",
1141 dfs->is_radar_found_on_secondary_seg,
1142 dfs_is_precac_timer_running(dfs));
1143 /*
1144 * Even if radar found on primary, we need to mark the channel as NOL
1145 * in preCAC list. The preCAC list also maintains the current CAC
1146 * channels as part of pre-cleared DFS. Hence call the API
1147 * to mark channels as NOL irrespective of preCAC being enabled or not.
1148 */
1149
1150 dfs_debug(dfs, WLAN_DEBUG_DFS,
1151 "Radar found on dfs detector: %d", radar_found->detector_id);
1152 dfs_mark_precac_nol_for_freq(dfs,
1153 dfs->is_radar_found_on_secondary_seg,
1154 radar_found->detector_id,
1155 nol_freq_list,
1156 num_channels);
1157
1158 dfs_send_nol_ie_and_rcsa(dfs,
1159 radar_found,
1160 nol_freq_list,
1161 num_channels,
1162 &wait_for_csa);
1163
1164 if (!dfs->dfs_is_offload_enabled &&
1165 dfs->is_radar_found_on_secondary_seg) {
1166 dfs_second_segment_radar_disable(dfs);
1167 dfs->is_radar_found_on_secondary_seg = 0;
1168
1169 if (dfs->is_radar_during_precac) {
1170 dfs->is_radar_during_precac = 0;
1171 goto exit;
1172 }
1173 }
1174
1175 /*
1176 * XXX TODO: the umac NOL code isn't used, but
1177 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
1178 * NOL code isn't used, that flag is never cleared. This
1179 * needs to be fixed. See EV 105776.
1180 */
1181 if (wait_for_csa)
1182 goto exit;
1183
1184 /*
1185 * EV 129487 : We have detected radar in the channel,
1186 * stop processing PHY error data as this can cause
1187 * false detect in the new channel while channel
1188 * change is in progress.
1189 */
1190
1191 if (!dfs->dfs_is_offload_enabled) {
1192 /*
1193 * The radar queues were reset just after the filter match, but
1194 * the phyerror reception was not disabled. This might
1195 * cause the unwanted additional/accumulated pulses to be
1196 * detected as radar in the new channel. So, clear the radar
1197 * queues and the associated variables.
1198 */
1199 dfs_disable_radar_and_flush_pulses(dfs);
1200 }
1201
1202 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
1203 dfs->dfs_curchan->dfs_ch_ieee,
1204 dfs->dfs_curchan->dfs_ch_freq,
1205 dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
1206 dfs->dfs_curchan->dfs_ch_flags,
1207 dfs_radar_bitmap);
1208
1209 exit:
1210 if (QDF_IS_STATUS_SUCCESS(status))
1211 utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq,
1212 WLAN_EV_RADAR_DETECTED);
1213
1214 return status;
1215 }
1216 #endif
1217