/* Allows active scan scan on Ch 12 and 13 */ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; const struct ieee80211_reg_rule *reg_rule; if (!wiphy->bands[IEEE80211_BAND_2GHZ]) return; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; /* *If no country IE has been received always enable active scan *on these channels. This is only done for specific regulatory SKUs */ if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; /* CH 12 */ if (ch->flags & IEEE80211_CHAN_NO_IR) ch->flags &= ~IEEE80211_CHAN_NO_IR; ch = &sband->channels[12]; /* CH 13 */ if (ch->flags & IEEE80211_CHAN_NO_IR) ch->flags &= ~IEEE80211_CHAN_NO_IR; return; } /* *If a country IE has been received check its rule for this *channel first before enabling active scan. The passive scan *would have been enforced by the initial processing of our *custom regulatory domain. */ ch = &sband->channels[11]; /* CH 12 */ reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (!IS_ERR(reg_rule)) { if (!(reg_rule->flags & NL80211_RRF_NO_IR)) if (ch->flags & IEEE80211_CHAN_NO_IR) ch->flags &= ~IEEE80211_CHAN_NO_IR; } ch = &sband->channels[12]; /* CH 13 */ reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (!IS_ERR(reg_rule)) { if (!(reg_rule->flags & NL80211_RRF_NO_IR)) if (ch->flags & IEEE80211_CHAN_NO_IR) ch->flags &= ~IEEE80211_CHAN_NO_IR; } }
static void ath_force_clear_no_ir_chan(struct wiphy *wiphy, struct ieee80211_channel *ch) { const struct ieee80211_reg_rule *reg_rule; reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (IS_ERR(reg_rule)) return; if (!(reg_rule->flags & NL80211_RRF_NO_IR)) if (ch->flags & IEEE80211_CHAN_NO_IR) ch->flags &= ~IEEE80211_CHAN_NO_IR; }
static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { enum ieee80211_band band; struct ieee80211_supported_band *sband; const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *ch; unsigned int i; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!wiphy->bands[band]) continue; sband = wiphy->bands[band]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; if (_rtl_is_radar_freq(ch->center_freq) || (ch->flags & IEEE80211_CHAN_RADAR)) continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (IS_ERR(reg_rule)) continue; /* *If 11d had a rule for this channel ensure *we enable adhoc/beaconing if it allows us to *use it. Note that we would have disabled it *by applying our static world regdomain by *default during init, prior to calling our *regulatory_hint(). */ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) ch->flags &= ~IEEE80211_CHAN_NO_IR; } else { if (ch->beacon_found) ch->flags &= ~IEEE80211_CHAN_NO_IR; } } } }
struct ieee80211_regdomain * iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int num_of_ch, __le32 *channels, u16 fw_mcc) { int ch_idx; u16 ch_flags, prev_ch_flags = 0; const u8 *nvm_chan = cfg->device_family == IWL_DEVICE_FAMILY_8000 ? iwl_nvm_channels_family_8000 : iwl_nvm_channels; struct ieee80211_regdomain *regd; int size_of_regd; struct ieee80211_reg_rule *rule; enum nl80211_band band; int center_freq, prev_center_freq = 0; int valid_rules = 0; bool new_rule; int max_num_ch = cfg->device_family == IWL_DEVICE_FAMILY_8000 ? IWL_NUM_CHANNELS_FAMILY_8000 : IWL_NUM_CHANNELS; if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) return ERR_PTR(-EINVAL); if (WARN_ON(num_of_ch > max_num_ch)) num_of_ch = max_num_ch; IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n", num_of_ch); /* build a regdomain rule for every valid channel */ size_of_regd = sizeof(struct ieee80211_regdomain) + num_of_ch * sizeof(struct ieee80211_reg_rule); regd = kzalloc(size_of_regd, GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM); for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { ch_flags = (u16)__le32_to_cpup(channels + ch_idx); band = (ch_idx < NUM_2GHZ_CHANNELS) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; center_freq = ieee80211_channel_to_frequency(nvm_chan[ch_idx], band); new_rule = false; if (!(ch_flags & NVM_CHANNEL_VALID)) { IWL_DEBUG_DEV(dev, IWL_DL_LAR, "Ch. %d Flags %x [%sGHz] - No traffic\n", nvm_chan[ch_idx], ch_flags, (ch_idx >= NUM_2GHZ_CHANNELS) ? "5.2" : "2.4"); continue; } /* we can't continue the same rule */ if (ch_idx == 0 || prev_ch_flags != ch_flags || center_freq - prev_center_freq > 20) { valid_rules++; new_rule = true; } rule = ®d->reg_rules[valid_rules - 1]; if (new_rule) rule->freq_range.start_freq_khz = MHZ_TO_KHZ(center_freq - 10); rule->freq_range.end_freq_khz = MHZ_TO_KHZ(center_freq + 10); /* this doesn't matter - not used by FW */ rule->power_rule.max_antenna_gain = DBI_TO_MBI(6); rule->power_rule.max_eirp = DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER); rule->flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, ch_flags, cfg); /* rely on auto-calculation to merge BW of contiguous chans */ rule->flags |= NL80211_RRF_AUTO_BW; rule->freq_range.max_bandwidth_khz = 0; prev_ch_flags = ch_flags; prev_center_freq = center_freq; IWL_DEBUG_DEV(dev, IWL_DL_LAR, "Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s(0x%02x): Ad-Hoc %ssupported\n", center_freq, band == NL80211_BAND_5GHZ ? "5.2" : "2.4", CHECK_AND_PRINT_I(VALID), CHECK_AND_PRINT_I(ACTIVE), CHECK_AND_PRINT_I(RADAR), CHECK_AND_PRINT_I(WIDE), CHECK_AND_PRINT_I(40MHZ), CHECK_AND_PRINT_I(80MHZ), CHECK_AND_PRINT_I(160MHZ), CHECK_AND_PRINT_I(INDOOR_ONLY), CHECK_AND_PRINT_I(GO_CONCURRENT), ch_flags, ((ch_flags & NVM_CHANNEL_ACTIVE) && !(ch_flags & NVM_CHANNEL_RADAR)) ? "" : "not "); } regd->n_reg_rules = valid_rules; /* set alpha2 from FW. */ regd->alpha2[0] = fw_mcc >> 8; regd->alpha2[1] = fw_mcc & 0xff; return regd; }
static struct ieee80211_regdomain * mwifiex_create_custom_regdomain(struct mwifiex_private *priv, u8 *buf, u16 buf_len) { u16 num_chan = buf_len / 2; struct ieee80211_regdomain *regd; struct ieee80211_reg_rule *rule; bool new_rule; int regd_size, idx, freq, prev_freq = 0; u32 bw, prev_bw = 0; u8 chflags, prev_chflags = 0, valid_rules = 0; if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES)) return ERR_PTR(-EINVAL); regd_size = sizeof(struct ieee80211_regdomain) + num_chan * sizeof(struct ieee80211_reg_rule); regd = kzalloc(regd_size, GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM); for (idx = 0; idx < num_chan; idx++) { u8 chan; enum nl80211_band band; chan = *buf++; if (!chan) { kfree(regd); return NULL; } chflags = *buf++; band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; freq = ieee80211_channel_to_frequency(chan, band); new_rule = false; if (chflags & MWIFIEX_CHANNEL_DISABLED) continue; if (band == NL80211_BAND_5GHZ) { if (!(chflags & MWIFIEX_CHANNEL_NOHT80)) bw = MHZ_TO_KHZ(80); else if (!(chflags & MWIFIEX_CHANNEL_NOHT40)) bw = MHZ_TO_KHZ(40); else bw = MHZ_TO_KHZ(20); } else { if (!(chflags & MWIFIEX_CHANNEL_NOHT40)) bw = MHZ_TO_KHZ(40); else bw = MHZ_TO_KHZ(20); } if (idx == 0 || prev_chflags != chflags || prev_bw != bw || freq - prev_freq > 20) { valid_rules++; new_rule = true; } rule = ®d->reg_rules[valid_rules - 1]; rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10); prev_chflags = chflags; prev_freq = freq; prev_bw = bw; if (!new_rule) continue; rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10); rule->power_rule.max_eirp = DBM_TO_MBM(19); if (chflags & MWIFIEX_CHANNEL_PASSIVE) rule->flags = NL80211_RRF_NO_IR; if (chflags & MWIFIEX_CHANNEL_DFS) rule->flags = NL80211_RRF_DFS; rule->freq_range.max_bandwidth_khz = bw; } regd->n_reg_rules = valid_rules; regd->alpha2[0] = '9'; regd->alpha2[1] = '9'; return regd; }
/** * cds_process_regulatory_data() - process regulatory data * @wiphy: wiphy * @band_capability: band_capability * * Return: int */ static int cds_process_regulatory_data(struct wiphy *wiphy, uint8_t band_capability, bool reset) { int i, j, m; int k = 0, n = 0; hdd_context_t *hdd_ctx; const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *chan; sRegulatoryChannel *temp_chan_k; sRegulatoryChannel *temp_chan_n; sRegulatoryChannel *temp_chan; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (NULL == hdd_ctx) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "invalid hdd_ctx pointer"); return CDF_STATUS_E_FAULT; } hdd_ctx->isVHT80Allowed = 0; if (band_capability == eCSR_BAND_24) CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "band capability is set to 2G only"); for (i = 0, m = 0; i < IEEE80211_NUM_BANDS; i++) { if (i == IEEE80211_BAND_2GHZ && band_capability == eCSR_BAND_5G) continue; else if (i == IEEE80211_BAND_5GHZ && band_capability == eCSR_BAND_24) continue; if (wiphy->bands[i] == NULL) continue; if (i == 0) m = 0; else m = wiphy->bands[i-1]->n_channels + m; for (j = 0; j < wiphy->bands[i]->n_channels; j++) { k = m + j; n = cds_bw20_ch_index_to_bw40_ch_index(k); chan = &(wiphy->bands[i]->channels[j]); temp_chan_k = &(reg_table.regDomains[temp_reg_domain]. channels[k]); temp_chan_n = &(reg_table.regDomains[temp_reg_domain]. channels[n]); if ((!reset) && #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) { #else (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) { #endif reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan-> center_freq)); if (!IS_ERR(reg_rule)) { chan->flags &= ~IEEE80211_CHAN_DISABLED; if (!(reg_rule->flags & NL80211_RRF_DFS)) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Remove passive scan restriction for %u", __func__, chan->center_freq); chan->flags &= ~IEEE80211_CHAN_RADAR; } if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Remove passive scan restriction for %u", __func__, chan->center_freq); chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Remove no ibss restriction for %u", __func__, chan->center_freq); chan->flags &= ~IEEE80211_CHAN_NO_IBSS; } chan->max_power = MBM_TO_DBM(reg_rule-> power_rule. max_eirp); } } #ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS if (is_dsrc_channel(chan->center_freq)) { temp_chan_k->enabled = CHANNEL_STATE_ENABLE; temp_chan_k->pwrLimit = DEFAULT_11P_POWER; temp_chan_k->flags = chan->flags; } else #endif if (chan->flags & IEEE80211_CHAN_DISABLED) { temp_chan_k->enabled = CHANNEL_STATE_DISABLE; temp_chan_k->flags = chan->flags; if (n != -1) { temp_chan_n->enabled = CHANNEL_STATE_DISABLE; temp_chan_n->flags = chan->flags; } } else if (chan->flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) | IEEE80211_CHAN_INDOOR_ONLY #endif )) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) if (chan->flags & IEEE80211_CHAN_INDOOR_ONLY) chan->flags |= IEEE80211_CHAN_PASSIVE_SCAN; #endif temp_chan_k->enabled = CHANNEL_STATE_DFS; temp_chan_k->pwrLimit = chan->max_power; temp_chan_k->flags = chan->flags; if (n != -1) { if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) { temp_chan_n->enabled = CHANNEL_STATE_DISABLE; } else { temp_chan_n->enabled = CHANNEL_STATE_DFS; temp_chan_n->pwrLimit = chan->max_power-3; } temp_chan_n->flags = chan->flags; } if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) == 0) hdd_ctx->isVHT80Allowed = 1; } else { temp_chan_k->enabled = CHANNEL_STATE_ENABLE; temp_chan_k->pwrLimit = chan->max_power; temp_chan_k->flags = chan->flags; if (n != -1) { if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) { temp_chan_n->enabled = CHANNEL_STATE_DISABLE; } else { temp_chan_n->enabled = CHANNEL_STATE_ENABLE; temp_chan_n->pwrLimit = chan->max_power - 3; } temp_chan_n->flags = chan->flags; } if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) == 0) hdd_ctx->isVHT80Allowed = 1; } } } if (0 == (hdd_ctx->reg.eeprom_rd_ext & (1 << WHAL_REG_EXT_FCC_CH_144))) { temp_chan = &(reg_table.regDomains[temp_reg_domain]. channels[RF_CHAN_144]); temp_chan->enabled = CHANNEL_STATE_DISABLE; } if (k == 0) return -1; return 0; }