1 /*
2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 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_utils.c
22 * This file defines the APIs to set and get the regulatory variables.
23 */
24
25 #include <wlan_cmn.h>
26 #include <reg_services_public_struct.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <wlan_objmgr_pdev_obj.h>
29 #include "reg_priv_objs.h"
30 #include "reg_utils.h"
31 #include "reg_callbacks.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 <wlan_reg_services_api.h>
37 #include <qdf_platform.h>
38 #include "reg_services_common.h"
39 #include "reg_build_chan_list.h"
40 #include "wlan_cm_bss_score_param.h"
41 #include "qdf_str.h"
42 #include "wmi_unified_param.h"
43
44 #define DEFAULT_WORLD_REGDMN 0x60
45 #define FCC3_FCCA 0x3A
46 #define FCC6_FCCA 0x14
47
48 #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj)
49 #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj)
50
51 #ifdef CONFIG_CHAN_FREQ_API
reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev * pdev,qdf_freq_t freq)52 bool reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev,
53 qdf_freq_t freq)
54 {
55 enum channel_enum ch_idx;
56 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
57
58 ch_idx = reg_get_chan_enum_for_freq(freq);
59
60 if (reg_is_chan_enum_invalid(ch_idx))
61 return false;
62
63 pdev_priv_obj = reg_get_pdev_obj(pdev);
64
65 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
66 reg_err("pdev reg obj is NULL");
67 return false;
68 }
69
70 if (pdev_priv_obj->cur_chan_list[ch_idx].chan_flags &
71 REGULATORY_CHAN_RADAR)
72 return true;
73
74 return false;
75 }
76 #endif /* CONFIG_CHAN_FREQ_API */
77
reg_is_world_ctry_code(uint16_t ctry_code)78 bool reg_is_world_ctry_code(uint16_t ctry_code)
79 {
80 if ((ctry_code & 0xFFF0) == DEFAULT_WORLD_REGDMN)
81 return true;
82
83 return false;
84 }
85
reg_read_current_country(struct wlan_objmgr_psoc * psoc,uint8_t * country_code)86 QDF_STATUS reg_read_current_country(struct wlan_objmgr_psoc *psoc,
87 uint8_t *country_code)
88 {
89 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
90
91 if (!country_code) {
92 reg_err("country_code is NULL");
93 return QDF_STATUS_E_INVAL;
94 }
95
96 psoc_reg = reg_get_psoc_obj(psoc);
97 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
98 reg_err("psoc reg component is NULL");
99 return QDF_STATUS_E_INVAL;
100 }
101
102 qdf_mem_copy(country_code, psoc_reg->cur_country, REG_ALPHA2_LEN + 1);
103
104 return QDF_STATUS_SUCCESS;
105 }
106
reg_set_default_country(struct wlan_objmgr_psoc * psoc,uint8_t * country)107 QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc,
108 uint8_t *country)
109 {
110 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
111
112 if (!country) {
113 reg_err("country is NULL");
114 return QDF_STATUS_E_INVAL;
115 }
116
117 psoc_reg = reg_get_psoc_obj(psoc);
118 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
119 reg_err("psoc reg component is NULL");
120 return QDF_STATUS_E_INVAL;
121 }
122
123 reg_info("set default_country: %s", country);
124
125 qdf_mem_copy(psoc_reg->def_country, country, REG_ALPHA2_LEN + 1);
126
127 return QDF_STATUS_SUCCESS;
128 }
129
reg_is_world_alpha2(uint8_t * alpha2)130 bool reg_is_world_alpha2(uint8_t *alpha2)
131 {
132 if ((alpha2[0] == '0') && (alpha2[1] == '0'))
133 return true;
134
135 return false;
136 }
137
reg_is_us_alpha2(uint8_t * alpha2)138 bool reg_is_us_alpha2(uint8_t *alpha2)
139 {
140 if ((alpha2[0] == 'U') && (alpha2[1] == 'S'))
141 return true;
142
143 return false;
144 }
145
reg_is_etsi_alpha2(uint8_t * alpha2)146 bool reg_is_etsi_alpha2(uint8_t *alpha2)
147 {
148 if ((alpha2[0] == 'G') && (alpha2[1] == 'B'))
149 return true;
150
151 return false;
152 }
153
154 static
reg_get_power_mode_string(uint16_t reg_dmn_pair_id)155 const char *reg_get_power_mode_string(uint16_t reg_dmn_pair_id)
156 {
157 switch (reg_dmn_pair_id) {
158 case FCC3_FCCA:
159 case FCC6_FCCA:
160 return "NON_VLP";
161 default:
162 return "VLP";
163 }
164 }
165
reg_ctry_domain_supports_vlp(uint8_t * alpha2)166 static bool reg_ctry_domain_supports_vlp(uint8_t *alpha2)
167 {
168 uint16_t i;
169 int no_of_countries;
170
171 reg_get_num_countries(&no_of_countries);
172 for (i = 0; i < no_of_countries; i++) {
173 if (g_all_countries[i].alpha2[0] == alpha2[0] &&
174 g_all_countries[i].alpha2[1] == alpha2[1]) {
175 if (!qdf_str_cmp(reg_get_power_mode_string(
176 g_all_countries[i].reg_dmn_pair_id), "NON_VLP"))
177 return false;
178 else
179 return true;
180 }
181 }
182 return true;
183 }
184
reg_ctry_support_vlp(uint8_t * alpha2)185 bool reg_ctry_support_vlp(uint8_t *alpha2)
186 {
187 if (((alpha2[0] == 'A') && (alpha2[1] == 'E')) ||
188 ((alpha2[0] == 'P') && (alpha2[1] == 'E')) ||
189 ((alpha2[0] == 'U') && (alpha2[1] == 'S')) ||
190 !reg_ctry_domain_supports_vlp(alpha2))
191 return false;
192 else
193 return true;
194 }
195
reg_set_non_offload_country(struct wlan_objmgr_pdev * pdev,struct set_country * cc)196 static QDF_STATUS reg_set_non_offload_country(struct wlan_objmgr_pdev *pdev,
197 struct set_country *cc)
198 {
199 struct wlan_objmgr_psoc *psoc;
200 struct wlan_lmac_if_reg_tx_ops *tx_ops;
201 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
202 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
203 struct cc_regdmn_s rd;
204 uint8_t pdev_id;
205 uint8_t phy_id;
206
207 if (!pdev) {
208 reg_err("pdev is NULL");
209 return QDF_STATUS_E_INVAL;
210 }
211
212 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
213 psoc = wlan_pdev_get_psoc(pdev);
214 tx_ops = reg_get_psoc_tx_ops(psoc);
215 if (tx_ops->get_phy_id_from_pdev_id)
216 tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
217 else
218 phy_id = pdev_id;
219
220 psoc_reg = reg_get_psoc_obj(psoc);
221 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
222 reg_err("psoc reg component is NULL");
223 return QDF_STATUS_E_INVAL;
224 }
225
226 if (reg_is_world_alpha2(cc->country)) {
227 pdev_priv_obj = reg_get_pdev_obj(pdev);
228 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
229 reg_err("reg component pdev priv is NULL");
230 psoc_reg->world_country_pending[phy_id] = false;
231 return QDF_STATUS_E_INVAL;
232 }
233 if (reg_is_world_ctry_code(pdev_priv_obj->def_region_domain))
234 rd.cc.regdmn.reg_2g_5g_pair_id =
235 pdev_priv_obj->def_region_domain;
236 else
237 rd.cc.regdmn.reg_2g_5g_pair_id = DEFAULT_WORLD_REGDMN;
238 rd.flags = REGDMN_IS_SET;
239 } else {
240 qdf_mem_copy(rd.cc.alpha, cc->country, REG_ALPHA2_LEN + 1);
241 rd.flags = ALPHA_IS_SET;
242 }
243
244 reg_program_chan_list(pdev, &rd);
245 return QDF_STATUS_SUCCESS;
246 }
247
248 #ifdef WLAN_REG_PARTIAL_OFFLOAD
249 /**
250 * reg_restore_def_country_for_po() - API to restore country code to default
251 * value if given country is invalid for Partial Offload
252 * @offload_enabled: Is offload enabled
253 * @country: Country code
254 * @cc_country: Country code array
255 * Return- void
256 */
reg_restore_def_country_for_po(bool offload_enabled,uint8_t * country,uint8_t cc_country[])257 static void reg_restore_def_country_for_po(bool offload_enabled,
258 uint8_t *country,
259 uint8_t cc_country[]){
260 if (!offload_enabled && !reg_is_world_alpha2(country)) {
261 QDF_STATUS status;
262
263 status = reg_is_country_code_valid(country);
264 if (!QDF_IS_STATUS_SUCCESS(status)) {
265 reg_err("Unable to set country code: %s\n", country);
266 reg_err("Restoring to world domain");
267 qdf_mem_copy(cc_country, REG_WORLD_ALPHA2,
268 REG_ALPHA2_LEN + 1);
269 }
270 }
271 }
272 #else
reg_restore_def_country_for_po(bool offload_enabled,uint8_t * country,uint8_t cc_country[])273 static void reg_restore_def_country_for_po(bool offload_enabled,
274 uint8_t *country,
275 uint8_t cc_country[]){
276 }
277 #endif
278
reg_set_country(struct wlan_objmgr_pdev * pdev,uint8_t * country)279 QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev,
280 uint8_t *country)
281 {
282 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
283 struct wlan_lmac_if_reg_tx_ops *tx_ops;
284 struct set_country cc;
285 struct wlan_objmgr_psoc *psoc;
286 uint8_t pdev_id;
287 uint8_t phy_id;
288
289 if (!pdev) {
290 reg_err("pdev is NULL");
291 return QDF_STATUS_E_INVAL;
292 }
293
294 if (!country) {
295 reg_err("country code is NULL");
296 return QDF_STATUS_E_INVAL;
297 }
298
299 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
300
301 psoc = wlan_pdev_get_psoc(pdev);
302
303 tx_ops = reg_get_psoc_tx_ops(psoc);
304 if (tx_ops->get_phy_id_from_pdev_id)
305 tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
306 else
307 phy_id = pdev_id;
308
309 psoc_reg = reg_get_psoc_obj(psoc);
310 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
311 reg_err("psoc reg component is NULL");
312 return QDF_STATUS_E_INVAL;
313 }
314
315 if (!qdf_mem_cmp(psoc_reg->cur_country, country, REG_ALPHA2_LEN)) {
316 if (psoc_reg->cc_src == SOURCE_USERSPACE ||
317 psoc_reg->cc_src == SOURCE_CORE) {
318 reg_debug("country is not different");
319 return QDF_STATUS_E_INVAL;
320 }
321 }
322
323 reg_debug("programming new country: %s to firmware", country);
324
325 qdf_mem_copy(cc.country, country, REG_ALPHA2_LEN + 1);
326 /*
327 * Need firmware to send channel list event
328 * for all phys. Therefore set pdev_id to 0xFF.
329 */
330 cc.pdev_id = WMI_HOST_PDEV_ID_SOC;
331
332 reg_restore_def_country_for_po(psoc_reg->offload_enabled,
333 country,
334 cc.country);
335
336 if (reg_is_world_alpha2(cc.country))
337 psoc_reg->world_country_pending[phy_id] = true;
338 else
339 psoc_reg->new_user_ctry_pending[phy_id] = true;
340
341 if (psoc_reg->offload_enabled) {
342 tx_ops = reg_get_psoc_tx_ops(psoc);
343 if (tx_ops->set_country_code) {
344 tx_ops->set_country_code(psoc, &cc);
345 } else {
346 reg_err("country set fw handler not present");
347 psoc_reg->new_user_ctry_pending[phy_id] = false;
348 return QDF_STATUS_E_FAULT;
349 }
350 } else {
351 return reg_set_non_offload_country(pdev, &cc);
352 }
353
354 return QDF_STATUS_SUCCESS;
355 }
356
reg_reset_country(struct wlan_objmgr_psoc * psoc)357 QDF_STATUS reg_reset_country(struct wlan_objmgr_psoc *psoc)
358 {
359 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
360
361 psoc_reg = reg_get_psoc_obj(psoc);
362 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
363 reg_err("psoc reg component is NULL");
364 return QDF_STATUS_E_INVAL;
365 }
366
367 qdf_mem_copy(psoc_reg->cur_country,
368 psoc_reg->def_country,
369 REG_ALPHA2_LEN + 1);
370 reg_debug("set cur_country %.2s", psoc_reg->cur_country);
371
372 return QDF_STATUS_SUCCESS;
373 }
374
reg_get_domain_from_country_code(v_REGDOMAIN_t * reg_domain_ptr,const uint8_t * country_alpha2,enum country_src source)375 QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr,
376 const uint8_t *country_alpha2,
377 enum country_src source)
378 {
379 if (!reg_domain_ptr) {
380 reg_err("Invalid reg domain pointer");
381 return QDF_STATUS_E_FAULT;
382 }
383
384 *reg_domain_ptr = 0;
385
386 if (!country_alpha2) {
387 reg_err("Country code is NULL");
388 return QDF_STATUS_E_FAULT;
389 }
390
391 return QDF_STATUS_SUCCESS;
392 }
393
394 #if defined(CONFIG_REG_CLIENT) && defined(CONFIG_BAND_6GHZ)
395 QDF_STATUS
reg_get_6ghz_cli_pwr_type_per_ap_pwr_type(struct wlan_objmgr_pdev * pdev,enum reg_6g_ap_type ap_pwr_type,enum supported_6g_pwr_types * cli_pwr_type)396 reg_get_6ghz_cli_pwr_type_per_ap_pwr_type(
397 struct wlan_objmgr_pdev *pdev,
398 enum reg_6g_ap_type ap_pwr_type,
399 enum supported_6g_pwr_types *cli_pwr_type)
400 {
401 enum reg_6g_client_type client_type;
402
403 reg_get_cur_6g_client_type(pdev, &client_type);
404
405 if (client_type == REG_DEFAULT_CLIENT) {
406 if (ap_pwr_type == REG_INDOOR_AP)
407 *cli_pwr_type = REG_CLI_DEF_LPI;
408 else if (ap_pwr_type == REG_VERY_LOW_POWER_AP)
409 *cli_pwr_type = REG_CLI_DEF_VLP;
410 else if (ap_pwr_type == REG_STANDARD_POWER_AP)
411 *cli_pwr_type = REG_CLI_DEF_SP;
412 else
413 return QDF_STATUS_E_FAILURE;
414 } else if (client_type == REG_SUBORDINATE_CLIENT) {
415 if (ap_pwr_type == REG_INDOOR_AP)
416 *cli_pwr_type = REG_CLI_SUB_LPI;
417 else if (ap_pwr_type == REG_VERY_LOW_POWER_AP)
418 *cli_pwr_type = REG_CLI_SUB_VLP;
419 else if (ap_pwr_type == REG_STANDARD_POWER_AP)
420 *cli_pwr_type = REG_CLI_SUB_SP;
421 else
422 return QDF_STATUS_E_FAILURE;
423 } else {
424 return QDF_STATUS_E_FAILURE;
425 }
426
427 return QDF_STATUS_SUCCESS;
428 }
429 #endif
430
431 #ifdef CONFIG_REG_CLIENT
432 #ifdef CONFIG_BAND_6GHZ
433 /**
434 * reg_check_if_6g_pwr_type_supp_for_chan() - Check if 6 GHz power type is
435 * supported for the channel
436 * @pdev: Pointer to pdev
437 * @pwr_type: 6 GHz power type
438 * @chan_idx: Connection channel index
439 *
440 * Return: Return QDF_STATUS_SUCCESS if 6 GHz power type supported for
441 * the given channel, else return QDF_STATUS_E_FAILURE.
442 */
443 static
reg_check_if_6g_pwr_type_supp_for_chan(struct wlan_objmgr_pdev * pdev,enum reg_6g_ap_type pwr_type,enum channel_enum chan_idx)444 QDF_STATUS reg_check_if_6g_pwr_type_supp_for_chan(
445 struct wlan_objmgr_pdev *pdev,
446 enum reg_6g_ap_type pwr_type,
447 enum channel_enum chan_idx)
448 {
449 struct super_chan_info *super_chan_list;
450 enum channel_state *chan_state_arr;
451 uint32_t *chan_flags_arr;
452 enum supported_6g_pwr_types cli_pwr_type;
453 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
454 uint16_t sup_idx;
455
456 pdev_priv_obj = reg_get_pdev_obj(pdev);
457 if (!pdev_priv_obj) {
458 reg_err("pdev priv obj null");
459 return QDF_STATUS_E_FAILURE;
460 }
461
462 sup_idx = reg_convert_enum_to_6g_idx(chan_idx);
463 if (sup_idx >= NUM_6GHZ_CHANNELS) {
464 reg_err("Invalid channel");
465 return QDF_STATUS_E_NOSUPPORT;
466 }
467
468 if (QDF_IS_STATUS_ERROR(reg_get_6ghz_cli_pwr_type_per_ap_pwr_type(
469 pdev, pwr_type, &cli_pwr_type)))
470 goto no_support;
471
472 super_chan_list = pdev_priv_obj->super_chan_list;
473 chan_state_arr = super_chan_list[sup_idx].state_arr;
474 chan_flags_arr = super_chan_list[sup_idx].chan_flags_arr;
475 if (reg_is_state_allowed(chan_state_arr[cli_pwr_type]) &&
476 !(chan_flags_arr[cli_pwr_type] & REGULATORY_CHAN_DISABLED))
477 return QDF_STATUS_SUCCESS;
478
479 no_support:
480 reg_err("6 GHz power type = %d not supported for 6 GHz channel idx = %d",
481 cli_pwr_type, sup_idx);
482 return QDF_STATUS_E_NOSUPPORT;
483 }
484
485 QDF_STATUS
reg_get_best_6g_power_type(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,enum reg_6g_ap_type * pwr_type_6g,enum reg_6g_ap_type ap_pwr_type,uint32_t chan_freq)486 reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc,
487 struct wlan_objmgr_pdev *pdev,
488 enum reg_6g_ap_type *pwr_type_6g,
489 enum reg_6g_ap_type ap_pwr_type,
490 uint32_t chan_freq)
491 {
492 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
493 enum channel_enum chan_idx = reg_get_chan_enum_for_freq(chan_freq);
494
495 *pwr_type_6g = ap_pwr_type;
496 pdev_priv_obj = reg_get_pdev_obj(pdev);
497 if (!pdev_priv_obj) {
498 reg_err("pdev priv obj null");
499 return QDF_STATUS_E_FAILURE;
500 }
501
502 /*
503 * If AP doesn't advertise 6 GHz power type or advertised invalid power
504 * type, select VLP power type if VLP rules are present for the
505 * connection channel, if not select LPI power type if LPI rules are
506 * present for connection channel, otherwise don't connect.
507 */
508 if (ap_pwr_type < REG_INDOOR_AP ||
509 ap_pwr_type >= REG_CURRENT_MAX_AP_TYPE) {
510 if (QDF_IS_STATUS_SUCCESS(
511 reg_check_if_6g_pwr_type_supp_for_chan(pdev,
512 REG_VERY_LOW_POWER_AP,
513 chan_idx))) {
514 reg_debug("Invalid AP power type: %d , selected power type: %d",
515 ap_pwr_type, REG_VERY_LOW_POWER_AP);
516 *pwr_type_6g = REG_VERY_LOW_POWER_AP;
517 return QDF_STATUS_SUCCESS;
518 } else if (QDF_IS_STATUS_SUCCESS(
519 reg_check_if_6g_pwr_type_supp_for_chan(pdev,
520 REG_INDOOR_AP,
521 chan_idx))) {
522 reg_debug("Invalid AP power type: %d , selected power type: %d",
523 ap_pwr_type, REG_INDOOR_AP);
524 *pwr_type_6g = REG_INDOOR_AP;
525 return QDF_STATUS_SUCCESS;
526 } else {
527 reg_err("Invalid AP power type: %d, couldn't find suitable power type",
528 ap_pwr_type);
529 return QDF_STATUS_E_NOSUPPORT;
530 }
531 }
532
533 if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[ap_pwr_type] &&
534 QDF_IS_STATUS_SUCCESS(reg_check_if_6g_pwr_type_supp_for_chan(
535 pdev,
536 ap_pwr_type, chan_idx))) {
537 reg_debug("AP power type: %d , is supported by client",
538 ap_pwr_type);
539 return QDF_STATUS_SUCCESS;
540 }
541
542 if (ap_pwr_type == REG_INDOOR_AP) {
543 if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP] &&
544 QDF_IS_STATUS_SUCCESS(
545 reg_check_if_6g_pwr_type_supp_for_chan(pdev,
546 REG_VERY_LOW_POWER_AP,
547 chan_idx))) {
548 *pwr_type_6g = REG_VERY_LOW_POWER_AP;
549 reg_debug("AP power type = %d, selected power type = %d",
550 ap_pwr_type, *pwr_type_6g);
551 return QDF_STATUS_SUCCESS;
552 } else {
553 goto no_support;
554 }
555 } else if (ap_pwr_type == REG_STANDARD_POWER_AP) {
556 if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP] &&
557 QDF_IS_STATUS_SUCCESS(
558 reg_check_if_6g_pwr_type_supp_for_chan(pdev,
559 REG_VERY_LOW_POWER_AP,
560 chan_idx))) {
561 if (wlan_cm_get_disable_vlp_sta_conn_to_sp_ap(psoc)) {
562 reg_debug("AP SP and STA VLP connection disabled");
563 return QDF_STATUS_E_NOSUPPORT;
564 }
565 *pwr_type_6g = REG_VERY_LOW_POWER_AP;
566 reg_debug("AP power type = %d, selected power type = %d",
567 ap_pwr_type, *pwr_type_6g);
568 return QDF_STATUS_SUCCESS;
569 } else {
570 goto no_support;
571 }
572 }
573
574 no_support:
575 reg_err("AP power type = %d, not supported", ap_pwr_type);
576 return QDF_STATUS_E_NOSUPPORT;
577 }
578 #else
579 QDF_STATUS
reg_get_best_6g_power_type(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,enum reg_6g_ap_type * pwr_type_6g,enum reg_6g_ap_type ap_pwr_type,uint32_t chan_freq)580 reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc,
581 struct wlan_objmgr_pdev *pdev,
582 enum reg_6g_ap_type *pwr_type_6g,
583 enum reg_6g_ap_type ap_pwr_type,
584 uint32_t chan_freq)
585 {
586 return QDF_STATUS_SUCCESS;
587 }
588 #endif
589 #endif
590
591 #ifdef FEATURE_WLAN_CH_AVOID_EXT
592 static inline
reg_get_coex_unsafe_chan_nb_user_prefer(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars config_vars)593 void reg_get_coex_unsafe_chan_nb_user_prefer(
594 struct wlan_regulatory_psoc_priv_obj
595 *psoc_priv_obj,
596 struct reg_config_vars config_vars)
597 {
598 psoc_priv_obj->coex_unsafe_chan_nb_user_prefer =
599 config_vars.coex_unsafe_chan_nb_user_prefer;
600 }
601
602 static inline
reg_get_coex_unsafe_chan_reg_disable(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars config_vars)603 void reg_get_coex_unsafe_chan_reg_disable(
604 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
605 struct reg_config_vars config_vars)
606 {
607 psoc_priv_obj->coex_unsafe_chan_reg_disable =
608 config_vars.coex_unsafe_chan_reg_disable;
609 }
610 #else
611 static inline
reg_get_coex_unsafe_chan_nb_user_prefer(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars config_vars)612 void reg_get_coex_unsafe_chan_nb_user_prefer(
613 struct wlan_regulatory_psoc_priv_obj
614 *psoc_priv_obj,
615 struct reg_config_vars config_vars)
616 {
617 }
618
619 static inline
reg_get_coex_unsafe_chan_reg_disable(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars config_vars)620 void reg_get_coex_unsafe_chan_reg_disable(
621 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
622 struct reg_config_vars config_vars)
623 {
624 }
625 #endif
626
627 #ifdef CONFIG_CHAN_FREQ_API
reg_is_passive_or_disable_for_pwrmode(struct wlan_objmgr_pdev * pdev,qdf_freq_t freq,enum supported_6g_pwr_types in_6g_pwr_mode)628 bool reg_is_passive_or_disable_for_pwrmode(
629 struct wlan_objmgr_pdev *pdev,
630 qdf_freq_t freq,
631 enum supported_6g_pwr_types in_6g_pwr_mode)
632 {
633 enum channel_state chan_state;
634
635 chan_state = reg_get_channel_state_for_pwrmode(pdev, freq,
636 in_6g_pwr_mode);
637
638 return (chan_state == CHANNEL_STATE_DFS) ||
639 (chan_state == CHANNEL_STATE_DISABLE);
640 }
641 #endif /* CONFIG_CHAN_FREQ_API */
642
643 #ifdef WLAN_FEATURE_DSRC
644 #ifdef CONFIG_CHAN_FREQ_API
reg_is_dsrc_freq(qdf_freq_t freq)645 bool reg_is_dsrc_freq(qdf_freq_t freq)
646 {
647 if (!REG_IS_5GHZ_FREQ(freq))
648 return false;
649
650 if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ))
651 return false;
652
653 return true;
654 }
655 #endif /*CONFIG_CHAN_FREQ_API*/
656 #else
reg_is_etsi_regdmn(struct wlan_objmgr_pdev * pdev)657 bool reg_is_etsi_regdmn(struct wlan_objmgr_pdev *pdev)
658 {
659 struct cur_regdmn_info cur_reg_dmn;
660 QDF_STATUS status;
661
662 status = reg_get_curr_regdomain(pdev, &cur_reg_dmn);
663 if (status != QDF_STATUS_SUCCESS) {
664 reg_debug_rl("Failed to get reg domain");
665 return false;
666 }
667
668 return reg_etsi_regdmn(cur_reg_dmn.dmn_id_5g);
669 }
670
671 #ifdef CONFIG_CHAN_FREQ_API
reg_is_etsi_srd_chan_for_freq(struct wlan_objmgr_pdev * pdev,uint16_t freq)672 bool reg_is_etsi_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev,
673 uint16_t freq)
674 {
675 if (!REG_IS_5GHZ_FREQ(freq))
676 return false;
677
678 if (!(freq >= REG_ETSI_SRD_START_FREQ &&
679 freq <= REG_ETSI_SRD_END_FREQ))
680 return false;
681
682 return reg_is_etsi_regdmn(pdev);
683 }
684 #endif /* CONFIG_CHAN_FREQ_API */
685
reg_is_etsi_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev * pdev)686 bool reg_is_etsi_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev)
687 {
688 struct wlan_objmgr_psoc *psoc;
689 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
690
691 if (!pdev) {
692 reg_alert("pdev is NULL");
693 return true;
694 }
695 psoc = wlan_pdev_get_psoc(pdev);
696
697 psoc_priv_obj = reg_get_psoc_obj(psoc);
698 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
699 reg_alert("psoc reg component is NULL");
700 return true;
701 }
702
703 return psoc_priv_obj->enable_srd_chan_in_master_mode &&
704 reg_is_etsi_regdmn(pdev);
705 }
706 #endif
707
reg_set_band(struct wlan_objmgr_pdev * pdev,uint32_t band_bitmap)708 QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap)
709 {
710 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
711 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
712 struct wlan_objmgr_psoc *psoc;
713 QDF_STATUS status;
714
715 pdev_priv_obj = reg_get_pdev_obj(pdev);
716
717 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
718 reg_err("pdev reg component is NULL");
719 return QDF_STATUS_E_INVAL;
720 }
721
722 /*
723 * If SET_FCC_CHANNEL 0 command is received first then 6 GHz band would
724 * be disabled and band_capability would be set to 3 but existing 6 GHz
725 * STA and P2P client connections won't be disconnected.
726 * If set band comes again for 6 GHz band disabled and band_bitmap is
727 * equal to band_capability, proceed to disable 6 GHz band completely.
728 */
729 if (pdev_priv_obj->band_capability == band_bitmap &&
730 !reg_get_keep_6ghz_sta_cli_connection(pdev)) {
731 reg_info("same band %d", band_bitmap);
732 return QDF_STATUS_SUCCESS;
733 }
734
735 /*
736 * If in current band_capability 6 GHz bit is not set, in current
737 * request 6 GHz band might be enabled/disabled. Hence reset
738 * reg_set_keep_6ghz_sta_cli_connection flag.
739 */
740 if (!reg_is_6ghz_band_set(pdev)) {
741 status = reg_set_keep_6ghz_sta_cli_connection(pdev, false);
742 if (QDF_IS_STATUS_ERROR(status))
743 return status;
744 }
745
746 psoc = wlan_pdev_get_psoc(pdev);
747 if (!psoc) {
748 reg_err("psoc is NULL");
749 return QDF_STATUS_E_INVAL;
750 }
751
752 psoc_priv_obj = reg_get_psoc_obj(psoc);
753 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
754 reg_err("psoc reg component is NULL");
755 return QDF_STATUS_E_INVAL;
756 }
757
758 reg_info("set band bitmap: %d", band_bitmap);
759 pdev_priv_obj->band_capability = band_bitmap;
760
761 reg_compute_pdev_current_chan_list(pdev_priv_obj);
762
763 status = reg_send_scheduler_msg_sb(psoc, pdev);
764
765 return status;
766 }
767
reg_get_band(struct wlan_objmgr_pdev * pdev,uint32_t * band_bitmap)768 QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev,
769 uint32_t *band_bitmap)
770 {
771 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
772
773 pdev_priv_obj = reg_get_pdev_obj(pdev);
774
775 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
776 reg_err("pdev reg component is NULL");
777 return QDF_STATUS_E_INVAL;
778 }
779
780 reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability);
781 *band_bitmap = pdev_priv_obj->band_capability;
782
783 return QDF_STATUS_SUCCESS;
784 }
785
786 #ifdef DISABLE_CHANNEL_LIST
reg_restore_cached_channels(struct wlan_objmgr_pdev * pdev)787 QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev)
788 {
789 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
790 struct wlan_objmgr_psoc *psoc;
791 QDF_STATUS status;
792
793 pdev_priv_obj = reg_get_pdev_obj(pdev);
794 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
795 reg_err("pdev reg component is NULL");
796 return QDF_STATUS_E_INVAL;
797 }
798
799 psoc = wlan_pdev_get_psoc(pdev);
800 if (!psoc) {
801 reg_err("psoc is NULL");
802 return QDF_STATUS_E_INVAL;
803 }
804
805 pdev_priv_obj->disable_cached_channels = false;
806 reg_compute_pdev_current_chan_list(pdev_priv_obj);
807 status = reg_send_scheduler_msg_sb(psoc, pdev);
808 return status;
809 }
810
reg_disable_cached_channels(struct wlan_objmgr_pdev * pdev)811 QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev)
812 {
813 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
814 struct wlan_objmgr_psoc *psoc;
815 QDF_STATUS status;
816
817 pdev_priv_obj = reg_get_pdev_obj(pdev);
818 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
819 reg_err("pdev reg component is NULL");
820 return QDF_STATUS_E_INVAL;
821 }
822
823 psoc = wlan_pdev_get_psoc(pdev);
824 if (!psoc) {
825 reg_err("psoc is NULL");
826 return QDF_STATUS_E_INVAL;
827 }
828
829 pdev_priv_obj->disable_cached_channels = true;
830 reg_compute_pdev_current_chan_list(pdev_priv_obj);
831 status = reg_send_scheduler_msg_sb(psoc, pdev);
832 return status;
833 }
834
835 #ifdef CONFIG_CHAN_FREQ_API
reg_cache_channel_freq_state(struct wlan_objmgr_pdev * pdev,uint32_t * channel_list,uint32_t num_channels)836 QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev,
837 uint32_t *channel_list,
838 uint32_t num_channels)
839 {
840 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
841 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
842 struct wlan_objmgr_psoc *psoc;
843 uint16_t i, j;
844
845 pdev_priv_obj = reg_get_pdev_obj(pdev);
846
847 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
848 reg_err("pdev reg component is NULL");
849 return QDF_STATUS_E_INVAL;
850 }
851
852 psoc = wlan_pdev_get_psoc(pdev);
853 if (!psoc) {
854 reg_err("psoc is NULL");
855 return QDF_STATUS_E_INVAL;
856 }
857
858 psoc_priv_obj = reg_get_psoc_obj(psoc);
859 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
860 reg_err("psoc reg component is NULL");
861 return QDF_STATUS_E_INVAL;
862 }
863 if (pdev_priv_obj->num_cache_channels > 0) {
864 pdev_priv_obj->num_cache_channels = 0;
865 qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list,
866 sizeof(pdev_priv_obj->cache_disable_chan_list));
867 }
868
869 for (i = 0; i < num_channels; i++) {
870 for (j = 0; j < NUM_CHANNELS; j++) {
871 if (channel_list[i] == pdev_priv_obj->
872 cur_chan_list[j].center_freq) {
873 pdev_priv_obj->
874 cache_disable_chan_list[i].center_freq =
875 channel_list[i];
876 pdev_priv_obj->
877 cache_disable_chan_list[i].state =
878 pdev_priv_obj->cur_chan_list[j].state;
879 pdev_priv_obj->
880 cache_disable_chan_list[i].chan_flags =
881 pdev_priv_obj->
882 cur_chan_list[j].chan_flags;
883 }
884 }
885 }
886 pdev_priv_obj->num_cache_channels = num_channels;
887
888 return QDF_STATUS_SUCCESS;
889 }
890 #endif /* CONFIG_CHAN_FREQ_API */
891 #endif
892
893 #ifdef CONFIG_REG_CLIENT
reg_get_keep_6ghz_sta_cli_connection(struct wlan_objmgr_pdev * pdev)894 bool reg_get_keep_6ghz_sta_cli_connection(struct wlan_objmgr_pdev *pdev)
895 {
896 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
897
898 pdev_priv_obj = reg_get_pdev_obj(pdev);
899 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
900 reg_err("pdev reg component is NULL");
901 return false;
902 }
903
904 return pdev_priv_obj->keep_6ghz_sta_cli_connection;
905 }
906
reg_set_keep_6ghz_sta_cli_connection(struct wlan_objmgr_pdev * pdev,bool keep_6ghz_sta_cli_connection)907 QDF_STATUS reg_set_keep_6ghz_sta_cli_connection(struct wlan_objmgr_pdev *pdev,
908 bool keep_6ghz_sta_cli_connection)
909 {
910 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
911
912 pdev_priv_obj = reg_get_pdev_obj(pdev);
913 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
914 reg_err("pdev reg component is NULL");
915 return QDF_STATUS_E_INVAL;
916 }
917
918 pdev_priv_obj->keep_6ghz_sta_cli_connection =
919 keep_6ghz_sta_cli_connection;
920
921 reg_debug("set keep_6ghz_sta_cli_connection = %d",
922 keep_6ghz_sta_cli_connection);
923 return QDF_STATUS_SUCCESS;
924 }
925
reg_set_fcc_constraint(struct wlan_objmgr_pdev * pdev,bool fcc_constraint)926 QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev,
927 bool fcc_constraint)
928 {
929 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
930 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
931 struct wlan_objmgr_psoc *psoc;
932
933 pdev_priv_obj = reg_get_pdev_obj(pdev);
934 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
935 reg_err("pdev reg component is NULL");
936 return QDF_STATUS_E_INVAL;
937 }
938
939 if (pdev_priv_obj->set_fcc_channel == fcc_constraint) {
940 reg_debug("same fcc_constraint %d", fcc_constraint);
941 return QDF_STATUS_SUCCESS;
942 }
943
944 reg_debug("set fcc_constraint: %d", fcc_constraint);
945
946 psoc = wlan_pdev_get_psoc(pdev);
947 if (!psoc) {
948 reg_err("psoc is NULL");
949 return QDF_STATUS_E_INVAL;
950 }
951
952 psoc_priv_obj = reg_get_psoc_obj(psoc);
953 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
954 reg_err("psoc reg component is NULL");
955 return QDF_STATUS_E_INVAL;
956 }
957
958 psoc_priv_obj->set_fcc_channel = fcc_constraint;
959 pdev_priv_obj->set_fcc_channel = fcc_constraint;
960
961 return QDF_STATUS_SUCCESS;
962 }
963
reg_is_6ghz_band_set(struct wlan_objmgr_pdev * pdev)964 bool reg_is_6ghz_band_set(struct wlan_objmgr_pdev *pdev)
965 {
966 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
967
968 pdev_priv_obj = reg_get_pdev_obj(pdev);
969 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
970 reg_err("pdev reg component is NULL");
971 return false;
972 }
973
974 if (!(pdev_priv_obj->band_capability & BIT(REG_BAND_6G)))
975 return false;
976
977 return true;
978 }
979
reg_get_fcc_constraint(struct wlan_objmgr_pdev * pdev,uint32_t freq)980 bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq)
981 {
982 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
983
984 pdev_priv_obj = reg_get_pdev_obj(pdev);
985 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
986 reg_err("pdev reg component is NULL");
987 return false;
988 }
989
990 if (freq != CHAN_12_CENT_FREQ && freq != CHAN_13_CENT_FREQ)
991 return false;
992
993 if (!pdev_priv_obj->set_fcc_channel)
994 return false;
995
996 return true;
997 }
998
reg_get_country_max_allowed_bw(struct wlan_objmgr_pdev * pdev)999 uint32_t reg_get_country_max_allowed_bw(struct wlan_objmgr_pdev *pdev)
1000 {
1001 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
1002 struct wlan_objmgr_psoc *psoc;
1003
1004 psoc = wlan_pdev_get_psoc(pdev);
1005 if (!psoc) {
1006 reg_err("psoc is NULL");
1007 return 0;
1008 }
1009
1010 psoc_priv_obj = reg_get_psoc_obj(psoc);
1011 if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
1012 reg_err("psoc reg component is NULL");
1013 return 0;
1014 }
1015
1016 return psoc_priv_obj->country_max_allowed_bw;
1017 }
1018
reg_is_user_country_set_allowed(struct wlan_objmgr_psoc * psoc)1019 bool reg_is_user_country_set_allowed(struct wlan_objmgr_psoc *psoc)
1020 {
1021 struct wlan_regulatory_psoc_priv_obj *psoc_reg;
1022
1023 psoc_reg = reg_get_psoc_obj(psoc);
1024 if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
1025 reg_err("psoc reg component is NULL");
1026 return false;
1027 }
1028
1029 if (!psoc_reg->user_ctry_priority &&
1030 psoc_reg->enable_11d_supp_original) {
1031 reg_err_rl("country set from userspace is not allowed");
1032 return false;
1033 }
1034
1035 return true;
1036 }
1037
reg_is_fcc_constraint_set(struct wlan_objmgr_pdev * pdev)1038 bool reg_is_fcc_constraint_set(struct wlan_objmgr_pdev *pdev)
1039 {
1040 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
1041
1042 pdev_priv_obj = reg_get_pdev_obj(pdev);
1043 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
1044 reg_err("pdev reg component is NULL");
1045 return false;
1046 }
1047
1048 if (!pdev_priv_obj->set_fcc_channel)
1049 return false;
1050
1051 return true;
1052 }
1053 #endif /* CONFIG_REG_CLIENT */
1054
1055 /**
1056 * reg_change_pdev_for_config() - Update user configuration in pdev private obj.
1057 * @psoc: Pointer to global psoc structure.
1058 * @object: Pointer to global pdev structure.
1059 * @arg: Pointer to argument list.
1060 */
reg_change_pdev_for_config(struct wlan_objmgr_psoc * psoc,void * object,void * arg)1061 static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc,
1062 void *object, void *arg)
1063 {
1064 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
1065 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
1066 struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
1067
1068 psoc_priv_obj = reg_get_psoc_obj(psoc);
1069 if (!psoc_priv_obj) {
1070 reg_err("psoc priv obj is NULL");
1071 return;
1072 }
1073
1074 pdev_priv_obj = reg_get_pdev_obj(pdev);
1075
1076 if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
1077 reg_err("reg pdev private obj is NULL");
1078 return;
1079 }
1080
1081 pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
1082 pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled;
1083 pdev_priv_obj->force_ssc_disable_indoor_channel =
1084 psoc_priv_obj->force_ssc_disable_indoor_channel;
1085 pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
1086 pdev_priv_obj->sta_sap_scc_on_indoor_channel =
1087 psoc_priv_obj->sta_sap_scc_on_indoor_channel;
1088 pdev_priv_obj->p2p_indoor_ch_support =
1089 psoc_priv_obj->p2p_indoor_ch_support;
1090
1091 reg_compute_pdev_current_chan_list(pdev_priv_obj);
1092
1093 reg_send_scheduler_msg_sb(psoc, pdev);
1094 }
1095
1096 #if defined(CONFIG_BAND_6GHZ) && defined(CONFIG_AFC_SUPPORT)
1097 static inline void
reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars * config_vars)1098 reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
1099 struct reg_config_vars *config_vars)
1100 {
1101 psoc_priv_obj->enable_6ghz_sp_pwrmode_supp =
1102 config_vars->enable_6ghz_sp_pwrmode_supp;
1103 psoc_priv_obj->afc_disable_timer_check =
1104 config_vars->afc_disable_timer_check;
1105 psoc_priv_obj->afc_disable_request_id_check =
1106 config_vars->afc_disable_request_id_check;
1107 psoc_priv_obj->is_afc_reg_noaction =
1108 config_vars->is_afc_reg_noaction;
1109 }
1110 #else
1111 static inline void
reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct reg_config_vars * config_vars)1112 reg_set_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
1113 struct reg_config_vars *config_vars)
1114 {
1115 }
1116 #endif
1117
reg_set_config_vars(struct wlan_objmgr_psoc * psoc,struct reg_config_vars config_vars)1118 QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
1119 struct reg_config_vars config_vars)
1120 {
1121 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
1122 QDF_STATUS status;
1123
1124 psoc_priv_obj = reg_get_psoc_obj(psoc);
1125 if (!psoc_priv_obj) {
1126 reg_err("psoc priv obj is NULL");
1127 return QDF_STATUS_E_FAILURE;
1128 }
1129
1130 psoc_priv_obj->enable_11d_supp_original =
1131 config_vars.enable_11d_support;
1132 psoc_priv_obj->scan_11d_interval = config_vars.scan_11d_interval;
1133 psoc_priv_obj->user_ctry_priority = config_vars.userspace_ctry_priority;
1134 psoc_priv_obj->dfs_enabled = config_vars.dfs_enabled;
1135 psoc_priv_obj->indoor_chan_enabled = config_vars.indoor_chan_enabled;
1136 psoc_priv_obj->force_ssc_disable_indoor_channel =
1137 config_vars.force_ssc_disable_indoor_channel;
1138 psoc_priv_obj->band_capability = config_vars.band_capability;
1139 psoc_priv_obj->restart_beaconing = config_vars.restart_beaconing;
1140 psoc_priv_obj->enable_srd_chan_in_master_mode =
1141 config_vars.enable_srd_chan_in_master_mode;
1142 psoc_priv_obj->enable_11d_in_world_mode =
1143 config_vars.enable_11d_in_world_mode;
1144 psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode =
1145 config_vars.enable_5dot9_ghz_chan_in_master_mode;
1146 psoc_priv_obj->retain_nol_across_regdmn_update =
1147 config_vars.retain_nol_across_regdmn_update;
1148 reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars);
1149 reg_get_coex_unsafe_chan_reg_disable(psoc_priv_obj, config_vars);
1150 psoc_priv_obj->sta_sap_scc_on_indoor_channel =
1151 config_vars.sta_sap_scc_on_indoor_channel;
1152 psoc_priv_obj->p2p_indoor_ch_support =
1153 config_vars.p2p_indoor_ch_support;
1154
1155 reg_set_afc_vars(psoc_priv_obj, &config_vars);
1156
1157 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
1158 if (QDF_IS_STATUS_ERROR(status)) {
1159 reg_err("error taking psoc ref cnt");
1160 return status;
1161 }
1162 status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
1163 reg_change_pdev_for_config,
1164 NULL, 1, WLAN_REGULATORY_SB_ID);
1165 wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
1166
1167 return status;
1168 }
1169
reg_program_mas_chan_list(struct wlan_objmgr_psoc * psoc,struct regulatory_channel * reg_channels,uint8_t * alpha2,enum dfs_reg dfs_region)1170 void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
1171 struct regulatory_channel *reg_channels,
1172 uint8_t *alpha2,
1173 enum dfs_reg dfs_region)
1174 {
1175 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
1176 QDF_STATUS status;
1177 uint32_t count;
1178 enum direction dir;
1179 uint32_t phy_cnt;
1180
1181 psoc_priv_obj = reg_get_psoc_obj(psoc);
1182 if (!psoc_priv_obj) {
1183 reg_err("reg psoc private obj is NULL");
1184 return;
1185 }
1186
1187 qdf_mem_copy(psoc_priv_obj->cur_country, alpha2,
1188 REG_ALPHA2_LEN);
1189 reg_debug("set cur_country %.2s", psoc_priv_obj->cur_country);
1190 for (count = 0; count < NUM_CHANNELS; count++) {
1191 reg_channels[count].chan_num = channel_map[count].chan_num;
1192 reg_channels[count].center_freq =
1193 channel_map[count].center_freq;
1194 reg_channels[count].nol_chan = false;
1195 }
1196
1197 for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
1198 qdf_mem_copy(psoc_priv_obj->mas_chan_params[phy_cnt].
1199 mas_chan_list, reg_channels,
1200 NUM_CHANNELS * sizeof(struct regulatory_channel));
1201
1202 psoc_priv_obj->mas_chan_params[phy_cnt].dfs_region =
1203 dfs_region;
1204 }
1205
1206 dir = SOUTHBOUND;
1207 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
1208 if (QDF_IS_STATUS_ERROR(status)) {
1209 reg_err("error taking psoc ref cnt");
1210 return;
1211 }
1212 status = wlan_objmgr_iterate_obj_list(
1213 psoc, WLAN_PDEV_OP, reg_propagate_mas_chan_list_to_pdev,
1214 &dir, 1, WLAN_REGULATORY_SB_ID);
1215 wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
1216 }
1217
reg_get_cc_and_src(struct wlan_objmgr_psoc * psoc,uint8_t * alpha2)1218 enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
1219 uint8_t *alpha2)
1220 {
1221 struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
1222
1223 psoc_priv_obj = reg_get_psoc_obj(psoc);
1224 if (!psoc_priv_obj) {
1225 reg_err("reg psoc private obj is NULL");
1226 return SOURCE_UNKNOWN;
1227 }
1228
1229 qdf_mem_copy(alpha2, psoc_priv_obj->cur_country, REG_ALPHA2_LEN + 1);
1230
1231 return psoc_priv_obj->cc_src;
1232 }
1233
reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj * soc_reg)1234 void reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj
1235 *soc_reg)
1236 {
1237 uint8_t ctr;
1238
1239 if (!soc_reg->offload_enabled)
1240 return;
1241
1242 for (ctr = 0; ctr < PSOC_MAX_PHY_REG_CAP; ctr++) {
1243 soc_reg->new_user_ctry_pending[ctr] = false;
1244 soc_reg->new_init_ctry_pending[ctr] = false;
1245 soc_reg->new_11d_ctry_pending[ctr] = false;
1246 soc_reg->world_country_pending[ctr] = false;
1247 }
1248 }
1249
reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj * soc_reg,struct cur_regulatory_info * regulat_info,struct wlan_lmac_if_reg_tx_ops * tx_ops)1250 QDF_STATUS reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1251 struct cur_regulatory_info *regulat_info,
1252 struct wlan_lmac_if_reg_tx_ops *tx_ops)
1253 {
1254 struct wlan_objmgr_psoc *psoc = regulat_info->psoc;
1255 struct wlan_objmgr_pdev *pdev;
1256 uint8_t pdev_id;
1257 uint8_t phy_id;
1258 uint8_t phy_num;
1259 struct set_country country_code;
1260 QDF_STATUS status;
1261
1262 /*
1263 * During SSR/WLAN restart ignore master channel list
1264 * for all events and in the last event handling if
1265 * current country and default country is different, send the last
1266 * configured (soc_reg->cur_country) country.
1267 */
1268 if ((regulat_info->num_phy != regulat_info->phy_id + 1) ||
1269 (!qdf_mem_cmp(soc_reg->cur_country, regulat_info->alpha2,
1270 REG_ALPHA2_LEN)))
1271 return QDF_STATUS_SUCCESS;
1272
1273 /*
1274 * Need firmware to send channel list event
1275 * for all phys. Therefore set pdev_id to 0xFF.
1276 */
1277 pdev_id = WMI_HOST_PDEV_ID_SOC;
1278 for (phy_num = 0; phy_num < regulat_info->num_phy; phy_num++) {
1279 if (soc_reg->cc_src == SOURCE_USERSPACE)
1280 soc_reg->new_user_ctry_pending[phy_num] = true;
1281 else if (soc_reg->cc_src == SOURCE_11D)
1282 soc_reg->new_11d_ctry_pending[phy_num] = true;
1283 else
1284 soc_reg->world_country_pending[phy_num] = true;
1285 }
1286
1287 qdf_mem_zero(&country_code, sizeof(country_code));
1288 qdf_mem_copy(country_code.country, soc_reg->cur_country,
1289 sizeof(soc_reg->cur_country));
1290 country_code.pdev_id = pdev_id;
1291
1292 if (soc_reg->offload_enabled) {
1293 if (!tx_ops || !tx_ops->set_country_code) {
1294 reg_err("No regulatory tx_ops");
1295 status = QDF_STATUS_E_FAULT;
1296 goto error;
1297 }
1298 status = tx_ops->set_country_code(psoc, &country_code);
1299 if (QDF_IS_STATUS_ERROR(status)) {
1300 reg_err("Failed to send country code to fw");
1301 goto error;
1302 }
1303 } else {
1304 phy_id = regulat_info->phy_id;
1305 if (tx_ops->get_pdev_id_from_phy_id)
1306 tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id);
1307 else
1308 pdev_id = phy_id;
1309
1310 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
1311 WLAN_REGULATORY_NB_ID);
1312 status = reg_set_non_offload_country(pdev, &country_code);
1313 wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID);
1314 if (QDF_IS_STATUS_ERROR(status)) {
1315 reg_err("Failed to set country code");
1316 goto error;
1317 }
1318 }
1319
1320 reg_debug("Target CC: %.2s, Restore to Previous CC: %.2s",
1321 regulat_info->alpha2, soc_reg->cur_country);
1322
1323 return status;
1324
1325 error:
1326 reg_reset_ctry_pending_hints(soc_reg);
1327
1328 return status;
1329 }
1330
reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj * soc_reg,struct cur_regulatory_info * regulat_info)1331 bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1332 struct cur_regulatory_info *regulat_info)
1333 {
1334 uint8_t phy_num;
1335
1336 if (soc_reg->cc_src == SOURCE_UNKNOWN)
1337 return false;
1338
1339 phy_num = regulat_info->phy_id;
1340 if (soc_reg->new_user_ctry_pending[phy_num] ||
1341 soc_reg->new_init_ctry_pending[phy_num] ||
1342 soc_reg->new_11d_ctry_pending[phy_num] ||
1343 soc_reg->world_country_pending[phy_num])
1344 return false;
1345
1346 return true;
1347 }
1348