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; #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)) u32 bandwidth = 0; int r; #endif 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) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) reg_rule = freq_reg_info(wiphy, ch->center_freq); if (IS_ERR(reg_rule)) continue; #else r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (r) continue; #endif /* *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_IBSS)) ch->flags &= ~IEEE80211_CHAN_NO_IBSS; if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } else { if (ch->beacon_found) ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN); } } } }
/* Allows active scan scan on Ch 12 and 13 */ static void ath_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; u32 bandwidth = 0; int r; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; #if 0 // by bbelief if (!sband) return; #endif /* * 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_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; ch = &sband->channels[12]; /* CH 13 */ if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; 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 */ r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } ch = &sband->channels[12]; /* CH 13 */ r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } }
/* 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_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; u32 bandwidth = 0; int r; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; if (!sband) return; if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; ch = &sband->channels[12]; if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; return; } ch = &sband->channels[11]; r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } ch = &sband->channels[12]; r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } }
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 ath_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; u32 bandwidth = 0; int r; 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 (ath_is_radar_freq(ch->center_freq) || (ch->flags & IEEE80211_CHAN_RADAR)) continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (r) continue; if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) ch->flags &= ~IEEE80211_CHAN_NO_IBSS; if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } else { if (ch->beacon_found) ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN); } } } }
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; } } } }
/* 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 (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)) u32 bandwidth = 0; int r; #endif 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_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; ch = &sband->channels[12]; /* CH 13 */ if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; return; } /* *If a country IE has been recieved 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 */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { #else r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { #endif if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } ch = &sband->channels[12]; /* CH 13 */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { #else r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { #endif if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } } /* *Always apply Radar/DFS rules on *freq range 5260 MHz - 5700 MHz */ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; unsigned int i; if (!wiphy->bands[IEEE80211_BAND_5GHZ]) return; sband = wiphy->bands[IEEE80211_BAND_5GHZ]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; if (!_rtl_is_radar_freq(ch->center_freq)) continue; /* *We always enable radar detection/DFS on this *frequency range. Additionally we also apply on *this frequency range: *- If STA mode does not yet have DFS supports disable * active scanning *- If adhoc mode does not support DFS yet then disable * adhoc in the frequency. *- If AP mode does not yet support radar detection/DFS *do not allow AP mode */ if (!(ch->flags & IEEE80211_CHAN_DISABLED)) ch->flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN; } } static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator, struct rtl_regulatory *reg) { _rtl_reg_apply_beaconing_flags(wiphy, initiator); _rtl_reg_apply_active_scan_flags(wiphy, initiator); return; }
/** * 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; }