xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
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_pwrmode(
494 				struct wlan_objmgr_pdev *pdev,
495 				qdf_freq_t freq,
496 				enum supported_6g_pwr_types in_6g_pwr_mode)
497 {
498 	enum channel_state chan_state;
499 
500 	chan_state = reg_get_channel_state_for_pwrmode(pdev, freq,
501 						       in_6g_pwr_mode);
502 
503 	return (chan_state == CHANNEL_STATE_DFS) ||
504 		(chan_state == CHANNEL_STATE_DISABLE);
505 }
506 #endif /* CONFIG_CHAN_FREQ_API */
507 
508 #ifdef WLAN_FEATURE_DSRC
509 #ifdef CONFIG_CHAN_FREQ_API
510 bool reg_is_dsrc_freq(qdf_freq_t freq)
511 {
512 	if (!REG_IS_5GHZ_FREQ(freq))
513 		return false;
514 
515 	if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ))
516 		return false;
517 
518 	return true;
519 }
520 #endif  /*CONFIG_CHAN_FREQ_API*/
521 #else
522 bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev)
523 {
524 	struct cur_regdmn_info cur_reg_dmn;
525 	QDF_STATUS status;
526 
527 	status = reg_get_curr_regdomain(pdev, &cur_reg_dmn);
528 	if (status != QDF_STATUS_SUCCESS) {
529 		reg_debug_rl("Failed to get reg domain");
530 		return false;
531 	}
532 
533 	return reg_etsi13_regdmn(cur_reg_dmn.dmn_id_5g);
534 }
535 
536 #ifdef CONFIG_CHAN_FREQ_API
537 bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev,
538 				     uint16_t freq)
539 {
540 	if (!REG_IS_5GHZ_FREQ(freq))
541 		return false;
542 
543 	if (!(freq >= REG_ETSI13_SRD_START_FREQ &&
544 	      freq <= REG_ETSI13_SRD_END_FREQ))
545 		return false;
546 
547 	return reg_is_etsi13_regdmn(pdev);
548 }
549 #endif /* CONFIG_CHAN_FREQ_API */
550 
551 bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev)
552 {
553 	struct wlan_objmgr_psoc *psoc;
554 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
555 
556 	if (!pdev) {
557 		reg_alert("pdev is NULL");
558 		return true;
559 	}
560 	psoc = wlan_pdev_get_psoc(pdev);
561 
562 	psoc_priv_obj = reg_get_psoc_obj(psoc);
563 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
564 		reg_alert("psoc reg component is NULL");
565 		return true;
566 	}
567 
568 	return psoc_priv_obj->enable_srd_chan_in_master_mode &&
569 	       reg_is_etsi13_regdmn(pdev);
570 }
571 #endif
572 
573 QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap)
574 {
575 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
576 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
577 	struct wlan_objmgr_psoc *psoc;
578 	QDF_STATUS status;
579 
580 	pdev_priv_obj = reg_get_pdev_obj(pdev);
581 
582 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
583 		reg_err("pdev reg component is NULL");
584 		return QDF_STATUS_E_INVAL;
585 	}
586 
587 	if (pdev_priv_obj->band_capability == band_bitmap) {
588 		reg_info("same band %d", band_bitmap);
589 		return QDF_STATUS_SUCCESS;
590 	}
591 
592 	psoc = wlan_pdev_get_psoc(pdev);
593 	if (!psoc) {
594 		reg_err("psoc is NULL");
595 		return QDF_STATUS_E_INVAL;
596 	}
597 
598 	psoc_priv_obj = reg_get_psoc_obj(psoc);
599 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
600 		reg_err("psoc reg component is NULL");
601 		return QDF_STATUS_E_INVAL;
602 	}
603 
604 	reg_info("set band bitmap: %d", band_bitmap);
605 	pdev_priv_obj->band_capability = band_bitmap;
606 
607 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
608 
609 	status = reg_send_scheduler_msg_sb(psoc, pdev);
610 
611 	return status;
612 }
613 
614 QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev,
615 			uint32_t *band_bitmap)
616 {
617 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
618 
619 	pdev_priv_obj = reg_get_pdev_obj(pdev);
620 
621 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
622 		reg_err("pdev reg component is NULL");
623 		return QDF_STATUS_E_INVAL;
624 	}
625 
626 	reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability);
627 	*band_bitmap = pdev_priv_obj->band_capability;
628 
629 	return QDF_STATUS_SUCCESS;
630 }
631 
632 #ifdef DISABLE_CHANNEL_LIST
633 QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev)
634 {
635 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
636 	struct wlan_objmgr_psoc *psoc;
637 	QDF_STATUS status;
638 
639 	pdev_priv_obj = reg_get_pdev_obj(pdev);
640 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
641 		reg_err("pdev reg component is NULL");
642 		return QDF_STATUS_E_INVAL;
643 	}
644 
645 	psoc = wlan_pdev_get_psoc(pdev);
646 	if (!psoc) {
647 		reg_err("psoc is NULL");
648 		return QDF_STATUS_E_INVAL;
649 	}
650 
651 	pdev_priv_obj->disable_cached_channels = false;
652 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
653 	status = reg_send_scheduler_msg_sb(psoc, pdev);
654 	return status;
655 }
656 
657 QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev)
658 {
659 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
660 	struct wlan_objmgr_psoc *psoc;
661 	QDF_STATUS status;
662 
663 	pdev_priv_obj = reg_get_pdev_obj(pdev);
664 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
665 		reg_err("pdev reg component is NULL");
666 		return QDF_STATUS_E_INVAL;
667 	}
668 
669 	psoc = wlan_pdev_get_psoc(pdev);
670 	if (!psoc) {
671 		reg_err("psoc is NULL");
672 		return QDF_STATUS_E_INVAL;
673 	}
674 
675 	pdev_priv_obj->disable_cached_channels = true;
676 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
677 	status = reg_send_scheduler_msg_sb(psoc, pdev);
678 	return status;
679 }
680 
681 #ifdef CONFIG_CHAN_FREQ_API
682 QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev,
683 					uint32_t *channel_list,
684 					uint32_t num_channels)
685 {
686 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
687 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
688 	struct wlan_objmgr_psoc *psoc;
689 	uint16_t i, j;
690 
691 	pdev_priv_obj = reg_get_pdev_obj(pdev);
692 
693 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
694 		reg_err("pdev reg component is NULL");
695 		return QDF_STATUS_E_INVAL;
696 	}
697 
698 	psoc = wlan_pdev_get_psoc(pdev);
699 	if (!psoc) {
700 		reg_err("psoc is NULL");
701 		return QDF_STATUS_E_INVAL;
702 	}
703 
704 	psoc_priv_obj = reg_get_psoc_obj(psoc);
705 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
706 		reg_err("psoc reg component is NULL");
707 		return QDF_STATUS_E_INVAL;
708 	}
709 	if (pdev_priv_obj->num_cache_channels > 0) {
710 		pdev_priv_obj->num_cache_channels = 0;
711 		qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list,
712 			     sizeof(pdev_priv_obj->cache_disable_chan_list));
713 	}
714 
715 	for (i = 0; i < num_channels; i++) {
716 		for (j = 0; j < NUM_CHANNELS; j++) {
717 			if (channel_list[i] == pdev_priv_obj->
718 						cur_chan_list[j].center_freq) {
719 				pdev_priv_obj->
720 					cache_disable_chan_list[i].center_freq =
721 							channel_list[i];
722 				pdev_priv_obj->
723 					cache_disable_chan_list[i].state =
724 					pdev_priv_obj->cur_chan_list[j].state;
725 				pdev_priv_obj->
726 					cache_disable_chan_list[i].chan_flags =
727 					pdev_priv_obj->
728 						cur_chan_list[j].chan_flags;
729 			}
730 		}
731 	}
732 	pdev_priv_obj->num_cache_channels = num_channels;
733 
734 	return QDF_STATUS_SUCCESS;
735 }
736 #endif /* CONFIG_CHAN_FREQ_API */
737 #endif
738 
739 #ifdef CONFIG_REG_CLIENT
740 
741 QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev,
742 				  bool fcc_constraint)
743 {
744 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
745 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
746 	struct wlan_objmgr_psoc *psoc;
747 	QDF_STATUS status;
748 
749 	pdev_priv_obj = reg_get_pdev_obj(pdev);
750 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
751 		reg_err("pdev reg component is NULL");
752 		return QDF_STATUS_E_INVAL;
753 	}
754 
755 	if (pdev_priv_obj->set_fcc_channel == fcc_constraint) {
756 		reg_debug("same fcc_constraint %d", fcc_constraint);
757 		return QDF_STATUS_SUCCESS;
758 	}
759 
760 	reg_debug("set fcc_constraint: %d", fcc_constraint);
761 
762 	psoc = wlan_pdev_get_psoc(pdev);
763 	if (!psoc) {
764 		reg_err("psoc is NULL");
765 		return QDF_STATUS_E_INVAL;
766 	}
767 
768 	psoc_priv_obj = reg_get_psoc_obj(psoc);
769 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
770 		reg_err("psoc reg component is NULL");
771 		return QDF_STATUS_E_INVAL;
772 	}
773 
774 	psoc_priv_obj->set_fcc_channel = fcc_constraint;
775 	pdev_priv_obj->set_fcc_channel = fcc_constraint;
776 
777 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
778 
779 	status = reg_send_scheduler_msg_sb(psoc, pdev);
780 
781 	return status;
782 }
783 
784 bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq)
785 {
786 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
787 
788 	pdev_priv_obj = reg_get_pdev_obj(pdev);
789 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
790 		reg_err("pdev reg component is NULL");
791 		return false;
792 	}
793 
794 	if (freq != CHAN_12_CENT_FREQ && freq != CHAN_13_CENT_FREQ)
795 		return false;
796 
797 	if (!pdev_priv_obj->set_fcc_channel)
798 		return false;
799 
800 	return true;
801 }
802 
803 #ifdef CONFIG_BAND_6GHZ
804 /**
805  * reg_is_afc_available() - check if the automated frequency control system is
806  * available, function will need to be updated once AFC is implemented
807  * @pdev: Pointer to pdev structure
808  *
809  * Return: false since the AFC system is not yet available
810  */
811 static bool reg_is_afc_available(struct wlan_objmgr_pdev *pdev)
812 {
813 	return false;
814 }
815 
816 enum reg_6g_ap_type reg_decide_6g_ap_pwr_type(struct wlan_objmgr_pdev *pdev)
817 {
818 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
819 	enum reg_6g_ap_type ap_pwr_type = REG_INDOOR_AP;
820 
821 	pdev_priv_obj = reg_get_pdev_obj(pdev);
822 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
823 		reg_err("pdev reg component is NULL");
824 		return REG_VERY_LOW_POWER_AP;
825 	}
826 
827 	if (reg_is_afc_available(pdev)) {
828 		ap_pwr_type = REG_STANDARD_POWER_AP;
829 	} else if (pdev_priv_obj->indoor_chan_enabled) {
830 		if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_INDOOR_AP])
831 			ap_pwr_type = REG_INDOOR_AP;
832 		else
833 			ap_pwr_type = REG_VERY_LOW_POWER_AP;
834 	} else if (pdev_priv_obj->reg_rules.num_of_6g_ap_reg_rules[REG_VERY_LOW_POWER_AP]) {
835 		ap_pwr_type = REG_VERY_LOW_POWER_AP;
836 	}
837 	reg_debug("indoor_chan_enabled %d ap_pwr_type %d",
838 		  pdev_priv_obj->indoor_chan_enabled, ap_pwr_type);
839 
840 	reg_set_ap_pwr_and_update_chan_list(pdev, ap_pwr_type);
841 
842 	return ap_pwr_type;
843 }
844 #endif /* CONFIG_BAND_6GHZ */
845 
846 #endif /* CONFIG_REG_CLIENT */
847 
848 /**
849  * reg_change_pdev_for_config() - Update user configuration in pdev private obj.
850  * @psoc: Pointer to global psoc structure.
851  * @object: Pointer to global pdev structure.
852  * @arg: Pointer to argument list.
853  */
854 static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc,
855 				       void *object, void *arg)
856 {
857 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
858 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
859 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
860 
861 	psoc_priv_obj = reg_get_psoc_obj(psoc);
862 	if (!psoc_priv_obj) {
863 		reg_err("psoc priv obj is NULL");
864 		return;
865 	}
866 
867 	pdev_priv_obj = reg_get_pdev_obj(pdev);
868 
869 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
870 		reg_err("reg pdev private obj is NULL");
871 		return;
872 	}
873 
874 	pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
875 	pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled;
876 	pdev_priv_obj->force_ssc_disable_indoor_channel =
877 		psoc_priv_obj->force_ssc_disable_indoor_channel;
878 	pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
879 	pdev_priv_obj->sta_sap_scc_on_indoor_channel =
880 		psoc_priv_obj->sta_sap_scc_on_indoor_channel;
881 
882 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
883 
884 	reg_send_scheduler_msg_sb(psoc, pdev);
885 }
886 
887 QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
888 			       struct reg_config_vars config_vars)
889 {
890 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
891 	QDF_STATUS status;
892 
893 	psoc_priv_obj = reg_get_psoc_obj(psoc);
894 	if (!psoc_priv_obj) {
895 		reg_err("psoc priv obj is NULL");
896 		return QDF_STATUS_E_FAILURE;
897 	}
898 
899 	psoc_priv_obj->enable_11d_supp_original =
900 		config_vars.enable_11d_support;
901 	psoc_priv_obj->scan_11d_interval = config_vars.scan_11d_interval;
902 	psoc_priv_obj->user_ctry_priority = config_vars.userspace_ctry_priority;
903 	psoc_priv_obj->dfs_enabled = config_vars.dfs_enabled;
904 	psoc_priv_obj->indoor_chan_enabled = config_vars.indoor_chan_enabled;
905 	psoc_priv_obj->force_ssc_disable_indoor_channel =
906 		config_vars.force_ssc_disable_indoor_channel;
907 	psoc_priv_obj->band_capability = config_vars.band_capability;
908 	psoc_priv_obj->restart_beaconing = config_vars.restart_beaconing;
909 	psoc_priv_obj->enable_srd_chan_in_master_mode =
910 		config_vars.enable_srd_chan_in_master_mode;
911 	psoc_priv_obj->enable_11d_in_world_mode =
912 		config_vars.enable_11d_in_world_mode;
913 	psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode =
914 		config_vars.enable_5dot9_ghz_chan_in_master_mode;
915 	psoc_priv_obj->retain_nol_across_regdmn_update =
916 		config_vars.retain_nol_across_regdmn_update;
917 	reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars);
918 	reg_get_coex_unsafe_chan_reg_disable(psoc_priv_obj, config_vars);
919 	psoc_priv_obj->sta_sap_scc_on_indoor_channel =
920 		config_vars.sta_sap_scc_on_indoor_channel;
921 
922 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
923 	if (QDF_IS_STATUS_ERROR(status)) {
924 		reg_err("error taking psoc ref cnt");
925 		return status;
926 	}
927 	status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
928 					      reg_change_pdev_for_config,
929 					      NULL, 1, WLAN_REGULATORY_SB_ID);
930 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
931 
932 	return status;
933 }
934 
935 void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
936 			       struct regulatory_channel *reg_channels,
937 			       uint8_t *alpha2,
938 			       enum dfs_reg dfs_region)
939 {
940 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
941 	QDF_STATUS status;
942 	uint32_t count;
943 	enum direction dir;
944 	uint32_t phy_cnt;
945 
946 	psoc_priv_obj = reg_get_psoc_obj(psoc);
947 	if (!psoc_priv_obj) {
948 		reg_err("reg psoc private obj is NULL");
949 		return;
950 	}
951 
952 	qdf_mem_copy(psoc_priv_obj->cur_country, alpha2,
953 		     REG_ALPHA2_LEN);
954 	reg_debug("set cur_country %.2s", psoc_priv_obj->cur_country);
955 	for (count = 0; count < NUM_CHANNELS; count++) {
956 		reg_channels[count].chan_num = channel_map[count].chan_num;
957 		reg_channels[count].center_freq =
958 			channel_map[count].center_freq;
959 		reg_channels[count].nol_chan = false;
960 	}
961 
962 	for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
963 		qdf_mem_copy(psoc_priv_obj->mas_chan_params[phy_cnt].
964 			     mas_chan_list, reg_channels,
965 			     NUM_CHANNELS * sizeof(struct regulatory_channel));
966 
967 		psoc_priv_obj->mas_chan_params[phy_cnt].dfs_region =
968 			dfs_region;
969 	}
970 
971 	dir = SOUTHBOUND;
972 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
973 	if (QDF_IS_STATUS_ERROR(status)) {
974 		reg_err("error taking psoc ref cnt");
975 		return;
976 	}
977 	status = wlan_objmgr_iterate_obj_list(
978 			psoc, WLAN_PDEV_OP, reg_propagate_mas_chan_list_to_pdev,
979 			&dir, 1, WLAN_REGULATORY_SB_ID);
980 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
981 }
982 
983 enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
984 				    uint8_t *alpha2)
985 {
986 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
987 
988 	psoc_priv_obj = reg_get_psoc_obj(psoc);
989 	if (!psoc_priv_obj) {
990 		reg_err("reg psoc private obj is NULL");
991 		return SOURCE_UNKNOWN;
992 	}
993 
994 	qdf_mem_copy(alpha2, psoc_priv_obj->cur_country, REG_ALPHA2_LEN + 1);
995 
996 	return psoc_priv_obj->cc_src;
997 }
998 
999 void reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj
1000 				  *soc_reg)
1001 {
1002 	uint8_t ctr;
1003 
1004 	if (!soc_reg->offload_enabled)
1005 		return;
1006 
1007 	for (ctr = 0; ctr < PSOC_MAX_PHY_REG_CAP; ctr++) {
1008 		soc_reg->new_user_ctry_pending[ctr] = false;
1009 		soc_reg->new_init_ctry_pending[ctr] = false;
1010 		soc_reg->new_11d_ctry_pending[ctr] = false;
1011 		soc_reg->world_country_pending[ctr] = false;
1012 	}
1013 }
1014 
1015 QDF_STATUS reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1016 				struct cur_regulatory_info *regulat_info,
1017 				struct wlan_lmac_if_reg_tx_ops *tx_ops)
1018 {
1019 	struct wlan_objmgr_psoc *psoc = regulat_info->psoc;
1020 	struct wlan_objmgr_pdev *pdev;
1021 	uint8_t pdev_id;
1022 	uint8_t phy_id;
1023 	uint8_t phy_num;
1024 	struct set_country country_code;
1025 	QDF_STATUS status;
1026 
1027 	/*
1028 	 * During SSR/WLAN restart ignore master channel list
1029 	 * for all events and in the last event handling if
1030 	 * current country and default country is different, send the last
1031 	 * configured (soc_reg->cur_country) country.
1032 	 */
1033 	if ((regulat_info->num_phy != regulat_info->phy_id + 1) ||
1034 	    (!qdf_mem_cmp(soc_reg->cur_country, regulat_info->alpha2,
1035 			  REG_ALPHA2_LEN)))
1036 		return QDF_STATUS_SUCCESS;
1037 
1038 	/*
1039 	 * Need firmware to send channel list event
1040 	 * for all phys. Therefore set pdev_id to 0xFF.
1041 	 */
1042 	pdev_id = WMI_HOST_PDEV_ID_SOC;
1043 	for (phy_num = 0; phy_num < regulat_info->num_phy; phy_num++) {
1044 		if (soc_reg->cc_src == SOURCE_USERSPACE)
1045 			soc_reg->new_user_ctry_pending[phy_num] = true;
1046 		else if (soc_reg->cc_src == SOURCE_11D)
1047 			soc_reg->new_11d_ctry_pending[phy_num] = true;
1048 		else
1049 			soc_reg->world_country_pending[phy_num] = true;
1050 	}
1051 
1052 	qdf_mem_zero(&country_code, sizeof(country_code));
1053 	qdf_mem_copy(country_code.country, soc_reg->cur_country,
1054 		     sizeof(soc_reg->cur_country));
1055 	country_code.pdev_id = pdev_id;
1056 
1057 	if (soc_reg->offload_enabled) {
1058 		if (!tx_ops || !tx_ops->set_country_code) {
1059 			reg_err("No regulatory tx_ops");
1060 			status = QDF_STATUS_E_FAULT;
1061 			goto error;
1062 		}
1063 		status = tx_ops->set_country_code(psoc, &country_code);
1064 		if (QDF_IS_STATUS_ERROR(status)) {
1065 			reg_err("Failed to send country code to fw");
1066 			goto error;
1067 		}
1068 	} else {
1069 		phy_id = regulat_info->phy_id;
1070 		if (tx_ops->get_pdev_id_from_phy_id)
1071 			tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id);
1072 		else
1073 			pdev_id = phy_id;
1074 
1075 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
1076 						  WLAN_REGULATORY_NB_ID);
1077 		status = reg_set_non_offload_country(pdev, &country_code);
1078 		wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID);
1079 		if (QDF_IS_STATUS_ERROR(status)) {
1080 			reg_err("Failed to set country code");
1081 			goto error;
1082 		}
1083 	}
1084 
1085 	reg_debug("Target CC: %.2s, Restore to Previous CC: %.2s",
1086 		  regulat_info->alpha2, soc_reg->cur_country);
1087 
1088 	return status;
1089 
1090 error:
1091 	reg_reset_ctry_pending_hints(soc_reg);
1092 
1093 	return status;
1094 }
1095 
1096 bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
1097 				struct cur_regulatory_info *regulat_info)
1098 {
1099 	uint8_t phy_num;
1100 
1101 	if (soc_reg->cc_src == SOURCE_UNKNOWN)
1102 		return false;
1103 
1104 	phy_num = regulat_info->phy_id;
1105 	if (soc_reg->new_user_ctry_pending[phy_num] ||
1106 	    soc_reg->new_init_ctry_pending[phy_num] ||
1107 	    soc_reg->new_11d_ctry_pending[phy_num] ||
1108 	    soc_reg->world_country_pending[phy_num])
1109 		return false;
1110 
1111 	return true;
1112 }
1113