xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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
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 
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 
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 
107 /**
108  * reg_set_default_country() - Read the default country for the regdomain
109  * @country: country code.
110  *
111  * Return: QDF_STATUS
112  */
113 QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc,
114 				   uint8_t *country)
115 {
116 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
117 
118 	if (!country) {
119 		reg_err("country is NULL");
120 		return QDF_STATUS_E_INVAL;
121 	}
122 
123 	psoc_reg = reg_get_psoc_obj(psoc);
124 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
125 		reg_err("psoc reg component is NULL");
126 		return QDF_STATUS_E_INVAL;
127 	}
128 
129 	reg_info("set default_country: %s", country);
130 
131 	qdf_mem_copy(psoc_reg->def_country, country, REG_ALPHA2_LEN + 1);
132 
133 	return QDF_STATUS_SUCCESS;
134 }
135 
136 bool reg_is_world_alpha2(uint8_t *alpha2)
137 {
138 	if ((alpha2[0] == '0') && (alpha2[1] == '0'))
139 		return true;
140 
141 	return false;
142 }
143 
144 bool reg_is_us_alpha2(uint8_t *alpha2)
145 {
146 	if ((alpha2[0] == 'U') && (alpha2[1] == 'S'))
147 		return true;
148 
149 	return false;
150 }
151 
152 bool reg_is_etsi_alpha2(uint8_t *alpha2)
153 {
154 	if ((alpha2[0] == 'G') && (alpha2[1] == 'B'))
155 		return true;
156 
157 	return false;
158 }
159 
160 static
161 const char *reg_get_power_mode_string(uint16_t reg_dmn_pair_id)
162 {
163 	switch (reg_dmn_pair_id) {
164 	case FCC3_FCCA:
165 	case FCC6_FCCA:
166 		return "NON_VLP";
167 	default:
168 		return "VLP";
169 	}
170 }
171 
172 static bool reg_ctry_domain_supports_vlp(uint8_t *alpha2)
173 {
174 	uint16_t i;
175 	int no_of_countries;
176 
177 	reg_get_num_countries(&no_of_countries);
178 	for (i = 0; i < no_of_countries; i++) {
179 		if (g_all_countries[i].alpha2[0] == alpha2[0] &&
180 		    g_all_countries[i].alpha2[1] == alpha2[1]) {
181 			if (!qdf_str_cmp(reg_get_power_mode_string(
182 			    g_all_countries[i].reg_dmn_pair_id), "NON_VLP"))
183 				return false;
184 			else
185 				return true;
186 		}
187 	}
188 	return true;
189 }
190 
191 bool reg_ctry_support_vlp(uint8_t *alpha2)
192 {
193 	if (((alpha2[0] == 'A') && (alpha2[1] == 'E')) ||
194 	    ((alpha2[0] == 'P') && (alpha2[1] == 'E')) ||
195 	    ((alpha2[0] == 'U') && (alpha2[1] == 'S')) ||
196 	   !reg_ctry_domain_supports_vlp(alpha2))
197 		return false;
198 	else
199 		return true;
200 }
201 
202 static QDF_STATUS reg_set_non_offload_country(struct wlan_objmgr_pdev *pdev,
203 					      struct set_country *cc)
204 {
205 	struct wlan_objmgr_psoc *psoc;
206 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
207 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
208 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
209 	struct cc_regdmn_s rd;
210 	uint8_t pdev_id;
211 	uint8_t phy_id;
212 
213 	if (!pdev) {
214 		reg_err("pdev is NULL");
215 		return QDF_STATUS_E_INVAL;
216 	}
217 
218 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
219 	psoc = wlan_pdev_get_psoc(pdev);
220 	tx_ops = reg_get_psoc_tx_ops(psoc);
221 	if (tx_ops->get_phy_id_from_pdev_id)
222 		tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
223 	else
224 		phy_id = pdev_id;
225 
226 	psoc_reg = reg_get_psoc_obj(psoc);
227 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
228 		reg_err("psoc reg component is NULL");
229 		return QDF_STATUS_E_INVAL;
230 	}
231 
232 	if (reg_is_world_alpha2(cc->country)) {
233 		pdev_priv_obj = reg_get_pdev_obj(pdev);
234 		if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
235 			reg_err("reg component pdev priv is NULL");
236 			psoc_reg->world_country_pending[phy_id] = false;
237 			return QDF_STATUS_E_INVAL;
238 		}
239 		if (reg_is_world_ctry_code(pdev_priv_obj->def_region_domain))
240 			rd.cc.regdmn.reg_2g_5g_pair_id =
241 				pdev_priv_obj->def_region_domain;
242 		else
243 			rd.cc.regdmn.reg_2g_5g_pair_id = DEFAULT_WORLD_REGDMN;
244 		rd.flags = REGDMN_IS_SET;
245 	} else {
246 		qdf_mem_copy(rd.cc.alpha, cc->country, REG_ALPHA2_LEN + 1);
247 		rd.flags = ALPHA_IS_SET;
248 	}
249 
250 	reg_program_chan_list(pdev, &rd);
251 	return QDF_STATUS_SUCCESS;
252 }
253 
254 #ifdef WLAN_REG_PARTIAL_OFFLOAD
255 /**
256  * reg_restore_def_country_for_po() - API to restore country code to default
257  * value if given country is invalid for Partial Offload
258  * @offload_enabled: Is offload enabled
259  * @country: Country code
260  * @cc_country: Country code array
261  * Return- void
262  */
263 static void reg_restore_def_country_for_po(bool offload_enabled,
264 					   uint8_t *country,
265 					   uint8_t cc_country[]){
266 	if (!offload_enabled && !reg_is_world_alpha2(country)) {
267 		QDF_STATUS status;
268 
269 		status = reg_is_country_code_valid(country);
270 		if (!QDF_IS_STATUS_SUCCESS(status)) {
271 			reg_err("Unable to set country code: %s\n", country);
272 			reg_err("Restoring to world domain");
273 			qdf_mem_copy(cc_country, REG_WORLD_ALPHA2,
274 				     REG_ALPHA2_LEN + 1);
275 		}
276 	}
277 }
278 #else
279 static void reg_restore_def_country_for_po(bool offload_enabled,
280 					   uint8_t *country,
281 					   uint8_t cc_country[]){
282 }
283 #endif
284 
285 QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev,
286 			   uint8_t *country)
287 {
288 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
289 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
290 	struct set_country cc;
291 	struct wlan_objmgr_psoc *psoc;
292 	uint8_t pdev_id;
293 	uint8_t phy_id;
294 
295 	if (!pdev) {
296 		reg_err("pdev is NULL");
297 		return QDF_STATUS_E_INVAL;
298 	}
299 
300 	if (!country) {
301 		reg_err("country code is NULL");
302 		return QDF_STATUS_E_INVAL;
303 	}
304 
305 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
306 
307 	psoc = wlan_pdev_get_psoc(pdev);
308 
309 	tx_ops = reg_get_psoc_tx_ops(psoc);
310 	if (tx_ops->get_phy_id_from_pdev_id)
311 		tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
312 	else
313 		phy_id = pdev_id;
314 
315 	psoc_reg = reg_get_psoc_obj(psoc);
316 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
317 		reg_err("psoc reg component is NULL");
318 		return QDF_STATUS_E_INVAL;
319 	}
320 
321 	if (!qdf_mem_cmp(psoc_reg->cur_country, country, REG_ALPHA2_LEN)) {
322 		if (psoc_reg->cc_src == SOURCE_USERSPACE ||
323 		    psoc_reg->cc_src == SOURCE_CORE) {
324 			reg_debug("country is not different");
325 			return QDF_STATUS_E_INVAL;
326 		}
327 	}
328 
329 	reg_debug("programming new country: %s to firmware", country);
330 
331 	qdf_mem_copy(cc.country, country, REG_ALPHA2_LEN + 1);
332 	/*
333 	 * Need firmware to send channel list event
334 	 * for all phys. Therefore set pdev_id to 0xFF.
335 	 */
336 	cc.pdev_id = WMI_HOST_PDEV_ID_SOC;
337 
338 	reg_restore_def_country_for_po(psoc_reg->offload_enabled,
339 				       country,
340 				       cc.country);
341 
342 	if (reg_is_world_alpha2(cc.country))
343 		psoc_reg->world_country_pending[phy_id] = true;
344 	else
345 		psoc_reg->new_user_ctry_pending[phy_id] = true;
346 
347 	if (psoc_reg->offload_enabled) {
348 		tx_ops = reg_get_psoc_tx_ops(psoc);
349 		if (tx_ops->set_country_code) {
350 			tx_ops->set_country_code(psoc, &cc);
351 		} else {
352 			reg_err("country set fw handler not present");
353 			psoc_reg->new_user_ctry_pending[phy_id] = false;
354 			return QDF_STATUS_E_FAULT;
355 		}
356 	} else {
357 		return reg_set_non_offload_country(pdev, &cc);
358 	}
359 
360 	return QDF_STATUS_SUCCESS;
361 }
362 
363 QDF_STATUS reg_reset_country(struct wlan_objmgr_psoc *psoc)
364 {
365 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
366 
367 	psoc_reg = reg_get_psoc_obj(psoc);
368 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
369 		reg_err("psoc reg component is NULL");
370 		return QDF_STATUS_E_INVAL;
371 	}
372 
373 	qdf_mem_copy(psoc_reg->cur_country,
374 		     psoc_reg->def_country,
375 		     REG_ALPHA2_LEN + 1);
376 	reg_debug("set cur_country %.2s", psoc_reg->cur_country);
377 
378 	return QDF_STATUS_SUCCESS;
379 }
380 
381 QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr,
382 					    const uint8_t *country_alpha2,
383 					    enum country_src source)
384 {
385 	if (!reg_domain_ptr) {
386 		reg_err("Invalid reg domain pointer");
387 		return QDF_STATUS_E_FAULT;
388 	}
389 
390 	*reg_domain_ptr = 0;
391 
392 	if (!country_alpha2) {
393 		reg_err("Country code is NULL");
394 		return QDF_STATUS_E_FAULT;
395 	}
396 
397 	return QDF_STATUS_SUCCESS;
398 }
399 
400 #ifdef CONFIG_REG_CLIENT
401 QDF_STATUS
402 reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc,
403 			       uint8_t *ap_ctry, uint8_t *sta_ctry,
404 			       enum reg_6g_ap_type *pwr_type_6g,
405 			       bool *ctry_code_match,
406 			       enum reg_6g_ap_type ap_pwr_type)
407 {
408 	*pwr_type_6g = REG_INDOOR_AP;
409 
410 	reg_debug("Country IE:%c%c, STA country:%c%c", ap_ctry[0],
411 		  ap_ctry[1], sta_ctry[0], sta_ctry[1]);
412 
413 	if (!qdf_mem_cmp(ap_ctry, sta_ctry, REG_ALPHA2_LEN)) {
414 		*ctry_code_match = true;
415 		return QDF_STATUS_SUCCESS;
416 	}
417 
418 	*ctry_code_match = false;
419 	/*
420 	 * If reg_info=0 not included, STA should operate in VLP mode.
421 	 * If STA country doesn't support VLP, do not return if Wi-Fi
422 	 * safe mode or RF test mode or enable relaxed connection policy,
423 	 * rather STA should operate in LPI mode.
424 	 * wlan_cm_get_check_6ghz_security API returns true if
425 	 * neither Safe mode nor RF test mode are enabled.
426 	 * wlan_cm_get_relaxed_6ghz_conn_policy API returns true if
427 	 * enabled.
428 	 */
429 	if (ap_pwr_type != REG_INDOOR_AP) {
430 		if (wlan_reg_ctry_support_vlp(sta_ctry) &&
431 		    wlan_reg_ctry_support_vlp(ap_ctry)) {
432 			reg_debug("STA ctry doesn't match with AP ctry, switch to VLP");
433 			*pwr_type_6g = REG_VERY_LOW_POWER_AP;
434 		} else {
435 			reg_debug("AP or STA doesn't support VLP");
436 			*pwr_type_6g = REG_INDOOR_AP;
437 		}
438 
439 		if (!wlan_reg_ctry_support_vlp(sta_ctry) &&
440 		    wlan_cm_get_check_6ghz_security(psoc) &&
441 		    !wlan_cm_get_relaxed_6ghz_conn_policy(psoc)) {
442 			reg_err("VLP not supported, can't connect");
443 			return QDF_STATUS_E_NOSUPPORT;
444 		}
445 	}
446 
447 	if (ap_pwr_type == REG_INDOOR_AP) {
448 		reg_debug("Indoor AP, allow STA IN LPI");
449 		*pwr_type_6g = REG_INDOOR_AP;
450 	}
451 
452 	return QDF_STATUS_SUCCESS;
453 }
454 #endif
455 
456 #ifdef FEATURE_WLAN_CH_AVOID_EXT
457 static inline
458 void reg_get_coex_unsafe_chan_nb_user_prefer(
459 		struct wlan_regulatory_psoc_priv_obj
460 		*psoc_priv_obj,
461 		 struct reg_config_vars config_vars)
462 {
463 	psoc_priv_obj->coex_unsafe_chan_nb_user_prefer =
464 		config_vars.coex_unsafe_chan_nb_user_prefer;
465 }
466 
467 static inline
468 void reg_get_coex_unsafe_chan_reg_disable(
469 		struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
470 		struct reg_config_vars config_vars)
471 {
472 	psoc_priv_obj->coex_unsafe_chan_reg_disable =
473 		config_vars.coex_unsafe_chan_reg_disable;
474 }
475 #else
476 static inline
477 void reg_get_coex_unsafe_chan_nb_user_prefer(
478 		struct wlan_regulatory_psoc_priv_obj
479 		*psoc_priv_obj,
480 		struct reg_config_vars config_vars)
481 {
482 }
483 
484 static inline
485 void reg_get_coex_unsafe_chan_reg_disable(
486 		struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
487 		struct reg_config_vars config_vars)
488 {
489 }
490 #endif
491 
492 #ifdef CONFIG_CHAN_FREQ_API
493 bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev,
494 					qdf_freq_t freq)
495 {
496 	enum channel_state chan_state;
497 
498 	chan_state = reg_get_channel_state_for_freq(pdev, freq);
499 
500 	return (chan_state == CHANNEL_STATE_DFS) ||
501 		(chan_state == CHANNEL_STATE_DISABLE);
502 }
503 #endif /* CONFIG_CHAN_FREQ_API */
504 
505 #ifdef WLAN_FEATURE_DSRC
506 #ifdef CONFIG_CHAN_FREQ_API
507 bool reg_is_dsrc_freq(qdf_freq_t freq)
508 {
509 	if (!REG_IS_5GHZ_FREQ(freq))
510 		return false;
511 
512 	if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ))
513 		return false;
514 
515 	return true;
516 }
517 #endif  /*CONFIG_CHAN_FREQ_API*/
518 #else
519 bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev)
520 {
521 	struct cur_regdmn_info cur_reg_dmn;
522 	QDF_STATUS status;
523 
524 	status = reg_get_curr_regdomain(pdev, &cur_reg_dmn);
525 	if (status != QDF_STATUS_SUCCESS) {
526 		reg_debug_rl("Failed to get reg domain");
527 		return false;
528 	}
529 
530 	return reg_etsi13_regdmn(cur_reg_dmn.dmn_id_5g);
531 }
532 
533 #ifdef CONFIG_CHAN_FREQ_API
534 bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev,
535 				     uint16_t freq)
536 {
537 	if (!REG_IS_5GHZ_FREQ(freq))
538 		return false;
539 
540 	if (!(freq >= REG_ETSI13_SRD_START_FREQ &&
541 	      freq <= REG_ETSI13_SRD_END_FREQ))
542 		return false;
543 
544 	return reg_is_etsi13_regdmn(pdev);
545 }
546 #endif /* CONFIG_CHAN_FREQ_API */
547 
548 bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev)
549 {
550 	struct wlan_objmgr_psoc *psoc;
551 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
552 
553 	if (!pdev) {
554 		reg_alert("pdev is NULL");
555 		return true;
556 	}
557 	psoc = wlan_pdev_get_psoc(pdev);
558 
559 	psoc_priv_obj = reg_get_psoc_obj(psoc);
560 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
561 		reg_alert("psoc reg component is NULL");
562 		return true;
563 	}
564 
565 	return psoc_priv_obj->enable_srd_chan_in_master_mode &&
566 	       reg_is_etsi13_regdmn(pdev);
567 }
568 #endif
569 
570 QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap)
571 {
572 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
573 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
574 	struct wlan_objmgr_psoc *psoc;
575 	QDF_STATUS status;
576 
577 	pdev_priv_obj = reg_get_pdev_obj(pdev);
578 
579 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
580 		reg_err("pdev reg component is NULL");
581 		return QDF_STATUS_E_INVAL;
582 	}
583 
584 	if (pdev_priv_obj->band_capability == band_bitmap) {
585 		reg_info("same band %d", band_bitmap);
586 		return QDF_STATUS_SUCCESS;
587 	}
588 
589 	psoc = wlan_pdev_get_psoc(pdev);
590 	if (!psoc) {
591 		reg_err("psoc is NULL");
592 		return QDF_STATUS_E_INVAL;
593 	}
594 
595 	psoc_priv_obj = reg_get_psoc_obj(psoc);
596 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
597 		reg_err("psoc reg component is NULL");
598 		return QDF_STATUS_E_INVAL;
599 	}
600 
601 	reg_info("set band bitmap: %d", band_bitmap);
602 	pdev_priv_obj->band_capability = band_bitmap;
603 
604 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
605 
606 	status = reg_send_scheduler_msg_sb(psoc, pdev);
607 
608 	return status;
609 }
610 
611 QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev,
612 			uint32_t *band_bitmap)
613 {
614 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
615 
616 	pdev_priv_obj = reg_get_pdev_obj(pdev);
617 
618 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
619 		reg_err("pdev reg component is NULL");
620 		return QDF_STATUS_E_INVAL;
621 	}
622 
623 	reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability);
624 	*band_bitmap = pdev_priv_obj->band_capability;
625 
626 	return QDF_STATUS_SUCCESS;
627 }
628 
629 #ifdef DISABLE_CHANNEL_LIST
630 QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev)
631 {
632 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
633 	struct wlan_objmgr_psoc *psoc;
634 	QDF_STATUS status;
635 
636 	pdev_priv_obj = reg_get_pdev_obj(pdev);
637 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
638 		reg_err("pdev reg component is NULL");
639 		return QDF_STATUS_E_INVAL;
640 	}
641 
642 	psoc = wlan_pdev_get_psoc(pdev);
643 	if (!psoc) {
644 		reg_err("psoc is NULL");
645 		return QDF_STATUS_E_INVAL;
646 	}
647 
648 	pdev_priv_obj->disable_cached_channels = false;
649 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
650 	status = reg_send_scheduler_msg_sb(psoc, pdev);
651 	return status;
652 }
653 
654 QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev)
655 {
656 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
657 	struct wlan_objmgr_psoc *psoc;
658 	QDF_STATUS status;
659 
660 	pdev_priv_obj = reg_get_pdev_obj(pdev);
661 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
662 		reg_err("pdev reg component is NULL");
663 		return QDF_STATUS_E_INVAL;
664 	}
665 
666 	psoc = wlan_pdev_get_psoc(pdev);
667 	if (!psoc) {
668 		reg_err("psoc is NULL");
669 		return QDF_STATUS_E_INVAL;
670 	}
671 
672 	pdev_priv_obj->disable_cached_channels = true;
673 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
674 	status = reg_send_scheduler_msg_sb(psoc, pdev);
675 	return status;
676 }
677 
678 #ifdef CONFIG_CHAN_FREQ_API
679 QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev,
680 					uint32_t *channel_list,
681 					uint32_t num_channels)
682 {
683 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
684 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
685 	struct wlan_objmgr_psoc *psoc;
686 	uint16_t i, j;
687 
688 	pdev_priv_obj = reg_get_pdev_obj(pdev);
689 
690 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
691 		reg_err("pdev reg component is NULL");
692 		return QDF_STATUS_E_INVAL;
693 	}
694 
695 	psoc = wlan_pdev_get_psoc(pdev);
696 	if (!psoc) {
697 		reg_err("psoc is NULL");
698 		return QDF_STATUS_E_INVAL;
699 	}
700 
701 	psoc_priv_obj = reg_get_psoc_obj(psoc);
702 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
703 		reg_err("psoc reg component is NULL");
704 		return QDF_STATUS_E_INVAL;
705 	}
706 	if (pdev_priv_obj->num_cache_channels > 0) {
707 		pdev_priv_obj->num_cache_channels = 0;
708 		qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list,
709 			     sizeof(pdev_priv_obj->cache_disable_chan_list));
710 	}
711 
712 	for (i = 0; i < num_channels; i++) {
713 		for (j = 0; j < NUM_CHANNELS; j++) {
714 			if (channel_list[i] == pdev_priv_obj->
715 						cur_chan_list[j].center_freq) {
716 				pdev_priv_obj->
717 					cache_disable_chan_list[i].center_freq =
718 							channel_list[i];
719 				pdev_priv_obj->
720 					cache_disable_chan_list[i].state =
721 					pdev_priv_obj->cur_chan_list[j].state;
722 				pdev_priv_obj->
723 					cache_disable_chan_list[i].chan_flags =
724 					pdev_priv_obj->
725 						cur_chan_list[j].chan_flags;
726 			}
727 		}
728 	}
729 	pdev_priv_obj->num_cache_channels = num_channels;
730 
731 	return QDF_STATUS_SUCCESS;
732 }
733 #endif /* CONFIG_CHAN_FREQ_API */
734 #endif
735 
736 #ifdef CONFIG_REG_CLIENT
737 
738 QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev,
739 				  bool fcc_constraint)
740 {
741 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
742 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
743 	struct wlan_objmgr_psoc *psoc;
744 	QDF_STATUS status;
745 
746 	pdev_priv_obj = reg_get_pdev_obj(pdev);
747 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
748 		reg_err("pdev reg component is NULL");
749 		return QDF_STATUS_E_INVAL;
750 	}
751 
752 	if (pdev_priv_obj->set_fcc_channel == fcc_constraint) {
753 		reg_debug("same fcc_constraint %d", fcc_constraint);
754 		return QDF_STATUS_SUCCESS;
755 	}
756 
757 	reg_debug("set fcc_constraint: %d", fcc_constraint);
758 
759 	psoc = wlan_pdev_get_psoc(pdev);
760 	if (!psoc) {
761 		reg_err("psoc is NULL");
762 		return QDF_STATUS_E_INVAL;
763 	}
764 
765 	psoc_priv_obj = reg_get_psoc_obj(psoc);
766 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
767 		reg_err("psoc reg component is NULL");
768 		return QDF_STATUS_E_INVAL;
769 	}
770 
771 	psoc_priv_obj->set_fcc_channel = fcc_constraint;
772 	pdev_priv_obj->set_fcc_channel = fcc_constraint;
773 
774 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
775 
776 	status = reg_send_scheduler_msg_sb(psoc, pdev);
777 
778 	return status;
779 }
780 
781 bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq)
782 {
783 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
784 
785 	pdev_priv_obj = reg_get_pdev_obj(pdev);
786 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
787 		reg_err("pdev reg component is NULL");
788 		return false;
789 	}
790 
791 	if (freq != CHAN_12_CENT_FREQ && freq != CHAN_13_CENT_FREQ)
792 		return false;
793 
794 	if (!pdev_priv_obj->set_fcc_channel)
795 		return false;
796 
797 	return true;
798 }
799 
800 #ifdef CONFIG_BAND_6GHZ
801 /**
802  * reg_is_afc_available() - check if the automated frequency control system is
803  * available, function will need to be updated once AFC is implemented
804  * @pdev: Pointer to pdev structure
805  *
806  * Return: false since the AFC system is not yet available
807  */
808 static bool reg_is_afc_available(struct wlan_objmgr_pdev *pdev)
809 {
810 	return false;
811 }
812 
813 enum reg_6g_ap_type reg_decide_6g_ap_pwr_type(struct wlan_objmgr_pdev *pdev)
814 {
815 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
816 	enum reg_6g_ap_type ap_pwr_type = REG_INDOOR_AP;
817 
818 	pdev_priv_obj = reg_get_pdev_obj(pdev);
819 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
820 		reg_err("pdev reg component is NULL");
821 		return REG_VERY_LOW_POWER_AP;
822 	}
823 
824 	if (reg_is_afc_available(pdev)) {
825 		ap_pwr_type = REG_STANDARD_POWER_AP;
826 	} else if (pdev_priv_obj->indoor_chan_enabled) {
827 		if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_INDOOR_AP])
828 			ap_pwr_type = REG_INDOOR_AP;
829 		else
830 			ap_pwr_type = REG_VERY_LOW_POWER_AP;
831 	} else if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_VERY_LOW_POWER_AP]) {
832 		ap_pwr_type = REG_VERY_LOW_POWER_AP;
833 	}
834 	reg_debug("indoor_chan_enabled %d ap_pwr_type %d",
835 		  pdev_priv_obj->indoor_chan_enabled, ap_pwr_type);
836 
837 	reg_set_ap_pwr_and_update_chan_list(pdev, ap_pwr_type);
838 
839 	return ap_pwr_type;
840 }
841 #endif /* CONFIG_BAND_6GHZ */
842 
843 #endif /* CONFIG_REG_CLIENT */
844 
845 /**
846  * reg_change_pdev_for_config() - Update user configuration in pdev private obj.
847  * @psoc: Pointer to global psoc structure.
848  * @object: Pointer to global pdev structure.
849  * @arg: Pointer to argument list.
850  */
851 static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc,
852 				       void *object, void *arg)
853 {
854 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
855 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
856 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
857 
858 	psoc_priv_obj = reg_get_psoc_obj(psoc);
859 	if (!psoc_priv_obj) {
860 		reg_err("psoc priv obj is NULL");
861 		return;
862 	}
863 
864 	pdev_priv_obj = reg_get_pdev_obj(pdev);
865 
866 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
867 		reg_err("reg pdev private obj is NULL");
868 		return;
869 	}
870 
871 	pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
872 	pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled;
873 	pdev_priv_obj->force_ssc_disable_indoor_channel =
874 		psoc_priv_obj->force_ssc_disable_indoor_channel;
875 	pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
876 	pdev_priv_obj->sta_sap_scc_on_indoor_channel =
877 		psoc_priv_obj->sta_sap_scc_on_indoor_channel;
878 
879 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
880 
881 	reg_send_scheduler_msg_sb(psoc, pdev);
882 }
883 
884 QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
885 			       struct reg_config_vars config_vars)
886 {
887 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
888 	QDF_STATUS status;
889 
890 	psoc_priv_obj = reg_get_psoc_obj(psoc);
891 	if (!psoc_priv_obj) {
892 		reg_err("psoc priv obj is NULL");
893 		return QDF_STATUS_E_FAILURE;
894 	}
895 
896 	psoc_priv_obj->enable_11d_supp_original =
897 		config_vars.enable_11d_support;
898 	psoc_priv_obj->scan_11d_interval = config_vars.scan_11d_interval;
899 	psoc_priv_obj->user_ctry_priority = config_vars.userspace_ctry_priority;
900 	psoc_priv_obj->dfs_enabled = config_vars.dfs_enabled;
901 	psoc_priv_obj->indoor_chan_enabled = config_vars.indoor_chan_enabled;
902 	psoc_priv_obj->force_ssc_disable_indoor_channel =
903 		config_vars.force_ssc_disable_indoor_channel;
904 	psoc_priv_obj->band_capability = config_vars.band_capability;
905 	psoc_priv_obj->restart_beaconing = config_vars.restart_beaconing;
906 	psoc_priv_obj->enable_srd_chan_in_master_mode =
907 		config_vars.enable_srd_chan_in_master_mode;
908 	psoc_priv_obj->enable_11d_in_world_mode =
909 		config_vars.enable_11d_in_world_mode;
910 	psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode =
911 		config_vars.enable_5dot9_ghz_chan_in_master_mode;
912 	psoc_priv_obj->retain_nol_across_regdmn_update =
913 		config_vars.retain_nol_across_regdmn_update;
914 	reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars);
915 	reg_get_coex_unsafe_chan_reg_disable(psoc_priv_obj, config_vars);
916 	psoc_priv_obj->sta_sap_scc_on_indoor_channel =
917 		config_vars.sta_sap_scc_on_indoor_channel;
918 
919 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
920 	if (QDF_IS_STATUS_ERROR(status)) {
921 		reg_err("error taking psoc ref cnt");
922 		return status;
923 	}
924 	status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
925 					      reg_change_pdev_for_config,
926 					      NULL, 1, WLAN_REGULATORY_SB_ID);
927 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
928 
929 	return status;
930 }
931 
932 void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
933 			       struct regulatory_channel *reg_channels,
934 			       uint8_t *alpha2,
935 			       enum dfs_reg dfs_region)
936 {
937 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
938 	QDF_STATUS status;
939 	uint32_t count;
940 	enum direction dir;
941 	uint32_t phy_cnt;
942 
943 	psoc_priv_obj = reg_get_psoc_obj(psoc);
944 	if (!psoc_priv_obj) {
945 		reg_err("reg psoc private obj is NULL");
946 		return;
947 	}
948 
949 	qdf_mem_copy(psoc_priv_obj->cur_country, alpha2,
950 		     REG_ALPHA2_LEN);
951 	reg_debug("set cur_country %.2s", psoc_priv_obj->cur_country);
952 	for (count = 0; count < NUM_CHANNELS; count++) {
953 		reg_channels[count].chan_num = channel_map[count].chan_num;
954 		reg_channels[count].center_freq =
955 			channel_map[count].center_freq;
956 		reg_channels[count].nol_chan = false;
957 	}
958 
959 	for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
960 		qdf_mem_copy(psoc_priv_obj->mas_chan_params[phy_cnt].
961 			     mas_chan_list, reg_channels,
962 			     NUM_CHANNELS * sizeof(struct regulatory_channel));
963 
964 		psoc_priv_obj->mas_chan_params[phy_cnt].dfs_region =
965 			dfs_region;
966 	}
967 
968 	dir = SOUTHBOUND;
969 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
970 	if (QDF_IS_STATUS_ERROR(status)) {
971 		reg_err("error taking psoc ref cnt");
972 		return;
973 	}
974 	status = wlan_objmgr_iterate_obj_list(
975 			psoc, WLAN_PDEV_OP, reg_propagate_mas_chan_list_to_pdev,
976 			&dir, 1, WLAN_REGULATORY_SB_ID);
977 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
978 }
979 
980 enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
981 				    uint8_t *alpha2)
982 {
983 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
984 
985 	psoc_priv_obj = reg_get_psoc_obj(psoc);
986 	if (!psoc_priv_obj) {
987 		reg_err("reg psoc private obj is NULL");
988 		return SOURCE_UNKNOWN;
989 	}
990 
991 	qdf_mem_copy(alpha2, psoc_priv_obj->cur_country, REG_ALPHA2_LEN + 1);
992 
993 	return psoc_priv_obj->cc_src;
994 }
995 
996 void reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj
997 				  *soc_reg)
998 {
999 	uint8_t ctr;
1000 
1001 	if (!soc_reg->offload_enabled)
1002 		return;
1003 
1004 	for (ctr = 0; ctr < PSOC_MAX_PHY_REG_CAP; ctr++) {
1005 		soc_reg->new_user_ctry_pending[ctr] = false;
1006 		soc_reg->new_init_ctry_pending[ctr] = false;
1007 		soc_reg->new_11d_ctry_pending[ctr] = false;
1008 		soc_reg->world_country_pending[ctr] = false;
1009 	}
1010 }
1011 
1012 QDF_STATUS reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1013 				struct cur_regulatory_info *regulat_info,
1014 				struct wlan_lmac_if_reg_tx_ops *tx_ops)
1015 {
1016 	struct wlan_objmgr_psoc *psoc = regulat_info->psoc;
1017 	struct wlan_objmgr_pdev *pdev;
1018 	uint8_t pdev_id;
1019 	uint8_t phy_id;
1020 	uint8_t phy_num;
1021 	struct set_country country_code;
1022 	QDF_STATUS status;
1023 
1024 	/*
1025 	 * During SSR/WLAN restart ignore master channel list
1026 	 * for all events and in the last event handling if
1027 	 * current country and default country is different, send the last
1028 	 * configured (soc_reg->cur_country) country.
1029 	 */
1030 	if ((regulat_info->num_phy != regulat_info->phy_id + 1) ||
1031 	    (!qdf_mem_cmp(soc_reg->cur_country, regulat_info->alpha2,
1032 			  REG_ALPHA2_LEN)))
1033 		return QDF_STATUS_SUCCESS;
1034 
1035 	/*
1036 	 * Need firmware to send channel list event
1037 	 * for all phys. Therefore set pdev_id to 0xFF.
1038 	 */
1039 	pdev_id = WMI_HOST_PDEV_ID_SOC;
1040 	for (phy_num = 0; phy_num < regulat_info->num_phy; phy_num++) {
1041 		if (soc_reg->cc_src == SOURCE_USERSPACE)
1042 			soc_reg->new_user_ctry_pending[phy_num] = true;
1043 		else if (soc_reg->cc_src == SOURCE_11D)
1044 			soc_reg->new_11d_ctry_pending[phy_num] = true;
1045 		else
1046 			soc_reg->world_country_pending[phy_num] = true;
1047 	}
1048 
1049 	qdf_mem_zero(&country_code, sizeof(country_code));
1050 	qdf_mem_copy(country_code.country, soc_reg->cur_country,
1051 		     sizeof(soc_reg->cur_country));
1052 	country_code.pdev_id = pdev_id;
1053 
1054 	if (soc_reg->offload_enabled) {
1055 		if (!tx_ops || !tx_ops->set_country_code) {
1056 			reg_err("No regulatory tx_ops");
1057 			status = QDF_STATUS_E_FAULT;
1058 			goto error;
1059 		}
1060 		status = tx_ops->set_country_code(psoc, &country_code);
1061 		if (QDF_IS_STATUS_ERROR(status)) {
1062 			reg_err("Failed to send country code to fw");
1063 			goto error;
1064 		}
1065 	} else {
1066 		phy_id = regulat_info->phy_id;
1067 		if (tx_ops->get_pdev_id_from_phy_id)
1068 			tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id);
1069 		else
1070 			pdev_id = phy_id;
1071 
1072 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
1073 						  WLAN_REGULATORY_NB_ID);
1074 		status = reg_set_non_offload_country(pdev, &country_code);
1075 		wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID);
1076 		if (QDF_IS_STATUS_ERROR(status)) {
1077 			reg_err("Failed to set country code");
1078 			goto error;
1079 		}
1080 	}
1081 
1082 	reg_debug("Target CC: %.2s, Restore to Previous CC: %.2s",
1083 		  regulat_info->alpha2, soc_reg->cur_country);
1084 
1085 	return status;
1086 
1087 error:
1088 	reg_reset_ctry_pending_hints(soc_reg);
1089 
1090 	return status;
1091 }
1092 
1093 bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1094 				struct cur_regulatory_info *regulat_info)
1095 {
1096 	uint8_t phy_num;
1097 
1098 	if (soc_reg->cc_src == SOURCE_UNKNOWN)
1099 		return false;
1100 
1101 	phy_num = regulat_info->phy_id;
1102 	if (soc_reg->new_user_ctry_pending[phy_num] ||
1103 	    soc_reg->new_init_ctry_pending[phy_num] ||
1104 	    soc_reg->new_11d_ctry_pending[phy_num] ||
1105 	    soc_reg->world_country_pending[phy_num])
1106 		return false;
1107 
1108 	return true;
1109 }
1110