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, ¤t_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, ®_rules_struct);
1480 if (QDF_IS_STATUS_ERROR(status)) {
1481 hdd_err("could not get reg rules");
1482 return;
1483 }
1484
1485 reg_rules = ®_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 ®d_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