xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 #include "../dfs.h"
29 #include "../dfs_random_chan_sel.h"
30 #include <qdf_mc_timer.h>
31 #include <wlan_utility.h>
32 
33 #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION
34 /*
35  * TODO: At present SAP Channel leakage matrix for ch 144
36  * is not available from system's team. So to play it safe
37  * and avoid crash if channel 144 is request, in following
38  * matix channel 144 is added such that it will cause code
39  * to avoid selecting channel 144.
40  *
41  * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS
42  * PROVIDED BY SYSTEM'S TEAM.
43  */
44 
45 /* channel tx leakage table - ht80 */
46 struct dfs_matrix_tx_leak_info ht80_chan[] = {
47 	{52,
48 	 {{36, 148}, {40, 199},
49 	  {44, 193}, {48, 197},
50 	  {52, DFS_TX_LEAKAGE_MIN}, {56, 153},
51 	  {60, 137}, {64, 134},
52 	  {100, 358}, {104, 350},
53 	  {108, 404}, {112, 344},
54 	  {116, 424}, {120, 429},
55 	  {124, 437}, {128, 435},
56 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
57 	  {140, DFS_TX_LEAKAGE_MAX},
58 	  {144, DFS_TX_LEAKAGE_MIN}
59 	  } },
60 
61 
62 	{56,
63 	 {{36, 171}, {40, 178},
64 	  {44, 171}, {48, 178},
65 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
66 	  {60, DFS_TX_LEAKAGE_MIN}, {64, 280},
67 	  {100, 351}, {104, 376},
68 	  {108, 362}, {112, 362},
69 	  {116, 403}, {120, 397},
70 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
71 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
72 	  {140, DFS_TX_LEAKAGE_MAX},
73 	  {144, DFS_TX_LEAKAGE_MIN}
74 	  } },
75 
76 	{60,
77 	 {{36, 156}, {40, 146},
78 	  {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN},
79 	  {52, 180}, {56, DFS_TX_LEAKAGE_MIN},
80 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
81 	  {100, 376}, {104, 360},
82 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
83 	  {116, 395}, {120, 399},
84 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
85 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
86 	  {140, DFS_TX_LEAKAGE_MAX},
87 	  {144, DFS_TX_LEAKAGE_MIN}
88 	  } },
89 
90 	{64,
91 	 {{36, 217}, {40, 221},
92 	  {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN},
93 	  {52, 176}, {56, 176},
94 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
95 	  {100, 384}, {104, 390},
96 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
97 	  {116, 375}, {120, 374},
98 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
99 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
100 	  {140, DFS_TX_LEAKAGE_MAX},
101 	  {144, DFS_TX_LEAKAGE_MIN}
102 	  } },
103 
104 	{100,
105 	 {{36, 357}, {40, 326},
106 	  {44, 321}, {48, 326},
107 	  {52, 378}, {56, 396},
108 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
109 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
110 	  {108, 196}, {112, 116},
111 	  {116, 166}, {120, DFS_TX_LEAKAGE_MIN},
112 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
113 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
114 	  {140, DFS_TX_LEAKAGE_MIN},
115 	  {144, DFS_TX_LEAKAGE_MIN}
116 	  } },
117 
118 	{104,
119 	 {{36, 325}, {40, 325},
120 	  {44, 305}, {48, 352},
121 	  {52, 411}, {56, 411},
122 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
123 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
124 	  {108, DFS_TX_LEAKAGE_MIN}, {112, 460},
125 	  {116, 198}, {120, DFS_TX_LEAKAGE_MIN},
126 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
127 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
128 	  {140, DFS_TX_LEAKAGE_MIN},
129 	  {144, DFS_TX_LEAKAGE_MIN}
130 	  } },
131 
132 	{108,
133 	 {{36, 304}, {40, 332},
134 	  {44, 310}, {48, 335},
135 	  {52, 431}, {56, 391},
136 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
137 	  {100, 280}, {104, DFS_TX_LEAKAGE_MIN},
138 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
139 	  {116, 185}, {120, DFS_TX_LEAKAGE_MIN},
140 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
141 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
142 	  {140, DFS_TX_LEAKAGE_MIN},
143 	  {144, DFS_TX_LEAKAGE_MIN}
144 	  } },
145 
146 	{112,
147 	 {{36, 327}, {40, 335},
148 	  {44, 331}, {48, 345},
149 	  {52, 367}, {56, 401},
150 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
151 	  {100, 131}, {104, 132},
152 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
153 	  {116, 189}, {120, DFS_TX_LEAKAGE_MIN},
154 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
155 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
156 	  {140, DFS_TX_LEAKAGE_MIN},
157 	  {144, DFS_TX_LEAKAGE_MIN}
158 	  } },
159 
160 	{116,
161 	 {{36, 384}, {40, 372},
162 	  {44, 389}, {48, 396},
163 	  {52, 348}, {56, 336},
164 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
165 	  {100, 172}, {104, 169},
166 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
167 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
168 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
169 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
170 	  {140, DFS_TX_LEAKAGE_MIN},
171 	  {144, DFS_TX_LEAKAGE_MIN}
172 	  } },
173 
174 	{120,
175 	 {{36, 395}, {40, 419},
176 	  {44, 439}, {48, 407},
177 	  {52, 321}, {56, 334},
178 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
179 	  {100, 134}, {104, 186},
180 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
181 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
182 	  {124, DFS_TX_LEAKAGE_MIN}, {128, 159},
183 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
184 	  {140, DFS_TX_LEAKAGE_MIN},
185 	  {144, DFS_TX_LEAKAGE_MIN}
186 	  } },
187 
188 	{124,
189 	 {{36, 469}, {40, 433},
190 	  {44, 434}, {48, 435},
191 	  {52, 332}, {56, 345},
192 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
193 	  {100, 146}, {104, 177},
194 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
195 	  {116, 350}, {120, DFS_TX_LEAKAGE_MIN},
196 	  {124, DFS_TX_LEAKAGE_MIN}, {128, 138},
197 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
198 	  {140, DFS_TX_LEAKAGE_MIN},
199 	  {144, DFS_TX_LEAKAGE_MIN}
200 	  } },
201 
202 	{128,
203 	 {{36, 408}, {40, 434},
204 	  {44, 449}, {48, 444},
205 	  {52, 341}, {56, 374},
206 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
207 	  {100, 205}, {104, 208},
208 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
209 	  {116, 142}, {120, DFS_TX_LEAKAGE_MIN},
210 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
211 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
212 	  {140, DFS_TX_LEAKAGE_MIN},
213 	  {144, DFS_TX_LEAKAGE_MIN}
214 	  } },
215 
216 	{132,
217 	 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX},
218 	  {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX},
219 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
220 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
221 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
222 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
223 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
224 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
225 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
226 	  {140, DFS_TX_LEAKAGE_MIN},
227 	  {144, DFS_TX_LEAKAGE_MIN}
228 	  } },
229 
230 	{136,
231 	 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX},
232 	  {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX},
233 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
234 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
235 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
236 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
237 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
238 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
239 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
240 	  {140, DFS_TX_LEAKAGE_MIN},
241 	  {144, DFS_TX_LEAKAGE_MIN}
242 	  } },
243 
244 	{140,
245 	 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX},
246 	  {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX},
247 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
248 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
249 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
250 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
251 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
252 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
253 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
254 	  {144, DFS_TX_LEAKAGE_MIN}
255 	  } },
256 
257 	{144,
258 	 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX},
259 	  {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX},
260 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
261 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
262 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
263 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
264 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
265 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
266 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
267 	  {144, DFS_TX_LEAKAGE_MIN}
268 	  } },
269 };
270 
271 /* channel tx leakage table - ht40 */
272 struct dfs_matrix_tx_leak_info ht40_chan[] = {
273 	{52,
274 	 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN},
275 	  {44, 230}, {48, 230},
276 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
277 	  {60, DFS_TX_LEAKAGE_AUTO_MIN}, {64, DFS_TX_LEAKAGE_AUTO_MIN},
278 	  {100, 625}, {104, 323},
279 	  {108, 646}, {112, 646},
280 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
281 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
282 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
283 	  {140, DFS_TX_LEAKAGE_MAX},
284 	  {144, DFS_TX_LEAKAGE_MIN}
285 	  } },
286 
287 	{56,
288 	 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN},
289 	  {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN},
290 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
291 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
292 	  {100, 611}, {104, 611},
293 	  {108, 617}, {112, 617},
294 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
295 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
296 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
297 	  {140, DFS_TX_LEAKAGE_MAX},
298 	  {144, DFS_TX_LEAKAGE_MIN}
299 	  } },
300 
301 	{60,
302 	 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN},
303 	  {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN},
304 	  {52, 190}, {56, 190},
305 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
306 	  {100, 608}, {104, 608},
307 	  {108, 623}, {112, 623},
308 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
309 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
310 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
311 	  {140, DFS_TX_LEAKAGE_MAX},
312 	  {144, DFS_TX_LEAKAGE_MIN}
313 	  } },
314 
315 	{64,
316 	 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN},
317 	  {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN},
318 	  {52, 295}, {56, 295},
319 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
320 	  {100, 594}, {104, 594},
321 	  {108, 625}, {112, 625},
322 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
323 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
324 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
325 	  {140, DFS_TX_LEAKAGE_MAX},
326 	  {144, DFS_TX_LEAKAGE_MIN}
327 	  } },
328 
329 	{100,
330 	 {{36, 618}, {40, 618},
331 	  {44, 604}, {48, 604},
332 	  {52, 596}, {56, 596},
333 	  {60, 584}, {64, 584},
334 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
335 	  {108, 299}, {112, 299},
336 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
337 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
338 	  {132, 538}, {136, 538},
339 	  {140, 598},
340 	  {144, DFS_TX_LEAKAGE_MIN}
341 	  } },
342 
343 	{104,
344 	 {{36, 636}, {40, 636},
345 	  {44, 601}, {48, 601},
346 	  {52, 616}, {56, 616},
347 	  {60, 584}, {64, 584},
348 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
349 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
350 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
351 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
352 	  {132, 553}, {136, 553},
353 	  {140, 568},
354 	  {144, DFS_TX_LEAKAGE_MIN}
355 	  } },
356 
357 	{108,
358 	 {{36, 600}, {40, 600},
359 	  {44, 627}, {48, 627},
360 	  {52, 611}, {56, 611},
361 	  {60, 611}, {64, 611},
362 	  {100, 214}, {104, 214},
363 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
364 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
365 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
366 	  {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN},
367 	  {140, 534},
368 	  {144, DFS_TX_LEAKAGE_MIN}
369 	  } },
370 
371 	{112,
372 	 {{36, 645}, {40, 645},
373 	  {44, 641}, {48, 641},
374 	  {52, 618}, {56, 618},
375 	  {60, 612}, {64, 612},
376 	  {100, 293}, {104, 293},
377 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
378 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
379 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
380 	  {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN},
381 	  {140, 521},
382 	  {144, DFS_TX_LEAKAGE_MIN}
383 	  } },
384 
385 	{116,
386 	 {{36, 661}, {40, 661},
387 	  {44, 624}, {48, 624},
388 	  {52, 634}, {56, 634},
389 	  {60, 611}, {64, 611},
390 	  {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN},
391 	  {108, 217}, {112, 217},
392 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
393 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
394 	  {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN},
395 	  {140, DFS_TX_LEAKAGE_AUTO_MIN},
396 	  {144, DFS_TX_LEAKAGE_MIN}
397 	  } },
398 
399 	{120,
400 	 {{36, 667}, {40, 667},
401 	  {44, 645}, {48, 645},
402 	  {52, 633}, {56, 633},
403 	  {60, 619}, {64, 619},
404 	  {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN},
405 	  {108, 291}, {112, 291},
406 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
407 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
408 	  {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN},
409 	  {140, DFS_TX_LEAKAGE_AUTO_MIN},
410 	  {144, DFS_TX_LEAKAGE_MIN}
411 	  } },
412 
413 	{124,
414 	 {{36, 676}, {40, 676},
415 	  {44, 668}, {48, 668},
416 	  {52, 595}, {56, 595},
417 	  {60, 622}, {64, 622},
418 	  {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN},
419 	  {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN},
420 	  {116, 225}, {120, 225},
421 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
422 	  {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN},
423 	  {140, DFS_TX_LEAKAGE_AUTO_MIN},
424 	  {144, DFS_TX_LEAKAGE_MIN}
425 	  } },
426 
427 	{128,
428 	 {{36, 678}, {40, 678},
429 	  {44, 664}, {48, 664},
430 	  {52, 651}, {56, 651},
431 	  {60, 643}, {64, 643},
432 	  {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN},
433 	  {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN},
434 	  {116, 293}, {120, 293},
435 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
436 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
437 	  {140, DFS_TX_LEAKAGE_AUTO_MIN},
438 	  {144, DFS_TX_LEAKAGE_MIN}
439 	  } },
440 
441 	{132,
442 	 {{36, 689}, {40, 689},
443 	  {44, 669}, {48, 669},
444 	  {52, 662}, {56, 662},
445 	  {60, 609}, {64, 609},
446 	  {100, 538}, {104, 538},
447 	  {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN},
448 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
449 	  {124, 247}, {128, 247},
450 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
451 	  {140, DFS_TX_LEAKAGE_MIN},
452 	  {144, DFS_TX_LEAKAGE_MIN}
453 	  } },
454 
455 	{136,
456 	 {{36, 703}, {40, 703},
457 	  {44, 688}, {48, DFS_TX_LEAKAGE_MIN},
458 	  {52, 671}, {56, 671},
459 	  {60, 658}, {64, 658},
460 	  {100, 504}, {104, 504},
461 	  {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN},
462 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
463 	  {124, 289}, {128, 289},
464 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
465 	  {140, DFS_TX_LEAKAGE_MIN},
466 	  {144, DFS_TX_LEAKAGE_MIN}
467 	  } },
468 
469 	{140,
470 	 {{36, 695}, {40, 695},
471 	  {44, 684}, {48, 684},
472 	  {52, 664}, {56, 664},
473 	  {60, 658}, {64, 658},
474 	  {100, 601}, {104, 601},
475 	  {108, 545}, {112, 545},
476 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
477 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
478 	  {132, 262}, {136, 262},
479 	  {140, DFS_TX_LEAKAGE_MIN},
480 	  {144, DFS_TX_LEAKAGE_MIN}
481 	  } },
482 
483 	{144,
484 	 {{36, 695}, {40, 695},
485 	  {44, 684}, {48, 684},
486 	  {52, 664}, {56, 664},
487 	  {60, 658}, {64, 658},
488 	  {100, 601}, {104, 601},
489 	  {108, 545}, {112, 545},
490 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN},
491 	  {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN},
492 	  {132, 262}, {136, 262},
493 	  {140, DFS_TX_LEAKAGE_MIN},
494 	  {144, DFS_TX_LEAKAGE_MIN}
495 	  } },
496 };
497 
498 /* channel tx leakage table - ht20 */
499 struct dfs_matrix_tx_leak_info ht20_chan[] = {
500 	{52,
501 	 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 286},
502 	  {44, 225}, {48, 121},
503 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
504 	  {60, 300}, {64, DFS_TX_LEAKAGE_AUTO_MIN},
505 	  {100, 637}, {104, DFS_TX_LEAKAGE_MAX},
506 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
507 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
508 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
509 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
510 	  {140, DFS_TX_LEAKAGE_MAX},
511 	  {144, DFS_TX_LEAKAGE_MIN}
512 	  } },
513 
514 	{56,
515 	 {{36, 468}, {40, DFS_TX_LEAKAGE_AUTO_MIN},
516 	  {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 206},
517 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
518 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
519 	  {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX},
520 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
521 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
522 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
523 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
524 	  {140, DFS_TX_LEAKAGE_MAX},
525 	  {144, DFS_TX_LEAKAGE_MIN}
526 	  } },
527 
528 	{60,
529 	 {{36, 507}, {40, 440},
530 	  {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 313},
531 	  {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN},
532 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
533 	  {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX},
534 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
535 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
536 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
537 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
538 	  {140, DFS_TX_LEAKAGE_MAX},
539 	  {144, DFS_TX_LEAKAGE_MIN}
540 	  } },
541 
542 	{64,
543 	 {{36, 516}, {40, 520},
544 	  {44, 506}, {48, DFS_TX_LEAKAGE_AUTO_MIN},
545 	  {52, 301}, {56, 258},
546 	  {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN},
547 	  {100, 620}, {104, 617},
548 	  {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX},
549 	  {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX},
550 	  {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX},
551 	  {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX},
552 	  {140, DFS_TX_LEAKAGE_MAX},
553 	  {144, DFS_TX_LEAKAGE_MIN}
554 	  } },
555 
556 	{100,
557 	 {{36, 616}, {40, 601},
558 	  {44, 604}, {48, 589},
559 	  {52, 612}, {56, 592},
560 	  {60, 590}, {64, 582},
561 	  {100, DFS_TX_LEAKAGE_MIN}, {104, 131},
562 	  {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN},
563 	  {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 522},
564 	  {124, 571}, {128, 589},
565 	  {132, 593}, {136, 598},
566 	  {140, 594},
567 	  {144, DFS_TX_LEAKAGE_MIN},
568 	  } },
569 
570 	{104,
571 	 {{36, 622}, {40, 624},
572 	  {44, 618}, {48, 610},
573 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
574 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
575 	  {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN},
576 	  {108, DFS_TX_LEAKAGE_MIN}, {112, 463},
577 	  {116, 483}, {120, 503},
578 	  {124, 523}, {128, 565},
579 	  {132, 570}, {136, 588},
580 	  {140, 585},
581 	  {144, DFS_TX_LEAKAGE_MIN},
582 	  } },
583 
584 	{108,
585 	 {{36, 620}, {40, 638},
586 	  {44, 611}, {48, 614},
587 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
588 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
589 	  {100, 477}, {104, DFS_TX_LEAKAGE_MIN},
590 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
591 	  {116, 477}, {120, 497},
592 	  {124, 517}, {128, 537},
593 	  {132, 557}, {136, 577},
594 	  {140, 603},
595 	  {144, DFS_TX_LEAKAGE_MIN},
596 	  } },
597 
598 	{112,
599 	 {{36, 636}, {40, 623},
600 	  {44, 638}, {48, 628},
601 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
602 	  {60, DFS_TX_LEAKAGE_MAX}, {64, 606},
603 	  {100, 501}, {104, 481},
604 	  {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN},
605 	  {116, DFS_TX_LEAKAGE_MIN}, {120, 481},
606 	  {124, 501}, {128, 421},
607 	  {132, 541}, {136, 561},
608 	  {140, 583},
609 	  {144, DFS_TX_LEAKAGE_MIN},
610 	  } },
611 
612 	{116,
613 	 {{36, 646}, {40, 648},
614 	  {44, 633}, {48, 634},
615 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
616 	  {60, 615}, {64, 594},
617 	  {100, 575}, {104, 554},
618 	  {108, 534}, {112, DFS_TX_LEAKAGE_MIN},
619 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
620 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
621 	  {132, 534}, {136, 554},
622 	  {140, 574},
623 	  {144, DFS_TX_LEAKAGE_MIN},
624 	  } },
625 
626 	{120,
627 	 {{36, 643}, {40, 649},
628 	  {44, 654}, {48, 629},
629 	  {52, DFS_TX_LEAKAGE_MAX}, {56, 621},
630 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
631 	  {100, 565}, {104, 545},
632 	  {108, 525}, {112, 505},
633 	  {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN},
634 	  {124, DFS_TX_LEAKAGE_MIN}, {128, 505},
635 	  {132, 525}, {136, 545},
636 	  {140, 565},
637 	  {144, DFS_TX_LEAKAGE_MIN},
638 	  } },
639 
640 	{124,
641 	 {{36, 638}, {40, 657},
642 	  {44, 663}, {48, 649},
643 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
644 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
645 	  {100, 581}, {104, 561},
646 	  {108, 541}, {112, 521},
647 	  {116, 499}, {120, DFS_TX_LEAKAGE_MIN},
648 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
649 	  {132, 499}, {136, 519},
650 	  {140, 539},
651 	  {144, DFS_TX_LEAKAGE_MIN}
652 	  } },
653 
654 	{128,
655 	 {{36, 651}, {40, 651},
656 	  {44, 674}, {48, 640},
657 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
658 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
659 	  {100, 603}, {104, 560},
660 	  {108, 540}, {112, 520},
661 	  {116, 499}, {120, 479},
662 	  {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN},
663 	  {132, DFS_TX_LEAKAGE_MIN}, {136, 479},
664 	  {140, 499},
665 	  {144, DFS_TX_LEAKAGE_MIN}
666 	  } },
667 
668 	{132,
669 	 {{36, 643}, {40, 668},
670 	  {44, 651}, {48, 657},
671 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
672 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
673 	  {100, DFS_TX_LEAKAGE_MAX}, {104, 602},
674 	  {108, 578}, {112, 570},
675 	  {116, 550}, {120, 530},
676 	  {124, 510}, {128, DFS_TX_LEAKAGE_MIN},
677 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
678 	  {140, 490},
679 	  {144, DFS_TX_LEAKAGE_MIN}
680 	  } },
681 
682 	{136,
683 	 {{36, 654}, {40, 667},
684 	  {44, 666}, {48, 642},
685 	  {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX},
686 	  {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX},
687 	  {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX},
688 	  {108, DFS_TX_LEAKAGE_MAX}, {112, 596},
689 	  {116, 555}, {120, 535},
690 	  {124, 515}, {128, 495},
691 	  {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN},
692 	  {140, DFS_TX_LEAKAGE_MIN},
693 	  {144, DFS_TX_LEAKAGE_MIN}
694 	  } },
695 
696 	{140,
697 	 {{36, 679}, {40, 673},
698 	  {44, 667}, {48, 656},
699 	  {52, 634}, {56, 663},
700 	  {60, 662}, {64, 660},
701 	  {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX},
702 	  {108, DFS_TX_LEAKAGE_MAX}, {112, 590},
703 	  {116, 573}, {120, 553},
704 	  {124, 533}, {128, 513},
705 	  {132, 490}, {136, DFS_TX_LEAKAGE_MIN},
706 	  {140, DFS_TX_LEAKAGE_MIN},
707 	  {144, DFS_TX_LEAKAGE_MIN}
708 	  } },
709 
710 	{144,
711 	 {{36, 679}, {40, 673},
712 	  {44, 667}, {48, 656},
713 	  {52, 634}, {56, 663},
714 	  {60, 662}, {64, 660},
715 	  {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX},
716 	  {108, DFS_TX_LEAKAGE_MAX}, {112, 590},
717 	  {116, 573}, {120, 553},
718 	  {124, 533}, {128, 513},
719 	  {132, 490}, {136, DFS_TX_LEAKAGE_MIN},
720 	  {140, DFS_TX_LEAKAGE_MIN},
721 	  {144, DFS_TX_LEAKAGE_MIN}
722 	  } },
723 };
724 
725 /*
726  * dfs_find_target_channel_in_channel_matrix() - finds the leakage matrix
727  * @ch_width: target channel width
728  * @NOL_channel: the NOL channel whose leakage matrix is required
729  * @pTarget_chnl_mtrx: pointer to target channel matrix returned.
730  *
731  * This function gives the leakage matrix for given NOL channel and ch_width
732  *
733  * Return: TRUE or FALSE
734  */
735 static bool
736 dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width,
737 				uint8_t NOL_channel,
738 				struct dfs_tx_leak_info **pTarget_chnl_mtrx)
739 {
740 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
741 	struct dfs_matrix_tx_leak_info *pchan_matrix = NULL;
742 	uint32_t nchan_matrix;
743 	int i = 0;
744 
745 	switch (ch_width) {
746 	case CH_WIDTH_20MHZ:
747 		/* HT20 */
748 		pchan_matrix = ht20_chan;
749 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
750 		break;
751 	case CH_WIDTH_40MHZ:
752 		/* HT40 */
753 		pchan_matrix = ht40_chan;
754 		nchan_matrix = QDF_ARRAY_SIZE(ht40_chan);
755 		break;
756 	case CH_WIDTH_80MHZ:
757 		/* HT80 */
758 		pchan_matrix = ht80_chan;
759 		nchan_matrix = QDF_ARRAY_SIZE(ht80_chan);
760 		break;
761 	default:
762 		/* handle exception and fall back to HT20 table */
763 		pchan_matrix = ht20_chan;
764 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
765 		break;
766 	}
767 
768 	for (i = 0; i < nchan_matrix; i++) {
769 		/* find the SAP channel to map the leakage matrix */
770 		if (NOL_channel == pchan_matrix[i].channel) {
771 			target_chan_matrix = pchan_matrix[i].chan_matrix;
772 			break;
773 		}
774 	}
775 
776 	if (NULL == target_chan_matrix) {
777 		return false;
778 	} else {
779 		*pTarget_chnl_mtrx = target_chan_matrix;
780 		return true;
781 	}
782 }
783 
784 QDF_STATUS
785 dfs_mark_leaking_ch(struct wlan_dfs *dfs,
786 		enum phy_ch_width ch_width,
787 		uint8_t temp_ch_lst_sz,
788 		uint8_t *temp_ch_lst)
789 {
790 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
791 	uint32_t         num_channel = (CHAN_ENUM_144 - CHAN_ENUM_36) + 1;
792 	uint32_t         j = 0;
793 	uint32_t         k = 0;
794 	uint8_t          dfs_nol_channel;
795 	struct dfs_nolelem *nol;
796 
797 	nol = dfs->dfs_nol;
798 	while (nol) {
799 		dfs_nol_channel = wlan_freq_to_chan(nol->nol_freq);
800 		if (false == dfs_find_target_channel_in_channel_matrix(
801 					ch_width, dfs_nol_channel,
802 					&target_chan_matrix)) {
803 			/*
804 			 * should never happen, we should always find a table
805 			 * here, if we don't, need a fix here!
806 			 */
807 			dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
808 				"Couldn't find target channel matrix!");
809 			QDF_ASSERT(0);
810 			return QDF_STATUS_E_FAILURE;
811 		}
812 		/*
813 		 * following is based on assumption that both temp_ch_lst
814 		 * and target channel matrix are in increasing order of
815 		 * ch_id
816 		 */
817 		for (j = 0, k = 0; j < temp_ch_lst_sz && k < num_channel;) {
818 			if (temp_ch_lst[j] == 0) {
819 				j++;
820 				continue;
821 			}
822 			if (target_chan_matrix[k].leak_chan != temp_ch_lst[j]) {
823 				k++;
824 				continue;
825 			}
826 			/*
827 			 * check leakage from candidate channel
828 			 * to NOL channel
829 			 */
830 			if (target_chan_matrix[k].leak_lvl <=
831 				dfs->tx_leakage_threshold) {
832 				/*
833 				 * candidate channel will have
834 				 * bad leakage in NOL channel,
835 				 * remove from temp list
836 				 */
837 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
838 					"dfs: channel: %d will have bad leakage due to channel: %d\n",
839 					dfs_nol_channel, temp_ch_lst[j]);
840 				temp_ch_lst[j] = 0;
841 			}
842 			j++;
843 			k++;
844 		}
845 		nol = nol->nol_next;
846 	} /* end of loop that selects each NOL */
847 
848 	return QDF_STATUS_SUCCESS;
849 }
850 #else
851 QDF_STATUS
852 dfs_mark_leaking_ch(struct wlan_dfs *dfs,
853 		enum phy_ch_width ch_width,
854 		uint8_t temp_ch_lst_sz,
855 		uint8_t *temp_ch_lst)
856 {
857 	return QDF_STATUS_SUCCESS;
858 }
859 #endif
860 
861 /**
862  * dfs_populate_80mhz_available_channels()- Populate channels for 80MHz using
863  *                                          bitmap
864  * @dfs: Pointer to DFS structure.
865  * @bitmap: bitmap
866  * @avail_chnl: prepared channel list
867  *
868  * Prepare 80MHz channels from the bitmap.
869  *
870  * Return: channel count
871  */
872 static uint8_t dfs_populate_80mhz_available_channels(
873 		struct wlan_dfs *dfs,
874 		struct chan_bonding_bitmap *bitmap,
875 		uint8_t *avail_chnl)
876 {
877 	uint8_t i = 0;
878 	uint8_t chnl_count = 0;
879 	uint8_t start_chan = 0;
880 
881 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
882 		start_chan = bitmap->chan_bonding_set[i].start_chan;
883 		if (bitmap->chan_bonding_set[i].chan_map ==
884 			DFS_80MHZ_MASK) {
885 			avail_chnl[chnl_count++] = start_chan +
886 				(DFS_NEXT_5GHZ_CHANNEL * 0);
887 			avail_chnl[chnl_count++] = start_chan +
888 				(DFS_NEXT_5GHZ_CHANNEL * 1);
889 			avail_chnl[chnl_count++] = start_chan +
890 				(DFS_NEXT_5GHZ_CHANNEL * 2);
891 			avail_chnl[chnl_count++] = start_chan +
892 				(DFS_NEXT_5GHZ_CHANNEL * 3);
893 		}
894 	}
895 
896 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
897 			"channel count %d", chnl_count);
898 
899 	return chnl_count;
900 }
901 
902 /**
903  * dfs_populate_40mhz_available_channels()- Populate channels for 40MHz using
904  *                                          bitmap
905  * @dfs: Pointer to DFS structure.
906  * @bitmap: bitmap
907  * @avail_chnl: prepared channel list
908  *
909  * Prepare 40MHz channels from the bitmap.
910  *
911  * Return: channel count
912  */
913 static uint8_t dfs_populate_40mhz_available_channels(
914 		struct wlan_dfs *dfs,
915 		struct chan_bonding_bitmap *bitmap,
916 		uint8_t *avail_chnl)
917 {
918 	uint8_t i = 0;
919 	uint8_t chnl_count = 0;
920 	uint8_t start_chan = 0;
921 
922 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
923 		start_chan = bitmap->chan_bonding_set[i].start_chan;
924 		if ((bitmap->chan_bonding_set[i].chan_map &
925 			DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) {
926 			avail_chnl[chnl_count++] = start_chan +
927 				(DFS_NEXT_5GHZ_CHANNEL * 0);
928 			avail_chnl[chnl_count++] = start_chan +
929 				(DFS_NEXT_5GHZ_CHANNEL * 1);
930 		}
931 		if ((bitmap->chan_bonding_set[i].chan_map &
932 			DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) {
933 			avail_chnl[chnl_count++] = start_chan +
934 				(DFS_NEXT_5GHZ_CHANNEL * 2);
935 			avail_chnl[chnl_count++] = start_chan +
936 				(DFS_NEXT_5GHZ_CHANNEL * 3);
937 		}
938 	}
939 
940 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
941 			"channel count %d", chnl_count);
942 
943 	return chnl_count;
944 }
945 
946 /**
947  * dfs_populate_available_channels()- Populate channels based on width and
948  *                                    bitmap
949  * @dfs: Pointer to DFS structure.
950  * @bitmap: bitmap
951  * @ch_width: channel width
952  * @avail_chnl: prepared channel list
953  *
954  * Prepare channel list based on width and channel bitmap.
955  *
956  * Return: channel count
957  */
958 static uint8_t dfs_populate_available_channels(
959 		struct wlan_dfs *dfs,
960 		struct chan_bonding_bitmap *bitmap,
961 		uint8_t ch_width,
962 		uint8_t *avail_chnl)
963 {
964 	switch (ch_width) {
965 	case DFS_CH_WIDTH_160MHZ:
966 	case DFS_CH_WIDTH_80P80MHZ:
967 	case DFS_CH_WIDTH_80MHZ:
968 		return dfs_populate_80mhz_available_channels(
969 			dfs, bitmap, avail_chnl);
970 	case DFS_CH_WIDTH_40MHZ:
971 		return dfs_populate_40mhz_available_channels(
972 			dfs, bitmap, avail_chnl);
973 	default:
974 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
975 				"Invalid ch_width %d", ch_width);
976 		break;
977 	}
978 
979 	return 0;
980 }
981 
982 /**
983  * dfs_get_rand_from_lst()- Get random channel from a given channel list
984  * @dfs: Pointer to DFS structure.
985  * @ch_lst: channel list
986  * @num_ch: number of channels
987  *
988  * Get random channel from given channel list.
989  *
990  * Return: channel number
991  */
992 static uint8_t dfs_get_rand_from_lst(
993 		struct wlan_dfs *dfs,
994 		uint8_t *ch_lst,
995 		uint8_t num_ch)
996 {
997 	uint8_t i;
998 	uint32_t rand_byte = 0;
999 
1000 	if (!num_ch || !ch_lst) {
1001 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
1002 				"invalid param ch_lst %pK, num_ch = %d",
1003 				ch_lst, num_ch);
1004 		return 0;
1005 	}
1006 
1007 	get_random_bytes((uint8_t *)&rand_byte, 1);
1008 	i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_ch;
1009 
1010 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1011 			"random channel %d", ch_lst[i]);
1012 
1013 	return ch_lst[i];
1014 }
1015 
1016 /**
1017  * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based
1018  * on given channel number
1019  * @dfs: Pointer to DFS structure.
1020  * @bitmap: bitmap
1021  * @channel: channel number
1022  *
1023  * Set channel bit in bitmap based on given channel number.
1024  *
1025  * Return: None
1026  */
1027 static void dfs_random_channel_sel_set_bitmap(
1028 		struct wlan_dfs *dfs,
1029 		struct chan_bonding_bitmap *bitmap,
1030 		uint8_t channel)
1031 {
1032 	int i = 0;
1033 	int start_chan = 0;
1034 
1035 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1036 		start_chan = bitmap->chan_bonding_set[i].start_chan;
1037 		if (channel >= start_chan && channel <= start_chan + 12) {
1038 			bitmap->chan_bonding_set[i].chan_map |=
1039 			(1 << ((channel - start_chan) /
1040 			DFS_80_NUM_SUB_CHANNNEL));
1041 			return;
1042 		}
1043 	}
1044 
1045 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1046 			"Channel=%d is not in the bitmap", channel);
1047 }
1048 
1049 /**
1050  * dfs_find_ch_with_fallback()- find random channel
1051  * @dfs: Pointer to DFS structure.
1052  * @ch_wd: channel width
1053  * @center_freq_seg1: center frequency of secondary segment.
1054  * @ch_lst: list of available channels.
1055  * @num_ch: number of channels in the list.
1056  *
1057  * Find random channel based on given channel width and channel list,
1058  * fallback to lower width if requested channel width not available.
1059  *
1060  * Return: channel number
1061  */
1062 static uint8_t dfs_find_ch_with_fallback(
1063 		struct wlan_dfs *dfs,
1064 		uint8_t *ch_wd,
1065 		uint8_t *center_freq_seg1,
1066 		uint8_t *ch_lst,
1067 		uint32_t num_ch)
1068 {
1069 	bool flag = false;
1070 	uint32_t rand_byte = 0;
1071 	struct  chan_bonding_bitmap ch_map = { { {0} } };
1072 	uint8_t count = 0, i, index = 0, final_cnt = 0, target_channel = 0;
1073 	uint8_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0;
1074 	uint8_t final_lst[DFS_MAX_NUM_CHAN] = {0};
1075 
1076 	/* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */
1077 	ch_map.chan_bonding_set[0].start_chan = 36;
1078 	ch_map.chan_bonding_set[1].start_chan = 52;
1079 	ch_map.chan_bonding_set[2].start_chan = 100;
1080 	ch_map.chan_bonding_set[3].start_chan = 116;
1081 	ch_map.chan_bonding_set[4].start_chan = 132;
1082 	ch_map.chan_bonding_set[5].start_chan = 149;
1083 
1084 	for (i = 0; i < num_ch; i++) {
1085 		dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1086 				"channel = %d added to bitmap", ch_lst[i]);
1087 		dfs_random_channel_sel_set_bitmap(dfs, &ch_map, ch_lst[i]);
1088 	}
1089 
1090 	/* populate available channel list from bitmap */
1091 	final_cnt = dfs_populate_available_channels(dfs, &ch_map,
1092 			*ch_wd, final_lst);
1093 
1094 	/* If no valid ch bonding found, fallback */
1095 	if (final_cnt == 0) {
1096 		if ((*ch_wd == DFS_CH_WIDTH_160MHZ) ||
1097 		    (*ch_wd == DFS_CH_WIDTH_80P80MHZ) ||
1098 		    (*ch_wd == DFS_CH_WIDTH_80MHZ)) {
1099 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1100 					"from [%d] to 40Mhz", *ch_wd);
1101 			*ch_wd = DFS_CH_WIDTH_40MHZ;
1102 		} else if (*ch_wd == DFS_CH_WIDTH_40MHZ) {
1103 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1104 					"from 40Mhz to 20MHz");
1105 			*ch_wd = DFS_CH_WIDTH_20MHZ;
1106 		}
1107 		return 0;
1108 	}
1109 
1110 	/* ch count should be > 8 to switch new channel in 160Mhz band */
1111 	if (((*ch_wd == DFS_CH_WIDTH_160MHZ) ||
1112 	     (*ch_wd == DFS_CH_WIDTH_80P80MHZ)) &&
1113 	     (final_cnt < DFS_MAX_20M_SUB_CH)) {
1114 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1115 				"from [%d] to 80Mhz", *ch_wd);
1116 		*ch_wd = DFS_CH_WIDTH_80MHZ;
1117 		return 0;
1118 	}
1119 
1120 	if (*ch_wd == DFS_CH_WIDTH_160MHZ) {
1121 		/*
1122 		 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128
1123 		 * and all the channels in these blocks are continuous
1124 		 * and seperated by 4Mhz.
1125 		 */
1126 		for (i = 1; ((i < final_cnt)); i++) {
1127 			if ((final_lst[i] - final_lst[i-1]) ==
1128 			     DFS_NEXT_5GHZ_CHANNEL)
1129 				count++;
1130 			else
1131 				count = 0;
1132 			if (count == DFS_MAX_20M_SUB_CH - 1) {
1133 				flag = true;
1134 				new_160_start_ch = final_lst[i - count];
1135 				break;
1136 			}
1137 		}
1138 	} else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) {
1139 		flag = true;
1140 	}
1141 
1142 	if ((flag == false) && (*ch_wd > DFS_CH_WIDTH_80MHZ)) {
1143 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1144 				"from [%d] to 80Mhz", *ch_wd);
1145 		*ch_wd = DFS_CH_WIDTH_80MHZ;
1146 		return 0;
1147 	}
1148 
1149 	if (*ch_wd == DFS_CH_WIDTH_160MHZ) {
1150 		get_random_bytes((uint8_t *)&rand_byte, 1);
1151 		rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks())
1152 			% DFS_MAX_20M_SUB_CH;
1153 		target_channel = new_160_start_ch + (rand_byte *
1154 				DFS_80_NUM_SUB_CHANNNEL);
1155 	} else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) {
1156 		get_random_bytes((uint8_t *)&rand_byte, 1);
1157 		index = (rand_byte + qdf_mc_timer_get_system_ticks()) %
1158 			final_cnt;
1159 		target_channel = final_lst[index];
1160 		index -= (index % DFS_80_NUM_SUB_CHANNNEL);
1161 		primary_seg_start_ch = final_lst[index];
1162 
1163 		/* reset channels associate with primary 80Mhz */
1164 		for (i = 0; i < DFS_80_NUM_SUB_CHANNNEL; i++)
1165 			final_lst[i + index] = 0;
1166 		/* select and calculate center freq for secondary segement */
1167 		for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNNEL; i++) {
1168 			if (final_lst[i * DFS_80_NUM_SUB_CHANNNEL] &&
1169 			    (abs(primary_seg_start_ch -
1170 			     final_lst[i * DFS_80_NUM_SUB_CHANNNEL]) >
1171 			     (DFS_MAX_20M_SUB_CH * 2))) {
1172 				sec_seg_ch =
1173 					final_lst[i * DFS_80_NUM_SUB_CHANNNEL] +
1174 					DFS_80MHZ_START_CENTER_CH_DIFF;
1175 				break;
1176 			}
1177 		}
1178 
1179 		if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH))
1180 			*ch_wd = DFS_CH_WIDTH_160MHZ;
1181 		else if (!sec_seg_ch)
1182 			*ch_wd = DFS_CH_WIDTH_80MHZ;
1183 
1184 		*center_freq_seg1 = sec_seg_ch;
1185 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1186 				"Center frequency seg1 = %d", sec_seg_ch);
1187 	} else {
1188 		target_channel = dfs_get_rand_from_lst(dfs,
1189 				final_lst, final_cnt);
1190 	}
1191 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1192 			"target channel = %d", target_channel);
1193 
1194 	return target_channel;
1195 }
1196 
1197 /**
1198  * dfs_remove_cur_ch_from_list()- remove current operating channels
1199  * @ch_list: list of avilable channel list
1200  * @ch_cnt: number of channels.
1201  * @ch_wd: channel width.
1202  * @cur_chan: current channel.
1203  *
1204  * Remove current channels from list of available channels.
1205  *
1206  * Return: channel number
1207  */
1208 static void dfs_remove_cur_ch_from_list(
1209 	struct dfs_channel *ch_list,
1210 	uint32_t *ch_cnt,
1211 	uint8_t *ch_wd,
1212 	struct dfs_channel *cur_chan)
1213 {
1214 	/* TODO */
1215 	return;
1216 }
1217 
1218 /**
1219  * dfs_freq_is_in_nol()- check if given channel in nol list
1220  * @dfs: dfs handler
1221  * @freq: channel frequency.
1222  *
1223  * check if given channel in nol list.
1224  *
1225  * Return: true if channel in nol, false else
1226  */
1227 static bool dfs_freq_is_in_nol(struct wlan_dfs *dfs, uint32_t freq)
1228 {
1229 	struct dfs_nolelem *nol;
1230 
1231 	if (!dfs) {
1232 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,  "null dfs");
1233 		return false;
1234 	}
1235 
1236 	nol = dfs->dfs_nol;
1237 	while (nol) {
1238 		if (freq == nol->nol_freq) {
1239 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1240 					"%d is in nol", freq);
1241 			return true;
1242 		}
1243 		nol = nol->nol_next;
1244 	}
1245 
1246 	return false;
1247 }
1248 
1249 /**
1250  * dfs_apply_rules()- prepare channel list based on flags
1251  * @dfs: dfs handler
1252  * @flags: channel flags
1253  * @random_chan_list: ouput channel list
1254  * @random_chan_cnt: output channel count
1255  * @ch_list: input channel list
1256  * @ch_cnt: input channel count
1257  * @dfs_region: dfs region
1258  * @acs_info: acs channel range information
1259  *
1260  * prepare channel list based on flags
1261  *
1262  * Return: None
1263  */
1264 static void dfs_apply_rules(struct wlan_dfs *dfs,
1265 	uint32_t flags,
1266 	uint8_t *random_chan_list,
1267 	uint32_t *random_chan_cnt,
1268 	struct dfs_channel *ch_list,
1269 	uint32_t ch_cnt,
1270 	uint8_t dfs_region,
1271 	struct dfs_acs_info *acs_info)
1272 {
1273 	struct dfs_channel *chan;
1274 	uint16_t flag_no_weather = 0;
1275 	uint16_t flag_no_lower_5g = 0;
1276 	uint16_t flag_no_upper_5g = 0;
1277 	uint16_t flag_no_dfs_chan = 0;
1278 	uint16_t flag_no_2g_chan  = 0;
1279 	uint16_t flag_no_5g_chan  = 0;
1280 	int i;
1281 
1282 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags);
1283 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
1284 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1285 
1286 	flag_no_lower_5g = (dfs_region == DFS_MKK_REGION_VAL) ?
1287 		flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH : 0;
1288 
1289 	flag_no_upper_5g = (dfs_region == DFS_MKK_REGION_VAL) ?
1290 		flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH : 0;
1291 
1292 	flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH;
1293 	flag_no_2g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH;
1294 	flag_no_5g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH;
1295 
1296 	for (i = 0; i < ch_cnt; i++) {
1297 		chan = &ch_list[i];
1298 
1299 		if ((chan->dfs_ch_ieee == 0) ||
1300 				(chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) {
1301 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1302 					"invalid channel %d",
1303 					chan->dfs_ch_ieee);
1304 			continue;
1305 		}
1306 
1307 		if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) {
1308 			/* TODO : Skip all HT20 channels in the given mode */
1309 			if (chan->dfs_ch_ieee ==
1310 					dfs->dfs_curchan->dfs_ch_ieee) {
1311 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1312 						"skip %d current operating channel\n",
1313 						chan->dfs_ch_ieee);
1314 				continue;
1315 			}
1316 		}
1317 
1318 		if (acs_info && (acs_info->acs_mode == 1) &&
1319 		    ((chan->dfs_ch_ieee < acs_info->start_ch) ||
1320 		    (chan->dfs_ch_ieee > acs_info->end_ch))) {
1321 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1322 					"skip ch %d not in acs range (%d-%d)",
1323 				    chan->dfs_ch_ieee, acs_info->start_ch,
1324 				   acs_info->end_ch);
1325 			continue;
1326 
1327 		}
1328 
1329 		if (flag_no_2g_chan &&
1330 				chan->dfs_ch_ieee <= DFS_MAX_24GHZ_CHANNEL) {
1331 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1332 					"skip 2.4 GHz channel=%d",
1333 				    chan->dfs_ch_ieee);
1334 			continue;
1335 		}
1336 
1337 		if (flag_no_5g_chan &&
1338 				chan->dfs_ch_ieee > DFS_MAX_24GHZ_CHANNEL) {
1339 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1340 					"skip 5 GHz channel=%d",
1341 				    chan->dfs_ch_ieee);
1342 			continue;
1343 		}
1344 
1345 		if (flag_no_weather) {
1346 			if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) {
1347 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1348 						"skip weather channel=%d",
1349 						chan->dfs_ch_ieee);
1350 				continue;
1351 			}
1352 		}
1353 
1354 		if (flag_no_lower_5g &&
1355 		    DFS_IS_CHAN_JAPAN_INDOOR(chan->dfs_ch_ieee)) {
1356 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1357 					"skip indoor channel=%d",
1358 					chan->dfs_ch_ieee);
1359 			continue;
1360 		}
1361 
1362 		if (flag_no_upper_5g &&
1363 		    DFS_IS_CHAN_JAPAN_OUTDOOR(chan->dfs_ch_ieee)) {
1364 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1365 					"skip outdoor channel=%d",
1366 				    chan->dfs_ch_ieee);
1367 			continue;
1368 		}
1369 
1370 		if (flag_no_dfs_chan &&
1371 		    (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) {
1372 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1373 					"skip dfs channel=%d",
1374 				    chan->dfs_ch_ieee);
1375 			continue;
1376 		}
1377 
1378 		if (dfs_freq_is_in_nol(dfs, chan->dfs_ch_freq)) {
1379 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1380 					"skip nol channel=%d",
1381 				    chan->dfs_ch_ieee);
1382 			continue;
1383 		}
1384 
1385 		random_chan_list[*random_chan_cnt] = chan->dfs_ch_ieee;
1386 		*random_chan_cnt += 1;
1387 	}
1388 }
1389 
1390 uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs,
1391 	struct dfs_channel *ch_list,
1392 	uint32_t ch_cnt,
1393 	uint32_t flags,
1394 	uint8_t *ch_wd,
1395 	struct dfs_channel *cur_chan,
1396 	uint8_t dfs_region,
1397 	struct dfs_acs_info *acs_info)
1398 {
1399 	int i = 0;
1400 	uint8_t final_cnt = 0;
1401 	uint8_t target_ch = 0;
1402 	uint8_t *random_chan_list = NULL;
1403 	uint32_t random_chan_cnt = 0;
1404 	uint16_t flag_no_weather = 0;
1405 	uint8_t *leakage_adjusted_lst;
1406 	uint8_t final_lst[NUM_CHANNELS] = {0};
1407 
1408 	if (!ch_list || !ch_cnt) {
1409 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1410 				"Invalid params %pK, ch_cnt=%d",
1411 				ch_list, ch_cnt);
1412 		return 0;
1413 	}
1414 
1415 	if (*ch_wd < DFS_CH_WIDTH_20MHZ || *ch_wd > DFS_CH_WIDTH_80P80MHZ) {
1416 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1417 				"Invalid ch_wd %d", *ch_wd);
1418 		return 0;
1419 	}
1420 
1421 	random_chan_list = qdf_mem_malloc(ch_cnt * sizeof(*random_chan_list));
1422 	if (!random_chan_list) {
1423 		dfs_alert(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1424 				"Memory allocation failed");
1425 		return 0;
1426 	}
1427 
1428 	if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH)
1429 		dfs_remove_cur_ch_from_list(ch_list, &ch_cnt, ch_wd, cur_chan);
1430 
1431 	dfs_apply_rules(dfs, flags, random_chan_list, &random_chan_cnt,
1432 		    ch_list, ch_cnt, dfs_region, acs_info);
1433 
1434 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
1435 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1436 
1437 	/* list adjusted after leakage has been marked */
1438 	leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt);
1439 	if (!leakage_adjusted_lst) {
1440 		dfs_alert(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1441 				"Memory allocation failed");
1442 		qdf_mem_free(random_chan_list);
1443 		return 0;
1444 	}
1445 
1446 	do {
1447 		qdf_mem_copy(leakage_adjusted_lst, random_chan_list,
1448 			     random_chan_cnt);
1449 		if (QDF_IS_STATUS_ERROR(dfs_mark_leaking_ch(dfs, *ch_wd,
1450 				random_chan_cnt,
1451 				leakage_adjusted_lst))) {
1452 			qdf_mem_free(random_chan_list);
1453 			qdf_mem_free(leakage_adjusted_lst);
1454 			return 0;
1455 		}
1456 
1457 		if (*ch_wd == DFS_CH_WIDTH_20MHZ) {
1458 			/*
1459 			 * PASS: 3 - from leakage_adjusted_lst, prepare valid
1460 			 * ch list and use random number from that
1461 			 */
1462 			for (i = 0; i < random_chan_cnt; i++) {
1463 				if (leakage_adjusted_lst[i] == 0)
1464 					continue;
1465 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1466 					  "dfs: Channel=%d added to available list",
1467 					  leakage_adjusted_lst[i]);
1468 				final_lst[final_cnt] = leakage_adjusted_lst[i];
1469 				final_cnt++;
1470 			}
1471 			target_ch = dfs_get_rand_from_lst(
1472 				dfs, final_lst, final_cnt);
1473 			break;
1474 		}
1475 
1476 		target_ch = dfs_find_ch_with_fallback(dfs, ch_wd,
1477 				&cur_chan->dfs_ch_vhtop_ch_freq_seg2,
1478 				leakage_adjusted_lst,
1479 				random_chan_cnt);
1480 
1481 		/*
1482 		 * When flag_no_weather is set, avoid usage of Adjacent
1483 		 * weather radar channel in HT40 mode as extension channel
1484 		 * will be on 5600.
1485 		 */
1486 		if (flag_no_weather &&
1487 				(target_ch ==
1488 				 DFS_ADJACENT_WEATHER_RADAR_CHANNEL_NUM) &&
1489 				(*ch_wd == DFS_CH_WIDTH_40MHZ)) {
1490 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1491 					"skip weather adjacent ch=%d\n",
1492 					target_ch);
1493 			continue;
1494 		}
1495 
1496 		if (target_ch)
1497 			break;
1498 	} while (true);
1499 
1500 	qdf_mem_free(random_chan_list);
1501 	qdf_mem_free(leakage_adjusted_lst);
1502 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_ch = %d", target_ch);
1503 
1504 	return target_ch;
1505 }
1506