mirror of https://gitee.com/openkylin/linux.git
mwifiex: add custom regulatory domain support
This patch creates custom regulatory rules based on the information received from firmware and enable them during wiphy registration. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
41960b4dfd
commit
7253979910
|
@ -4141,9 +4141,12 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|||
wiphy->cipher_suites = mwifiex_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
|
||||
|
||||
if (adapter->region_code)
|
||||
wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
|
||||
if (adapter->regd) {
|
||||
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||
REGULATORY_DISABLE_BEACON_HINTS |
|
||||
REGULATORY_COUNTRY_IE_IGNORE;
|
||||
wiphy_apply_custom_regulatory(wiphy, adapter->regd);
|
||||
}
|
||||
|
||||
ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
|
@ -4209,19 +4212,27 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"driver hint alpha2: %2.2s\n", reg_alpha2);
|
||||
regulatory_hint(wiphy, reg_alpha2);
|
||||
} else {
|
||||
if (adapter->region_code == 0x00) {
|
||||
mwifiex_dbg(adapter, WARN, "Ignore world regulatory domain\n");
|
||||
if (!adapter->regd) {
|
||||
if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"driver hint alpha2: %2.2s\n", reg_alpha2);
|
||||
regulatory_hint(wiphy, reg_alpha2);
|
||||
} else {
|
||||
country_code =
|
||||
mwifiex_11d_code_2_region(adapter->region_code);
|
||||
if (country_code &&
|
||||
regulatory_hint(wiphy, country_code))
|
||||
mwifiex_dbg(priv->adapter, ERROR, "regulatory_hint() failed\n");
|
||||
if (adapter->region_code == 0x00) {
|
||||
mwifiex_dbg(adapter, WARN,
|
||||
"Ignore world regulatory domain\n");
|
||||
} else {
|
||||
wiphy->regulatory_flags |=
|
||||
REGULATORY_DISABLE_BEACON_HINTS |
|
||||
REGULATORY_COUNTRY_IE_IGNORE;
|
||||
country_code =
|
||||
mwifiex_11d_code_2_region(
|
||||
adapter->region_code);
|
||||
if (country_code &&
|
||||
regulatory_hint(wiphy, country_code))
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"regulatory_hint() failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -416,6 +416,14 @@ enum P2P_MODES {
|
|||
P2P_MODE_CLIENT = 3,
|
||||
};
|
||||
|
||||
enum mwifiex_channel_flags {
|
||||
MWIFIEX_CHANNEL_PASSIVE = BIT(0),
|
||||
MWIFIEX_CHANNEL_DFS = BIT(1),
|
||||
MWIFIEX_CHANNEL_NOHT40 = BIT(2),
|
||||
MWIFIEX_CHANNEL_NOHT80 = BIT(3),
|
||||
MWIFIEX_CHANNEL_DISABLED = BIT(7),
|
||||
};
|
||||
|
||||
#define HostCmd_RET_BIT 0x8000
|
||||
#define HostCmd_ACT_GEN_GET 0x0000
|
||||
#define HostCmd_ACT_GEN_SET 0x0001
|
||||
|
|
|
@ -139,6 +139,8 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
|
|||
adapter->nd_info = NULL;
|
||||
}
|
||||
|
||||
kfree(adapter->regd);
|
||||
|
||||
vfree(adapter->chan_stats);
|
||||
kfree(adapter);
|
||||
return 0;
|
||||
|
|
|
@ -1005,6 +1005,7 @@ struct mwifiex_adapter {
|
|||
bool usb_mc_status;
|
||||
bool usb_mc_setup;
|
||||
struct cfg80211_wowlan_nd_info *nd_info;
|
||||
struct ieee80211_regdomain *regd;
|
||||
};
|
||||
|
||||
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
|
||||
|
|
|
@ -1022,6 +1022,93 @@ static int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
|
|||
return 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)
|
||||
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;
|
||||
}
|
||||
|
||||
static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
{
|
||||
|
@ -1050,6 +1137,10 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
|
|||
mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:",
|
||||
(u8 *)head + sizeof(*head),
|
||||
tlv_buf_len);
|
||||
priv->adapter->regd =
|
||||
mwifiex_create_custom_regdomain(priv,
|
||||
(u8 *)head +
|
||||
sizeof(*head), tlv_buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue