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