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