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: wlan_hdd_regulatory.c
22  *
23  * hdd regulatory implementation
24  */
25 
26 #include "qdf_types.h"
27 #include "qdf_trace.h"
28 #include "wlan_hdd_main.h"
29 #include <wlan_osif_priv.h>
30 #include "wlan_hdd_regulatory.h"
31 #include <wlan_reg_ucfg_api.h>
32 #include "cds_regdomain.h"
33 #include "cds_utils.h"
34 #include "pld_common.h"
35 #include <net/cfg80211.h>
36 #include "wlan_policy_mgr_ucfg.h"
37 #include "sap_api.h"
38 #include "wlan_hdd_hostapd.h"
39 #include "osif_psoc_sync.h"
40 #include "wlan_osif_features.h"
41 #include "wlan_p2p_ucfg_api.h"
42 
43 #define REG_RULE_2412_2462    REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
44 
45 #define REG_RULE_2467_2472    REG_RULE(2467-10, 2472+10, 40, 0, 20, \
46 		NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
47 
48 #define REG_RULE_2484         REG_RULE(2484-10, 2484+10, 20, 0, 20, \
49 		NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | \
50 				       NL80211_RRF_NO_OFDM)
51 
52 #define REG_RULE_5180_5320    REG_RULE(5180-10, 5320+10, 160, 0, 20, \
53 		NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
54 
55 #define REG_RULE_5500_5720    REG_RULE(5500-10, 5720+10, 160, 0, 20, \
56 		NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
57 
58 #define REG_RULE_5745_5925    REG_RULE(5745-10, 5925+10, 80, 0, 20, \
59 		NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
60 
61 static bool init_by_driver;
62 static bool init_by_reg_core;
63 
64 struct regulatory_channel reg_channels[NUM_CHANNELS];
65 
66 static const struct ieee80211_regdomain
67 hdd_world_regrules_60_61_62 = {
68 	.n_reg_rules = 6,
69 	.alpha2 =  "00",
70 	.reg_rules = {
71 		REG_RULE_2412_2462,
72 		REG_RULE_2467_2472,
73 		REG_RULE_2484,
74 		REG_RULE_5180_5320,
75 		REG_RULE_5500_5720,
76 		REG_RULE_5745_5925,
77 	}
78 };
79 
80 static const struct ieee80211_regdomain
81 hdd_world_regrules_63_65 = {
82 	.n_reg_rules = 4,
83 	.alpha2 =  "00",
84 	.reg_rules = {
85 		REG_RULE_2412_2462,
86 		REG_RULE_2467_2472,
87 		REG_RULE_5180_5320,
88 		REG_RULE_5745_5925,
89 	}
90 };
91 
92 static const struct ieee80211_regdomain
93 hdd_world_regrules_64 = {
94 	.n_reg_rules = 3,
95 	.alpha2 =  "00",
96 	.reg_rules = {
97 		REG_RULE_2412_2462,
98 		REG_RULE_5180_5320,
99 		REG_RULE_5745_5925,
100 	}
101 };
102 
103 static const struct ieee80211_regdomain
104 hdd_world_regrules_66_69 = {
105 	.n_reg_rules = 4,
106 	.alpha2 =  "00",
107 	.reg_rules = {
108 		REG_RULE_2412_2462,
109 		REG_RULE_5180_5320,
110 		REG_RULE_5500_5720,
111 		REG_RULE_5745_5925,
112 	}
113 };
114 
115 static const struct ieee80211_regdomain
116 hdd_world_regrules_67_68_6A_6C = {
117 	.n_reg_rules = 5,
118 	.alpha2 =  "00",
119 	.reg_rules = {
120 		REG_RULE_2412_2462,
121 		REG_RULE_2467_2472,
122 		REG_RULE_5180_5320,
123 		REG_RULE_5500_5720,
124 		REG_RULE_5745_5925,
125 	}
126 };
127 
128 #define COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME 30
129 /**
130  * hdd_get_world_regrules() - get the appropriate world regrules
131  * @reg: regulatory data
132  *
133  * Return: regulatory rules ptr
134  */
135 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
hdd_get_world_regrules(struct regulatory * reg)136 static const struct ieee80211_regdomain *hdd_get_world_regrules(
137 	struct regulatory *reg)
138 {
139 	struct reg_dmn_pair *regpair =
140 		(struct reg_dmn_pair *)reg->regpair;
141 
142 	switch (regpair->reg_dmn_pair) {
143 	case 0x60:
144 	case 0x61:
145 	case 0x62:
146 		return &hdd_world_regrules_60_61_62;
147 	case 0x63:
148 	case 0x65:
149 		return &hdd_world_regrules_63_65;
150 	case 0x64:
151 		return &hdd_world_regrules_64;
152 	case 0x66:
153 	case 0x69:
154 		return &hdd_world_regrules_66_69;
155 	case 0x67:
156 	case 0x68:
157 	case 0x6A:
158 	case 0x6C:
159 		return &hdd_world_regrules_67_68_6A_6C;
160 	default:
161 		hdd_warn("invalid world mode in BDF");
162 		return &hdd_world_regrules_60_61_62;
163 	}
164 }
165 
166 /**
167  * hdd_is_world_regdomain() - whether world regdomain
168  * @reg_domain: integer regulatory domain
169  *
170  * Return: bool
171  */
hdd_is_world_regdomain(uint32_t reg_domain)172 static bool hdd_is_world_regdomain(uint32_t reg_domain)
173 {
174 	uint32_t temp_regd = reg_domain & ~WORLD_ROAMING_FLAG;
175 
176 	return ((temp_regd & CTRY_FLAG) != CTRY_FLAG) &&
177 		((temp_regd & WORLD_ROAMING_MASK) ==
178 		 WORLD_ROAMING_PREFIX);
179 }
180 
181 /**
182  * hdd_update_regulatory_info() - update regulatory info
183  * @hdd_ctx: hdd context
184  *
185  * Return: Error Code
186  */
hdd_update_regulatory_info(struct hdd_context * hdd_ctx)187 static int hdd_update_regulatory_info(struct hdd_context *hdd_ctx)
188 {
189 	uint32_t country_code;
190 
191 	country_code = cds_get_country_from_alpha2(hdd_ctx->reg.alpha2);
192 
193 	hdd_ctx->reg.reg_domain = CTRY_FLAG;
194 	hdd_ctx->reg.reg_domain |= country_code;
195 
196 	return cds_fill_some_regulatory_info(&hdd_ctx->reg);
197 
198 }
199 #endif
200 
201 /**
202  * hdd_reset_global_reg_params - Reset global static reg params
203  *
204  * This function is helpful in static driver to reset
205  * the global params.
206  *
207  * Return: void
208  */
hdd_reset_global_reg_params(void)209 void hdd_reset_global_reg_params(void)
210 {
211 	init_by_driver = false;
212 	init_by_reg_core = false;
213 }
214 
215 /**
216  * hdd_update_coex_unsafe_chan_nb_user_prefer() - update coex unsafe
217  * nb prefer framework
218  * @hdd_ctx: hdd context
219  * @config_vars: reg config
220  *
221  * Return: void
222  */
223 #ifdef FEATURE_WLAN_CH_AVOID_EXT
224 static inline
hdd_update_coex_unsafe_chan_nb_user_prefer(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)225 void hdd_update_coex_unsafe_chan_nb_user_prefer(
226 		struct hdd_context *hdd_ctx,
227 		struct reg_config_vars *config_vars)
228 {
229 	config_vars->coex_unsafe_chan_nb_user_prefer =
230 		ucfg_mlme_get_coex_unsafe_chan_nb_user_prefer(
231 		hdd_ctx->psoc);
232 }
233 
234 static inline
hdd_update_coex_unsafe_chan_reg_disable(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)235 void hdd_update_coex_unsafe_chan_reg_disable(
236 		struct hdd_context *hdd_ctx,
237 		struct reg_config_vars *config_vars)
238 {
239 	config_vars->coex_unsafe_chan_reg_disable =
240 		ucfg_mlme_get_coex_unsafe_chan_reg_disable(
241 		hdd_ctx->psoc);
242 }
243 #else
244 static inline
hdd_update_coex_unsafe_chan_nb_user_prefer(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)245 void hdd_update_coex_unsafe_chan_nb_user_prefer(
246 		struct hdd_context *hdd_ctx,
247 		struct reg_config_vars *config_vars)
248 {
249 }
250 
251 static inline
hdd_update_coex_unsafe_chan_reg_disable(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)252 void hdd_update_coex_unsafe_chan_reg_disable(
253 		struct hdd_context *hdd_ctx,
254 		struct reg_config_vars *config_vars)
255 {
256 }
257 #endif
258 
259 #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ)
260 static inline
hdd_update_afc_config(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)261 void hdd_update_afc_config(struct hdd_context *hdd_ctx,
262 			   struct reg_config_vars *config_vars)
263 {
264 	bool enable_6ghz_sp_pwrmode_supp = false;
265 	bool afc_disable_timer_check = false;
266 	bool afc_disable_request_id_check = false;
267 	bool is_afc_reg_noaction = false;
268 
269 	ucfg_mlme_get_enable_6ghz_sp_mode_support(hdd_ctx->psoc,
270 						  &enable_6ghz_sp_pwrmode_supp);
271 	config_vars->enable_6ghz_sp_pwrmode_supp = enable_6ghz_sp_pwrmode_supp;
272 	ucfg_mlme_get_afc_disable_timer_check(hdd_ctx->psoc,
273 					      &afc_disable_timer_check);
274 	config_vars->afc_disable_timer_check = afc_disable_timer_check;
275 	ucfg_mlme_get_afc_disable_request_id_check(
276 				hdd_ctx->psoc, &afc_disable_request_id_check);
277 	config_vars->afc_disable_request_id_check =
278 				afc_disable_request_id_check;
279 	ucfg_mlme_get_afc_reg_noaction(hdd_ctx->psoc,
280 				       &is_afc_reg_noaction);
281 	config_vars->is_afc_reg_noaction = is_afc_reg_noaction;
282 }
283 #else
284 static inline
hdd_update_afc_config(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)285 void hdd_update_afc_config(struct hdd_context *hdd_ctx,
286 			   struct reg_config_vars *config_vars)
287 {
288 }
289 #endif
290 
reg_program_config_vars(struct hdd_context * hdd_ctx,struct reg_config_vars * config_vars)291 static void reg_program_config_vars(struct hdd_context *hdd_ctx,
292 				    struct reg_config_vars *config_vars)
293 {
294 	uint8_t indoor_chnl_marking = 0;
295 	uint32_t band_capability = 0, scan_11d_interval = 0;
296 	bool indoor_chan_enabled = false;
297 	uint32_t restart_beaconing = 0;
298 	uint8_t enable_srd_chan;
299 	bool enable_5dot9_ghz_chan;
300 	QDF_STATUS status;
301 	bool country_priority = 0;
302 	bool value = false;
303 	bool enable_dfs_scan = true;
304 
305 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
306 	if (QDF_IS_STATUS_ERROR(status))
307 		hdd_err("Failed to get MLME band cap, defaulting to BAND_ALL");
308 
309 	status = ucfg_policy_mgr_get_indoor_chnl_marking(hdd_ctx->psoc,
310 							 &indoor_chnl_marking);
311 	if (QDF_STATUS_SUCCESS != status)
312 		hdd_err("can't get indoor channel marking, using default");
313 
314 	status = ucfg_mlme_is_11d_enabled(hdd_ctx->psoc, &value);
315 	if (!QDF_IS_STATUS_SUCCESS(status))
316 		hdd_err("Invalid 11d_enable flag");
317 	config_vars->enable_11d_support = value;
318 
319 	ucfg_mlme_get_nol_across_regdmn(hdd_ctx->psoc, &value);
320 	config_vars->retain_nol_across_regdmn_update = value;
321 
322 	ucfg_mlme_get_scan_11d_interval(hdd_ctx->psoc, &scan_11d_interval);
323 	config_vars->scan_11d_interval = scan_11d_interval;
324 
325 	ucfg_mlme_get_sap_country_priority(hdd_ctx->psoc,
326 					   &country_priority);
327 	config_vars->userspace_ctry_priority = country_priority;
328 
329 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
330 						&enable_dfs_scan);
331 
332 	config_vars->dfs_enabled = enable_dfs_scan;
333 
334 	ucfg_mlme_get_indoor_channel_support(hdd_ctx->psoc,
335 					     &indoor_chan_enabled);
336 	config_vars->indoor_chan_enabled = indoor_chan_enabled;
337 
338 	config_vars->force_ssc_disable_indoor_channel = indoor_chnl_marking;
339 	config_vars->band_capability = band_capability;
340 
341 	ucfg_mlme_get_restart_beaconing_on_ch_avoid(hdd_ctx->psoc,
342 						    &restart_beaconing);
343 	config_vars->restart_beaconing = restart_beaconing;
344 
345 	ucfg_mlme_get_etsi_srd_chan_in_master_mode(hdd_ctx->psoc,
346 						   &enable_srd_chan);
347 	config_vars->enable_srd_chan_in_master_mode = enable_srd_chan;
348 
349 	ucfg_mlme_get_11d_in_world_mode(hdd_ctx->psoc,
350 					&config_vars->enable_11d_in_world_mode);
351 
352 	ucfg_mlme_get_5dot9_ghz_chan_in_master_mode(hdd_ctx->psoc,
353 						    &enable_5dot9_ghz_chan);
354 	config_vars->enable_5dot9_ghz_chan_in_master_mode =
355 						enable_5dot9_ghz_chan;
356 	hdd_update_coex_unsafe_chan_nb_user_prefer(hdd_ctx, config_vars);
357 	hdd_update_coex_unsafe_chan_reg_disable(hdd_ctx, config_vars);
358 	hdd_update_afc_config(hdd_ctx, config_vars);
359 	config_vars->sta_sap_scc_on_indoor_channel =
360 		ucfg_policy_mgr_get_sta_sap_scc_on_indoor_chnl(hdd_ctx->psoc);
361 	config_vars->p2p_indoor_ch_support =
362 		ucfg_p2p_get_indoor_ch_support(hdd_ctx->psoc);
363 }
364 
365 /**
366  * hdd_regulatory_wiphy_init() - regulatory wiphy init
367  * @hdd_ctx: hdd context
368  * @reg: regulatory data
369  * @wiphy: wiphy structure
370  *
371  * Return: void
372  */
373 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
374 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS)
hdd_regulatory_wiphy_init(struct hdd_context * hdd_ctx,struct regulatory * reg,struct wiphy * wiphy)375 static void hdd_regulatory_wiphy_init(struct hdd_context *hdd_ctx,
376 				     struct regulatory *reg,
377 				     struct wiphy *wiphy)
378 {
379 	const struct ieee80211_regdomain *reg_rules;
380 	int chan_num;
381 	struct ieee80211_channel *chan;
382 
383 	if (hdd_is_world_regdomain(reg->reg_domain)) {
384 		reg_rules = hdd_get_world_regrules(reg);
385 		wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
386 	} else {
387 		wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
388 		reg_rules = &hdd_world_regrules_60_61_62;
389 	}
390 
391 	/*
392 	 * save the original driver regulatory flags
393 	 */
394 	hdd_ctx->reg.reg_flags = wiphy->regulatory_flags;
395 	wiphy_apply_custom_regulatory(wiphy, reg_rules);
396 
397 	/*
398 	 * disable 2.4 Ghz channels that dont have 20 mhz bw
399 	 */
400 	for (chan_num = 0;
401 	     chan_num < wiphy->bands[HDD_NL80211_BAND_2GHZ]->n_channels;
402 	     chan_num++) {
403 		chan = &(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels[chan_num]);
404 		if (chan->flags & IEEE80211_CHAN_NO_20MHZ)
405 			chan->flags |= IEEE80211_CHAN_DISABLED;
406 	}
407 
408 	/*
409 	 * restore the driver regulatory flags since
410 	 * wiphy_apply_custom_regulatory may have
411 	 * changed them
412 	 */
413 	wiphy->regulatory_flags = hdd_ctx->reg.reg_flags;
414 
415 }
416 #else
hdd_regulatory_wiphy_init(struct hdd_context * hdd_ctx,struct regulatory * reg,struct wiphy * wiphy)417 static void hdd_regulatory_wiphy_init(struct hdd_context *hdd_ctx,
418 				     struct regulatory *reg,
419 				     struct wiphy *wiphy)
420 {
421 	const struct ieee80211_regdomain *reg_rules;
422 
423 	if (hdd_is_world_regdomain(reg->reg_domain)) {
424 		reg_rules = hdd_get_world_regrules(reg);
425 		wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
426 	} else {
427 		wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
428 		reg_rules = &hdd_world_regrules_60_61_62;
429 	}
430 
431 	/*
432 	 * save the original driver regulatory flags
433 	 */
434 	hdd_ctx->reg.reg_flags = wiphy->flags;
435 	wiphy_apply_custom_regulatory(wiphy, reg_rules);
436 
437 	/*
438 	 * restore the driver regulatory flags since
439 	 * wiphy_apply_custom_regulatory may have
440 	 * changed them
441 	 */
442 	wiphy->flags = hdd_ctx->reg.reg_flags;
443 
444 }
445 #endif
446 
447 /**
448  * is_wiphy_custom_regulatory() - is custom regulatory defined
449  * @wiphy: wiphy
450  *
451  * Return: int
452  */
453 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
454 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS)
is_wiphy_custom_regulatory(struct wiphy * wiphy)455 static int is_wiphy_custom_regulatory(struct wiphy *wiphy)
456 {
457 
458 	return wiphy->regulatory_flags & REGULATORY_CUSTOM_REG;
459 }
460 #else
is_wiphy_custom_regulatory(struct wiphy * wiphy)461 static int is_wiphy_custom_regulatory(struct wiphy *wiphy)
462 {
463 	return wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY;
464 }
465 #endif
466 
467 /**
468  * hdd_modify_wiphy() - modify wiphy
469  * @wiphy: wiphy
470  * @chan: channel structure
471  *
472  * Return: void
473  */
474 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
hdd_modify_wiphy(struct wiphy * wiphy,struct ieee80211_channel * chan)475 static void hdd_modify_wiphy(struct wiphy  *wiphy,
476 			     struct ieee80211_channel *chan)
477 {
478 	const struct ieee80211_reg_rule *reg_rule;
479 
480 	if (is_wiphy_custom_regulatory(wiphy)) {
481 		reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
482 		if (!IS_ERR(reg_rule)) {
483 			chan->flags &= ~IEEE80211_CHAN_DISABLED;
484 
485 			if (!(reg_rule->flags & NL80211_RRF_DFS)) {
486 				hdd_debug("Remove dfs restriction for %u",
487 					chan->center_freq);
488 				chan->flags &= ~IEEE80211_CHAN_RADAR;
489 			}
490 
491 			if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) {
492 				hdd_debug("Remove passive restriction for %u",
493 					chan->center_freq);
494 				chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
495 			}
496 
497 			if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) {
498 				hdd_debug("Remove no ibss restriction for %u",
499 					chan->center_freq);
500 				chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
501 			}
502 
503 			chan->max_power =
504 				MBM_TO_DBM(reg_rule->power_rule.max_eirp);
505 		}
506 	}
507 }
508 #endif
509 
510 /**
511  * hdd_set_dfs_region() - set the dfs_region
512  * @hdd_ctx: HDD context
513  * @dfs_reg: the dfs_region to set
514  *
515  * Return: void
516  */
517 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
518 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS)
hdd_set_dfs_region(struct hdd_context * hdd_ctx,enum dfs_reg dfs_reg)519 static void hdd_set_dfs_region(struct hdd_context *hdd_ctx,
520 			       enum dfs_reg dfs_reg)
521 {
522 	wlan_reg_set_dfs_region(hdd_ctx->pdev, dfs_reg);
523 }
524 #endif
525 
526 /**
527  * hdd_process_regulatory_data() - process regulatory data
528  * @hdd_ctx: hdd context
529  * @wiphy: wiphy
530  * @reset: whether to reset channel data
531  *
532  * Return: void
533  */
534 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
hdd_process_regulatory_data(struct hdd_context * hdd_ctx,struct wiphy * wiphy,bool reset)535 static void hdd_process_regulatory_data(struct hdd_context *hdd_ctx,
536 					struct wiphy *wiphy,
537 					bool reset)
538 {
539 	int band_num;
540 	int chan_num;
541 	enum channel_enum chan_enum = CHAN_ENUM_1;
542 	struct ieee80211_channel *wiphy_chan, *wiphy_chan_144 = NULL;
543 	struct regulatory_channel *cds_chan;
544 	uint8_t band_capability, indoor_chnl_marking = 0;
545 	bool indoor, sta_sap_con_on_indoor;
546 	QDF_STATUS status;
547 
548 	band_capability = hdd_ctx->curr_band;
549 
550 	status = ucfg_policy_mgr_get_indoor_chnl_marking(hdd_ctx->psoc,
551 							 &indoor_chnl_marking);
552 
553 	if (QDF_STATUS_SUCCESS != status)
554 		hdd_err("can't get indoor channel marking, using default");
555 
556 	 sta_sap_con_on_indoor =
557 		 ucfg_policy_mgr_get_sta_sap_scc_on_indoor_chnl(hdd_ctx->psoc);
558 
559 	for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) {
560 
561 		if (!wiphy->bands[band_num])
562 			continue;
563 
564 		for (chan_num = 0;
565 		     chan_num < wiphy->bands[band_num]->n_channels &&
566 		     chan_enum < NUM_CHANNELS;
567 		     chan_num++) {
568 			wiphy_chan =
569 				&(wiphy->bands[band_num]->channels[chan_num]);
570 			cds_chan = &(reg_channels[chan_enum]);
571 			cds_chan->chan_flags = 0;
572 			if (CHAN_ENUM_144 == chan_enum)
573 				wiphy_chan_144 = wiphy_chan;
574 
575 			chan_enum++;
576 
577 			if (!reset)
578 				hdd_modify_wiphy(wiphy, wiphy_chan);
579 
580 			if (indoor_chnl_marking &&
581 			    (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
582 				cds_chan->chan_flags |=
583 					REGULATORY_CHAN_INDOOR_ONLY;
584 
585 			if (wiphy_chan->flags & IEEE80211_CHAN_DISABLED) {
586 				cds_chan->state = CHANNEL_STATE_DISABLE;
587 				cds_chan->chan_flags |=
588 					REGULATORY_CHAN_DISABLED;
589 			} else if (wiphy_chan->flags &
590 				    (IEEE80211_CHAN_RADAR |
591 				     IEEE80211_CHAN_PASSIVE_SCAN)) {
592 				cds_chan->state = CHANNEL_STATE_DFS;
593 				if (wiphy_chan->flags & IEEE80211_CHAN_RADAR)
594 					cds_chan->chan_flags |=
595 						REGULATORY_CHAN_RADAR;
596 				if (wiphy_chan->flags &
597 				    IEEE80211_CHAN_PASSIVE_SCAN)
598 					cds_chan->chan_flags |=
599 						REGULATORY_CHAN_NO_IR;
600 			} else if (wiphy_chan->flags &
601 				     IEEE80211_CHAN_INDOOR_ONLY) {
602 				cds_chan->chan_flags |=
603 						REGULATORY_CHAN_INDOOR_ONLY;
604 
605 				ucfg_mlme_get_indoor_channel_support(
606 								hdd_ctx->psoc,
607 								&indoor);
608 				if (!indoor) {
609 					cds_chan->state = CHANNEL_STATE_DFS;
610 					wiphy_chan->flags |=
611 						IEEE80211_CHAN_PASSIVE_SCAN;
612 					if (!sta_sap_con_on_indoor)
613 						cds_chan->chan_flags |=
614 							REGULATORY_CHAN_NO_IR;
615 				} else
616 					cds_chan->state = CHANNEL_STATE_ENABLE;
617 			} else
618 				cds_chan->state = CHANNEL_STATE_ENABLE;
619 			cds_chan->tx_power = wiphy_chan->max_power;
620 			if (wiphy_chan->flags & IEEE80211_CHAN_NO_10MHZ)
621 				cds_chan->max_bw = 5;
622 			else if (wiphy_chan->flags & IEEE80211_CHAN_NO_20MHZ)
623 				cds_chan->max_bw = 10;
624 			/*
625 			 * IEEE80211_CHAN_NO_HT40  is defined as 0x30 in kernel
626 			 * 4th BIT representing IEEE80211_CHAN_NO_HT40PLUS
627 			 * 5th BIT representing IEEE80211_CHAN_NO_HT40MINUS
628 			 *
629 			 * In order to claim no 40Mhz support value of
630 			 * wiphy_chan->flags needs to be 0x30.
631 			 * 0x20 and 0x10 values shows that either HT40+ or
632 			 * HT40- is not supported based on BIT set but they
633 			 * can support 40Mhz Operation.
634 			 */
635 			else if ((wiphy_chan->flags & IEEE80211_CHAN_NO_HT40) ==
636 					IEEE80211_CHAN_NO_HT40)
637 				cds_chan->max_bw = 20;
638 			else if (wiphy_chan->flags & IEEE80211_CHAN_NO_80MHZ)
639 				cds_chan->max_bw = 40;
640 			else if (wiphy_chan->flags & IEEE80211_CHAN_NO_160MHZ)
641 				cds_chan->max_bw = 80;
642 			else
643 				cds_chan->max_bw = 160;
644 		}
645 	}
646 
647 	if (0 == (hdd_ctx->reg.eeprom_rd_ext &
648 		  (1 << WMI_REG_EXT_FCC_CH_144))) {
649 		cds_chan = &(reg_channels[CHAN_ENUM_144]);
650 		cds_chan->state = CHANNEL_STATE_DISABLE;
651 		if (wiphy_chan_144)
652 			wiphy_chan_144->flags |= IEEE80211_CHAN_DISABLED;
653 	}
654 
655 	wlan_hdd_cfg80211_update_band(hdd_ctx, wiphy, band_capability);
656 }
657 
658 /**
659  * hdd_regulatory_init_no_offload() - regulatory init
660  * @hdd_ctx: hdd context
661  * @wiphy: wiphy
662  *
663  * Return: int
664  */
hdd_regulatory_init_no_offload(struct hdd_context * hdd_ctx,struct wiphy * wiphy)665 static int hdd_regulatory_init_no_offload(struct hdd_context *hdd_ctx,
666 					  struct wiphy *wiphy)
667 {
668 	int ret_val;
669 	struct regulatory *reg_info;
670 	enum dfs_reg dfs_reg;
671 	struct reg_config_vars config_vars;
672 
673 	reg_info = &hdd_ctx->reg;
674 
675 	ret_val = cds_fill_some_regulatory_info(reg_info);
676 	if (ret_val) {
677 		hdd_err("incorrect BDF regulatory data");
678 		return ret_val;
679 	}
680 
681 	hdd_set_dfs_region(hdd_ctx, DFS_FCC_REGION);
682 
683 	hdd_regulatory_wiphy_init(hdd_ctx, reg_info, wiphy);
684 
685 	hdd_process_regulatory_data(hdd_ctx, wiphy, true);
686 
687 	reg_info->cc_src = SOURCE_DRIVER;
688 
689 	ucfg_reg_set_default_country(hdd_ctx->psoc, reg_info->alpha2);
690 
691 	cds_fill_and_send_ctl_to_fw(reg_info);
692 
693 	wlan_reg_get_dfs_region(hdd_ctx->pdev, &dfs_reg);
694 
695 	reg_program_config_vars(hdd_ctx, &config_vars);
696 	ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars);
697 	ucfg_reg_program_mas_chan_list(hdd_ctx->psoc,
698 				       reg_channels,
699 				       hdd_ctx->reg.alpha2,
700 				       dfs_reg);
701 
702 	return 0;
703 }
704 #endif
705 
706 /**
707  * hdd_modify_indoor_channel_state_flags() - modify wiphy flags and cds state
708  * @hdd_ctx: HDD context
709  * @wiphy_chan: wiphy channel number
710  * @cds_chan: cds channel structure
711  * @chan_enum: enumerated value of the channel
712  * @chan_num: channel number
713  * @disable: Disable/enable the flags
714  *
715  * Modify wiphy flags and cds state if channel is indoor.
716  *
717  * Return: void
718  */
hdd_modify_indoor_channel_state_flags(struct hdd_context * hdd_ctx,struct ieee80211_channel * wiphy_chan,struct regulatory_channel * cds_chan,enum channel_enum chan_enum,int chan_num,bool disable)719 void hdd_modify_indoor_channel_state_flags(
720 	struct hdd_context *hdd_ctx,
721 	struct ieee80211_channel *wiphy_chan,
722 	struct regulatory_channel *cds_chan,
723 	enum channel_enum chan_enum, int chan_num, bool disable)
724 {
725 	bool indoor_support;
726 
727 	ucfg_mlme_get_indoor_channel_support(hdd_ctx->psoc, &indoor_support);
728 
729 	/* Mark indoor channel to disable in wiphy and cds */
730 	if (disable) {
731 		if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
732 			wiphy_chan->flags |=
733 				IEEE80211_CHAN_DISABLED;
734 			hdd_info("Mark indoor channel %d as disable",
735 				cds_chan->center_freq);
736 			cds_chan->state =
737 				CHANNEL_STATE_DISABLE;
738 		}
739 	} else {
740 		if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
741 			wiphy_chan->flags &=
742 					~IEEE80211_CHAN_DISABLED;
743 			 /*
744 			  * Indoor channels may be marked as dfs / enable
745 			  * during regulatory processing
746 			  */
747 			if ((wiphy_chan->flags &
748 				(IEEE80211_CHAN_RADAR |
749 				IEEE80211_CHAN_PASSIVE_SCAN)) ||
750 			     ((indoor_support == false) &&
751 				(wiphy_chan->flags &
752 				IEEE80211_CHAN_INDOOR_ONLY)))
753 				cds_chan->state =
754 					CHANNEL_STATE_DFS;
755 			else
756 				cds_chan->state =
757 					CHANNEL_STATE_ENABLE;
758 			hdd_debug("Mark indoor channel %d as cds_chan state %d",
759 					cds_chan->chan_num, cds_chan->state);
760 		}
761 	}
762 
763 }
764 
hdd_update_indoor_channel(struct hdd_context * hdd_ctx,bool disable)765 void hdd_update_indoor_channel(struct hdd_context *hdd_ctx,
766 					bool disable)
767 {
768 	int band_num;
769 	int chan_num;
770 	enum channel_enum chan_enum = CHAN_ENUM_2412;
771 	struct ieee80211_channel *wiphy_chan, *wiphy_chan_144 = NULL;
772 	struct regulatory_channel *cds_chan;
773 	uint8_t band_capability;
774 	struct wiphy *wiphy = hdd_ctx->wiphy;
775 
776 	hdd_enter();
777 	hdd_debug("mark indoor channel disable: %d", disable);
778 
779 	band_capability = hdd_ctx->curr_band;
780 	for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) {
781 
782 		if (!wiphy->bands[band_num])
783 			continue;
784 
785 		for (chan_num = 0;
786 		     chan_num < wiphy->bands[band_num]->n_channels &&
787 		     chan_enum < NUM_CHANNELS;
788 		     chan_num++) {
789 
790 			wiphy_chan =
791 				&(wiphy->bands[band_num]->channels[chan_num]);
792 			cds_chan = &(reg_channels[chan_enum]);
793 			if (chan_enum == CHAN_ENUM_5720)
794 				wiphy_chan_144 = wiphy_chan;
795 
796 			chan_enum++;
797 			hdd_modify_indoor_channel_state_flags(hdd_ctx,
798 				wiphy_chan, cds_chan,
799 				chan_enum, chan_num, disable);
800 		}
801 	}
802 
803 	/* Notify the regulatory domain to update the channel list */
804 	if (QDF_IS_STATUS_ERROR(ucfg_reg_notify_sap_event(hdd_ctx->pdev,
805 							  disable))) {
806 		hdd_err("Failed to notify sap event");
807 	}
808 	hdd_exit();
809 
810 }
811 
812 /**
813  * hdd_program_country_code() - process channel information from country code
814  * @hdd_ctx: hddc context
815  *
816  * Return: void
817  */
818 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
hdd_program_country_code(struct hdd_context * hdd_ctx)819 void hdd_program_country_code(struct hdd_context *hdd_ctx)
820 {
821 }
822 #else
hdd_program_country_code(struct hdd_context * hdd_ctx)823 void hdd_program_country_code(struct hdd_context *hdd_ctx)
824 {
825 	struct wiphy *wiphy = hdd_ctx->wiphy;
826 	uint8_t *country_alpha2 = hdd_ctx->reg.alpha2;
827 
828 	if (!init_by_reg_core && !init_by_driver) {
829 		init_by_driver = true;
830 		if (('0' != country_alpha2[0]) ||
831 		    ('0' != country_alpha2[1]))
832 			regulatory_hint(wiphy, country_alpha2);
833 	}
834 }
835 #endif
836 
hdd_reg_wait_for_country_change(struct hdd_context * hdd_ctx)837 void hdd_reg_wait_for_country_change(struct hdd_context *hdd_ctx)
838 {
839 	qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
840 	if (hdd_ctx->is_regulatory_update_in_progress) {
841 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
842 		hdd_debug("waiting for channel list to update");
843 		qdf_wait_for_event_completion(&hdd_ctx->regulatory_update_event,
844 					      CHANNEL_LIST_UPDATE_TIMEOUT);
845 		/* In case of set country failure in FW, response never comes
846 		 * so wait the full timeout, then set in_progress to false.
847 		 * If the response comes back, in_progress will already be set
848 		 * to false anyways.
849 		 */
850 		qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
851 		hdd_ctx->is_regulatory_update_in_progress = false;
852 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
853 	} else {
854 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
855 	}
856 }
857 
hdd_reg_set_country(struct hdd_context * hdd_ctx,char * country_code)858 int hdd_reg_set_country(struct hdd_context *hdd_ctx, char *country_code)
859 {
860 	QDF_STATUS status;
861 	uint8_t cc[REG_ALPHA2_LEN + 1];
862 	uint8_t alpha2[REG_ALPHA2_LEN + 1];
863 	enum country_src cc_src;
864 
865 	if (!country_code) {
866 		hdd_err("country_code is null");
867 		return -EINVAL;
868 	}
869 
870 	if (!ucfg_reg_is_user_country_set_allowed(hdd_ctx->psoc)) {
871 		hdd_err("user_country is not allowed");
872 		return -EINVAL;
873 	}
874 
875 	qdf_mem_copy(cc, country_code, REG_ALPHA2_LEN);
876 	cc[REG_ALPHA2_LEN] = '\0';
877 
878 	if (!qdf_mem_cmp(country_code, hdd_ctx->reg.alpha2, REG_ALPHA2_LEN)) {
879 		cc_src = ucfg_reg_get_cc_and_src(hdd_ctx->psoc, alpha2);
880 		if (cc_src == SOURCE_USERSPACE || cc_src == SOURCE_CORE) {
881 			hdd_debug("country code is the same");
882 			return 0;
883 		}
884 	}
885 
886 	qdf_event_reset(&hdd_ctx->regulatory_update_event);
887 	qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
888 	hdd_ctx->is_regulatory_update_in_progress = true;
889 	qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
890 
891 	status = ucfg_reg_set_country(hdd_ctx->pdev, cc);
892 	if (QDF_IS_STATUS_ERROR(status)) {
893 		hdd_err("Failed to set country");
894 		qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
895 		hdd_ctx->is_regulatory_update_in_progress = false;
896 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
897 	}
898 
899 	hdd_reg_wait_for_country_change(hdd_ctx);
900 
901 	return qdf_status_to_os_return(status);
902 }
903 
hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(uint8_t qca_setband)904 uint32_t hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(uint8_t qca_setband)
905 {
906 	uint32_t band_bitmap = 0;
907 
908 	switch (qca_setband) {
909 	case QCA_SETBAND_AUTO:
910 		band_bitmap |= REG_BAND_MASK_ALL;
911 		break;
912 	case QCA_SETBAND_5G:
913 		band_bitmap |= BIT(REG_BAND_5G);
914 		break;
915 	case QCA_SETBAND_2G:
916 		band_bitmap |= BIT(REG_BAND_2G);
917 		break;
918 	default:
919 		hdd_err("Invalid band value %u", qca_setband);
920 		return 0;
921 	}
922 
923 	return band_bitmap;
924 }
925 
hdd_reg_set_band(struct net_device * dev,uint32_t band_bitmap)926 int hdd_reg_set_band(struct net_device *dev, uint32_t band_bitmap)
927 {
928 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
929 	struct hdd_context *hdd_ctx;
930 	uint32_t current_band;
931 	QDF_STATUS status;
932 
933 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
934 
935 	if (!band_bitmap) {
936 		hdd_err("Can't disable all bands");
937 		return -EINVAL;
938 	}
939 
940 	hdd_debug("change band to %u", band_bitmap);
941 
942 	if (ucfg_reg_get_band(hdd_ctx->pdev, &current_band) !=
943 	    QDF_STATUS_SUCCESS) {
944 		hdd_debug("Failed to get current band config");
945 		return -EIO;
946 	}
947 
948 	/*
949 	 * If SET_FCC_CHANNEL 0 command is received first then 6 GHz band would
950 	 * be disabled and band_capability would be set to 3 but existing 6 GHz
951 	 * STA and P2P client connections won't be disconnected.
952 	 * If set band comes again for 6 GHz band disabled and band_bitmap is
953 	 * equal to band_capability, proceed to disable 6 GHz band completely.
954 	 */
955 	if (current_band == band_bitmap &&
956 	    !ucfg_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev)) {
957 		hdd_debug("band is the same so not updating");
958 		return 0;
959 	}
960 
961 	hdd_ctx->curr_band = wlan_reg_band_bitmap_to_band_info(band_bitmap);
962 
963 	if (QDF_IS_STATUS_ERROR(ucfg_reg_set_band(hdd_ctx->pdev,
964 						  band_bitmap))) {
965 		hdd_err("Failed to set the band bitmap value to %u",
966 			band_bitmap);
967 		return -EINVAL;
968 	}
969 
970 	status = ucfg_cm_set_roam_band_update(hdd_ctx->psoc,
971 					      adapter->deflink->vdev_id);
972 	if (QDF_IS_STATUS_ERROR(status))
973 		hdd_err("Failed to send RSO update to fw on set band");
974 
975 	return 0;
976 }
977 
978 /**
979  * hdd_restore_custom_reg_settings() - restore custom reg settings
980  * @wiphy: wiphy structure
981  * @country_alpha2: alpha2 of the country
982  * @reset: whether wiphy is reset
983  *
984  * Return: void
985  */
986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
987 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS)
hdd_restore_custom_reg_settings(struct wiphy * wiphy,uint8_t * country_alpha2,bool * reset)988 static void hdd_restore_custom_reg_settings(struct wiphy *wiphy,
989 					    uint8_t *country_alpha2,
990 					    bool *reset)
991 {
992 }
993 #else
hdd_restore_custom_reg_settings(struct wiphy * wiphy,uint8_t * country_alpha2,bool * reset)994 static void hdd_restore_custom_reg_settings(struct wiphy *wiphy,
995 					    uint8_t *country_alpha2,
996 					    bool *reset)
997 {
998 	struct ieee80211_supported_band *sband;
999 	enum nl80211_band band;
1000 	struct ieee80211_channel *chan;
1001 	int i;
1002 
1003 	if ((country_alpha2[0] == '0') &&
1004 	    (country_alpha2[1] == '0') &&
1005 	    (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) {
1006 
1007 		for (band = 0; band < HDD_NUM_NL80211_BANDS; band++) {
1008 			sband = wiphy->bands[band];
1009 			if (!sband)
1010 				continue;
1011 			for (i = 0; i < sband->n_channels; i++) {
1012 				chan = &sband->channels[i];
1013 				chan->flags = chan->orig_flags;
1014 				chan->max_antenna_gain = chan->orig_mag;
1015 				chan->max_power = chan->orig_mpwr;
1016 			}
1017 		}
1018 		*reset = true;
1019 	}
1020 }
1021 #endif
1022 
1023 /**
1024  * hdd_restore_reg_flags() - restore regulatory flags
1025  * @wiphy: device wiphy
1026  * @flags: regulatory flags
1027  *
1028  * Return: void
1029  */
1030 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1031 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS)
hdd_restore_reg_flags(struct wiphy * wiphy,uint32_t flags)1032 static void hdd_restore_reg_flags(struct wiphy *wiphy, uint32_t flags)
1033 {
1034 	wiphy->regulatory_flags = flags;
1035 }
1036 #else
hdd_restore_reg_flags(struct wiphy * wiphy,uint32_t flags)1037 static void hdd_restore_reg_flags(struct wiphy *wiphy, uint32_t flags)
1038 {
1039 	wiphy->flags = flags;
1040 }
1041 #endif
1042 
1043 /**
1044  * hdd_reg_notifier() - regulatory notifier
1045  * @wiphy: wiphy
1046  * @request: regulatory request
1047  *
1048  * Return: void
1049  */
1050 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
hdd_reg_notifier(struct wiphy * wiphy,struct regulatory_request * request)1051 void hdd_reg_notifier(struct wiphy *wiphy,
1052 		      struct regulatory_request *request)
1053 {
1054 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1055 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1056 	char country[REG_ALPHA2_LEN + 1] = {0};
1057 	bool update_already_in_progress =
1058 		hdd_ctx->is_regulatory_update_in_progress;
1059 
1060 	if (cds_is_driver_unloading() || cds_is_driver_recovering() ||
1061 	    cds_is_driver_in_bad_state()) {
1062 		hdd_err("unloading or ssr in progress, ignore");
1063 		return;
1064 	}
1065 
1066 	if (hdd_ctx->is_wiphy_suspended) {
1067 		hdd_err_rl("system/cfg80211 is already suspend");
1068 		return;
1069 	}
1070 
1071 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
1072 		hdd_err_rl("Driver module is closed, dropping request");
1073 		return;
1074 	}
1075 
1076 	hdd_debug("country: %c%c, initiator %d, dfs_region: %d",
1077 		  request->alpha2[0],
1078 		  request->alpha2[1],
1079 		  request->initiator,
1080 		  request->dfs_region);
1081 
1082 	switch (request->initiator) {
1083 	case NL80211_REGDOM_SET_BY_USER:
1084 
1085 		if (request->user_reg_hint_type !=
1086 		    NL80211_USER_REG_HINT_CELL_BASE)
1087 			return;
1088 
1089 		qdf_event_reset(&hdd_ctx->regulatory_update_event);
1090 		qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
1091 		hdd_ctx->is_regulatory_update_in_progress = true;
1092 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
1093 
1094 		qdf_mem_copy(country, request->alpha2, QDF_MIN(
1095 			     sizeof(request->alpha2), sizeof(country)));
1096 		status = ucfg_reg_set_country(hdd_ctx->pdev, country);
1097 		break;
1098 	case NL80211_REGDOM_SET_BY_CORE:
1099 	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
1100 	case NL80211_REGDOM_SET_BY_DRIVER:
1101 	default:
1102 		break;
1103 	}
1104 
1105 	if (QDF_IS_STATUS_ERROR(status) && !update_already_in_progress) {
1106 		hdd_err("Failed to set country");
1107 		qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
1108 		hdd_ctx->is_regulatory_update_in_progress = false;
1109 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
1110 	}
1111 }
1112 #else
hdd_reg_notifier(struct wiphy * wiphy,struct regulatory_request * request)1113 void hdd_reg_notifier(struct wiphy *wiphy,
1114 		      struct regulatory_request *request)
1115 {
1116 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1117 	bool reset = false;
1118 	enum dfs_reg dfs_reg;
1119 	struct reg_config_vars config_vars;
1120 	int ret_val;
1121 
1122 	hdd_debug("country: %c%c, initiator %d, dfs_region: %d",
1123 		  request->alpha2[0],
1124 		  request->alpha2[1],
1125 		  request->initiator,
1126 		  request->dfs_region);
1127 
1128 	if (!hdd_ctx) {
1129 		hdd_err("invalid hdd_ctx pointer");
1130 		return;
1131 	}
1132 
1133 	if (cds_is_driver_unloading() || cds_is_driver_recovering() ||
1134 	    cds_is_driver_in_bad_state()) {
1135 		hdd_err("unloading or ssr in progress, ignore");
1136 		return;
1137 	}
1138 
1139 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
1140 		hdd_err("Driver module is closed; dropping request");
1141 		return;
1142 	}
1143 
1144 	if (hdd_ctx->is_wiphy_suspended == true) {
1145 		hdd_err("system/cfg80211 is already suspend");
1146 		return;
1147 	}
1148 
1149 	if (('K' == request->alpha2[0]) &&
1150 	    ('R' == request->alpha2[1]))
1151 		request->dfs_region = (enum nl80211_dfs_regions)DFS_KR_REGION;
1152 
1153 	if (('C' == request->alpha2[0]) &&
1154 	    ('N' == request->alpha2[1]))
1155 		request->dfs_region = (enum nl80211_dfs_regions)DFS_CN_REGION;
1156 
1157 	/* first check if this callback is in response to the driver callback */
1158 	switch (request->initiator) {
1159 	case NL80211_REGDOM_SET_BY_DRIVER:
1160 	case NL80211_REGDOM_SET_BY_CORE:
1161 	case NL80211_REGDOM_SET_BY_USER:
1162 
1163 		if ((false == init_by_driver) &&
1164 		    (false == init_by_reg_core)) {
1165 
1166 			if (NL80211_REGDOM_SET_BY_CORE == request->initiator)
1167 				return;
1168 			init_by_reg_core = true;
1169 		}
1170 
1171 		if ((NL80211_REGDOM_SET_BY_DRIVER == request->initiator) &&
1172 		    (true == init_by_driver)) {
1173 
1174 			/*
1175 			 * restore the driver regulatory flags since
1176 			 * regulatory_hint may have
1177 			 * changed them
1178 			 */
1179 			hdd_restore_reg_flags(wiphy, hdd_ctx->reg.reg_flags);
1180 		}
1181 
1182 		if (NL80211_REGDOM_SET_BY_CORE == request->initiator) {
1183 			hdd_ctx->reg.cc_src = SOURCE_CORE;
1184 			if (is_wiphy_custom_regulatory(wiphy))
1185 				reset = true;
1186 		} else if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) {
1187 			hdd_ctx->reg.cc_src = SOURCE_DRIVER;
1188 		} else {
1189 			hdd_ctx->reg.cc_src = SOURCE_USERSPACE;
1190 			hdd_restore_custom_reg_settings(wiphy,
1191 							request->alpha2,
1192 							&reset);
1193 		}
1194 
1195 		hdd_ctx->reg.alpha2[0] = request->alpha2[0];
1196 		hdd_ctx->reg.alpha2[1] = request->alpha2[1];
1197 
1198 		ret_val = hdd_update_regulatory_info(hdd_ctx);
1199 		if (ret_val) {
1200 			hdd_err("invalid reg info, do not process");
1201 			return;
1202 		}
1203 
1204 		hdd_process_regulatory_data(hdd_ctx, wiphy, reset);
1205 
1206 		sme_generic_change_country_code(hdd_ctx->mac_handle,
1207 						hdd_ctx->reg.alpha2);
1208 
1209 		cds_fill_and_send_ctl_to_fw(&hdd_ctx->reg);
1210 
1211 		hdd_set_dfs_region(hdd_ctx, request->dfs_region);
1212 		wlan_reg_get_dfs_region(hdd_ctx->pdev, &dfs_reg);
1213 
1214 		reg_program_config_vars(hdd_ctx, &config_vars);
1215 		ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars);
1216 		ucfg_reg_program_mas_chan_list(hdd_ctx->psoc,
1217 					       reg_channels,
1218 					       hdd_ctx->reg.alpha2,
1219 					       dfs_reg);
1220 		break;
1221 
1222 	default:
1223 		break;
1224 	}
1225 }
1226 #endif
1227 
1228 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1229 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
fill_wiphy_channel_320mhz(struct ieee80211_channel * wiphy_chan,uint16_t max_bw)1230 static void fill_wiphy_channel_320mhz(struct ieee80211_channel *wiphy_chan,
1231 				      uint16_t max_bw)
1232 {
1233 	if (max_bw < 320)
1234 		wiphy_chan->flags |= IEEE80211_CHAN_NO_320MHZ;
1235 }
1236 #else
1237 static inline
fill_wiphy_channel_320mhz(struct ieee80211_channel * wiphy_chan,uint16_t max_bw)1238 void fill_wiphy_channel_320mhz(struct ieee80211_channel *wiphy_chan,
1239 			       uint16_t max_bw)
1240 {
1241 }
1242 #endif
1243 
fill_wiphy_channel(struct ieee80211_channel * wiphy_chan,struct regulatory_channel * cur_chan)1244 static void fill_wiphy_channel(struct ieee80211_channel *wiphy_chan,
1245 			       struct regulatory_channel *cur_chan)
1246 {
1247 
1248 	wiphy_chan->flags = 0;
1249 	wiphy_chan->max_power = cur_chan->tx_power;
1250 
1251 	if (cur_chan->chan_flags & REGULATORY_CHAN_DISABLED)
1252 		wiphy_chan->flags  |= IEEE80211_CHAN_DISABLED;
1253 	if (cur_chan->chan_flags & REGULATORY_CHAN_NO_IR)
1254 		wiphy_chan->flags  |= IEEE80211_CHAN_NO_IR;
1255 	if (cur_chan->chan_flags & REGULATORY_CHAN_RADAR)
1256 		wiphy_chan->flags  |= IEEE80211_CHAN_RADAR;
1257 	if (cur_chan->chan_flags & REGULATORY_CHAN_NO_OFDM)
1258 		wiphy_chan->flags  |= IEEE80211_CHAN_NO_OFDM;
1259 	if (cur_chan->chan_flags & REGULATORY_CHAN_INDOOR_ONLY)
1260 		wiphy_chan->flags  |= IEEE80211_CHAN_INDOOR_ONLY;
1261 
1262 	if (cur_chan->max_bw < 10)
1263 		wiphy_chan->flags |= IEEE80211_CHAN_NO_10MHZ;
1264 	if (cur_chan->max_bw < 20)
1265 		wiphy_chan->flags |= IEEE80211_CHAN_NO_20MHZ;
1266 	if (cur_chan->max_bw < 40)
1267 		wiphy_chan->flags |= IEEE80211_CHAN_NO_HT40;
1268 	if (cur_chan->max_bw < 80)
1269 		wiphy_chan->flags |= IEEE80211_CHAN_NO_80MHZ;
1270 	if (cur_chan->max_bw < 160)
1271 		wiphy_chan->flags |= IEEE80211_CHAN_NO_160MHZ;
1272 
1273 	fill_wiphy_channel_320mhz(wiphy_chan, cur_chan->max_bw);
1274 
1275 	wiphy_chan->orig_flags = wiphy_chan->flags;
1276 }
1277 
fill_wiphy_band_channels(struct wiphy * wiphy,struct regulatory_channel * cur_chan_list,uint8_t band_id)1278 static void fill_wiphy_band_channels(struct wiphy *wiphy,
1279 				     struct regulatory_channel *cur_chan_list,
1280 				     uint8_t band_id)
1281 {
1282 	uint32_t wiphy_num_chan, wiphy_index;
1283 	uint32_t chan_cnt;
1284 	struct ieee80211_channel *wiphy_chan;
1285 
1286 	if (!wiphy->bands[band_id])
1287 		return;
1288 
1289 	wiphy_num_chan = wiphy->bands[band_id]->n_channels;
1290 	wiphy_chan = wiphy->bands[band_id]->channels;
1291 
1292 	for (wiphy_index = 0; wiphy_index < wiphy_num_chan; wiphy_index++) {
1293 		for (chan_cnt = 0; chan_cnt < NUM_CHANNELS; chan_cnt++) {
1294 			if (wiphy_chan[wiphy_index].center_freq ==
1295 			    cur_chan_list[chan_cnt].center_freq) {
1296 				fill_wiphy_channel(&(wiphy_chan[wiphy_index]),
1297 						   &(cur_chan_list[chan_cnt]));
1298 				break;
1299 			}
1300 		}
1301 	}
1302 }
1303 
1304 #ifdef FEATURE_WLAN_CH_AVOID
1305 /**
1306  * hdd_ch_avoid_ind() - Avoid notified channels from FW handler
1307  * @hdd_ctxt: HDD context
1308  * @unsafe_chan_list: Channels that are unsafe
1309  * @avoid_freq_list: Frequencies to avoid
1310  *
1311  * Avoid channel notification from FW handler.
1312  * FW will send un-safe channel list to avoid over wrapping.
1313  * hostapd should not use notified channel
1314  *
1315  * Return: None
1316  */
hdd_ch_avoid_ind(struct hdd_context * hdd_ctxt,struct unsafe_ch_list * unsafe_chan_list,struct ch_avoid_ind_type * avoid_freq_list)1317 void hdd_ch_avoid_ind(struct hdd_context *hdd_ctxt,
1318 		struct unsafe_ch_list *unsafe_chan_list,
1319 		struct ch_avoid_ind_type *avoid_freq_list)
1320 {
1321 	uint16_t *local_unsafe_list;
1322 	uint16_t local_unsafe_list_count;
1323 	uint32_t restriction_mask;
1324 	uint8_t i;
1325 
1326 	/* Basic sanity */
1327 	if (!hdd_ctxt) {
1328 		hdd_err("Invalid arguments");
1329 		return;
1330 	}
1331 
1332 	mutex_lock(&hdd_ctxt->avoid_freq_lock);
1333 	qdf_mem_copy(&hdd_ctxt->coex_avoid_freq_list, avoid_freq_list,
1334 			sizeof(struct ch_avoid_ind_type));
1335 	mutex_unlock(&hdd_ctxt->avoid_freq_lock);
1336 
1337 	restriction_mask = wlan_hdd_get_restriction_mask(hdd_ctxt);
1338 	if (hdd_clone_local_unsafe_chan(hdd_ctxt,
1339 					&local_unsafe_list,
1340 					&local_unsafe_list_count) != 0) {
1341 		hdd_err("failed to clone cur unsafe chan list");
1342 		return;
1343 	}
1344 
1345 	/* clear existing unsafe channel cache */
1346 	hdd_ctxt->unsafe_channel_count = 0;
1347 	qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
1348 					sizeof(hdd_ctxt->unsafe_channel_list));
1349 
1350 	hdd_ctxt->unsafe_channel_count = unsafe_chan_list->chan_cnt;
1351 
1352 	wlan_hdd_set_restriction_mask(hdd_ctxt);
1353 
1354 	for (i = 0; i < unsafe_chan_list->chan_cnt; i++) {
1355 		hdd_ctxt->unsafe_channel_list[i] =
1356 				unsafe_chan_list->chan_freq_list[i];
1357 	}
1358 	hdd_debug("number of unsafe channels is %d ",
1359 	       hdd_ctxt->unsafe_channel_count);
1360 
1361 	if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
1362 					hdd_ctxt->unsafe_channel_list,
1363 				hdd_ctxt->unsafe_channel_count)) {
1364 		hdd_err("Failed to set unsafe channel");
1365 
1366 		/* clear existing unsafe channel cache */
1367 		hdd_ctxt->unsafe_channel_count = 0;
1368 		qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
1369 			sizeof(hdd_ctxt->unsafe_channel_list));
1370 		qdf_mem_free(local_unsafe_list);
1371 		return;
1372 	}
1373 
1374 	mutex_lock(&hdd_ctxt->avoid_freq_lock);
1375 	if (hdd_ctxt->dnbs_avoid_freq_list.ch_avoid_range_cnt)
1376 		if (wlan_hdd_merge_avoid_freqs(avoid_freq_list,
1377 					&hdd_ctxt->dnbs_avoid_freq_list)) {
1378 			mutex_unlock(&hdd_ctxt->avoid_freq_lock);
1379 			hdd_debug("unable to merge avoid freqs");
1380 			qdf_mem_free(local_unsafe_list);
1381 			return;
1382 	}
1383 	mutex_unlock(&hdd_ctxt->avoid_freq_lock);
1384 	/*
1385 	 * first update the unsafe channel list to the platform driver and
1386 	 * send the avoid freq event to the application
1387 	 */
1388 	wlan_hdd_send_avoid_freq_event(hdd_ctxt, avoid_freq_list);
1389 
1390 	if (!hdd_ctxt->unsafe_channel_count) {
1391 		hdd_debug("no unsafe channels - not restarting SAP");
1392 		qdf_mem_free(local_unsafe_list);
1393 		return;
1394 	}
1395 	if (hdd_local_unsafe_channel_updated(hdd_ctxt,
1396 					    local_unsafe_list,
1397 					    local_unsafe_list_count,
1398 					    restriction_mask))
1399 		hdd_unsafe_channel_restart_sap(hdd_ctxt);
1400 	qdf_mem_free(local_unsafe_list);
1401 
1402 }
1403 #endif
1404 
1405 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
1406 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
map_nl_reg_rule_flags(uint16_t drv_reg_rule_flag,uint32_t * regd_rule_flag)1407 static void map_nl_reg_rule_flags(uint16_t drv_reg_rule_flag,
1408 				  uint32_t *regd_rule_flag)
1409 {
1410 	if (drv_reg_rule_flag & REGULATORY_CHAN_NO_IR)
1411 		*regd_rule_flag |= NL80211_RRF_NO_IR;
1412 	if (drv_reg_rule_flag & REGULATORY_CHAN_RADAR)
1413 		*regd_rule_flag |= NL80211_RRF_DFS;
1414 	if (drv_reg_rule_flag & REGULATORY_CHAN_INDOOR_ONLY)
1415 		*regd_rule_flag |= NL80211_RRF_NO_OUTDOOR;
1416 	if (drv_reg_rule_flag & REGULATORY_CHAN_NO_OFDM)
1417 		*regd_rule_flag |= NL80211_RRF_NO_OFDM;
1418 	*regd_rule_flag |= NL80211_RRF_AUTO_BW;
1419 }
1420 
1421 /**
1422  * dfs_reg_to_nl80211_dfs_regions() - convert dfs_reg to nl80211_dfs_regions
1423  * @dfs_region: DFS region
1424  *
1425  * Return: nl80211_dfs_regions
1426  */
dfs_reg_to_nl80211_dfs_regions(enum dfs_reg dfs_region)1427 static enum nl80211_dfs_regions dfs_reg_to_nl80211_dfs_regions(
1428 					enum dfs_reg dfs_region)
1429 {
1430 	switch (dfs_region) {
1431 	case DFS_UNINIT_REGION:
1432 		return NL80211_DFS_UNSET;
1433 	case DFS_FCC_REGION:
1434 		return NL80211_DFS_FCC;
1435 	case DFS_ETSI_REGION:
1436 		return NL80211_DFS_ETSI;
1437 	case DFS_MKK_REGION:
1438 		return NL80211_DFS_JP;
1439 	default:
1440 		return NL80211_DFS_UNSET;
1441 	}
1442 }
1443 
1444 /**
1445  * hdd_set_dfs_pri_multiplier() - Set dfs_pri_multiplier for ETSI region
1446  * @hdd_ctx: HDD context
1447  * @dfs_region: DFS region
1448  *
1449  * Return: none
1450  */
1451 #ifdef DFS_PRI_MULTIPLIER
hdd_set_dfs_pri_multiplier(struct hdd_context * hdd_ctx,enum dfs_reg dfs_region)1452 static void hdd_set_dfs_pri_multiplier(struct hdd_context *hdd_ctx,
1453 				       enum dfs_reg dfs_region)
1454 {
1455 	if (dfs_region == DFS_ETSI_REGION)
1456 		wlan_sap_set_dfs_pri_multiplier(hdd_ctx->mac_handle);
1457 }
1458 #else
hdd_set_dfs_pri_multiplier(struct hdd_context * hdd_ctx,enum dfs_reg dfs_region)1459 static inline void hdd_set_dfs_pri_multiplier(struct hdd_context *hdd_ctx,
1460 					      enum dfs_reg dfs_region)
1461 {
1462 }
1463 #endif
1464 
hdd_send_wiphy_regd_sync_event(struct hdd_context * hdd_ctx)1465 void hdd_send_wiphy_regd_sync_event(struct hdd_context *hdd_ctx)
1466 {
1467 	struct ieee80211_regdomain *regd;
1468 	struct ieee80211_reg_rule *regd_rules;
1469 	struct reg_rule_info reg_rules_struct;
1470 	struct reg_rule_info *reg_rules;
1471 	QDF_STATUS  status;
1472 	uint8_t i;
1473 
1474 	if (!hdd_ctx) {
1475 		hdd_err("hdd_ctx is NULL");
1476 		return;
1477 	}
1478 
1479 	status = ucfg_reg_get_regd_rules(hdd_ctx->pdev, &reg_rules_struct);
1480 	if (QDF_IS_STATUS_ERROR(status)) {
1481 		hdd_err("could not get reg rules");
1482 		return;
1483 	}
1484 
1485 	reg_rules = &reg_rules_struct;
1486 	if (!reg_rules->num_of_reg_rules) {
1487 		hdd_err("no reg rules %d", reg_rules->num_of_reg_rules);
1488 		return;
1489 	}
1490 
1491 	regd = qdf_mem_malloc((reg_rules->num_of_reg_rules *
1492 				sizeof(*regd_rules) + sizeof(*regd)));
1493 	if (!regd)
1494 		return;
1495 
1496 	regd->n_reg_rules = reg_rules->num_of_reg_rules;
1497 	qdf_mem_copy(regd->alpha2, reg_rules->alpha2, REG_ALPHA2_LEN + 1);
1498 	regd->dfs_region =
1499 		dfs_reg_to_nl80211_dfs_regions(reg_rules->dfs_region);
1500 
1501 	hdd_set_dfs_pri_multiplier(hdd_ctx, reg_rules->dfs_region);
1502 
1503 	regd_rules = regd->reg_rules;
1504 	hdd_debug("Regulatory Domain %s", regd->alpha2);
1505 	hdd_debug("start freq\tend freq\t@ max_bw\tant_gain\tpwr\tflags");
1506 	for (i = 0; i < reg_rules->num_of_reg_rules; i++) {
1507 		regd_rules[i].freq_range.start_freq_khz =
1508 			reg_rules->reg_rules[i].start_freq * 1000;
1509 		regd_rules[i].freq_range.end_freq_khz =
1510 			reg_rules->reg_rules[i].end_freq * 1000;
1511 		regd_rules[i].freq_range.max_bandwidth_khz =
1512 			reg_rules->reg_rules[i].max_bw * 1000;
1513 		regd_rules[i].power_rule.max_antenna_gain =
1514 			reg_rules->reg_rules[i].ant_gain * 100;
1515 		regd_rules[i].power_rule.max_eirp =
1516 			reg_rules->reg_rules[i].reg_power * 100;
1517 		map_nl_reg_rule_flags(reg_rules->reg_rules[i].flags,
1518 				      &regd_rules[i].flags);
1519 		hdd_debug("%d KHz\t%d KHz\t@ %d KHz\t%d\t\t%d\t%d",
1520 			  regd_rules[i].freq_range.start_freq_khz,
1521 			  regd_rules[i].freq_range.end_freq_khz,
1522 			  regd_rules[i].freq_range.max_bandwidth_khz,
1523 			  regd_rules[i].power_rule.max_antenna_gain,
1524 			  regd_rules[i].power_rule.max_eirp,
1525 			  regd_rules[i].flags);
1526 	}
1527 
1528 	regulatory_set_wiphy_regd(hdd_ctx->wiphy, regd);
1529 
1530 	hdd_debug("regd sync event sent with reg rules info");
1531 	qdf_mem_free(regd);
1532 }
1533 #endif
1534 
1535 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
1536 	(KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
1537 static void
fill_wiphy_6ghz_band_channels(struct wiphy * wiphy,struct regulatory_channel * chan_list)1538 fill_wiphy_6ghz_band_channels(struct wiphy *wiphy,
1539 			      struct regulatory_channel *chan_list)
1540 {
1541 	fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_6GHZ);
1542 }
1543 #else
1544 static void
fill_wiphy_6ghz_band_channels(struct wiphy * wiphy,struct regulatory_channel * chan_list)1545 fill_wiphy_6ghz_band_channels(struct wiphy *wiphy,
1546 			      struct regulatory_channel *chan_list)
1547 {
1548 }
1549 #endif
1550 
1551 #define HDD_MAX_CHAN_INFO_LOG 192
1552 
1553 /**
1554  * hdd_regulatory_chanlist_dump() - Dump regulatory channel list info
1555  * @chan_list: regulatory channel list
1556  *
1557  * Return: void
1558  */
hdd_regulatory_chanlist_dump(struct regulatory_channel * chan_list)1559 static void hdd_regulatory_chanlist_dump(struct regulatory_channel *chan_list)
1560 {
1561 	uint32_t i;
1562 	uint8_t info[HDD_MAX_CHAN_INFO_LOG];
1563 	int len = 0;
1564 	struct regulatory_channel *chan;
1565 	uint32_t count = 0;
1566 	int ret;
1567 
1568 	hdd_debug("start (freq MHz, tx power dBm):");
1569 	for (i = 0; i < NUM_CHANNELS; i++) {
1570 		chan = &chan_list[i];
1571 		if ((chan->chan_flags & REGULATORY_CHAN_DISABLED))
1572 			continue;
1573 		count++;
1574 		ret = scnprintf(info + len, sizeof(info) - len, "%d %d ",
1575 				chan->center_freq, chan->tx_power);
1576 		if (ret <= 0)
1577 			break;
1578 		len += ret;
1579 		if (len >= (sizeof(info) - 20)) {
1580 			hdd_debug("%s", info);
1581 			len = 0;
1582 		}
1583 	}
1584 	if (len > 0)
1585 		hdd_debug("%s", info);
1586 	hdd_debug("end total_count %d", count);
1587 }
1588 
1589 #ifdef FEATURE_WLAN_CH_AVOID_EXT
1590 /**
1591  * hdd_country_change_bw_check() - Check if bandwidth changed
1592  * @link_info: Link info pointer in HDD adapter
1593  * @oper_freq: current frequency of adapter
1594  *
1595  * Return: true if bandwidth changed otherwise false.
1596  */
hdd_country_change_bw_check(struct wlan_hdd_link_info * link_info,qdf_freq_t oper_freq)1597 static bool hdd_country_change_bw_check(struct wlan_hdd_link_info *link_info,
1598 					qdf_freq_t oper_freq)
1599 {
1600 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1601 	bool width_changed = false;
1602 	enum phy_ch_width width;
1603 	uint16_t org_bw = 0;
1604 	struct regulatory_channel *cur_chan_list = NULL;
1605 	int i;
1606 
1607 	cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * NUM_CHANNELS);
1608 	if (!cur_chan_list)
1609 		return false;
1610 
1611 	ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list);
1612 
1613 	width = hdd_get_link_info_width(link_info);
1614 	org_bw = wlan_reg_get_bw_value(width);
1615 
1616 	for (i = 0; i < NUM_CHANNELS; i++) {
1617 		if (cur_chan_list[i].state ==
1618 			CHANNEL_STATE_DISABLE)
1619 			continue;
1620 
1621 		if (cur_chan_list[i].center_freq == oper_freq &&
1622 		    org_bw > cur_chan_list[i].max_bw) {
1623 			width_changed = true;
1624 			break;
1625 		}
1626 	}
1627 	qdf_mem_free(cur_chan_list);
1628 	return width_changed;
1629 }
1630 #else
1631 static inline bool
hdd_country_change_bw_check(struct wlan_hdd_link_info * link_info,qdf_freq_t oper_freq)1632 hdd_country_change_bw_check(struct wlan_hdd_link_info *link_info,
1633 			    qdf_freq_t oper_freq)
1634 {
1635 	return false;
1636 }
1637 #endif
1638 
1639 /**
1640  * hdd_country_change_update_sta() - handle country code change for STA
1641  * @hdd_ctx: Global HDD context
1642  *
1643  * This function handles the stop/start/restart of STA/P2P_CLI adapters when
1644  * the country code changes
1645  *
1646  * Return: none
1647  */
hdd_country_change_update_sta(struct hdd_context * hdd_ctx)1648 static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
1649 {
1650 	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
1651 	struct hdd_station_ctx *sta_ctx = NULL;
1652 	struct wlan_objmgr_pdev *pdev = NULL;
1653 	uint32_t new_phy_mode;
1654 	bool freq_changed, phy_changed, width_changed;
1655 	qdf_freq_t oper_freq;
1656 	eCsrPhyMode csr_phy_mode;
1657 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_STA;
1658 	struct wlan_hdd_link_info *link_info;
1659 	enum qca_wlan_vendor_phy_mode vendor_phy_mode =
1660 						QCA_WLAN_VENDOR_PHY_MODE_AUTO;
1661 
1662 	pdev = hdd_ctx->pdev;
1663 
1664 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1665 					   dbgid) {
1666 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
1667 			width_changed = false;
1668 			oper_freq = hdd_get_link_info_home_channel(link_info);
1669 			if (oper_freq)
1670 				freq_changed = wlan_reg_is_disable_for_pwrmode(
1671 							pdev, oper_freq,
1672 							REG_CURRENT_PWR_MODE);
1673 			else
1674 				freq_changed = false;
1675 
1676 			switch (adapter->device_mode) {
1677 			case QDF_P2P_CLIENT_MODE:
1678 				/*
1679 				 * P2P client is the same as STA
1680 				 * continue to next statement
1681 				 */
1682 			case QDF_STA_MODE:
1683 				sta_ctx =
1684 					WLAN_HDD_GET_STATION_CTX_PTR(link_info);
1685 				new_phy_mode = wlan_reg_get_max_phymode(pdev,
1686 								REG_PHYMODE_MAX,
1687 								oper_freq);
1688 				csr_phy_mode =
1689 					csr_convert_from_reg_phy_mode(new_phy_mode);
1690 				phy_changed =
1691 					(sta_ctx->reg_phymode != csr_phy_mode);
1692 
1693 				width_changed =
1694 					hdd_country_change_bw_check(link_info,
1695 								    oper_freq);
1696 
1697 				if (!hdd_is_vdev_in_conn_state(link_info)) {
1698 					hdd_set_vdev_phy_mode(adapter,
1699 							      vendor_phy_mode);
1700 					continue;
1701 				}
1702 
1703 				if (phy_changed || freq_changed ||
1704 				    width_changed) {
1705 					hdd_debug("changed: phy %d, freq %d, width %d",
1706 						  phy_changed, freq_changed,
1707 						  width_changed);
1708 					wlan_hdd_cm_issue_disconnect(
1709 							link_info,
1710 							REASON_UNSPEC_FAILURE,
1711 							false);
1712 					hdd_set_vdev_phy_mode(adapter,
1713 							      vendor_phy_mode);
1714 					sta_ctx->reg_phymode = csr_phy_mode;
1715 				} else {
1716 					hdd_debug("Remain on current channel but update tx power");
1717 					wlan_reg_update_tx_power_on_ctry_change(
1718 							    pdev,
1719 							    link_info->vdev_id);
1720 				}
1721 				sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
1722 							  link_info->vdev_id,
1723 							  QDF_STA_MODE);
1724 				break;
1725 			default:
1726 				break;
1727 			}
1728 		}
1729 		/* dev_put has to be done here */
1730 		hdd_adapter_dev_put_debug(adapter, dbgid);
1731 	}
1732 }
1733 
1734 /**
1735  * hdd_restart_sap_with_new_phymode() - restart the SAP with the new phymode
1736  * @link_info: Link info pointer in HDD adapter.
1737  * @sap_config: sap configuration pointer
1738  * @csr_phy_mode: phymode to restart SAP with
1739  *
1740  * This function handles the stop/start/restart of SAP/P2P_GO adapters when the
1741  * country code changes
1742  *
1743  * Return: none
1744  */
1745 static void
hdd_restart_sap_with_new_phymode(struct wlan_hdd_link_info * link_info,struct sap_config * sap_config,eCsrPhyMode csr_phy_mode)1746 hdd_restart_sap_with_new_phymode(struct wlan_hdd_link_info *link_info,
1747 				 struct sap_config *sap_config,
1748 				 eCsrPhyMode csr_phy_mode)
1749 {
1750 	struct hdd_adapter *adapter = link_info->adapter;
1751 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
1752 	struct hdd_hostapd_state *hostapd_state = NULL;
1753 	struct sap_context *sap_ctx = NULL;
1754 	QDF_STATUS status;
1755 
1756 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
1757 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
1758 
1759 	if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
1760 		sap_config->sap_orig_hw_mode = sap_config->SapHw_mode;
1761 		sap_config->SapHw_mode = csr_phy_mode;
1762 		hdd_err("Can't restart AP because it is not started");
1763 		return;
1764 	}
1765 
1766 	qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
1767 	status = wlansap_stop_bss(sap_ctx);
1768 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1769 		hdd_err("SAP Stop Bss fail");
1770 		return;
1771 	}
1772 	status = qdf_wait_single_event(&hostapd_state->qdf_stop_bss_event,
1773 				       SME_CMD_STOP_BSS_TIMEOUT);
1774 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1775 		hdd_err("SAP Stop timeout");
1776 		return;
1777 	}
1778 
1779 	sap_config->chan_freq =
1780 		wlansap_get_safe_channel_from_pcl_and_acs_range(sap_ctx, NULL);
1781 
1782 	sap_config->sap_orig_hw_mode = sap_config->SapHw_mode;
1783 	sap_config->SapHw_mode = csr_phy_mode;
1784 
1785 	mutex_lock(&hdd_ctx->sap_lock);
1786 	qdf_event_reset(&hostapd_state->qdf_event);
1787 	status = wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
1788 				   sap_config, adapter->dev);
1789 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1790 		mutex_unlock(&hdd_ctx->sap_lock);
1791 		hdd_err("SAP Start Bss fail");
1792 		return;
1793 	}
1794 	status = qdf_wait_single_event(&hostapd_state->qdf_event,
1795 				       SME_CMD_START_BSS_TIMEOUT);
1796 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1797 		mutex_unlock(&hdd_ctx->sap_lock);
1798 		hdd_err("SAP Start timeout");
1799 		return;
1800 	}
1801 	mutex_unlock(&hdd_ctx->sap_lock);
1802 }
1803 
1804 /**
1805  * hdd_country_change_update_sap() - handle country code change for SAP
1806  * @hdd_ctx: Global HDD context
1807  *
1808  * This function handles the stop/start/restart of SAP/P2P_GO adapters when the
1809  * country code changes
1810  *
1811  * Return: none
1812  */
hdd_country_change_update_sap(struct hdd_context * hdd_ctx)1813 static void hdd_country_change_update_sap(struct hdd_context *hdd_ctx)
1814 {
1815 	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
1816 	struct sap_config *sap_config = NULL;
1817 	struct wlan_objmgr_pdev *pdev = NULL;
1818 	uint32_t reg_phy_mode, new_phy_mode;
1819 	bool phy_changed;
1820 	qdf_freq_t oper_freq;
1821 	eCsrPhyMode csr_phy_mode;
1822 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP;
1823 	struct wlan_hdd_link_info *link_info;
1824 
1825 	pdev = hdd_ctx->pdev;
1826 
1827 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
1828 					   dbgid) {
1829 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
1830 			oper_freq = hdd_get_link_info_home_channel(link_info);
1831 
1832 			switch (adapter->device_mode) {
1833 			case QDF_P2P_GO_MODE:
1834 				policy_mgr_check_sap_restart(hdd_ctx->psoc,
1835 							     link_info->vdev_id);
1836 				break;
1837 			case QDF_SAP_MODE:
1838 				if (!test_bit(SOFTAP_INIT_DONE,
1839 					      &link_info->link_flags)) {
1840 					hdd_info("AP is not started yet");
1841 					break;
1842 				}
1843 				sap_config = &link_info->session.ap.sap_config;
1844 				reg_phy_mode = csr_convert_to_reg_phy_mode(
1845 						    sap_config->sap_orig_hw_mode,
1846 						    oper_freq);
1847 				new_phy_mode = wlan_reg_get_max_phymode(pdev,
1848 								reg_phy_mode,
1849 								oper_freq);
1850 				csr_phy_mode =
1851 					csr_convert_from_reg_phy_mode(new_phy_mode);
1852 				phy_changed =
1853 					(csr_phy_mode != sap_config->SapHw_mode);
1854 
1855 				if (phy_changed)
1856 					hdd_restart_sap_with_new_phymode(link_info,
1857 									 sap_config,
1858 									 csr_phy_mode);
1859 				else
1860 					policy_mgr_check_sap_restart(
1861 							hdd_ctx->psoc,
1862 							link_info->vdev_id);
1863 				hdd_debug("Update tx power due to ctry change");
1864 				wlan_reg_update_tx_power_on_ctry_change(
1865 						    pdev, link_info->vdev_id);
1866 				break;
1867 			default:
1868 				break;
1869 			}
1870 		}
1871 		/* dev_put has to be done here */
1872 		hdd_adapter_dev_put_debug(adapter, dbgid);
1873 	}
1874 }
1875 
__hdd_country_change_work_handle(struct hdd_context * hdd_ctx)1876 static void __hdd_country_change_work_handle(struct hdd_context *hdd_ctx)
1877 {
1878 	/*
1879 	 * Loop over STAs first since it may lead to different channel
1880 	 * selection for SAPs
1881 	 */
1882 	hdd_country_change_update_sta(hdd_ctx);
1883 	sme_generic_change_country_code(hdd_ctx->mac_handle,
1884 					hdd_ctx->reg.alpha2);
1885 
1886 	qdf_event_set_all(&hdd_ctx->regulatory_update_event);
1887 	qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
1888 	hdd_ctx->is_regulatory_update_in_progress = false;
1889 	qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
1890 
1891 	hdd_country_change_update_sap(hdd_ctx);
1892 }
1893 
1894 /**
1895  * hdd_handle_country_change_work_error() - handle country code change error
1896  * @hdd_ctx: Global HDD context
1897  * @errno: country code change error number
1898  *
1899  * This function handles error code in country code change worker
1900  *
1901  * Return: none
1902  */
hdd_handle_country_change_work_error(struct hdd_context * hdd_ctx,int errno)1903 static void hdd_handle_country_change_work_error(struct hdd_context *hdd_ctx,
1904 						 int errno)
1905 {
1906 	if (errno == -EAGAIN) {
1907 		qdf_sleep(COUNTRY_CHANGE_WORK_RESCHED_WAIT_TIME);
1908 		hdd_debug("rescheduling country change work");
1909 		qdf_sched_work(0, &hdd_ctx->country_change_work);
1910 	} else {
1911 		hdd_err("can not handle country change %d", errno);
1912 		qdf_event_set_all(&hdd_ctx->regulatory_update_event);
1913 		qdf_mutex_acquire(&hdd_ctx->regulatory_status_lock);
1914 		hdd_ctx->is_regulatory_update_in_progress = false;
1915 		qdf_mutex_release(&hdd_ctx->regulatory_status_lock);
1916 	}
1917 }
1918 
1919 /**
1920  * hdd_country_change_work_handle() - handle country code change
1921  * @arg: Global HDD context
1922  *
1923  * This function handles the stop/start/restart of all adapters when the
1924  * country code changes
1925  *
1926  * Return: none
1927  */
hdd_country_change_work_handle(void * arg)1928 static void hdd_country_change_work_handle(void *arg)
1929 {
1930 	struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
1931 	struct osif_psoc_sync *psoc_sync;
1932 	int errno;
1933 
1934 	errno = wlan_hdd_validate_context(hdd_ctx);
1935 	if (errno)
1936 		return hdd_handle_country_change_work_error(hdd_ctx, errno);
1937 
1938 	errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
1939 	if (errno)
1940 		return hdd_handle_country_change_work_error(hdd_ctx, errno);
1941 
1942 	if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED)
1943 		hdd_err("Driver disabled, ignore country code change");
1944 	else
1945 		__hdd_country_change_work_handle(hdd_ctx);
1946 
1947 	osif_psoc_sync_op_stop(psoc_sync);
1948 }
1949 
hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,struct regulatory_channel * chan_list,struct avoid_freq_ind_data * avoid_freq_ind,void * arg)1950 static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc,
1951 				   struct wlan_objmgr_pdev *pdev,
1952 				   struct regulatory_channel *chan_list,
1953 				   struct avoid_freq_ind_data *avoid_freq_ind,
1954 				   void *arg)
1955 {
1956 	struct wiphy *wiphy;
1957 	struct pdev_osif_priv *pdev_priv;
1958 	struct hdd_context *hdd_ctx;
1959 	enum country_src cc_src;
1960 	uint8_t alpha2[REG_ALPHA2_LEN + 1];
1961 	bool nb_flag;
1962 	bool reg_flag;
1963 
1964 	pdev_priv = wlan_pdev_get_ospriv(pdev);
1965 	wiphy = pdev_priv->wiphy;
1966 	hdd_ctx = wiphy_priv(wiphy);
1967 
1968 	nb_flag = ucfg_mlme_get_coex_unsafe_chan_nb_user_prefer_for_sap(
1969 								hdd_ctx->psoc);
1970 	reg_flag = ucfg_mlme_get_coex_unsafe_chan_reg_disable(hdd_ctx->psoc);
1971 
1972 	if (avoid_freq_ind && nb_flag && reg_flag)
1973 		goto sync_chanlist;
1974 
1975 	if (avoid_freq_ind) {
1976 		hdd_ch_avoid_ind(hdd_ctx, &avoid_freq_ind->chan_list,
1977 				 &avoid_freq_ind->freq_list);
1978 		return;
1979 	}
1980 
1981 sync_chanlist:
1982 
1983 	hdd_debug("process channel list update from regulatory");
1984 	hdd_regulatory_chanlist_dump(chan_list);
1985 
1986 	fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_2GHZ);
1987 	fill_wiphy_band_channels(wiphy, chan_list, NL80211_BAND_5GHZ);
1988 	fill_wiphy_6ghz_band_channels(wiphy, chan_list);
1989 	cc_src = ucfg_reg_get_cc_and_src(hdd_ctx->psoc, alpha2);
1990 	qdf_mem_copy(hdd_ctx->reg.alpha2, alpha2, REG_ALPHA2_LEN + 1);
1991 
1992 	/* Check the kernel version for upstream commit aced43ce780dc5 that
1993 	 * has support for processing user cell_base hints when wiphy is
1994 	 * self managed or check the backport flag for the same.
1995 	 */
1996 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
1997 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
1998 	if (wiphy->registered)
1999 		hdd_send_wiphy_regd_sync_event(hdd_ctx);
2000 #endif
2001 
2002 	hdd_config_tdls_with_band_switch(hdd_ctx);
2003 	qdf_sched_work(0, &hdd_ctx->country_change_work);
2004 }
2005 
hdd_update_regulatory_config(struct hdd_context * hdd_ctx)2006 int hdd_update_regulatory_config(struct hdd_context *hdd_ctx)
2007 {
2008 	struct reg_config_vars config_vars;
2009 
2010 	reg_program_config_vars(hdd_ctx, &config_vars);
2011 	ucfg_reg_set_config_vars(hdd_ctx->psoc, config_vars);
2012 	return 0;
2013 }
2014 
hdd_init_regulatory_update_event(struct hdd_context * hdd_ctx)2015 int hdd_init_regulatory_update_event(struct hdd_context *hdd_ctx)
2016 {
2017 	QDF_STATUS status;
2018 
2019 	status = qdf_event_create(&hdd_ctx->regulatory_update_event);
2020 	if (QDF_IS_STATUS_ERROR(status)) {
2021 		hdd_err("Failed to create regulatory update event");
2022 		goto failure;
2023 	}
2024 	status = qdf_mutex_create(&hdd_ctx->regulatory_status_lock);
2025 	if (QDF_IS_STATUS_ERROR(status)) {
2026 		hdd_err("Failed to create regulatory status mutex");
2027 		goto failure;
2028 	}
2029 	hdd_ctx->is_regulatory_update_in_progress = false;
2030 
2031 failure:
2032 	return qdf_status_to_os_return(status);
2033 }
2034 
hdd_regulatory_init(struct hdd_context * hdd_ctx,struct wiphy * wiphy)2035 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy)
2036 {
2037 	bool offload_enabled;
2038 	struct regulatory_channel *cur_chan_list;
2039 	int ret;
2040 
2041 	cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * NUM_CHANNELS);
2042 	if (!cur_chan_list) {
2043 		return -ENOMEM;
2044 	}
2045 
2046 	qdf_create_work(0, &hdd_ctx->country_change_work,
2047 			hdd_country_change_work_handle, hdd_ctx);
2048 	ucfg_reg_register_chan_change_callback(hdd_ctx->psoc,
2049 					       hdd_regulatory_dyn_cbk,
2050 					       NULL);
2051 
2052 	ret = hdd_update_country_code(hdd_ctx);
2053 	if (ret) {
2054 		hdd_err("Failed to update country code; errno:%d", ret);
2055 		return -EINVAL;
2056 	}
2057 
2058 	wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
2059 	/* Check the kernel version for upstream commit aced43ce780dc5 that
2060 	 * has support for processing user cell_base hints when wiphy is
2061 	 * self managed or check the backport flag for the same.
2062 	 */
2063 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
2064 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
2065 	wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
2066 #endif
2067 	wiphy->reg_notifier = hdd_reg_notifier;
2068 	offload_enabled = ucfg_reg_is_regdb_offloaded(hdd_ctx->psoc);
2069 	hdd_debug("regulatory offload_enabled %d", offload_enabled);
2070 	if (offload_enabled)
2071 		hdd_ctx->reg_offload = true;
2072 	else
2073 		hdd_ctx->reg_offload = false;
2074 
2075 	ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list);
2076 	hdd_regulatory_chanlist_dump(cur_chan_list);
2077 	fill_wiphy_band_channels(wiphy, cur_chan_list, NL80211_BAND_2GHZ);
2078 	fill_wiphy_band_channels(wiphy, cur_chan_list, NL80211_BAND_5GHZ);
2079 	fill_wiphy_6ghz_band_channels(wiphy, cur_chan_list);
2080 	qdf_mem_zero(hdd_ctx->reg.alpha2, REG_ALPHA2_LEN + 1);
2081 
2082 	qdf_mem_free(cur_chan_list);
2083 	return 0;
2084 }
2085 
2086 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
hdd_regulatory_init(struct hdd_context * hdd_ctx,struct wiphy * wiphy)2087 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy)
2088 {
2089 	hdd_ctx->reg_offload = false;
2090 	wiphy->reg_notifier = hdd_reg_notifier;
2091 	wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
2092 	wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
2093 	hdd_regulatory_init_no_offload(hdd_ctx, wiphy);
2094 
2095 	return 0;
2096 }
2097 
2098 #else
hdd_regulatory_init(struct hdd_context * hdd_ctx,struct wiphy * wiphy)2099 int hdd_regulatory_init(struct hdd_context *hdd_ctx, struct wiphy *wiphy)
2100 {
2101 	hdd_ctx->reg_offload = false;
2102 	wiphy->reg_notifier = hdd_reg_notifier;
2103 	wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
2104 	wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
2105 	hdd_regulatory_init_no_offload(hdd_ctx, wiphy);
2106 
2107 	return 0;
2108 }
2109 #endif
2110 
hdd_deinit_regulatory_update_event(struct hdd_context * hdd_ctx)2111 void hdd_deinit_regulatory_update_event(struct hdd_context *hdd_ctx)
2112 {
2113 	QDF_STATUS status;
2114 
2115 	status = qdf_event_destroy(&hdd_ctx->regulatory_update_event);
2116 	if (QDF_IS_STATUS_ERROR(status))
2117 		hdd_err("Failed to destroy regulatory update event");
2118 	status = qdf_mutex_destroy(&hdd_ctx->regulatory_status_lock);
2119 	if (QDF_IS_STATUS_ERROR(status))
2120 		hdd_err("Failed to destroy regulatory status mutex");
2121 }
2122 
hdd_regulatory_deinit(struct hdd_context * hdd_ctx)2123 void hdd_regulatory_deinit(struct hdd_context *hdd_ctx)
2124 {
2125 	qdf_flush_work(&hdd_ctx->country_change_work);
2126 	qdf_destroy_work(0, &hdd_ctx->country_change_work);
2127 }
2128 
hdd_update_regdb_offload_config(struct hdd_context * hdd_ctx)2129 void hdd_update_regdb_offload_config(struct hdd_context *hdd_ctx)
2130 {
2131 	bool ignore_fw_reg_offload_ind = false;
2132 
2133 	ucfg_mlme_get_ignore_fw_reg_offload_ind(hdd_ctx->psoc,
2134 						&ignore_fw_reg_offload_ind);
2135 	if (!ignore_fw_reg_offload_ind) {
2136 		hdd_debug("regdb offload is based on firmware capability");
2137 		return;
2138 	}
2139 
2140 	hdd_debug("Ignore regdb offload Indication from FW");
2141 	ucfg_set_ignore_fw_reg_offload_ind(hdd_ctx->psoc);
2142 }
2143