xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.c (revision 876f765030b53bdf9f91327d1a20e5800c335361)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: reg_opclass.c
22  * This file defines regulatory opclass functions.
23  */
24 
25 #include <qdf_types.h>
26 #include <wlan_cmn.h>
27 #include <reg_services_public_struct.h>
28 #include <wlan_objmgr_psoc_obj.h>
29 #include <wlan_objmgr_pdev_obj.h>
30 #include "reg_priv_objs.h"
31 #include "reg_utils.h"
32 #include "reg_db.h"
33 #include "reg_db_parser.h"
34 #include "reg_host_11d.h"
35 #include <scheduler_api.h>
36 #include "reg_build_chan_list.h"
37 #include "reg_opclass.h"
38 #include "reg_services_common.h"
39 #include <wlan_objmgr_pdev_obj.h>
40 
41 #ifdef HOST_OPCLASS
42 static struct reg_dmn_supp_op_classes reg_dmn_curr_supp_opp_classes = { 0 };
43 #endif
44 
45 /*
46  * Given a global opclass number create the corresponding  array token.
47  * Examples:
48  *     'CFISARR(132)' expands to  'opcls_132_cfis_arr'
49  *     'CFISARR(133)' expands to  'opcls_133_cfis_arr'
50  */
51 #define CFISARR(_g_opcls)  opcls_ ## _g_opcls ## _cfis_arr
52 
53 /*
54  * Given a global opclass number create the corresponding list token.
55  * Examples:
56  *     'CFISLST(132)' expands to  'opcls_132_cfis_lst'
57  *     'CFISLST(133)' expands to  'opcls_133_cfis_lst'
58  */
59 #define CFISLST(_g_opcls)  opcls_ ## _g_opcls ## _cfis_lst
60 
61 /* The type of the opclass list objects */
62 #define CFISLST_TYPE static const struct c_freq_lst
63 
64 /* The number of elements of the array */
65 #define NELEMS QDF_ARRAY_SIZE
66 
67 /*
68  * Given a global opclass number create the corresponding cfis list and assign
69  * the corresponding cfis array and size of the cfis array
70  * Examples:
71  *     'CREATE_CFIS_LST(132);'
72  *     expands to
73  *     '
74  *     static const struct c_freq_lst opcls_132_cfis_lst =
75  *                   {QDF_ARRAY_SIZE(opcls_132_cfis_arr), opcls_132_cfis_arr};
76  *     '
77  *
78  *     'CREATE_CFIS_LST(133);'
79  *     expands to
80  *     '
81  *     static const struct c_freq_lst opcls_133_cfis_lst =
82  *                   {QDF_ARRAY_SIZE(opcls_133_cfis_arr), opcls_133_cfis_arr};
83  *     '
84  */
85 #define CREATE_CFIS_LST(_gopcls) \
86 CFISLST_TYPE CFISLST(_gopcls) = {NELEMS(CFISARR(_gopcls)), CFISARR(_gopcls)}
87 
88 /* The NULL pointer to a cfis list object */
89 #define NULL_CFIS_LST NULL
90 
91 /* CFIs for global opclass 131: (start Freq=5925 BW=20MHz) */
92 static const uint8_t opcls_131_cfis_arr[] = {
93 #ifdef CONFIG_AFC_SUPPORT
94 	  1, 5, 9, 13, 17, 21, 25, 29, 33,
95 	  37, 41, 45, 49, 53, 57, 61, 65, 69,
96 	  73, 77, 81, 85, 89, 93, 97,
97 	  101, 105, 109, 113, 117, 121, 125,
98 	  129, 133, 137, 141, 145, 149, 153,
99 	  157, 161, 165, 169, 173, 177, 181,
100 	  185, 189, 193, 197, 201, 205, 209,
101 	  213, 217, 221, 225, 229, 233,
102 #endif
103 };
104 
105 /* CFIs for global opclass 132: (start Freq=5925 BW=40MHz) */
106 static const uint8_t opcls_132_cfis_arr[] = {
107 #ifdef CONFIG_AFC_SUPPORT
108 	3, 11, 19, 27, 35, 43, 51, 59, 67, 75,
109 	83, 91, 99, 107, 115, 123, 131, 139, 147, 155,
110 	163, 171, 179, 187, 195, 203, 211, 219, 227,
111 #endif
112 };
113 
114 /* CFIs for global opclass 133: (start Freq=5925 BW=80MHz) */
115 static const uint8_t opcls_133_cfis_arr[] = {
116 #ifdef CONFIG_AFC_SUPPORT
117 	7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183,
118 	  199, 215,
119 #endif
120 };
121 
122 /* CFIs for global opclass 134: (start Freq=5950 BW=160MHz) */
123 static const uint8_t opcls_134_cfis_arr[] = {
124 #ifdef CONFIG_AFC_SUPPORT
125 	15, 47, 79, 111, 143, 175, 207,
126 #endif
127 };
128 
129 /* CFIs for global opclass 135: (start Freq=5950 BW=80MHz+80MHz) */
130 static const uint8_t opcls_135_cfis_arr[] = {
131 #ifdef CONFIG_AFC_SUPPORT
132 	7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183,
133 	199, 215,
134 #endif
135 };
136 
137 /* CFIs for global opclass 136: (start Freq=5925 BW=20MHz) */
138 static const uint8_t opcls_136_cfis_arr[] = {
139 #ifdef CONFIG_AFC_SUPPORT
140 	2,
141 #endif
142 };
143 
144 /* CFIs for global opclass 137: (start Freq=5950 BW=320MHz) */
145 #ifdef WLAN_FEATURE_11BE
146 static const uint8_t opcls_137_cfis_arr[] = {
147 #ifdef CONFIG_AFC_SUPPORT
148 	31, 63, 95, 127, 159, 191,
149 #endif
150 };
151 #endif
152 
153 /* Create the CFIS static constant lists */
154 CREATE_CFIS_LST(131);
155 CREATE_CFIS_LST(132);
156 CREATE_CFIS_LST(133);
157 CREATE_CFIS_LST(134);
158 CREATE_CFIS_LST(135);
159 CREATE_CFIS_LST(136);
160 #ifdef WLAN_FEATURE_11BE
161 CREATE_CFIS_LST(137);
162 #endif
163 
164 static const struct reg_dmn_op_class_map_t global_op_class[] = {
165 	{81, 25, BW20, BIT(BEHAV_NONE), 2407,
166 	 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
167 	 NULL_CFIS_LST },
168 	{82, 25, BW20, BIT(BEHAV_NONE), 2414,
169 	 {14},
170 	 NULL_CFIS_LST },
171 	{83, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407,
172 	 {1, 2, 3, 4, 5, 6, 7, 8, 9},
173 	 NULL_CFIS_LST },
174 	{84, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407,
175 	 {5, 6, 7, 8, 9, 10, 11, 12, 13},
176 	 NULL_CFIS_LST },
177 	{115, 20, BW20, BIT(BEHAV_NONE), 5000,
178 	 {36, 40, 44, 48},
179 	 NULL_CFIS_LST },
180 	{116, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
181 	 {36, 44},
182 	 NULL_CFIS_LST },
183 	{117, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
184 	 {40, 48},
185 	 NULL_CFIS_LST },
186 	{118, 20, BW20, BIT(BEHAV_NONE), 5000,
187 	 {52, 56, 60, 64},
188 	 NULL_CFIS_LST },
189 	{119, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
190 	 {52, 60},
191 	 NULL_CFIS_LST },
192 	{120, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
193 	 {56, 64},
194 	 NULL_CFIS_LST },
195 	{121, 20, BW20, BIT(BEHAV_NONE), 5000,
196 	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144},
197 	 NULL_CFIS_LST },
198 	{122, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
199 	 {100, 108, 116, 124, 132, 140},
200 	 NULL_CFIS_LST },
201 	{123, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
202 	 {104, 112, 120, 128, 136, 144},
203 	 NULL_CFIS_LST },
204 	{125, 20, BW20, BIT(BEHAV_NONE), 5000,
205 	 {149, 153, 157, 161, 165, 169, 173, 177},
206 	 NULL_CFIS_LST },
207 	{126, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
208 	 {149, 157, 165, 173},
209 	 NULL_CFIS_LST },
210 	{127, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
211 	 {153, 161, 169, 177},
212 	 NULL_CFIS_LST },
213 	{128, 80, BW80, BIT(BEHAV_NONE), 5000,
214 	 {36, 40, 44, 48, 52, 56, 60, 64,
215 	  100, 104, 108, 112, 116, 120, 124, 128,
216 	  132, 136, 140, 144, 149, 153, 157, 161,
217 	  165, 169, 173, 177},
218 	  NULL_CFIS_LST },
219 	{129, 160, BW80, BIT(BEHAV_NONE), 5000,
220 	 {36, 40, 44, 48, 52, 56, 60, 64,
221 	  100, 104, 108, 112, 116, 120, 124, 128,
222 	  149, 153, 157, 161, 165, 169, 173, 177},
223 	 NULL_CFIS_LST },
224 	{130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000,
225 	 {36, 40, 44, 48, 52, 56, 60, 64,
226 	  100, 104, 108, 112, 116, 120, 124, 128,
227 	  132, 136, 140, 144, 149, 153, 157, 161,
228 	  165, 169, 173, 177},
229 	 NULL_CFIS_LST },
230 
231 #ifdef CONFIG_BAND_6GHZ
232 	{131, 20, BW20, BIT(BEHAV_NONE), 5950,
233 	 {1, 5, 9, 13, 17, 21, 25, 29, 33,
234 	  37, 41, 45, 49, 53, 57, 61, 65, 69,
235 	  73, 77, 81, 85, 89, 93, 97,
236 	  101, 105, 109, 113, 117, 121, 125,
237 	  129, 133, 137, 141, 145, 149, 153,
238 	  157, 161, 165, 169, 173, 177, 181,
239 	  185, 189, 193, 197, 201, 205, 209,
240 	  213, 217, 221, 225, 229, 233},
241 	&CFISLST(131)},
242 
243 	{132, 40, BW40_LOW_PRIMARY, BIT(BEHAV_NONE), 5950,
244 	 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49,
245 	  53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
246 	  101, 105, 109, 113, 117, 121, 125, 129, 133, 137,
247 	  141, 145, 149, 153, 157, 161, 165, 169, 173, 177,
248 	  181, 185, 189, 193, 197, 201, 205, 209, 213, 217,
249 	  221, 225, 229, 233},
250 	&CFISLST(132)},
251 
252 	{133, 80, BW80, BIT(BEHAV_NONE), 5950,
253 	 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49,
254 	  53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
255 	  101, 105, 109, 113, 117, 121, 125, 129, 133, 137,
256 	  141, 145, 149, 153, 157, 161, 165, 169, 173,
257 	  177, 181, 185, 189, 193, 197, 201, 205, 209, 213,
258 	  217, 221, 225, 229, 233},
259 	&CFISLST(133)},
260 
261 	{134, 160, BW80, BIT(BEHAV_NONE), 5950,
262 	 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45,
263 	  49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89,
264 	  93, 97, 101, 105, 109, 113, 117, 121, 125,
265 	  129, 133, 137, 141, 145, 149, 153, 157, 161,
266 	  165, 169, 173, 177, 181, 185, 189, 193, 197,
267 	     201, 205, 209, 213, 217, 221, 225, 229, 233},
268 	&CFISLST(134)},
269 
270 	{135, 80, BW80, BIT(BEHAV_BW80_PLUS), 5950,
271 	 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41,
272 	  45, 49, 53, 57, 61, 65, 69, 73, 77, 81,
273 	  85, 89, 93, 97, 101, 105, 109, 113, 117,
274 	  121, 125, 129, 133, 137, 141, 145, 149,
275 	  153, 157, 161, 165, 169, 173, 177, 181,
276 	  185, 189, 193, 197, 201, 205, 209, 213,
277 	  217, 221, 225, 229, 233},
278 	&CFISLST(135)},
279 
280 	{136, 20, BW20, BIT(BEHAV_NONE), 5925,
281 	 {2},
282 	&CFISLST(136)},
283 #ifdef WLAN_FEATURE_11BE
284 	{137, 320, BW20, BIT(BEHAV_NONE), 5950,
285 	 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41,
286 	  45, 49, 53, 57, 61, 65, 69, 73, 77, 81,
287 	  85, 89, 93, 97, 101, 105, 109, 113, 117,
288 	  121, 125, 129, 133, 137, 141, 145, 149,
289 	  153, 157, 161, 165, 169, 173, 177, 181,
290 	  185, 189, 193, 197, 201, 205, 209, 213,
291 	  217, 221, 225, 229, 233},
292 	&CFISLST(137)},
293 #endif
294 #endif
295 	{0, 0, 0, 0, 0, {0},
296 	NULL_CFIS_LST },
297 };
298 
299 static const struct reg_dmn_op_class_map_t us_op_class[] = {
300 	{1, 20, BW20, BIT(BEHAV_NONE), 5000,
301 	 {36, 40, 44, 48},
302 	 NULL_CFIS_LST },
303 	{2, 20, BW20, BIT(BEHAV_NONE), 5000,
304 	 {52, 56, 60, 64},
305 	 NULL_CFIS_LST },
306 	{4, 20, BW20, BIT(BEHAV_NONE), 5000,
307 	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144},
308 	 NULL_CFIS_LST },
309 	{5, 20, BW20, BIT(BEHAV_NONE), 5000,
310 	 {149, 153, 157, 161, 165},
311 	 NULL_CFIS_LST },
312 	{12, 25, BW20, BIT(BEHAV_NONE), 2407,
313 	 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
314 	 NULL_CFIS_LST },
315 	{22, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
316 	 {36, 44},
317 	 NULL_CFIS_LST },
318 	{23, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
319 	 {52, 60},
320 	 NULL_CFIS_LST },
321 	{24, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
322 	 {100, 108, 116, 124, 132, 140},
323 	 NULL_CFIS_LST },
324 	{26, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
325 	 {149, 157},
326 	 NULL_CFIS_LST },
327 	{27, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
328 	 {40, 48},
329 	 NULL_CFIS_LST },
330 	{28, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
331 	 {56, 64},
332 	 NULL_CFIS_LST },
333 	{29, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
334 	 {104, 112, 120, 128, 136, 144},
335 	 NULL_CFIS_LST },
336 	{30, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
337 	 {153, 161},
338 	 NULL_CFIS_LST },
339 	{31, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
340 	 {153, 161},
341 	 NULL_CFIS_LST },
342 	{32, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407,
343 	 {1, 2, 3, 4, 5, 6, 7},
344 	 NULL_CFIS_LST },
345 	{33, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407,
346 	 {5, 6, 7, 8, 9, 10, 11},
347 	 NULL_CFIS_LST },
348 	{128, 80, BW80, BIT(BEHAV_NONE), 5000,
349 	 {36, 40, 44, 48, 52, 56, 60, 64, 100,
350 	  104, 108, 112, 116, 120, 124, 128, 132,
351 	  136, 140, 144, 149, 153, 157, 161},
352 	 NULL_CFIS_LST },
353 	{129, 160, BW80, BIT(BEHAV_NONE), 5000,
354 	 {36, 40, 44, 48, 52, 56, 60, 64, 100,
355 	  104, 108, 112, 116, 120, 124, 128},
356 	 NULL_CFIS_LST },
357 	{130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000,
358 	 {36, 40, 44, 48, 52, 56, 60, 64, 100,
359 	  104, 108, 112, 116, 120, 124, 128, 132,
360 	  136, 140, 144, 149, 153, 157, 161},
361 	 NULL_CFIS_LST },
362 	{0, 0, 0, 0, 0, {0},
363 	 NULL_CFIS_LST },
364 };
365 
366 static const struct reg_dmn_op_class_map_t euro_op_class[] = {
367 	{1, 20, BW20, BIT(BEHAV_NONE), 5000,
368 	 {36, 40, 44, 48},
369 	 NULL_CFIS_LST },
370 	{2, 20, BW20, BIT(BEHAV_NONE), 5000,
371 	 {52, 56, 60, 64},
372 	 NULL_CFIS_LST },
373 	{3, 20, BW20, BIT(BEHAV_NONE), 5000,
374 	 {100, 104, 108, 112, 116, 120,
375 	  124, 128, 132, 136, 140},
376 	 NULL_CFIS_LST },
377 	{4, 25, BW20, BIT(BEHAV_NONE), 2407,
378 	 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
379 	 NULL_CFIS_LST },
380 	{5, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
381 	 {36, 44},
382 	 NULL_CFIS_LST },
383 	{6, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
384 	 {52, 60},
385 	 NULL_CFIS_LST },
386 	{7, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
387 	 {100, 108, 116, 124, 132},
388 	 NULL_CFIS_LST },
389 	{8, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
390 	 {40, 48},
391 	 NULL_CFIS_LST },
392 	{9, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
393 	 {56, 64},
394 	 NULL_CFIS_LST },
395 	{10, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
396 	 {104, 112, 120, 128, 136},
397 	 NULL_CFIS_LST },
398 	{11, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407,
399 	 {1, 2, 3, 4, 5, 6, 7, 8, 9},
400 	 NULL_CFIS_LST },
401 	{12, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407,
402 	 {5, 6, 7, 8, 9, 10, 11, 12, 13},
403 	 NULL_CFIS_LST },
404 	{17, 20, BW20, BIT(BEHAV_NONE), 5000,
405 	 {149, 153, 157, 161, 165, 169},
406 	 NULL_CFIS_LST },
407 	{128, 80, BW80, BIT(BEHAV_NONE), 5000,
408 	 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
409 	  124, 128},
410 	 NULL_CFIS_LST },
411 	{129, 160, BW80, BIT(BEHAV_NONE), 5000,
412 	 {36, 40, 44, 48, 52, 56, 60, 64, 100,
413 	  104, 108, 112, 116, 120, 124, 128},
414 	 NULL_CFIS_LST },
415 	{130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000,
416 	 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
417 	  124, 128},
418 	 NULL_CFIS_LST },
419 	{0, 0, 0, 0, 0, {0},
420 	 NULL_CFIS_LST },
421 };
422 
423 static const struct reg_dmn_op_class_map_t japan_op_class[] = {
424 	{1, 20, BW20, BIT(BEHAV_NONE), 5000,
425 	 {36, 40, 44, 48},
426 	 NULL_CFIS_LST },
427 	{30, 25, BW20, BIT(BEHAV_NONE), 2407,
428 	 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
429 	 NULL_CFIS_LST },
430 	{31, 25, BW20, BIT(BEHAV_NONE), 2414,
431 	 {14},
432 	 NULL_CFIS_LST },
433 	{32, 20, BW20, BIT(BEHAV_NONE), 5000,
434 	 {52, 56, 60, 64},
435 	 NULL_CFIS_LST },
436 	{34, 20, BW20, BIT(BEHAV_NONE), 5000,
437 	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140},
438 	 NULL_CFIS_LST },
439 	{36, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
440 	 {36, 44},
441 	 NULL_CFIS_LST },
442 	{37, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
443 	 {52, 60},
444 	 NULL_CFIS_LST },
445 	{39, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
446 	 {100, 108, 116, 124, 132},
447 	 NULL_CFIS_LST },
448 	{41, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
449 	 {40, 48},
450 	 NULL_CFIS_LST },
451 	{42, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
452 	 {56, 64},
453 	 NULL_CFIS_LST },
454 	{44, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
455 	 {104, 112, 120, 128, 136},
456 	 NULL_CFIS_LST },
457 	{128, 80, BW80, BIT(BEHAV_NONE), 5000,
458 	 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
459 	  124, 128, 132, 136, 140, 144},
460 	 NULL_CFIS_LST },
461 	{129, 160, BW80, BIT(BEHAV_NONE), 5000,
462 	 {36, 40, 44, 48, 52, 56, 60, 64, 100,
463 	  104, 108, 112, 116, 120, 124, 128},
464 	 NULL_CFIS_LST },
465 	{130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000,
466 	 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
467 	  124, 128, 132, 136, 140, 144},
468 	 NULL_CFIS_LST },
469 	{0, 0, 0, 0, 0, {0},
470 	 NULL_CFIS_LST },
471 };
472 
473 static const struct reg_dmn_op_class_map_t china_op_class[] = {
474 	{7, 25, BW20, BIT(BEHAV_NONE), 2407,
475 	 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
476 	 NULL_CFIS_LST },
477 	{8, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407,
478 	 {1, 2, 3, 4, 5, 6, 7, 8, 9},
479 	 NULL_CFIS_LST },
480 	{9, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407,
481 	 {5, 6, 7, 8, 9, 10, 11, 12, 13},
482 	 NULL_CFIS_LST },
483 	{1, 20, BW20, BIT(BEHAV_NONE), 5000,
484 	 {36, 40, 44, 48},
485 	 NULL_CFIS_LST },
486 	{4, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
487 	 {36, 44},
488 	 NULL_CFIS_LST },
489 	{117, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000,
490 	 {40, 48},
491 	 NULL_CFIS_LST },
492 	{2, 20, BW20, BIT(BEHAV_NONE), 5000,
493 	 {52, 56, 60, 64},
494 	 NULL_CFIS_LST },
495 	{5, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
496 	 {52, 60},
497 	 NULL_CFIS_LST },
498 	{3, 20, BW20, BIT(BEHAV_NONE), 5000,
499 	 {149, 153, 157, 161, 165},
500 	 NULL_CFIS_LST },
501 	{6, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000,
502 	 {149, 157},
503 	 NULL_CFIS_LST },
504 	{128, 80, BW80, BIT(BEHAV_NONE), 5000,
505 	 {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161},
506 	 NULL_CFIS_LST },
507 	{129, 160, BW80, BIT(BEHAV_NONE), 5000,
508 	 {36, 40, 44, 48, 52, 56, 60, 64,},
509 	 NULL_CFIS_LST },
510 	{130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000,
511 	 {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161},
512 	 NULL_CFIS_LST },
513 	{0, 0, 0, 0, 0, {0},
514 	 NULL_CFIS_LST },
515 };
516 #ifdef HOST_OPCLASS
517 /**
518  * reg_get_class_from_country()- Get Class from country
519  * @country: Country
520  *
521  * Return: class.
522  */
523 static const struct reg_dmn_op_class_map_t
524 *reg_get_class_from_country(const uint8_t *country)
525 {
526 	const struct reg_dmn_op_class_map_t *class = NULL;
527 
528 	if (!country)
529 		return global_op_class;
530 
531 	reg_debug_rl("Country %c%c 0x%x", country[0], country[1], country[2]);
532 
533 	switch (country[2]) {
534 	case OP_CLASS_US:
535 		class = us_op_class;
536 		break;
537 
538 	case OP_CLASS_EU:
539 		class = euro_op_class;
540 		break;
541 
542 	case OP_CLASS_JAPAN:
543 		class = japan_op_class;
544 		break;
545 
546 	case OP_CLASS_GLOBAL:
547 		class = global_op_class;
548 		break;
549 
550 	case OP_CLASS_CHINA:
551 		class = china_op_class;
552 		break;
553 	default:
554 		if (!qdf_mem_cmp(country, "US", 2))
555 			class = us_op_class;
556 		else if (!qdf_mem_cmp(country, "EU", 2))
557 			class = euro_op_class;
558 		else if (!qdf_mem_cmp(country, "JP", 2))
559 			class = japan_op_class;
560 		else if (!qdf_mem_cmp(country, "CN", 2))
561 			class = china_op_class;
562 		else
563 			class = global_op_class;
564 	}
565 	return class;
566 }
567 
568 #ifdef CONFIG_AFC_SUPPORT
569 static bool reg_is_range_valid(struct freq_range *range)
570 {
571 	return (range->right > range->left);
572 }
573 
574 /**
575  * reg_is_subrange() - Check if range_first is a subrange of range_second
576  * @range_first: Pointer to first range
577  * @range_second: Pointer to first range
578  *
579  * Return: True if the range_first is a subrange range_second, else false
580  */
581 static bool reg_is_subrange(struct freq_range *range_first,
582 			    struct freq_range *range_second)
583 {
584 	bool is_subrange;
585 	bool is_valid;
586 
587 	is_valid = reg_is_range_valid(range_first) &&
588 		   reg_is_range_valid(range_second);
589 
590 	if (!is_valid)
591 		return false;
592 
593 	is_subrange = (range_first->left >= range_second->left) &&
594 		      (range_first->right <= range_second->right);
595 
596 	return is_subrange;
597 }
598 
599 /**
600  * reg_is_cfi_freq_in_ranges() - Check if the given 'cfi' in the any of the
601  * frequency ranges
602  * @cfi_freq: The center frequency index frequency
603  * @bw: bandwidth of the band with center freq cfi_freq
604  * @p_frange_lst: Pointer to frequency range list (AFC)
605  *
606  * return: True if the cfi is in the ranges, else false
607  */
608 static bool reg_is_cfi_freq_in_ranges(qdf_freq_t cfi_freq,
609 				      uint16_t bw,
610 				      struct wlan_afc_frange_list *p_frange_lst)
611 {
612 	uint32_t num_ranges;
613 	struct wlan_afc_freq_range_obj *p_range_objs;
614 	uint8_t i;
615 	bool is_cfi_supported = false;
616 
617 	num_ranges = p_frange_lst->num_ranges;
618 	p_range_objs = &p_frange_lst->range_objs[0];
619 	for (i = 0; i <  num_ranges; i++) {
620 		qdf_freq_t cfi_band_left;
621 		qdf_freq_t cfi_band_right;
622 		struct freq_range range_cfi;
623 		struct freq_range range_chip;
624 
625 		cfi_band_left = cfi_freq - bw / 2;
626 		cfi_band_right = cfi_freq + bw / 2;
627 
628 		range_cfi = reg_init_freq_range(cfi_band_left,
629 						cfi_band_right);
630 		range_chip = reg_init_freq_range(p_range_objs->lowfreq,
631 						 p_range_objs->highfreq);
632 		is_cfi_supported = reg_is_subrange(&range_cfi, &range_chip);
633 
634 		if (is_cfi_supported)
635 			return true;
636 
637 		p_range_objs++;
638 	}
639 
640 	return is_cfi_supported;
641 }
642 
643 void reg_dmn_free_6g_opclasses_and_channels(struct wlan_objmgr_pdev *pdev,
644 					    uint8_t num_opclasses,
645 					    uint8_t *opclass_lst,
646 					    uint8_t *chansize_lst,
647 					    uint8_t *channel_lists[])
648 {
649 	/*
650 	 * All the elements of channel_lists were allocated as a single
651 	 * allocation with 'channel_lists[0]' holding the first location of the
652 	 * allocation. Therefore, freeing only 'channel_lists[0]' is enough.
653 	 * Freeing any other 'channel_lists[i]' will result in error of freeing
654 	 * unallocated memory.
655 
656 	 */
657 	if (channel_lists)
658 		qdf_mem_free(channel_lists[0]);
659 
660 	/*
661 	 * opclass_lst, chansize_lst and channel_lists were allocated as a
662 	 * single allocation with 'opclass_lst' holding the first location of
663 	 * allocation. Therefore, freeing only 'opclass_lst' is enough.
664 	 * Freeing chansize_lst, channel_lists will result in error of freeing
665 	 * unallocated memory.
666 	 */
667 	qdf_mem_free(opclass_lst);
668 }
669 
670 /**
671  * reg_dmn_get_num_6g_opclasses() - Calculate the number of opclasses in the
672  *                                  6 GHz band.
673  * @pdev: Pointer to pdev.
674  *
675  * Return: The number of opclasses
676  */
677 static uint8_t reg_dmn_get_num_6g_opclasses(struct wlan_objmgr_pdev *pdev)
678 {
679 	const struct reg_dmn_op_class_map_t *op_class_tbl;
680 	uint8_t count;
681 
682 	op_class_tbl = global_op_class;
683 
684 	count = 0;
685 	while (op_class_tbl && op_class_tbl->op_class) {
686 		const struct c_freq_lst *p_lst;
687 
688 		p_lst = op_class_tbl->p_cfi_lst_obj;
689 		if (p_lst &&
690 		    reg_is_6ghz_op_class(pdev, op_class_tbl->op_class))
691 			count++;
692 
693 		op_class_tbl++;
694 	}
695 
696 	return count;
697 }
698 
699 /**
700  * reg_dmn_fill_cfis() - Fill the cfis for the given
701  * opclass and frequency range.
702  * @op_class_tbl: Pointer to struct reg_dmn_op_class_map_t
703  * @p_lst: Pointer to struct c_freq_lst
704  * @p_frange_lst: Pointer to struct wlan_afc_frange_list
705  * @dst: Pointer to dst buffer
706  *
707  * Return: Number of valid cfis
708  */
709 static uint8_t
710 reg_dmn_fill_cfis(const struct reg_dmn_op_class_map_t *op_class_tbl,
711 		  const struct c_freq_lst *p_lst,
712 		  struct wlan_afc_frange_list *p_frange_lst,
713 		  uint8_t *dst)
714 {
715 	uint8_t j;
716 	uint8_t cfi_idx = 0;
717 
718 	for (j = 0; j < p_lst->num_cfis; j++) {
719 		uint8_t cfi;
720 		qdf_freq_t cfi_freq;
721 		qdf_freq_t start_freq = op_class_tbl->start_freq;
722 		uint16_t bw = op_class_tbl->chan_spacing;
723 
724 		cfi = p_lst->p_cfis_arr[j];
725 		cfi_freq = start_freq + FREQ_TO_CHAN_SCALE * cfi;
726 
727 		if (reg_is_cfi_freq_in_ranges(cfi_freq, bw, p_frange_lst))
728 			dst[cfi_idx++] = cfi;
729 	}
730 	return cfi_idx;
731 }
732 
733 /**
734  * reg_dmn_fill_6g_opcls_chan_lists() - Copy the channel lists for 6g opclasses
735  * to the output argument list ('channel_lists')
736  * @pdev: Pointer to pdev.
737  * @p_frange_lst: Pointer to frequency range list (AFC)
738  * @chansize_lst: Array of sizes of channel lists
739  * @channel_lists: The array list pointers where the channel lists are to be
740  *                 copied.
741  *
742  * Return: Void
743  */
744 static void reg_dmn_fill_6g_opcls_chan_lists(struct wlan_objmgr_pdev *pdev,
745 					     struct wlan_afc_frange_list *p_frange_lst,
746 					     uint8_t chansize_lst[],
747 					     uint8_t *channel_lists[])
748 {
749 	uint8_t i = 0;
750 	const struct reg_dmn_op_class_map_t *op_class_tbl;
751 
752 	op_class_tbl = global_op_class;
753 
754 	while (op_class_tbl && op_class_tbl->op_class) {
755 		const struct c_freq_lst *p_lst;
756 
757 		p_lst = op_class_tbl->p_cfi_lst_obj;
758 		if (p_lst &&
759 		    reg_is_6ghz_op_class(pdev, op_class_tbl->op_class)) {
760 			uint8_t *dst;
761 			uint8_t num_valid_cfi = 0;
762 
763 			dst = channel_lists[i];
764 			if (!dst) {
765 				reg_debug("dest list empty\n");
766 				return;
767 			}
768 			num_valid_cfi = reg_dmn_fill_cfis(op_class_tbl, p_lst,
769 							  p_frange_lst, dst);
770 			if (num_valid_cfi)
771 				i++;
772 
773 		}
774 		op_class_tbl++;
775 	}
776 }
777 
778 QDF_STATUS reg_dmn_get_6g_opclasses_and_channels(struct wlan_objmgr_pdev *pdev,
779 						 struct wlan_afc_frange_list *p_frange_lst,
780 						 uint8_t *num_opclasses,
781 						 uint8_t **opclass_lst,
782 						 uint8_t **chansize_lst,
783 						 uint8_t **channel_lists[])
784 {
785 	const struct reg_dmn_op_class_map_t *op_class_tbl;
786 	uint8_t *l_opcls_lst;
787 	uint8_t *l_chansize_lst;
788 	uint8_t count;
789 	uint8_t i;
790 	uint8_t **arr_chan_lists;
791 	uint16_t total_alloc_size;
792 	uint16_t opcls_lst_size;
793 	uint16_t chansize_lst_size;
794 	uint16_t arr_chan_lists_size;
795 	uint8_t *p_total_alloc1;
796 	uint8_t *p_total_alloc2;
797 	uint8_t *p_temp_alloc;
798 	uint8_t n_tot_opclss;
799 
800 	*opclass_lst = NULL;
801 	*chansize_lst =  NULL;
802 	*channel_lists = NULL;
803 	*num_opclasses = 0;
804 
805 	op_class_tbl = global_op_class;
806 	n_tot_opclss = reg_dmn_get_num_6g_opclasses(pdev);
807 	opcls_lst_size = n_tot_opclss * sizeof(uint8_t);
808 	chansize_lst_size = n_tot_opclss * sizeof(uint8_t);
809 	arr_chan_lists_size = n_tot_opclss * sizeof(uint8_t *);
810 
811 	total_alloc_size = 0;
812 	total_alloc_size += opcls_lst_size
813 		+ chansize_lst_size
814 		+ arr_chan_lists_size;
815 
816 	if (!total_alloc_size) {
817 		reg_err("Number of Opclasses is zero");
818 		return QDF_STATUS_E_INVAL;
819 	}
820 
821 	p_total_alloc1 = qdf_mem_malloc(total_alloc_size);
822 	if (!p_total_alloc1) {
823 		return QDF_STATUS_E_NOMEM;
824 	}
825 
826 	 /* Assign memory locations to each pointers */
827 	p_temp_alloc = p_total_alloc1;
828 
829 	l_opcls_lst = p_temp_alloc;
830 	p_temp_alloc += opcls_lst_size;
831 
832 	l_chansize_lst = p_temp_alloc;
833 	p_temp_alloc += chansize_lst_size;
834 
835 	arr_chan_lists = (uint8_t **)p_temp_alloc;
836 
837 	/* Fill arrays with opclasses and chanlist sizes */
838 	count = 0;
839 	while (op_class_tbl && op_class_tbl->op_class) {
840 		const struct c_freq_lst *p_lst;
841 
842 		p_lst = op_class_tbl->p_cfi_lst_obj;
843 		if (p_lst &&
844 		    reg_is_6ghz_op_class(pdev, op_class_tbl->op_class)) {
845 			uint8_t n_supp_cfis = 0;
846 			uint8_t j;
847 
848 			for (j = 0; j < p_lst->num_cfis; j++) {
849 				uint8_t cfi;
850 				qdf_freq_t cfi_freq;
851 				qdf_freq_t start_freq = op_class_tbl->start_freq;
852 				uint16_t bw = op_class_tbl->chan_spacing;
853 
854 				cfi = p_lst->p_cfis_arr[j];
855 				cfi_freq = start_freq +
856 					FREQ_TO_CHAN_SCALE * cfi;
857 				if (reg_is_cfi_freq_in_ranges(cfi_freq,
858 							      bw,
859 							      p_frange_lst)) {
860 					n_supp_cfis++;
861 				}
862 			}
863 			/* Fill opclass number, num cfis and increment
864 			 * num_opclasses only if the cfi of the opclass
865 			 * is within the frequency range of interest.
866 			 */
867 			if (n_supp_cfis) {
868 				l_chansize_lst[count] = n_supp_cfis;
869 				l_opcls_lst[count] = op_class_tbl->op_class;
870 				(*num_opclasses)++;
871 				count++;
872 			}
873 		}
874 		op_class_tbl++;
875 	}
876 
877 	/* Calculate total allocation size for the array */
878 	total_alloc_size = 0;
879 	for (i = 0; i < *num_opclasses; i++)
880 		total_alloc_size += l_chansize_lst[i] * sizeof(uint8_t *);
881 
882 	if (!total_alloc_size) {
883 		reg_err("Number of Opclasses is zero");
884 		qdf_mem_free(p_total_alloc1);
885 		return QDF_STATUS_E_INVAL;
886 	}
887 
888 	p_total_alloc2 = qdf_mem_malloc(total_alloc_size);
889 	if (!p_total_alloc2) {
890 		qdf_mem_free(p_total_alloc1);
891 		return QDF_STATUS_E_NOMEM;
892 	}
893 
894 	/* Assign memory locations to each list pointers */
895 	p_temp_alloc = p_total_alloc2;
896 	for (i = 0; i < *num_opclasses; i++) {
897 		if (!l_chansize_lst[i])
898 			arr_chan_lists[i] = NULL;
899 		else
900 			arr_chan_lists[i] = p_temp_alloc;
901 
902 		p_temp_alloc += l_chansize_lst[i] * sizeof(uint8_t *);
903 	}
904 
905 	/* Fill the array with channel lists */
906 	reg_dmn_fill_6g_opcls_chan_lists(pdev, p_frange_lst, l_chansize_lst, arr_chan_lists);
907 
908 	*opclass_lst = l_opcls_lst;
909 	*chansize_lst = l_chansize_lst;
910 	*channel_lists = arr_chan_lists;
911 
912 	return QDF_STATUS_SUCCESS;
913 }
914 #endif /* CONFIG_AFC_SUPPORT */
915 
916 uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel,
917 					    uint8_t opclass)
918 {
919 	const struct reg_dmn_op_class_map_t *class;
920 	uint16_t i;
921 
922 	class = reg_get_class_from_country(country);
923 
924 	while (class->op_class) {
925 		if (opclass == class->op_class) {
926 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
927 				     class->channels[i]); i++) {
928 				if (channel == class->channels[i])
929 					return class->chan_spacing;
930 			}
931 		}
932 		class++;
933 	}
934 
935 	return 0;
936 }
937 
938 uint16_t reg_dmn_get_chanwidth_from_opclass_auto(uint8_t *country,
939 						 uint8_t channel,
940 						 uint8_t opclass)
941 {
942 	uint16_t ret;
943 	uint8_t global_country[REG_ALPHA2_LEN + 1];
944 
945 	ret = reg_dmn_get_chanwidth_from_opclass(country, channel, opclass);
946 
947 	if (!ret) {
948 		global_country[2] = OP_CLASS_GLOBAL;
949 		ret = reg_dmn_get_chanwidth_from_opclass(global_country,
950 							 channel, opclass);
951 	}
952 
953 	return ret;
954 }
955 
956 uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel,
957 					  uint8_t offset)
958 {
959 	const struct reg_dmn_op_class_map_t *class = NULL;
960 	uint16_t i = 0;
961 
962 	class = reg_get_class_from_country(country);
963 	while (class && class->op_class) {
964 		if ((offset == class->offset) || (offset == BWALL)) {
965 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
966 				     class->channels[i]); i++) {
967 				if (channel == class->channels[i])
968 					return class->op_class;
969 			}
970 		}
971 		class++;
972 	}
973 
974 	return 0;
975 }
976 
977 uint8_t reg_dmn_get_opclass_from_freq_width(uint8_t *country,
978 					    qdf_freq_t freq,
979 					    uint16_t ch_width,
980 					    uint16_t behav_limit)
981 {
982 	const struct reg_dmn_op_class_map_t *op_class_tbl = NULL;
983 	uint16_t i = 0;
984 
985 	op_class_tbl = reg_get_class_from_country(country);
986 
987 	while (op_class_tbl && op_class_tbl->op_class) {
988 		if (op_class_tbl->chan_spacing == ch_width) {
989 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
990 				     op_class_tbl->channels[i]); i++) {
991 				if ((op_class_tbl->start_freq +
992 				     (FREQ_TO_CHAN_SCALE *
993 				      op_class_tbl->channels[i]) == freq) &&
994 				    (behav_limit & op_class_tbl->behav_limit)) {
995 					return op_class_tbl->op_class;
996 				}
997 			}
998 		}
999 		op_class_tbl++;
1000 	}
1001 
1002 	return 0;
1003 }
1004 
1005 static void
1006 reg_get_band_cap_from_chan_set(const struct reg_dmn_op_class_map_t
1007 			       *op_class_tbl,
1008 			       uint8_t *supported_band)
1009 {
1010 	qdf_freq_t chan_freq = op_class_tbl->start_freq +
1011 						(op_class_tbl->channels[0] *
1012 						 FREQ_TO_CHAN_SCALE);
1013 
1014 	if (reg_is_24ghz_ch_freq(chan_freq))
1015 		*supported_band |= BIT(REG_BAND_2G);
1016 	else if (reg_is_5ghz_ch_freq(chan_freq))
1017 		*supported_band |= BIT(REG_BAND_5G);
1018 	else if (reg_is_6ghz_chan_freq(chan_freq))
1019 		*supported_band |= BIT(REG_BAND_6G);
1020 	else
1021 		reg_err_rl("Unknown band");
1022 }
1023 
1024 uint8_t reg_get_band_cap_from_op_class(const uint8_t *country,
1025 				       uint8_t num_of_opclass,
1026 				       const uint8_t *opclass)
1027 {
1028 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1029 	uint8_t supported_band = 0, opclassidx;
1030 
1031 	op_class_tbl = reg_get_class_from_country(country);
1032 
1033 	while (op_class_tbl && op_class_tbl->op_class) {
1034 		for (opclassidx = 0; opclassidx < num_of_opclass;
1035 		     opclassidx++) {
1036 			if (op_class_tbl->op_class == opclass[opclassidx]) {
1037 				reg_get_band_cap_from_chan_set(op_class_tbl,
1038 							       &supported_band);
1039 			}
1040 		}
1041 		op_class_tbl++;
1042 	}
1043 
1044 	if (!supported_band)
1045 		reg_err_rl("None of the operating classes is found");
1046 
1047 	return supported_band;
1048 }
1049 
1050 void reg_dmn_print_channels_in_opclass(uint8_t *country, uint8_t op_class)
1051 {
1052 	const struct reg_dmn_op_class_map_t *class = NULL;
1053 	uint16_t i = 0;
1054 
1055 	class = reg_get_class_from_country(country);
1056 
1057 	if (!class) {
1058 		reg_err("class is NULL");
1059 		return;
1060 	}
1061 
1062 	while (class->op_class) {
1063 		if (class->op_class == op_class) {
1064 			for (i = 0;
1065 			     (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1066 			      class->channels[i]); i++) {
1067 				reg_debug("Valid channel(%d) in requested RC(%d)",
1068 					  class->channels[i], op_class);
1069 			}
1070 			break;
1071 		}
1072 		class++;
1073 	}
1074 	if (!class->op_class)
1075 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
1076 			  "Invalid requested RC (%d)", op_class);
1077 }
1078 
1079 uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class)
1080 {
1081 	uint8_t i;
1082 
1083 	if (num_classes > REG_MAX_SUPP_OPER_CLASSES) {
1084 		reg_err("invalid num classes %d", num_classes);
1085 		return 0;
1086 	}
1087 
1088 	for (i = 0; i < num_classes; i++)
1089 		reg_dmn_curr_supp_opp_classes.classes[i] = class[i];
1090 
1091 	reg_dmn_curr_supp_opp_classes.num_classes = num_classes;
1092 
1093 	return 0;
1094 }
1095 
1096 uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class)
1097 {
1098 	uint8_t i;
1099 
1100 	if (!num_classes || !class) {
1101 		reg_err("either num_classes or class is null");
1102 		return 0;
1103 	}
1104 
1105 	for (i = 0; i < reg_dmn_curr_supp_opp_classes.num_classes; i++)
1106 		class[i] = reg_dmn_curr_supp_opp_classes.classes[i];
1107 
1108 	*num_classes = reg_dmn_curr_supp_opp_classes.num_classes;
1109 
1110 	return 0;
1111 }
1112 
1113 #ifdef CONFIG_CHAN_FREQ_API
1114 /**
1115  * reg_find_opclass_absent_in_ctry_opclss_tables() - Check Global Opclass table
1116  * when Opclass is not present in specific country.
1117  * @pdev: Pointer to pdev
1118  * @freq: Destination Frequency
1119  * @chan_width: Channel Width
1120  * @global_tbl_lookup: Global Table Lookup
1121  * @behav_limit: Behav Limit
1122  * @op_class: Pointer to Opclass
1123  * @chan_num: Pointer to Channel
1124  *
1125  * Return: Void
1126  */
1127 static void
1128 reg_find_opclass_absent_in_ctry_opclss_tables(struct wlan_objmgr_pdev *pdev,
1129 					      qdf_freq_t freq,
1130 					      uint16_t chan_width,
1131 					      bool global_tbl_lookup,
1132 					      uint16_t behav_limit,
1133 					      uint8_t *op_class,
1134 					      uint8_t *chan_num)
1135 {
1136 	if (!global_tbl_lookup && !*op_class) {
1137 		global_tbl_lookup = true;
1138 		reg_freq_width_to_chan_op_class(pdev, freq,
1139 						chan_width,
1140 						global_tbl_lookup,
1141 						behav_limit,
1142 						op_class,
1143 						chan_num);
1144 	}
1145 }
1146 
1147 static bool
1148 reg_is_country_opclass_global(struct wlan_objmgr_pdev *pdev)
1149 {
1150 	struct wlan_lmac_if_reg_tx_ops *reg_tx_ops;
1151 	struct wlan_objmgr_psoc *psoc;
1152 	uint8_t opclass_tbl_idx;
1153 
1154 	psoc = wlan_pdev_get_psoc(pdev);
1155 	if (!psoc) {
1156 		reg_err("psoc is NULL");
1157 		return false;
1158 	}
1159 
1160 	reg_tx_ops = reg_get_psoc_tx_ops(psoc);
1161 	if (!reg_tx_ops) {
1162 		reg_err("reg_tx_ops is NULL");
1163 		return false;
1164 	}
1165 
1166 	if (reg_tx_ops->get_opclass_tbl_idx) {
1167 		reg_tx_ops->get_opclass_tbl_idx(pdev, &opclass_tbl_idx);
1168 
1169 		if (opclass_tbl_idx == OP_CLASS_GLOBAL)
1170 			return true;
1171 	}
1172 
1173 	return false;
1174 }
1175 
1176 void reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev,
1177 					  qdf_freq_t freq,
1178 					  uint16_t chan_width,
1179 					  bool global_tbl_lookup,
1180 					  uint16_t behav_limit,
1181 					  uint8_t *op_class,
1182 					  uint8_t *chan_num)
1183 {
1184 	if (reg_freq_to_band(freq) == REG_BAND_6G) {
1185 		global_tbl_lookup = true;
1186 		if (chan_width == BW_40_MHZ)
1187 			behav_limit = BIT(BEHAV_NONE);
1188 	} else if (reg_is_5dot9_ghz_freq(pdev, freq)) {
1189 		global_tbl_lookup = true;
1190 	} else {
1191 		global_tbl_lookup = reg_is_country_opclass_global(pdev);
1192 	}
1193 
1194 	*op_class = 0;
1195 	reg_freq_width_to_chan_op_class(pdev, freq,
1196 					chan_width,
1197 					global_tbl_lookup,
1198 					behav_limit,
1199 					op_class,
1200 					chan_num);
1201 	reg_find_opclass_absent_in_ctry_opclss_tables(pdev, freq,
1202 						      chan_width,
1203 						      global_tbl_lookup,
1204 						      behav_limit,
1205 						      op_class,
1206 						      chan_num);
1207 }
1208 
1209 void reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev,
1210 				     qdf_freq_t freq,
1211 				     uint16_t chan_width,
1212 				     bool global_tbl_lookup,
1213 				     uint16_t behav_limit,
1214 				     uint8_t *op_class,
1215 				     uint8_t *chan_num)
1216 {
1217 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1218 	enum channel_enum chan_enum;
1219 	uint16_t i;
1220 
1221 	chan_enum = reg_get_chan_enum_for_freq(freq);
1222 
1223 	if (reg_is_chan_enum_invalid(chan_enum)) {
1224 		reg_err_rl("Invalid chan enum %d", chan_enum);
1225 		return;
1226 	}
1227 
1228 	if (global_tbl_lookup) {
1229 		op_class_tbl = global_op_class;
1230 	} else {
1231 		if (channel_map == channel_map_us)
1232 			op_class_tbl = us_op_class;
1233 		else if (channel_map == channel_map_eu)
1234 			op_class_tbl = euro_op_class;
1235 		else if (channel_map == channel_map_china)
1236 			op_class_tbl = china_op_class;
1237 		else if (channel_map == channel_map_jp)
1238 			op_class_tbl = japan_op_class;
1239 		else
1240 			op_class_tbl = global_op_class;
1241 	}
1242 
1243 	while (op_class_tbl->op_class) {
1244 		if (op_class_tbl->chan_spacing >= chan_width) {
1245 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1246 				     op_class_tbl->channels[i]); i++) {
1247 				if ((op_class_tbl->start_freq +
1248 				     FREQ_TO_CHAN_SCALE *
1249 				     op_class_tbl->channels[i] == freq) &&
1250 				    (behav_limit & op_class_tbl->behav_limit ||
1251 				     behav_limit == BIT(BEHAV_NONE))) {
1252 					*chan_num = op_class_tbl->channels[i];
1253 					*op_class = op_class_tbl->op_class;
1254 					return;
1255 				}
1256 			}
1257 		}
1258 		op_class_tbl++;
1259 	}
1260 
1261 	reg_err_rl("no op class for frequency %d", freq);
1262 }
1263 
1264 void reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev,
1265 			       qdf_freq_t freq,
1266 			       bool global_tbl_lookup,
1267 			       uint16_t behav_limit,
1268 			       uint8_t *op_class,
1269 			       uint8_t *chan_num)
1270 {
1271 	enum channel_enum chan_enum;
1272 	struct regulatory_channel *cur_chan_list;
1273 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
1274 	struct ch_params chan_params = {0};
1275 
1276 	pdev_priv_obj = reg_get_pdev_obj(pdev);
1277 
1278 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
1279 		reg_err_rl("NULL pdev reg obj");
1280 		return;
1281 	}
1282 
1283 	cur_chan_list = pdev_priv_obj->cur_chan_list;
1284 
1285 	chan_enum = reg_get_chan_enum_for_freq(freq);
1286 
1287 	if (reg_is_chan_enum_invalid(chan_enum)) {
1288 		reg_err_rl("Invalid chan enum %d", chan_enum);
1289 		return;
1290 	}
1291 
1292 	chan_params.ch_width = CH_WIDTH_MAX;
1293 	reg_set_channel_params_for_pwrmode(pdev, freq,
1294 					   0,
1295 					   &chan_params,
1296 					   REG_CURRENT_PWR_MODE, true);
1297 
1298 	reg_freq_width_to_chan_op_class(pdev, freq,
1299 					reg_get_bw_value(chan_params.ch_width),
1300 					global_tbl_lookup,
1301 					behav_limit,
1302 					op_class,
1303 					chan_num);
1304 }
1305 
1306 bool reg_is_freq_in_country_opclass(struct wlan_objmgr_pdev *pdev,
1307 				    const uint8_t country[3],
1308 				    uint8_t op_class,
1309 				    qdf_freq_t chan_freq)
1310 {
1311 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1312 	uint8_t i;
1313 
1314 	op_class_tbl = reg_get_class_from_country((uint8_t *)country);
1315 
1316 	while (op_class_tbl && op_class_tbl->op_class) {
1317 		if  (op_class_tbl->op_class == op_class) {
1318 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1319 				     op_class_tbl->channels[i]); i++) {
1320 				if (op_class_tbl->channels[i] *
1321 				    FREQ_TO_CHAN_SCALE +
1322 				    op_class_tbl->start_freq == chan_freq)
1323 					return true;
1324 			}
1325 		}
1326 		op_class_tbl++;
1327 	}
1328 	return false;
1329 }
1330 
1331 #endif
1332 
1333 uint16_t reg_get_op_class_width(struct wlan_objmgr_pdev *pdev,
1334 				uint8_t op_class,
1335 				bool global_tbl_lookup)
1336 {
1337 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1338 
1339 	if (global_tbl_lookup) {
1340 		op_class_tbl = global_op_class;
1341 	} else {
1342 		if (channel_map == channel_map_us)
1343 			op_class_tbl = us_op_class;
1344 		else if (channel_map == channel_map_eu)
1345 			op_class_tbl = euro_op_class;
1346 		else if (channel_map == channel_map_china)
1347 			op_class_tbl = china_op_class;
1348 		else if (channel_map == channel_map_jp)
1349 			op_class_tbl = japan_op_class;
1350 		else
1351 			op_class_tbl = global_op_class;
1352 	}
1353 
1354 	while (op_class_tbl->op_class) {
1355 		if  (op_class_tbl->op_class == op_class)
1356 			return op_class_tbl->chan_spacing;
1357 		op_class_tbl++;
1358 	}
1359 
1360 	return 0;
1361 }
1362 
1363 uint16_t reg_chan_opclass_to_freq(uint8_t chan,
1364 				  uint8_t op_class,
1365 				  bool global_tbl_lookup)
1366 {
1367 	const struct reg_dmn_op_class_map_t *op_class_tbl = NULL;
1368 	uint8_t i = 0;
1369 
1370 	if (global_tbl_lookup) {
1371 		op_class_tbl = global_op_class;
1372 	} else {
1373 		if (channel_map == channel_map_global) {
1374 			op_class_tbl = global_op_class;
1375 		} else if (channel_map == channel_map_us) {
1376 			op_class_tbl = us_op_class;
1377 		} else if (channel_map == channel_map_eu) {
1378 			op_class_tbl = euro_op_class;
1379 		} else if (channel_map == channel_map_china) {
1380 			op_class_tbl = china_op_class;
1381 		} else if (channel_map == channel_map_jp) {
1382 			op_class_tbl = japan_op_class;
1383 		} else {
1384 			reg_err_rl("Invalid channel map");
1385 			return 0;
1386 		}
1387 	}
1388 
1389 	while (op_class_tbl->op_class) {
1390 		if  (op_class_tbl->op_class == op_class) {
1391 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1392 				     op_class_tbl->channels[i]); i++) {
1393 				if (op_class_tbl->channels[i] == chan) {
1394 					chan = op_class_tbl->channels[i];
1395 					return op_class_tbl->start_freq +
1396 						(chan * FREQ_TO_CHAN_SCALE);
1397 				}
1398 			}
1399 			reg_err_rl("Channel not found");
1400 			return 0;
1401 		}
1402 		op_class_tbl++;
1403 	}
1404 	reg_err_rl("Invalid opclass");
1405 	return 0;
1406 }
1407 
1408 qdf_freq_t reg_chan_opclass_to_freq_auto(uint8_t chan, uint8_t op_class,
1409 					 bool global_tbl_lookup)
1410 {
1411 	if ((op_class >= MIN_6GHZ_OPER_CLASS) &&
1412 	    (op_class <= MAX_6GHZ_OPER_CLASS)) {
1413 		global_tbl_lookup = true;
1414 	} else {
1415 		qdf_freq_t freq = reg_chan_opclass_to_freq(chan,
1416 				op_class,
1417 				global_tbl_lookup);
1418 		if (freq)
1419 			return freq;
1420 		global_tbl_lookup = true;
1421 	}
1422 
1423 	return reg_chan_opclass_to_freq(chan, op_class, global_tbl_lookup);
1424 }
1425 
1426 #ifdef HOST_OPCLASS_EXT
1427 qdf_freq_t reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev,
1428 					    const uint8_t country[3],
1429 					    uint8_t chan, uint8_t op_class,
1430 					    bool strict)
1431 {
1432 	const struct reg_dmn_op_class_map_t *op_class_tbl, *op_class_tbl_org;
1433 	uint16_t i;
1434 
1435 	if (reg_is_6ghz_op_class(pdev, op_class))
1436 		op_class_tbl_org = global_op_class;
1437 	else
1438 		op_class_tbl_org =
1439 			reg_get_class_from_country((uint8_t *)country);
1440 	op_class_tbl = op_class_tbl_org;
1441 	while (op_class_tbl && op_class_tbl->op_class) {
1442 		if  (op_class_tbl->op_class == op_class) {
1443 			for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1444 				     op_class_tbl->channels[i]); i++) {
1445 				if (op_class_tbl->channels[i] == chan)
1446 					return op_class_tbl->start_freq +
1447 						(chan * FREQ_TO_CHAN_SCALE);
1448 			}
1449 		}
1450 		op_class_tbl++;
1451 	}
1452 	reg_debug_rl("Not found ch %d in op class %d ch list, strict %d",
1453 		     chan, op_class, strict);
1454 	if (strict)
1455 		return 0;
1456 
1457 	op_class_tbl = op_class_tbl_org;
1458 	while (op_class_tbl && op_class_tbl->op_class) {
1459 		for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
1460 			     op_class_tbl->channels[i]); i++) {
1461 			if (op_class_tbl->channels[i] == chan)
1462 				return op_class_tbl->start_freq +
1463 					(chan * FREQ_TO_CHAN_SCALE);
1464 		}
1465 		op_class_tbl++;
1466 	}
1467 	reg_debug_rl("Got invalid freq 0 for ch %d", chan);
1468 
1469 	return 0;
1470 }
1471 #endif
1472 
1473 static void
1474 reg_get_op_class_tbl_by_chan_map(const struct
1475 				 reg_dmn_op_class_map_t **op_class_tbl)
1476 {
1477 	if (channel_map == channel_map_us)
1478 		*op_class_tbl = us_op_class;
1479 	else if (channel_map == channel_map_eu)
1480 		*op_class_tbl = euro_op_class;
1481 	else if (channel_map == channel_map_china)
1482 		*op_class_tbl = china_op_class;
1483 	else if (channel_map == channel_map_jp)
1484 		*op_class_tbl = japan_op_class;
1485 	else
1486 		*op_class_tbl = global_op_class;
1487 }
1488 
1489 /**
1490  * reg_get_channel_cen - Calculate central channel in the channel set.
1491  *
1492  * @op_class_tbl: Pointer to op_class_tbl.
1493  * @idx: Pointer to channel index.
1494  * @num_channels: Number of channels.
1495  * @center_chan: Pointer to center channel number
1496  *
1497  * Return : void
1498  */
1499 static void reg_get_channel_cen(const struct
1500 				reg_dmn_op_class_map_t *op_class_tbl,
1501 				uint8_t *idx,
1502 				uint8_t num_channels,
1503 				uint8_t *center_chan)
1504 {
1505 	uint8_t i;
1506 	uint16_t new_chan = 0;
1507 
1508 	for (i = *idx; i < (*idx + num_channels); i++)
1509 		new_chan += op_class_tbl->channels[i];
1510 
1511 	new_chan = new_chan / num_channels;
1512 	*center_chan = new_chan;
1513 	*idx = *idx + num_channels;
1514 }
1515 
1516 /**
1517  * reg_is_chan_320mhz() - Return true if the chan width is 320MHZ,
1518  * false otherwise.
1519  * @chan_spacing: Channel spacing in MHZ.
1520  *
1521  * Return: true if chan_width is 320, false otherwise.
1522  */
1523 #ifdef WLAN_FEATURE_11BE
1524 static bool reg_is_chan_320mhz(uint16_t chan_spacing)
1525 {
1526 	if (chan_spacing == BW_320_MHZ)
1527 		return true;
1528 	return false;
1529 }
1530 #else
1531 static bool reg_is_chan_320mhz(uint16_t chan_spacing)
1532 {
1533 	return false;
1534 }
1535 #endif
1536 
1537 /**
1538  * reg_get_chan_or_chan_center - Calculate central channel in the channel set.
1539  *
1540  * @op_class_tbl: Pointer to op_class_tbl.
1541  * @idx: Pointer to channel index.
1542  *
1543  * Return : Center channel number
1544  */
1545 static uint8_t reg_get_chan_or_chan_center(const struct
1546 					   reg_dmn_op_class_map_t *op_class_tbl,
1547 					   uint8_t *idx)
1548 {
1549 	uint8_t center_chan;
1550 
1551 	if (((op_class_tbl->chan_spacing == BW_80_MHZ) &&
1552 	     (op_class_tbl->behav_limit == BIT(BEHAV_NONE))) ||
1553 	    ((op_class_tbl->chan_spacing == BW_80_MHZ) &&
1554 	     (op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)))) {
1555 		reg_get_channel_cen(op_class_tbl,
1556 				    idx,
1557 				    NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN,
1558 				    &center_chan);
1559 	} else if (op_class_tbl->chan_spacing == BW_160_MHZ) {
1560 		reg_get_channel_cen(op_class_tbl,
1561 				    idx,
1562 				    NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN,
1563 				    &center_chan);
1564 	} else if (reg_is_chan_320mhz(op_class_tbl->chan_spacing)) {
1565 		reg_get_channel_cen(op_class_tbl,
1566 				    idx,
1567 				    NUM_20_MHZ_CHAN_IN_320_MHZ_CHAN,
1568 				    &center_chan);
1569 	} else {
1570 		center_chan = op_class_tbl->channels[*idx];
1571 		*idx = *idx + 1;
1572 	}
1573 
1574 	return center_chan;
1575 }
1576 
1577 static inline qdf_freq_t reg_get_nearest_primary_freq(uint16_t bw,
1578 						      qdf_freq_t cfi_freq,
1579 						      uint8_t op_class)
1580 {
1581 	qdf_freq_t pri_freq;
1582 
1583 	if (bw <= BW_40_MHZ && op_class != OPCLS_132) {
1584 		pri_freq = cfi_freq;
1585 	} else {
1586 		if (cfi_freq >= BW_10_MHZ)
1587 			pri_freq = cfi_freq - BW_10_MHZ;
1588 		else
1589 			pri_freq = 0;
1590 	}
1591 
1592 	return pri_freq;
1593 }
1594 
1595 #ifdef WLAN_FEATURE_11BE
1596 /**
1597  * reg_is_chan_supported()- Check if given channel is supported based on its
1598  * freq provided
1599  * @pdev: Pointer to pdev
1600  * @pri_freq: Primary frequency of the input channel
1601  * @cfi_freq: cfi frequency of the input channel
1602  * @ch_width: Input channel width
1603  * @in_6g_pwr_mode: 6g power type which decides 6G channel list lookup.
1604  *
1605  * Return: True if the channel is supported, else false
1606  */
1607 static bool reg_is_chan_supported(struct wlan_objmgr_pdev *pdev,
1608 				  qdf_freq_t pri_freq,
1609 				  qdf_freq_t cfi_freq,
1610 				  enum phy_ch_width ch_width,
1611 				  enum supported_6g_pwr_types in_6g_pwr_mode)
1612 {
1613 	struct reg_channel_list chan_list = {0};
1614 	qdf_freq_t center_320;
1615 	struct ch_params ch_params = {0};
1616 
1617 	center_320 = (ch_width == CH_WIDTH_320MHZ) ? cfi_freq : 0;
1618 	reg_fill_channel_list_for_pwrmode(pdev, pri_freq, 0,
1619 					  ch_width, center_320, &chan_list,
1620 					  in_6g_pwr_mode, true);
1621 	ch_params = chan_list.chan_param[0];
1622 
1623 	if (ch_params.ch_width == ch_width)
1624 		return true;
1625 
1626 	return false;
1627 }
1628 #else
1629 static bool reg_is_chan_supported(struct wlan_objmgr_pdev *pdev,
1630 				  qdf_freq_t pri_freq,
1631 				  qdf_freq_t cfi_freq,
1632 				  enum phy_ch_width ch_width,
1633 				  enum supported_6g_pwr_types in_6g_pwr_mode)
1634 {
1635 	struct ch_params ch_params = {0};
1636 
1637 	ch_params.ch_width = ch_width;
1638 	reg_set_channel_params_for_pwrmode(pdev, pri_freq, 0, &ch_params,
1639 					   in_6g_pwr_mode, true);
1640 	if (ch_params.ch_width == ch_width)
1641 		return true;
1642 
1643 	return false;
1644 }
1645 #endif
1646 
1647 /**
1648  * reg_is_cfi_supported()- Check if given cfi is supported
1649  * @pdev: Pointer to pdev
1650  * @cfi_freq: cfi frequency
1651  * @bw: bandwidth
1652  * @op_class: op_class
1653  * @in_6g_pwr_mode: 6g power type which decides 6G channel list lookup.
1654  *
1655  * Return: True if the cfi is supported, else false
1656  */
1657 static bool reg_is_cfi_supported(struct wlan_objmgr_pdev *pdev,
1658 				 qdf_freq_t cfi_freq,
1659 				 uint16_t bw,
1660 				 uint8_t op_class,
1661 				 enum supported_6g_pwr_types in_6g_pwr_mode)
1662 {
1663 	enum phy_ch_width ch_width;
1664 	qdf_freq_t pri_freq;
1665 	bool is_cfi_supported;
1666 
1667 	ch_width = reg_find_chwidth_from_bw(bw);
1668 	pri_freq = reg_get_nearest_primary_freq(bw, cfi_freq, op_class);
1669 	is_cfi_supported = reg_is_chan_supported(pdev,
1670 						 pri_freq,
1671 						 cfi_freq,
1672 						 ch_width,
1673 						 in_6g_pwr_mode);
1674 
1675 	return is_cfi_supported;
1676 }
1677 
1678 /**
1679  * reg_get_cfis_from_opclassmap_for_6g()- Get channels from the opclass map
1680  * for 6GHz
1681  * @pdev: Pointer to pdev
1682  * @cap: Pointer to regdmn_ap_cap_opclass_t
1683  * @op_class_tbl: Pointer to op_class_tbl
1684  * @in_opclass_conf: input opclass configuration
1685  * Supported or not-supported by current HW mode
1686  * @in_6g_pwr_mode: 6g power type which decides 6G channel list lookup.
1687  *
1688  * Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
1689  * and non-supported channels for 6Ghz.
1690  *
1691  * Return: void.
1692  */
1693 static void reg_get_cfis_from_opclassmap_for_6g(
1694 			struct wlan_objmgr_pdev *pdev,
1695 			struct regdmn_ap_cap_opclass_t *cap,
1696 			const struct reg_dmn_op_class_map_t *op_class_tbl,
1697 			enum opclass_config in_opclass_conf,
1698 			enum supported_6g_pwr_types in_6g_pwr_mode)
1699 {
1700 	uint8_t n_sup_chans = 0, n_unsup_chans = 0, j;
1701 	const struct c_freq_lst *p_cfi_lst = op_class_tbl->p_cfi_lst_obj;
1702 	qdf_freq_t cfi_freq;
1703 	qdf_freq_t start_freq = op_class_tbl->start_freq;
1704 	uint16_t bw = op_class_tbl->chan_spacing;
1705 
1706 	for (j = 0; j < p_cfi_lst->num_cfis; j++) {
1707 		uint8_t cfi = p_cfi_lst->p_cfis_arr[j];
1708 		bool is_cfi_supported;
1709 
1710 		cfi_freq = start_freq + FREQ_TO_CHAN_SCALE * cfi;
1711 		is_cfi_supported = reg_is_cfi_supported(pdev,
1712 							cfi_freq,
1713 							bw,
1714 							op_class_tbl->op_class,
1715 							in_6g_pwr_mode);
1716 		if (is_cfi_supported &&
1717 		    (in_opclass_conf == OPCLASSES_SUPPORTED_BY_CUR_HWMODE ||
1718 		     in_opclass_conf == OPCLASSES_SUPPORTED_BY_DOMAIN)) {
1719 			cap->sup_chan_list[n_sup_chans++] = cfi;
1720 			cap->num_supported_chan++;
1721 		} else {
1722 			cap->non_sup_chan_list[n_unsup_chans++] = cfi;
1723 			cap->num_non_supported_chan++;
1724 		}
1725 	}
1726 }
1727 
1728 static uint16_t reg_find_nearest_ieee_bw(uint16_t spacing)
1729 {
1730 	#define SMALLEST_BW 20
1731 	return (spacing / SMALLEST_BW) * SMALLEST_BW;
1732 }
1733 
1734 /**
1735  * reg_get_cfis_from_opclassmap_for_non6g()- Get channels from the opclass map
1736  * for non-6GHz
1737  * @pdev: Pointer to pdev
1738  * @cap: Pointer to regdmn_ap_cap_opclass_t
1739  * @op_class_tbl: Pointer to op_class_tbl
1740  * @in_opclass_conf: input opclass configuration
1741  * Supported or not-supported by current HW mode
1742  * @in_6g_pwr_mode: 6g power type which decides 6G channel list lookup.
1743  *
1744  * Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
1745  * and non-supported channels for non-6Ghz.
1746  *
1747  * Return: void.
1748  */
1749 static void reg_get_cfis_from_opclassmap_for_non6g(
1750 			struct wlan_objmgr_pdev *pdev,
1751 			struct regdmn_ap_cap_opclass_t *cap,
1752 			const struct reg_dmn_op_class_map_t *op_class_tbl,
1753 			enum opclass_config in_opclass_conf,
1754 			enum supported_6g_pwr_types in_6g_pwr_mode)
1755 {
1756 	qdf_freq_t start_freq = op_class_tbl->start_freq;
1757 	uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
1758 
1759 	while (op_class_tbl->channels[chan_idx]) {
1760 		uint8_t op_cls_chan;
1761 		qdf_freq_t pri_freq;
1762 		enum phy_ch_width ch_width;
1763 		bool is_supported;
1764 		uint16_t opcls_bw;
1765 
1766 		op_cls_chan = reg_get_chan_or_chan_center(op_class_tbl,
1767 							  &chan_idx);
1768 		pri_freq = start_freq + FREQ_TO_CHAN_SCALE * op_cls_chan;
1769 		opcls_bw = reg_find_nearest_ieee_bw(op_class_tbl->chan_spacing);
1770 		ch_width = reg_find_chwidth_from_bw(opcls_bw);
1771 		pri_freq = reg_get_nearest_primary_freq(opcls_bw,
1772 							pri_freq,
1773 							op_class_tbl->op_class);
1774 		is_supported = reg_is_chan_supported(pdev,
1775 						     pri_freq,
1776 						     0,
1777 						     ch_width,
1778 						     in_6g_pwr_mode);
1779 
1780 		if (is_supported &&
1781 		    (in_opclass_conf == OPCLASSES_SUPPORTED_BY_CUR_HWMODE ||
1782 		     in_opclass_conf == OPCLASSES_SUPPORTED_BY_DOMAIN)) {
1783 			cap->sup_chan_list[n_sup_chans++] = op_cls_chan;
1784 			cap->num_supported_chan++;
1785 		} else {
1786 			cap->non_sup_chan_list[n_unsup_chans++] = op_cls_chan;
1787 			cap->num_non_supported_chan++;
1788 		}
1789 	}
1790 }
1791 
1792 /**
1793  * reg_get_channels_from_opclassmap()- Get channels from the opclass map
1794  * @pdev: Pointer to pdev
1795  * @reg_ap_cap: Pointer to reg_ap_cap
1796  * @index: Pointer to index of reg_ap_cap
1797  * @op_class_tbl: Pointer to op_class_tbl
1798  * @is_opclass_operable: Set true if opclass is operable, else set false
1799  * @in_opclass_conf: input opclass configuration
1800  * Supported or not-supported by current HW mode
1801  * @in_6g_pwr_mode: 6g power type which decides 6G channel list lookup.
1802  *
1803  * Populate channels from opclass map to reg_ap_cap as supported and
1804  * non-supported channels.
1805  *
1806  * Return: void.
1807  */
1808 static void
1809 reg_get_channels_from_opclassmap(
1810 		struct wlan_objmgr_pdev *pdev,
1811 		struct regdmn_ap_cap_opclass_t *reg_ap_cap,
1812 		uint8_t index,
1813 		const struct reg_dmn_op_class_map_t *op_class_tbl,
1814 		bool *is_opclass_operable,
1815 		enum opclass_config in_opclass_conf,
1816 		enum supported_6g_pwr_types in_6g_pwr_mode)
1817 {
1818 	struct regdmn_ap_cap_opclass_t *cap = &reg_ap_cap[index];
1819 
1820 	if (reg_is_6ghz_op_class(pdev, op_class_tbl->op_class)) {
1821 		reg_get_cfis_from_opclassmap_for_6g(pdev,
1822 						    cap,
1823 						    op_class_tbl,
1824 						    in_opclass_conf,
1825 						    in_6g_pwr_mode);
1826 	} else {
1827 		reg_get_cfis_from_opclassmap_for_non6g(pdev,
1828 						       cap,
1829 						       op_class_tbl,
1830 						       in_opclass_conf,
1831 						       in_6g_pwr_mode);
1832 	}
1833 
1834 	if (cap->num_supported_chan >= 1)
1835 		*is_opclass_operable = true;
1836 }
1837 
1838 QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
1839 				   struct regdmn_ap_cap_opclass_t *reg_ap_cap,
1840 				   uint8_t *n_opclasses,
1841 				   uint8_t max_supp_op_class,
1842 				   bool global_tbl_lookup,
1843 				   enum supported_6g_pwr_types in_6g_pwr_mode)
1844 {
1845 	uint8_t max_reg_power = 0;
1846 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1847 	uint8_t index = 0;
1848 	enum opclass_config opclass_conf = OPCLASSES_SUPPORTED_BY_DOMAIN;
1849 
1850 	if (global_tbl_lookup)
1851 		op_class_tbl = global_op_class;
1852 	else
1853 		reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
1854 
1855 	max_reg_power = reg_get_max_tx_power(pdev);
1856 
1857 	while (op_class_tbl->op_class && (index < max_supp_op_class)) {
1858 		bool is_opclass_operable = false;
1859 
1860 		qdf_mem_zero(reg_ap_cap[index].sup_chan_list,
1861 			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
1862 		reg_ap_cap[index].num_supported_chan = 0;
1863 		qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list,
1864 			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
1865 		reg_ap_cap[index].num_non_supported_chan = 0;
1866 		reg_get_channels_from_opclassmap(pdev,
1867 						 reg_ap_cap,
1868 						 index,
1869 						 op_class_tbl,
1870 						 &is_opclass_operable,
1871 						 opclass_conf,
1872 						 in_6g_pwr_mode);
1873 		if (is_opclass_operable) {
1874 			reg_ap_cap[index].op_class = op_class_tbl->op_class;
1875 			reg_ap_cap[index].ch_width =
1876 						op_class_tbl->chan_spacing;
1877 			reg_ap_cap[index].start_freq =
1878 						op_class_tbl->start_freq;
1879 			reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power;
1880 			reg_ap_cap[index].behav_limit =
1881 						op_class_tbl->behav_limit;
1882 			index++;
1883 		}
1884 
1885 		op_class_tbl++;
1886 	}
1887 
1888 	*n_opclasses = index;
1889 
1890 	return QDF_STATUS_SUCCESS;
1891 }
1892 
1893 bool reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, uint8_t op_class)
1894 {
1895 	return ((op_class >= MIN_6GHZ_OPER_CLASS) &&
1896 		(op_class <= MAX_6GHZ_OPER_CLASS));
1897 }
1898 
1899 /**
1900  * reg_is_opclass_band_found() - Check if the input opclass is 2G or 5G.
1901  * @country: Pointer to country.
1902  * @op_class: Operating class.
1903  * @bandmask: Bitmask for band.
1904  *
1905  * Return : Return true if the input opclass' band (2Ghz or 5Ghz) matches one
1906  * of bandmask's band.
1907  */
1908 static bool reg_is_opclass_band_found(const uint8_t *country,
1909 				      uint8_t op_class,
1910 				      uint8_t bandmask)
1911 {
1912 	const struct reg_dmn_op_class_map_t *op_class_tbl;
1913 
1914 	op_class_tbl = reg_get_class_from_country((uint8_t *)country);
1915 
1916 	while (op_class_tbl && op_class_tbl->op_class) {
1917 		if (op_class_tbl->op_class == op_class) {
1918 			qdf_freq_t freq = op_class_tbl->start_freq +
1919 			(op_class_tbl->channels[0] * FREQ_TO_CHAN_SCALE);
1920 
1921 			if ((bandmask & BIT(REG_BAND_5G)) &&
1922 			    REG_IS_5GHZ_FREQ(freq))
1923 				return true;
1924 
1925 			if ((bandmask & BIT(REG_BAND_2G)) &&
1926 			    REG_IS_24GHZ_CH_FREQ(freq))
1927 				return true;
1928 
1929 			return false;
1930 		}
1931 
1932 		op_class_tbl++;
1933 	}
1934 
1935 	reg_err_rl("Opclass %d is not found", op_class);
1936 
1937 	return false;
1938 }
1939 
1940 bool reg_is_5ghz_op_class(const uint8_t *country, uint8_t op_class)
1941 {
1942 	return reg_is_opclass_band_found(country, op_class, BIT(REG_BAND_5G));
1943 }
1944 
1945 bool reg_is_2ghz_op_class(const uint8_t *country, uint8_t op_class)
1946 {
1947 	return reg_is_opclass_band_found(country, op_class, BIT(REG_BAND_2G));
1948 }
1949 
1950 /**
1951  * reg_convert_chan_spacing_to_width() - Convert channel spacing to
1952  * channel width.
1953  * @chan_spacing: Channel spacing
1954  * @opclass_chwidth: Opclass channel width
1955  *
1956  * Return: None
1957  */
1958 #ifdef WLAN_FEATURE_11BE
1959 static void reg_convert_chan_spacing_to_width(uint16_t chan_spacing,
1960 					      uint16_t *opclass_chwidth)
1961 {
1962 	switch (chan_spacing) {
1963 	case BW_20_MHZ:
1964 	case BW_25_MHZ:
1965 		*opclass_chwidth = BW_20_MHZ;
1966 		break;
1967 	case BW_40_MHZ:
1968 		*opclass_chwidth = BW_40_MHZ;
1969 		break;
1970 	case BW_80_MHZ:
1971 		*opclass_chwidth = BW_80_MHZ;
1972 		break;
1973 	case BW_160_MHZ:
1974 		*opclass_chwidth = BW_160_MHZ;
1975 		break;
1976 	case BW_320_MHZ:
1977 		*opclass_chwidth = BW_320_MHZ;
1978 		break;
1979 	default:
1980 		*opclass_chwidth = 0;
1981 	}
1982 }
1983 #else
1984 static void reg_convert_chan_spacing_to_width(uint16_t chan_spacing,
1985 					      uint16_t *opclass_chwidth)
1986 {
1987 	switch (chan_spacing) {
1988 	case BW_20_MHZ:
1989 	case BW_25_MHZ:
1990 		*opclass_chwidth = BW_20_MHZ;
1991 		break;
1992 	case BW_40_MHZ:
1993 		*opclass_chwidth = BW_40_MHZ;
1994 		break;
1995 	case BW_80_MHZ:
1996 		*opclass_chwidth = BW_80_MHZ;
1997 		break;
1998 	case BW_160_MHZ:
1999 		*opclass_chwidth = BW_160_MHZ;
2000 		break;
2001 	default:
2002 		*opclass_chwidth = 0;
2003 	}
2004 }
2005 #endif
2006 
2007 QDF_STATUS
2008 reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
2009 			       struct regdmn_ap_cap_opclass_t *reg_ap_cap,
2010 			       uint8_t *n_opclasses,
2011 			       uint8_t max_supp_op_class,
2012 			       bool global_tbl_lookup,
2013 			       enum phy_ch_width max_chwidth,
2014 			       bool is_80p80_supp,
2015 			       enum supported_6g_pwr_types in_6g_pwr_mode)
2016 {
2017 	uint8_t max_reg_power = 0;
2018 	const struct reg_dmn_op_class_map_t *op_class_tbl;
2019 	uint8_t index = 0;
2020 	uint16_t out_width;
2021 
2022 	if (global_tbl_lookup)
2023 		op_class_tbl = global_op_class;
2024 	else
2025 		reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
2026 
2027 	max_reg_power = reg_get_max_tx_power(pdev);
2028 
2029 	out_width = reg_get_bw_value(max_chwidth);
2030 
2031 	while (op_class_tbl->op_class && (index < max_supp_op_class)) {
2032 		bool is_opclass_operable = false;
2033 		enum opclass_config opclass_in_config =
2034 		    OPCLASSES_SUPPORTED_BY_CUR_HWMODE;
2035 		uint16_t opclass_width;
2036 
2037 		qdf_mem_zero(reg_ap_cap[index].sup_chan_list,
2038 			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
2039 		reg_ap_cap[index].num_supported_chan = 0;
2040 		qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list,
2041 			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
2042 		reg_ap_cap[index].num_non_supported_chan = 0;
2043 
2044 		reg_convert_chan_spacing_to_width(op_class_tbl->chan_spacing,
2045 						  &opclass_width);
2046 
2047 		if ((opclass_width > out_width) ||
2048 		    ((op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)) &&
2049 		     !is_80p80_supp))
2050 			opclass_in_config =
2051 			    OPCLASSES_NOT_SUPPORTED_BY_CUR_HWMODE;
2052 
2053 		reg_get_channels_from_opclassmap(pdev,
2054 						 reg_ap_cap,
2055 						 index,
2056 						 op_class_tbl,
2057 						 &is_opclass_operable,
2058 						 opclass_in_config,
2059 						 in_6g_pwr_mode);
2060 
2061 		if (is_opclass_operable && opclass_in_config ==
2062 		    OPCLASSES_SUPPORTED_BY_CUR_HWMODE) {
2063 			reg_ap_cap[index].op_class = op_class_tbl->op_class;
2064 			reg_ap_cap[index].ch_width =
2065 				op_class_tbl->chan_spacing;
2066 			reg_ap_cap[index].start_freq =
2067 				op_class_tbl->start_freq;
2068 			reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power;
2069 			reg_ap_cap[index].behav_limit =
2070 				op_class_tbl->behav_limit;
2071 			index++;
2072 		}
2073 		op_class_tbl++;
2074 	}
2075 
2076 	*n_opclasses = index;
2077 
2078 	return QDF_STATUS_SUCCESS;
2079 }
2080 
2081 #ifndef CONFIG_REG_CLIENT
2082 /**
2083  * reg_enable_disable_chan_in_mas_chan_list() - Mark the opclass flag of the
2084  * freq/channel as disabled in the master channel list. Then based on that
2085  * regulatory disable/enable the freq/channel in the current channel list
2086  * @pdev_priv_obj: Pointer to regulatory pdev private object
2087  * @chan_num:  2.4 GHz or 5 GHz channel number
2088  * @is_disable: Boolean to disable or enable
2089  *
2090  * Return: void
2091  */
2092 static void
2093 reg_enable_disable_chan_in_mas_chan_list(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
2094 					 uint8_t chan_num,
2095 					 bool is_disable)
2096 {
2097 	enum channel_enum chan_enum;
2098 	struct regulatory_channel *mas_chan_list;
2099 	qdf_freq_t freq;
2100 
2101 	freq = reg_legacy_chan_to_freq(pdev_priv_obj->pdev_ptr, chan_num);
2102 
2103 	/*
2104 	 * freq = 0 represent a regulatory disabled channel in master channel
2105 	 * list. Do not apply opclass disable/enable on a channel disabled in
2106 	 * the master channel list.
2107 	 */
2108 	if (!freq) {
2109 		reg_err("Frequency should not be zero");
2110 		return;
2111 	}
2112 
2113 	chan_enum = reg_get_chan_enum_for_freq(freq);
2114 	if (reg_is_chan_enum_invalid(chan_enum)) {
2115 		reg_err("Invalid chan enum %d", chan_enum);
2116 		return;
2117 	}
2118 
2119 	mas_chan_list = pdev_priv_obj->mas_chan_list;
2120 
2121 	if (is_disable) {
2122 		mas_chan_list[chan_enum].opclass_chan_disable = true;
2123 	} else {
2124 		/* A channel can be enabled only if its not in NOL */
2125 		if (!mas_chan_list[chan_enum].nol_chan)
2126 			mas_chan_list[chan_enum].opclass_chan_disable = false;
2127 	}
2128 }
2129 
2130 /**
2131  * reg_enable_disable_chan_freq() - Disable or enable a channel in the master
2132  * channel list, that is present in the operating class table's channel set.
2133  * @pdev: Pointer to pdev.
2134  * @is_disable: Boolean to disable or enable
2135  * @ieee_chan_list: Pointer to ieee_chan_list
2136  * @chan_list_size: Size of ieee_chan_list
2137  *
2138  * Return: void.
2139  */
2140 static void
2141 reg_enable_disable_chan_freq(struct wlan_objmgr_pdev *pdev,
2142 			     bool is_disable,
2143 			     uint8_t *ieee_chan_list,
2144 			     uint8_t chan_list_size)
2145 {
2146 	uint8_t i;
2147 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
2148 
2149 	pdev_priv_obj = reg_get_pdev_obj(pdev);
2150 	if (!pdev_priv_obj) {
2151 		reg_err("pdev priv obj is NULL");
2152 		return;
2153 	}
2154 
2155 	for (i = 0; i < chan_list_size; i++) {
2156 		reg_enable_disable_chan_in_mas_chan_list(pdev_priv_obj,
2157 							 ieee_chan_list[i],
2158 							 is_disable);
2159 	}
2160 
2161 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
2162 }
2163 
2164 /**
2165  * reg_is_chan_in_opclass_chan_list() - Check if a channel is present in the
2166  * operating class table's channel set
2167  * @chan: IEEE channel number
2168  * @opclass_chan_list: Pointer to opclass_chan_list
2169  *
2170  * Return: bool.
2171  */
2172 static bool
2173 reg_is_chan_in_opclass_chan_list(uint8_t chan, const uint8_t *opclass_chan_list)
2174 {
2175 	uint8_t j;
2176 
2177 	for (j = 0; j < REG_MAX_CHANNELS_PER_OPERATING_CLASS &&
2178 	     opclass_chan_list[j]; j++) {
2179 		if (chan == opclass_chan_list[j])
2180 			return true;
2181 	}
2182 
2183 	return false;
2184 }
2185 
2186 /**
2187  * reg_is_inlst_subset_of_opchanlst() - Check if a channel present
2188  * in the input ieee_chan_list, is absent in the operating class table
2189  * channel set.
2190  * @opclass_chan_list: Pointer to opclass_chan_list
2191  * @ieee_chan_list: Pointer to ieee_chan_list
2192  * @ieee_chan_list_size: Size of ieee_chan_list
2193  *
2194  * Return: True if channel is absent in operating class table channel set.
2195  */
2196 static bool
2197 reg_is_inlst_subset_of_opchanlst(const uint8_t *opclass_chan_list,
2198 				 uint8_t *ieee_chan_list,
2199 				 uint8_t ieee_chan_list_size)
2200 {
2201 	uint8_t i;
2202 
2203 	for (i = 0; i < ieee_chan_list_size; i++) {
2204 		if (!reg_is_chan_in_opclass_chan_list(ieee_chan_list[i],
2205 						      opclass_chan_list))
2206 			return true;
2207 	}
2208 
2209 	return false;
2210 }
2211 
2212 static bool reg_is_chanspacing_20mhz(uint16_t ch_spacing)
2213 {
2214 	return (ch_spacing >= BW_20_MHZ) && (ch_spacing <= BW_25_MHZ);
2215 }
2216 
2217 QDF_STATUS reg_enable_disable_opclass_chans(struct wlan_objmgr_pdev *pdev,
2218 					    bool is_disable, uint8_t opclass,
2219 					    uint8_t *ieee_chan_list,
2220 					    uint8_t chan_list_size,
2221 					    bool global_tbl_lookup)
2222 {
2223 	const struct reg_dmn_op_class_map_t *op_class_tbl;
2224 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
2225 
2226 	if (!ieee_chan_list) {
2227 		reg_err("IEEE channel list is empty");
2228 		return QDF_STATUS_E_INVAL;
2229 	}
2230 
2231 	pdev_priv_obj = reg_get_pdev_obj(pdev);
2232 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
2233 		reg_err("pdev reg obj is NULL");
2234 		return QDF_STATUS_E_FAILURE;
2235 	}
2236 
2237 	if (global_tbl_lookup)
2238 		op_class_tbl = global_op_class;
2239 	else
2240 		reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
2241 
2242 	if (reg_is_6ghz_op_class(pdev, opclass)) {
2243 		reg_err("6GHz operating class is not supported");
2244 		return QDF_STATUS_E_INVAL;
2245 	}
2246 
2247 	while (op_class_tbl->op_class) {
2248 		if (opclass == op_class_tbl->op_class) {
2249 			if (!reg_is_chanspacing_20mhz(op_class_tbl->chan_spacing)) {
2250 				reg_err("Opclass should only be 20 MHz opclass");
2251 				return QDF_STATUS_E_INVAL;
2252 			}
2253 
2254 			if (reg_is_inlst_subset_of_opchanlst(op_class_tbl->channels,
2255 							     ieee_chan_list,
2256 							     chan_list_size)) {
2257 				reg_err("Invalid channel present in chan list");
2258 				return QDF_STATUS_E_INVAL;
2259 			}
2260 
2261 			reg_enable_disable_chan_freq(pdev, is_disable,
2262 						     ieee_chan_list,
2263 						     chan_list_size);
2264 
2265 			return QDF_STATUS_SUCCESS;
2266 		}
2267 
2268 		op_class_tbl++;
2269 	}
2270 
2271 	reg_err("The opclass is not found %d", opclass);
2272 	return QDF_STATUS_E_INVAL;
2273 }
2274 #endif /* #ifndef CONFIG_REG_CLIENT */
2275 #endif
2276