1 /* 2 * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: reg_opclass.c 21 * This file defines regulatory opclass functions. 22 */ 23 24 #include <qdf_types.h> 25 #include <wlan_cmn.h> 26 #include <reg_services_public_struct.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include "reg_priv_objs.h" 29 #include "reg_utils.h" 30 #include "reg_db.h" 31 #include "reg_db_parser.h" 32 #include "reg_host_11d.h" 33 #include <scheduler_api.h> 34 #include "reg_build_chan_list.h" 35 #include "reg_opclass.h" 36 #include "reg_services_common.h" 37 38 #ifdef HOST_OPCLASS 39 static struct reg_dmn_supp_op_classes reg_dmn_curr_supp_opp_classes = { 0 }; 40 #endif 41 42 static const struct reg_dmn_op_class_map_t global_op_class[] = { 43 {81, 25, BW20, BIT(BEHAV_NONE), 2407, 44 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 45 {82, 25, BW20, BIT(BEHAV_NONE), 2414, 46 {14} }, 47 {83, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, 48 {1, 2, 3, 4, 5, 6, 7, 8, 9} }, 49 {84, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, 50 {5, 6, 7, 8, 9, 10, 11, 12, 13} }, 51 {115, 20, BW20, BIT(BEHAV_NONE), 5000, 52 {36, 40, 44, 48} }, 53 {116, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 54 {36, 44} }, 55 {117, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 56 {40, 48} }, 57 {118, 20, BW20, BIT(BEHAV_NONE), 5000, 58 {52, 56, 60, 64} }, 59 {119, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 60 {52, 60} }, 61 {120, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 62 {56, 64} }, 63 {121, 20, BW20, BIT(BEHAV_NONE), 5000, 64 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144} }, 65 {122, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 66 {100, 108, 116, 124, 132, 140} }, 67 {123, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 68 {104, 112, 120, 128, 136, 144} }, 69 {125, 20, BW20, BIT(BEHAV_NONE), 5000, 70 {149, 153, 157, 161, 165, 169} }, 71 {126, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 72 {149, 157} }, 73 {127, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 74 {153, 161} }, 75 {128, 80, BW80, BIT(BEHAV_NONE), 5000, 76 {36, 40, 44, 48, 52, 56, 60, 64, 77 100, 104, 108, 112, 116, 120, 124, 78 128, 132, 136, 140, 144, 79 149, 153, 157, 161} }, 80 {129, 160, BW80, BIT(BEHAV_NONE), 5000, 81 {36, 40, 44, 48, 52, 56, 60, 64, 82 100, 104, 108, 112, 116, 120, 124, 128} }, 83 {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, 84 {36, 40, 44, 48, 52, 56, 60, 64, 85 100, 104, 108, 112, 116, 120, 124, 128, 86 132, 136, 140, 144, 149, 153, 157, 161} }, 87 88 #ifdef CONFIG_BAND_6GHZ 89 {131, 20, BW20, BIT(BEHAV_NONE), 5940, 90 {1, 5, 9, 13, 17, 21, 25, 29, 33, 91 37, 41, 45, 49, 53, 57, 61, 65, 69, 92 73, 77, 81, 85, 89, 93, 97, 93 101, 105, 109, 113, 117, 121, 125, 94 129, 133, 137, 141, 145, 149, 153, 95 157, 161, 165, 169, 173, 177, 181, 96 185, 189, 193, 197, 201, 205, 209, 97 213, 217, 221, 225, 229, 233} }, 98 99 {132, 40, BW40_LOW_PRIMARY, BIT(BEHAV_NONE), 5940, 100 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 101 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 102 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 103 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 104 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 105 221, 225, 229, 233} }, 106 107 {133, 80, BW80, BIT(BEHAV_NONE), 5940, 108 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 109 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 110 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 111 141, 145, 149, 153, 157, 161, 165, 169, 173, 112 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 113 217, 221, 225, 229, 233} }, 114 115 {134, 160, BW80, BIT(BEHAV_NONE), 5940, 116 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 117 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 118 93, 97, 101, 105, 109, 113, 117, 121, 125, 119 129, 133, 137, 141, 145, 149, 153, 157, 161, 120 165, 169, 173, 177, 181, 185, 189, 193, 197, 121 201, 205, 209, 213, 217, 221, 225, 229, 233} }, 122 123 {135, 80, BW80, BIT(BEHAV_BW80_PLUS), 5940, 124 {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 125 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 126 85, 89, 93, 97, 101, 105, 109, 113, 117, 127 121, 125, 129, 133, 137, 141, 145, 149, 128 153, 157, 161, 165, 169, 173, 177, 181, 129 185, 189, 193, 197, 201, 205, 209, 213, 130 217, 221, 225, 229, 233} }, 131 #endif 132 {0, 0, 0, 0, 0, {0} }, 133 }; 134 135 static const struct reg_dmn_op_class_map_t us_op_class[] = { 136 {1, 20, BW20, BIT(BEHAV_NONE), 5000, 137 {36, 40, 44, 48} }, 138 {2, 20, BW20, BIT(BEHAV_NONE), 5000, 139 {52, 56, 60, 64} }, 140 {4, 20, BW20, BIT(BEHAV_NONE), 5000, 141 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144} }, 142 {5, 20, BW20, BIT(BEHAV_NONE), 5000, 143 {149, 153, 157, 161, 165} }, 144 {12, 25, BW20, BIT(BEHAV_NONE), 2407, 145 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} }, 146 {22, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 147 {36, 44} }, 148 {23, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 149 {52, 60} }, 150 {24, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 151 {100, 108, 116, 124, 132} }, 152 {26, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 153 {149, 157} }, 154 {27, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 155 {40, 48} }, 156 {28, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 157 {56, 64} }, 158 {29, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 159 {104, 112, 120, 128, 136} }, 160 {30, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 161 {153, 161} }, 162 {31, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 163 {153, 161} }, 164 {32, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, 165 {1, 2, 3, 4, 5, 6, 7} }, 166 {33, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, 167 {5, 6, 7, 8, 9, 10, 11} }, 168 {128, 80, BW80, BIT(BEHAV_NONE), 5000, 169 {36, 40, 44, 48, 52, 56, 60, 64, 100, 170 104, 108, 112, 116, 120, 124, 128, 132, 171 136, 140, 144, 149, 153, 157, 161} }, 172 {129, 160, BW80, BIT(BEHAV_NONE), 5000, 173 {36, 40, 44, 48, 52, 56, 60, 64, 100, 174 104, 108, 112, 116, 120, 124, 128} }, 175 {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, 176 {36, 40, 44, 48, 52, 56, 60, 64, 100, 177 104, 108, 112, 116, 120, 124, 128, 132, 178 136, 140, 144, 149, 153, 157, 161} }, 179 {0, 0, 0, 0, 0, {0} }, 180 }; 181 182 static const struct reg_dmn_op_class_map_t euro_op_class[] = { 183 {1, 20, BW20, BIT(BEHAV_NONE), 5000, 184 {36, 40, 44, 48} }, 185 {2, 20, BW20, BIT(BEHAV_NONE), 5000, 186 {52, 56, 60, 64} }, 187 {3, 20, BW20, BIT(BEHAV_NONE), 5000, 188 {100, 104, 108, 112, 116, 120, 189 124, 128, 132, 136, 140} }, 190 {4, 25, BW20, BIT(BEHAV_NONE), 2407, 191 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 192 {5, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 193 {36, 44} }, 194 {6, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 195 {52, 60} }, 196 {7, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 197 {100, 108, 116, 124, 132} }, 198 {8, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 199 {40, 48} }, 200 {9, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 201 {56, 64} }, 202 {10, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 203 {104, 112, 120, 128, 136} }, 204 {11, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, 205 {1, 2, 3, 4, 5, 6, 7, 8, 9} }, 206 {12, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, 207 {5, 6, 7, 8, 9, 10, 11, 12, 13} }, 208 {17, 20, BW20, BIT(BEHAV_NONE), 5000, 209 {149, 153, 157, 161, 165, 169} }, 210 {128, 80, BW80, BIT(BEHAV_NONE), 5000, 211 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 212 124, 128} }, 213 {129, 160, BW80, BIT(BEHAV_NONE), 5000, 214 {36, 40, 44, 48, 52, 56, 60, 64, 100, 215 104, 108, 112, 116, 120, 124, 128} }, 216 {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, 217 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 218 124, 128} }, 219 {0, 0, 0, 0, 0, {0} }, 220 }; 221 222 static const struct reg_dmn_op_class_map_t japan_op_class[] = { 223 {1, 20, BW20, BIT(BEHAV_NONE), 5000, 224 {36, 40, 44, 48} }, 225 {30, 25, BW20, BIT(BEHAV_NONE), 2407, 226 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 227 {31, 25, BW20, BIT(BEHAV_NONE), 2407, 228 {14} }, 229 {32, 20, BW20, BIT(BEHAV_NONE), 5000, 230 {52, 56, 60, 64} }, 231 {34, 20, BW20, BIT(BEHAV_NONE), 5000, 232 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, 233 {36, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 234 {36, 44} }, 235 {37, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 236 {52, 60} }, 237 {39, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, 238 {100, 108, 116, 124, 132} }, 239 {41, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 240 {40, 48} }, 241 {42, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 242 {56, 64} }, 243 {44, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, 244 {104, 112, 120, 128, 136} }, 245 {128, 80, BW80, BIT(BEHAV_NONE), 5000, 246 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 247 124, 128} }, 248 {129, 160, BW80, BIT(BEHAV_NONE), 5000, 249 {36, 40, 44, 48, 52, 56, 60, 64, 100, 250 104, 108, 112, 116, 120, 124, 128} }, 251 {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, 252 {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 253 124, 128} }, 254 {0, 0, 0, 0, 0, {0} }, 255 }; 256 257 #ifdef HOST_OPCLASS 258 /** 259 * reg_get_class_from_country()- Get Class from country 260 * @country- Country 261 * 262 * Return: class. 263 */ 264 static const 265 struct reg_dmn_op_class_map_t *reg_get_class_from_country(uint8_t *country) 266 { 267 const struct reg_dmn_op_class_map_t *class = NULL; 268 269 qdf_debug("Country %c%c 0x%x", 270 country[0], country[1], country[2]); 271 272 switch (country[2]) { 273 case OP_CLASS_US: 274 class = us_op_class; 275 break; 276 277 case OP_CLASS_EU: 278 class = euro_op_class; 279 break; 280 281 case OP_CLASS_JAPAN: 282 class = japan_op_class; 283 break; 284 285 case OP_CLASS_GLOBAL: 286 class = global_op_class; 287 break; 288 289 default: 290 if (!qdf_mem_cmp(country, "US", 2)) 291 class = us_op_class; 292 else if (!qdf_mem_cmp(country, "EU", 2)) 293 class = euro_op_class; 294 else if (!qdf_mem_cmp(country, "JP", 2)) 295 class = japan_op_class; 296 else 297 class = global_op_class; 298 } 299 return class; 300 } 301 302 uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel, 303 uint8_t opclass) 304 { 305 const struct reg_dmn_op_class_map_t *class; 306 uint16_t i; 307 308 class = reg_get_class_from_country(country); 309 310 while (class->op_class) { 311 if (opclass == class->op_class) { 312 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 313 class->channels[i]); i++) { 314 if (channel == class->channels[i]) 315 return class->chan_spacing; 316 } 317 } 318 class++; 319 } 320 321 return 0; 322 } 323 324 uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, 325 uint8_t offset) 326 { 327 const struct reg_dmn_op_class_map_t *class = NULL; 328 uint16_t i = 0; 329 330 class = reg_get_class_from_country(country); 331 while (class && class->op_class) { 332 if ((offset == class->offset) || (offset == BWALL)) { 333 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 334 class->channels[i]); i++) { 335 if (channel == class->channels[i]) 336 return class->op_class; 337 } 338 } 339 class++; 340 } 341 342 return 0; 343 } 344 345 uint8_t reg_dmn_get_opclass_from_freq_width(uint8_t *country, 346 qdf_freq_t freq, 347 uint8_t ch_width, 348 uint16_t behav_limit) 349 { 350 const struct reg_dmn_op_class_map_t *op_class_tbl = NULL; 351 uint16_t i = 0; 352 353 op_class_tbl = reg_get_class_from_country(country); 354 355 while (op_class_tbl && op_class_tbl->op_class) { 356 if (op_class_tbl->chan_spacing == ch_width) { 357 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 358 op_class_tbl->channels[i]); i++) { 359 if ((op_class_tbl->start_freq + 360 (FREQ_TO_CHAN_SCALE * 361 op_class_tbl->channels[i]) == freq) && 362 (behav_limit & op_class_tbl->behav_limit)) { 363 return op_class_tbl->op_class; 364 } 365 } 366 } 367 op_class_tbl++; 368 } 369 370 return 0; 371 } 372 373 void reg_dmn_print_channels_in_opclass(uint8_t *country, uint8_t op_class) 374 { 375 const struct reg_dmn_op_class_map_t *class = NULL; 376 uint16_t i = 0; 377 378 class = reg_get_class_from_country(country); 379 380 if (!class) { 381 reg_err("class is NULL"); 382 return; 383 } 384 385 while (class->op_class) { 386 if (class->op_class == op_class) { 387 for (i = 0; 388 (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 389 class->channels[i]); i++) { 390 reg_debug("Valid channel(%d) in requested RC(%d)", 391 class->channels[i], op_class); 392 } 393 break; 394 } 395 class++; 396 } 397 if (!class->op_class) 398 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 399 "Invalid requested RC (%d)", op_class); 400 } 401 402 uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class) 403 { 404 uint8_t i; 405 406 if (num_classes > REG_MAX_SUPP_OPER_CLASSES) { 407 reg_err("invalid num classes %d", num_classes); 408 return 0; 409 } 410 411 for (i = 0; i < num_classes; i++) 412 reg_dmn_curr_supp_opp_classes.classes[i] = class[i]; 413 414 reg_dmn_curr_supp_opp_classes.num_classes = num_classes; 415 416 return 0; 417 } 418 419 uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class) 420 { 421 uint8_t i; 422 423 if (!num_classes || !class) { 424 reg_err("either num_classes or class is null"); 425 return 0; 426 } 427 428 for (i = 0; i < reg_dmn_curr_supp_opp_classes.num_classes; i++) 429 class[i] = reg_dmn_curr_supp_opp_classes.classes[i]; 430 431 *num_classes = reg_dmn_curr_supp_opp_classes.num_classes; 432 433 return 0; 434 } 435 436 #ifdef CONFIG_CHAN_FREQ_API 437 void reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, 438 qdf_freq_t freq, 439 uint16_t chan_width, 440 bool global_tbl_lookup, 441 uint16_t behav_limit, 442 uint8_t *op_class, 443 uint8_t *chan_num) 444 { 445 const struct reg_dmn_op_class_map_t *op_class_tbl; 446 enum channel_enum chan_enum; 447 uint16_t i; 448 449 chan_enum = reg_get_chan_enum_for_freq(freq); 450 451 if (chan_enum == INVALID_CHANNEL) { 452 reg_err(" channel enumeration is invalid %d", chan_enum); 453 return; 454 } 455 456 if (global_tbl_lookup) { 457 op_class_tbl = global_op_class; 458 } else { 459 if (channel_map == channel_map_us) 460 op_class_tbl = us_op_class; 461 else if (channel_map == channel_map_eu) 462 op_class_tbl = euro_op_class; 463 else if (channel_map == channel_map_china) 464 op_class_tbl = us_op_class; 465 else if (channel_map == channel_map_jp) 466 op_class_tbl = japan_op_class; 467 else 468 op_class_tbl = global_op_class; 469 } 470 471 while (op_class_tbl->op_class) { 472 if (op_class_tbl->chan_spacing >= chan_width) { 473 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 474 op_class_tbl->channels[i]); i++) { 475 if ((op_class_tbl->start_freq + 476 FREQ_TO_CHAN_SCALE * 477 op_class_tbl->channels[i] == freq) && 478 (behav_limit & op_class_tbl->behav_limit || 479 behav_limit == BIT(BEHAV_NONE))) { 480 *chan_num = op_class_tbl->channels[i]; 481 *op_class = op_class_tbl->op_class; 482 return; 483 } 484 } 485 } 486 op_class_tbl++; 487 } 488 489 reg_err_rl("invalid frequency %d", freq); 490 } 491 492 void reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, 493 qdf_freq_t freq, 494 bool global_tbl_lookup, 495 uint16_t behav_limit, 496 uint8_t *op_class, 497 uint8_t *chan_num) 498 { 499 enum channel_enum chan_enum; 500 uint16_t chan_width; 501 struct regulatory_channel *cur_chan_list; 502 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; 503 504 pdev_priv_obj = reg_get_pdev_obj(pdev); 505 506 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { 507 reg_err("pdev reg obj is NULL"); 508 return; 509 } 510 511 cur_chan_list = pdev_priv_obj->cur_chan_list; 512 513 chan_enum = reg_get_chan_enum_for_freq(freq); 514 515 if (chan_enum == INVALID_CHANNEL) { 516 reg_err(" channel enumeration is invalid %d", chan_enum); 517 return; 518 } 519 520 chan_width = cur_chan_list[chan_enum].max_bw; 521 522 reg_freq_width_to_chan_op_class(pdev, freq, 523 chan_width, 524 global_tbl_lookup, 525 behav_limit, 526 op_class, 527 chan_num); 528 } 529 #endif 530 531 uint16_t reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, 532 uint8_t op_class, 533 bool global_tbl_lookup) 534 { 535 const struct reg_dmn_op_class_map_t *op_class_tbl; 536 537 if (global_tbl_lookup) { 538 op_class_tbl = global_op_class; 539 } else { 540 if (channel_map == channel_map_us) 541 op_class_tbl = us_op_class; 542 else if (channel_map == channel_map_eu) 543 op_class_tbl = euro_op_class; 544 else if (channel_map == channel_map_china) 545 op_class_tbl = us_op_class; 546 else if (channel_map == channel_map_jp) 547 op_class_tbl = japan_op_class; 548 else 549 op_class_tbl = global_op_class; 550 } 551 552 while (op_class_tbl->op_class) { 553 if (op_class_tbl->op_class == op_class) 554 return op_class_tbl->chan_spacing; 555 op_class_tbl++; 556 } 557 558 return 0; 559 } 560 561 uint16_t reg_chan_opclass_to_freq(uint8_t chan, 562 uint8_t op_class, 563 bool global_tbl_lookup) 564 { 565 const struct reg_dmn_op_class_map_t *op_class_tbl = NULL; 566 uint8_t i = 0; 567 568 if (global_tbl_lookup) { 569 op_class_tbl = global_op_class; 570 } else { 571 if (channel_map == channel_map_global) { 572 op_class_tbl = global_op_class; 573 } else if (channel_map == channel_map_us) { 574 op_class_tbl = us_op_class; 575 } else if (channel_map == channel_map_eu) { 576 op_class_tbl = euro_op_class; 577 } else if (channel_map == channel_map_china) { 578 op_class_tbl = us_op_class; 579 } else if (channel_map == channel_map_jp) { 580 op_class_tbl = japan_op_class; 581 } else { 582 reg_err_rl("Invalid channel map"); 583 return 0; 584 } 585 } 586 587 while (op_class_tbl->op_class) { 588 if (op_class_tbl->op_class == op_class) { 589 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 590 op_class_tbl->channels[i]); i++) { 591 if (op_class_tbl->channels[i] == chan) { 592 chan = op_class_tbl->channels[i]; 593 return (op_class_tbl->start_freq + 594 (chan * FREQ_TO_CHAN_SCALE)); 595 } 596 } 597 reg_err_rl("Channel not found"); 598 return 0; 599 } 600 op_class_tbl++; 601 } 602 reg_err_rl("Invalid opclass given as input"); 603 return 0; 604 } 605 #endif 606