Exemple #1
0
/* 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;
}
Exemple #3
0
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;
			}
		}
	}
}
Exemple #4
0
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 = &regd->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;
}
Exemple #5
0
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 = &regd->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;
}