xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: reg_utils.c
21  * This file defines the APIs to set and get the regulatory variables.
22  */
23 
24 #include <wlan_cmn.h>
25 #include <reg_services_public_struct.h>
26 #include <wlan_objmgr_psoc_obj.h>
27 #include <wlan_objmgr_pdev_obj.h>
28 #include "reg_priv_objs.h"
29 #include "reg_utils.h"
30 #include "reg_callbacks.h"
31 #include "reg_db.h"
32 #include "reg_db_parser.h"
33 #include "reg_host_11d.h"
34 #include <scheduler_api.h>
35 #include <wlan_reg_services_api.h>
36 #include <qdf_platform.h>
37 #include "reg_services_common.h"
38 #include "reg_build_chan_list.h"
39 
40 #define DEFAULT_WORLD_REGDMN 0x60
41 
42 #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj)
43 #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj)
44 
45 #ifdef CONFIG_CHAN_FREQ_API
46 bool reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev,
47 					 qdf_freq_t freq)
48 {
49 	enum channel_enum ch_idx;
50 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
51 
52 	ch_idx = reg_get_chan_enum_for_freq(freq);
53 
54 	if (ch_idx == INVALID_CHANNEL)
55 		return false;
56 
57 	pdev_priv_obj = reg_get_pdev_obj(pdev);
58 
59 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
60 		reg_err("pdev reg obj is NULL");
61 		return false;
62 	}
63 
64 	if (pdev_priv_obj->cur_chan_list[ch_idx].chan_flags &
65 	    REGULATORY_CHAN_RADAR)
66 		return true;
67 
68 	return false;
69 }
70 #endif /* CONFIG_CHAN_FREQ_API */
71 
72 bool reg_is_world_ctry_code(uint16_t ctry_code)
73 {
74 	if ((ctry_code & 0xFFF0) == DEFAULT_WORLD_REGDMN)
75 		return true;
76 
77 	return false;
78 }
79 
80 QDF_STATUS reg_read_current_country(struct wlan_objmgr_psoc *psoc,
81 				    uint8_t *country_code)
82 {
83 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
84 
85 	if (!country_code) {
86 		reg_err("country_code is NULL");
87 		return QDF_STATUS_E_INVAL;
88 	}
89 
90 	psoc_reg = reg_get_psoc_obj(psoc);
91 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
92 		reg_err("psoc reg component is NULL");
93 		return QDF_STATUS_E_INVAL;
94 	}
95 
96 	qdf_mem_copy(country_code, psoc_reg->cur_country, REG_ALPHA2_LEN + 1);
97 
98 	return QDF_STATUS_SUCCESS;
99 }
100 
101 /**
102  * reg_set_default_country() - Read the default country for the regdomain
103  * @country: country code.
104  *
105  * Return: QDF_STATUS
106  */
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 
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 
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 
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 QDF_STATUS reg_set_non_offload_country(struct wlan_objmgr_pdev *pdev,
155 					      struct set_country *cc)
156 {
157 	struct wlan_objmgr_psoc *psoc;
158 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
159 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
160 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
161 	struct cc_regdmn_s rd;
162 	uint8_t pdev_id;
163 	uint8_t phy_id;
164 
165 	if (!pdev) {
166 		reg_err("pdev is NULL");
167 		return QDF_STATUS_E_INVAL;
168 	}
169 
170 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
171 	psoc = wlan_pdev_get_psoc(pdev);
172 	tx_ops = reg_get_psoc_tx_ops(psoc);
173 	if (tx_ops->get_phy_id_from_pdev_id)
174 		tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
175 	else
176 		phy_id = pdev_id;
177 
178 	psoc_reg = reg_get_psoc_obj(psoc);
179 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
180 		reg_err("psoc reg component is NULL");
181 		return QDF_STATUS_E_INVAL;
182 	}
183 
184 	if (reg_is_world_alpha2(cc->country)) {
185 		pdev_priv_obj = reg_get_pdev_obj(pdev);
186 		if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
187 			reg_err("reg component pdev priv is NULL");
188 			psoc_reg->world_country_pending[phy_id] = false;
189 			return QDF_STATUS_E_INVAL;
190 		}
191 		if (reg_is_world_ctry_code(pdev_priv_obj->def_region_domain))
192 			rd.cc.regdmn.reg_2g_5g_pair_id =
193 				pdev_priv_obj->def_region_domain;
194 		else
195 			rd.cc.regdmn.reg_2g_5g_pair_id = DEFAULT_WORLD_REGDMN;
196 		rd.flags = REGDMN_IS_SET;
197 	} else {
198 		qdf_mem_copy(rd.cc.alpha, cc->country, REG_ALPHA2_LEN + 1);
199 		rd.flags = ALPHA_IS_SET;
200 	}
201 
202 	reg_program_chan_list(pdev, &rd);
203 	return QDF_STATUS_SUCCESS;
204 }
205 
206 QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev,
207 			   uint8_t *country)
208 {
209 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
210 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
211 	struct set_country cc;
212 	struct wlan_objmgr_psoc *psoc;
213 	uint8_t pdev_id;
214 	uint8_t phy_id;
215 
216 	if (!pdev) {
217 		reg_err("pdev is NULL");
218 		return QDF_STATUS_E_INVAL;
219 	}
220 
221 	if (!country) {
222 		reg_err("country code is NULL");
223 		return QDF_STATUS_E_INVAL;
224 	}
225 
226 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
227 
228 	psoc = wlan_pdev_get_psoc(pdev);
229 
230 	tx_ops = reg_get_psoc_tx_ops(psoc);
231 	if (tx_ops->get_phy_id_from_pdev_id)
232 		tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
233 	else
234 		phy_id = pdev_id;
235 
236 	psoc_reg = reg_get_psoc_obj(psoc);
237 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
238 		reg_err("psoc reg component is NULL");
239 		return QDF_STATUS_E_INVAL;
240 	}
241 
242 	if (!qdf_mem_cmp(psoc_reg->cur_country, country, REG_ALPHA2_LEN)) {
243 		if (psoc_reg->cc_src == SOURCE_USERSPACE ||
244 		    psoc_reg->cc_src == SOURCE_CORE) {
245 			reg_debug("country is not different");
246 			return QDF_STATUS_E_INVAL;
247 		}
248 	}
249 
250 	reg_debug("programming new country: %s to firmware", country);
251 
252 	qdf_mem_copy(cc.country, country, REG_ALPHA2_LEN + 1);
253 	cc.pdev_id = pdev_id;
254 
255 	if (!psoc_reg->offload_enabled && !reg_is_world_alpha2(country)) {
256 		QDF_STATUS status;
257 
258 		status = reg_is_country_code_valid(country);
259 		if (!QDF_IS_STATUS_SUCCESS(status)) {
260 			reg_err("Unable to set country code: %s\n", country);
261 			reg_err("Restoring to world domain");
262 			qdf_mem_copy(cc.country, REG_WORLD_ALPHA2,
263 				     REG_ALPHA2_LEN + 1);
264 		}
265 	}
266 
267 
268 	if (reg_is_world_alpha2(cc.country))
269 		psoc_reg->world_country_pending[phy_id] = true;
270 	else
271 		psoc_reg->new_user_ctry_pending[phy_id] = true;
272 
273 	if (psoc_reg->offload_enabled) {
274 		tx_ops = reg_get_psoc_tx_ops(psoc);
275 		if (tx_ops->set_country_code) {
276 			tx_ops->set_country_code(psoc, &cc);
277 		} else {
278 			reg_err("country set fw handler not present");
279 			psoc_reg->new_user_ctry_pending[phy_id] = false;
280 			return QDF_STATUS_E_FAULT;
281 		}
282 	} else {
283 		return reg_set_non_offload_country(pdev, &cc);
284 	}
285 
286 	return QDF_STATUS_SUCCESS;
287 }
288 
289 QDF_STATUS reg_reset_country(struct wlan_objmgr_psoc *psoc)
290 {
291 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
292 
293 	psoc_reg = reg_get_psoc_obj(psoc);
294 	if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) {
295 		reg_err("psoc reg component is NULL");
296 		return QDF_STATUS_E_INVAL;
297 	}
298 
299 	qdf_mem_copy(psoc_reg->cur_country,
300 		     psoc_reg->def_country,
301 		     REG_ALPHA2_LEN + 1);
302 	reg_debug("set cur_country %.2s", psoc_reg->cur_country);
303 
304 	return QDF_STATUS_SUCCESS;
305 }
306 
307 QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr,
308 					    const uint8_t *country_alpha2,
309 					    enum country_src source)
310 {
311 	if (!reg_domain_ptr) {
312 		reg_err("Invalid reg domain pointer");
313 		return QDF_STATUS_E_FAULT;
314 	}
315 
316 	*reg_domain_ptr = 0;
317 
318 	if (!country_alpha2) {
319 		reg_err("Country code is NULL");
320 		return QDF_STATUS_E_FAULT;
321 	}
322 
323 	return QDF_STATUS_SUCCESS;
324 }
325 
326 #ifdef CONFIG_REG_CLIENT
327 QDF_STATUS
328 reg_get_6g_power_type_for_ctry(uint8_t *ap_ctry, uint8_t *sta_ctry,
329 			       enum reg_6g_ap_type *pwr_type_6g,
330 			       bool *ctry_code_match)
331 {
332 	*pwr_type_6g = REG_INDOOR_AP;
333 
334 	if (qdf_mem_cmp(ap_ctry, sta_ctry, REG_ALPHA2_LEN)) {
335 		reg_debug("Country IE:%c%c, STA country:%c%c", ap_ctry[0],
336 			  ap_ctry[1], sta_ctry[0], sta_ctry[1]);
337 		*ctry_code_match = false;
338 
339 		if (wlan_reg_is_us(sta_ctry)) {
340 			reg_err("US VLP not in place yet, connection not allowed");
341 			return QDF_STATUS_E_NOSUPPORT;
342 		}
343 
344 		if (wlan_reg_is_etsi(sta_ctry)) {
345 			reg_debug("STA ctry:%c%c, doesn't match with AP ctry, switch to VLP",
346 				  sta_ctry[0], sta_ctry[1]);
347 			*pwr_type_6g = REG_VERY_LOW_POWER_AP;
348 		}
349 	} else {
350 		*ctry_code_match = true;
351 	}
352 
353 	return QDF_STATUS_SUCCESS;
354 }
355 #endif
356 
357 #ifdef CONFIG_CHAN_FREQ_API
358 bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev,
359 					qdf_freq_t freq)
360 {
361 	enum channel_state chan_state;
362 
363 	chan_state = reg_get_channel_state_for_freq(pdev, freq);
364 
365 	return (chan_state == CHANNEL_STATE_DFS) ||
366 		(chan_state == CHANNEL_STATE_DISABLE);
367 }
368 #endif /* CONFIG_CHAN_FREQ_API */
369 
370 #ifdef WLAN_FEATURE_DSRC
371 #ifdef CONFIG_CHAN_FREQ_API
372 bool reg_is_dsrc_freq(qdf_freq_t freq)
373 {
374 	if (!REG_IS_5GHZ_FREQ(freq))
375 		return false;
376 
377 	if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ))
378 		return false;
379 
380 	return true;
381 }
382 #endif  /*CONFIG_CHAN_FREQ_API*/
383 #else
384 bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev)
385 {
386 	struct cur_regdmn_info cur_reg_dmn;
387 	QDF_STATUS status;
388 
389 	status = reg_get_curr_regdomain(pdev, &cur_reg_dmn);
390 	if (status != QDF_STATUS_SUCCESS) {
391 		reg_debug_rl("Failed to get reg domain");
392 		return false;
393 	}
394 
395 	return reg_etsi13_regdmn(cur_reg_dmn.dmn_id_5g);
396 }
397 
398 #ifdef CONFIG_CHAN_FREQ_API
399 bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev,
400 				     uint16_t freq)
401 {
402 	if (!REG_IS_5GHZ_FREQ(freq))
403 		return false;
404 
405 	if (!(freq >= REG_ETSI13_SRD_START_FREQ &&
406 	      freq <= REG_ETSI13_SRD_END_FREQ))
407 		return false;
408 
409 	return reg_is_etsi13_regdmn(pdev);
410 }
411 #endif /* CONFIG_CHAN_FREQ_API */
412 
413 bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev)
414 {
415 	struct wlan_objmgr_psoc *psoc;
416 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
417 
418 	if (!pdev) {
419 		reg_alert("pdev is NULL");
420 		return true;
421 	}
422 	psoc = wlan_pdev_get_psoc(pdev);
423 
424 	psoc_priv_obj = reg_get_psoc_obj(psoc);
425 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
426 		reg_alert("psoc reg component is NULL");
427 		return true;
428 	}
429 
430 	return psoc_priv_obj->enable_srd_chan_in_master_mode &&
431 	       reg_is_etsi13_regdmn(pdev);
432 }
433 #endif
434 
435 QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap)
436 {
437 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
438 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
439 	struct wlan_objmgr_psoc *psoc;
440 	QDF_STATUS status;
441 
442 	pdev_priv_obj = reg_get_pdev_obj(pdev);
443 
444 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
445 		reg_err("pdev reg component is NULL");
446 		return QDF_STATUS_E_INVAL;
447 	}
448 
449 	if (pdev_priv_obj->band_capability == band_bitmap) {
450 		reg_info("same band %d", band_bitmap);
451 		return QDF_STATUS_SUCCESS;
452 	}
453 
454 	psoc = wlan_pdev_get_psoc(pdev);
455 	if (!psoc) {
456 		reg_err("psoc is NULL");
457 		return QDF_STATUS_E_INVAL;
458 	}
459 
460 	psoc_priv_obj = reg_get_psoc_obj(psoc);
461 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
462 		reg_err("psoc reg component is NULL");
463 		return QDF_STATUS_E_INVAL;
464 	}
465 
466 	reg_info("set band bitmap: %d", band_bitmap);
467 	pdev_priv_obj->band_capability = band_bitmap;
468 
469 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
470 
471 	status = reg_send_scheduler_msg_sb(psoc, pdev);
472 
473 	return status;
474 }
475 
476 QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev,
477 			uint32_t *band_bitmap)
478 {
479 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
480 
481 	pdev_priv_obj = reg_get_pdev_obj(pdev);
482 
483 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
484 		reg_err("pdev reg component is NULL");
485 		return QDF_STATUS_E_INVAL;
486 	}
487 
488 	reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability);
489 	*band_bitmap = pdev_priv_obj->band_capability;
490 
491 	return QDF_STATUS_SUCCESS;
492 }
493 
494 #ifdef DISABLE_CHANNEL_LIST
495 QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev)
496 {
497 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
498 	struct wlan_objmgr_psoc *psoc;
499 	QDF_STATUS status;
500 
501 	pdev_priv_obj = reg_get_pdev_obj(pdev);
502 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
503 		reg_err("pdev reg component is NULL");
504 		return QDF_STATUS_E_INVAL;
505 	}
506 
507 	psoc = wlan_pdev_get_psoc(pdev);
508 	if (!psoc) {
509 		reg_err("psoc is NULL");
510 		return QDF_STATUS_E_INVAL;
511 	}
512 
513 	pdev_priv_obj->disable_cached_channels = false;
514 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
515 	status = reg_send_scheduler_msg_sb(psoc, pdev);
516 	return status;
517 }
518 
519 QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev)
520 {
521 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
522 	struct wlan_objmgr_psoc *psoc;
523 	QDF_STATUS status;
524 
525 	pdev_priv_obj = reg_get_pdev_obj(pdev);
526 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
527 		reg_err("pdev reg component is NULL");
528 		return QDF_STATUS_E_INVAL;
529 	}
530 
531 	psoc = wlan_pdev_get_psoc(pdev);
532 	if (!psoc) {
533 		reg_err("psoc is NULL");
534 		return QDF_STATUS_E_INVAL;
535 	}
536 
537 	pdev_priv_obj->disable_cached_channels = true;
538 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
539 	status = reg_send_scheduler_msg_sb(psoc, pdev);
540 	return status;
541 }
542 
543 #ifdef CONFIG_CHAN_FREQ_API
544 QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev,
545 					uint32_t *channel_list,
546 					uint32_t num_channels)
547 {
548 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
549 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
550 	struct wlan_objmgr_psoc *psoc;
551 	uint16_t i, j;
552 
553 	pdev_priv_obj = reg_get_pdev_obj(pdev);
554 
555 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
556 		reg_err("pdev reg component is NULL");
557 		return QDF_STATUS_E_INVAL;
558 	}
559 
560 	psoc = wlan_pdev_get_psoc(pdev);
561 	if (!psoc) {
562 		reg_err("psoc is NULL");
563 		return QDF_STATUS_E_INVAL;
564 	}
565 
566 	psoc_priv_obj = reg_get_psoc_obj(psoc);
567 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
568 		reg_err("psoc reg component is NULL");
569 		return QDF_STATUS_E_INVAL;
570 	}
571 	if (pdev_priv_obj->num_cache_channels > 0) {
572 		pdev_priv_obj->num_cache_channels = 0;
573 		qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list,
574 			     sizeof(pdev_priv_obj->cache_disable_chan_list));
575 	}
576 
577 	for (i = 0; i < num_channels; i++) {
578 		for (j = 0; j < NUM_CHANNELS; j++) {
579 			if (channel_list[i] == pdev_priv_obj->
580 						cur_chan_list[j].center_freq) {
581 				pdev_priv_obj->
582 					cache_disable_chan_list[i].center_freq =
583 							channel_list[i];
584 				pdev_priv_obj->
585 					cache_disable_chan_list[i].state =
586 					pdev_priv_obj->cur_chan_list[j].state;
587 				pdev_priv_obj->
588 					cache_disable_chan_list[i].chan_flags =
589 					pdev_priv_obj->
590 						cur_chan_list[j].chan_flags;
591 			}
592 		}
593 	}
594 	pdev_priv_obj->num_cache_channels = num_channels;
595 
596 	return QDF_STATUS_SUCCESS;
597 }
598 #endif /* CONFIG_CHAN_FREQ_API */
599 #endif
600 
601 #ifdef CONFIG_REG_CLIENT
602 
603 QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev,
604 				  bool fcc_constraint)
605 {
606 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
607 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
608 	struct wlan_objmgr_psoc *psoc;
609 	QDF_STATUS status;
610 
611 	pdev_priv_obj = reg_get_pdev_obj(pdev);
612 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
613 		reg_err("pdev reg component is NULL");
614 		return QDF_STATUS_E_INVAL;
615 	}
616 
617 	if (pdev_priv_obj->set_fcc_channel == fcc_constraint) {
618 		reg_info("same fcc_constraint %d", fcc_constraint);
619 		return QDF_STATUS_SUCCESS;
620 	}
621 
622 	reg_info("set fcc_constraint: %d", fcc_constraint);
623 	pdev_priv_obj->set_fcc_channel = fcc_constraint;
624 
625 	psoc = wlan_pdev_get_psoc(pdev);
626 	if (!psoc) {
627 		reg_err("psoc is NULL");
628 		return QDF_STATUS_E_INVAL;
629 	}
630 
631 	psoc_priv_obj = reg_get_psoc_obj(psoc);
632 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
633 		reg_err("psoc reg component is NULL");
634 		return QDF_STATUS_E_INVAL;
635 	}
636 
637 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
638 
639 	status = reg_send_scheduler_msg_sb(psoc, pdev);
640 
641 	return status;
642 }
643 
644 bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq)
645 {
646 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
647 
648 	pdev_priv_obj = reg_get_pdev_obj(pdev);
649 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
650 		reg_err("pdev reg component is NULL");
651 		return false;
652 	}
653 
654 	if (freq != CHAN_12_CENT_FREQ && freq != CHAN_13_CENT_FREQ)
655 		return false;
656 
657 	if (!pdev_priv_obj->set_fcc_channel)
658 		return false;
659 
660 	return true;
661 }
662 
663 #ifdef CONFIG_BAND_6GHZ
664 /**
665  * reg_is_afc_available() - check if the automated frequency control system is
666  * available, function will need to be updated once AFC is implemented
667  * @pdev: Pointer to pdev structure
668  *
669  * Return: false since the AFC system is not yet available
670  */
671 static bool reg_is_afc_available(struct wlan_objmgr_pdev *pdev)
672 {
673 	return false;
674 }
675 
676 enum reg_6g_ap_type reg_decide_6g_ap_pwr_type(struct wlan_objmgr_pdev *pdev)
677 {
678 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
679 	enum reg_6g_ap_type ap_pwr_type = REG_INDOOR_AP;
680 
681 	pdev_priv_obj = reg_get_pdev_obj(pdev);
682 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
683 		reg_err("pdev reg component is NULL");
684 		return REG_VERY_LOW_POWER_AP;
685 	}
686 
687 	if (reg_is_afc_available(pdev))
688 		ap_pwr_type = REG_STANDARD_POWER_AP;
689 	else if (pdev_priv_obj->reg_6g_superid != FCC1_6G_01 &&
690 		 pdev_priv_obj->reg_6g_superid != FCC1_6G_05)
691 		ap_pwr_type = REG_VERY_LOW_POWER_AP;
692 
693 	reg_set_ap_pwr_and_update_chan_list(pdev, ap_pwr_type);
694 
695 	return ap_pwr_type;
696 }
697 #endif /* CONFIG_BAND_6GHZ */
698 
699 #endif /* CONFIG_REG_CLIENT */
700 
701 /**
702  * reg_change_pdev_for_config() - Update user configuration in pdev private obj.
703  * @psoc: Pointer to global psoc structure.
704  * @object: Pointer to global pdev structure.
705  * @arg: Pointer to argument list.
706  */
707 static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc,
708 				       void *object, void *arg)
709 {
710 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
711 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
712 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
713 
714 	psoc_priv_obj = reg_get_psoc_obj(psoc);
715 	if (!psoc_priv_obj) {
716 		reg_err("psoc priv obj is NULL");
717 		return;
718 	}
719 
720 	pdev_priv_obj = reg_get_pdev_obj(pdev);
721 
722 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
723 		reg_err("reg pdev private obj is NULL");
724 		return;
725 	}
726 
727 	pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
728 	pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled;
729 	pdev_priv_obj->force_ssc_disable_indoor_channel =
730 		psoc_priv_obj->force_ssc_disable_indoor_channel;
731 	pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
732 
733 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
734 
735 	reg_send_scheduler_msg_sb(psoc, pdev);
736 }
737 
738 QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
739 			       struct reg_config_vars config_vars)
740 {
741 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
742 	QDF_STATUS status;
743 
744 	psoc_priv_obj = reg_get_psoc_obj(psoc);
745 	if (!psoc_priv_obj) {
746 		reg_err("psoc priv obj is NULL");
747 		return QDF_STATUS_E_FAILURE;
748 	}
749 
750 	psoc_priv_obj->enable_11d_supp_original =
751 		config_vars.enable_11d_support;
752 	psoc_priv_obj->scan_11d_interval = config_vars.scan_11d_interval;
753 	psoc_priv_obj->user_ctry_priority = config_vars.userspace_ctry_priority;
754 	psoc_priv_obj->dfs_enabled = config_vars.dfs_enabled;
755 	psoc_priv_obj->indoor_chan_enabled = config_vars.indoor_chan_enabled;
756 	psoc_priv_obj->force_ssc_disable_indoor_channel =
757 		config_vars.force_ssc_disable_indoor_channel;
758 	psoc_priv_obj->band_capability = config_vars.band_capability;
759 	psoc_priv_obj->restart_beaconing = config_vars.restart_beaconing;
760 	psoc_priv_obj->enable_srd_chan_in_master_mode =
761 		config_vars.enable_srd_chan_in_master_mode;
762 	psoc_priv_obj->enable_11d_in_world_mode =
763 		config_vars.enable_11d_in_world_mode;
764 	psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode =
765 		config_vars.enable_5dot9_ghz_chan_in_master_mode;
766 	psoc_priv_obj->retain_nol_across_regdmn_update =
767 		config_vars.retain_nol_across_regdmn_update;
768 
769 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
770 	if (QDF_IS_STATUS_ERROR(status)) {
771 		reg_err("error taking psoc ref cnt");
772 		return status;
773 	}
774 	status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
775 					      reg_change_pdev_for_config,
776 					      NULL, 1, WLAN_REGULATORY_SB_ID);
777 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
778 
779 	return status;
780 }
781 
782 void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
783 			       struct regulatory_channel *reg_channels,
784 			       uint8_t *alpha2,
785 			       enum dfs_reg dfs_region)
786 {
787 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
788 	QDF_STATUS status;
789 	uint32_t count;
790 	enum direction dir;
791 	uint32_t phy_cnt;
792 
793 	psoc_priv_obj = reg_get_psoc_obj(psoc);
794 	if (!psoc_priv_obj) {
795 		reg_err("reg psoc private obj is NULL");
796 		return;
797 	}
798 
799 	qdf_mem_copy(psoc_priv_obj->cur_country, alpha2,
800 		     REG_ALPHA2_LEN);
801 	reg_debug("set cur_country %.2s", psoc_priv_obj->cur_country);
802 	for (count = 0; count < NUM_CHANNELS; count++) {
803 		reg_channels[count].chan_num = channel_map[count].chan_num;
804 		reg_channels[count].center_freq =
805 			channel_map[count].center_freq;
806 		reg_channels[count].nol_chan = false;
807 	}
808 
809 	for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
810 		qdf_mem_copy(psoc_priv_obj->mas_chan_params[phy_cnt].
811 			     mas_chan_list, reg_channels,
812 			     NUM_CHANNELS * sizeof(struct regulatory_channel));
813 
814 		psoc_priv_obj->mas_chan_params[phy_cnt].dfs_region =
815 			dfs_region;
816 	}
817 
818 	dir = SOUTHBOUND;
819 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
820 	if (QDF_IS_STATUS_ERROR(status)) {
821 		reg_err("error taking psoc ref cnt");
822 		return;
823 	}
824 	status = wlan_objmgr_iterate_obj_list(
825 			psoc, WLAN_PDEV_OP, reg_propagate_mas_chan_list_to_pdev,
826 			&dir, 1, WLAN_REGULATORY_SB_ID);
827 	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
828 }
829 
830 enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
831 				    uint8_t *alpha2)
832 {
833 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
834 
835 	psoc_priv_obj = reg_get_psoc_obj(psoc);
836 	if (!psoc_priv_obj) {
837 		reg_err("reg psoc private obj is NULL");
838 		return SOURCE_UNKNOWN;
839 	}
840 
841 	qdf_mem_copy(alpha2, psoc_priv_obj->cur_country, REG_ALPHA2_LEN + 1);
842 
843 	return psoc_priv_obj->cc_src;
844 }
845 
846 QDF_STATUS reg_get_regd_rules(struct wlan_objmgr_pdev *pdev,
847 			      struct reg_rule_info *reg_rules)
848 {
849 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
850 
851 	if (!pdev) {
852 		reg_err("pdev is NULL");
853 		return QDF_STATUS_E_FAILURE;
854 	}
855 
856 	pdev_priv_obj = reg_get_pdev_obj(pdev);
857 	if (!pdev_priv_obj) {
858 		reg_err("pdev priv obj is NULL");
859 		return QDF_STATUS_E_FAILURE;
860 	}
861 
862 	qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock);
863 	qdf_mem_copy(reg_rules, &pdev_priv_obj->reg_rules,
864 		     sizeof(struct reg_rule_info));
865 	qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock);
866 
867 	return QDF_STATUS_SUCCESS;
868 }
869 
870 void reg_reset_ctry_pending_hints(struct wlan_regulatory_psoc_priv_obj
871 				  *soc_reg)
872 {
873 	uint8_t ctr;
874 
875 	if (!soc_reg->offload_enabled)
876 		return;
877 
878 	for (ctr = 0; ctr < PSOC_MAX_PHY_REG_CAP; ctr++) {
879 		soc_reg->new_user_ctry_pending[ctr] = false;
880 		soc_reg->new_init_ctry_pending[ctr] = false;
881 		soc_reg->new_11d_ctry_pending[ctr] = false;
882 		soc_reg->world_country_pending[ctr] = false;
883 	}
884 }
885 
886 QDF_STATUS reg_set_curr_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
887 				struct cur_regulatory_info *regulat_info,
888 				struct wlan_lmac_if_reg_tx_ops *tx_ops)
889 {
890 	struct wlan_objmgr_psoc *psoc = regulat_info->psoc;
891 	struct wlan_objmgr_pdev *pdev;
892 	uint8_t pdev_id;
893 	uint8_t phy_id;
894 	uint8_t phy_num;
895 	struct set_country country_code;
896 	QDF_STATUS status;
897 
898 	/*
899 	 * During SSR/WLAN restart ignore master channel list
900 	 * for all events and in the last event handling if
901 	 * current country and default country is different, send the last
902 	 * configured (soc_reg->cur_country) country.
903 	 */
904 	if ((regulat_info->num_phy != regulat_info->phy_id + 1) ||
905 	    (!qdf_mem_cmp(soc_reg->cur_country, regulat_info->alpha2,
906 			  REG_ALPHA2_LEN)))
907 		return QDF_STATUS_SUCCESS;
908 
909 	/*
910 	 * Need firmware to send channel list event
911 	 * for all phys. Therefore set pdev_id to 0xFF
912 	 */
913 	pdev_id = 0xFF;
914 	for (phy_num = 0; phy_num < regulat_info->num_phy; phy_num++) {
915 		if (soc_reg->cc_src == SOURCE_USERSPACE)
916 			soc_reg->new_user_ctry_pending[phy_num] = true;
917 		else if (soc_reg->cc_src == SOURCE_11D)
918 			soc_reg->new_11d_ctry_pending[phy_num] = true;
919 		else
920 			soc_reg->world_country_pending[phy_num] = true;
921 	}
922 
923 	qdf_mem_zero(&country_code, sizeof(country_code));
924 	qdf_mem_copy(country_code.country, soc_reg->cur_country,
925 		     sizeof(soc_reg->cur_country));
926 	country_code.pdev_id = pdev_id;
927 
928 	if (soc_reg->offload_enabled) {
929 		if (!tx_ops || !tx_ops->set_country_code) {
930 			reg_err("No regulatory tx_ops");
931 			status = QDF_STATUS_E_FAULT;
932 			goto error;
933 		}
934 		status = tx_ops->set_country_code(psoc, &country_code);
935 		if (QDF_IS_STATUS_ERROR(status)) {
936 			reg_err("Failed to send country code to fw");
937 			goto error;
938 		}
939 	} else {
940 		phy_id = regulat_info->phy_id;
941 		if (tx_ops->get_pdev_id_from_phy_id)
942 			tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id);
943 		else
944 			pdev_id = phy_id;
945 
946 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
947 						  WLAN_REGULATORY_NB_ID);
948 		status = reg_set_non_offload_country(pdev, &country_code);
949 		wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID);
950 		if (QDF_IS_STATUS_ERROR(status)) {
951 			reg_err("Failed to set country code");
952 			goto error;
953 		}
954 	}
955 
956 	reg_debug("Target CC: %.2s, Restore to Previous CC: %.2s",
957 		  regulat_info->alpha2, soc_reg->cur_country);
958 
959 	return status;
960 
961 error:
962 	reg_reset_ctry_pending_hints(soc_reg);
963 
964 	return status;
965 }
966 
967 bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg,
968 				struct cur_regulatory_info *regulat_info)
969 {
970 	uint8_t phy_num;
971 
972 	if (soc_reg->cc_src == SOURCE_UNKNOWN)
973 		return false;
974 
975 	phy_num = regulat_info->phy_id;
976 	if (soc_reg->new_user_ctry_pending[phy_num] ||
977 	    soc_reg->new_init_ctry_pending[phy_num] ||
978 	    soc_reg->new_11d_ctry_pending[phy_num] ||
979 	    soc_reg->world_country_pending[phy_num])
980 		return false;
981 
982 	return true;
983 }
984