xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c (revision 11f5a63a6cbdda84849a730de22f0a71e635d58c)
1 /*
2  * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "../dfs.h"
20 #include "../dfs_random_chan_sel.h"
21 #include <qdf_mc_timer.h>
22 #include <wlan_utility.h>
23 
24 #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION
25 /*
26  * TODO: At present SAP Channel leakage matrix for ch 144
27  * is not available from system's team. So to play it safe
28  * and avoid crash if channel 144 is request, in following
29  * matix channel 144 is added such that it will cause code
30  * to avoid selecting channel 144.
31  *
32  * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS
33  * PROVIDED BY SYSTEM'S TEAM.
34  */
35 
36 /* channel tx leakage table - ht80 */
37 struct dfs_matrix_tx_leak_info ht80_chan[] = {
38 	{52, 5260,
39 	 {{36, 5180, 148}, {40, 5200, 199},
40 	  {44, 5520, 193}, {48, 5240, 197},
41 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, 153},
42 	  {60, 5300, 137}, {64, 5320, 134},
43 	  {100, 5500, 358}, {104, 5520, 350},
44 	  {108, 5540, 404}, {112, 5560, 344},
45 	  {116, 5580, 424}, {120, 5600, 429},
46 	  {124, 5620, 437}, {128, 5640, 435},
47 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
48 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
49 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
50 	  } },
51 
52 
53 	{56, 5280,
54 	 {{36, 5180, 171}, {40, 5200, 178},
55 	  {44, 5220, 171}, {48, 5240, 178},
56 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
57 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, 280},
58 	  {100, 5500, 351}, {104, 5520, 376},
59 	  {108, 5540, 362}, {112, 5560, 362},
60 	  {116, 5580, 403}, {120, 5600, 397},
61 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
62 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
63 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
64 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
65 	  } },
66 
67 	{60,5300,
68 	 {{36, 5180, 156}, {40, 5200, 146},
69 	  {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN},
70 	  {52, 5260, 180}, {56, 5280, DFS_TX_LEAKAGE_MIN},
71 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
72 	  {100, 5500, 376}, {104, 5520, 360},
73 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
74 	  {116, 5580, 395}, {120, 5600, 399},
75 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
76 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
77 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
78 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
79 	  } },
80 
81 	{64, 5320,
82 	 {{36, 5180,  217}, {40, 5200, 221},
83 	  {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN},
84 	  {52, 5260, 176}, {56, 5280, 176},
85 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
86 	  {100, 5500, 384}, {104, 5520, 390},
87 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
88 	  {116, 5580, 375}, {120, 5600, 374},
89 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
90 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
91 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
92 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
93 	  } },
94 
95 	{100, 5500,
96 	 {{36, 5180, 357}, {40, 5200, 326},
97 	  {44, 5220, 321}, {48, 5240, 326},
98 	  {52, 5260, 378}, {56, 5280, 396},
99 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
100 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
101 	  {108, 5540, 196}, {112, 5560, 116},
102 	  {116, 5580, 166}, {120, 5600, DFS_TX_LEAKAGE_MIN},
103 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
104 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
105 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
106 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
107 	  } },
108 
109 	{104, 5520,
110 	 {{36, 5180,  325}, {40, 5200, 325},
111 	  {44, 5220, 305}, {48, 5240, 352},
112 	  {52, 5260, 411}, {56, 5280, 411},
113 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
114 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
115 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 460},
116 	  {116, 5580, 198}, {120, 5600, DFS_TX_LEAKAGE_MIN},
117 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
118 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
119 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
120 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
121 	  } },
122 
123 	{108, 5540,
124 	 {{36,5180,  304}, {40, 5200, 332},
125 	  {44, 5220, 310}, {48, 5240, 335},
126 	  {52, 5260, 431}, {56, 5280, 391},
127 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
128 	  {100, 5500, 280}, {104, 5520, DFS_TX_LEAKAGE_MIN},
129 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
130 	  {116, 5580, 185}, {120, 5600, DFS_TX_LEAKAGE_MIN},
131 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
132 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
133 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
134 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
135 	  } },
136 
137 	{112,5560,
138 	 {{36, 5180, 327}, {40, 5200, 335},
139 	  {44, 5220, 331}, {48, 5240, 345},
140 	  {52, 5260, 367}, {56, 5280, 401},
141 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
142 	  {100, 5500, 131}, {104, 5520, 132},
143 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
144 	  {116, 5580, 189}, {120, 5600, DFS_TX_LEAKAGE_MIN},
145 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
146 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
147 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
148 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
149 	  } },
150 
151 	{116, 5580,
152 	 {{36, 5180, 384}, {40, 5200, 372},
153 	  {44, 5220, 389}, {48, 5240, 396},
154 	  {52, 5260, 348}, {56, 5280, 336},
155 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
156 	  {100, 5500, 172}, {104, 5520, 169},
157 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
158 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
159 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
160 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
161 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
162 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
163 	  } },
164 
165 	{120, 5600,
166 	 {{36, 5180, 395}, {40, 5200, 419},
167 	  {44, 5220, 439}, {48, 5240, 407},
168 	  {52, 5260, 321}, {56, 5280, 334},
169 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
170 	  {100, 5500, 134}, {104, 5520, 186},
171 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
172 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
173 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 159},
174 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
175 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
176 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
177 	  } },
178 
179 	{124, 5620,
180 	 {{36, 5180, 469}, {40, 5200, 433},
181 	  {44, 5220, 434}, {48, 5240, 435},
182 	  {52, 5260, 332}, {56, 5280, 345},
183 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
184 	  {100, 5500, 146}, {104, 5520, 177},
185 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
186 	  {116, 5580, 350}, {120, 5600, DFS_TX_LEAKAGE_MIN},
187 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 138},
188 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
189 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
190 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
191 	  } },
192 
193 	{128, 5640,
194 	 {{36, 5180, 408}, {40, 5200, 434},
195 	  {44, 5220, 449}, {48, 5240, 444},
196 	  {52, 5260, 341}, {56, 5280, 374},
197 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
198 	  {100, 5500, 205}, {104, 5520, 208},
199 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
200 	  {116, 5580, 142}, {120, 5600, DFS_TX_LEAKAGE_MIN},
201 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
202 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
203 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
204 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
205 	  } },
206 
207 	{132, 5660,
208 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
209 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
210 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
211 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
212 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
213 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
214 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
215 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
216 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
217 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
218 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
219 	  } },
220 
221 	{136, 5680,
222 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
223 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
224 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
225 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
226 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
227 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
228 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
229 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
230 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
231 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
232 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
233 	  } },
234 
235 	{140, 5700,
236 	 {{36, 5180,  DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
237 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
238 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
239 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
240 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
241 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
242 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
243 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
244 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
245 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
246 	  } },
247 
248 	{144, 5720,
249 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
250 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
251 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
252 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
253 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
254 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
255 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
256 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
257 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
258 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
259 	  } },
260 };
261 
262 /* channel tx leakage table - ht40 */
263 struct dfs_matrix_tx_leak_info ht40_chan[] = {
264 	{52, 5260,
265 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
266 	  {44, 5220, 230}, {48, 5240, 230},
267 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
268 	  {60, 5300, DFS_TX_LEAKAGE_AUTO_MIN}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN},
269 	  {100, 5500, 625}, {104, 5520, 323},
270 	  {108, 5540, 646}, {112, 5560, 646},
271 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
272 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
273 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
274 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
275 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
276 	  } },
277 
278 	{56, 5280,
279 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
280 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
281 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
282 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
283 	  {100, 5500, 611}, {104, 5520, 611},
284 	  {108, 5540, 617}, {112, 5560, 617},
285 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
286 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
287 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
288 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
289 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
290 	  } },
291 
292 	{60, 5300,
293 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
294 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
295 	  {52, 5260, 190}, {56, 5280, 190},
296 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
297 	  {100, 5500, 608}, {104, 5520, 608},
298 	  {108, 5540, 623}, {112, 5560, 623},
299 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
300 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
301 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
302 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
303 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
304 	  } },
305 
306 	{64, 5320,
307 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
308 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
309 	  {52, 5260, 295}, {56, 5280, 295},
310 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
311 	  {100, 5500, 594}, {104, 5520, 594},
312 	  {108, 5540, 625}, {112, 5560, 625},
313 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
314 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
315 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
316 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
317 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
318 	  } },
319 
320 	{100, 5500,
321 	 {{36, 5180, 618}, {40, 5200, 618},
322 	  {44, 5220, 604}, {48, 5240, 604},
323 	  {52, 5260, 596}, {56, 5280, 596},
324 	  {60, 5300, 584}, {64, 5320, 584},
325 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
326 	  {108, 5540, 299}, {112, 5560, 299},
327 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
328 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
329 	  {132, 5660, 538}, {136,5680, 538},
330 	  {140, 5700, 598},
331 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
332 	  } },
333 
334 	{104, 5520,
335 	 {{36, 5180, 636}, {40, 5200, 636},
336 	  {44, 5220, 601}, {48, 5240, 601},
337 	  {52, 5260, 616}, {56, 5280, 616},
338 	  {60, 5300, 584}, {64, 5320, 584},
339 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
340 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
341 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
342 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
343 	  {132, 5660, 553}, {136, 5680, 553},
344 	  {140, 5700, 568},
345 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
346 	  } },
347 
348 	{108, 5540,
349 	 {{36, 5180, 600}, {40, 5200, 600},
350 	  {44, 5220, 627}, {48, 5240, 627},
351 	  {52, 5260, 611}, {56, 5280, 611},
352 	  {60, 5300, 611}, {64, 5320, 611},
353 	  {100, 5500, 214}, {104, 5520, 214},
354 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
355 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
356 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
357 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
358 	  {140, 5700, 534},
359 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
360 	  } },
361 
362 	{112, 5560,
363 	 {{36, 5180, 645}, {40, 5200, 645},
364 	  {44, 5220, 641}, {48, 5240, 641},
365 	  {52, 5260, 618}, {56, 5280, 618},
366 	  {60, 5300, 612}, {64, 5320, 612},
367 	  {100, 5500, 293}, {104, 5520, 293},
368 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
369 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
370 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
371 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
372 	  {140, 5700, 521},
373 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
374 	  } },
375 
376 	{116, 5580,
377 	 {{36, 5180, 661}, {40, 5200, 661},
378 	  {44, 5220, 624}, {48, 5240, 624},
379 	  {52, 5260, 634}, {56, 5280, 634},
380 	  {60, 5300, 611}, {64, 5320, 611},
381 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
382 	  {108, 5540, 217}, {112, 5560, 217},
383 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
384 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
385 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
386 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
387 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
388 	  } },
389 
390 	{120, 5600,
391 	 {{36, 5180, 667}, {40, 5200, 667},
392 	  {44, 5220, 645}, {48, 5240, 645},
393 	  {52, 5260, 633}, {56, 5280, 633},
394 	  {60, 5300, 619}, {64, 5320, 619},
395 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
396 	  {108, 5540, 291}, {112, 5560, 291},
397 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
398 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
399 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
400 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
401 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
402 	  } },
403 
404 	{124, 5620,
405 	 {{36, 5180,  676}, {40, 5200, 676},
406 	  {44, 5220, 668}, {48, 5240, 668},
407 	  {52, 5260, 595}, {56, 5280, 595},
408 	  {60, 5300, 622}, {64, 5320, 622},
409 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
410 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
411 	  {116, 5580, 225}, {120, 5600, 225},
412 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
413 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
414 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
415 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
416 	  } },
417 
418 	{128, 5640,
419 	 {{36, 5180, 678}, {40, 5200, 678},
420 	  {44, 5220, 664}, {48, 5240, 664},
421 	  {52, 5260, 651}, {56, 5280, 651},
422 	  {60, 5300, 643}, {64, 5320, 643},
423 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
424 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
425 	  {116, 5580, 293}, {120, 5600, 293},
426 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
427 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
428 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
429 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
430 	  } },
431 
432 	{132, 5660,
433 	 {{36, 5180, 689}, {40, 5200, 689},
434 	  {44, 5220, 669}, {48, 5240, 669},
435 	  {52, 5260, 662}, {56, 5280, 662},
436 	  {60, 5300, 609}, {64, 5320, 609},
437 	  {100, 5500, 538}, {104, 5520, 538},
438 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
439 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
440 	  {124, 5620, 247}, {128, 5640, 247},
441 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
442 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
443 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
444 	  } },
445 
446 	{136, 5680,
447 	 {{36, 5180, 703}, {40, 5200, 703},
448 	  {44, 5220, 688}, {48, 5240, DFS_TX_LEAKAGE_MIN},
449 	  {52, 5260, 671}, {56, 5280, 671},
450 	  {60, 5300, 658}, {64, 5320, 658},
451 	  {100, 5500, 504}, {104, 5520, 504},
452 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
453 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
454 	  {124, 5620, 289}, {128, 5640, 289},
455 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
456 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
457 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
458 	  } },
459 
460 	{140, 5700,
461 	 {{36, 5180, 695}, {40, 5200, 695},
462 	  {44, 5220, 684}, {48, 5240, 684},
463 	  {52, 5260, 664}, {56, 5280, 664},
464 	  {60, 5300, 658}, {64, 5320, 658},
465 	  {100, 5500, 601}, {104, 5520, 601},
466 	  {108, 5540, 545}, {112, 5560, 545},
467 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
468 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
469 	  {132, 5660, 262}, {136, 5680, 262},
470 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
471 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
472 	  } },
473 
474 	{144, 5720,
475 	 {{36, 5180, 695}, {40, 5200, 695},
476 	  {44, 5220, 684}, {48, 5240, 684},
477 	  {52, 5260, 664}, {56, 5280, 664},
478 	  {60, 5300, 658}, {64, 5320, 658},
479 	  {100, 5500, 601}, {104, 5520, 601},
480 	  {108, 5540, 545}, {112, 5560, 545},
481 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
482 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
483 	  {132, 5660, 262}, {136, 5680, 262},
484 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
485 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
486 	  } },
487 };
488 
489 /* channel tx leakage table - ht20 */
490 struct dfs_matrix_tx_leak_info ht20_chan[] = {
491 	{52, 5260,
492 	 {{36, 5180,DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, 286},
493 	  {44, 5220, 225}, {48,5240, 121},
494 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
495 	  {60, 5300, 300}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN},
496 	  {100, 5500, 637}, {104, 5520, DFS_TX_LEAKAGE_MAX},
497 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
498 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
499 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
500 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
501 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
502 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
503 	  } },
504 
505 	{56, 5280,
506 	 {{36, 5180, 468}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
507 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, 206},
508 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
509 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
510 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
511 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
512 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
513 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
514 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
515 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
516 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
517 	  } },
518 
519 	{60, 5300,
520 	 {{36, 5180, 507}, {40, 5200, 440},
521 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48,5240, 313},
522 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
523 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
524 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
525 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
526 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
527 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
528 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
529 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
530 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
531 	  } },
532 
533 	{64, 5320 ,
534 	 {{36, 5180, 516}, {40, 5200, 520},
535 	  {44, 5220, 506}, {48, 5240,DFS_TX_LEAKAGE_AUTO_MIN},
536 	  {52, 5260, 301}, {56, 5280, 258},
537 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
538 	  {100, 5500, 620}, {104, 5520, 617},
539 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
540 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
541 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
542 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
543 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
544 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
545 	  } },
546 
547 	{100, 5500,
548 	 {{36, 5180, 616}, {40, 5200, 601},
549 	  {44, 5220, 604}, {48, 5240, 589},
550 	  {52, 5260, 612}, {56, 5280, 592},
551 	  {60, 5300, 590}, {64, 5320, 582},
552 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, 131},
553 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
554 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, 522},
555 	  {124, 5620, 571}, {128, 5640, 589},
556 	  {132, 5660, 593}, {136, 5680, 598},
557 	  {140, 5700, 594},
558 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
559 	  } },
560 
561 	{104, 5520,
562 	 {{36, 5180, 622}, {40, 5200, 624},
563 	  {44, 5220, 618}, {48, 5240, 610},
564 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
565 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
566 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
567 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 463},
568 	  {116, 5580, 483}, {120, 5600, 503},
569 	  {124, 5620, 523}, {128, 5640, 565},
570 	  {132, 5660, 570}, {136, 5680, 588},
571 	  {140, 5700, 585},
572 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
573 	  } },
574 
575 	{108, 5540,
576 	 {{36, 5180, 620}, {40, 5200, 638},
577 	  {44, 5220, 611}, {48, 5240, 614},
578 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
579 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
580 	  {100, 5500, 477}, {104, 5520, DFS_TX_LEAKAGE_MIN},
581 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
582 	  {116, 5580, 477}, {120, 5600, 497},
583 	  {124, 5620, 517}, {128, 5640, 537},
584 	  {132, 5660, 557}, {136, 5680, 577},
585 	  {140, 5700, 603},
586 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
587 	  } },
588 
589 	{112, 5560,
590 	 {{36, 5180, 636}, {40, 5200, 623},
591 	  {44, 5220, 638}, {48, 5240, 628},
592 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
593 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, 606},
594 	  {100, 5500, 501}, {104, 5520, 481},
595 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
596 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, 481},
597 	  {124, 5620, 501}, {128, 5640, 421},
598 	  {132, 5660, 541}, {136, 5680, 561},
599 	  {140, 5700, 583},
600 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
601 	  } },
602 
603 	{116, 5580,
604 	 {{36, 5180, 646}, {40, 5200, 648},
605 	  {44, 5220, 633}, {48, 5240, 634},
606 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
607 	  {60, 5300, 615}, {64, 5320, 594},
608 	  {100, 5500, 575}, {104, 5520, 554},
609 	  {108, 5540, 534}, {112, 5560, DFS_TX_LEAKAGE_MIN},
610 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
611 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
612 	  {132, 5660, 534}, {136, 5680, 554},
613 	  {140, 5700, 574},
614 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
615 	  } },
616 
617 	{120, 5600,
618 	 {{36, 5180, 643}, {40, 5200, 649},
619 	  {44, 5220, 654}, {48, 5240, 629},
620 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, 621},
621 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
622 	  {100, 5500, 565}, {104, 5520, 545},
623 	  {108, 5540, 525}, {112, 5560, 505},
624 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
625 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 505},
626 	  {132, 5660, 525}, {136, 5680, 545},
627 	  {140, 5700, 565},
628 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
629 	  } },
630 
631 	{124, 5620,
632 	 {{36, 5180, 638}, {40, 5200, 657},
633 	  {44, 5220, 663}, {48, 5240, 649},
634 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
635 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
636 	  {100, 5500, 581}, {104, 5520, 561},
637 	  {108, 5540, 541}, {112, 5560, 521},
638 	  {116, 5580, 499}, {120, 5600, DFS_TX_LEAKAGE_MIN},
639 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
640 	  {132, 5660, 499}, {136, 5680, 519},
641 	  {140, 5700, 539},
642 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
643 	  } },
644 
645 	{128, 5640,
646 	 {{36, 5180, 651}, {40, 5200, 651},
647 	  {44, 5220, 674}, {48, 5240, 640},
648 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
649 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
650 	  {100, 5500, 603}, {104, 5520, 560},
651 	  {108, 5540, 540}, {112, 5560, 520},
652 	  {116, 5580, 499}, {120, 5600, 479},
653 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
654 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, 479},
655 	  {140, 5700, 499},
656 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
657 	  } },
658 
659 	{132, 5660,
660 	 {{36, 5180, 643}, {40, 5200, 668},
661 	  {44, 5220, 651}, {48, 5240, 657},
662 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
663 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
664 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, 602},
665 	  {108, 5540, 578}, {112,5560, 570},
666 	  {116, 5580, 550}, {120, 5600, 530},
667 	  {124, 5620, 510}, {128, 5640, DFS_TX_LEAKAGE_MIN},
668 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
669 	  {140, 5700, 490},
670 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
671 	  } },
672 
673 	{136,5680,
674 	 {{36, 5180, 654}, {40, 5200, 667},
675 	  {44, 5220, 666}, {48, 5240, 642},
676 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
677 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
678 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
679 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 596},
680 	  {116, 5580, 555}, {120, 5600, 535},
681 	  {124, 5620, 515}, {128, 5640, 495},
682 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
683 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
684 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
685 	  } },
686 
687 	{140,5700,
688 	 {{36, 5180, 679}, {40, 5200, 673},
689 	  {44, 5220, 667}, {48, 5240, 656},
690 	  {52, 5260, 634}, {56, 5280, 663},
691 	  {60, 5300, 662}, {64, 5320, 660},
692 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
693 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590},
694 	  {116, 5580, 573}, {120, 5600, 553},
695 	  {124, 5620, 533}, {128, 5640, 513},
696 	  {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN},
697 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
698 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
699 	  } },
700 
701 	{144,5720,
702 	 {{36, 5180, 679}, {40, 5200, 673},
703 	  {44, 5220, 667}, {48, 5240, 656},
704 	  {52, 5260, 634}, {56, 5280, 663},
705 	  {60, 5300, 662}, {64, 5320, 660},
706 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
707 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590},
708 	  {116, 5580, 573}, {120, 5600, 553},
709 	  {124, 5620, 533}, {128, 5640, 513},
710 	  {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN},
711 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
712 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
713 	  } },
714 };
715 
716 /*
717  * dfs_find_target_channel_in_channel_matrix() - finds the leakage matrix
718  * @ch_width: target channel width
719  * @NOL_channel: the NOL channel whose leakage matrix is required
720  * @pTarget_chnl_mtrx: pointer to target channel matrix returned.
721  *
722  * This function gives the leakage matrix for given NOL channel and ch_width
723  *
724  * Return: TRUE or FALSE
725  */
726 #ifdef CONFIG_CHAN_NUM_API
727 static bool
728 dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width,
729 				uint8_t NOL_channel,
730 				struct dfs_tx_leak_info **pTarget_chnl_mtrx)
731 {
732 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
733 	struct dfs_matrix_tx_leak_info *pchan_matrix = NULL;
734 	uint32_t nchan_matrix;
735 	int i = 0;
736 
737 	switch (ch_width) {
738 	case CH_WIDTH_20MHZ:
739 		/* HT20 */
740 		pchan_matrix = ht20_chan;
741 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
742 		break;
743 	case CH_WIDTH_40MHZ:
744 		/* HT40 */
745 		pchan_matrix = ht40_chan;
746 		nchan_matrix = QDF_ARRAY_SIZE(ht40_chan);
747 		break;
748 	case CH_WIDTH_80MHZ:
749 		/* HT80 */
750 		pchan_matrix = ht80_chan;
751 		nchan_matrix = QDF_ARRAY_SIZE(ht80_chan);
752 		break;
753 	default:
754 		/* handle exception and fall back to HT20 table */
755 		pchan_matrix = ht20_chan;
756 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
757 		break;
758 	}
759 
760 	for (i = 0; i < nchan_matrix; i++) {
761 		/* find the SAP channel to map the leakage matrix */
762 		if (NOL_channel == pchan_matrix[i].channel) {
763 			target_chan_matrix = pchan_matrix[i].chan_matrix;
764 			break;
765 		}
766 	}
767 
768 	if (!target_chan_matrix) {
769 		return false;
770 	} else {
771 		*pTarget_chnl_mtrx = target_chan_matrix;
772 		return true;
773 	}
774 }
775 #endif
776 
777 /*
778  * dfs_find_target_channel_in_channel_matrix_for_freq() - finds the leakage
779  * matrix.
780  * @chan_width: target channel width
781  * @nol_channel: the NOL channel frequency whose leakage matrix is required
782  * @pTarget_chnl_mtrx: pointer to target channel matrix returned.
783  *
784  * This function gives the leakage matrix for given NOL channel and ch_width
785  *
786  * Return: TRUE or FALSE
787  */
788 #ifdef CONFIG_CHAN_FREQ_API
789 static bool
790 dfs_find_target_channel_in_channel_matrix_for_freq(enum phy_ch_width chan_width,
791 						   uint16_t nol_freq,
792 						   struct dfs_tx_leak_info
793 						   **pTarget_chnl_mtrx)
794 {
795 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
796 	struct dfs_matrix_tx_leak_info *pchan_matrix = NULL;
797 	uint32_t nchan_matrix;
798 	int i = 0;
799 
800 	switch (chan_width) {
801 	case CH_WIDTH_20MHZ:
802 		/* HT20 */
803 		pchan_matrix = ht20_chan;
804 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
805 		break;
806 	case CH_WIDTH_40MHZ:
807 		/* HT40 */
808 		pchan_matrix = ht40_chan;
809 		nchan_matrix = QDF_ARRAY_SIZE(ht40_chan);
810 		break;
811 	case CH_WIDTH_80MHZ:
812 		/* HT80 */
813 		pchan_matrix = ht80_chan;
814 		nchan_matrix = QDF_ARRAY_SIZE(ht80_chan);
815 		break;
816 	default:
817 		/* handle exception and fall back to HT20 table */
818 		pchan_matrix = ht20_chan;
819 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
820 		break;
821 	}
822 
823 	for (i = 0; i < nchan_matrix; i++) {
824 		/* find the SAP channel to map the leakage matrix */
825 		if (nol_freq == pchan_matrix[i].channel_freq) {
826 			target_chan_matrix = pchan_matrix[i].chan_matrix;
827 			break;
828 		}
829 	}
830 
831 	if (!target_chan_matrix) {
832 		return false;
833 	} else {
834 		*pTarget_chnl_mtrx = target_chan_matrix;
835 		return true;
836 	}
837 }
838 #endif
839 
840 #ifdef CONFIG_CHAN_NUM_API
841 QDF_STATUS
842 dfs_mark_leaking_ch(struct wlan_dfs *dfs,
843 		enum phy_ch_width ch_width,
844 		uint8_t temp_ch_lst_sz,
845 		uint8_t *temp_ch_lst)
846 {
847 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
848 	uint32_t         num_channel = (CHAN_ENUM_5720 - CHAN_ENUM_5180) + 1;
849 	uint32_t         j = 0;
850 	uint32_t         k = 0;
851 	uint8_t          dfs_nol_channel;
852 	struct dfs_nolelem *nol;
853 
854 	nol = dfs->dfs_nol;
855 	while (nol) {
856 		dfs_nol_channel = wlan_freq_to_chan(nol->nol_freq);
857 		if (false == dfs_find_target_channel_in_channel_matrix(
858 					ch_width, dfs_nol_channel,
859 					&target_chan_matrix)) {
860 			/*
861 			 * should never happen, we should always find a table
862 			 * here, if we don't, need a fix here!
863 			 */
864 			dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
865 				"Couldn't find target channel matrix!");
866 			QDF_ASSERT(0);
867 			return QDF_STATUS_E_FAILURE;
868 		}
869 		/*
870 		 * following is based on assumption that both temp_ch_lst
871 		 * and target channel matrix are in increasing order of
872 		 * ch_id
873 		 */
874 		for (j = 0, k = 0; j < temp_ch_lst_sz && k < num_channel;) {
875 			if (temp_ch_lst[j] == 0) {
876 				j++;
877 				continue;
878 			}
879 			if (target_chan_matrix[k].leak_chan != temp_ch_lst[j]) {
880 				k++;
881 				continue;
882 			}
883 			/*
884 			 * check leakage from candidate channel
885 			 * to NOL channel
886 			 */
887 			if (target_chan_matrix[k].leak_lvl <=
888 				dfs->tx_leakage_threshold) {
889 				/*
890 				 * candidate channel will have
891 				 * bad leakage in NOL channel,
892 				 * remove from temp list
893 				 */
894 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
895 					"dfs: channel: %d will have bad leakage due to channel: %d\n",
896 					dfs_nol_channel, temp_ch_lst[j]);
897 				temp_ch_lst[j] = 0;
898 			}
899 			j++;
900 			k++;
901 		}
902 		nol = nol->nol_next;
903 	} /* end of loop that selects each NOL */
904 
905 	return QDF_STATUS_SUCCESS;
906 }
907 #endif
908 
909 #ifdef CONFIG_CHAN_FREQ_API
910 #define END_CHAN_INDEX CHAN_ENUM_5720
911 #define START_CHAN_INDEX CHAN_ENUM_5180
912 QDF_STATUS
913 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs,
914 			     enum phy_ch_width ch_width,
915 			     uint8_t temp_chan_lst_sz,
916 			     uint16_t *temp_freq_lst)
917 {
918 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
919 	uint32_t         num_channel = (END_CHAN_INDEX - START_CHAN_INDEX) + 1;
920 	uint32_t         j = 0;
921 	uint32_t         k = 0;
922 	struct dfs_nolelem *nol;
923 
924 	nol = dfs->dfs_nol;
925 	while (nol) {
926 		if (false == dfs_find_target_channel_in_channel_matrix_for_freq(
927 					ch_width, nol->nol_freq,
928 					&target_chan_matrix)) {
929 			/*
930 			 * should never happen, we should always find a table
931 			 * here, if we don't, need a fix here!
932 			 */
933 			dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
934 				"Couldn't find target channel matrix!");
935 			QDF_ASSERT(0);
936 			return QDF_STATUS_E_FAILURE;
937 		}
938 		/*
939 		 * following is based on assumption that both temp_freq_lst
940 		 * and target channel matrix are in increasing order of
941 		 * ch_id
942 		 */
943 		for (j = 0, k = 0; j < temp_chan_lst_sz && k < num_channel;) {
944 			if (temp_freq_lst[j] == 0) {
945 				j++;
946 				continue;
947 			}
948 			if (target_chan_matrix[k].leak_chan_freq !=
949 			    temp_freq_lst[j]) {
950 				k++;
951 				continue;
952 			}
953 			/*
954 			 * check leakage from candidate channel
955 			 * to NOL channel
956 			 */
957 			if (target_chan_matrix[k].leak_lvl <=
958 				dfs->tx_leakage_threshold) {
959 				/*
960 				 * candidate channel will have
961 				 * bad leakage in NOL channel,
962 				 * remove from temp list
963 				 */
964 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
965 					"dfs: channel: %d will have bad leakage due to channel: %d\n",
966 					nol->nol_freq, temp_freq_lst[j]);
967 				temp_freq_lst[j] = 0;
968 			}
969 			j++;
970 			k++;
971 		}
972 		nol = nol->nol_next;
973 	} /* end of loop that selects each NOL */
974 
975 	return QDF_STATUS_SUCCESS;
976 }
977 #endif
978 #else
979 #ifdef CONFIG_CHAN_NUM_API
980 QDF_STATUS
981 dfs_mark_leaking_ch(struct wlan_dfs *dfs,
982 		enum phy_ch_width ch_width,
983 		uint8_t temp_ch_lst_sz,
984 		uint8_t *temp_ch_lst)
985 {
986 	return QDF_STATUS_SUCCESS;
987 }
988 #endif
989 #ifdef CONFIG_CHAN_FREQ_API
990 QDF_STATUS
991 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs,
992 			     enum phy_ch_width ch_width,
993 			     uint8_t temp_chan_lst_sz,
994 			     uint16_t *temp_freq_lst)
995 {
996 	return QDF_STATUS_SUCCESS;
997 }
998 #endif
999 #endif
1000 
1001 /**
1002  * dfs_populate_80mhz_available_channels()- Populate channels for 80MHz using
1003  *                                          bitmap
1004  * @dfs: Pointer to DFS structure.
1005  * @bitmap: bitmap
1006  * @avail_freq_list: prepared channel list
1007  *
1008  * Prepare 80MHz channels from the bitmap.
1009  *
1010  * Return: channel count
1011  */
1012 #ifdef CONFIG_CHAN_NUM_API
1013 static uint8_t dfs_populate_80mhz_available_channels(
1014 		struct wlan_dfs *dfs,
1015 		struct chan_bonding_bitmap *bitmap,
1016 		uint8_t *avail_chnl)
1017 {
1018 	uint8_t i = 0;
1019 	uint8_t chnl_count = 0;
1020 	uint8_t start_chan = 0;
1021 
1022 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1023 		start_chan = bitmap->chan_bonding_set[i].start_chan;
1024 		if (bitmap->chan_bonding_set[i].chan_map ==
1025 			DFS_80MHZ_MASK) {
1026 			avail_chnl[chnl_count++] = start_chan +
1027 				(DFS_NEXT_5GHZ_CHANNEL * 0);
1028 			avail_chnl[chnl_count++] = start_chan +
1029 				(DFS_NEXT_5GHZ_CHANNEL * 1);
1030 			avail_chnl[chnl_count++] = start_chan +
1031 				(DFS_NEXT_5GHZ_CHANNEL * 2);
1032 			avail_chnl[chnl_count++] = start_chan +
1033 				(DFS_NEXT_5GHZ_CHANNEL * 3);
1034 		}
1035 	}
1036 
1037 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1038 			"channel count %d", chnl_count);
1039 
1040 	return chnl_count;
1041 }
1042 #endif
1043 
1044 /*
1045  * dfs_populate_80mhz_available_channel_for_freq() - Populate 80MHZ channels
1046  * available for selection.
1047  * @dfs: Pointer to wlan_dfs.
1048  * @bitmap: Pointer to bonding channel bitmap.
1049  * @avail_freq_list: Pointer to frequency list of available channels.
1050  */
1051 #ifdef CONFIG_CHAN_FREQ_API
1052 static uint8_t dfs_populate_80mhz_available_channel_for_freq(
1053 		struct wlan_dfs *dfs,
1054 		struct chan_bonding_bitmap *bitmap,
1055 		uint16_t *avail_freq_list)
1056 {
1057 	uint8_t i = 0;
1058 	uint8_t chnl_count = 0;
1059 	uint16_t start_chan_freq = 0;
1060 
1061 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1062 		start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq;
1063 		if (bitmap->chan_bonding_set[i].chan_map ==
1064 			DFS_80MHZ_MASK) {
1065 			avail_freq_list[chnl_count++] = start_chan_freq +
1066 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0);
1067 			avail_freq_list[chnl_count++] = start_chan_freq +
1068 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1);
1069 			avail_freq_list[chnl_count++] = start_chan_freq +
1070 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2);
1071 			avail_freq_list[chnl_count++] = start_chan_freq +
1072 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3);
1073 		}
1074 	}
1075 
1076 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1077 		 "channel count %d", chnl_count);
1078 
1079 	return chnl_count;
1080 }
1081 #endif
1082 
1083 /**
1084  * dfs_populate_40mhz_available_channels()- Populate channels for 40MHz using
1085  *                                          bitmap
1086  * @dfs: Pointer to DFS structure.
1087  * @bitmap: bitmap
1088  * @avail_chnl: prepared channel list
1089  *
1090  * Prepare 40MHz channels from the bitmap.
1091  *
1092  * Return: channel count
1093  */
1094 #ifdef CONFIG_CHAN_NUM_API
1095 static uint8_t dfs_populate_40mhz_available_channels(
1096 		struct wlan_dfs *dfs,
1097 		struct chan_bonding_bitmap *bitmap,
1098 		uint8_t *avail_chnl)
1099 {
1100 	uint8_t i = 0;
1101 	uint8_t chnl_count = 0;
1102 	uint8_t start_chan = 0;
1103 
1104 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1105 		start_chan = bitmap->chan_bonding_set[i].start_chan;
1106 		if ((bitmap->chan_bonding_set[i].chan_map &
1107 			DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) {
1108 			avail_chnl[chnl_count++] = start_chan +
1109 				(DFS_NEXT_5GHZ_CHANNEL * 0);
1110 			avail_chnl[chnl_count++] = start_chan +
1111 				(DFS_NEXT_5GHZ_CHANNEL * 1);
1112 		}
1113 		if ((bitmap->chan_bonding_set[i].chan_map &
1114 			DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) {
1115 			avail_chnl[chnl_count++] = start_chan +
1116 				(DFS_NEXT_5GHZ_CHANNEL * 2);
1117 			avail_chnl[chnl_count++] = start_chan +
1118 				(DFS_NEXT_5GHZ_CHANNEL * 3);
1119 		}
1120 	}
1121 
1122 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1123 			"channel count %d", chnl_count);
1124 
1125 	return chnl_count;
1126 }
1127 #endif
1128 
1129 #ifdef CONFIG_CHAN_FREQ_API
1130 static uint8_t
1131 dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs *dfs,
1132 					      struct chan_bonding_bitmap *bmap,
1133 					      uint16_t *avail_freq_list)
1134 {
1135 	uint8_t i = 0;
1136 	uint8_t chnl_count = 0;
1137 	uint16_t start_chan_freq = 0;
1138 
1139 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1140 		start_chan_freq = bmap->chan_bonding_set[i].start_chan_freq;
1141 		if ((bmap->chan_bonding_set[i].chan_map &
1142 			DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) {
1143 			avail_freq_list[chnl_count++] = start_chan_freq +
1144 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0);
1145 			avail_freq_list[chnl_count++] = start_chan_freq +
1146 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1);
1147 		}
1148 		if ((bmap->chan_bonding_set[i].chan_map &
1149 			DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) {
1150 			avail_freq_list[chnl_count++] = start_chan_freq +
1151 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2);
1152 			avail_freq_list[chnl_count++] = start_chan_freq +
1153 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3);
1154 		}
1155 	}
1156 
1157 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1158 		 "channel count %d", chnl_count);
1159 
1160 	return chnl_count;
1161 }
1162 #endif
1163 
1164 /**
1165  * dfs_populate_available_channels()- Populate channels based on width and
1166  *                                    bitmap
1167  * @dfs: Pointer to DFS structure.
1168  * @bitmap: bitmap
1169  * @ch_width: channel width
1170  * @avail_chnl: prepared channel list
1171  *
1172  * Prepare channel list based on width and channel bitmap.
1173  *
1174  * Return: channel count
1175  */
1176 #ifdef CONFIG_CHAN_NUM_API
1177 static uint8_t dfs_populate_available_channels(
1178 		struct wlan_dfs *dfs,
1179 		struct chan_bonding_bitmap *bitmap,
1180 		uint8_t ch_width,
1181 		uint8_t *avail_chnl)
1182 {
1183 	switch (ch_width) {
1184 	case DFS_CH_WIDTH_160MHZ:
1185 	case DFS_CH_WIDTH_80P80MHZ:
1186 	case DFS_CH_WIDTH_80MHZ:
1187 		return dfs_populate_80mhz_available_channels(
1188 			dfs, bitmap, avail_chnl);
1189 	case DFS_CH_WIDTH_40MHZ:
1190 		return dfs_populate_40mhz_available_channels(
1191 			dfs, bitmap, avail_chnl);
1192 	default:
1193 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1194 				"Invalid ch_width %d", ch_width);
1195 		break;
1196 	}
1197 
1198 	return 0;
1199 }
1200 #endif
1201 
1202 /**
1203  * dfs_populate_available_channel_for_freq()- Populate channels based on width
1204  * and bitmap.
1205  * @dfs: Pointer to DFS structure.
1206  * @bitmap: bitmap
1207  * @chan_width: channel width
1208  * @avail_freq_list: prepared channel list
1209  *
1210  * Prepare channel list based on width and channel bitmap.
1211  *
1212  * Return: channel count
1213  */
1214 #ifdef CONFIG_CHAN_FREQ_API
1215 static uint8_t
1216 dfs_populate_available_channel_for_freq(struct wlan_dfs *dfs,
1217 					struct chan_bonding_bitmap *bitmap,
1218 					uint8_t chan_width,
1219 					uint16_t *freq_list)
1220 {
1221 	switch (chan_width) {
1222 	case DFS_CH_WIDTH_160MHZ:
1223 	case DFS_CH_WIDTH_80P80MHZ:
1224 	case DFS_CH_WIDTH_80MHZ:
1225 		return dfs_populate_80mhz_available_channel_for_freq(dfs,
1226 								     bitmap,
1227 								     freq_list);
1228 	case DFS_CH_WIDTH_40MHZ:
1229 		return dfs_populate_40mhz_available_channel_for_freq(dfs,
1230 								     bitmap,
1231 								     freq_list);
1232 	default:
1233 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1234 			"Invalid chan_width %d", chan_width);
1235 		break;
1236 	}
1237 
1238 	return 0;
1239 }
1240 #endif
1241 
1242 /**
1243  * dfs_get_rand_from_lst()- Get random channel from a given channel list
1244  * @dfs: Pointer to DFS structure.
1245  * @ch_lst: channel list
1246  * @num_ch: number of channels
1247  *
1248  * Get random channel from given channel list.
1249  *
1250  * Return: channel number
1251  */
1252 #ifdef CONFIG_CHAN_NUM_API
1253 static uint8_t dfs_get_rand_from_lst(
1254 		struct wlan_dfs *dfs,
1255 		uint8_t *ch_lst,
1256 		uint8_t num_ch)
1257 {
1258 	uint8_t i;
1259 	uint32_t rand_byte = 0;
1260 
1261 	if (!num_ch || !ch_lst) {
1262 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
1263 				"invalid param ch_lst %pK, num_ch = %d",
1264 				ch_lst, num_ch);
1265 		return 0;
1266 	}
1267 
1268 	get_random_bytes((uint8_t *)&rand_byte, 1);
1269 	i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_ch;
1270 
1271 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1272 			"random channel %d", ch_lst[i]);
1273 
1274 	return ch_lst[i];
1275 }
1276 #endif
1277 
1278 /**
1279  * dfs_get_rand_from_lst_for_freq()- Get random channel from a given channel
1280  * list.
1281  * @dfs: Pointer to DFS structure.
1282  * @freq_lst: Frequency list
1283  * @num_chan: number of channels
1284  *
1285  * Get random channel from given channel list.
1286  *
1287  * Return: channel frequency.
1288  */
1289 
1290 #ifdef CONFIG_CHAN_FREQ_API
1291 static uint16_t dfs_get_rand_from_lst_for_freq(struct wlan_dfs *dfs,
1292 					       uint16_t *freq_lst,
1293 					       uint8_t num_chan)
1294 {
1295 	uint8_t i;
1296 	uint32_t rand_byte = 0;
1297 
1298 	if (!num_chan || !freq_lst) {
1299 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
1300 			"invalid param freq_lst %pK, num_chan = %d",
1301 			freq_lst, num_chan);
1302 		return 0;
1303 	}
1304 
1305 	get_random_bytes((uint8_t *)&rand_byte, 1);
1306 	i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_chan;
1307 
1308 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1309 		 "random channel %d", freq_lst[i]);
1310 
1311 	return freq_lst[i];
1312 }
1313 #endif
1314 
1315 /**
1316  * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based
1317  * on given channel number
1318  * @dfs: Pointer to DFS structure.
1319  * @bitmap: bitmap
1320  * @channel: channel number
1321  *
1322  * Set channel bit in bitmap based on given channel number.
1323  *
1324  * Return: None
1325  */
1326 #ifdef CONFIG_CHAN_NUM_API
1327 static void dfs_random_channel_sel_set_bitmap(
1328 		struct wlan_dfs *dfs,
1329 		struct chan_bonding_bitmap *bitmap,
1330 		uint8_t channel)
1331 {
1332 	int i = 0;
1333 	int start_chan = 0;
1334 
1335 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1336 		start_chan = bitmap->chan_bonding_set[i].start_chan;
1337 		if (channel >= start_chan && channel <= start_chan + 12) {
1338 			bitmap->chan_bonding_set[i].chan_map |=
1339 			(1 << ((channel - start_chan) /
1340 			DFS_80_NUM_SUB_CHANNEL));
1341 			return;
1342 		}
1343 	}
1344 
1345 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1346 			"Channel=%d is not in the bitmap", channel);
1347 }
1348 #endif
1349 
1350 /**
1351  * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based
1352  * on given channel number
1353  * @dfs: Pointer to DFS structure.
1354  * @bitmap: bitmap
1355  * @chan_freq: channel frequency
1356  *
1357  * Set channel bit in bitmap based on given channel frequency.
1358  *
1359  * Return: None
1360  */
1361 #ifdef CONFIG_CHAN_FREQ_API
1362 #define FREQUENCY_BAND_LIMIT 60
1363 static void
1364 dfs_random_channel_sel_set_bitmap_for_freq(struct wlan_dfs *dfs,
1365 					   struct chan_bonding_bitmap *bitmap,
1366 					   uint16_t chan_freq)
1367 {
1368 	int i = 0;
1369 	int start_chan_freq = 0;
1370 
1371 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1372 		start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq;
1373 		if (chan_freq >= start_chan_freq &&
1374 		    chan_freq <= start_chan_freq +
1375 		    FREQUENCY_BAND_LIMIT) {
1376 			bitmap->chan_bonding_set[i].chan_map |=
1377 				(1 << ((chan_freq - start_chan_freq) /
1378 				       DFS_80_NUM_SUB_CHANNEL_FREQ));
1379 			return;
1380 		}
1381 	}
1382 
1383 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1384 		  "Frequency=%d is not in the bitmap", chan_freq);
1385 }
1386 #endif
1387 
1388 /**
1389  * dfs_find_ch_with_fallback()- find random channel
1390  * @dfs: Pointer to DFS structure.
1391  * @ch_wd: channel width
1392  * @center_freq_seg1: center frequency of secondary segment.
1393  * @ch_lst: list of available channels.
1394  * @num_ch: number of channels in the list.
1395  *
1396  * Find random channel based on given channel width and channel list,
1397  * fallback to lower width if requested channel width not available.
1398  *
1399  * Return: channel number
1400  */
1401 #ifdef CONFIG_CHAN_NUM_API
1402 static uint8_t dfs_find_ch_with_fallback(
1403 		struct wlan_dfs *dfs,
1404 		uint8_t *ch_wd,
1405 		uint8_t *center_freq_seg1,
1406 		uint8_t *ch_lst,
1407 		uint32_t num_ch)
1408 {
1409 	bool flag = false;
1410 	uint32_t rand_byte = 0;
1411 	struct  chan_bonding_bitmap ch_map = { { {0} } };
1412 	uint8_t count = 0, i, index = 0, final_cnt = 0, target_channel = 0;
1413 	uint8_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0;
1414 	uint8_t final_lst[DFS_MAX_NUM_CHAN] = {0};
1415 
1416 	/* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */
1417 	ch_map.chan_bonding_set[0].start_chan = 36;
1418 	ch_map.chan_bonding_set[1].start_chan = 52;
1419 	ch_map.chan_bonding_set[2].start_chan = 100;
1420 	ch_map.chan_bonding_set[3].start_chan = 116;
1421 	ch_map.chan_bonding_set[4].start_chan = 132;
1422 	ch_map.chan_bonding_set[5].start_chan = 149;
1423 
1424 	for (i = 0; i < num_ch; i++) {
1425 		dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1426 				"channel = %d added to bitmap", ch_lst[i]);
1427 		dfs_random_channel_sel_set_bitmap(dfs, &ch_map, ch_lst[i]);
1428 	}
1429 
1430 	/* populate available channel list from bitmap */
1431 	final_cnt = dfs_populate_available_channels(dfs, &ch_map,
1432 			*ch_wd, final_lst);
1433 
1434 	/* If no valid ch bonding found, fallback */
1435 	if (final_cnt == 0) {
1436 		if ((*ch_wd == DFS_CH_WIDTH_160MHZ) ||
1437 		    (*ch_wd == DFS_CH_WIDTH_80P80MHZ) ||
1438 		    (*ch_wd == DFS_CH_WIDTH_80MHZ)) {
1439 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1440 					"from [%d] to 40Mhz", *ch_wd);
1441 			*ch_wd = DFS_CH_WIDTH_40MHZ;
1442 		} else if (*ch_wd == DFS_CH_WIDTH_40MHZ) {
1443 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1444 					"from 40Mhz to 20MHz");
1445 			*ch_wd = DFS_CH_WIDTH_20MHZ;
1446 		}
1447 		return 0;
1448 	}
1449 
1450 	/* ch count should be > 8 to switch new channel in 160Mhz band */
1451 	if (((*ch_wd == DFS_CH_WIDTH_160MHZ) ||
1452 	     (*ch_wd == DFS_CH_WIDTH_80P80MHZ)) &&
1453 	     (final_cnt < DFS_MAX_20M_SUB_CH)) {
1454 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1455 				"from [%d] to 80Mhz", *ch_wd);
1456 		*ch_wd = DFS_CH_WIDTH_80MHZ;
1457 		return 0;
1458 	}
1459 
1460 	if (*ch_wd == DFS_CH_WIDTH_160MHZ) {
1461 		/*
1462 		 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128
1463 		 * and all the channels in these blocks are continuous
1464 		 * and separated by 4Mhz.
1465 		 */
1466 		for (i = 1; ((i < final_cnt)); i++) {
1467 			if ((final_lst[i] - final_lst[i-1]) ==
1468 			     DFS_NEXT_5GHZ_CHANNEL)
1469 				count++;
1470 			else
1471 				count = 0;
1472 			if (count == DFS_MAX_20M_SUB_CH - 1) {
1473 				flag = true;
1474 				new_160_start_ch = final_lst[i - count];
1475 				break;
1476 			}
1477 		}
1478 	} else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) {
1479 		flag = true;
1480 	}
1481 
1482 	if ((flag == false) && (*ch_wd > DFS_CH_WIDTH_80MHZ)) {
1483 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1484 				"from [%d] to 80Mhz", *ch_wd);
1485 		*ch_wd = DFS_CH_WIDTH_80MHZ;
1486 		return 0;
1487 	}
1488 
1489 	if (*ch_wd == DFS_CH_WIDTH_160MHZ) {
1490 		get_random_bytes((uint8_t *)&rand_byte, 1);
1491 		rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks())
1492 			% DFS_MAX_20M_SUB_CH;
1493 		target_channel = new_160_start_ch + (rand_byte *
1494 				DFS_80_NUM_SUB_CHANNEL);
1495 	} else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) {
1496 		get_random_bytes((uint8_t *)&rand_byte, 1);
1497 		index = (rand_byte + qdf_mc_timer_get_system_ticks()) %
1498 			final_cnt;
1499 		target_channel = final_lst[index];
1500 		index -= (index % DFS_80_NUM_SUB_CHANNEL);
1501 		primary_seg_start_ch = final_lst[index];
1502 
1503 		/* reset channels associate with primary 80Mhz */
1504 		for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++)
1505 			final_lst[i + index] = 0;
1506 		/* select and calculate center freq for secondary segment */
1507 		for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) {
1508 			if (final_lst[i * DFS_80_NUM_SUB_CHANNEL] &&
1509 			    (abs(primary_seg_start_ch -
1510 			     final_lst[i * DFS_80_NUM_SUB_CHANNEL]) >
1511 			     (DFS_MAX_20M_SUB_CH * 2))) {
1512 				sec_seg_ch =
1513 					final_lst[i * DFS_80_NUM_SUB_CHANNEL] +
1514 					DFS_80MHZ_START_CENTER_CH_DIFF;
1515 				break;
1516 			}
1517 		}
1518 
1519 		if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH))
1520 			*ch_wd = DFS_CH_WIDTH_160MHZ;
1521 		else if (!sec_seg_ch)
1522 			*ch_wd = DFS_CH_WIDTH_80MHZ;
1523 
1524 		*center_freq_seg1 = sec_seg_ch;
1525 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1526 				"Center frequency seg1 = %d", sec_seg_ch);
1527 	} else {
1528 		target_channel = dfs_get_rand_from_lst(dfs,
1529 				final_lst, final_cnt);
1530 	}
1531 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1532 			"target channel = %d", target_channel);
1533 
1534 	return target_channel;
1535 }
1536 #endif
1537 
1538 /**
1539  * dfs_find_ch_with_fallback_for_freq()- find random channel
1540  * @dfs: Pointer to DFS structure.
1541  * @chan_wd: channel width
1542  * @center_freq_seg1: center frequency of secondary segment.
1543  * @freq_lst: list of available frequency.
1544  * @num_chan: number of channels in the list.
1545  *
1546  * Find random channel based on given channel width and channel list,
1547  * fallback to lower width if requested channel width not available.
1548  *
1549  * Return: channel frequency.
1550  */
1551 #ifdef CONFIG_CHAN_FREQ_API
1552 static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
1553 						   uint8_t *chan_wd,
1554 						   uint16_t *center_freq_seg1,
1555 						   uint16_t *freq_lst,
1556 						   uint32_t num_chan)
1557 {
1558 	bool flag = false;
1559 	uint32_t rand_byte = 0;
1560 	struct  chan_bonding_bitmap ch_map = { { {0} } };
1561 	uint8_t count = 0, i, index = 0, final_cnt = 0;
1562 	uint16_t target_channel = 0;
1563 	uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0;
1564 	uint16_t final_lst[DFS_MAX_NUM_CHAN] = {0};
1565 
1566 	/* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */
1567 	ch_map.chan_bonding_set[0].start_chan_freq = 5180;
1568 	ch_map.chan_bonding_set[1].start_chan_freq = 5260;
1569 	ch_map.chan_bonding_set[2].start_chan_freq = 5500;
1570 	ch_map.chan_bonding_set[3].start_chan_freq = 5580;
1571 	ch_map.chan_bonding_set[4].start_chan_freq = 5660;
1572 	ch_map.chan_bonding_set[5].start_chan_freq = 5745;
1573 
1574 	for (i = 0; i < num_chan; i++) {
1575 		dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1576 			  "channel = %d added to bitmap", freq_lst[i]);
1577 		dfs_random_channel_sel_set_bitmap_for_freq(dfs, &ch_map,
1578 							   freq_lst[i]);
1579 	}
1580 
1581 	/* populate available channel list from bitmap */
1582 	final_cnt = dfs_populate_available_channel_for_freq(dfs, &ch_map,
1583 							    *chan_wd, final_lst);
1584 
1585 	/* If no valid ch bonding found, fallback */
1586 	if (final_cnt == 0) {
1587 		if ((*chan_wd == DFS_CH_WIDTH_160MHZ) ||
1588 		    (*chan_wd == DFS_CH_WIDTH_80P80MHZ) ||
1589 		    (*chan_wd == DFS_CH_WIDTH_80MHZ)) {
1590 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1591 				 "from [%d] to 40Mhz", *chan_wd);
1592 			*chan_wd = DFS_CH_WIDTH_40MHZ;
1593 		} else if (*chan_wd == DFS_CH_WIDTH_40MHZ) {
1594 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1595 				 "from 40Mhz to 20MHz");
1596 			*chan_wd = DFS_CH_WIDTH_20MHZ;
1597 		}
1598 		return 0;
1599 	}
1600 
1601 	/* ch count should be > 8 to switch new channel in 160Mhz band */
1602 	if (((*chan_wd == DFS_CH_WIDTH_160MHZ) ||
1603 	     (*chan_wd == DFS_CH_WIDTH_80P80MHZ)) &&
1604 	     (final_cnt < DFS_MAX_20M_SUB_CH)) {
1605 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1606 			 "from [%d] to 80Mhz", *chan_wd);
1607 		*chan_wd = DFS_CH_WIDTH_80MHZ;
1608 		return 0;
1609 	}
1610 
1611 	if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
1612 		/*
1613 		 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128
1614 		 * and all the channels in these blocks are continuous
1615 		 * and separated by 4Mhz.
1616 		 */
1617 		for (i = 1; ((i < final_cnt)); i++) {
1618 			if ((final_lst[i] - final_lst[i - 1]) ==
1619 			     DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET)
1620 				count++;
1621 			else
1622 				count = 0;
1623 			if (count == DFS_MAX_20M_SUB_CH - 1) {
1624 				flag = true;
1625 				new_160_start_ch = final_lst[i - count];
1626 				break;
1627 			}
1628 		}
1629 	} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
1630 		flag = true;
1631 	}
1632 
1633 	if ((flag == false) && (*chan_wd > DFS_CH_WIDTH_80MHZ)) {
1634 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1635 			 "from [%d] to 80Mhz", *chan_wd);
1636 		*chan_wd = DFS_CH_WIDTH_80MHZ;
1637 		return 0;
1638 	}
1639 
1640 	if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
1641 		get_random_bytes((uint8_t *)&rand_byte, 1);
1642 		rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks())
1643 			% DFS_MAX_20M_SUB_CH;
1644 		target_channel = new_160_start_ch + (rand_byte *
1645 				DFS_80_NUM_SUB_CHANNEL_FREQ);
1646 	} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
1647 		get_random_bytes((uint8_t *)&rand_byte, 1);
1648 		index = (rand_byte + qdf_mc_timer_get_system_ticks()) %
1649 			final_cnt;
1650 		target_channel = final_lst[index];
1651 		index -= (index % DFS_80_NUM_SUB_CHANNEL_FREQ);
1652 		primary_seg_start_ch = final_lst[index];
1653 
1654 		/* reset channels associate with primary 80Mhz */
1655 		for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++)
1656 			final_lst[i + index] = 0;
1657 		/* select and calculate center freq for secondary segment */
1658 		for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) {
1659 			if (final_lst[i * DFS_80_NUM_SUB_CHANNEL_FREQ] &&
1660 			    (abs(primary_seg_start_ch -
1661 				 final_lst[i * DFS_80_NUM_SUB_CHANNEL_FREQ]) >
1662 			     (DFS_MAX_20M_SUB_CH * 2))) {
1663 				sec_seg_ch = final_lst[i *
1664 					DFS_80_NUM_SUB_CHANNEL_FREQ] +
1665 					DFS_80MHZ_START_CENTER_CH_FREQ_DIFF;
1666 				break;
1667 			}
1668 		}
1669 
1670 		if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH))
1671 			*chan_wd = DFS_CH_WIDTH_160MHZ;
1672 		else if (!sec_seg_ch)
1673 			*chan_wd = DFS_CH_WIDTH_80MHZ;
1674 
1675 		*center_freq_seg1 = sec_seg_ch;
1676 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1677 			 "Center frequency seg1 = %d", sec_seg_ch);
1678 	} else {
1679 		target_channel = dfs_get_rand_from_lst_for_freq(dfs,
1680 								final_lst,
1681 								final_cnt);
1682 	}
1683 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1684 		 "target channel = %d", target_channel);
1685 
1686 	return target_channel;
1687 }
1688 #endif
1689 
1690 /**
1691  * dfs_remove_cur_ch_from_list()- remove current operating channels
1692  * @ch_list: list of avilable channel list
1693  * @ch_cnt: number of channels.
1694  * @ch_wd: channel width.
1695  * @cur_chan: current channel.
1696  *
1697  * Remove current channels from list of available channels.
1698  *
1699  * Return: channel number
1700  */
1701 static void dfs_remove_cur_ch_from_list(
1702 	struct dfs_channel *ch_list,
1703 	uint32_t *ch_cnt,
1704 	uint8_t *ch_wd,
1705 	struct dfs_channel *cur_chan)
1706 {
1707 	/* TODO */
1708 	return;
1709 }
1710 
1711 bool dfs_is_freq_in_nol(struct wlan_dfs *dfs, uint32_t freq)
1712 {
1713 	struct dfs_nolelem *nol;
1714 
1715 	if (!dfs) {
1716 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,  "null dfs");
1717 		return false;
1718 	}
1719 
1720 	nol = dfs->dfs_nol;
1721 	while (nol) {
1722 		if (freq == nol->nol_freq) {
1723 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1724 					"%d is in nol", freq);
1725 			return true;
1726 		}
1727 		nol = nol->nol_next;
1728 	}
1729 
1730 	return false;
1731 }
1732 
1733 /**
1734  * dfs_apply_rules()- prepare channel list based on flags
1735  * @dfs: dfs handler
1736  * @flags: channel flags
1737  * @random_chan_list: output channel list
1738  * @random_chan_cnt: output channel count
1739  * @ch_list: input channel list
1740  * @ch_cnt: input channel count
1741  * @dfs_region: dfs region
1742  * @acs_info: acs channel range information
1743  *
1744  * prepare channel list based on flags
1745  *
1746  * return: none
1747  */
1748 #ifdef CONFIG_CHAN_NUM_API
1749 static void dfs_apply_rules(struct wlan_dfs *dfs,
1750 	uint32_t flags,
1751 	uint8_t *random_chan_list,
1752 	uint32_t *random_chan_cnt,
1753 	struct dfs_channel *ch_list,
1754 	uint32_t ch_cnt,
1755 	uint8_t dfs_region,
1756 	struct dfs_acs_info *acs_info)
1757 {
1758 	struct dfs_channel *chan;
1759 	bool flag_no_weather = 0;
1760 	bool flag_no_lower_5g = 0;
1761 	bool flag_no_upper_5g = 0;
1762 	bool flag_no_dfs_chan = 0;
1763 	bool flag_no_2g_chan  = 0;
1764 	bool flag_no_5g_chan  = 0;
1765 	bool flag_no_japan_w53 = 0;
1766 	int i;
1767 	bool found = false;
1768 	uint16_t j;
1769 
1770 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags);
1771 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
1772 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1773 
1774 	if (dfs_region == DFS_MKK_REGION_VAL) {
1775 		flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH;
1776 		flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH;
1777 		flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH;
1778 	}
1779 
1780 	flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH;
1781 	flag_no_2g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH;
1782 	flag_no_5g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH;
1783 
1784 	for (i = 0; i < ch_cnt; i++) {
1785 		chan = &ch_list[i];
1786 
1787 		if ((chan->dfs_ch_ieee == 0) ||
1788 				(chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) {
1789 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1790 				  "invalid channel %d", chan->dfs_ch_ieee);
1791 			continue;
1792 		}
1793 
1794 		if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) {
1795 			/* TODO : Skip all HT20 channels in the given mode */
1796 			if (chan->dfs_ch_ieee ==
1797 					dfs->dfs_curchan->dfs_ch_ieee) {
1798 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1799 					  "skip %d current operating channel",
1800 					  chan->dfs_ch_ieee);
1801 				continue;
1802 			}
1803 		}
1804 
1805 		if (acs_info && acs_info->acs_mode) {
1806 			for (j = 0; j < acs_info->num_of_channel; j++) {
1807 				if (acs_info->channel_list[j] ==
1808 				    chan->dfs_ch_ieee) {
1809 					found = true;
1810 					break;
1811 				}
1812 			}
1813 
1814 			if (!found) {
1815 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1816 					  "skip ch %d not in acs range",
1817 					  chan->dfs_ch_ieee);
1818 				continue;
1819 			}
1820 			found = false;
1821 		}
1822 
1823 		if (flag_no_2g_chan &&
1824 				chan->dfs_ch_ieee <= DFS_MAX_24GHZ_CHANNEL) {
1825 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1826 				  "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee);
1827 			continue;
1828 		}
1829 
1830 		if (flag_no_5g_chan &&
1831 				chan->dfs_ch_ieee > DFS_MAX_24GHZ_CHANNEL) {
1832 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1833 				  "skip 5 GHz channel=%d", chan->dfs_ch_ieee);
1834 			continue;
1835 		}
1836 
1837 		if (flag_no_weather) {
1838 			if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) {
1839 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1840 					  "skip weather channel=%d",
1841 					  chan->dfs_ch_ieee);
1842 				continue;
1843 			}
1844 		}
1845 
1846 		if (flag_no_lower_5g &&
1847 		    DFS_IS_CHAN_JAPAN_INDOOR(chan->dfs_ch_ieee)) {
1848 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1849 				  "skip indoor channel=%d", chan->dfs_ch_ieee);
1850 			continue;
1851 		}
1852 
1853 		if (flag_no_upper_5g &&
1854 		    DFS_IS_CHAN_JAPAN_OUTDOOR(chan->dfs_ch_ieee)) {
1855 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1856 				  "skip outdoor channel=%d", chan->dfs_ch_ieee);
1857 			continue;
1858 		}
1859 
1860 		if (flag_no_dfs_chan &&
1861 		    (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) {
1862 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1863 				  "skip dfs channel=%d", chan->dfs_ch_ieee);
1864 			continue;
1865 		}
1866 
1867 		if (flag_no_japan_w53 &&
1868 		    DFS_IS_CHAN_JAPAN_W53(chan->dfs_ch_ieee)) {
1869 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1870 				  "skip japan W53 channel=%d",
1871 				  chan->dfs_ch_ieee);
1872 			continue;
1873 		}
1874 
1875 		if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) {
1876 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1877 				  "skip nol channel=%d", chan->dfs_ch_ieee);
1878 			continue;
1879 		}
1880 
1881 		random_chan_list[*random_chan_cnt] = chan->dfs_ch_ieee;
1882 		*random_chan_cnt += 1;
1883 	}
1884 }
1885 #endif
1886 
1887 /**
1888  * dfs_apply_rules_for_freq()- prepare channel list based on flags
1889  * @dfs: dfs handler
1890  * @flags: channel flags
1891  * @random_chan_freq_list: output channel list
1892  * @random_chan_cnt: output channel count
1893  * @chan_list: input channel list
1894  * @chan_cnt: input channel count
1895  * @dfs_region: dfs region
1896  * @acs_info: acs channel range information
1897  *
1898  * prepare channel list based on flags
1899  *
1900  * return: none
1901  */
1902 #ifdef CONFIG_CHAN_FREQ_API
1903 static void dfs_apply_rules_for_freq(struct wlan_dfs *dfs,
1904 				     uint32_t flags,
1905 				     uint16_t *random_chan_freq_list,
1906 				     uint32_t *random_chan_cnt,
1907 				     struct dfs_channel *chan_list,
1908 				     uint32_t chan_cnt,
1909 				     uint8_t dfs_region,
1910 				     struct dfs_acs_info *acs_info)
1911 {
1912 	struct dfs_channel *chan;
1913 	bool flag_no_weather = 0;
1914 	bool flag_no_lower_5g = 0;
1915 	bool flag_no_upper_5g = 0;
1916 	bool flag_no_dfs_chan = 0;
1917 	bool flag_no_2g_chan  = 0;
1918 	bool flag_no_5g_chan  = 0;
1919 	bool flag_no_japan_w53 = 0;
1920 	int i;
1921 	bool found = false;
1922 	uint16_t j;
1923 
1924 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags);
1925 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
1926 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1927 
1928 	if (dfs_region == DFS_MKK_REGION_VAL) {
1929 		flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH;
1930 		flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH;
1931 		flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH;
1932 	}
1933 
1934 	flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH;
1935 	flag_no_2g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH;
1936 	flag_no_5g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH;
1937 
1938 	for (i = 0; i < chan_cnt; i++) {
1939 		chan = &chan_list[i];
1940 
1941 		if ((chan->dfs_ch_ieee == 0) ||
1942 		    (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) {
1943 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1944 				  "invalid channel %d", chan->dfs_ch_ieee);
1945 			continue;
1946 		}
1947 
1948 		if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) {
1949 			/* TODO : Skip all HT20 channels in the given mode */
1950 			if (chan->dfs_ch_freq ==
1951 					dfs->dfs_curchan->dfs_ch_freq) {
1952 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1953 					  "skip %d current operating channel",
1954 					  chan->dfs_ch_ieee);
1955 				continue;
1956 			}
1957 		}
1958 		if (acs_info && acs_info->acs_mode) {
1959 			for (j = 0; j < acs_info->num_of_channel; j++) {
1960 				if (acs_info->channel_list[j] ==
1961 				    chan->dfs_ch_ieee) {
1962 					found = true;
1963 					break;
1964 				}
1965 			}
1966 
1967 			if (!found) {
1968 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1969 					  "skip ch %d not in acs range",
1970 					  chan->dfs_ch_ieee);
1971 				continue;
1972 			}
1973 			found = false;
1974 		}
1975 
1976 		if (flag_no_2g_chan &&
1977 		    chan->dfs_ch_freq <= DFS_MAX_24GHZ_CHANNEL_FREQ) {
1978 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1979 				  "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee);
1980 			continue;
1981 		}
1982 
1983 		if (flag_no_5g_chan && chan->dfs_ch_freq >
1984 		    DFS_MAX_24GHZ_CHANNEL_FREQ)
1985 		{
1986 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1987 				  "skip 5 GHz channel=%d", chan->dfs_ch_ieee);
1988 			continue;
1989 		}
1990 
1991 		if (flag_no_weather) {
1992 			if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) {
1993 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1994 					  "skip weather channel=%d",
1995 					  chan->dfs_ch_ieee);
1996 				continue;
1997 			}
1998 		}
1999 
2000 		if (flag_no_lower_5g &&
2001 		    DFS_IS_CHAN_JAPAN_INDOOR_FREQ(chan->dfs_ch_freq)) {
2002 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2003 				  "skip indoor channel=%d", chan->dfs_ch_ieee);
2004 			continue;
2005 		}
2006 
2007 		if (flag_no_upper_5g &&
2008 		    DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(chan->dfs_ch_freq)) {
2009 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2010 				  "skip outdoor channel=%d", chan->dfs_ch_ieee);
2011 			continue;
2012 		}
2013 
2014 		if (flag_no_dfs_chan &&
2015 		    (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) {
2016 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2017 				  "skip dfs channel=%d", chan->dfs_ch_ieee);
2018 			continue;
2019 		}
2020 
2021 		if (flag_no_japan_w53 &&
2022 		    DFS_IS_CHAN_JAPAN_W53_FREQ(chan->dfs_ch_freq)) {
2023 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2024 				  "skip japan W53 channel=%d",
2025 				  chan->dfs_ch_ieee);
2026 			continue;
2027 		}
2028 
2029 		if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) {
2030 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2031 				  "skip nol channel=%d", chan->dfs_ch_ieee);
2032 			continue;
2033 		}
2034 
2035 		random_chan_freq_list[*random_chan_cnt] = chan->dfs_ch_freq;
2036 		*random_chan_cnt += 1;
2037 	}
2038 }
2039 #endif
2040 
2041 #ifdef CONFIG_CHAN_NUM_API
2042 uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs,
2043 	struct dfs_channel *ch_list,
2044 	uint32_t ch_cnt,
2045 	uint32_t flags,
2046 	uint8_t *ch_wd,
2047 	struct dfs_channel *cur_chan,
2048 	uint8_t dfs_region,
2049 	struct dfs_acs_info *acs_info)
2050 {
2051 	int i = 0;
2052 	uint8_t final_cnt = 0;
2053 	uint8_t target_ch = 0;
2054 	uint8_t *random_chan_list = NULL;
2055 	uint32_t random_chan_cnt = 0;
2056 	uint16_t flag_no_weather = 0;
2057 	uint8_t *leakage_adjusted_lst;
2058 	uint8_t final_lst[NUM_CHANNELS] = {0};
2059 
2060 	if (!ch_list || !ch_cnt) {
2061 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2062 				"Invalid params %pK, ch_cnt=%d",
2063 				ch_list, ch_cnt);
2064 		return 0;
2065 	}
2066 
2067 	if (*ch_wd < DFS_CH_WIDTH_20MHZ || *ch_wd > DFS_CH_WIDTH_80P80MHZ) {
2068 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2069 				"Invalid ch_wd %d", *ch_wd);
2070 		return 0;
2071 	}
2072 
2073 	random_chan_list = qdf_mem_malloc(ch_cnt * sizeof(*random_chan_list));
2074 	if (!random_chan_list)
2075 		return 0;
2076 
2077 	if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH)
2078 		dfs_remove_cur_ch_from_list(ch_list, &ch_cnt, ch_wd, cur_chan);
2079 
2080 	dfs_apply_rules(dfs, flags, random_chan_list, &random_chan_cnt,
2081 		    ch_list, ch_cnt, dfs_region, acs_info);
2082 
2083 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
2084 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
2085 
2086 	/* list adjusted after leakage has been marked */
2087 	leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt);
2088 	if (!leakage_adjusted_lst) {
2089 		qdf_mem_free(random_chan_list);
2090 		return 0;
2091 	}
2092 
2093 	do {
2094 		qdf_mem_copy(leakage_adjusted_lst, random_chan_list,
2095 			     random_chan_cnt);
2096 		if (QDF_IS_STATUS_ERROR(dfs_mark_leaking_ch(dfs, *ch_wd,
2097 				random_chan_cnt,
2098 				leakage_adjusted_lst))) {
2099 			qdf_mem_free(random_chan_list);
2100 			qdf_mem_free(leakage_adjusted_lst);
2101 			return 0;
2102 		}
2103 
2104 		if (*ch_wd == DFS_CH_WIDTH_20MHZ) {
2105 			/*
2106 			 * PASS: 3 - from leakage_adjusted_lst, prepare valid
2107 			 * ch list and use random number from that
2108 			 */
2109 			for (i = 0; i < random_chan_cnt; i++) {
2110 				if (leakage_adjusted_lst[i] == 0)
2111 					continue;
2112 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2113 					  "dfs: Channel=%d added to available list",
2114 					  leakage_adjusted_lst[i]);
2115 				final_lst[final_cnt] = leakage_adjusted_lst[i];
2116 				final_cnt++;
2117 			}
2118 			target_ch = dfs_get_rand_from_lst(
2119 				dfs, final_lst, final_cnt);
2120 			break;
2121 		}
2122 
2123 		target_ch = dfs_find_ch_with_fallback(dfs, ch_wd,
2124 				&cur_chan->dfs_ch_vhtop_ch_freq_seg2,
2125 				leakage_adjusted_lst,
2126 				random_chan_cnt);
2127 
2128 		/*
2129 		 * When flag_no_weather is set, avoid usage of Adjacent
2130 		 * weather radar channel in HT40 mode as extension channel
2131 		 * will be on 5600.
2132 		 */
2133 		if (flag_no_weather &&
2134 				(target_ch ==
2135 				 DFS_ADJACENT_WEATHER_RADAR_CHANNEL_NUM) &&
2136 				(*ch_wd == DFS_CH_WIDTH_40MHZ)) {
2137 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2138 					"skip weather adjacent ch=%d\n",
2139 					target_ch);
2140 			continue;
2141 		}
2142 
2143 		if (target_ch)
2144 			break;
2145 	} while (true);
2146 
2147 	qdf_mem_free(random_chan_list);
2148 	qdf_mem_free(leakage_adjusted_lst);
2149 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_ch = %d", target_ch);
2150 
2151 	return target_ch;
2152 }
2153 #endif
2154 
2155 #ifdef CONFIG_CHAN_FREQ_API
2156 uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs,
2157 					     struct dfs_channel *chan_list,
2158 					     uint32_t chan_cnt,
2159 					     uint32_t flags,
2160 					     uint8_t *chan_wd,
2161 					     struct dfs_channel *cur_chan,
2162 					     uint8_t dfs_region,
2163 					     struct dfs_acs_info *acs_info)
2164 {
2165 	int i = 0;
2166 	uint8_t final_cnt = 0;
2167 	uint16_t target_freq = 0;
2168 	uint16_t *random_chan_freq_list = NULL;
2169 	uint32_t random_chan_cnt = 0;
2170 	uint16_t flag_no_weather = 0;
2171 	uint16_t *leakage_adjusted_lst;
2172 	uint16_t final_lst[NUM_CHANNELS] = {0};
2173 	uint16_t *dfs_cfreq_seg2 = NULL;
2174 
2175 	if (!chan_list || !chan_cnt) {
2176 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2177 			 "Invalid params %pK, chan_cnt=%d",
2178 			 chan_list, chan_cnt);
2179 		return 0;
2180 	}
2181 
2182 	if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_80P80MHZ) {
2183 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2184 			 "Invalid chan_wd %d", *chan_wd);
2185 		return 0;
2186 	}
2187 
2188 	random_chan_freq_list =
2189 	    qdf_mem_malloc(chan_cnt * sizeof(*random_chan_freq_list));
2190 	if (!random_chan_freq_list)
2191 		return 0;
2192 
2193 	if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH)
2194 		dfs_remove_cur_ch_from_list(chan_list, &chan_cnt, chan_wd, cur_chan);
2195 
2196 	dfs_apply_rules_for_freq(dfs, flags, random_chan_freq_list,
2197 				 &random_chan_cnt, chan_list, chan_cnt,
2198 				 dfs_region, acs_info);
2199 
2200 	flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ?
2201 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
2202 
2203 	/* list adjusted after leakage has been marked */
2204 	leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt);
2205 	if (!leakage_adjusted_lst) {
2206 		qdf_mem_free(random_chan_freq_list);
2207 		return 0;
2208 	}
2209 
2210 	do {
2211 		int ret;
2212 
2213 		qdf_mem_copy(leakage_adjusted_lst, random_chan_freq_list,
2214 			     random_chan_cnt);
2215 		ret = dfs_mark_leaking_chan_for_freq(dfs, *chan_wd,
2216 						   random_chan_cnt,
2217 						   leakage_adjusted_lst);
2218 		if (QDF_IS_STATUS_ERROR(ret)) {
2219 			qdf_mem_free(random_chan_freq_list);
2220 			qdf_mem_free(leakage_adjusted_lst);
2221 			return 0;
2222 		}
2223 
2224 		if (*chan_wd == DFS_CH_WIDTH_20MHZ) {
2225 			/*
2226 			 * PASS: 3 - from leakage_adjusted_lst, prepare valid
2227 			 * ch list and use random number from that
2228 			 */
2229 			for (i = 0; i < random_chan_cnt; i++) {
2230 				if (leakage_adjusted_lst[i] == 0)
2231 					continue;
2232 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2233 					  "Channel=%d added to available list",
2234 					  leakage_adjusted_lst[i]);
2235 				final_lst[final_cnt] = leakage_adjusted_lst[i];
2236 				final_cnt++;
2237 			}
2238 			target_freq = dfs_get_rand_from_lst_for_freq(dfs,
2239 								     final_lst,
2240 								     final_cnt);
2241 			break;
2242 		}
2243 		dfs_cfreq_seg2 = &cur_chan->dfs_ch_mhz_freq_seg2;
2244 		target_freq =
2245 			dfs_find_ch_with_fallback_for_freq(dfs, chan_wd,
2246 							   dfs_cfreq_seg2,
2247 							   leakage_adjusted_lst,
2248 							   random_chan_cnt);
2249 
2250 		/*
2251 		 * When flag_no_weather is set, avoid usage of Adjacent
2252 		 * weather radar channel in HT40 mode as extension channel
2253 		 * will be on 5600.
2254 		 */
2255 		if (flag_no_weather &&
2256 		    (target_freq ==
2257 		     DFS_ADJACENT_WEATHER_RADAR_CHANNEL_FREQ) &&
2258 		    (*chan_wd == DFS_CH_WIDTH_40MHZ)) {
2259 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
2260 				  "skip weather adjacent ch=%d\n",
2261 				  target_freq);
2262 			continue;
2263 		}
2264 
2265 		if (target_freq)
2266 			break;
2267 	} while (true);
2268 
2269 	qdf_mem_free(random_chan_freq_list);
2270 	qdf_mem_free(leakage_adjusted_lst);
2271 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_freq = %d",
2272 		 target_freq);
2273 
2274 	return target_freq;
2275 }
2276 #endif
2277