xref: /wlan-driver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "../dfs.h"
21 #include "../dfs_random_chan_sel.h"
22 #include <qdf_mc_timer.h>
23 #include <wlan_utility.h>
24 #include <wlan_reg_services_api.h>
25 #include "../dfs_process_radar_found_ind.h"
26 
27 #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION
28 /*
29  * TODO: At present SAP Channel leakage matrix for ch 144
30  * is not available from system's team. So to play it safe
31  * and avoid crash if channel 144 is request, in following
32  * matrix channel 144 is added such that it will cause code
33  * to avoid selecting channel 144.
34  *
35  * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS
36  * PROVIDED BY SYSTEM'S TEAM.
37  */
38 
39 /* channel tx leakage table - ht80 */
40 struct dfs_matrix_tx_leak_info ht80_chan[] = {
41 	{52, 5260,
42 	 {{36, 5180, 148}, {40, 5200, 199},
43 	  {44, 5520, 193}, {48, 5240, 197},
44 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, 153},
45 	  {60, 5300, 137}, {64, 5320, 134},
46 	  {100, 5500, 358}, {104, 5520, 350},
47 	  {108, 5540, 404}, {112, 5560, 344},
48 	  {116, 5580, 424}, {120, 5600, 429},
49 	  {124, 5620, 437}, {128, 5640, 435},
50 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
51 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
52 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
53 	  } },
54 
55 
56 	{56, 5280,
57 	 {{36, 5180, 171}, {40, 5200, 178},
58 	  {44, 5220, 171}, {48, 5240, 178},
59 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
60 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, 280},
61 	  {100, 5500, 351}, {104, 5520, 376},
62 	  {108, 5540, 362}, {112, 5560, 362},
63 	  {116, 5580, 403}, {120, 5600, 397},
64 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
65 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
66 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
67 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
68 	  } },
69 
70 	{60,5300,
71 	 {{36, 5180, 156}, {40, 5200, 146},
72 	  {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN},
73 	  {52, 5260, 180}, {56, 5280, DFS_TX_LEAKAGE_MIN},
74 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
75 	  {100, 5500, 376}, {104, 5520, 360},
76 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
77 	  {116, 5580, 395}, {120, 5600, 399},
78 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
79 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
80 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
81 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
82 	  } },
83 
84 	{64, 5320,
85 	 {{36, 5180,  217}, {40, 5200, 221},
86 	  {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN},
87 	  {52, 5260, 176}, {56, 5280, 176},
88 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
89 	  {100, 5500, 384}, {104, 5520, 390},
90 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
91 	  {116, 5580, 375}, {120, 5600, 374},
92 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
93 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
94 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
95 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
96 	  } },
97 
98 	{100, 5500,
99 	 {{36, 5180, 357}, {40, 5200, 326},
100 	  {44, 5220, 321}, {48, 5240, 326},
101 	  {52, 5260, 378}, {56, 5280, 396},
102 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
103 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
104 	  {108, 5540, 196}, {112, 5560, 116},
105 	  {116, 5580, 166}, {120, 5600, DFS_TX_LEAKAGE_MIN},
106 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
107 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
108 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
109 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
110 	  } },
111 
112 	{104, 5520,
113 	 {{36, 5180,  325}, {40, 5200, 325},
114 	  {44, 5220, 305}, {48, 5240, 352},
115 	  {52, 5260, 411}, {56, 5280, 411},
116 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
117 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
118 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 460},
119 	  {116, 5580, 198}, {120, 5600, DFS_TX_LEAKAGE_MIN},
120 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
121 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
122 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
123 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
124 	  } },
125 
126 	{108, 5540,
127 	 {{36,5180,  304}, {40, 5200, 332},
128 	  {44, 5220, 310}, {48, 5240, 335},
129 	  {52, 5260, 431}, {56, 5280, 391},
130 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
131 	  {100, 5500, 280}, {104, 5520, DFS_TX_LEAKAGE_MIN},
132 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
133 	  {116, 5580, 185}, {120, 5600, DFS_TX_LEAKAGE_MIN},
134 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
135 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
136 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
137 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
138 	  } },
139 
140 	{112,5560,
141 	 {{36, 5180, 327}, {40, 5200, 335},
142 	  {44, 5220, 331}, {48, 5240, 345},
143 	  {52, 5260, 367}, {56, 5280, 401},
144 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
145 	  {100, 5500, 131}, {104, 5520, 132},
146 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
147 	  {116, 5580, 189}, {120, 5600, DFS_TX_LEAKAGE_MIN},
148 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
149 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
150 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
151 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
152 	  } },
153 
154 	{116, 5580,
155 	 {{36, 5180, 384}, {40, 5200, 372},
156 	  {44, 5220, 389}, {48, 5240, 396},
157 	  {52, 5260, 348}, {56, 5280, 336},
158 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
159 	  {100, 5500, 172}, {104, 5520, 169},
160 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
161 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
162 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
163 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
164 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
165 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
166 	  } },
167 
168 	{120, 5600,
169 	 {{36, 5180, 395}, {40, 5200, 419},
170 	  {44, 5220, 439}, {48, 5240, 407},
171 	  {52, 5260, 321}, {56, 5280, 334},
172 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
173 	  {100, 5500, 134}, {104, 5520, 186},
174 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
175 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
176 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 159},
177 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
178 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
179 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
180 	  } },
181 
182 	{124, 5620,
183 	 {{36, 5180, 469}, {40, 5200, 433},
184 	  {44, 5220, 434}, {48, 5240, 435},
185 	  {52, 5260, 332}, {56, 5280, 345},
186 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
187 	  {100, 5500, 146}, {104, 5520, 177},
188 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
189 	  {116, 5580, 350}, {120, 5600, DFS_TX_LEAKAGE_MIN},
190 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 138},
191 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
192 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
193 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
194 	  } },
195 
196 	{128, 5640,
197 	 {{36, 5180, 408}, {40, 5200, 434},
198 	  {44, 5220, 449}, {48, 5240, 444},
199 	  {52, 5260, 341}, {56, 5280, 374},
200 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
201 	  {100, 5500, 205}, {104, 5520, 208},
202 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
203 	  {116, 5580, 142}, {120, 5600, DFS_TX_LEAKAGE_MIN},
204 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
205 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
206 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
207 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
208 	  } },
209 
210 	{132, 5660,
211 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
212 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
213 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
214 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
215 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
216 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
217 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
218 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
219 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
220 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
221 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
222 	  } },
223 
224 	{136, 5680,
225 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
226 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
227 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
228 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
229 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
230 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
231 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
232 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
233 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
234 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
235 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
236 	  } },
237 
238 	{140, 5700,
239 	 {{36, 5180,  DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
240 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
241 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
242 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
243 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
244 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
245 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
246 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
247 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
248 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
249 	  } },
250 
251 	{144, 5720,
252 	 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX},
253 	  {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX},
254 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
255 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
256 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
257 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
258 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
259 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
260 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
261 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
262 	  } },
263 };
264 
265 /* channel tx leakage table - ht40 */
266 struct dfs_matrix_tx_leak_info ht40_chan[] = {
267 	{52, 5260,
268 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
269 	  {44, 5220, 230}, {48, 5240, 230},
270 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
271 	  {60, 5300, DFS_TX_LEAKAGE_AUTO_MIN}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN},
272 	  {100, 5500, 625}, {104, 5520, 323},
273 	  {108, 5540, 646}, {112, 5560, 646},
274 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
275 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
276 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
277 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
278 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
279 	  } },
280 
281 	{56, 5280,
282 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
283 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
284 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
285 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
286 	  {100, 5500, 611}, {104, 5520, 611},
287 	  {108, 5540, 617}, {112, 5560, 617},
288 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
289 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
290 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
291 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
292 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
293 	  } },
294 
295 	{60, 5300,
296 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
297 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
298 	  {52, 5260, 190}, {56, 5280, 190},
299 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
300 	  {100, 5500, 608}, {104, 5520, 608},
301 	  {108, 5540, 623}, {112, 5560, 623},
302 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
303 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
304 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
305 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
306 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
307 	  } },
308 
309 	{64, 5320,
310 	 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
311 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN},
312 	  {52, 5260, 295}, {56, 5280, 295},
313 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
314 	  {100, 5500, 594}, {104, 5520, 594},
315 	  {108, 5540, 625}, {112, 5560, 625},
316 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
317 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
318 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
319 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
320 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
321 	  } },
322 
323 	{100, 5500,
324 	 {{36, 5180, 618}, {40, 5200, 618},
325 	  {44, 5220, 604}, {48, 5240, 604},
326 	  {52, 5260, 596}, {56, 5280, 596},
327 	  {60, 5300, 584}, {64, 5320, 584},
328 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
329 	  {108, 5540, 299}, {112, 5560, 299},
330 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
331 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
332 	  {132, 5660, 538}, {136,5680, 538},
333 	  {140, 5700, 598},
334 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
335 	  } },
336 
337 	{104, 5520,
338 	 {{36, 5180, 636}, {40, 5200, 636},
339 	  {44, 5220, 601}, {48, 5240, 601},
340 	  {52, 5260, 616}, {56, 5280, 616},
341 	  {60, 5300, 584}, {64, 5320, 584},
342 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
343 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
344 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
345 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
346 	  {132, 5660, 553}, {136, 5680, 553},
347 	  {140, 5700, 568},
348 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
349 	  } },
350 
351 	{108, 5540,
352 	 {{36, 5180, 600}, {40, 5200, 600},
353 	  {44, 5220, 627}, {48, 5240, 627},
354 	  {52, 5260, 611}, {56, 5280, 611},
355 	  {60, 5300, 611}, {64, 5320, 611},
356 	  {100, 5500, 214}, {104, 5520, 214},
357 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
358 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
359 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
360 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
361 	  {140, 5700, 534},
362 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
363 	  } },
364 
365 	{112, 5560,
366 	 {{36, 5180, 645}, {40, 5200, 645},
367 	  {44, 5220, 641}, {48, 5240, 641},
368 	  {52, 5260, 618}, {56, 5280, 618},
369 	  {60, 5300, 612}, {64, 5320, 612},
370 	  {100, 5500, 293}, {104, 5520, 293},
371 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
372 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
373 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
374 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
375 	  {140, 5700, 521},
376 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
377 	  } },
378 
379 	{116, 5580,
380 	 {{36, 5180, 661}, {40, 5200, 661},
381 	  {44, 5220, 624}, {48, 5240, 624},
382 	  {52, 5260, 634}, {56, 5280, 634},
383 	  {60, 5300, 611}, {64, 5320, 611},
384 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
385 	  {108, 5540, 217}, {112, 5560, 217},
386 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
387 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
388 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
389 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
390 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
391 	  } },
392 
393 	{120, 5600,
394 	 {{36, 5180, 667}, {40, 5200, 667},
395 	  {44, 5220, 645}, {48, 5240, 645},
396 	  {52, 5260, 633}, {56, 5280, 633},
397 	  {60, 5300, 619}, {64, 5320, 619},
398 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
399 	  {108, 5540, 291}, {112, 5560, 291},
400 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
401 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
402 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
403 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
404 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
405 	  } },
406 
407 	{124, 5620,
408 	 {{36, 5180,  676}, {40, 5200, 676},
409 	  {44, 5220, 668}, {48, 5240, 668},
410 	  {52, 5260, 595}, {56, 5280, 595},
411 	  {60, 5300, 622}, {64, 5320, 622},
412 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
413 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
414 	  {116, 5580, 225}, {120, 5600, 225},
415 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
416 	  {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN},
417 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
418 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
419 	  } },
420 
421 	{128, 5640,
422 	 {{36, 5180, 678}, {40, 5200, 678},
423 	  {44, 5220, 664}, {48, 5240, 664},
424 	  {52, 5260, 651}, {56, 5280, 651},
425 	  {60, 5300, 643}, {64, 5320, 643},
426 	  {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN},
427 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
428 	  {116, 5580, 293}, {120, 5600, 293},
429 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
430 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
431 	  {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN},
432 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
433 	  } },
434 
435 	{132, 5660,
436 	 {{36, 5180, 689}, {40, 5200, 689},
437 	  {44, 5220, 669}, {48, 5240, 669},
438 	  {52, 5260, 662}, {56, 5280, 662},
439 	  {60, 5300, 609}, {64, 5320, 609},
440 	  {100, 5500, 538}, {104, 5520, 538},
441 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
442 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
443 	  {124, 5620, 247}, {128, 5640, 247},
444 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
445 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
446 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
447 	  } },
448 
449 	{136, 5680,
450 	 {{36, 5180, 703}, {40, 5200, 703},
451 	  {44, 5220, 688}, {48, 5240, DFS_TX_LEAKAGE_MIN},
452 	  {52, 5260, 671}, {56, 5280, 671},
453 	  {60, 5300, 658}, {64, 5320, 658},
454 	  {100, 5500, 504}, {104, 5520, 504},
455 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
456 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
457 	  {124, 5620, 289}, {128, 5640, 289},
458 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
459 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
460 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
461 	  } },
462 
463 	{140, 5700,
464 	 {{36, 5180, 695}, {40, 5200, 695},
465 	  {44, 5220, 684}, {48, 5240, 684},
466 	  {52, 5260, 664}, {56, 5280, 664},
467 	  {60, 5300, 658}, {64, 5320, 658},
468 	  {100, 5500, 601}, {104, 5520, 601},
469 	  {108, 5540, 545}, {112, 5560, 545},
470 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
471 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
472 	  {132, 5660, 262}, {136, 5680, 262},
473 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
474 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
475 	  } },
476 
477 	{144, 5720,
478 	 {{36, 5180, 695}, {40, 5200, 695},
479 	  {44, 5220, 684}, {48, 5240, 684},
480 	  {52, 5260, 664}, {56, 5280, 664},
481 	  {60, 5300, 658}, {64, 5320, 658},
482 	  {100, 5500, 601}, {104, 5520, 601},
483 	  {108, 5540, 545}, {112, 5560, 545},
484 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN},
485 	  {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN},
486 	  {132, 5660, 262}, {136, 5680, 262},
487 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
488 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
489 	  } },
490 };
491 
492 /* channel tx leakage table - ht20 */
493 struct dfs_matrix_tx_leak_info ht20_chan[] = {
494 	{52, 5260,
495 	 {{36, 5180,DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, 286},
496 	  {44, 5220, 225}, {48,5240, 121},
497 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
498 	  {60, 5300, 300}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN},
499 	  {100, 5500, 637}, {104, 5520, DFS_TX_LEAKAGE_MAX},
500 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
501 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
502 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
503 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
504 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
505 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
506 	  } },
507 
508 	{56, 5280,
509 	 {{36, 5180, 468}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN},
510 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, 206},
511 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
512 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
513 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
514 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
515 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
516 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
517 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
518 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
519 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
520 	  } },
521 
522 	{60, 5300,
523 	 {{36, 5180, 507}, {40, 5200, 440},
524 	  {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48,5240, 313},
525 	  {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN},
526 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
527 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
528 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
529 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
530 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
531 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
532 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
533 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
534 	  } },
535 
536 	{64, 5320 ,
537 	 {{36, 5180, 516}, {40, 5200, 520},
538 	  {44, 5220, 506}, {48, 5240,DFS_TX_LEAKAGE_AUTO_MIN},
539 	  {52, 5260, 301}, {56, 5280, 258},
540 	  {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN},
541 	  {100, 5500, 620}, {104, 5520, 617},
542 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX},
543 	  {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX},
544 	  {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX},
545 	  {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX},
546 	  {140, 5700, DFS_TX_LEAKAGE_MAX},
547 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
548 	  } },
549 
550 	{100, 5500,
551 	 {{36, 5180, 616}, {40, 5200, 601},
552 	  {44, 5220, 604}, {48, 5240, 589},
553 	  {52, 5260, 612}, {56, 5280, 592},
554 	  {60, 5300, 590}, {64, 5320, 582},
555 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, 131},
556 	  {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN},
557 	  {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, 522},
558 	  {124, 5620, 571}, {128, 5640, 589},
559 	  {132, 5660, 593}, {136, 5680, 598},
560 	  {140, 5700, 594},
561 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
562 	  } },
563 
564 	{104, 5520,
565 	 {{36, 5180, 622}, {40, 5200, 624},
566 	  {44, 5220, 618}, {48, 5240, 610},
567 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
568 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
569 	  {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN},
570 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 463},
571 	  {116, 5580, 483}, {120, 5600, 503},
572 	  {124, 5620, 523}, {128, 5640, 565},
573 	  {132, 5660, 570}, {136, 5680, 588},
574 	  {140, 5700, 585},
575 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
576 	  } },
577 
578 	{108, 5540,
579 	 {{36, 5180, 620}, {40, 5200, 638},
580 	  {44, 5220, 611}, {48, 5240, 614},
581 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
582 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
583 	  {100, 5500, 477}, {104, 5520, DFS_TX_LEAKAGE_MIN},
584 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
585 	  {116, 5580, 477}, {120, 5600, 497},
586 	  {124, 5620, 517}, {128, 5640, 537},
587 	  {132, 5660, 557}, {136, 5680, 577},
588 	  {140, 5700, 603},
589 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
590 	  } },
591 
592 	{112, 5560,
593 	 {{36, 5180, 636}, {40, 5200, 623},
594 	  {44, 5220, 638}, {48, 5240, 628},
595 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
596 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, 606},
597 	  {100, 5500, 501}, {104, 5520, 481},
598 	  {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN},
599 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, 481},
600 	  {124, 5620, 501}, {128, 5640, 421},
601 	  {132, 5660, 541}, {136, 5680, 561},
602 	  {140, 5700, 583},
603 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
604 	  } },
605 
606 	{116, 5580,
607 	 {{36, 5180, 646}, {40, 5200, 648},
608 	  {44, 5220, 633}, {48, 5240, 634},
609 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
610 	  {60, 5300, 615}, {64, 5320, 594},
611 	  {100, 5500, 575}, {104, 5520, 554},
612 	  {108, 5540, 534}, {112, 5560, DFS_TX_LEAKAGE_MIN},
613 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
614 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
615 	  {132, 5660, 534}, {136, 5680, 554},
616 	  {140, 5700, 574},
617 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
618 	  } },
619 
620 	{120, 5600,
621 	 {{36, 5180, 643}, {40, 5200, 649},
622 	  {44, 5220, 654}, {48, 5240, 629},
623 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, 621},
624 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
625 	  {100, 5500, 565}, {104, 5520, 545},
626 	  {108, 5540, 525}, {112, 5560, 505},
627 	  {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN},
628 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 505},
629 	  {132, 5660, 525}, {136, 5680, 545},
630 	  {140, 5700, 565},
631 	  {144, 5720, DFS_TX_LEAKAGE_MIN},
632 	  } },
633 
634 	{124, 5620,
635 	 {{36, 5180, 638}, {40, 5200, 657},
636 	  {44, 5220, 663}, {48, 5240, 649},
637 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
638 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
639 	  {100, 5500, 581}, {104, 5520, 561},
640 	  {108, 5540, 541}, {112, 5560, 521},
641 	  {116, 5580, 499}, {120, 5600, DFS_TX_LEAKAGE_MIN},
642 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
643 	  {132, 5660, 499}, {136, 5680, 519},
644 	  {140, 5700, 539},
645 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
646 	  } },
647 
648 	{128, 5640,
649 	 {{36, 5180, 651}, {40, 5200, 651},
650 	  {44, 5220, 674}, {48, 5240, 640},
651 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
652 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
653 	  {100, 5500, 603}, {104, 5520, 560},
654 	  {108, 5540, 540}, {112, 5560, 520},
655 	  {116, 5580, 499}, {120, 5600, 479},
656 	  {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN},
657 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, 479},
658 	  {140, 5700, 499},
659 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
660 	  } },
661 
662 	{132, 5660,
663 	 {{36, 5180, 643}, {40, 5200, 668},
664 	  {44, 5220, 651}, {48, 5240, 657},
665 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
666 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
667 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, 602},
668 	  {108, 5540, 578}, {112,5560, 570},
669 	  {116, 5580, 550}, {120, 5600, 530},
670 	  {124, 5620, 510}, {128, 5640, DFS_TX_LEAKAGE_MIN},
671 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
672 	  {140, 5700, 490},
673 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
674 	  } },
675 
676 	{136,5680,
677 	 {{36, 5180, 654}, {40, 5200, 667},
678 	  {44, 5220, 666}, {48, 5240, 642},
679 	  {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX},
680 	  {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX},
681 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
682 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 596},
683 	  {116, 5580, 555}, {120, 5600, 535},
684 	  {124, 5620, 515}, {128, 5640, 495},
685 	  {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN},
686 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
687 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
688 	  } },
689 
690 	{140,5700,
691 	 {{36, 5180, 679}, {40, 5200, 673},
692 	  {44, 5220, 667}, {48, 5240, 656},
693 	  {52, 5260, 634}, {56, 5280, 663},
694 	  {60, 5300, 662}, {64, 5320, 660},
695 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
696 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590},
697 	  {116, 5580, 573}, {120, 5600, 553},
698 	  {124, 5620, 533}, {128, 5640, 513},
699 	  {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN},
700 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
701 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
702 	  } },
703 
704 	{144,5720,
705 	 {{36, 5180, 679}, {40, 5200, 673},
706 	  {44, 5220, 667}, {48, 5240, 656},
707 	  {52, 5260, 634}, {56, 5280, 663},
708 	  {60, 5300, 662}, {64, 5320, 660},
709 	  {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX},
710 	  {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590},
711 	  {116, 5580, 573}, {120, 5600, 553},
712 	  {124, 5620, 533}, {128, 5640, 513},
713 	  {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN},
714 	  {140, 5700, DFS_TX_LEAKAGE_MIN},
715 	  {144, 5720, DFS_TX_LEAKAGE_MIN}
716 	  } },
717 };
718 
719 /*
720  * dfs_find_target_channel_in_channel_matrix_for_freq() - finds the leakage
721  * matrix.
722  * @chan_width: target channel width
723  * @nol_channel: the NOL channel frequency whose leakage matrix is required
724  * @pTarget_chnl_mtrx: pointer to target channel matrix returned.
725  *
726  * This function gives the leakage matrix for given NOL channel and ch_width
727  *
728  * Return: TRUE or FALSE
729  */
730 #ifdef CONFIG_CHAN_FREQ_API
731 static bool
dfs_find_target_channel_in_channel_matrix_for_freq(enum phy_ch_width chan_width,uint16_t nol_freq,struct dfs_tx_leak_info ** pTarget_chnl_mtrx)732 dfs_find_target_channel_in_channel_matrix_for_freq(enum phy_ch_width chan_width,
733 						   uint16_t nol_freq,
734 						   struct dfs_tx_leak_info
735 						   **pTarget_chnl_mtrx)
736 {
737 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
738 	struct dfs_matrix_tx_leak_info *pchan_matrix = NULL;
739 	uint32_t nchan_matrix;
740 	int i = 0;
741 
742 	switch (chan_width) {
743 	case CH_WIDTH_20MHZ:
744 		/* HT20 */
745 		pchan_matrix = ht20_chan;
746 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
747 		break;
748 	case CH_WIDTH_40MHZ:
749 		/* HT40 */
750 		pchan_matrix = ht40_chan;
751 		nchan_matrix = QDF_ARRAY_SIZE(ht40_chan);
752 		break;
753 	case CH_WIDTH_80MHZ:
754 		/* HT80 */
755 		pchan_matrix = ht80_chan;
756 		nchan_matrix = QDF_ARRAY_SIZE(ht80_chan);
757 		break;
758 	default:
759 		/* handle exception and fall back to HT20 table */
760 		pchan_matrix = ht20_chan;
761 		nchan_matrix = QDF_ARRAY_SIZE(ht20_chan);
762 		break;
763 	}
764 
765 	for (i = 0; i < nchan_matrix; i++) {
766 		/* find the SAP channel to map the leakage matrix */
767 		if (nol_freq == pchan_matrix[i].channel_freq) {
768 			target_chan_matrix = pchan_matrix[i].chan_matrix;
769 			break;
770 		}
771 	}
772 
773 	if (!target_chan_matrix) {
774 		return false;
775 	} else {
776 		*pTarget_chnl_mtrx = target_chan_matrix;
777 		return true;
778 	}
779 }
780 #endif
781 
782 #ifdef CONFIG_CHAN_FREQ_API
783 
784 #ifdef CONFIG_BAND_6GHZ
785 #define END_CHAN_INDEX CHAN_ENUM_7115
786 #else
787 #define END_CHAN_INDEX CHAN_ENUM_5720
788 #endif
789 
790 #define START_CHAN_INDEX CHAN_ENUM_5180
791 QDF_STATUS
dfs_mark_leaking_chan_for_freq(struct wlan_dfs * dfs,enum phy_ch_width ch_width,uint8_t temp_chan_lst_sz,uint16_t * temp_freq_lst)792 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs,
793 			     enum phy_ch_width ch_width,
794 			     uint8_t temp_chan_lst_sz,
795 			     uint16_t *temp_freq_lst)
796 {
797 	struct dfs_tx_leak_info *target_chan_matrix = NULL;
798 	uint32_t         num_channel = (END_CHAN_INDEX - START_CHAN_INDEX) + 1;
799 	uint32_t         j = 0;
800 	uint32_t         k = 0;
801 	struct dfs_nolelem *nol;
802 
803 	nol = dfs->dfs_nol;
804 	while (nol) {
805 		if (false == dfs_find_target_channel_in_channel_matrix_for_freq(
806 					ch_width, nol->nol_freq,
807 					&target_chan_matrix)) {
808 			/*
809 			 * should never happen, we should always find a table
810 			 * here, if we don't, need a fix here!
811 			 */
812 			dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
813 				"Couldn't find target channel matrix!");
814 			QDF_ASSERT(0);
815 			return QDF_STATUS_E_FAILURE;
816 		}
817 		/*
818 		 * following is based on assumption that both temp_freq_lst
819 		 * and target channel matrix are in increasing order of
820 		 * ch_id
821 		 */
822 		for (j = 0, k = 0; j < temp_chan_lst_sz && k < num_channel;) {
823 			if (temp_freq_lst[j] == 0) {
824 				j++;
825 				continue;
826 			}
827 			if (target_chan_matrix[k].leak_chan_freq !=
828 			    temp_freq_lst[j]) {
829 				k++;
830 				continue;
831 			}
832 			/*
833 			 * check leakage from candidate channel
834 			 * to NOL channel
835 			 */
836 			if (target_chan_matrix[k].leak_lvl <=
837 				dfs->tx_leakage_threshold) {
838 				/*
839 				 * candidate channel will have
840 				 * bad leakage in NOL channel,
841 				 * remove from temp list
842 				 */
843 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
844 					"dfs: channel: %d will have bad leakage due to channel: %d\n",
845 					nol->nol_freq, temp_freq_lst[j]);
846 				temp_freq_lst[j] = 0;
847 			}
848 			j++;
849 			k++;
850 		}
851 		nol = nol->nol_next;
852 	} /* end of loop that selects each NOL */
853 
854 	return QDF_STATUS_SUCCESS;
855 }
856 #endif
857 #else
858 #ifdef CONFIG_CHAN_FREQ_API
859 QDF_STATUS
dfs_mark_leaking_chan_for_freq(struct wlan_dfs * dfs,enum phy_ch_width ch_width,uint8_t temp_chan_lst_sz,uint16_t * temp_freq_lst)860 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs,
861 			     enum phy_ch_width ch_width,
862 			     uint8_t temp_chan_lst_sz,
863 			     uint16_t *temp_freq_lst)
864 {
865 	return QDF_STATUS_SUCCESS;
866 }
867 #endif
868 #endif
869 
870 /*
871  * dfs_populate_80mhz_available_channel_for_freq() - Populate 80MHZ channels
872  * available for selection.
873  * @dfs: Pointer to wlan_dfs.
874  * @bitmap: Pointer to bonding channel bitmap.
875  * @avail_freq_list: Pointer to frequency list of available channels.
876  */
877 #ifdef CONFIG_CHAN_FREQ_API
dfs_populate_80mhz_available_channel_for_freq(struct wlan_dfs * dfs,struct chan_bonding_bitmap * bitmap,uint16_t * avail_freq_list)878 static uint8_t dfs_populate_80mhz_available_channel_for_freq(
879 		struct wlan_dfs *dfs,
880 		struct chan_bonding_bitmap *bitmap,
881 		uint16_t *avail_freq_list)
882 {
883 	uint8_t i = 0;
884 	uint8_t chnl_count = 0;
885 	uint16_t start_chan_freq = 0;
886 
887 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
888 		start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq;
889 		if (bitmap->chan_bonding_set[i].chan_map ==
890 			DFS_80MHZ_MASK) {
891 			avail_freq_list[chnl_count++] = start_chan_freq +
892 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0);
893 			avail_freq_list[chnl_count++] = start_chan_freq +
894 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1);
895 			avail_freq_list[chnl_count++] = start_chan_freq +
896 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2);
897 			avail_freq_list[chnl_count++] = start_chan_freq +
898 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3);
899 		}
900 	}
901 
902 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
903 		 "channel count %d", chnl_count);
904 
905 	return chnl_count;
906 }
907 #endif
908 
909 #ifdef CONFIG_CHAN_FREQ_API
910 static uint8_t
dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs * dfs,struct chan_bonding_bitmap * bmap,uint16_t * avail_freq_list)911 dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs *dfs,
912 					      struct chan_bonding_bitmap *bmap,
913 					      uint16_t *avail_freq_list)
914 {
915 	uint8_t i = 0;
916 	uint8_t chnl_count = 0;
917 	uint16_t start_chan_freq = 0;
918 
919 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
920 		start_chan_freq = bmap->chan_bonding_set[i].start_chan_freq;
921 		if ((bmap->chan_bonding_set[i].chan_map &
922 			DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) {
923 			avail_freq_list[chnl_count++] = start_chan_freq +
924 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0);
925 			avail_freq_list[chnl_count++] = start_chan_freq +
926 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1);
927 		}
928 		if ((bmap->chan_bonding_set[i].chan_map &
929 			DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) {
930 			avail_freq_list[chnl_count++] = start_chan_freq +
931 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2);
932 			avail_freq_list[chnl_count++] = start_chan_freq +
933 				(DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3);
934 		}
935 	}
936 
937 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
938 		 "channel count %d", chnl_count);
939 
940 	return chnl_count;
941 }
942 #endif
943 
944 /**
945  * dfs_populate_available_channel_for_freq()- Populate channels based on width
946  * and bitmap.
947  * @dfs: Pointer to DFS structure.
948  * @bitmap: bitmap
949  * @chan_width: channel width
950  * @freq_list: prepared channel list
951  *
952  * Prepare channel list based on width and channel bitmap.
953  *
954  * Return: channel count
955  */
956 #ifdef CONFIG_CHAN_FREQ_API
957 static uint8_t
dfs_populate_available_channel_for_freq(struct wlan_dfs * dfs,struct chan_bonding_bitmap * bitmap,uint16_t chan_width,uint16_t * freq_list)958 dfs_populate_available_channel_for_freq(struct wlan_dfs *dfs,
959 					struct chan_bonding_bitmap *bitmap,
960 					uint16_t chan_width,
961 					uint16_t *freq_list)
962 {
963 	switch (chan_width) {
964 	case DFS_CH_WIDTH_320MHZ:
965 	case DFS_CH_WIDTH_160MHZ:
966 	case DFS_CH_WIDTH_80P80MHZ:
967 	case DFS_CH_WIDTH_80MHZ:
968 		return dfs_populate_80mhz_available_channel_for_freq(dfs,
969 								     bitmap,
970 								     freq_list);
971 	case DFS_CH_WIDTH_40MHZ:
972 		return dfs_populate_40mhz_available_channel_for_freq(dfs,
973 								     bitmap,
974 								     freq_list);
975 	default:
976 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
977 			"Invalid chan_width %d", chan_width);
978 		break;
979 	}
980 
981 	return 0;
982 }
983 #endif
984 
985 /**
986  * dfs_get_rand_from_lst_for_freq()- Get random channel from a given channel
987  * list.
988  * @dfs: Pointer to DFS structure.
989  * @freq_lst: Frequency list
990  * @num_chan: number of channels
991  *
992  * Get random channel from given channel list.
993  *
994  * Return: channel frequency.
995  */
996 
997 #ifdef CONFIG_CHAN_FREQ_API
dfs_get_rand_from_lst_for_freq(struct wlan_dfs * dfs,uint16_t * freq_lst,uint8_t num_chan)998 static uint16_t dfs_get_rand_from_lst_for_freq(struct wlan_dfs *dfs,
999 					       uint16_t *freq_lst,
1000 					       uint8_t num_chan)
1001 {
1002 	uint8_t i;
1003 	uint32_t rand_byte = 0;
1004 
1005 	if (!num_chan || !freq_lst) {
1006 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
1007 			"invalid param freq_lst %pK, num_chan = %d",
1008 			freq_lst, num_chan);
1009 		return 0;
1010 	}
1011 
1012 	get_random_bytes((uint8_t *)&rand_byte, 1);
1013 	i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_chan;
1014 
1015 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1016 		 "random chan freq %d", freq_lst[i]);
1017 
1018 	return freq_lst[i];
1019 }
1020 #endif
1021 
1022 #ifdef CONFIG_CHAN_FREQ_API
1023 #define FREQUENCY_BAND_LIMIT 60
1024 
1025 /**
1026  * dfs_random_channel_sel_set_bitmap_for_freq()- Set channel bit in bitmap based
1027  * on given channel number
1028  * @dfs: Pointer to DFS structure.
1029  * @bitmap: bitmap
1030  * @chan_freq: channel frequency
1031  *
1032  * Set channel bit in bitmap based on given channel frequency.
1033  *
1034  * Return: None
1035  */
1036 static void
dfs_random_channel_sel_set_bitmap_for_freq(struct wlan_dfs * dfs,struct chan_bonding_bitmap * bitmap,uint16_t chan_freq)1037 dfs_random_channel_sel_set_bitmap_for_freq(struct wlan_dfs *dfs,
1038 					   struct chan_bonding_bitmap *bitmap,
1039 					   uint16_t chan_freq)
1040 {
1041 	int i = 0;
1042 	int start_chan_freq = 0;
1043 
1044 	for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) {
1045 		start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq;
1046 		if (chan_freq >= start_chan_freq &&
1047 		    chan_freq <= start_chan_freq +
1048 		    FREQUENCY_BAND_LIMIT) {
1049 			bitmap->chan_bonding_set[i].chan_map |=
1050 				(1 << ((chan_freq - start_chan_freq) /
1051 				       DFS_80_NUM_SUB_CHANNEL_FREQ));
1052 			return;
1053 		}
1054 	}
1055 
1056 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1057 		  "Frequency=%d is not in the bitmap", chan_freq);
1058 }
1059 #endif
1060 
1061 #ifdef CONFIG_BAND_6GHZ
1062 /**
1063  * dfs_assign_6g_channels()- Assign the center frequency of the first 20 MHZ
1064  * channel in every 80MHz channel, present in the 6G band.
1065  * @ch_map: Pointer to ch_map.
1066  *
1067  * Return: Void
1068  */
dfs_assign_6g_channels(struct chan_bonding_bitmap * ch_map)1069 static void dfs_assign_6g_channels(struct  chan_bonding_bitmap *ch_map)
1070 {
1071 	ch_map->chan_bonding_set[7].start_chan_freq = 5955;
1072 	ch_map->chan_bonding_set[8].start_chan_freq = 6035;
1073 	ch_map->chan_bonding_set[9].start_chan_freq = 6115;
1074 	ch_map->chan_bonding_set[10].start_chan_freq = 6195;
1075 	ch_map->chan_bonding_set[11].start_chan_freq = 6275;
1076 	ch_map->chan_bonding_set[12].start_chan_freq = 6355;
1077 	ch_map->chan_bonding_set[13].start_chan_freq = 6435;
1078 	ch_map->chan_bonding_set[14].start_chan_freq = 6515;
1079 	ch_map->chan_bonding_set[15].start_chan_freq = 6595;
1080 	ch_map->chan_bonding_set[16].start_chan_freq = 6675;
1081 	ch_map->chan_bonding_set[17].start_chan_freq = 6755;
1082 	ch_map->chan_bonding_set[18].start_chan_freq = 6835;
1083 	ch_map->chan_bonding_set[19].start_chan_freq = 6915;
1084 	ch_map->chan_bonding_set[20].start_chan_freq = 6995;
1085 }
1086 #else
dfs_assign_6g_channels(struct chan_bonding_bitmap * ch_map)1087 static inline void dfs_assign_6g_channels(struct  chan_bonding_bitmap *ch_map)
1088 {
1089 }
1090 #endif
1091 
1092 /**
1093  * dfs_find_num_sub_channels_for_chwidth_320_160() - Find the max number
1094  * of sub channels for the given channel width (320/160)
1095  * @chan_width: Channel width
1096  *
1097  * Return - Number of sub-channels
1098  */
1099 static uint8_t
dfs_find_num_sub_channels_for_chwidth_320_160(uint16_t chan_width)1100 dfs_find_num_sub_channels_for_chwidth_320_160(uint16_t chan_width)
1101 {
1102 	if (chan_width == DFS_CH_WIDTH_160MHZ)
1103 		return DFS_MAX_NUM_160_SUBCHAN;
1104 	else if (chan_width == DFS_CH_WIDTH_320MHZ)
1105 		return DFS_MAX_NUM_240_SUBCHAN;
1106 
1107 	return 0;
1108 }
1109 
1110 /**
1111  * dfs_find_next_chan_start_freq_for_320_160() - Find the next 160/320 channel's
1112  * start freq based on the available channel list. Validate the
1113  * continuity of the sub channels of 160/320M BW, if they are contiguous
1114  * declare channel to be found. Return the start_freq of the channel band found.
1115  * @chan_count: Total number of available channels.
1116  * @freq_list: Available list of frequency
1117  * @chan_width: Target channel width
1118  * @chan_found: Bool to indicate if channel is found
1119  *
1120  * Return: Next chan's start freq
1121  */
1122 
1123 static qdf_freq_t
dfs_find_next_chan_start_freq_for_320_160(uint8_t chan_count,uint16_t * freq_list,uint16_t chan_width,bool * chan_found)1124 dfs_find_next_chan_start_freq_for_320_160(uint8_t chan_count,
1125 					  uint16_t *freq_list,
1126 					  uint16_t chan_width, bool *chan_found)
1127 {
1128 	uint8_t i;
1129 	uint8_t count = 0;
1130 	qdf_freq_t next_chan_start_freq = 0;
1131 	uint8_t num_sub_chans =
1132 		dfs_find_num_sub_channels_for_chwidth_320_160(chan_width);
1133 
1134 	for (i = 1; i < chan_count; i++) {
1135 		if ((freq_list[i] - freq_list[i - 1]) ==
1136 		    DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET)
1137 			count++;
1138 		else
1139 			count = 0;
1140 		if (count == num_sub_chans - 1) {
1141 			*chan_found = true;
1142 			next_chan_start_freq = freq_list[i - count];
1143 			break;
1144 		}
1145 	}
1146 	return next_chan_start_freq;
1147 }
1148 
1149 /**
1150  * dfs_find_ch_with_fallback_for_freq()- find random channel
1151  * @dfs: Pointer to DFS structure.
1152  * @chan_wd: channel width
1153  * @center_freq_seg1: center frequency of secondary segment.
1154  * @freq_lst: list of available frequency.
1155  * @num_chan: number of channels in the list.
1156  *
1157  * Find random channel based on given channel width and channel list,
1158  * fallback to lower width if requested channel width not available.
1159  *
1160  * Return: channel frequency.
1161  */
1162 #ifdef CONFIG_CHAN_FREQ_API
dfs_find_ch_with_fallback_for_freq(struct wlan_dfs * dfs,uint16_t * chan_wd,qdf_freq_t * center_freq_seg1,uint16_t * freq_lst,uint32_t num_chan)1163 static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
1164 						   uint16_t *chan_wd,
1165 						   qdf_freq_t *center_freq_seg1,
1166 						   uint16_t *freq_lst,
1167 						   uint32_t num_chan)
1168 {
1169 	bool flag = false;
1170 	uint32_t rand_byte = 0;
1171 	struct  chan_bonding_bitmap ch_map = { { {0} } };
1172 	uint8_t i, index = 0, final_cnt = 0;
1173 	uint16_t target_channel = 0;
1174 	uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_start_ch = 0;
1175 	uint16_t final_lst[NUM_CHANNELS] = {0};
1176 
1177 	/* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */
1178 	ch_map.chan_bonding_set[0].start_chan_freq = 5180;
1179 	ch_map.chan_bonding_set[1].start_chan_freq = 5260;
1180 	ch_map.chan_bonding_set[2].start_chan_freq = 5500;
1181 	ch_map.chan_bonding_set[3].start_chan_freq = 5580;
1182 	ch_map.chan_bonding_set[4].start_chan_freq = 5660;
1183 	ch_map.chan_bonding_set[5].start_chan_freq = 5745;
1184 	ch_map.chan_bonding_set[6].start_chan_freq = 5825;
1185 
1186 	dfs_assign_6g_channels(&ch_map);
1187 	for (i = 0; i < num_chan; i++) {
1188 		dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1189 			  "channel = %d added to bitmap", freq_lst[i]);
1190 		dfs_random_channel_sel_set_bitmap_for_freq(dfs, &ch_map,
1191 							   freq_lst[i]);
1192 	}
1193 
1194 	/* populate available channel list from bitmap */
1195 	final_cnt = dfs_populate_available_channel_for_freq(dfs, &ch_map,
1196 							    *chan_wd, final_lst);
1197 
1198 	/* If no valid 80mhz bonded chan found, fallback */
1199 	if (final_cnt == 0) {
1200 		if ((*chan_wd == DFS_CH_WIDTH_320MHZ) ||
1201 		    (*chan_wd == DFS_CH_WIDTH_160MHZ) ||
1202 		    (*chan_wd == DFS_CH_WIDTH_80P80MHZ) ||
1203 		    (*chan_wd == DFS_CH_WIDTH_80MHZ)) {
1204 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1205 				 "from [%d] to 40Mhz", *chan_wd);
1206 			*chan_wd = DFS_CH_WIDTH_40MHZ;
1207 		} else if (*chan_wd == DFS_CH_WIDTH_40MHZ) {
1208 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1209 				 "from 40Mhz to 20MHz");
1210 			*chan_wd = DFS_CH_WIDTH_20MHZ;
1211 		}
1212 		return 0;
1213 	}
1214 
1215 	/* ch count should be > 8 to switch new channel in 160Mhz band */
1216 	if (((*chan_wd == DFS_CH_WIDTH_160MHZ) ||
1217 	     (*chan_wd == DFS_CH_WIDTH_80P80MHZ)) &&
1218 	     (final_cnt < DFS_MAX_NUM_160_SUBCHAN)) {
1219 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1220 			 "from [%d] to 80Mhz", *chan_wd);
1221 		*chan_wd = DFS_CH_WIDTH_80MHZ;
1222 		return 0;
1223 	}
1224 
1225 	/* ch count should be 12 to switch new 320 channel band (240MHZ) */
1226 	if (*chan_wd == DFS_CH_WIDTH_320MHZ) {
1227 		if (final_cnt < DFS_MAX_NUM_240_SUBCHAN) {
1228 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1229 				 "from [%d] to 160Mhz", *chan_wd);
1230 			*chan_wd = DFS_CH_WIDTH_160MHZ;
1231 			return 0;
1232 		}
1233 	}
1234 
1235 	if (*chan_wd == DFS_CH_WIDTH_320MHZ ||
1236 	    *chan_wd == DFS_CH_WIDTH_160MHZ) {
1237 		/*
1238 		 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128
1239 		 * and all the channels in these blocks are continuous
1240 		 * and separated by 4Mhz.
1241 		 * Only 1 block of 240 channel is
1242 		 * available from 100 - 140 comprising of 12 sub 20 channels.
1243 		 * These are continuous and separated by 20MHZ in
1244 		 * frequency spectrum.
1245 		 */
1246 		new_start_ch =
1247 		    dfs_find_next_chan_start_freq_for_320_160(final_cnt,
1248 							      final_lst,
1249 							      *chan_wd,
1250 							      &flag);
1251 	} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
1252 		flag = true;
1253 	}
1254 
1255 	if (!flag) {
1256 		if (*chan_wd == DFS_CH_WIDTH_320MHZ) {
1257 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1258 				 "from [%d] to 160Mhz", *chan_wd);
1259 			*chan_wd = DFS_CH_WIDTH_160MHZ;
1260 			return 0;
1261 		} else if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
1262 			dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1263 				 "from [%d] to 80Mhz", *chan_wd);
1264 			*chan_wd = DFS_CH_WIDTH_80MHZ;
1265 			return 0;
1266 		}
1267 	}
1268 
1269 	if (*chan_wd == DFS_CH_WIDTH_320MHZ ||
1270 	    *chan_wd == DFS_CH_WIDTH_160MHZ) {
1271 		get_random_bytes((uint8_t *)&rand_byte, 1);
1272 		rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks())
1273 			% dfs_find_num_sub_channels_for_chwidth_320_160
1274 			(*chan_wd);
1275 		target_channel = new_start_ch + (rand_byte *
1276 				DFS_80_NUM_SUB_CHANNEL_FREQ);
1277 	} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
1278 		get_random_bytes((uint8_t *)&rand_byte, 1);
1279 		index = (rand_byte + qdf_mc_timer_get_system_ticks()) %
1280 			final_cnt;
1281 		target_channel = final_lst[index];
1282 		index -= (index % DFS_80_NUM_SUB_CHANNEL);
1283 		primary_seg_start_ch = final_lst[index];
1284 
1285 		/* reset channels associate with primary 80Mhz */
1286 		for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++)
1287 			final_lst[i + index] = 0;
1288 		/* select and calculate center freq for secondary segment */
1289 		for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) {
1290 			if (final_lst[i * DFS_80_NUM_SUB_CHANNEL] &&
1291 			    (abs(primary_seg_start_ch -
1292 				 final_lst[i * DFS_80_NUM_SUB_CHANNEL]) >
1293 			     (DFS_80P80M_FREQ_DIFF * 2))) {
1294 				sec_seg_ch = final_lst[i *
1295 					DFS_80_NUM_SUB_CHANNEL] +
1296 					DFS_80MHZ_START_CENTER_CH_FREQ_DIFF;
1297 				break;
1298 			}
1299 		}
1300 
1301 		if (!sec_seg_ch && (final_cnt == DFS_MAX_NUM_160_SUBCHAN))
1302 			*chan_wd = DFS_CH_WIDTH_160MHZ;
1303 		else if (!sec_seg_ch)
1304 			*chan_wd = DFS_CH_WIDTH_80MHZ;
1305 
1306 		*center_freq_seg1 = sec_seg_ch;
1307 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1308 			 "Center frequency seg1 = %d", sec_seg_ch);
1309 	} else {
1310 		target_channel = dfs_get_rand_from_lst_for_freq(dfs,
1311 								final_lst,
1312 								final_cnt);
1313 	}
1314 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1315 		 "target channel = %d", target_channel);
1316 
1317 	return target_channel;
1318 }
1319 #endif
1320 
dfs_is_freq_in_nol(struct wlan_dfs * dfs,uint32_t freq)1321 bool dfs_is_freq_in_nol(struct wlan_dfs *dfs, uint32_t freq)
1322 {
1323 	struct dfs_nolelem *nol;
1324 
1325 	if (!dfs) {
1326 		dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,  "null dfs");
1327 		return false;
1328 	}
1329 
1330 	nol = dfs->dfs_nol;
1331 	while (nol) {
1332 		if (freq == nol->nol_freq) {
1333 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1334 					"%d is in nol", freq);
1335 			return true;
1336 		}
1337 		nol = nol->nol_next;
1338 	}
1339 
1340 	return false;
1341 }
1342 
1343 /**
1344  * dfs_apply_rules_for_freq()- prepare channel list based on flags
1345  * @dfs: dfs handler
1346  * @flags: channel flags
1347  * @random_chan_freq_list: output channel list
1348  * @random_chan_cnt: output channel count
1349  * @chan_list: input channel list
1350  * @chan_cnt: input channel count
1351  * @dfs_region: dfs region
1352  * @acs_info: acs channel range information
1353  *
1354  * prepare channel list based on flags
1355  *
1356  * return: none
1357  */
1358 #ifdef CONFIG_CHAN_FREQ_API
dfs_apply_rules_for_freq(struct wlan_dfs * dfs,uint32_t flags,uint16_t * random_chan_freq_list,uint32_t * random_chan_cnt,struct dfs_channel * chan_list,uint32_t chan_cnt,uint8_t dfs_region,struct dfs_acs_info * acs_info)1359 static void dfs_apply_rules_for_freq(struct wlan_dfs *dfs,
1360 				     uint32_t flags,
1361 				     uint16_t *random_chan_freq_list,
1362 				     uint32_t *random_chan_cnt,
1363 				     struct dfs_channel *chan_list,
1364 				     uint32_t chan_cnt,
1365 				     uint8_t dfs_region,
1366 				     struct dfs_acs_info *acs_info)
1367 {
1368 	struct dfs_channel *chan;
1369 	bool flag_no_weather = 0;
1370 	bool flag_no_lower_5g = 0;
1371 	bool flag_no_upper_5g = 0;
1372 	bool flag_no_dfs_chan = 0;
1373 	bool flag_no_2g_chan  = 0;
1374 	bool flag_no_5g_chan  = 0;
1375 	bool flag_no_japan_w53 = 0;
1376 	bool flag_no_6g_freq;
1377 	int i;
1378 	bool found = false;
1379 	uint16_t j;
1380 	uint16_t freq_list[MAX_20MHZ_SUBCHANS];
1381 	uint8_t num_channels = 0;
1382 
1383 	dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags);
1384 	flag_no_weather = (dfs_region == DFS_ETSI_REGION) ?
1385 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1386 
1387 	if (dfs_region == DFS_MKK_REGION ||
1388 	    dfs_region == DFS_MKKN_REGION) {
1389 		flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH;
1390 		flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH;
1391 		flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH;
1392 	}
1393 
1394 	flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH;
1395 	flag_no_2g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH;
1396 	flag_no_5g_chan  = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH;
1397 	flag_no_6g_freq = flags & DFS_RANDOM_CH_FLAG_NO_6GHZ_CH;
1398 
1399 	if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) {
1400 		num_channels =
1401 			dfs_get_bonding_channel_without_seg_info_for_freq
1402 			(dfs->dfs_curchan, freq_list);
1403 	}
1404 
1405 	for (i = 0; i < chan_cnt; i++) {
1406 		chan = &chan_list[i];
1407 		found = false;
1408 
1409 		if ((chan->dfs_ch_ieee == 0) ||
1410 		    (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) {
1411 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1412 				  "invalid channel %d", chan->dfs_ch_ieee);
1413 			continue;
1414 		}
1415 
1416 		if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) {
1417 			for (j = 0; j < num_channels; j++) {
1418 				if (chan->dfs_ch_freq == freq_list[j]) {
1419 					dfs_debug(dfs,
1420 						  WLAN_DEBUG_DFS_RANDOM_CHAN,
1421 						  "skip %d current operating channel",
1422 						  chan->dfs_ch_freq);
1423 					found = true;
1424 					break;
1425 				}
1426 			}
1427 
1428 			if (found)
1429 				continue;
1430 		}
1431 
1432 		if (acs_info && acs_info->acs_mode) {
1433 			for (j = 0; j < acs_info->num_of_channel; j++) {
1434 				if (acs_info->chan_freq_list[j] ==
1435 				    chan->dfs_ch_freq) {
1436 					found = true;
1437 					break;
1438 				}
1439 			}
1440 
1441 			if (!found) {
1442 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1443 					  "skip ch freq %d not in acs range",
1444 					  chan->dfs_ch_freq);
1445 				continue;
1446 			}
1447 			found = false;
1448 		}
1449 
1450 		if (flag_no_2g_chan &&
1451 		    chan->dfs_ch_freq <= DFS_MAX_24GHZ_CHANNEL_FREQ) {
1452 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1453 				  "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee);
1454 			continue;
1455 		}
1456 
1457 		if (flag_no_5g_chan &&
1458 		    WLAN_REG_IS_5GHZ_CH_FREQ(chan->dfs_ch_freq)) {
1459 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1460 				  "skip 5 GHz channel=%d", chan->dfs_ch_ieee);
1461 			continue;
1462 		}
1463 
1464 		if (flag_no_weather) {
1465 			if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) {
1466 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1467 					  "skip weather channel=%d",
1468 					  chan->dfs_ch_ieee);
1469 				continue;
1470 			}
1471 		}
1472 
1473 		if (flag_no_lower_5g &&
1474 		    DFS_IS_CHAN_JAPAN_INDOOR_FREQ(chan->dfs_ch_freq)) {
1475 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1476 				  "skip indoor channel=%d", chan->dfs_ch_ieee);
1477 			continue;
1478 		}
1479 
1480 		if (flag_no_upper_5g &&
1481 		    DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(chan->dfs_ch_freq)) {
1482 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1483 				  "skip outdoor channel=%d", chan->dfs_ch_ieee);
1484 			continue;
1485 		}
1486 
1487 		if (flag_no_6g_freq &&
1488 		    WLAN_REG_IS_6GHZ_CHAN_FREQ(chan->dfs_ch_freq)) {
1489 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1490 				  "skip 6 GHz channel=%d", chan->dfs_ch_ieee);
1491 			continue;
1492 		}
1493 
1494 		if (flag_no_dfs_chan &&
1495 		    (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) {
1496 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1497 				  "skip dfs channel=%d", chan->dfs_ch_ieee);
1498 			continue;
1499 		}
1500 
1501 		if (flag_no_japan_w53 &&
1502 		    DFS_IS_CHAN_JAPAN_W53_FREQ(chan->dfs_ch_freq)) {
1503 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1504 				  "skip japan W53 channel=%d",
1505 				  chan->dfs_ch_ieee);
1506 			continue;
1507 		}
1508 
1509 		if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) {
1510 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1511 				  "skip nol channel=%d", chan->dfs_ch_ieee);
1512 			continue;
1513 		}
1514 
1515 		random_chan_freq_list[*random_chan_cnt] = chan->dfs_ch_freq;
1516 		*random_chan_cnt += 1;
1517 	}
1518 }
1519 #endif
1520 
1521 /**
1522  * dfs_remove_spruce_spur_channels_for_bw_20_40() - API to remove the
1523  * spur channels in spruce if current bw is 20/40MHz.
1524  * @freq_list: Input list from which spur channels are removed.
1525  * @freq_count: Input list count.
1526  *
1527  * return: void.
1528  */
1529 static void
dfs_remove_spruce_spur_channels_for_bw_20_40(uint16_t * freq_list,uint8_t freq_count)1530 dfs_remove_spruce_spur_channels_for_bw_20_40(uint16_t *freq_list,
1531 					     uint8_t freq_count)
1532 {
1533 	uint8_t i;
1534 
1535 	for (i = 0; i < freq_count; i++) {
1536 		if (DFS_IS_CHAN_SPRUCE_SPUR_FREQ_20_40_MHZ(freq_list[i]))
1537 			freq_list[i] = 0;
1538 	}
1539 }
1540 
1541 #ifdef CONFIG_CHAN_FREQ_API
dfs_prepare_random_channel_for_freq(struct wlan_dfs * dfs,struct dfs_channel * chan_list,uint32_t chan_cnt,uint32_t flags,struct ch_params * chan_params,uint8_t dfs_region,struct dfs_acs_info * acs_info)1542 uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs,
1543 					     struct dfs_channel *chan_list,
1544 					     uint32_t chan_cnt,
1545 					     uint32_t flags,
1546 					     struct ch_params *chan_params,
1547 					     uint8_t dfs_region,
1548 					     struct dfs_acs_info *acs_info)
1549 {
1550 	int i = 0;
1551 	uint8_t final_cnt = 0;
1552 	uint16_t target_freq = 0;
1553 	uint16_t *random_chan_freq_list = NULL;
1554 	uint32_t random_chan_cnt = 0;
1555 	uint16_t flag_no_weather = 0;
1556 	uint16_t *leakage_adjusted_lst;
1557 	uint16_t final_lst[NUM_CHANNELS] = {0};
1558 	uint16_t *chan_wd = (uint16_t *)&chan_params->ch_width;
1559 	bool flag_no_spur_leakage_adj_chans = false;
1560 
1561 	if (!chan_list || !chan_cnt) {
1562 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1563 			 "Invalid params %pK, chan_cnt=%d",
1564 			 chan_list, chan_cnt);
1565 		return 0;
1566 	}
1567 
1568 	if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_320MHZ) {
1569 		dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1570 			 "Invalid chan_wd %d", *chan_wd);
1571 		return 0;
1572 	}
1573 
1574 	random_chan_freq_list =
1575 	    qdf_mem_malloc(chan_cnt * sizeof(*random_chan_freq_list));
1576 	if (!random_chan_freq_list)
1577 		return 0;
1578 
1579 	dfs_apply_rules_for_freq(dfs, flags, random_chan_freq_list,
1580 				 &random_chan_cnt, chan_list, chan_cnt,
1581 				 dfs_region, acs_info);
1582 	flag_no_weather = (dfs_region == DFS_ETSI_REGION) ?
1583 		flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0;
1584 	flag_no_spur_leakage_adj_chans =
1585 	    flags & DFS_RANDOM_CH_FLAG_NO_SPRUCE_SPUR_ADJ_CH;
1586 
1587 	/* list adjusted after leakage has been marked */
1588 	leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt *
1589 					      sizeof(*leakage_adjusted_lst));
1590 	if (!leakage_adjusted_lst) {
1591 		qdf_mem_free(random_chan_freq_list);
1592 		return 0;
1593 	}
1594 
1595 	if (flag_no_spur_leakage_adj_chans &&
1596 	    (*chan_wd == DFS_CH_WIDTH_20MHZ ||
1597 	     *chan_wd == DFS_CH_WIDTH_40MHZ))
1598 		dfs_remove_spruce_spur_channels_for_bw_20_40(
1599 				random_chan_freq_list,
1600 				random_chan_cnt);
1601 	do {
1602 		int ret;
1603 
1604 		qdf_mem_copy(leakage_adjusted_lst, random_chan_freq_list,
1605 			     random_chan_cnt * sizeof(*leakage_adjusted_lst));
1606 		ret = dfs_mark_leaking_chan_for_freq(dfs, *chan_wd,
1607 						   random_chan_cnt,
1608 						   leakage_adjusted_lst);
1609 		if (QDF_IS_STATUS_ERROR(ret)) {
1610 			qdf_mem_free(random_chan_freq_list);
1611 			qdf_mem_free(leakage_adjusted_lst);
1612 			return 0;
1613 		}
1614 
1615 		if (*chan_wd == DFS_CH_WIDTH_20MHZ) {
1616 			/*
1617 			 * PASS: 3 - from leakage_adjusted_lst, prepare valid
1618 			 * ch list and use random number from that
1619 			 */
1620 			for (i = 0; i < random_chan_cnt; i++) {
1621 				if (leakage_adjusted_lst[i] == 0)
1622 					continue;
1623 				dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1624 					  "Chan freq =%d added to available list",
1625 					  leakage_adjusted_lst[i]);
1626 				final_lst[final_cnt] = leakage_adjusted_lst[i];
1627 				final_cnt++;
1628 			}
1629 			target_freq = dfs_get_rand_from_lst_for_freq(dfs,
1630 								     final_lst,
1631 								     final_cnt);
1632 			break;
1633 		}
1634 		target_freq = dfs_find_ch_with_fallback_for_freq(
1635 				dfs, chan_wd, &chan_params->mhz_freq_seg1,
1636 				leakage_adjusted_lst, random_chan_cnt);
1637 
1638 		/* Since notion of 80+80 is not present in the regulatory
1639 		 * channel the function may return invalid 80+80 channels for
1640 		 * some devices (e.g. Pine). Therefore, check if we need to
1641 		 * correct it by checking the following condition.
1642 		 */
1643 		if ((*chan_wd == DFS_CH_WIDTH_80P80MHZ) &&
1644 		    (flags & DFS_RANDOM_CH_FLAG_RESTRICTED_80P80_ENABLED) &&
1645 		    target_freq) {
1646 			wlan_reg_set_channel_params_for_pwrmode(
1647 						dfs->dfs_pdev_obj,
1648 						target_freq,
1649 						0, chan_params,
1650 						REG_CURRENT_PWR_MODE);
1651 			if (!(CHAN_WITHIN_RESTRICTED_80P80(
1652 						chan_params->mhz_freq_seg0,
1653 						chan_params->mhz_freq_seg1))) {
1654 				*chan_wd = DFS_CH_WIDTH_160MHZ;
1655 				target_freq =
1656 				    dfs_find_ch_with_fallback_for_freq(
1657 					    dfs, chan_wd,
1658 					    &chan_params->mhz_freq_seg1,
1659 					    leakage_adjusted_lst,
1660 					    random_chan_cnt);
1661 			}
1662 		}
1663 
1664 		/*
1665 		 * When flag_no_weather is set, avoid usage of Adjacent
1666 		 * weather radar channel in HT40 mode as extension channel
1667 		 * will be on 5600.
1668 		 */
1669 		if (flag_no_weather &&
1670 		    (target_freq ==
1671 		     DFS_ADJACENT_WEATHER_RADAR_CHANNEL_FREQ) &&
1672 		    (*chan_wd == DFS_CH_WIDTH_40MHZ)) {
1673 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1674 				  "skip weather adjacent ch freq =%d\n",
1675 				  target_freq);
1676 			continue;
1677 		}
1678 
1679 		/*
1680 		 * Spur or leakage transmissions is observed in Spruce HW in
1681 		 * frequencies from 5260MHz to 5320MHz when one of the following
1682 		 * conditions is true,
1683 		 * i) The AP is transmitting in 52/56/60/64 in 80MHz mode and
1684 		 * then the AP moves to the adjacent channel 36/44/48 in 80MHz
1685 		 * mode and starts transmitting.
1686 		 * ii) The AP is transmitting in 36/44/48/52/56/60/64 in 160MHz
1687 		 * mode and then the  AP moves to the adjacent channel 36/44/48
1688 		 * in 80MHz mode and starts transmitting.
1689 		 *
1690 		 * The random channel selection algorithm prevents the channel
1691 		 * movement mentioned above, thereby eliminating the leakage.
1692 		 */
1693 		if (flag_no_spur_leakage_adj_chans &&
1694 		    DFS_IS_SPRUCE_SPUR_AVOID_FREQS(target_freq) &&
1695 		    *chan_wd == DFS_CH_WIDTH_80MHZ) {
1696 			dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
1697 				  "skip spruce spur causing (adjacent) channel=%hu",
1698 				  target_freq);
1699 			continue;
1700 		}
1701 
1702 		if (target_freq)
1703 			break;
1704 	} while (true);
1705 
1706 	qdf_mem_free(random_chan_freq_list);
1707 	qdf_mem_free(leakage_adjusted_lst);
1708 	dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_freq = %d",
1709 		 target_freq);
1710 
1711 	return target_freq;
1712 }
1713 #endif
1714