cfg80211: pass a channel definition struct
Instead of passing a channel pointer and channel type to all functions and driver methods, pass a new channel definition struct. Right now, this struct contains just the control channel and channel type, but for VHT this will change. Also, add a small inline cfg80211_get_chandef_type() so that drivers don't need to use the _type field of the new structure all the time, which will change. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
fe4b31810c
commit
683b6d3b31
|
@ -1093,15 +1093,20 @@ out:
|
||||||
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||||
enum wmi_phy_mode mode)
|
enum wmi_phy_mode mode)
|
||||||
{
|
{
|
||||||
enum nl80211_channel_type type;
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||||
"channel switch notify nw_type %d freq %d mode %d\n",
|
"channel switch notify nw_type %d freq %d mode %d\n",
|
||||||
vif->nw_type, freq, mode);
|
vif->nw_type, freq, mode);
|
||||||
|
|
||||||
type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
|
chandef.chan = ieee80211_get_channel(vif->ar->wiphy, freq);
|
||||||
|
if (WARN_ON(!chandef.chan))
|
||||||
|
return;
|
||||||
|
|
||||||
cfg80211_ch_switch_notify(vif->ndev, freq, type);
|
chandef._type = (mode == WMI_11G_HT20) ?
|
||||||
|
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
|
||||||
|
|
||||||
|
cfg80211_ch_switch_notify(vif->ndev, &chandef);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
|
@ -1613,8 +1618,8 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
|
||||||
vif->ssid_len = ibss_param->ssid_len;
|
vif->ssid_len = ibss_param->ssid_len;
|
||||||
memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
|
memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
|
||||||
|
|
||||||
if (ibss_param->channel)
|
if (ibss_param->chandef.chan)
|
||||||
vif->ch_hint = ibss_param->channel->center_freq;
|
vif->ch_hint = ibss_param->chandef.chan->center_freq;
|
||||||
|
|
||||||
if (ibss_param->channel_fixed) {
|
if (ibss_param->channel_fixed) {
|
||||||
/*
|
/*
|
||||||
|
@ -2856,7 +2861,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
p.ssid_len = vif->ssid_len;
|
p.ssid_len = vif->ssid_len;
|
||||||
memcpy(p.ssid, vif->ssid, vif->ssid_len);
|
memcpy(p.ssid, vif->ssid, vif->ssid_len);
|
||||||
p.dot11_auth_mode = vif->dot11_auth_mode;
|
p.dot11_auth_mode = vif->dot11_auth_mode;
|
||||||
p.ch = cpu_to_le16(info->channel->center_freq);
|
p.ch = cpu_to_le16(info->chandef.chan->center_freq);
|
||||||
|
|
||||||
/* Enable uAPSD support by default */
|
/* Enable uAPSD support by default */
|
||||||
res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
|
res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
|
||||||
|
@ -2880,8 +2885,9 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ath6kl_set_htcap(vif, info->channel->band,
|
if (ath6kl_set_htcap(vif, info->chandef.chan->band,
|
||||||
info->channel_type != NL80211_CHAN_NO_HT))
|
cfg80211_get_chandef_type(&info->chandef)
|
||||||
|
!= NL80211_CHAN_NO_HT))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1212,8 +1212,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
else
|
else
|
||||||
WL_CONN("No BSSID specified\n");
|
WL_CONN("No BSSID specified\n");
|
||||||
|
|
||||||
if (params->channel)
|
if (params->chandef.chan)
|
||||||
WL_CONN("channel: %d\n", params->channel->center_freq);
|
WL_CONN("channel: %d\n", params->chandef.chan->center_freq);
|
||||||
else
|
else
|
||||||
WL_CONN("no channel specified\n");
|
WL_CONN("no channel specified\n");
|
||||||
|
|
||||||
|
@ -1286,12 +1286,12 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Channel */
|
/* Channel */
|
||||||
if (params->channel) {
|
if (params->chandef.chan) {
|
||||||
u32 target_channel;
|
u32 target_channel;
|
||||||
|
|
||||||
cfg->channel =
|
cfg->channel =
|
||||||
ieee80211_frequency_to_channel(
|
ieee80211_frequency_to_channel(
|
||||||
params->channel->center_freq);
|
params->chandef.chan->center_freq);
|
||||||
if (params->channel_fixed) {
|
if (params->channel_fixed) {
|
||||||
/* adding chanspec */
|
/* adding chanspec */
|
||||||
brcmf_ch_to_chanspec(cfg->channel,
|
brcmf_ch_to_chanspec(cfg->channel,
|
||||||
|
@ -3938,7 +3938,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
s32 bssidx = 0;
|
s32 bssidx = 0;
|
||||||
|
|
||||||
WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
|
WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
|
||||||
settings->channel_type, settings->beacon_interval,
|
cfg80211_get_chandef_type(&settings->chandef),
|
||||||
|
settings->beacon_interval,
|
||||||
settings->dtim_period);
|
settings->dtim_period);
|
||||||
WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
|
WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
|
||||||
settings->ssid, settings->ssid_len, settings->auth_type,
|
settings->ssid, settings->ssid_len, settings->auth_type,
|
||||||
|
|
|
@ -436,19 +436,19 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
|
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *channel,
|
struct cfg80211_chan_def *chandef)
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||||
int ret = -ENOTSUPP;
|
int ret = -ENOTSUPP;
|
||||||
|
|
||||||
lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
|
lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
|
||||||
channel->center_freq, channel_type);
|
chandef->chan->center_freq,
|
||||||
|
cfg80211_get_chandef_type(chandef));
|
||||||
|
|
||||||
if (channel_type != NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = lbs_set_channel(priv, channel->hw_value);
|
ret = lbs_set_channel(priv, chandef->chan->hw_value);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
||||||
|
@ -1734,7 +1734,7 @@ static void lbs_join_post(struct lbs_private *priv,
|
||||||
/* Fake DS channel IE */
|
/* Fake DS channel IE */
|
||||||
*fake++ = WLAN_EID_DS_PARAMS;
|
*fake++ = WLAN_EID_DS_PARAMS;
|
||||||
*fake++ = 1;
|
*fake++ = 1;
|
||||||
*fake++ = params->channel->hw_value;
|
*fake++ = params->chandef.chan->hw_value;
|
||||||
/* Fake IBSS params IE */
|
/* Fake IBSS params IE */
|
||||||
*fake++ = WLAN_EID_IBSS_PARAMS;
|
*fake++ = WLAN_EID_IBSS_PARAMS;
|
||||||
*fake++ = 2;
|
*fake++ = 2;
|
||||||
|
@ -1755,7 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv,
|
||||||
lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
|
lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
|
||||||
|
|
||||||
bss = cfg80211_inform_bss(priv->wdev->wiphy,
|
bss = cfg80211_inform_bss(priv->wdev->wiphy,
|
||||||
params->channel,
|
params->chandef.chan,
|
||||||
bssid,
|
bssid,
|
||||||
0,
|
0,
|
||||||
capability,
|
capability,
|
||||||
|
@ -1833,7 +1833,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
|
||||||
cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
|
cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
|
||||||
cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
|
cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
|
||||||
cmd.bss.ds.header.len = 1;
|
cmd.bss.ds.header.len = 1;
|
||||||
cmd.bss.ds.channel = params->channel->hw_value;
|
cmd.bss.ds.channel = params->chandef.chan->hw_value;
|
||||||
cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
|
cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
|
||||||
cmd.bss.ibss.header.len = 2;
|
cmd.bss.ibss.header.len = 2;
|
||||||
cmd.bss.ibss.atimwindow = 0;
|
cmd.bss.ibss.atimwindow = 0;
|
||||||
|
@ -1942,7 +1942,7 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
|
||||||
cmd.ibss.atimwindow = 0;
|
cmd.ibss.atimwindow = 0;
|
||||||
cmd.ds.header.id = WLAN_EID_DS_PARAMS;
|
cmd.ds.header.id = WLAN_EID_DS_PARAMS;
|
||||||
cmd.ds.header.len = 1;
|
cmd.ds.header.len = 1;
|
||||||
cmd.ds.channel = params->channel->hw_value;
|
cmd.ds.channel = params->chandef.chan->hw_value;
|
||||||
/* Only v8 and below support setting probe delay */
|
/* Only v8 and below support setting probe delay */
|
||||||
if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
|
if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
|
||||||
cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
||||||
|
@ -1987,18 +1987,18 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
|
||||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||||
|
|
||||||
if (!params->channel) {
|
if (!params->chandef.chan) {
|
||||||
ret = -ENOTSUPP;
|
ret = -ENOTSUPP;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lbs_set_channel(priv, params->channel->hw_value);
|
ret = lbs_set_channel(priv, params->chandef.chan->hw_value);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Search if someone is beaconing. This assumes that the
|
/* Search if someone is beaconing. This assumes that the
|
||||||
* bss list is populated already */
|
* bss list is populated already */
|
||||||
bss = cfg80211_get_bss(wiphy, params->channel, params->bssid,
|
bss = cfg80211_get_bss(wiphy, params->chandef.chan, params->bssid,
|
||||||
params->ssid, params->ssid_len,
|
params->ssid, params->ssid_len,
|
||||||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||||
|
|
||||||
|
|
|
@ -1291,21 +1291,23 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bss_cfg->channel =
|
bss_cfg->channel = ieee80211_frequency_to_channel(
|
||||||
(u8)ieee80211_frequency_to_channel(params->channel->center_freq);
|
params->chandef.chan->center_freq);
|
||||||
|
|
||||||
/* Set appropriate bands */
|
/* Set appropriate bands */
|
||||||
if (params->channel->band == IEEE80211_BAND_2GHZ) {
|
if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
|
||||||
bss_cfg->band_cfg = BAND_CONFIG_BG;
|
bss_cfg->band_cfg = BAND_CONFIG_BG;
|
||||||
|
|
||||||
if (params->channel_type == NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(¶ms->chandef) ==
|
||||||
|
NL80211_CHAN_NO_HT)
|
||||||
config_bands = BAND_B | BAND_G;
|
config_bands = BAND_B | BAND_G;
|
||||||
else
|
else
|
||||||
config_bands = BAND_B | BAND_G | BAND_GN;
|
config_bands = BAND_B | BAND_G | BAND_GN;
|
||||||
} else {
|
} else {
|
||||||
bss_cfg->band_cfg = BAND_CONFIG_A;
|
bss_cfg->band_cfg = BAND_CONFIG_A;
|
||||||
|
|
||||||
if (params->channel_type == NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(¶ms->chandef) ==
|
||||||
|
NL80211_CHAN_NO_HT)
|
||||||
config_bands = BAND_A;
|
config_bands = BAND_A;
|
||||||
else
|
else
|
||||||
config_bands = BAND_AN | BAND_A;
|
config_bands = BAND_AN | BAND_A;
|
||||||
|
@ -1678,7 +1680,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
|
||||||
int index = 0, i;
|
int index = 0, i;
|
||||||
u8 config_bands = 0;
|
u8 config_bands = 0;
|
||||||
|
|
||||||
if (params->channel->band == IEEE80211_BAND_2GHZ) {
|
if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
|
||||||
if (!params->basic_rates) {
|
if (!params->basic_rates) {
|
||||||
config_bands = BAND_B | BAND_G;
|
config_bands = BAND_B | BAND_G;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1703,10 +1705,12 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params->channel_type != NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(¶ms->chandef) !=
|
||||||
|
NL80211_CHAN_NO_HT)
|
||||||
config_bands |= BAND_GN;
|
config_bands |= BAND_GN;
|
||||||
} else {
|
} else {
|
||||||
if (params->channel_type == NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(¶ms->chandef) !=
|
||||||
|
NL80211_CHAN_NO_HT)
|
||||||
config_bands = BAND_A;
|
config_bands = BAND_A;
|
||||||
else
|
else
|
||||||
config_bands = BAND_AN | BAND_A;
|
config_bands = BAND_AN | BAND_A;
|
||||||
|
@ -1723,9 +1727,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter->sec_chan_offset =
|
adapter->sec_chan_offset =
|
||||||
mwifiex_chan_type_to_sec_chan_offset(params->channel_type);
|
mwifiex_chan_type_to_sec_chan_offset(
|
||||||
priv->adhoc_channel =
|
cfg80211_get_chandef_type(¶ms->chandef));
|
||||||
ieee80211_frequency_to_channel(params->channel->center_freq);
|
priv->adhoc_channel = ieee80211_frequency_to_channel(
|
||||||
|
params->chandef.chan->center_freq);
|
||||||
|
|
||||||
wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
|
wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
|
||||||
config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
|
config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
|
||||||
|
@ -1759,7 +1764,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
|
||||||
ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
|
ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
|
||||||
params->bssid, priv->bss_mode,
|
params->bssid, priv->bss_mode,
|
||||||
params->channel, NULL, params->privacy);
|
params->chandef.chan, NULL,
|
||||||
|
params->privacy);
|
||||||
done:
|
done:
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
|
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
|
||||||
|
|
|
@ -161,24 +161,23 @@ static int orinoco_scan(struct wiphy *wiphy,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orinoco_set_monitor_channel(struct wiphy *wiphy,
|
static int orinoco_set_monitor_channel(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *chan,
|
struct cfg80211_chan_def *chandef)
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
struct orinoco_private *priv = wiphy_priv(wiphy);
|
struct orinoco_private *priv = wiphy_priv(wiphy);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int channel;
|
int channel;
|
||||||
|
|
||||||
if (!chan)
|
if (!chandef->chan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (channel_type != NL80211_CHAN_NO_HT)
|
if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (chan->band != IEEE80211_BAND_2GHZ)
|
if (chandef->chan->band != IEEE80211_BAND_2GHZ)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
|
channel = ieee80211_freq_to_dsss_chan(chandef->chan->center_freq);
|
||||||
|
|
||||||
if ((channel < 1) || (channel > NUM_CHANNELS) ||
|
if ((channel < 1) || (channel > NUM_CHANNELS) ||
|
||||||
!(priv->channel_mask & (1 << (channel - 1))))
|
!(priv->channel_mask & (1 << (channel - 1))))
|
||||||
|
|
|
@ -2293,7 +2293,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||||
struct usbnet *usbdev = priv->usbdev;
|
struct usbnet *usbdev = priv->usbdev;
|
||||||
struct ieee80211_channel *channel = params->channel;
|
struct ieee80211_channel *channel = params->chandef.chan;
|
||||||
struct ndis_80211_ssid ssid;
|
struct ndis_80211_ssid ssid;
|
||||||
enum nl80211_auth_type auth_type;
|
enum nl80211_auth_type auth_type;
|
||||||
int ret, alg, length, chan = -1;
|
int ret, alg, length, chan = -1;
|
||||||
|
|
|
@ -305,6 +305,23 @@ struct key_params {
|
||||||
u32 cipher;
|
u32 cipher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_chan_def - channel definition
|
||||||
|
* @chan: the (control) channel
|
||||||
|
* @_type: the channel type, don't use this field,
|
||||||
|
* use cfg80211_get_chandef_type() if needed.
|
||||||
|
*/
|
||||||
|
struct cfg80211_chan_def {
|
||||||
|
struct ieee80211_channel *chan;
|
||||||
|
enum nl80211_channel_type _type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline enum nl80211_channel_type
|
||||||
|
cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
return chandef->_type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum survey_info_flags - survey information flags
|
* enum survey_info_flags - survey information flags
|
||||||
*
|
*
|
||||||
|
@ -426,8 +443,7 @@ struct cfg80211_beacon_data {
|
||||||
*
|
*
|
||||||
* Used to configure an AP interface.
|
* Used to configure an AP interface.
|
||||||
*
|
*
|
||||||
* @channel: the channel to start the AP on
|
* @chandef: defines the channel to use
|
||||||
* @channel_type: the channel type to use
|
|
||||||
* @beacon: beacon data
|
* @beacon: beacon data
|
||||||
* @beacon_interval: beacon interval
|
* @beacon_interval: beacon interval
|
||||||
* @dtim_period: DTIM period
|
* @dtim_period: DTIM period
|
||||||
|
@ -441,8 +457,7 @@ struct cfg80211_beacon_data {
|
||||||
* @inactivity_timeout: time in seconds to determine station's inactivity.
|
* @inactivity_timeout: time in seconds to determine station's inactivity.
|
||||||
*/
|
*/
|
||||||
struct cfg80211_ap_settings {
|
struct cfg80211_ap_settings {
|
||||||
struct ieee80211_channel *channel;
|
struct cfg80211_chan_def chandef;
|
||||||
enum nl80211_channel_type channel_type;
|
|
||||||
|
|
||||||
struct cfg80211_beacon_data beacon;
|
struct cfg80211_beacon_data beacon;
|
||||||
|
|
||||||
|
@ -909,8 +924,7 @@ struct mesh_config {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct mesh_setup - 802.11s mesh setup configuration
|
* struct mesh_setup - 802.11s mesh setup configuration
|
||||||
* @channel: the channel to start the mesh network on
|
* @chandef: defines the channel to use
|
||||||
* @channel_type: the channel type to use
|
|
||||||
* @mesh_id: the mesh ID
|
* @mesh_id: the mesh ID
|
||||||
* @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
|
* @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
|
||||||
* @sync_method: which synchronization method to use
|
* @sync_method: which synchronization method to use
|
||||||
|
@ -925,8 +939,7 @@ struct mesh_config {
|
||||||
* These parameters are fixed when the mesh is created.
|
* These parameters are fixed when the mesh is created.
|
||||||
*/
|
*/
|
||||||
struct mesh_setup {
|
struct mesh_setup {
|
||||||
struct ieee80211_channel *channel;
|
struct cfg80211_chan_def chandef;
|
||||||
enum nl80211_channel_type channel_type;
|
|
||||||
const u8 *mesh_id;
|
const u8 *mesh_id;
|
||||||
u8 mesh_id_len;
|
u8 mesh_id_len;
|
||||||
u8 sync_method;
|
u8 sync_method;
|
||||||
|
@ -1266,8 +1279,7 @@ struct cfg80211_disassoc_request {
|
||||||
* @ssid_len: The length of the SSID, will always be non-zero.
|
* @ssid_len: The length of the SSID, will always be non-zero.
|
||||||
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
|
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
|
||||||
* search for IBSSs with a different BSSID.
|
* search for IBSSs with a different BSSID.
|
||||||
* @channel: The channel to use if no IBSS can be found to join.
|
* @chandef: defines the channel to use if no other IBSS to join can be found
|
||||||
* @channel_type: channel type (HT mode)
|
|
||||||
* @channel_fixed: The channel should be fixed -- do not search for
|
* @channel_fixed: The channel should be fixed -- do not search for
|
||||||
* IBSSs to join on other channels.
|
* IBSSs to join on other channels.
|
||||||
* @ie: information element(s) to include in the beacon
|
* @ie: information element(s) to include in the beacon
|
||||||
|
@ -1285,8 +1297,7 @@ struct cfg80211_disassoc_request {
|
||||||
struct cfg80211_ibss_params {
|
struct cfg80211_ibss_params {
|
||||||
u8 *ssid;
|
u8 *ssid;
|
||||||
u8 *bssid;
|
u8 *bssid;
|
||||||
struct ieee80211_channel *channel;
|
struct cfg80211_chan_def chandef;
|
||||||
enum nl80211_channel_type channel_type;
|
|
||||||
u8 *ie;
|
u8 *ie;
|
||||||
u8 ssid_len, ie_len;
|
u8 ssid_len, ie_len;
|
||||||
u16 beacon_interval;
|
u16 beacon_interval;
|
||||||
|
@ -1728,8 +1739,7 @@ struct cfg80211_ops {
|
||||||
struct ieee80211_channel *chan);
|
struct ieee80211_channel *chan);
|
||||||
|
|
||||||
int (*set_monitor_channel)(struct wiphy *wiphy,
|
int (*set_monitor_channel)(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *chan,
|
struct cfg80211_chan_def *chandef);
|
||||||
enum nl80211_channel_type channel_type);
|
|
||||||
|
|
||||||
int (*scan)(struct wiphy *wiphy,
|
int (*scan)(struct wiphy *wiphy,
|
||||||
struct cfg80211_scan_request *request);
|
struct cfg80211_scan_request *request);
|
||||||
|
@ -1855,10 +1865,9 @@ struct cfg80211_ops {
|
||||||
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
|
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
|
||||||
u32 sset, u8 *data);
|
u32 sset, u8 *data);
|
||||||
|
|
||||||
struct ieee80211_channel *
|
int (*get_channel)(struct wiphy *wiphy,
|
||||||
(*get_channel)(struct wiphy *wiphy,
|
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_channel_type *type);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
int (*start_p2p_device)(struct wiphy *wiphy,
|
int (*start_p2p_device)(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev);
|
struct wireless_dev *wdev);
|
||||||
|
@ -2466,8 +2475,7 @@ struct wireless_dev {
|
||||||
spinlock_t event_lock;
|
spinlock_t event_lock;
|
||||||
|
|
||||||
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
||||||
struct ieee80211_channel *preset_chan;
|
struct cfg80211_chan_def preset_chandef;
|
||||||
enum nl80211_channel_type preset_chantype;
|
|
||||||
|
|
||||||
/* for AP and mesh channel tracking */
|
/* for AP and mesh channel tracking */
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
|
@ -3563,28 +3571,25 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
|
||||||
int freq, int sig_dbm);
|
int freq, int sig_dbm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
|
* cfg80211_reg_can_beacon - check if beaconing is allowed
|
||||||
* @wiphy: the wiphy
|
* @wiphy: the wiphy
|
||||||
* @chan: main channel
|
* @chandef: the channel definition
|
||||||
* @channel_type: HT mode
|
|
||||||
*
|
*
|
||||||
* This function returns true if there is no secondary channel or the secondary
|
* This function returns true if there is no secondary channel or the secondary
|
||||||
* channel can be used for beaconing (i.e. is not a radar channel etc.)
|
* channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
|
||||||
*/
|
*/
|
||||||
bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
|
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *chan,
|
struct cfg80211_chan_def *chandef);
|
||||||
enum nl80211_channel_type channel_type);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
|
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
|
||||||
* @dev: the device which switched channels
|
* @dev: the device which switched channels
|
||||||
* @freq: new channel frequency (in MHz)
|
* @chandef: the new channel definition
|
||||||
* @type: channel type
|
|
||||||
*
|
*
|
||||||
* Acquires wdev_lock, so must only be called from sleepable driver context!
|
* Acquires wdev_lock, so must only be called from sleepable driver context!
|
||||||
*/
|
*/
|
||||||
void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
|
void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||||
enum nl80211_channel_type type);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
|
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
|
||||||
|
|
|
@ -735,14 +735,16 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *chan,
|
struct cfg80211_chan_def *chandef)
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
enum nl80211_channel_type channel_type;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (local->monitor_channel == chan &&
|
channel_type = cfg80211_get_chandef_type(chandef);
|
||||||
|
|
||||||
|
if (local->monitor_channel == chandef->chan &&
|
||||||
local->monitor_channel_type == channel_type)
|
local->monitor_channel_type == channel_type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -754,17 +756,17 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
||||||
if (sdata) {
|
if (sdata) {
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
ret = ieee80211_vif_use_channel(
|
ret = ieee80211_vif_use_channel(
|
||||||
sdata, chan, channel_type,
|
sdata, chandef->chan, channel_type,
|
||||||
IEEE80211_CHANCTX_EXCLUSIVE);
|
IEEE80211_CHANCTX_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
} else if (local->open_count == local->monitors) {
|
} else if (local->open_count == local->monitors) {
|
||||||
local->_oper_channel = chan;
|
local->_oper_channel = chandef->chan;
|
||||||
local->_oper_channel_type = channel_type;
|
local->_oper_channel_type = channel_type;
|
||||||
ieee80211_hw_config(local, 0);
|
ieee80211_hw_config(local, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
local->monitor_channel = chan;
|
local->monitor_channel = chandef->chan;
|
||||||
local->monitor_channel_type = channel_type;
|
local->monitor_channel_type = channel_type;
|
||||||
}
|
}
|
||||||
mutex_unlock(&local->iflist_mtx);
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
@ -888,9 +890,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||||
sdata->needed_rx_chains = sdata->local->rx_chains;
|
sdata->needed_rx_chains = sdata->local->rx_chains;
|
||||||
|
|
||||||
err = ieee80211_vif_use_channel(sdata, params->channel,
|
err = ieee80211_vif_use_channel(
|
||||||
params->channel_type,
|
sdata, params->chandef.chan,
|
||||||
IEEE80211_CHANCTX_SHARED);
|
cfg80211_get_chandef_type(¶ms->chandef),
|
||||||
|
IEEE80211_CHANCTX_SHARED);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -1707,9 +1710,10 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
|
||||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||||
sdata->needed_rx_chains = sdata->local->rx_chains;
|
sdata->needed_rx_chains = sdata->local->rx_chains;
|
||||||
|
|
||||||
err = ieee80211_vif_use_channel(sdata, setup->channel,
|
err = ieee80211_vif_use_channel(
|
||||||
setup->channel_type,
|
sdata, setup->chandef.chan,
|
||||||
IEEE80211_CHANCTX_SHARED);
|
cfg80211_get_chandef_type(&setup->chandef),
|
||||||
|
IEEE80211_CHANCTX_SHARED);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -3110,23 +3114,24 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ieee80211_channel *
|
static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
|
||||||
ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_channel_type *type)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
struct ieee80211_channel *chan = NULL;
|
int ret = -ENODATA;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
if (chanctx_conf) {
|
if (chanctx_conf) {
|
||||||
*type = chanctx_conf->channel_type;
|
chandef->chan = chanctx_conf->channel;
|
||||||
chan = chanctx_conf->channel;
|
chandef->_type = chanctx_conf->channel_type;
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
return chan;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -51,7 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
struct cfg80211_bss *bss;
|
struct cfg80211_bss *bss;
|
||||||
u32 bss_change;
|
u32 bss_change;
|
||||||
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
|
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
|
||||||
enum nl80211_channel_type channel_type;
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
lockdep_assert_held(&ifibss->mtx);
|
lockdep_assert_held(&ifibss->mtx);
|
||||||
|
|
||||||
|
@ -79,12 +79,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
|
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
|
||||||
|
|
||||||
channel_type = ifibss->channel_type;
|
chandef.chan = chan;
|
||||||
if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
|
chandef._type = ifibss->channel_type;
|
||||||
channel_type = NL80211_CHAN_HT20;
|
if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef))
|
||||||
|
chandef._type = NL80211_CHAN_HT20;
|
||||||
|
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
if (ieee80211_vif_use_channel(sdata, chan, channel_type,
|
if (ieee80211_vif_use_channel(sdata, chan, chandef._type,
|
||||||
ifibss->fixed_channel ?
|
ifibss->fixed_channel ?
|
||||||
IEEE80211_CHANCTX_SHARED :
|
IEEE80211_CHANCTX_SHARED :
|
||||||
IEEE80211_CHANCTX_EXCLUSIVE)) {
|
IEEE80211_CHANCTX_EXCLUSIVE)) {
|
||||||
|
@ -158,7 +159,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
ifibss->ie, ifibss->ie_len);
|
ifibss->ie, ifibss->ie_len);
|
||||||
|
|
||||||
/* add HT capability and information IEs */
|
/* add HT capability and information IEs */
|
||||||
if (channel_type && sband->ht_cap.ht_supported) {
|
if (chandef._type != NL80211_CHAN_NO_HT &&
|
||||||
|
sband->ht_cap.ht_supported) {
|
||||||
pos = skb_put(skb, 4 +
|
pos = skb_put(skb, 4 +
|
||||||
sizeof(struct ieee80211_ht_cap) +
|
sizeof(struct ieee80211_ht_cap) +
|
||||||
sizeof(struct ieee80211_ht_operation));
|
sizeof(struct ieee80211_ht_operation));
|
||||||
|
@ -170,7 +172,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
* keep them at 0
|
* keep them at 0
|
||||||
*/
|
*/
|
||||||
pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
|
pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
|
||||||
chan, channel_type, 0);
|
chan, chandef._type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local->hw.queues >= IEEE80211_NUM_ACS) {
|
if (local->hw.queues >= IEEE80211_NUM_ACS) {
|
||||||
|
@ -1078,8 +1080,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
||||||
|
|
||||||
sdata->u.ibss.channel = params->channel;
|
sdata->u.ibss.channel = params->chandef.chan;
|
||||||
sdata->u.ibss.channel_type = params->channel_type;
|
sdata->u.ibss.channel_type =
|
||||||
|
cfg80211_get_chandef_type(¶ms->chandef);
|
||||||
sdata->u.ibss.fixed_channel = params->channel_fixed;
|
sdata->u.ibss.fixed_channel = params->channel_fixed;
|
||||||
|
|
||||||
if (params->ie) {
|
if (params->ie) {
|
||||||
|
|
|
@ -11,51 +11,15 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "rdev-ops.h"
|
#include "rdev-ops.h"
|
||||||
|
|
||||||
struct ieee80211_channel *
|
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
|
struct cfg80211_chan_def *chandef)
|
||||||
int freq, enum nl80211_channel_type channel_type)
|
|
||||||
{
|
|
||||||
struct ieee80211_channel *chan;
|
|
||||||
struct ieee80211_sta_ht_cap *ht_cap;
|
|
||||||
|
|
||||||
chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
|
||||||
|
|
||||||
/* Primary channel not allowed */
|
|
||||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (channel_type == NL80211_CHAN_HT40MINUS &&
|
|
||||||
chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
|
||||||
return NULL;
|
|
||||||
else if (channel_type == NL80211_CHAN_HT40PLUS &&
|
|
||||||
chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
|
|
||||||
|
|
||||||
if (channel_type != NL80211_CHAN_NO_HT) {
|
|
||||||
if (!ht_cap->ht_supported)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (channel_type != NL80211_CHAN_HT20 &&
|
|
||||||
(!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
|
||||||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
|
|
||||||
struct ieee80211_channel *chan,
|
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *sec_chan;
|
struct ieee80211_channel *sec_chan;
|
||||||
int diff;
|
int diff;
|
||||||
|
|
||||||
trace_cfg80211_can_beacon_sec_chan(wiphy, chan, channel_type);
|
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
||||||
|
|
||||||
switch (channel_type) {
|
switch (chandef->_type) {
|
||||||
case NL80211_CHAN_HT40PLUS:
|
case NL80211_CHAN_HT40PLUS:
|
||||||
diff = 20;
|
diff = 20;
|
||||||
break;
|
break;
|
||||||
|
@ -67,7 +31,8 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
|
sec_chan = ieee80211_get_channel(wiphy,
|
||||||
|
chandef->chan->center_freq + diff);
|
||||||
if (!sec_chan) {
|
if (!sec_chan) {
|
||||||
trace_cfg80211_return_bool(false);
|
trace_cfg80211_return_bool(false);
|
||||||
return false;
|
return false;
|
||||||
|
@ -84,23 +49,17 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
|
||||||
trace_cfg80211_return_bool(true);
|
trace_cfg80211_return_bool(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
|
EXPORT_SYMBOL(cfg80211_reg_can_beacon);
|
||||||
|
|
||||||
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||||
int freq, enum nl80211_channel_type chantype)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *chan;
|
|
||||||
|
|
||||||
if (!rdev->ops->set_monitor_channel)
|
if (!rdev->ops->set_monitor_channel)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
if (!cfg80211_has_monitors_only(rdev))
|
if (!cfg80211_has_monitors_only(rdev))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
chan = rdev_freq_to_chan(rdev, freq, chantype);
|
return rdev_set_monitor_channel(rdev, chandef);
|
||||||
if (!chan)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return rdev_set_monitor_channel(rdev, chan, chantype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -309,9 +309,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
const struct mesh_config *conf);
|
const struct mesh_config *conf);
|
||||||
int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
|
int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev, int freq,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_channel_type channel_type);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
/* AP */
|
/* AP */
|
||||||
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||||
|
@ -470,11 +470,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel **chan,
|
struct ieee80211_channel **chan,
|
||||||
enum cfg80211_chan_mode *chanmode);
|
enum cfg80211_chan_mode *chanmode);
|
||||||
|
|
||||||
struct ieee80211_channel *
|
|
||||||
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
|
|
||||||
int freq, enum nl80211_channel_type channel_type);
|
|
||||||
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||||
int freq, enum nl80211_channel_type chantype);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|
||||||
const u8 *rates, unsigned int n_rates,
|
const u8 *rates, unsigned int n_rates,
|
||||||
|
|
|
@ -100,9 +100,9 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||||
* 11a for maximum compatibility.
|
* 11a for maximum compatibility.
|
||||||
*/
|
*/
|
||||||
struct ieee80211_supported_band *sband =
|
struct ieee80211_supported_band *sband =
|
||||||
rdev->wiphy.bands[params->channel->band];
|
rdev->wiphy.bands[params->chandef.chan->band];
|
||||||
int j;
|
int j;
|
||||||
u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
|
u32 flag = params->chandef.chan->band == IEEE80211_BAND_5GHZ ?
|
||||||
IEEE80211_RATE_MANDATORY_A :
|
IEEE80211_RATE_MANDATORY_A :
|
||||||
IEEE80211_RATE_MANDATORY_B;
|
IEEE80211_RATE_MANDATORY_B;
|
||||||
|
|
||||||
|
@ -118,11 +118,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
wdev->ibss_fixed = params->channel_fixed;
|
wdev->ibss_fixed = params->channel_fixed;
|
||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
wdev->wext.ibss.channel = params->channel;
|
wdev->wext.ibss.chandef = params->chandef;
|
||||||
#endif
|
#endif
|
||||||
wdev->sme_state = CFG80211_SME_CONNECTING;
|
wdev->sme_state = CFG80211_SME_CONNECTING;
|
||||||
|
|
||||||
err = cfg80211_can_use_chan(rdev, wdev, params->channel,
|
err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan,
|
||||||
params->channel_fixed
|
params->channel_fixed
|
||||||
? CHAN_MODE_SHARED
|
? CHAN_MODE_SHARED
|
||||||
: CHAN_MODE_EXCLUSIVE);
|
: CHAN_MODE_EXCLUSIVE);
|
||||||
|
@ -251,7 +251,9 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||||
wdev->wext.ibss.beacon_interval = 100;
|
wdev->wext.ibss.beacon_interval = 100;
|
||||||
|
|
||||||
/* try to find an IBSS channel if none requested ... */
|
/* try to find an IBSS channel if none requested ... */
|
||||||
if (!wdev->wext.ibss.channel) {
|
if (!wdev->wext.ibss.chandef.chan) {
|
||||||
|
wdev->wext.ibss.chandef._type = NL80211_CHAN_NO_HT;
|
||||||
|
|
||||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
struct ieee80211_channel *chan;
|
struct ieee80211_channel *chan;
|
||||||
|
@ -266,15 +268,15 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||||
continue;
|
continue;
|
||||||
if (chan->flags & IEEE80211_CHAN_DISABLED)
|
if (chan->flags & IEEE80211_CHAN_DISABLED)
|
||||||
continue;
|
continue;
|
||||||
wdev->wext.ibss.channel = chan;
|
wdev->wext.ibss.chandef.chan = chan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wdev->wext.ibss.channel)
|
if (wdev->wext.ibss.chandef.chan)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wdev->wext.ibss.channel)
|
if (!wdev->wext.ibss.chandef.chan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +338,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wdev->wext.ibss.channel == chan)
|
if (wdev->wext.ibss.chandef.chan == chan)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
@ -349,7 +351,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (chan) {
|
if (chan) {
|
||||||
wdev->wext.ibss.channel = chan;
|
wdev->wext.ibss.chandef.chan = chan;
|
||||||
|
wdev->wext.ibss.chandef._type = NL80211_CHAN_NO_HT;
|
||||||
wdev->wext.ibss.channel_fixed = true;
|
wdev->wext.ibss.channel_fixed = true;
|
||||||
} else {
|
} else {
|
||||||
/* cfg80211_ibss_wext_join will pick one if needed */
|
/* cfg80211_ibss_wext_join will pick one if needed */
|
||||||
|
@ -379,8 +382,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
if (wdev->current_bss)
|
if (wdev->current_bss)
|
||||||
chan = wdev->current_bss->pub.channel;
|
chan = wdev->current_bss->pub.channel;
|
||||||
else if (wdev->wext.ibss.channel)
|
else if (wdev->wext.ibss.chandef.chan)
|
||||||
chan = wdev->wext.ibss.channel;
|
chan = wdev->wext.ibss.chandef.chan;
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
if (chan) {
|
if (chan) {
|
||||||
|
|
|
@ -73,8 +73,6 @@ const struct mesh_config default_mesh_config = {
|
||||||
|
|
||||||
const struct mesh_setup default_mesh_setup = {
|
const struct mesh_setup default_mesh_setup = {
|
||||||
/* cfg80211_join_mesh() will pick a channel if needed */
|
/* cfg80211_join_mesh() will pick a channel if needed */
|
||||||
.channel = NULL,
|
|
||||||
.channel_type = NL80211_CHAN_NO_HT,
|
|
||||||
.sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
|
.sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
|
||||||
.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
|
.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
|
||||||
.path_metric = IEEE80211_PATH_METRIC_AIRTIME,
|
.path_metric = IEEE80211_PATH_METRIC_AIRTIME,
|
||||||
|
@ -111,13 +109,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
if (!rdev->ops->join_mesh)
|
if (!rdev->ops->join_mesh)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!setup->channel) {
|
if (!setup->chandef.chan) {
|
||||||
/* if no channel explicitly given, use preset channel */
|
/* if no channel explicitly given, use preset channel */
|
||||||
setup->channel = wdev->preset_chan;
|
setup->chandef = wdev->preset_chandef;
|
||||||
setup->channel_type = wdev->preset_chantype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setup->channel) {
|
if (!setup->chandef.chan) {
|
||||||
/* if we don't have that either, use the first usable channel */
|
/* if we don't have that either, use the first usable channel */
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
|
|
||||||
|
@ -137,26 +134,25 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
IEEE80211_CHAN_DISABLED |
|
IEEE80211_CHAN_DISABLED |
|
||||||
IEEE80211_CHAN_RADAR))
|
IEEE80211_CHAN_RADAR))
|
||||||
continue;
|
continue;
|
||||||
setup->channel = chan;
|
setup->chandef.chan = chan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup->channel)
|
if (setup->chandef.chan)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no usable channel ... */
|
/* no usable channel ... */
|
||||||
if (!setup->channel)
|
if (!setup->chandef.chan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
setup->channel_type = NL80211_CHAN_NO_HT;
|
setup->chandef._type = NL80211_CHAN_NO_HT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel,
|
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
|
||||||
setup->channel_type))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
|
err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan,
|
||||||
CHAN_MODE_SHARED);
|
CHAN_MODE_SHARED);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -165,7 +161,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
if (!err) {
|
if (!err) {
|
||||||
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
|
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
|
||||||
wdev->mesh_id_len = setup->mesh_id_len;
|
wdev->mesh_id_len = setup->mesh_id_len;
|
||||||
wdev->channel = setup->channel;
|
wdev->channel = setup->chandef.chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -188,20 +184,12 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
|
int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev, int freq,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_channel_type channel_type)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *channel;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
channel = rdev_freq_to_chan(rdev, freq, channel_type);
|
|
||||||
if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
|
|
||||||
channel,
|
|
||||||
channel_type)) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Workaround for libertas (only!), it puts the interface
|
* Workaround for libertas (only!), it puts the interface
|
||||||
* into mesh mode but doesn't implement join_mesh. Instead,
|
* into mesh mode but doesn't implement join_mesh. Instead,
|
||||||
|
@ -210,21 +198,21 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
|
||||||
* compatible with 802.11 mesh.
|
* compatible with 802.11 mesh.
|
||||||
*/
|
*/
|
||||||
if (rdev->ops->libertas_set_mesh_channel) {
|
if (rdev->ops->libertas_set_mesh_channel) {
|
||||||
if (channel_type != NL80211_CHAN_NO_HT)
|
if (chandef->_type != NL80211_CHAN_NO_HT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!netif_running(wdev->netdev))
|
if (!netif_running(wdev->netdev))
|
||||||
return -ENETDOWN;
|
return -ENETDOWN;
|
||||||
|
|
||||||
err = cfg80211_can_use_chan(rdev, wdev, channel,
|
err = cfg80211_can_use_chan(rdev, wdev, chandef->chan,
|
||||||
CHAN_MODE_SHARED);
|
CHAN_MODE_SHARED);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
|
err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
|
||||||
channel);
|
chandef->chan);
|
||||||
if (!err)
|
if (!err)
|
||||||
wdev->channel = channel;
|
wdev->channel = chandef->chan;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -232,8 +220,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
|
||||||
if (wdev->mesh_id_len)
|
if (wdev->mesh_id_len)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
wdev->preset_chan = channel;
|
wdev->preset_chandef = *chandef;
|
||||||
wdev->preset_chantype = channel_type;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -988,15 +988,14 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
|
EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
|
||||||
|
|
||||||
void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
|
void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||||
enum nl80211_channel_type type)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct wiphy *wiphy = wdev->wiphy;
|
struct wiphy *wiphy = wdev->wiphy;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||||
struct ieee80211_channel *chan;
|
|
||||||
|
|
||||||
trace_cfg80211_ch_switch_notify(dev, freq, type);
|
trace_cfg80211_ch_switch_notify(dev, chandef);
|
||||||
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
|
@ -1004,12 +1003,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
|
||||||
wdev->iftype != NL80211_IFTYPE_P2P_GO))
|
wdev->iftype != NL80211_IFTYPE_P2P_GO))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
chan = rdev_freq_to_chan(rdev, freq, type);
|
wdev->channel = chandef->chan;
|
||||||
if (WARN_ON(!chan))
|
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
|
||||||
goto out;
|
|
||||||
|
|
||||||
wdev->channel = chan;
|
|
||||||
nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
|
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1381,30 +1381,82 @@ static bool nl80211_valid_channel_type(struct genl_info *info,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
|
||||||
|
struct genl_info *info,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
struct ieee80211_sta_ht_cap *ht_cap;
|
||||||
|
struct ieee80211_channel *sc;
|
||||||
|
u32 control_freq;
|
||||||
|
int offs;
|
||||||
|
|
||||||
|
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||||
|
|
||||||
|
chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
|
||||||
|
chandef->_type = NL80211_CHAN_NO_HT;
|
||||||
|
|
||||||
|
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
||||||
|
!nl80211_valid_channel_type(info, &chandef->_type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Primary channel not allowed */
|
||||||
|
if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap;
|
||||||
|
|
||||||
|
switch (chandef->_type) {
|
||||||
|
case NL80211_CHAN_NO_HT:
|
||||||
|
break;
|
||||||
|
case NL80211_CHAN_HT40MINUS:
|
||||||
|
if (chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
||||||
|
return -EINVAL;
|
||||||
|
offs = -20;
|
||||||
|
/* fall through */
|
||||||
|
case NL80211_CHAN_HT40PLUS:
|
||||||
|
if (chandef->_type == NL80211_CHAN_HT40PLUS) {
|
||||||
|
if (chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
||||||
|
return -EINVAL;
|
||||||
|
offs = 20;
|
||||||
|
}
|
||||||
|
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
||||||
|
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
sc = ieee80211_get_channel(&rdev->wiphy,
|
||||||
|
chandef->chan->center_freq + offs);
|
||||||
|
if (!sc || sc->flags & IEEE80211_CHAN_DISABLED)
|
||||||
|
return -EINVAL;
|
||||||
|
/* fall through */
|
||||||
|
case NL80211_CHAN_HT20:
|
||||||
|
if (!ht_cap->ht_supported)
|
||||||
|
return -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
struct genl_info *info)
|
struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *channel;
|
struct cfg80211_chan_def chandef;
|
||||||
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
|
|
||||||
u32 freq;
|
|
||||||
int result;
|
int result;
|
||||||
enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
|
enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
|
||||||
|
|
||||||
if (wdev)
|
if (wdev)
|
||||||
iftype = wdev->iftype;
|
iftype = wdev->iftype;
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!nl80211_can_set_dev_channel(wdev))
|
if (!nl80211_can_set_dev_channel(wdev))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
result = nl80211_parse_chandef(rdev, info, &chandef);
|
||||||
!nl80211_valid_channel_type(info, &channel_type))
|
if (result)
|
||||||
return -EINVAL;
|
return result;
|
||||||
|
|
||||||
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
switch (iftype) {
|
switch (iftype) {
|
||||||
|
@ -1414,22 +1466,18 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
||||||
result = -EBUSY;
|
result = -EBUSY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
channel = rdev_freq_to_chan(rdev, freq, channel_type);
|
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) {
|
||||||
if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
|
|
||||||
channel,
|
|
||||||
channel_type)) {
|
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wdev->preset_chan = channel;
|
wdev->preset_chandef = chandef;
|
||||||
wdev->preset_chantype = channel_type;
|
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type);
|
result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
result = cfg80211_set_monitor_channel(rdev, freq, channel_type);
|
result = cfg80211_set_monitor_channel(rdev, &chandef);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
|
@ -1749,6 +1797,17 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
|
||||||
((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
|
((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nl80211_send_chandef(struct sk_buff *msg,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
|
||||||
|
chandef->chan->center_freq))
|
||||||
|
return -ENOBUFS;
|
||||||
|
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, chandef->_type))
|
||||||
|
return -ENOBUFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
|
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
|
||||||
struct cfg80211_registered_device *rdev,
|
struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev)
|
struct wireless_dev *wdev)
|
||||||
|
@ -1775,16 +1834,14 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (rdev->ops->get_channel) {
|
if (rdev->ops->get_channel) {
|
||||||
struct ieee80211_channel *chan;
|
int ret;
|
||||||
enum nl80211_channel_type channel_type;
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
chan = rdev_get_channel(rdev, wdev, &channel_type);
|
ret = rdev_get_channel(rdev, wdev, &chandef);
|
||||||
if (chan &&
|
if (ret == 0) {
|
||||||
(nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
|
if (nl80211_send_chandef(msg, &chandef))
|
||||||
chan->center_freq) ||
|
goto nla_put_failure;
|
||||||
nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
|
}
|
||||||
channel_type)))
|
|
||||||
goto nla_put_failure;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wdev->ssid_len) {
|
if (wdev->ssid_len) {
|
||||||
|
@ -2492,11 +2549,10 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
||||||
wdev->iftype != NL80211_IFTYPE_P2P_GO)
|
wdev->iftype != NL80211_IFTYPE_P2P_GO)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!wdev->preset_chan)
|
if (!wdev->preset_chandef.chan)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
params->channel = wdev->preset_chan;
|
params->chandef = wdev->preset_chandef;
|
||||||
params->channel_type = wdev->preset_chantype;
|
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2618,30 +2674,19 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||||
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
|
err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
|
||||||
|
if (err)
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
return err;
|
||||||
!nl80211_valid_channel_type(info, &channel_type))
|
} else if (wdev->preset_chandef.chan) {
|
||||||
return -EINVAL;
|
params.chandef = wdev->preset_chandef;
|
||||||
|
|
||||||
params.channel = rdev_freq_to_chan(rdev,
|
|
||||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
|
|
||||||
channel_type);
|
|
||||||
if (!params.channel)
|
|
||||||
return -EINVAL;
|
|
||||||
params.channel_type = channel_type;
|
|
||||||
} else if (wdev->preset_chan) {
|
|
||||||
params.channel = wdev->preset_chan;
|
|
||||||
params.channel_type = wdev->preset_chantype;
|
|
||||||
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
|
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
|
||||||
params.channel_type))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
err = cfg80211_can_use_chan(rdev, wdev, params.channel,
|
err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan,
|
||||||
CHAN_MODE_SHARED);
|
CHAN_MODE_SHARED);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
|
|
||||||
|
@ -2650,10 +2695,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
|
||||||
err = rdev_start_ap(rdev, dev, ¶ms);
|
err = rdev_start_ap(rdev, dev, ¶ms);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
wdev->preset_chan = params.channel;
|
wdev->preset_chandef = params.chandef;
|
||||||
wdev->preset_chantype = params.channel_type;
|
|
||||||
wdev->beacon_interval = params.beacon_interval;
|
wdev->beacon_interval = params.beacon_interval;
|
||||||
wdev->channel = params.channel;
|
wdev->channel = params.chandef.chan;
|
||||||
wdev->ssid_len = params.ssid_len;
|
wdev->ssid_len = params.ssid_len;
|
||||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
||||||
}
|
}
|
||||||
|
@ -5330,8 +5374,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
|
if (!info->attrs[NL80211_ATTR_SSID] ||
|
||||||
!info->attrs[NL80211_ATTR_SSID] ||
|
|
||||||
!nla_len(info->attrs[NL80211_ATTR_SSID]))
|
!nla_len(info->attrs[NL80211_ATTR_SSID]))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -5366,34 +5409,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
||||||
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
|
err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
|
||||||
enum nl80211_channel_type channel_type;
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (!nl80211_valid_channel_type(info, &channel_type))
|
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (channel_type != NL80211_CHAN_NO_HT &&
|
|
||||||
!(wiphy->features & NL80211_FEATURE_HT_IBSS))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ibss.channel_type = channel_type;
|
|
||||||
} else {
|
|
||||||
ibss.channel_type = NL80211_CHAN_NO_HT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ibss.channel = rdev_freq_to_chan(rdev,
|
|
||||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
|
|
||||||
ibss.channel_type);
|
|
||||||
if (!ibss.channel ||
|
|
||||||
ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
|
|
||||||
ibss.channel->flags & IEEE80211_CHAN_DISABLED)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Both channels should be able to initiate communication */
|
|
||||||
if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
|
|
||||||
ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
|
|
||||||
!cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
|
|
||||||
ibss.channel_type))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
|
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
|
||||||
|
@ -5405,7 +5425,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
||||||
int n_rates =
|
int n_rates =
|
||||||
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
|
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
|
||||||
struct ieee80211_supported_band *sband =
|
struct ieee80211_supported_band *sband =
|
||||||
wiphy->bands[ibss.channel->band];
|
wiphy->bands[ibss.chandef.chan->band];
|
||||||
|
|
||||||
err = ieee80211_get_ratemask(sband, rates, n_rates,
|
err = ieee80211_get_ratemask(sband, rates, n_rates,
|
||||||
&ibss.basic_rates);
|
&ibss.basic_rates);
|
||||||
|
@ -5427,7 +5447,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (IS_ERR(connkeys))
|
if (IS_ERR(connkeys))
|
||||||
return PTR_ERR(connkeys);
|
return PTR_ERR(connkeys);
|
||||||
|
|
||||||
if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) {
|
if ((ibss.chandef._type != NL80211_CHAN_NO_HT) && no_ht) {
|
||||||
kfree(connkeys);
|
kfree(connkeys);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -5948,11 +5968,11 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
struct wireless_dev *wdev = info->user_ptr[1];
|
struct wireless_dev *wdev = info->user_ptr[1];
|
||||||
struct ieee80211_channel *chan;
|
struct cfg80211_chan_def chandef;
|
||||||
struct sk_buff *msg;
|
struct sk_buff *msg;
|
||||||
void *hdr;
|
void *hdr;
|
||||||
u64 cookie;
|
u64 cookie;
|
||||||
u32 freq, duration;
|
u32 duration;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
|
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
|
||||||
|
@ -5973,14 +5993,9 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||||
duration > rdev->wiphy.max_remain_on_channel_duration)
|
duration > rdev->wiphy.max_remain_on_channel_duration)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
err = nl80211_parse_chandef(rdev, info, &chandef);
|
||||||
!nl80211_valid_channel_type(info, NULL))
|
if (err)
|
||||||
return -EINVAL;
|
return err;
|
||||||
|
|
||||||
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
|
||||||
chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT);
|
|
||||||
if (chan == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
|
@ -5994,7 +6009,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||||
goto free_msg;
|
goto free_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rdev_remain_on_channel(rdev, wdev, chan, duration, &cookie);
|
err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
|
||||||
|
duration, &cookie);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto free_msg;
|
goto free_msg;
|
||||||
|
@ -6213,8 +6229,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
struct wireless_dev *wdev = info->user_ptr[1];
|
struct wireless_dev *wdev = info->user_ptr[1];
|
||||||
struct ieee80211_channel *chan;
|
struct cfg80211_chan_def chandef;
|
||||||
u32 freq;
|
|
||||||
int err;
|
int err;
|
||||||
void *hdr = NULL;
|
void *hdr = NULL;
|
||||||
u64 cookie;
|
u64 cookie;
|
||||||
|
@ -6224,8 +6239,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
|
||||||
dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
|
dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_FRAME] ||
|
if (!info->attrs[NL80211_ATTR_FRAME])
|
||||||
!info->attrs[NL80211_ATTR_WIPHY_FREQ])
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rdev->ops->mgmt_tx)
|
if (!rdev->ops->mgmt_tx)
|
||||||
|
@ -6260,10 +6274,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
|
||||||
!nl80211_valid_channel_type(info, NULL))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
|
offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
|
||||||
|
|
||||||
if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
||||||
|
@ -6271,10 +6281,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
|
||||||
no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
|
no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
|
||||||
|
|
||||||
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
err = nl80211_parse_chandef(rdev, info, &chandef);
|
||||||
chan = rdev_freq_to_chan(rdev, freq, NL80211_CHAN_NO_HT);
|
if (err)
|
||||||
if (chan == NULL)
|
return err;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!dont_wait_for_ack) {
|
if (!dont_wait_for_ack) {
|
||||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
|
@ -6290,7 +6299,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, wait,
|
err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
|
||||||
nla_data(info->attrs[NL80211_ATTR_FRAME]),
|
nla_data(info->attrs[NL80211_ATTR_FRAME]),
|
||||||
nla_len(info->attrs[NL80211_ATTR_FRAME]),
|
nla_len(info->attrs[NL80211_ATTR_FRAME]),
|
||||||
no_cck, dont_wait_for_ack, &cookie);
|
no_cck, dont_wait_for_ack, &cookie);
|
||||||
|
@ -6554,21 +6563,12 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||||
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
|
err = nl80211_parse_chandef(rdev, info, &setup.chandef);
|
||||||
|
if (err)
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
|
return err;
|
||||||
!nl80211_valid_channel_type(info, &channel_type))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
setup.channel = rdev_freq_to_chan(rdev,
|
|
||||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
|
|
||||||
channel_type);
|
|
||||||
if (!setup.channel)
|
|
||||||
return -EINVAL;
|
|
||||||
setup.channel_type = channel_type;
|
|
||||||
} else {
|
} else {
|
||||||
/* cfg80211_join_mesh() will sort it out */
|
/* cfg80211_join_mesh() will sort it out */
|
||||||
setup.channel = NULL;
|
setup.chandef.chan = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
|
return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
|
||||||
|
@ -8800,8 +8800,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *netdev, int freq,
|
struct net_device *netdev,
|
||||||
enum nl80211_channel_type type, gfp_t gfp)
|
struct cfg80211_chan_def *chandef, gfp_t gfp)
|
||||||
{
|
{
|
||||||
struct sk_buff *msg;
|
struct sk_buff *msg;
|
||||||
void *hdr;
|
void *hdr;
|
||||||
|
@ -8816,9 +8816,10 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
|
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
|
||||||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
|
goto nla_put_failure;
|
||||||
nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type))
|
|
||||||
|
if (nl80211_send_chandef(msg, chandef))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
genlmsg_end(msg, hdr);
|
genlmsg_end(msg, hdr);
|
||||||
|
|
|
@ -127,8 +127,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
|
||||||
const u8 *bssid, bool preauth, gfp_t gfp);
|
const u8 *bssid, bool preauth, gfp_t gfp);
|
||||||
|
|
||||||
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev, int freq,
|
struct net_device *dev,
|
||||||
enum nl80211_channel_type type, gfp_t gfp);
|
struct cfg80211_chan_def *chandef, gfp_t gfp);
|
||||||
|
|
||||||
bool nl80211_unexpected_frame(struct net_device *dev,
|
bool nl80211_unexpected_frame(struct net_device *dev,
|
||||||
const u8 *addr, gfp_t gfp);
|
const u8 *addr, gfp_t gfp);
|
||||||
|
|
|
@ -359,12 +359,11 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct ieee80211_channel *chan,
|
struct cfg80211_chan_def *chandef)
|
||||||
enum nl80211_channel_type channel_type)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
trace_rdev_set_monitor_channel(&rdev->wiphy, chan, channel_type);
|
trace_rdev_set_monitor_channel(&rdev->wiphy, chandef);
|
||||||
ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, channel_type);
|
ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef);
|
||||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -844,14 +843,17 @@ static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev,
|
||||||
trace_rdev_return_void(&rdev->wiphy);
|
trace_rdev_return_void(&rdev->wiphy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct ieee80211_channel
|
static inline int
|
||||||
*rdev_get_channel(struct cfg80211_registered_device *rdev,
|
rdev_get_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev, enum nl80211_channel_type *type)
|
struct wireless_dev *wdev,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *ret;
|
int ret;
|
||||||
|
|
||||||
trace_rdev_get_channel(&rdev->wiphy, wdev);
|
trace_rdev_get_channel(&rdev->wiphy, wdev);
|
||||||
ret = rdev->ops->get_channel(&rdev->wiphy, wdev, type);
|
ret = rdev->ops->get_channel(&rdev->wiphy, wdev, chandef);
|
||||||
trace_rdev_return_channel(&rdev->wiphy, ret, *type);
|
trace_rdev_return_chandef(&rdev->wiphy, ret, chandef);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,26 @@
|
||||||
#define CHAN_PR_FMT ", band: %d, freq: %u"
|
#define CHAN_PR_FMT ", band: %d, freq: %u"
|
||||||
#define CHAN_PR_ARG __entry->band, __entry->center_freq
|
#define CHAN_PR_ARG __entry->band, __entry->center_freq
|
||||||
|
|
||||||
|
#define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \
|
||||||
|
__field(u16, center_freq) \
|
||||||
|
__field(u32, channel_type)
|
||||||
|
#define CHAN_DEF_ASSIGN(chandef) \
|
||||||
|
do { \
|
||||||
|
if ((chandef) && (chandef)->chan) { \
|
||||||
|
__entry->band = (chandef)->chan->band; \
|
||||||
|
__entry->center_freq = \
|
||||||
|
(chandef)->chan->center_freq; \
|
||||||
|
__entry->channel_type = (chandef)->_type; \
|
||||||
|
} else { \
|
||||||
|
__entry->band = 0; \
|
||||||
|
__entry->center_freq = 0; \
|
||||||
|
__entry->channel_type = 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define CHAN_DEF_PR_FMT ", band: %d, freq: %u, chantype: %d"
|
||||||
|
#define CHAN_DEF_PR_ARG __entry->band, __entry->center_freq, \
|
||||||
|
__entry->channel_type
|
||||||
|
|
||||||
#define SINFO_ENTRY __field(int, generation) \
|
#define SINFO_ENTRY __field(int, generation) \
|
||||||
__field(u32, connected_time) \
|
__field(u32, connected_time) \
|
||||||
__field(u32, inactive_time) \
|
__field(u32, inactive_time) \
|
||||||
|
@ -433,7 +453,7 @@ TRACE_EVENT(rdev_start_ap,
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
NETDEV_ENTRY
|
NETDEV_ENTRY
|
||||||
CHAN_ENTRY
|
CHAN_DEF_ENTRY
|
||||||
__field(int, beacon_interval)
|
__field(int, beacon_interval)
|
||||||
__field(int, dtim_period)
|
__field(int, dtim_period)
|
||||||
__array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
|
__array(char, ssid, IEEE80211_MAX_SSID_LEN + 1)
|
||||||
|
@ -446,7 +466,7 @@ TRACE_EVENT(rdev_start_ap,
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
NETDEV_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
CHAN_ASSIGN(settings->channel);
|
CHAN_DEF_ASSIGN(&settings->chandef);
|
||||||
__entry->beacon_interval = settings->beacon_interval;
|
__entry->beacon_interval = settings->beacon_interval;
|
||||||
__entry->dtim_period = settings->dtim_period;
|
__entry->dtim_period = settings->dtim_period;
|
||||||
__entry->hidden_ssid = settings->hidden_ssid;
|
__entry->hidden_ssid = settings->hidden_ssid;
|
||||||
|
@ -458,10 +478,10 @@ TRACE_EVENT(rdev_start_ap,
|
||||||
memcpy(__entry->ssid, settings->ssid, settings->ssid_len);
|
memcpy(__entry->ssid, settings->ssid, settings->ssid_len);
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", AP settings - ssid: %s, "
|
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", AP settings - ssid: %s, "
|
||||||
CHAN_PR_FMT ", beacon interval: %d, dtim period: %d, "
|
CHAN_DEF_PR_FMT ", beacon interval: %d, dtim period: %d, "
|
||||||
"hidden ssid: %d, wpa versions: %u, privacy: %s, "
|
"hidden ssid: %d, wpa versions: %u, privacy: %s, "
|
||||||
"auth type: %d, inactivity timeout: %d",
|
"auth type: %d, inactivity timeout: %d",
|
||||||
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_PR_ARG,
|
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_DEF_PR_ARG,
|
||||||
__entry->beacon_interval, __entry->dtim_period,
|
__entry->beacon_interval, __entry->dtim_period,
|
||||||
__entry->hidden_ssid, __entry->wpa_ver,
|
__entry->hidden_ssid, __entry->wpa_ver,
|
||||||
BOOL_TO_STR(__entry->privacy), __entry->auth_type,
|
BOOL_TO_STR(__entry->privacy), __entry->auth_type,
|
||||||
|
@ -933,21 +953,19 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel,
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_set_monitor_channel,
|
TRACE_EVENT(rdev_set_monitor_channel,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan,
|
TP_PROTO(struct wiphy *wiphy,
|
||||||
enum nl80211_channel_type chan_type),
|
struct cfg80211_chan_def *chandef),
|
||||||
TP_ARGS(wiphy, chan, chan_type),
|
TP_ARGS(wiphy, chandef),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
CHAN_ENTRY
|
CHAN_DEF_ENTRY
|
||||||
__field(enum nl80211_channel_type, chan_type)
|
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
CHAN_ASSIGN(chan);
|
CHAN_DEF_ASSIGN(chandef);
|
||||||
__entry->chan_type = chan_type;
|
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type : %d",
|
TP_printk(WIPHY_PR_FMT CHAN_DEF_PR_FMT,
|
||||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->chan_type)
|
WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_auth,
|
TRACE_EVENT(rdev_auth,
|
||||||
|
@ -1713,22 +1731,25 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel,
|
||||||
TP_ARGS(wiphy, wdev)
|
TP_ARGS(wiphy, wdev)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_return_channel,
|
TRACE_EVENT(rdev_return_chandef,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan,
|
TP_PROTO(struct wiphy *wiphy, int ret,
|
||||||
enum nl80211_channel_type type),
|
struct cfg80211_chan_def *chandef),
|
||||||
TP_ARGS(wiphy, chan, type),
|
TP_ARGS(wiphy, ret, chandef),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
CHAN_ENTRY
|
__field(int, ret)
|
||||||
__field(enum nl80211_channel_type, type)
|
CHAN_DEF_ENTRY
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
CHAN_ASSIGN(chan);
|
if (ret == 0)
|
||||||
__entry->type = type;
|
CHAN_DEF_ASSIGN(chandef);
|
||||||
|
else
|
||||||
|
CHAN_DEF_ASSIGN((struct cfg80211_chan_def *)NULL);
|
||||||
|
__entry->ret = ret;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type: %d",
|
TP_printk(WIPHY_PR_FMT CHAN_DEF_PR_FMT ", ret: %d",
|
||||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->type)
|
WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->ret)
|
||||||
);
|
);
|
||||||
|
|
||||||
DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device,
|
DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device,
|
||||||
|
@ -1992,40 +2013,35 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify,
|
||||||
NETDEV_PR_ARG, __entry->rssi_event)
|
NETDEV_PR_ARG, __entry->rssi_event)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(cfg80211_can_beacon_sec_chan,
|
TRACE_EVENT(cfg80211_reg_can_beacon,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
|
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||||
enum nl80211_channel_type channel_type),
|
TP_ARGS(wiphy, chandef),
|
||||||
TP_ARGS(wiphy, channel, channel_type),
|
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
CHAN_ENTRY
|
CHAN_DEF_ENTRY
|
||||||
__field(enum nl80211_channel_type, channel_type)
|
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
CHAN_ASSIGN(channel);
|
CHAN_DEF_ASSIGN(chandef);
|
||||||
__entry->channel_type = channel_type;
|
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel_type: %d",
|
TP_printk(WIPHY_PR_FMT CHAN_DEF_PR_FMT,
|
||||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->channel_type)
|
WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(cfg80211_ch_switch_notify,
|
TRACE_EVENT(cfg80211_ch_switch_notify,
|
||||||
TP_PROTO(struct net_device *netdev, int freq,
|
TP_PROTO(struct net_device *netdev,
|
||||||
enum nl80211_channel_type type),
|
struct cfg80211_chan_def *chandef),
|
||||||
TP_ARGS(netdev, freq, type),
|
TP_ARGS(netdev, chandef),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
NETDEV_ENTRY
|
NETDEV_ENTRY
|
||||||
__field(int, freq)
|
CHAN_DEF_ENTRY
|
||||||
__field(enum nl80211_channel_type, type)
|
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
NETDEV_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
__entry->freq = freq;
|
CHAN_DEF_ASSIGN(chandef);
|
||||||
__entry->type = type;
|
|
||||||
),
|
),
|
||||||
TP_printk(NETDEV_PR_FMT ", freq: %d, type: %d", NETDEV_PR_ARG,
|
TP_printk(NETDEV_PR_FMT CHAN_DEF_PR_FMT,
|
||||||
__entry->freq, __entry->type)
|
NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
|
||||||
);
|
);
|
||||||
|
|
||||||
DECLARE_EVENT_CLASS(cfg80211_rx_evt,
|
DECLARE_EVENT_CLASS(cfg80211_rx_evt,
|
||||||
|
|
|
@ -784,6 +784,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||||
|
struct cfg80211_chan_def chandef = {
|
||||||
|
._type = NL80211_CHAN_NO_HT,
|
||||||
|
};
|
||||||
int freq, err;
|
int freq, err;
|
||||||
|
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
|
@ -797,8 +800,11 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
||||||
return freq;
|
return freq;
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||||
|
if (!chandef.chan)
|
||||||
|
return -EINVAL;
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT);
|
err = cfg80211_set_monitor_channel(rdev, &chandef);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
return err;
|
return err;
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
|
@ -807,9 +813,11 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
||||||
return freq;
|
return freq;
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||||
|
if (!chandef.chan)
|
||||||
|
return -EINVAL;
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
err = cfg80211_set_mesh_freq(rdev, wdev, freq,
|
err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
|
||||||
NL80211_CHAN_NO_HT);
|
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
return err;
|
return err;
|
||||||
default:
|
default:
|
||||||
|
@ -823,8 +831,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||||
struct ieee80211_channel *chan;
|
struct cfg80211_chan_def chandef;
|
||||||
enum nl80211_channel_type channel_type;
|
int ret;
|
||||||
|
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
|
@ -835,10 +843,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
|
||||||
if (!rdev->ops->get_channel)
|
if (!rdev->ops->get_channel)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
chan = rdev_get_channel(rdev, wdev, &channel_type);
|
ret = rdev_get_channel(rdev, wdev, &chandef);
|
||||||
if (!chan)
|
if (ret)
|
||||||
return -EINVAL;
|
return ret;
|
||||||
freq->m = chan->center_freq;
|
freq->m = chandef.chan->center_freq;
|
||||||
freq->e = 6;
|
freq->e = 6;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -119,7 +119,15 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
||||||
* channel we disconnected above and reconnect below.
|
* channel we disconnected above and reconnect below.
|
||||||
*/
|
*/
|
||||||
if (chan && !wdev->wext.connect.ssid_len) {
|
if (chan && !wdev->wext.connect.ssid_len) {
|
||||||
err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT);
|
struct cfg80211_chan_def chandef = {
|
||||||
|
._type = NL80211_CHAN_NO_HT,
|
||||||
|
};
|
||||||
|
|
||||||
|
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||||
|
if (chandef.chan)
|
||||||
|
err = cfg80211_set_monitor_channel(rdev, &chandef);
|
||||||
|
else
|
||||||
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue