2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-15 08:44:14 +08:00

Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

This commit is contained in:
John W. Linville 2012-11-26 14:46:41 -05:00
commit 62c8003ecb
55 changed files with 1649 additions and 1069 deletions

View File

@ -1074,15 +1074,18 @@ 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; cfg80211_chandef_create(&chandef,
ieee80211_get_channel(vif->ar->wiphy, freq),
(mode == WMI_11G_HT20) ?
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
cfg80211_ch_switch_notify(vif->ndev, freq, type); 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,
@ -1594,8 +1597,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) {
/* /*
@ -2878,7 +2881,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);
@ -2909,8 +2912,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;
/* /*
@ -3006,7 +3010,6 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
static int ath6kl_remain_on_channel(struct wiphy *wiphy, static int ath6kl_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, unsigned int duration,
u64 *cookie) u64 *cookie)
{ {
@ -3165,10 +3168,8 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie)
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev); struct ath6kl *ar = ath6kl_priv(vif->ndev);

View File

@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
return -EINVAL; return -EINVAL;
} }
id = vif->last_roc_id; id = vif->last_roc_id;
cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT, cfg80211_ready_on_channel(&vif->wdev, id, chan,
dur, GFP_ATOMIC); dur, GFP_ATOMIC);
return 0; return 0;
@ -513,8 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
else else
id = vif->last_roc_id; /* timeout on uncanceled r-o-c */ id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
vif->last_cancel_roc_id = 0; vif->last_cancel_roc_id = 0;
cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, GFP_ATOMIC);
NL80211_CHAN_NO_HT, GFP_ATOMIC);
return 0; return 0;
} }

View File

@ -1013,8 +1013,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");
@ -1087,12 +1087,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,
@ -3506,7 +3506,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(%zu), auth_type=%d, inactivity_timeout=%d\n", WL_TRACE("ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
settings->ssid, settings->ssid_len, settings->auth_type, settings->ssid, settings->ssid_len, settings->auth_type,

View File

@ -789,7 +789,6 @@ struct iwl_priv {
/* remain-on-channel offload support */ /* remain-on-channel offload support */
struct ieee80211_channel *hw_roc_channel; struct ieee80211_channel *hw_roc_channel;
struct delayed_work hw_roc_disable_work; struct delayed_work hw_roc_disable_work;
enum nl80211_channel_type hw_roc_chantype;
int hw_roc_duration; int hw_roc_duration;
bool hw_roc_setup, hw_roc_start_notified; bool hw_roc_setup, hw_roc_start_notified;

View File

@ -1037,7 +1037,6 @@ done:
static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
int duration) int duration)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@ -1069,7 +1068,6 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
} }
priv->hw_roc_channel = channel; priv->hw_roc_channel = channel;
priv->hw_roc_chantype = channel_type;
/* convert from ms to TU */ /* convert from ms to TU */
priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024); priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
priv->hw_roc_start_notified = false; priv->hw_roc_start_notified = false;

View File

@ -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);

View File

@ -681,7 +681,7 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
return; return;
if (!hwsim_chans_compat(data->channel, if (!hwsim_chans_compat(data->channel,
rcu_dereference(vif->chanctx_conf)->channel)) rcu_dereference(vif->chanctx_conf)->def.chan))
return; return;
data->receive = true; data->receive = true;
@ -832,7 +832,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
} else { } else {
chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf); chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
if (chanctx_conf) if (chanctx_conf)
channel = chanctx_conf->channel; channel = chanctx_conf->def.chan;
else else
channel = NULL; channel = NULL;
} }
@ -977,7 +977,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
return; return;
mac80211_hwsim_tx_frame(hw, skb, mac80211_hwsim_tx_frame(hw, skb,
rcu_dereference(vif->chanctx_conf)->channel); rcu_dereference(vif->chanctx_conf)->def.chan);
} }
@ -1107,9 +1107,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
} }
if (changed & BSS_CHANGED_HT) { if (changed & BSS_CHANGED_HT) {
wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n", wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n",
info->ht_operation_mode, info->ht_operation_mode);
hwsim_chantypes[info->channel_type]);
} }
if (changed & BSS_CHANGED_BASIC_RATES) { if (changed & BSS_CHANGED_BASIC_RATES) {
@ -1368,7 +1367,6 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req) struct cfg80211_scan_request *req)
{ {
struct mac80211_hwsim_data *hwsim = hw->priv; struct mac80211_hwsim_data *hwsim = hw->priv;
int i;
mutex_lock(&hwsim->mutex); mutex_lock(&hwsim->mutex);
if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
@ -1381,11 +1379,6 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(&hwsim->mutex); mutex_unlock(&hwsim->mutex);
wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
for (i = 0; i < req->n_channels; i++)
printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
req->channels[i]->center_freq);
print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
16, 1, req->ie, req->ie_len, 1);
ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
@ -1455,7 +1448,6 @@ static void hw_roc_done(struct work_struct *work)
static int mac80211_hwsim_roc(struct ieee80211_hw *hw, static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
int duration) int duration)
{ {
struct mac80211_hwsim_data *hwsim = hw->priv; struct mac80211_hwsim_data *hwsim = hw->priv;
@ -1498,16 +1490,20 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx) struct ieee80211_chanctx_conf *ctx)
{ {
hwsim_set_chanctx_magic(ctx); hwsim_set_chanctx_magic(ctx);
wiphy_debug(hw->wiphy, "add channel context %d MHz/%d\n", wiphy_debug(hw->wiphy,
ctx->channel->center_freq, ctx->channel_type); "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
ctx->def.chan->center_freq, ctx->def.width,
ctx->def.center_freq1, ctx->def.center_freq2);
return 0; return 0;
} }
static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx) struct ieee80211_chanctx_conf *ctx)
{ {
wiphy_debug(hw->wiphy, "remove channel context %d MHz/%d\n", wiphy_debug(hw->wiphy,
ctx->channel->center_freq, ctx->channel_type); "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
ctx->def.chan->center_freq, ctx->def.width,
ctx->def.center_freq1, ctx->def.center_freq2);
hwsim_check_chanctx_magic(ctx); hwsim_check_chanctx_magic(ctx);
hwsim_clear_chanctx_magic(ctx); hwsim_clear_chanctx_magic(ctx);
} }
@ -1517,8 +1513,10 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
u32 changed) u32 changed)
{ {
hwsim_check_chanctx_magic(ctx); hwsim_check_chanctx_magic(ctx);
wiphy_debug(hw->wiphy, "change channel context %#x (%d MHz/%d)\n", wiphy_debug(hw->wiphy,
changed, ctx->channel->center_freq, ctx->channel_type); "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
ctx->def.chan->center_freq, ctx->def.width,
ctx->def.center_freq1, ctx->def.center_freq2);
} }
static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
@ -1640,7 +1638,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
rcu_read_lock(); rcu_read_lock();
mac80211_hwsim_tx_frame(data->hw, skb, mac80211_hwsim_tx_frame(data->hw, skb,
rcu_dereference(vif->chanctx_conf)->channel); rcu_dereference(vif->chanctx_conf)->def.chan);
rcu_read_unlock(); rcu_read_unlock();
} }
@ -1672,7 +1670,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
rcu_read_lock(); rcu_read_lock();
mac80211_hwsim_tx_frame(data->hw, skb, mac80211_hwsim_tx_frame(data->hw, skb,
rcu_dereference(vif->chanctx_conf)->channel); rcu_dereference(vif->chanctx_conf)->def.chan);
rcu_read_unlock(); rcu_read_unlock();
} }
@ -2204,6 +2202,34 @@ static int __init init_mac80211_hwsim(void)
sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
hw->wiphy->bands[band] = sband; hw->wiphy->bands[band] = sband;
if (channels == 1)
continue;
sband->vht_cap.vht_supported = true;
sband->vht_cap.cap =
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
IEEE80211_VHT_CAP_RXLDPC |
IEEE80211_VHT_CAP_SHORT_GI_80 |
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_TXSTBC |
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_RXSTBC_2 |
IEEE80211_VHT_CAP_RXSTBC_3 |
IEEE80211_VHT_CAP_RXSTBC_4 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT;
sband->vht_cap.vht_mcs.rx_mcs_map =
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 |
IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 |
IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 |
IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 |
IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 |
IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 |
IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 |
IEEE80211_VHT_MCS_SUPPORT_0_8 << 14);
sband->vht_cap.vht_mcs.tx_mcs_map =
sband->vht_cap.vht_mcs.rx_mcs_map;
} }
/* By default all radios are belonging to the first group */ /* By default all radios are belonging to the first group */
data->group = 1; data->group = 1;

View File

@ -180,10 +180,8 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
static int static int
mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie)
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u16 pkt_len; u16 pkt_len;
@ -253,7 +251,6 @@ static int
mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie) unsigned int duration, u64 *cookie)
{ {
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
@ -271,15 +268,14 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
} }
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan, ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
&channel_type, duration); duration);
if (!ret) { if (!ret) {
*cookie = random32() | 1; *cookie = random32() | 1;
priv->roc_cfg.cookie = *cookie; priv->roc_cfg.cookie = *cookie;
priv->roc_cfg.chan = *chan; priv->roc_cfg.chan = *chan;
priv->roc_cfg.chan_type = channel_type;
cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type, cfg80211_ready_on_channel(wdev, *cookie, chan,
duration, GFP_ATOMIC); duration, GFP_ATOMIC);
wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie); wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
@ -302,13 +298,11 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
return -ENOENT; return -ENOENT;
ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE, ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
&priv->roc_cfg.chan, &priv->roc_cfg.chan, 0);
&priv->roc_cfg.chan_type, 0);
if (!ret) { if (!ret) {
cfg80211_remain_on_channel_expired(wdev, cookie, cfg80211_remain_on_channel_expired(wdev, cookie,
&priv->roc_cfg.chan, &priv->roc_cfg.chan,
priv->roc_cfg.chan_type,
GFP_ATOMIC); GFP_ATOMIC);
memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
@ -1297,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(&params->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(&params->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;
@ -1684,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 {
@ -1709,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(&params->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(&params->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;
@ -1729,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(&params->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);
@ -1765,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);

View File

@ -371,7 +371,6 @@ struct wps {
struct mwifiex_roc_cfg { struct mwifiex_roc_cfg {
u64 cookie; u64 cookie;
struct ieee80211_channel chan; struct ieee80211_channel chan;
enum nl80211_channel_type chan_type;
}; };
struct mwifiex_adapter; struct mwifiex_adapter;
@ -1018,7 +1017,6 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv);
int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type *channel_type,
unsigned int duration); unsigned int duration);
int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role);

View File

@ -421,7 +421,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
cfg80211_remain_on_channel_expired(priv->wdev, cfg80211_remain_on_channel_expired(priv->wdev,
priv->roc_cfg.cookie, priv->roc_cfg.cookie,
&priv->roc_cfg.chan, &priv->roc_cfg.chan,
priv->roc_cfg.chan_type,
GFP_ATOMIC); GFP_ATOMIC);
memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));

View File

@ -1044,7 +1044,6 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv)
int int
mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type *ct,
unsigned int duration) unsigned int duration)
{ {
struct host_cmd_ds_remain_on_chan roc_cfg; struct host_cmd_ds_remain_on_chan roc_cfg;
@ -1054,7 +1053,7 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
roc_cfg.action = cpu_to_le16(action); roc_cfg.action = cpu_to_le16(action);
if (action == HostCmd_ACT_GEN_SET) { if (action == HostCmd_ACT_GEN_SET) {
roc_cfg.band_cfg = chan->band; roc_cfg.band_cfg = chan->band;
sc = mwifiex_chan_type_to_sec_chan_offset(*ct); sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);
roc_cfg.band_cfg |= (sc << 2); roc_cfg.band_cfg |= (sc << 2);
roc_cfg.channel = roc_cfg.channel =

View File

@ -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))))

View File

@ -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;

View File

@ -3791,7 +3791,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
/* Handle HT information change */ /* Handle HT information change */
if ((changed & BSS_CHANGED_HT) && if ((changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) { (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_information(wl, wlvif, ret = wl1271_acx_set_ht_information(wl, wlvif,
bss_conf->ht_operation_mode); bss_conf->ht_operation_mode);
if (ret < 0) { if (ret < 0) {
@ -3905,7 +3905,8 @@ sta_not_found:
u32 rates; u32 rates;
int ieoffset; int ieoffset;
wlvif->aid = bss_conf->aid; wlvif->aid = bss_conf->aid;
wlvif->channel_type = bss_conf->channel_type; wlvif->channel_type =
cfg80211_get_chandef_type(&bss_conf->chandef);
wlvif->beacon_int = bss_conf->beacon_int; wlvif->beacon_int = bss_conf->beacon_int;
do_join = true; do_join = true;
set_assoc = true; set_assoc = true;
@ -4071,7 +4072,7 @@ sta_not_found:
/* Handle new association with HT. Do this after join. */ /* Handle new association with HT. Do this after join. */
if (sta_exists) { if (sta_exists) {
if ((changed & BSS_CHANGED_HT) && if ((changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) { (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_capabilities(wl, ret = wl1271_acx_set_ht_capabilities(wl,
&sta_ht_cap, &sta_ht_cap,
true, true,
@ -4098,7 +4099,7 @@ sta_not_found:
/* Handle HT information change. Done after join. */ /* Handle HT information change. Done after join. */
if ((changed & BSS_CHANGED_HT) && if ((changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) { (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
ret = wl1271_acx_set_ht_information(wl, wlvif, ret = wl1271_acx_set_ht_information(wl, wlvif,
bss_conf->ht_operation_mode); bss_conf->ht_operation_mode);
if (ret < 0) { if (ret < 0) {

View File

@ -667,6 +667,21 @@ struct ieee80211_meshconf_ie {
u8 meshconf_cap; u8 meshconf_cap;
} __attribute__ ((packed)); } __attribute__ ((packed));
/**
* enum mesh_config_capab_flags - Mesh Configuration IE capability field flags
*
* @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
* additional mesh peerings with other mesh STAs
* @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
* @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
* is ongoing
*/
enum mesh_config_capab_flags {
IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01,
IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08,
IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20,
};
/** /**
* struct ieee80211_rann_ie * struct ieee80211_rann_ie
* *
@ -1148,11 +1163,13 @@ struct ieee80211_ht_operation {
* STA can receive. Rate expressed in units of 1 Mbps. * STA can receive. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to * If this field is 0 this value should not be used to
* consider the highest RX data rate supported. * consider the highest RX data rate supported.
* The top 3 bits of this field are reserved.
* @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
* @tx_highest: Indicates highest long GI VHT PPDU data rate * @tx_highest: Indicates highest long GI VHT PPDU data rate
* STA can transmit. Rate expressed in units of 1 Mbps. * STA can transmit. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to * If this field is 0 this value should not be used to
* consider the highest TX data rate supported. * consider the highest TX data rate supported.
* The top 3 bits of this field are reserved.
*/ */
struct ieee80211_vht_mcs_info { struct ieee80211_vht_mcs_info {
__le16 rx_mcs_map; __le16 rx_mcs_map;
@ -1161,6 +1178,27 @@ struct ieee80211_vht_mcs_info {
__le16 tx_highest; __le16 tx_highest;
} __packed; } __packed;
/**
* enum ieee80211_vht_mcs_support - VHT MCS support definitions
* @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
* number of streams
* @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported
* @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported
* @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported
*
* These definitions are used in each 2-bit subfield of the @rx_mcs_map
* and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are
* both split into 8 subfields by number of streams. These values indicate
* which MCSes are supported for the number of streams the value appears
* for.
*/
enum ieee80211_vht_mcs_support {
IEEE80211_VHT_MCS_SUPPORT_0_7 = 0,
IEEE80211_VHT_MCS_SUPPORT_0_8 = 1,
IEEE80211_VHT_MCS_SUPPORT_0_9 = 2,
IEEE80211_VHT_MCS_NOT_SUPPORTED = 3,
};
/** /**
* struct ieee80211_vht_cap - VHT capabilities * struct ieee80211_vht_cap - VHT capabilities
* *

View File

@ -305,6 +305,88 @@ struct key_params {
u32 cipher; u32 cipher;
}; };
/**
* struct cfg80211_chan_def - channel definition
* @chan: the (control) channel
* @width: channel width
* @center_freq1: center frequency of first segment
* @center_freq2: center frequency of second segment
* (only with 80+80 MHz)
*/
struct cfg80211_chan_def {
struct ieee80211_channel *chan;
enum nl80211_chan_width width;
u32 center_freq1;
u32 center_freq2;
};
/**
* cfg80211_get_chandef_type - return old channel type from chandef
* @chandef: the channel definition
*
* Returns the old channel type (NOHT, HT20, HT40+/-) from a given
* chandef, which must have a bandwidth allowing this conversion.
*/
static inline enum nl80211_channel_type
cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef)
{
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
return NL80211_CHAN_NO_HT;
case NL80211_CHAN_WIDTH_20:
return NL80211_CHAN_HT20;
case NL80211_CHAN_WIDTH_40:
if (chandef->center_freq1 > chandef->chan->center_freq)
return NL80211_CHAN_HT40PLUS;
return NL80211_CHAN_HT40MINUS;
default:
WARN_ON(1);
return NL80211_CHAN_NO_HT;
}
}
/**
* cfg80211_chandef_create - create channel definition using channel type
* @chandef: the channel definition struct to fill
* @channel: the control channel
* @chantype: the channel type
*
* Given a channel type, create a channel definition.
*/
void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *channel,
enum nl80211_channel_type chantype);
/**
* cfg80211_chandef_identical - check if two channel definitions are identical
* @chandef1: first channel definition
* @chandef2: second channel definition
*
* Returns %true if the channels defined by the channel definitions are
* identical, %false otherwise.
*/
static inline bool
cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
const struct cfg80211_chan_def *chandef2)
{
return (chandef1->chan == chandef2->chan &&
chandef1->width == chandef2->width &&
chandef1->center_freq1 == chandef2->center_freq1 &&
chandef1->center_freq2 == chandef2->center_freq2);
}
/**
* cfg80211_chandef_compatible - check if two channel definitions are compatible
* @chandef1: first channel definition
* @chandef2: second channel definition
*
* Returns %NULL if the given channel definitions are incompatible,
* chandef1 or chandef2 otherwise.
*/
const struct cfg80211_chan_def *
cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
const struct cfg80211_chan_def *chandef2);
/** /**
* enum survey_info_flags - survey information flags * enum survey_info_flags - survey information flags
* *
@ -426,8 +508,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 +522,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;
@ -582,16 +662,24 @@ enum station_info_flags {
* Used by the driver to indicate the specific rate transmission * Used by the driver to indicate the specific rate transmission
* type for 802.11n transmissions. * type for 802.11n transmissions.
* *
* @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
* @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
* @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission
* @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission
* @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission
* @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
* @RATE_INFO_FLAGS_60G: 60gHz MCS * @RATE_INFO_FLAGS_60G: 60GHz MCS
*/ */
enum rate_info_flags { enum rate_info_flags {
RATE_INFO_FLAGS_MCS = 1<<0, RATE_INFO_FLAGS_MCS = BIT(0),
RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, RATE_INFO_FLAGS_VHT_MCS = BIT(1),
RATE_INFO_FLAGS_SHORT_GI = 1<<2, RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2),
RATE_INFO_FLAGS_60G = 1<<3, RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3),
RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4),
RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5),
RATE_INFO_FLAGS_SHORT_GI = BIT(6),
RATE_INFO_FLAGS_60G = BIT(7),
}; };
/** /**
@ -602,11 +690,13 @@ enum rate_info_flags {
* @flags: bitflag of flags from &enum rate_info_flags * @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes a 802.11n bitrate * @mcs: mcs index if struct describes a 802.11n bitrate
* @legacy: bitrate in 100kbit/s for 802.11abg * @legacy: bitrate in 100kbit/s for 802.11abg
* @nss: number of streams (VHT only)
*/ */
struct rate_info { struct rate_info {
u8 flags; u8 flags;
u8 mcs; u8 mcs;
u16 legacy; u16 legacy;
u8 nss;
}; };
/** /**
@ -909,8 +999,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 +1014,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 +1354,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 +1372,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 +1814,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);
@ -1791,7 +1876,6 @@ struct cfg80211_ops {
int (*remain_on_channel)(struct wiphy *wiphy, int (*remain_on_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, unsigned int duration,
u64 *cookie); u64 *cookie);
int (*cancel_remain_on_channel)(struct wiphy *wiphy, int (*cancel_remain_on_channel)(struct wiphy *wiphy,
@ -1800,10 +1884,8 @@ struct cfg80211_ops {
int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie);
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie);
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
u64 cookie); u64 cookie);
@ -1858,10 +1940,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);
@ -2469,8 +2550,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;
@ -3350,14 +3430,12 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
* @wdev: wireless device * @wdev: wireless device
* @cookie: the request cookie * @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request) * @chan: The current channel (from remain_on_channel request)
* @channel_type: Channel type
* @duration: Duration in milliseconds that the driver intents to remain on the * @duration: Duration in milliseconds that the driver intents to remain on the
* channel * channel
* @gfp: allocation flags * @gfp: allocation flags
*/ */
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp); unsigned int duration, gfp_t gfp);
/** /**
@ -3365,12 +3443,10 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
* @wdev: wireless device * @wdev: wireless device
* @cookie: the request cookie * @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request) * @chan: The current channel (from remain_on_channel request)
* @channel_type: Channel type
* @gfp: allocation flags * @gfp: allocation flags
*/ */
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
gfp_t gfp); gfp_t gfp);
@ -3570,28 +3646,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
@ -3652,8 +3725,9 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev);
* the data is malformed or the attribute can't be found (respectively), * the data is malformed or the attribute can't be found (respectively),
* or the length of the found attribute (which can be zero). * or the length of the found attribute (which can be zero).
*/ */
unsigned int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
u8 attr, u8 *buf, unsigned int bufsize); enum ieee80211_p2p_attr_id attr,
u8 *buf, unsigned int bufsize);
/* Logging, debugging and troubleshooting/diagnostic helpers. */ /* Logging, debugging and troubleshooting/diagnostic helpers. */

View File

@ -145,11 +145,11 @@ struct ieee80211_low_level_stats {
/** /**
* enum ieee80211_chanctx_change - change flag for channel context * enum ieee80211_chanctx_change - change flag for channel context
* @IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE: The channel type was changed * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
* @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
*/ */
enum ieee80211_chanctx_change { enum ieee80211_chanctx_change {
IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE = BIT(0), IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
}; };
@ -159,8 +159,7 @@ enum ieee80211_chanctx_change {
* This is the driver-visible part. The ieee80211_chanctx * This is the driver-visible part. The ieee80211_chanctx
* that contains it is visible in mac80211 only. * that contains it is visible in mac80211 only.
* *
* @channel: the channel to tune to * @def: the channel definition
* @channel_type: the channel (HT) type
* @rx_chains_static: The number of RX chains that must always be * @rx_chains_static: The number of RX chains that must always be
* active on the channel to receive MIMO transmissions * active on the channel to receive MIMO transmissions
* @rx_chains_dynamic: The number of RX chains that must be enabled * @rx_chains_dynamic: The number of RX chains that must be enabled
@ -170,8 +169,7 @@ enum ieee80211_chanctx_change {
* sizeof(void *), size is determined in hw information. * sizeof(void *), size is determined in hw information.
*/ */
struct ieee80211_chanctx_conf { struct ieee80211_chanctx_conf {
struct ieee80211_channel *channel; struct cfg80211_chan_def def;
enum nl80211_channel_type channel_type;
u8 rx_chains_static, rx_chains_dynamic; u8 rx_chains_static, rx_chains_dynamic;
@ -288,9 +286,8 @@ enum ieee80211_rssi_event {
* @mcast_rate: per-band multicast rate index + 1 (0: disabled) * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
* @bssid: The BSSID for this BSS * @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not * @enable_beacon: whether beaconing should be enabled or not
* @channel_type: Channel type for this BSS -- the hardware might be * @chandef: Channel definition for this BSS -- the hardware might be
* configured for HT40+ while this BSS only uses no-HT, for * configured a higher bandwidth than this BSS uses, for example.
* example.
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
* This field is only valid when the channel type is one of the HT types. * This field is only valid when the channel type is one of the HT types.
* @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@ -339,7 +336,7 @@ struct ieee80211_bss_conf {
u16 ht_operation_mode; u16 ht_operation_mode;
s32 cqm_rssi_thold; s32 cqm_rssi_thold;
u32 cqm_rssi_hyst; u32 cqm_rssi_hyst;
enum nl80211_channel_type channel_type; struct cfg80211_chan_def chandef;
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
u8 arp_addr_cnt; u8 arp_addr_cnt;
bool arp_filter_enabled; bool arp_filter_enabled;
@ -502,9 +499,14 @@ enum mac80211_tx_control_flags {
* This is set if the current BSS requires ERP protection. * This is set if the current BSS requires ERP protection.
* @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble. * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @IEEE80211_TX_RC_MCS: HT rate. * @IEEE80211_TX_RC_MCS: HT rate.
* @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
* into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
* Greenfield mode. * Greenfield mode.
* @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz. * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
* @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
* @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
* (80+80 isn't supported yet)
* @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
* adjacent 20 MHz channels, if the current channel type is * adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS. * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
@ -515,12 +517,15 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
/* rate index is an MCS rate number instead of an index */ /* rate index is an HT/VHT MCS instead of an index */
IEEE80211_TX_RC_MCS = BIT(3), IEEE80211_TX_RC_MCS = BIT(3),
IEEE80211_TX_RC_GREEN_FIELD = BIT(4), IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
IEEE80211_TX_RC_DUP_DATA = BIT(6), IEEE80211_TX_RC_DUP_DATA = BIT(6),
IEEE80211_TX_RC_SHORT_GI = BIT(7), IEEE80211_TX_RC_SHORT_GI = BIT(7),
IEEE80211_TX_RC_VHT_MCS = BIT(8),
IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9),
IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10),
}; };
@ -563,10 +568,32 @@ enum mac80211_rate_control_flags {
*/ */
struct ieee80211_tx_rate { struct ieee80211_tx_rate {
s8 idx; s8 idx;
u8 count; u16 count:5,
u8 flags; flags:11;
} __packed; } __packed;
#define IEEE80211_MAX_TX_RETRY 31
static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
u8 mcs, u8 nss)
{
WARN_ON(mcs & ~0xF);
WARN_ON(nss & ~0x7);
rate->idx = (nss << 4) | mcs;
}
static inline u8
ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
{
return rate->idx & 0xF;
}
static inline u8
ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
{
return rate->idx >> 4;
}
/** /**
* struct ieee80211_tx_info - skb transmit information * struct ieee80211_tx_info - skb transmit information
* *
@ -720,7 +747,11 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* (including FCS) was received. * (including FCS) was received.
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
* @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
* @RX_FLAG_80MHZ: 80 MHz was used
* @RX_FLAG_80P80MHZ: 80+80 MHz was used
* @RX_FLAG_160MHZ: 160 MHz was used
* @RX_FLAG_SHORT_GI: Short guard interval was used * @RX_FLAG_SHORT_GI: Short guard interval was used
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
* Valid only for data frames (mainly A-MPDU) * Valid only for data frames (mainly A-MPDU)
@ -763,6 +794,10 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
RX_FLAG_MACTIME_END = BIT(21), RX_FLAG_MACTIME_END = BIT(21),
RX_FLAG_VHT = BIT(22),
RX_FLAG_80MHZ = BIT(23),
RX_FLAG_80P80MHZ = BIT(24),
RX_FLAG_160MHZ = BIT(25),
}; };
/** /**
@ -783,7 +818,8 @@ enum mac80211_rx_flags {
* @IEEE80211_HW_SIGNAL_* * @IEEE80211_HW_SIGNAL_*
* @antenna: antenna used * @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates or MCS index if * @rate_idx: index of data rate into band's supported rates or MCS index if
* HT rates are use (RX_FLAG_HT) * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
* @vht_nss: number of streams (VHT only)
* @flag: %RX_FLAG_* * @flag: %RX_FLAG_*
* @rx_flags: internal RX flags for mac80211 * @rx_flags: internal RX flags for mac80211
* @ampdu_reference: A-MPDU reference number, must be a different value for * @ampdu_reference: A-MPDU reference number, must be a different value for
@ -806,6 +842,7 @@ struct ieee80211_rx_status {
u16 vendor_radiotap_len; u16 vendor_radiotap_len;
u16 freq; u16 freq;
u8 rate_idx; u8 rate_idx;
u8 vht_nss;
u8 rx_flags; u8 rx_flags;
u8 band; u8 band;
u8 antenna; u8 antenna;
@ -2550,7 +2587,6 @@ struct ieee80211_ops {
int (*remain_on_channel)(struct ieee80211_hw *hw, int (*remain_on_channel)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
int duration); int duration);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);

View File

@ -118,8 +118,9 @@
* to get a list of all present wiphys. * to get a list of all present wiphys.
* @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
* %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
* %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, * attributes determining the channel width; this is used for setting
* monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT,
* %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
* and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
* However, for setting the channel, see %NL80211_CMD_SET_CHANNEL * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
@ -171,7 +172,7 @@
* %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
* %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
* The channel to use can be set on the interface or be given using the * The channel to use can be set on the interface or be given using the
* %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_CHANNEL_TYPE attrs. * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width.
* @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
* @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
* @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@ -401,8 +402,7 @@
* a response while being associated to an AP on another channel. * a response while being associated to an AP on another channel.
* %NL80211_ATTR_IFINDEX is used to specify which interface (and thus * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus
* radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
* frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be * frequency for the operation.
* optionally used to specify additional channel parameters.
* %NL80211_ATTR_DURATION is used to specify the duration in milliseconds * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
* to remain on the channel. This command is also used as an event to * to remain on the channel. This command is also used as an event to
* notify when the requested duration starts (it may take a while for the * notify when the requested duration starts (it may take a while for the
@ -440,12 +440,11 @@
* as an event indicating reception of a frame that was not processed in * as an event indicating reception of a frame that was not processed in
* kernel code, but is for us (i.e., which may need to be processed in a * kernel code, but is for us (i.e., which may need to be processed in a
* user space application). %NL80211_ATTR_FRAME is used to specify the * user space application). %NL80211_ATTR_FRAME is used to specify the
* frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used
* optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on * to indicate on which channel the frame is to be transmitted or was
* which channel the frame is to be transmitted or was received. If this * received. If this channel is not the current channel (remain-on-channel
* channel is not the current channel (remain-on-channel or the * or the operational channel) the device will switch to the given channel
* operational channel) the device will switch to the given channel and * and transmit the frame, optionally waiting for a response for the time
* transmit the frame, optionally waiting for a response for the time
* specified using %NL80211_ATTR_DURATION. When called, this operation * specified using %NL80211_ATTR_DURATION. When called, this operation
* returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
* TX status event pertaining to the TX request. * TX status event pertaining to the TX request.
@ -473,8 +472,8 @@
* command is used as an event to indicate the that a trigger level was * command is used as an event to indicate the that a trigger level was
* reached. * reached.
* @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
* and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed * and the attributes determining channel width) the given interface
* by %NL80211_ATTR_IFINDEX) shall operate on. * (identifed by %NL80211_ATTR_IFINDEX) shall operate on.
* In case multiple channels are supported by the device, the mechanism * In case multiple channels are supported by the device, the mechanism
* with which it switches channels is implementation-defined. * with which it switches channels is implementation-defined.
* When a monitor interface is given, it can only switch channel while * When a monitor interface is given, it can only switch channel while
@ -568,8 +567,8 @@
* *
* @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
* independently of the userspace SME, send this event indicating * independently of the userspace SME, send this event indicating
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE. * attributes determining channel width.
* *
* @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
* its %NL80211_ATTR_WDEV identifier. It must have been created with * its %NL80211_ATTR_WDEV identifier. It must have been created with
@ -773,14 +772,26 @@ enum nl80211_commands {
* /sys/class/ieee80211/<phyname>/index * /sys/class/ieee80211/<phyname>/index
* @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
* @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
* @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz,
* defines the channel together with the (deprecated)
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes
* %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1
* and %NL80211_ATTR_CENTER_FREQ2
* @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values
* of &enum nl80211_chan_width, describing the channel width. See the
* documentation of the enum for more information.
* @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the
* channel, used for anything but 20 MHz bandwidth
* @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the
* channel, used only for 80+80 MHz bandwidth
* @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
* if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): * if HT20 or HT40 are to be used (i.e., HT disabled if not included):
* NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
* this attribute) * this attribute)
* NL80211_CHAN_HT20 = HT20 only * NL80211_CHAN_HT20 = HT20 only
* NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
* NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
* This attribute is now deprecated.
* @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
* less than or equal to the RTS threshold; allowed range: 1..255; * less than or equal to the RTS threshold; allowed range: 1..255;
* dot11ShortRetryLimit; u8 * dot11ShortRetryLimit; u8
@ -1555,6 +1566,10 @@ enum nl80211_attrs {
NL80211_ATTR_SCAN_FLAGS, NL80211_ATTR_SCAN_FLAGS,
NL80211_ATTR_CHANNEL_WIDTH,
NL80211_ATTR_CENTER_FREQ1,
NL80211_ATTR_CENTER_FREQ2,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
@ -1719,10 +1734,15 @@ struct nl80211_sta_flag_update {
* @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
* @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
* @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
* @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate
* @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
* @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
* @NL80211_RATE_INFO_MAX: highest rate_info number currently defined * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
* @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8)
* @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8)
* @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate
* @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate
* @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate
* @__NL80211_RATE_INFO_AFTER_LAST: internal use * @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/ */
enum nl80211_rate_info { enum nl80211_rate_info {
@ -1732,6 +1752,11 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_40_MHZ_WIDTH, NL80211_RATE_INFO_40_MHZ_WIDTH,
NL80211_RATE_INFO_SHORT_GI, NL80211_RATE_INFO_SHORT_GI,
NL80211_RATE_INFO_BITRATE32, NL80211_RATE_INFO_BITRATE32,
NL80211_RATE_INFO_VHT_MCS,
NL80211_RATE_INFO_VHT_NSS,
NL80211_RATE_INFO_80_MHZ_WIDTH,
NL80211_RATE_INFO_80P80_MHZ_WIDTH,
NL80211_RATE_INFO_160_MHZ_WIDTH,
/* keep last */ /* keep last */
__NL80211_RATE_INFO_AFTER_LAST, __NL80211_RATE_INFO_AFTER_LAST,
@ -2440,6 +2465,15 @@ enum nl80211_ac {
#define NL80211_TXQ_Q_BE NL80211_AC_BE #define NL80211_TXQ_Q_BE NL80211_AC_BE
#define NL80211_TXQ_Q_BK NL80211_AC_BK #define NL80211_TXQ_Q_BK NL80211_AC_BK
/**
* enum nl80211_channel_type - channel type
* @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel
* @NL80211_CHAN_HT20: 20 MHz HT channel
* @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel
* below the control channel
* @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel
* above the control channel
*/
enum nl80211_channel_type { enum nl80211_channel_type {
NL80211_CHAN_NO_HT, NL80211_CHAN_NO_HT,
NL80211_CHAN_HT20, NL80211_CHAN_HT20,
@ -2447,6 +2481,32 @@ enum nl80211_channel_type {
NL80211_CHAN_HT40PLUS NL80211_CHAN_HT40PLUS
}; };
/**
* enum nl80211_chan_width - channel width definitions
*
* These values are used with the %NL80211_ATTR_CHANNEL_WIDTH
* attribute.
*
* @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel
* @NL80211_CHAN_WIDTH_20: 20 MHz HT channel
* @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
* @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
* @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
* @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
*/
enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT,
NL80211_CHAN_WIDTH_20,
NL80211_CHAN_WIDTH_40,
NL80211_CHAN_WIDTH_80,
NL80211_CHAN_WIDTH_80P80,
NL80211_CHAN_WIDTH_160,
};
/** /**
* enum nl80211_bss - netlink attributes for a BSS * enum nl80211_bss - netlink attributes for a BSS
* *

View File

@ -370,30 +370,32 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
return 0; return 0;
} }
static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
{
enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata);
if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
struct ieee80211_supported_band *sband;
sband = sta->local->hw.wiphy->bands[band];
rate->legacy = sband->bitrates[idx].bitrate;
} else
rate->mcs = idx;
}
void sta_set_rate_info_tx(struct sta_info *sta, void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate, const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo) struct rate_info *rinfo)
{ {
rinfo->flags = 0; rinfo->flags = 0;
if (rate->flags & IEEE80211_TX_RC_MCS) if (rate->flags & IEEE80211_TX_RC_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_MCS; rinfo->flags |= RATE_INFO_FLAGS_MCS;
rinfo->mcs = rate->idx;
} else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
rinfo->nss = ieee80211_rate_get_vht_nss(rate);
} else {
struct ieee80211_supported_band *sband;
sband = sta->local->hw.wiphy->bands[
ieee80211_get_sdata_band(sta->sdata)];
rinfo->legacy = sband->bitrates[rate->idx].bitrate;
}
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_SHORT_GI) if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
rate_idx_to_bitrate(rinfo, sta, rate->idx);
} }
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
@ -444,13 +446,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
sinfo->rxrate.flags = 0; sinfo->rxrate.flags = 0;
if (sta->last_rx_rate_flag & RX_FLAG_HT) if (sta->last_rx_rate_flag & RX_FLAG_HT) {
sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
sinfo->rxrate.mcs = sta->last_rx_rate_idx;
} else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
sinfo->rxrate.nss = sta->last_rx_rate_vht_nss;
sinfo->rxrate.mcs = sta->last_rx_rate_idx;
} else {
struct ieee80211_supported_band *sband;
sband = sta->local->hw.wiphy->bands[
ieee80211_get_sdata_band(sta->sdata)];
sinfo->rxrate.legacy =
sband->bitrates[sta->last_rx_rate_idx].bitrate;
}
if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
if (ieee80211_vif_is_mesh(&sdata->vif)) { if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
@ -615,7 +636,7 @@ do_survey:
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)
channel = chanctx_conf->channel; channel = chanctx_conf->def.chan;
else else
channel = NULL; channel = NULL;
rcu_read_unlock(); rcu_read_unlock();
@ -735,15 +756,13 @@ 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;
int ret = 0; int ret = 0;
if (local->monitor_channel == chan && if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
local->monitor_channel_type == channel_type)
return 0; return 0;
mutex_lock(&local->iflist_mtx); mutex_lock(&local->iflist_mtx);
@ -753,20 +772,17 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
lockdep_is_held(&local->iflist_mtx)); lockdep_is_held(&local->iflist_mtx));
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, chandef,
sdata, 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 = cfg80211_get_chandef_type(chandef);
ieee80211_hw_config(local, 0); ieee80211_hw_config(local, 0);
} }
if (ret == 0) { if (ret == 0)
local->monitor_channel = chan; local->monitor_chandef = *chandef;
local->monitor_channel_type = channel_type;
}
mutex_unlock(&local->iflist_mtx); mutex_unlock(&local->iflist_mtx);
return ret; return ret;
@ -888,8 +904,7 @@ 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(sdata, &params->chandef,
params->channel_type,
IEEE80211_CHANCTX_SHARED); IEEE80211_CHANCTX_SHARED);
if (err) if (err)
return err; return err;
@ -1707,8 +1722,7 @@ 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(sdata, &setup->chandef,
setup->channel_type,
IEEE80211_CHANCTX_SHARED); IEEE80211_CHANCTX_SHARED);
if (err) if (err)
return err; return err;
@ -1990,10 +2004,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return err; return err;
} }
if (changed & WIPHY_PARAM_RETRY_SHORT) if (changed & WIPHY_PARAM_RETRY_SHORT) {
if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY)
return -EINVAL;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
if (changed & WIPHY_PARAM_RETRY_LONG) }
if (changed & WIPHY_PARAM_RETRY_LONG) {
if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY)
return -EINVAL;
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
}
if (changed & if (changed &
(WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
@ -2129,7 +2149,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
* the new value until we associate. * the new value until we associate.
*/ */
if (!sdata->u.mgd.associated || if (!sdata->u.mgd.associated ||
sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0; return 0;
ap = sdata->u.mgd.associated->bssid; ap = sdata->u.mgd.associated->bssid;
@ -2236,7 +2256,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
static int ieee80211_start_roc_work(struct ieee80211_local *local, static int ieee80211_start_roc_work(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie, unsigned int duration, u64 *cookie,
struct sk_buff *txskb) struct sk_buff *txskb)
{ {
@ -2254,7 +2273,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
return -ENOMEM; return -ENOMEM;
roc->chan = channel; roc->chan = channel;
roc->chan_type = channel_type;
roc->duration = duration; roc->duration = duration;
roc->req_duration = duration; roc->req_duration = duration;
roc->frame = txskb; roc->frame = txskb;
@ -2287,8 +2305,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
if (!duration) if (!duration)
duration = 10; duration = 10;
ret = drv_remain_on_channel(local, sdata, channel, channel_type, ret = drv_remain_on_channel(local, sdata, channel, duration);
duration);
if (ret) { if (ret) {
kfree(roc); kfree(roc);
return ret; return ret;
@ -2299,8 +2316,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
out_check_combine: out_check_combine:
list_for_each_entry(tmp, &local->roc_list, list) { list_for_each_entry(tmp, &local->roc_list, list) {
if (tmp->chan != channel || tmp->chan_type != channel_type || if (tmp->chan != channel || tmp->sdata != sdata)
tmp->sdata != sdata)
continue; continue;
/* /*
@ -2417,7 +2433,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
static int ieee80211_remain_on_channel(struct wiphy *wiphy, static int ieee80211_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, unsigned int duration,
u64 *cookie) u64 *cookie)
{ {
@ -2426,7 +2441,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy,
int ret; int ret;
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, ret = ieee80211_start_roc_work(local, sdata, chan,
duration, cookie, NULL); duration, cookie, NULL);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
@ -2519,10 +2534,8 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie)
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
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_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
@ -2591,14 +2604,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
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)
need_offchan = chan != chanctx_conf->channel; need_offchan = chan != chanctx_conf->def.chan;
if (channel_type_valid && else
channel_type != chanctx_conf->channel_type)
need_offchan = true;
} else {
need_offchan = true; need_offchan = true;
}
rcu_read_unlock(); rcu_read_unlock();
} }
@ -2633,7 +2642,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
local->hw.offchannel_tx_hw_queue; local->hw.offchannel_tx_hw_queue;
/* This will handle all kinds of coalescing and immediate TX */ /* This will handle all kinds of coalescing and immediate TX */
ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, ret = ieee80211_start_roc_work(local, sdata, chan,
wait, cookie, skb); wait, cookie, skb);
if (ret) if (ret)
kfree_skb(skb); kfree_skb(skb);
@ -3067,7 +3076,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
} }
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
sta = sta_info_get(sdata, peer); sta = sta_info_get(sdata, peer);
if (sta) { if (sta) {
qos = test_sta_flag(sta, WLAN_STA_WME); qos = test_sta_flag(sta, WLAN_STA_WME);
@ -3124,23 +3133,23 @@ 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 = chanctx_conf->def;
chan = chanctx_conf->channel; ret = 0;
} }
rcu_read_unlock(); rcu_read_unlock();
return chan; return ret;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -8,93 +8,47 @@
#include "ieee80211_i.h" #include "ieee80211_i.h"
#include "driver-ops.h" #include "driver-ops.h"
static bool static void ieee80211_change_chandef(struct ieee80211_local *local,
ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, struct ieee80211_chanctx *ctx,
enum nl80211_channel_type chantype2, const struct cfg80211_chan_def *chandef)
enum nl80211_channel_type *compat)
{ {
/* if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
* start out with chantype1 being the result,
* overwriting later if needed
*/
if (compat)
*compat = chantype1;
switch (chantype1) {
case NL80211_CHAN_NO_HT:
if (compat)
*compat = chantype2;
break;
case NL80211_CHAN_HT20:
/*
* allow any change that doesn't go to no-HT
* (if it already is no-HT no change is needed)
*/
if (chantype2 == NL80211_CHAN_NO_HT)
break;
if (compat)
*compat = chantype2;
break;
case NL80211_CHAN_HT40PLUS:
case NL80211_CHAN_HT40MINUS:
/* allow smaller bandwidth and same */
if (chantype2 == NL80211_CHAN_NO_HT)
break;
if (chantype2 == NL80211_CHAN_HT20)
break;
if (chantype2 == chantype1)
break;
return false;
}
return true;
}
static void ieee80211_change_chantype(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx,
enum nl80211_channel_type chantype)
{
if (chantype == ctx->conf.channel_type)
return; return;
ctx->conf.channel_type = chantype; WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE);
ctx->conf.def = *chandef;
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
if (!local->use_chanctx) { if (!local->use_chanctx) {
local->_oper_channel_type = chantype; local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
ieee80211_hw_config(local, 0); ieee80211_hw_config(local, 0);
} }
} }
static struct ieee80211_chanctx * static struct ieee80211_chanctx *
ieee80211_find_chanctx(struct ieee80211_local *local, ieee80211_find_chanctx(struct ieee80211_local *local,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
enum ieee80211_chanctx_mode mode) enum ieee80211_chanctx_mode mode)
{ {
struct ieee80211_chanctx *ctx; struct ieee80211_chanctx *ctx;
enum nl80211_channel_type compat_type;
lockdep_assert_held(&local->chanctx_mtx); lockdep_assert_held(&local->chanctx_mtx);
if (mode == IEEE80211_CHANCTX_EXCLUSIVE) if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
return NULL; return NULL;
if (WARN_ON(!channel))
return NULL;
list_for_each_entry(ctx, &local->chanctx_list, list) { list_for_each_entry(ctx, &local->chanctx_list, list) {
compat_type = ctx->conf.channel_type; const struct cfg80211_chan_def *compat;
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
continue; continue;
if (ctx->conf.channel != channel)
continue; compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type, if (!compat)
channel_type,
&compat_type))
continue; continue;
ieee80211_change_chantype(local, ctx, compat_type); ieee80211_change_chandef(local, ctx, compat);
return ctx; return ctx;
} }
@ -104,8 +58,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
static struct ieee80211_chanctx * static struct ieee80211_chanctx *
ieee80211_new_chanctx(struct ieee80211_local *local, ieee80211_new_chanctx(struct ieee80211_local *local,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
enum ieee80211_chanctx_mode mode) enum ieee80211_chanctx_mode mode)
{ {
struct ieee80211_chanctx *ctx; struct ieee80211_chanctx *ctx;
@ -117,15 +70,15 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
if (!ctx) if (!ctx)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ctx->conf.channel = channel; ctx->conf.def = *chandef;
ctx->conf.channel_type = channel_type;
ctx->conf.rx_chains_static = 1; ctx->conf.rx_chains_static = 1;
ctx->conf.rx_chains_dynamic = 1; ctx->conf.rx_chains_dynamic = 1;
ctx->mode = mode; ctx->mode = mode;
if (!local->use_chanctx) { if (!local->use_chanctx) {
local->_oper_channel_type = channel_type; local->_oper_channel_type =
local->_oper_channel = channel; cfg80211_get_chandef_type(chandef);
local->_oper_channel = chandef->chan;
ieee80211_hw_config(local, 0); ieee80211_hw_config(local, 0);
} else { } else {
err = drv_add_chanctx(local, ctx); err = drv_add_chanctx(local, ctx);
@ -178,41 +131,37 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
return 0; return 0;
} }
static enum nl80211_channel_type static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
ieee80211_calc_chantype(struct ieee80211_local *local, struct ieee80211_chanctx *ctx)
struct ieee80211_chanctx *ctx)
{ {
struct ieee80211_chanctx_conf *conf = &ctx->conf; struct ieee80211_chanctx_conf *conf = &ctx->conf;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
enum nl80211_channel_type result = NL80211_CHAN_NO_HT; const struct cfg80211_chan_def *compat = NULL;
lockdep_assert_held(&local->chanctx_mtx); lockdep_assert_held(&local->chanctx_mtx);
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) { list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
continue; continue;
WARN_ON_ONCE(!ieee80211_channel_types_are_compatible( if (!compat)
sdata->vif.bss_conf.channel_type, compat = &sdata->vif.bss_conf.chandef;
result, &result));
compat = cfg80211_chandef_compatible(
&sdata->vif.bss_conf.chandef, compat);
if (!compat)
break;
} }
rcu_read_unlock(); rcu_read_unlock();
return result; if (WARN_ON_ONCE(!compat))
} return;
static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, ieee80211_change_chandef(local, ctx, compat);
struct ieee80211_chanctx *ctx)
{
enum nl80211_channel_type chantype;
lockdep_assert_held(&local->chanctx_mtx);
chantype = ieee80211_calc_chantype(local, ctx);
ieee80211_change_chantype(local, ctx, chantype);
} }
static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
@ -337,8 +286,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
} }
int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
enum ieee80211_chanctx_mode mode) enum ieee80211_chanctx_mode mode)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
@ -350,15 +298,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->chanctx_mtx); mutex_lock(&local->chanctx_mtx);
__ieee80211_vif_release_channel(sdata); __ieee80211_vif_release_channel(sdata);
ctx = ieee80211_find_chanctx(local, channel, channel_type, mode); ctx = ieee80211_find_chanctx(local, chandef, mode);
if (!ctx) if (!ctx)
ctx = ieee80211_new_chanctx(local, channel, channel_type, mode); ctx = ieee80211_new_chanctx(local, chandef, mode);
if (IS_ERR(ctx)) { if (IS_ERR(ctx)) {
ret = PTR_ERR(ctx); ret = PTR_ERR(ctx);
goto out; goto out;
} }
sdata->vif.bss_conf.channel_type = channel_type; sdata->vif.bss_conf.chandef = *chandef;
ret = ieee80211_assign_vif_chanctx(sdata, ctx); ret = ieee80211_assign_vif_chanctx(sdata, ctx);
if (ret) { if (ret) {

View File

@ -168,7 +168,6 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
IEEE80211_IF_FILE(flags, flags, HEX); IEEE80211_IF_FILE(flags, flags, HEX);
IEEE80211_IF_FILE(state, state, LHEX); IEEE80211_IF_FILE(state, state, LHEX);
IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
@ -632,7 +631,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(flags); DEBUGFS_ADD(flags);
DEBUGFS_ADD(state); DEBUGFS_ADD(state);
DEBUGFS_ADD(channel_type);
DEBUGFS_ADD(txpower); DEBUGFS_ADD(txpower);
DEBUGFS_ADD(user_power_level); DEBUGFS_ADD(user_power_level);
DEBUGFS_ADD(ap_power_level); DEBUGFS_ADD(ap_power_level);

View File

@ -738,16 +738,15 @@ static inline int drv_get_antenna(struct ieee80211_local *local,
static inline int drv_remain_on_channel(struct ieee80211_local *local, static inline int drv_remain_on_channel(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type chantype,
unsigned int duration) unsigned int duration)
{ {
int ret; int ret;
might_sleep(); might_sleep();
trace_drv_remain_on_channel(local, sdata, chan, chantype, duration); trace_drv_remain_on_channel(local, sdata, chan, duration);
ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
chan, chantype, duration); chan, duration);
trace_drv_return_int(local, ret); trace_drv_return_int(local, ret);
return ret; return ret;

View File

@ -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,14 @@ 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; cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
channel_type = NL80211_CHAN_HT20; chandef.width = NL80211_CHAN_WIDTH_20;
chandef.center_freq1 = chan->center_freq;
}
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, &chandef,
ifibss->fixed_channel ? ifibss->fixed_channel ?
IEEE80211_CHANCTX_SHARED : IEEE80211_CHANCTX_SHARED :
IEEE80211_CHANCTX_EXCLUSIVE)) { IEEE80211_CHANCTX_EXCLUSIVE)) {
@ -158,7 +160,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.width != NL80211_CHAN_WIDTH_20_NOHT &&
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 +173,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); &chandef, 0);
} }
if (local->hw.queues >= IEEE80211_NUM_ACS) { if (local->hw.queues >= IEEE80211_NUM_ACS) {
@ -326,7 +329,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (WARN_ON_ONCE(!chanctx_conf)) if (WARN_ON_ONCE(!chanctx_conf))
return NULL; return NULL;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
rcu_read_unlock(); rcu_read_unlock();
sta = sta_info_alloc(sdata, addr, GFP_KERNEL); sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
@ -374,11 +377,13 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
return;
ibss_dbg(sdata, ibss_dbg(sdata,
"RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction);
if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
return;
sta_info_destroy_addr(sdata, mgmt->sa); sta_info_destroy_addr(sdata, mgmt->sa);
sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false);
rcu_read_unlock(); rcu_read_unlock();
@ -473,9 +478,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
/* we both use HT */ /* we both use HT */
struct ieee80211_sta_ht_cap sta_ht_cap_new; struct ieee80211_sta_ht_cap sta_ht_cap_new;
enum nl80211_channel_type channel_type = struct cfg80211_chan_def chandef;
ieee80211_ht_oper_to_channel_type(
elems->ht_operation); ieee80211_ht_oper_to_chandef(channel,
elems->ht_operation,
&chandef);
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems->ht_cap_elem, elems->ht_cap_elem,
@ -485,9 +492,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
* fall back to HT20 if we don't use or use * fall back to HT20 if we don't use or use
* the other extension channel * the other extension channel
*/ */
if (!(channel_type == NL80211_CHAN_HT40MINUS || if (chandef.width != NL80211_CHAN_WIDTH_40 ||
channel_type == NL80211_CHAN_HT40PLUS) || cfg80211_get_chandef_type(&chandef) !=
channel_type != sdata->u.ibss.channel_type) sdata->u.ibss.channel_type)
sta_ht_cap_new.cap &= sta_ht_cap_new.cap &=
~IEEE80211_HT_CAP_SUP_WIDTH_20_40; ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
@ -611,7 +618,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
rcu_read_unlock(); rcu_read_unlock();
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
@ -1076,8 +1083,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(&params->chandef);
sdata->u.ibss.fixed_channel = params->channel_fixed; sdata->u.ibss.fixed_channel = params->channel_fixed;
if (params->ie) { if (params->ie) {

View File

@ -348,7 +348,6 @@ struct ieee80211_roc_work {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
enum nl80211_channel_type chan_type;
bool started, abort, hw_begun, notified; bool started, abort, hw_begun, notified;
@ -364,7 +363,7 @@ enum ieee80211_sta_flags {
IEEE80211_STA_BEACON_POLL = BIT(0), IEEE80211_STA_BEACON_POLL = BIT(0),
IEEE80211_STA_CONNECTION_POLL = BIT(1), IEEE80211_STA_CONNECTION_POLL = BIT(1),
IEEE80211_STA_CONTROL_PORT = BIT(2), IEEE80211_STA_CONTROL_PORT = BIT(2),
IEEE80211_STA_DISABLE_11N = BIT(4), IEEE80211_STA_DISABLE_HT = BIT(4),
IEEE80211_STA_CSA_RECEIVED = BIT(5), IEEE80211_STA_CSA_RECEIVED = BIT(5),
IEEE80211_STA_MFP_ENABLED = BIT(6), IEEE80211_STA_MFP_ENABLED = BIT(6),
IEEE80211_STA_UAPSD_ENABLED = BIT(7), IEEE80211_STA_UAPSD_ENABLED = BIT(7),
@ -800,7 +799,7 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
rcu_read_lock(); rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!WARN_ON(!chanctx_conf)) if (!WARN_ON(!chanctx_conf))
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
rcu_read_unlock(); rcu_read_unlock();
return band; return band;
@ -1048,7 +1047,6 @@ struct ieee80211_local {
/* Temporary remain-on-channel for off-channel operations */ /* Temporary remain-on-channel for off-channel operations */
struct ieee80211_channel *tmp_channel; struct ieee80211_channel *tmp_channel;
enum nl80211_channel_type tmp_channel_type;
/* channel contexts */ /* channel contexts */
struct list_head chanctx_list; struct list_head chanctx_list;
@ -1158,8 +1156,7 @@ struct ieee80211_local {
/* virtual monitor interface */ /* virtual monitor interface */
struct ieee80211_sub_if_data __rcu *monitor_sdata; struct ieee80211_sub_if_data __rcu *monitor_sdata;
struct ieee80211_channel *monitor_channel; struct cfg80211_chan_def monitor_chandef;
enum nl80211_channel_type monitor_channel_type;
}; };
static inline struct ieee80211_sub_if_data * static inline struct ieee80211_sub_if_data *
@ -1518,7 +1515,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
} }
__ieee80211_tx_skb_tid_band(sdata, skb, tid, __ieee80211_tx_skb_tid_band(sdata, skb, tid,
chanctx_conf->channel->band); chanctx_conf->def.chan->band);
rcu_read_unlock(); rcu_read_unlock();
} }
@ -1607,8 +1604,7 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u16 cap); u16 cap);
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
u16 prot_mode); u16 prot_mode);
u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
u32 cap); u32 cap);
@ -1620,13 +1616,13 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
enum ieee80211_band band); enum ieee80211_band band);
/* channel management */ /* channel management */
enum nl80211_channel_type void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); struct ieee80211_ht_operation *ht_oper,
struct cfg80211_chan_def *chandef);
int __must_check int __must_check
ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
enum ieee80211_chanctx_mode mode); enum ieee80211_chanctx_mode mode);
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);

View File

@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
return false; return false;
} }
power = chanctx_conf->channel->max_power; power = chanctx_conf->def.chan->max_power;
rcu_read_unlock(); rcu_read_unlock();
if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
@ -415,8 +415,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
goto out_unlock; goto out_unlock;
} }
ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
local->monitor_channel_type,
IEEE80211_CHANCTX_EXCLUSIVE); IEEE80211_CHANCTX_EXCLUSIVE);
if (ret) { if (ret) {
drv_remove_interface(local, sdata); drv_remove_interface(local, sdata);

View File

@ -115,7 +115,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
channel_type = NL80211_CHAN_NO_HT; channel_type = NL80211_CHAN_NO_HT;
} else if (local->tmp_channel) { } else if (local->tmp_channel) {
chan = local->tmp_channel; chan = local->tmp_channel;
channel_type = local->tmp_channel_type; channel_type = NL80211_CHAN_NO_HT;
} else { } else {
chan = local->_oper_channel; chan = local->_oper_channel;
channel_type = local->_oper_channel_type; channel_type = local->_oper_channel_type;
@ -798,10 +798,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
local->_oper_channel = &sband->channels[0]; local->_oper_channel = &sband->channels[0];
local->hw.conf.channel_type = NL80211_CHAN_NO_HT; local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
} }
if (!local->monitor_channel) { cfg80211_chandef_create(&local->monitor_chandef,
local->monitor_channel = &sband->channels[0]; &sband->channels[0],
local->monitor_channel_type = NL80211_CHAN_NO_HT; NL80211_CHAN_NO_HT);
}
channels += sband->n_channels; channels += sband->n_channels;
if (max_bitrates < sband->n_bitrates) if (max_bitrates < sband->n_bitrates)
@ -884,10 +883,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (supp_ht) if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
if (supp_vht) if (supp_vht) {
local->scan_ies_len += local->scan_ies_len +=
2 + sizeof(struct ieee80211_vht_cap); 2 + sizeof(struct ieee80211_vht_cap);
/*
* (for now at least), drivers wanting to use VHT must
* support channel contexts, as they contain all the
* necessary VHT information and the global hw config
* doesn't (yet)
*/
if (WARN_ON(!local->use_chanctx)) {
result = -EINVAL;
goto fail_wiphy_register;
}
}
if (!local->ops->hw_scan) { if (!local->ops->hw_scan) {
/* For hw_scan, driver needs to set these up. */ /* For hw_scan, driver needs to set these up. */
local->hw.wiphy->max_scan_ssids = 4; local->hw.wiphy->max_scan_ssids = 4;

View File

@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
u32 basic_rates = 0; u32 basic_rates = 0;
enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; struct cfg80211_chan_def sta_chan_def;
/* /*
* As support for each feature is added, check for matching * As support for each feature is added, check for matching
@ -103,17 +103,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.bss_conf.basic_rates != basic_rates) if (sdata->vif.bss_conf.basic_rates != basic_rates)
goto mismatch; goto mismatch;
if (ie->ht_operation) ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
sta_channel_type = ie->ht_operation, &sta_chan_def);
ieee80211_ht_oper_to_channel_type(ie->ht_operation);
/* Disallow HT40+/- mismatch */ if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
if (ie->ht_operation && &sta_chan_def))
(sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS ||
sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) &&
(sta_channel_type == NL80211_CHAN_HT40MINUS ||
sta_channel_type == NL80211_CHAN_HT40PLUS) &&
sdata->vif.bss_conf.channel_type != sta_channel_type)
goto mismatch; goto mismatch;
return true; return true;
@ -129,7 +123,7 @@ mismatch:
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
{ {
return (ie->mesh_config->meshconf_cap & return (ie->mesh_config->meshconf_cap &
MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
} }
/** /**
@ -269,11 +263,11 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
neighbors = (neighbors > 15) ? 15 : neighbors; neighbors = (neighbors > 15) ? 15 : neighbors;
*pos++ = neighbors << 1; *pos++ = neighbors << 1;
/* Mesh capability */ /* Mesh capability */
*pos = MESHCONF_CAPAB_FORWARDING; *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
*pos |= ifmsh->accepting_plinks ? *pos |= ifmsh->accepting_plinks ?
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ |= ifmsh->adjusting_tbtt ? *pos++ |= ifmsh->adjusting_tbtt ?
MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
*pos++ = 0x00; *pos++ = 0x00;
return 0; return 0;
@ -368,7 +362,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
} }
chan = chanctx_conf->channel; chan = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
sband = local->hw.wiphy->bands[chan->band]; sband = local->hw.wiphy->bands[chan->band];
@ -392,7 +386,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
sband = local->hw.wiphy->bands[band]; sband = local->hw.wiphy->bands[band];
if (!sband->ht_cap.ht_supported || if (!sband->ht_cap.ht_supported ||
sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0; return 0;
if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@ -411,7 +405,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
enum nl80211_channel_type channel_type = enum nl80211_channel_type channel_type =
sdata->vif.bss_conf.channel_type; cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef);
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_ht_cap *ht_cap;
u8 *pos; u8 *pos;
@ -422,7 +416,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
} }
channel = chanctx_conf->channel; channel = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
sband = local->hw.wiphy->bands[channel->band]; sband = local->hw.wiphy->bands[channel->band];
@ -435,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
return -ENOMEM; return -ENOMEM;
pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
sdata->vif.bss_conf.ht_operation_mode); sdata->vif.bss_conf.ht_operation_mode);
return 0; return 0;

View File

@ -18,20 +18,6 @@
/* Data structures */ /* Data structures */
/**
* enum mesh_config_capab_flags - mesh config IE capability flags
*
* @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
* additional mesh peerings with other mesh STAs
* @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
* @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing
*/
enum mesh_config_capab_flags {
MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0),
MESHCONF_CAPAB_FORWARDING = BIT(3),
MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5),
};
/** /**
* enum mesh_path_flags - mac80211 mesh path flags * enum mesh_path_flags - mac80211 mesh path flags
* *

View File

@ -19,12 +19,6 @@
#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
jiffies + HZ * t / 1000)) jiffies + HZ * t / 1000))
#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
/* We only need a valid sta if user configured a minimum rssi_threshold. */ /* We only need a valid sta if user configured a minimum rssi_threshold. */
#define rssi_threshold_check(sta, sdata) \ #define rssi_threshold_check(sta, sdata) \
(sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
@ -117,7 +111,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
u16 ht_opmode; u16 ht_opmode;
bool non_ht_sta = false, ht20_sta = false; bool non_ht_sta = false, ht20_sta = false;
if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0; return 0;
rcu_read_lock(); rcu_read_lock();
@ -126,14 +120,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
sta->plink_state != NL80211_PLINK_ESTAB) sta->plink_state != NL80211_PLINK_ESTAB)
continue; continue;
switch (sta->ch_type) { switch (sta->ch_width) {
case NL80211_CHAN_NO_HT: case NL80211_CHAN_WIDTH_20_NOHT:
mpl_dbg(sdata, mpl_dbg(sdata,
"mesh_plink %pM: nonHT sta (%pM) is present\n", "mesh_plink %pM: nonHT sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr); sdata->vif.addr, sta->sta.addr);
non_ht_sta = true; non_ht_sta = true;
goto out; goto out;
case NL80211_CHAN_HT20: case NL80211_CHAN_WIDTH_20:
mpl_dbg(sdata, mpl_dbg(sdata,
"mesh_plink %pM: HT20 sta (%pM) is present\n", "mesh_plink %pM: HT20 sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr); sdata->vif.addr, sta->sta.addr);
@ -148,7 +142,7 @@ out:
if (non_ht_sta) if (non_ht_sta)
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
else if (ht20_sta && else if (ht20_sta &&
sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
else else
ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
@ -378,7 +372,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
sta->sta.supp_rates[band] = rates; sta->sta.supp_rates[band] = rates;
if (elems->ht_cap_elem && if (elems->ht_cap_elem &&
sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems->ht_cap_elem, elems->ht_cap_elem,
&sta->sta.ht_cap); &sta->sta.ht_cap);
@ -386,12 +380,15 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
if (elems->ht_operation) { if (elems->ht_operation) {
struct cfg80211_chan_def chandef;
if (!(elems->ht_operation->ht_param & if (!(elems->ht_operation->ht_param &
IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
sta->sta.ht_cap.cap &= sta->sta.ht_cap.cap &=
~IEEE80211_HT_CAP_SUP_WIDTH_20_40; ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
sta->ch_type = ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
ieee80211_ht_oper_to_channel_type(elems->ht_operation); elems->ht_operation, &chandef);
sta->ch_width = chandef.width;
} }
rate_control_rate_init(sta); rate_control_rate_init(sta);
@ -430,6 +427,7 @@ static void mesh_plink_timer(unsigned long data)
struct sta_info *sta; struct sta_info *sta;
__le16 llid, plid, reason; __le16 llid, plid, reason;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
struct mesh_config *mshcfg;
/* /*
* This STA is valid because sta_info_destroy() will * This STA is valid because sta_info_destroy() will
@ -456,12 +454,13 @@ static void mesh_plink_timer(unsigned long data)
llid = sta->llid; llid = sta->llid;
plid = sta->plid; plid = sta->plid;
sdata = sta->sdata; sdata = sta->sdata;
mshcfg = &sdata->u.mesh.mshcfg;
switch (sta->plink_state) { switch (sta->plink_state) {
case NL80211_PLINK_OPN_RCVD: case NL80211_PLINK_OPN_RCVD:
case NL80211_PLINK_OPN_SNT: case NL80211_PLINK_OPN_SNT:
/* retry timer */ /* retry timer */
if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) {
u32 rand; u32 rand;
mpl_dbg(sta->sdata, mpl_dbg(sta->sdata,
"Mesh plink for %pM (retry, timeout): %d %d\n", "Mesh plink for %pM (retry, timeout): %d %d\n",
@ -484,7 +483,7 @@ static void mesh_plink_timer(unsigned long data)
if (!reason) if (!reason)
reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
sta->sta.addr, llid, plid, reason); sta->sta.addr, llid, plid, reason);
@ -543,7 +542,7 @@ int mesh_plink_open(struct sta_info *sta)
return -EBUSY; return -EBUSY;
} }
sta->plink_state = NL80211_PLINK_OPN_SNT; sta->plink_state = NL80211_PLINK_OPN_SNT;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
mpl_dbg(sdata, mpl_dbg(sdata,
"Mesh plink: starting establishment with %pM\n", "Mesh plink: starting establishment with %pM\n",
@ -570,6 +569,7 @@ void mesh_plink_block(struct sta_info *sta)
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
size_t len, struct ieee80211_rx_status *rx_status) size_t len, struct ieee80211_rx_status *rx_status)
{ {
struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
struct sta_info *sta; struct sta_info *sta;
enum plink_event event; enum plink_event event;
@ -777,7 +777,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->plid = plid; sta->plid = plid;
get_random_bytes(&llid, 2); get_random_bytes(&llid, 2);
sta->llid = llid; sta->llid = llid;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); mesh_plink_timer_set(sta,
mshcfg->dot11MeshRetryTimeout);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, mesh_plink_frame_tx(sdata,
WLAN_SP_MESH_PEERING_OPEN, WLAN_SP_MESH_PEERING_OPEN,
@ -803,7 +804,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason; sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta, if (!mod_plink_timer(sta,
dot11MeshHoldingTimeout(sdata))) mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true; sta->ignore_plink_timer = true;
llid = sta->llid; llid = sta->llid;
@ -825,7 +826,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CNF_ACPT: case CNF_ACPT:
sta->plink_state = NL80211_PLINK_CNF_RCVD; sta->plink_state = NL80211_PLINK_CNF_RCVD;
if (!mod_plink_timer(sta, if (!mod_plink_timer(sta,
dot11MeshConfirmTimeout(sdata))) mshcfg->dot11MeshConfirmTimeout))
sta->ignore_plink_timer = true; sta->ignore_plink_timer = true;
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
@ -847,7 +848,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason; sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta, if (!mod_plink_timer(sta,
dot11MeshHoldingTimeout(sdata))) mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true; sta->ignore_plink_timer = true;
llid = sta->llid; llid = sta->llid;
@ -888,7 +889,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->reason = reason; sta->reason = reason;
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
if (!mod_plink_timer(sta, if (!mod_plink_timer(sta,
dot11MeshHoldingTimeout(sdata))) mshcfg->dot11MeshHoldingTimeout))
sta->ignore_plink_timer = true; sta->ignore_plink_timer = true;
llid = sta->llid; llid = sta->llid;
@ -923,7 +924,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
changed |= __mesh_plink_deactivate(sta); changed |= __mesh_plink_deactivate(sta);
sta->plink_state = NL80211_PLINK_HOLDING; sta->plink_state = NL80211_PLINK_HOLDING;
llid = sta->llid; llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
changed |= mesh_set_ht_prot_mode(sdata); changed |= mesh_set_ht_prot_mode(sdata);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,

View File

@ -43,7 +43,7 @@ struct sync_method {
static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie)
{ {
return (ie->mesh_config->meshconf_cap & return (ie->mesh_config->meshconf_cap &
MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0;
} }
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)

View File

@ -191,17 +191,19 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock(); rcu_read_unlock();
return 0; return 0;
} }
chan = chanctx_conf->channel; chan = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
sband = local->hw.wiphy->bands[chan->band]; sband = local->hw.wiphy->bands[chan->band];
switch (sdata->vif.bss_conf.channel_type) { switch (sdata->vif.bss_conf.chandef.width) {
case NL80211_CHAN_HT40PLUS: case NL80211_CHAN_WIDTH_40:
if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) if (sdata->vif.bss_conf.chandef.chan->center_freq >
sdata->vif.bss_conf.chandef.center_freq1 &&
chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
disable_40 = true; disable_40 = true;
break; if (sdata->vif.bss_conf.chandef.chan->center_freq <
case NL80211_CHAN_HT40MINUS: sdata->vif.bss_conf.chandef.center_freq1 &&
if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
disable_40 = true; disable_40 = true;
break; break;
default: default:
@ -381,7 +383,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
chan = chanctx_conf->channel; chan = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
sband = local->hw.wiphy->bands[chan->band]; sband = local->hw.wiphy->bands[chan->band];
@ -541,7 +543,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
offset = noffset; offset = noffset;
} }
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
sband, chan, sdata->smps_mode); sband, chan, sdata->smps_mode);
@ -1528,8 +1530,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_vif_release_channel(sdata);
/* disassociated - set to defaults now */ /* disassociated - set to defaults now */
ieee80211_set_wmm_default(sdata, false); ieee80211_set_wmm_default(sdata, false);
@ -1539,6 +1539,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync(&sdata->u.mgd.chswitch_timer); del_timer_sync(&sdata->u.mgd.chswitch_timer);
sdata->u.mgd.timers_running = 0; sdata->u.mgd.timers_running = 0;
ifmgd->flags = 0;
ieee80211_vif_release_channel(sdata);
} }
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@ -1864,6 +1867,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
memset(sdata->u.mgd.bssid, 0, ETH_ALEN); memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
} }
@ -2106,6 +2110,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
memset(sdata->u.mgd.bssid, 0, ETH_ALEN); memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
sdata->u.mgd.flags = 0;
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
} }
@ -2170,7 +2175,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems.ht_cap_elem, &sta->sta.ht_cap); elems.ht_cap_elem, &sta->sta.ht_cap);
@ -2222,7 +2227,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_QOS; changed |= BSS_CHANGED_QOS;
if (elems.ht_operation && elems.wmm_param && if (elems.ht_operation && elems.wmm_param &&
!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
cbss->bssid, false); cbss->bssid, false);
@ -2473,11 +2478,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
return; return;
} }
if (rx_status->freq != chanctx_conf->channel->center_freq) { if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
chan = chanctx_conf->channel; chan = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
@ -2658,7 +2663,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
bssid, true); bssid, true);
@ -3188,6 +3193,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
const u8 *ht_oper_ie; const u8 *ht_oper_ie;
const struct ieee80211_ht_operation *ht_oper = NULL; const struct ieee80211_ht_operation *ht_oper = NULL;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct cfg80211_chan_def chandef;
sband = local->hw.wiphy->bands[cbss->channel->band]; sband = local->hw.wiphy->bands[cbss->channel->band];
@ -3219,12 +3225,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
ht_cfreq, ht_oper->primary_chan, ht_cfreq, ht_oper->primary_chan,
cbss->channel->band); cbss->channel->band);
ht_oper = NULL; ht_oper = NULL;
} else {
channel_type = NL80211_CHAN_HT20;
} }
} }
if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { if (ht_oper) {
/* /*
* cfg80211 already verified that the channel itself can * cfg80211 already verified that the channel itself can
* be used, but it didn't check that we can do the right * be used, but it didn't check that we can do the right
@ -3237,19 +3241,26 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
channel_type = NL80211_CHAN_HT20; channel_type = NL80211_CHAN_HT20;
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: switch (ht_oper->ht_param &
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
else if (cbss->channel->flags &
channel_type = NL80211_CHAN_HT40PLUS; IEEE80211_CHAN_NO_HT40PLUS)
break; ifmgd->flags |=
case IEEE80211_HT_PARAM_CHA_SEC_BELOW: IEEE80211_STA_DISABLE_40MHZ;
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) else
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; channel_type = NL80211_CHAN_HT40PLUS;
else break;
channel_type = NL80211_CHAN_HT40MINUS; case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
break; if (cbss->channel->flags &
IEEE80211_CHAN_NO_HT40MINUS)
ifmgd->flags |=
IEEE80211_STA_DISABLE_40MHZ;
else
channel_type = NL80211_CHAN_HT40MINUS;
break;
}
} }
ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
@ -3262,13 +3273,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
sdata->needed_rx_chains = min(chains, local->rx_chains); sdata->needed_rx_chains = min(chains, local->rx_chains);
} else { } else {
sdata->needed_rx_chains = 1; sdata->needed_rx_chains = 1;
sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT;
} }
/* will change later if needed */ /* will change later if needed */
sdata->smps_mode = IEEE80211_SMPS_OFF; sdata->smps_mode = IEEE80211_SMPS_OFF;
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, cfg80211_chandef_create(&chandef, cbss->channel, channel_type);
return ieee80211_vif_use_channel(sdata, &chandef,
IEEE80211_CHANCTX_SHARED); IEEE80211_CHANCTX_SHARED);
} }
@ -3530,13 +3543,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
/* prepare assoc data */ /* prepare assoc data */
/*
* keep only the 40 MHz disable bit set as it might have
* been set during authentication already, all other bits
* should be reset for a new connection
*/
ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ;
ifmgd->beacon_crc_valid = false; ifmgd->beacon_crc_valid = false;
/* /*
@ -3550,7 +3556,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
netdev_info(sdata->dev, netdev_info(sdata->dev,
"disabling HT/VHT due to WEP/TKIP use\n"); "disabling HT/VHT due to WEP/TKIP use\n");
@ -3558,7 +3564,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
} }
if (req->flags & ASSOC_REQ_DISABLE_HT) { if (req->flags & ASSOC_REQ_DISABLE_HT) {
ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
} }
@ -3566,7 +3572,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[req->bss->channel->band]; sband = local->hw.wiphy->bands[req->bss->channel->band];
if (!sband->ht_cap.ht_supported || if (!sband->ht_cap.ht_supported ||
local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
if (!bss->wmm_used) if (!bss->wmm_used)
netdev_info(sdata->dev, netdev_info(sdata->dev,
"disabling HT as WMM/QoS is not supported by the AP\n"); "disabling HT as WMM/QoS is not supported by the AP\n");
@ -3611,7 +3617,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->ap_ht_param = assoc_data->ap_ht_param =
((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
else else
ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
if (bss->wmm_used && bss->uapsd_supported && if (bss->wmm_used && bss->uapsd_supported &&
(sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {

View File

@ -205,8 +205,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
} }
} else { } else {
cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie,
roc->chan, roc->chan_type, roc->chan, roc->req_duration,
roc->req_duration, GFP_KERNEL); GFP_KERNEL);
} }
roc->notified = true; roc->notified = true;
@ -284,7 +284,6 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
duration = 10; duration = 10;
ret = drv_remain_on_channel(local, roc->sdata, roc->chan, ret = drv_remain_on_channel(local, roc->sdata, roc->chan,
roc->chan_type,
duration); duration);
roc->started = true; roc->started = true;
@ -321,7 +320,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
if (!roc->mgmt_tx_cookie) if (!roc->mgmt_tx_cookie)
cfg80211_remain_on_channel_expired(&roc->sdata->wdev, cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
roc->cookie, roc->chan, roc->cookie, roc->chan,
roc->chan_type, GFP_KERNEL); GFP_KERNEL);
list_for_each_entry_safe(dep, tmp, &roc->dependents, list) list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
ieee80211_roc_notify_destroy(dep); ieee80211_roc_notify_destroy(dep);
@ -359,7 +358,6 @@ void ieee80211_sw_roc_work(struct work_struct *work)
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
local->tmp_channel = roc->chan; local->tmp_channel = roc->chan;
local->tmp_channel_type = roc->chan_type;
ieee80211_hw_config(local, 0); ieee80211_hw_config(local, 0);
/* tell userspace or send frame */ /* tell userspace or send frame */

View File

@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
return; return;
/* if HT BSS, and we handle a data frame, also try HT rates */ /* if HT BSS, and we handle a data frame, also try HT rates */
if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return; return;
fc = hdr->frame_control; fc = hdr->frame_control;
@ -408,8 +408,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
alt_rate.flags |= IEEE80211_TX_RC_MCS; alt_rate.flags |= IEEE80211_TX_RC_MCS;
if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40)
(txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS))
alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {

View File

@ -65,7 +65,7 @@ static inline void rate_control_rate_init(struct sta_info *sta)
return; return;
} }
sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
rcu_read_unlock(); rcu_read_unlock();
ref->ops->rate_init(ref->priv, sband, ista, priv_sta); ref->ops->rate_init(ref->priv, sband, ista, priv_sta);

View File

@ -62,13 +62,16 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len)
{ {
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr;
hdr = (void *)(skb->data + status->vendor_radiotap_len);
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
RX_FLAG_FAILED_PLCP_CRC | RX_FLAG_FAILED_PLCP_CRC |
RX_FLAG_AMPDU_IS_ZEROLEN)) RX_FLAG_AMPDU_IS_ZEROLEN))
return 1; return 1;
if (unlikely(skb->len < 16 + present_fcs_len)) if (unlikely(skb->len < 16 + present_fcs_len +
status->vendor_radiotap_len))
return 1; return 1;
if (ieee80211_is_ctl(hdr->frame_control) && if (ieee80211_is_ctl(hdr->frame_control) &&
!ieee80211_is_pspoll(hdr->frame_control) && !ieee80211_is_pspoll(hdr->frame_control) &&
@ -190,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++; pos++;
/* IEEE80211_RADIOTAP_RATE */ /* IEEE80211_RADIOTAP_RATE */
if (!rate || status->flag & RX_FLAG_HT) { if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
/* /*
* Without rate information don't add it. If we have, * Without rate information don't add it. If we have,
* MCS information is a separate field in radiotap, * MCS information is a separate field in radiotap,
@ -210,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
if (status->band == IEEE80211_BAND_5GHZ) if (status->band == IEEE80211_BAND_5GHZ)
put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
pos); pos);
else if (status->flag & RX_FLAG_HT) else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
pos); pos);
else if (rate && rate->flags & IEEE80211_RATE_ERP_G) else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
@ -341,8 +344,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN; present_fcs_len = FCS_LEN;
/* make sure hdr->frame_control is on the linear part */ /* ensure hdr->frame_control and vendor radiotap data are in skb head */
if (!pskb_may_pull(origskb, 2)) { if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) {
dev_kfree_skb(origskb); dev_kfree_skb(origskb);
return NULL; return NULL;
} }
@ -1338,17 +1341,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
/* /*
* Update last_rx only for IBSS packets which are for the current * Update last_rx only for IBSS packets which are for the current
* BSSID to avoid keeping the current IBSS network alive in cases * BSSID and for station already AUTHORIZED to avoid keeping the
* where other STAs start using different BSSID. * current IBSS network alive in cases where other STAs start
* using different BSSID. This will also give the station another
* chance to restart the authentication/authorization in case
* something went wrong the first time.
*/ */
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
NL80211_IFTYPE_ADHOC); NL80211_IFTYPE_ADHOC);
if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid)) { if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
sta->last_rx = jiffies; sta->last_rx = jiffies;
if (ieee80211_is_data(hdr->frame_control)) { if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag; sta->last_rx_rate_flag = status->flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
} }
} }
} else if (!is_multicast_ether_addr(hdr->addr1)) { } else if (!is_multicast_ether_addr(hdr->addr1)) {
@ -1360,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) { if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag; sta->last_rx_rate_flag = status->flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
} }
} }
@ -2703,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
status = IEEE80211_SKB_RXCB((rx->skb)); status = IEEE80211_SKB_RXCB((rx->skb));
sband = rx->local->hw.wiphy->bands[status->band]; sband = rx->local->hw.wiphy->bands[status->band];
if (!(status->flag & RX_FLAG_HT)) if (!(status->flag & RX_FLAG_HT) &&
!(status->flag & RX_FLAG_VHT))
rate = &sband->bitrates[status->rate_idx]; rate = &sband->bitrates[status->rate_idx];
ieee80211_rx_cooked_monitor(rx, rate); ieee80211_rx_cooked_monitor(rx, rate);
@ -2870,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
status->rx_flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta) { } else if (!rx->sta) {
int rate_idx; int rate_idx;
if (status->flag & RX_FLAG_HT) if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
rate_idx = 0; /* TODO: HT rates */ rate_idx = 0; /* TODO: HT/VHT rates */
else else
rate_idx = status->rate_idx; rate_idx = status->rate_idx;
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
@ -3147,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
status->rate_idx, status->rate_idx,
status->rate_idx)) status->rate_idx))
goto drop; goto drop;
} else if (status->flag & RX_FLAG_VHT) {
if (WARN_ONCE(status->rate_idx > 9 ||
!status->vht_nss ||
status->vht_nss > 8,
"Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
status->rate_idx, status->vht_nss))
goto drop;
} else { } else {
if (WARN_ON(status->rate_idx >= sband->n_bitrates)) if (WARN_ON(status->rate_idx >= sband->n_bitrates))
goto drop; goto drop;

View File

@ -174,7 +174,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
u8 *elements; u8 *elements;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
size_t baselen; size_t baselen;
int freq;
bool beacon; bool beacon;
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
@ -209,13 +208,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
ieee802_11_parse_elems(elements, skb->len - baselen, &elems); ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
if (elems.ds_params && elems.ds_params_len == 1) channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
freq = ieee80211_channel_to_frequency(elems.ds_params[0],
rx_status->band);
else
freq = rx_status->freq;
channel = ieee80211_get_channel(local->hw.wiphy, freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return; return;

View File

@ -1092,7 +1092,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
return; return;
} }
ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band);
rcu_read_unlock(); rcu_read_unlock();
} }

View File

@ -227,6 +227,7 @@ struct sta_ampdu_mlme {
* "the" transmit rate * "the" transmit rate
* @last_rx_rate_idx: rx status rate index of the last data packet * @last_rx_rate_idx: rx status rate index of the last data packet
* @last_rx_rate_flag: rx status flag of the last data packet * @last_rx_rate_flag: rx status flag of the last data packet
* @last_rx_rate_vht_nss: rx status nss of last data packet
* @lock: used for locking all fields that require locking, see comments * @lock: used for locking all fields that require locking, see comments
* in the header file. * in the header file.
* @drv_unblock_wk: used for driver PS unblocking * @drv_unblock_wk: used for driver PS unblocking
@ -272,7 +273,7 @@ struct sta_ampdu_mlme {
* @t_offset: timing offset relative to this host * @t_offset: timing offset relative to this host
* @t_offset_setpoint: reference timing offset of this sta to be used when * @t_offset_setpoint: reference timing offset of this sta to be used when
* calculating clockdrift * calculating clockdrift
* @ch_type: peer's channel type * @ch_width: peer's channel width
* @debugfs: debug filesystem info * @debugfs: debug filesystem info
* @dead: set to true when sta is unlinked * @dead: set to true when sta is unlinked
* @uploaded: set to true when sta is uploaded to the driver * @uploaded: set to true when sta is uploaded to the driver
@ -343,7 +344,8 @@ struct sta_info {
unsigned long tx_fragments; unsigned long tx_fragments;
struct ieee80211_tx_rate last_tx_rate; struct ieee80211_tx_rate last_tx_rate;
int last_rx_rate_idx; int last_rx_rate_idx;
int last_rx_rate_flag; u32 last_rx_rate_flag;
u8 last_rx_rate_vht_nss;
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
/* /*
@ -368,7 +370,7 @@ struct sta_info {
struct timer_list plink_timer; struct timer_list plink_timer;
s64 t_offset; s64 t_offset;
s64 t_offset_setpoint; s64 t_offset_setpoint;
enum nl80211_channel_type ch_type; enum nl80211_chan_width ch_width;
#endif #endif
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS

View File

@ -28,16 +28,21 @@
#define VIF_PR_FMT " vif:%s(%d%s)" #define VIF_PR_FMT " vif:%s(%d%s)"
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
#define CHANCTX_ENTRY __field(int, freq) \ #define CHANCTX_ENTRY __field(u32, control_freq) \
__field(int, chantype) \ __field(u32, chan_width) \
__field(u32, center_freq1) \
__field(u32, center_freq2) \
__field(u8, rx_chains_static) \ __field(u8, rx_chains_static) \
__field(u8, rx_chains_dynamic) __field(u8, rx_chains_dynamic)
#define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq; \ #define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\
__entry->chantype = ctx->conf.channel_type; \ __entry->chan_width = ctx->conf.def.width; \
__entry->center_freq1 = ctx->conf.def.center_freq1; \
__entry->center_freq2 = ctx->conf.def.center_freq2; \
__entry->rx_chains_static = ctx->conf.rx_chains_static; \ __entry->rx_chains_static = ctx->conf.rx_chains_static; \
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
#define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d" #define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d"
#define CHANCTX_PR_ARG __entry->freq, __entry->chantype, \ #define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \
__entry->center_freq1, __entry->center_freq2, \
__entry->rx_chains_static, __entry->rx_chains_dynamic __entry->rx_chains_static, __entry->rx_chains_dynamic
@ -334,7 +339,8 @@ TRACE_EVENT(drv_bss_info_changed,
__field(u16, ht_operation_mode) __field(u16, ht_operation_mode)
__field(s32, cqm_rssi_thold); __field(s32, cqm_rssi_thold);
__field(s32, cqm_rssi_hyst); __field(s32, cqm_rssi_hyst);
__field(u32, channel_type); __field(u32, channel_width);
__field(u32, channel_cfreq1);
__dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt);
__field(bool, arp_filter_enabled); __field(bool, arp_filter_enabled);
__field(bool, qos); __field(bool, qos);
@ -370,7 +376,8 @@ TRACE_EVENT(drv_bss_info_changed,
__entry->ht_operation_mode = info->ht_operation_mode; __entry->ht_operation_mode = info->ht_operation_mode;
__entry->cqm_rssi_thold = info->cqm_rssi_thold; __entry->cqm_rssi_thold = info->cqm_rssi_thold;
__entry->cqm_rssi_hyst = info->cqm_rssi_hyst; __entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
__entry->channel_type = info->channel_type; __entry->channel_width = info->chandef.width;
__entry->channel_cfreq1 = info->chandef.center_freq1;
memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
sizeof(u32) * info->arp_addr_cnt); sizeof(u32) * info->arp_addr_cnt);
__entry->arp_filter_enabled = info->arp_filter_enabled; __entry->arp_filter_enabled = info->arp_filter_enabled;
@ -1022,15 +1029,14 @@ TRACE_EVENT(drv_remain_on_channel,
TP_PROTO(struct ieee80211_local *local, TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type chantype, unsigned int duration), unsigned int duration),
TP_ARGS(local, sdata, chan, chantype, duration), TP_ARGS(local, sdata, chan, duration),
TP_STRUCT__entry( TP_STRUCT__entry(
LOCAL_ENTRY LOCAL_ENTRY
VIF_ENTRY VIF_ENTRY
__field(int, center_freq) __field(int, center_freq)
__field(int, channel_type)
__field(unsigned int, duration) __field(unsigned int, duration)
), ),
@ -1038,7 +1044,6 @@ TRACE_EVENT(drv_remain_on_channel,
LOCAL_ASSIGN; LOCAL_ASSIGN;
VIF_ASSIGN; VIF_ASSIGN;
__entry->center_freq = chan->center_freq; __entry->center_freq = chan->center_freq;
__entry->channel_type = chantype;
__entry->duration = duration; __entry->duration = duration;
), ),

View File

@ -1676,7 +1676,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
chan = chanctx_conf->channel; chan = chanctx_conf->def.chan;
/* /*
* Frame injection is not allowed if beaconing is not allowed * Frame injection is not allowed if beaconing is not allowed
@ -1779,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
if (sta) if (sta)
break; break;
/* fall through */ /* fall through */
@ -1794,7 +1794,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
break; break;
case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_WDS:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@ -1871,7 +1871,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
break; break;
#endif #endif
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
@ -1930,7 +1930,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */ /* DA SA BSSID */
@ -1941,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) if (!chanctx_conf)
goto fail_rcu; goto fail_rcu;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
break; break;
default: default:
goto fail_rcu; goto fail_rcu;
@ -2194,7 +2194,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
return true; return true;
} }
result = ieee80211_tx(sdata, skb, true, result = ieee80211_tx(sdata, skb, true,
chanctx_conf->channel->band); chanctx_conf->def.chan->band);
} else { } else {
struct sk_buff_head skbs; struct sk_buff_head skbs;
@ -2458,7 +2458,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
*pos++ = WLAN_EID_SSID; *pos++ = WLAN_EID_SSID;
*pos++ = 0x0; *pos++ = 0x0;
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
if (ieee80211_add_srates_ie(sdata, skb, true, band) || if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
mesh_add_ds_params_ie(skb, sdata) || mesh_add_ds_params_ie(skb, sdata) ||
@ -2477,7 +2477,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
goto out; goto out;
} }
band = chanctx_conf->channel->band; band = chanctx_conf->def.chan->band;
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
@ -2757,7 +2757,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
tx.flags |= IEEE80211_TX_PS_BUFFERED; tx.flags |= IEEE80211_TX_PS_BUFFERED;
info->band = chanctx_conf->channel->band; info->band = chanctx_conf->def.chan->band;
if (invoke_tx_handlers(&tx)) if (invoke_tx_handlers(&tx))
skb = NULL; skb = NULL;

View File

@ -898,7 +898,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
rcu_read_lock(); rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
use_11b = (chanctx_conf && use_11b = (chanctx_conf &&
chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) &&
!(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
rcu_read_unlock(); rcu_read_unlock();
@ -991,7 +991,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (chanctx_conf && if (chanctx_conf &&
chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ &&
have_higher_than_11mbit) have_higher_than_11mbit)
sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
else else
@ -1873,8 +1873,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
} }
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel, const struct cfg80211_chan_def *chandef,
enum nl80211_channel_type channel_type,
u16 prot_mode) u16 prot_mode)
{ {
struct ieee80211_ht_operation *ht_oper; struct ieee80211_ht_operation *ht_oper;
@ -1882,23 +1881,25 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
*pos++ = WLAN_EID_HT_OPERATION; *pos++ = WLAN_EID_HT_OPERATION;
*pos++ = sizeof(struct ieee80211_ht_operation); *pos++ = sizeof(struct ieee80211_ht_operation);
ht_oper = (struct ieee80211_ht_operation *)pos; ht_oper = (struct ieee80211_ht_operation *)pos;
ht_oper->primary_chan = ht_oper->primary_chan = ieee80211_frequency_to_channel(
ieee80211_frequency_to_channel(channel->center_freq); chandef->chan->center_freq);
switch (channel_type) { switch (chandef->width) {
case NL80211_CHAN_HT40MINUS: case NL80211_CHAN_WIDTH_160:
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_40:
if (chandef->center_freq1 > chandef->chan->center_freq)
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
else
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break; break;
case NL80211_CHAN_HT40PLUS:
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
break;
case NL80211_CHAN_HT20:
default: default:
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
break; break;
} }
if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
channel_type != NL80211_CHAN_NO_HT && chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
channel_type != NL80211_CHAN_HT20) chandef->width != NL80211_CHAN_WIDTH_20)
ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
ht_oper->operation_mode = cpu_to_le16(prot_mode); ht_oper->operation_mode = cpu_to_le16(prot_mode);
@ -1912,13 +1913,17 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
return pos + sizeof(struct ieee80211_ht_operation); return pos + sizeof(struct ieee80211_ht_operation);
} }
enum nl80211_channel_type void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) struct ieee80211_ht_operation *ht_oper,
struct cfg80211_chan_def *chandef)
{ {
enum nl80211_channel_type channel_type; enum nl80211_channel_type channel_type;
if (!ht_oper) if (!ht_oper) {
return NL80211_CHAN_NO_HT; cfg80211_chandef_create(chandef, control_chan,
NL80211_CHAN_NO_HT);
return;
}
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_NONE: case IEEE80211_HT_PARAM_CHA_SEC_NONE:
@ -1934,7 +1939,7 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
channel_type = NL80211_CHAN_NO_HT; channel_type = NL80211_CHAN_NO_HT;
} }
return channel_type; cfg80211_chandef_create(chandef, control_chan, channel_type);
} }
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
@ -2066,6 +2071,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (status->flag & RX_FLAG_SHORT_GI) if (status->flag & RX_FLAG_SHORT_GI)
ri.flags |= RATE_INFO_FLAGS_SHORT_GI; ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
} else if (status->flag & RX_FLAG_VHT) {
ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
ri.mcs = status->rate_idx;
ri.nss = status->vht_nss;
if (status->flag & RX_FLAG_40MHZ)
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (status->flag & RX_FLAG_80MHZ)
ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
if (status->flag & RX_FLAG_80P80MHZ)
ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
if (status->flag & RX_FLAG_160MHZ)
ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
if (status->flag & RX_FLAG_SHORT_GI)
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
} else { } else {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;

View File

@ -160,31 +160,37 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
return ieee80211_downgrade_queue(sdata, skb); return ieee80211_downgrade_queue(sdata, skb);
} }
/**
* ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
*
* @sdata: local subif
* @skb: packet to be updated
*/
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *p;
u8 ack_policy, tid;
/* Fill in the QoS header if there is one. */ if (!ieee80211_is_data_qos(hdr->frame_control))
if (ieee80211_is_data_qos(hdr->frame_control)) { return;
u8 *p = ieee80211_get_qos_ctl(hdr);
u8 ack_policy, tid;
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; p = ieee80211_get_qos_ctl(hdr);
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
/* preserve EOSP bit */ /* preserve EOSP bit */
ack_policy = *p & IEEE80211_QOS_CTL_EOSP; ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
if (is_multicast_ether_addr(hdr->addr1) || if (is_multicast_ether_addr(hdr->addr1) ||
sdata->noack_map & BIT(tid)) { sdata->noack_map & BIT(tid)) {
ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
info->flags |= IEEE80211_TX_CTL_NO_ACK; info->flags |= IEEE80211_TX_CTL_NO_ACK;
}
/* qos header is 2 bytes */
*p++ = ack_policy | tid;
*p = ieee80211_vif_is_mesh(&sdata->vif) ?
(IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
} }
/* qos header is 2 bytes */
*p++ = ack_policy | tid;
*p = ieee80211_vif_is_mesh(&sdata->vif) ?
(IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
} }

View File

@ -11,96 +11,264 @@
#include "core.h" #include "core.h"
#include "rdev-ops.h" #include "rdev-ops.h"
struct ieee80211_channel * void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
rdev_freq_to_chan(struct cfg80211_registered_device *rdev, struct ieee80211_channel *chan,
int freq, enum nl80211_channel_type channel_type) enum nl80211_channel_type chan_type)
{ {
struct ieee80211_channel *chan; if (WARN_ON(!chan))
struct ieee80211_sta_ht_cap *ht_cap; return;
chan = ieee80211_get_channel(&rdev->wiphy, freq); chandef->chan = chan;
chandef->center_freq2 = 0;
/* Primary channel not allowed */ switch (chan_type) {
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) case NL80211_CHAN_NO_HT:
return NULL; chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = chan->center_freq;
if (channel_type == NL80211_CHAN_HT40MINUS && break;
chan->flags & IEEE80211_CHAN_NO_HT40MINUS) case NL80211_CHAN_HT20:
return NULL; chandef->width = NL80211_CHAN_WIDTH_20;
else if (channel_type == NL80211_CHAN_HT40PLUS && chandef->center_freq1 = chan->center_freq;
chan->flags & IEEE80211_CHAN_NO_HT40PLUS) break;
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;
int diff;
trace_cfg80211_can_beacon_sec_chan(wiphy, chan, channel_type);
switch (channel_type) {
case NL80211_CHAN_HT40PLUS: case NL80211_CHAN_HT40PLUS:
diff = 20; chandef->width = NL80211_CHAN_WIDTH_40;
chandef->center_freq1 = chan->center_freq + 10;
break; break;
case NL80211_CHAN_HT40MINUS: case NL80211_CHAN_HT40MINUS:
diff = -20; chandef->width = NL80211_CHAN_WIDTH_40;
chandef->center_freq1 = chan->center_freq - 10;
break; break;
default: default:
trace_cfg80211_return_bool(true); WARN_ON(1);
return true;
} }
}
EXPORT_SYMBOL(cfg80211_chandef_create);
sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
if (!sec_chan) { {
trace_cfg80211_return_bool(false); u32 control_freq;
if (!chandef->chan)
return false;
control_freq = chandef->chan->center_freq;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
if (chandef->center_freq1 != control_freq)
return false;
if (chandef->center_freq2)
return false;
break;
case NL80211_CHAN_WIDTH_40:
if (chandef->center_freq1 != control_freq + 10 &&
chandef->center_freq1 != control_freq - 10)
return false;
if (chandef->center_freq2)
return false;
break;
case NL80211_CHAN_WIDTH_80P80:
if (chandef->center_freq1 != control_freq + 30 &&
chandef->center_freq1 != control_freq + 10 &&
chandef->center_freq1 != control_freq - 10 &&
chandef->center_freq1 != control_freq - 30)
return false;
if (!chandef->center_freq2)
return false;
break;
case NL80211_CHAN_WIDTH_80:
if (chandef->center_freq1 != control_freq + 30 &&
chandef->center_freq1 != control_freq + 10 &&
chandef->center_freq1 != control_freq - 10 &&
chandef->center_freq1 != control_freq - 30)
return false;
if (chandef->center_freq2)
return false;
break;
case NL80211_CHAN_WIDTH_160:
if (chandef->center_freq1 != control_freq + 70 &&
chandef->center_freq1 != control_freq + 50 &&
chandef->center_freq1 != control_freq + 30 &&
chandef->center_freq1 != control_freq + 10 &&
chandef->center_freq1 != control_freq - 10 &&
chandef->center_freq1 != control_freq - 30 &&
chandef->center_freq1 != control_freq - 50 &&
chandef->center_freq1 != control_freq - 70)
return false;
if (chandef->center_freq2)
return false;
break;
default:
return false; return false;
} }
/* we'll need a DFS capability later */
if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
IEEE80211_CHAN_PASSIVE_SCAN |
IEEE80211_CHAN_NO_IBSS |
IEEE80211_CHAN_RADAR)) {
trace_cfg80211_return_bool(false);
return false;
}
trace_cfg80211_return_bool(true);
return true; return true;
} }
EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
int *pri40, int *pri80)
{
int tmp;
switch (c->width) {
case NL80211_CHAN_WIDTH_40:
*pri40 = c->center_freq1;
*pri80 = 0;
break;
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
*pri80 = c->center_freq1;
/* n_P20 */
tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
/* n_P40 */
tmp /= 2;
/* freq_P40 */
*pri40 = c->center_freq1 - 20 + 40 * tmp;
break;
case NL80211_CHAN_WIDTH_160:
/* n_P20 */
tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
/* n_P40 */
tmp /= 2;
/* freq_P40 */
*pri40 = c->center_freq1 - 60 + 40 * tmp;
/* n_P80 */
tmp /= 2;
*pri80 = c->center_freq1 - 40 + 80 * tmp;
break;
default:
WARN_ON_ONCE(1);
}
}
const struct cfg80211_chan_def *
cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
const struct cfg80211_chan_def *c2)
{
u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80;
/* If they are identical, return */
if (cfg80211_chandef_identical(c1, c2))
return c1;
/* otherwise, must have same control channel */
if (c1->chan != c2->chan)
return NULL;
/*
* If they have the same width, but aren't identical,
* then they can't be compatible.
*/
if (c1->width == c2->width)
return NULL;
if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
c1->width == NL80211_CHAN_WIDTH_20)
return c2;
if (c2->width == NL80211_CHAN_WIDTH_20_NOHT ||
c2->width == NL80211_CHAN_WIDTH_20)
return c1;
chandef_primary_freqs(c1, &c1_pri40, &c1_pri80);
chandef_primary_freqs(c2, &c2_pri40, &c2_pri80);
if (c1_pri40 != c2_pri40)
return NULL;
WARN_ON(!c1_pri80 && !c2_pri80);
if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80)
return NULL;
if (c1->width > c2->width)
return c1;
return c2;
}
EXPORT_SYMBOL(cfg80211_chandef_compatible);
bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
u32 prohibited_flags)
{
struct ieee80211_channel *c;
u32 freq;
for (freq = center_freq - bandwidth/2 + 10;
freq <= center_freq + bandwidth/2 - 10;
freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c || c->flags & prohibited_flags)
return false;
}
return true;
}
static bool cfg80211_check_beacon_chans(struct wiphy *wiphy,
u32 center_freq, u32 bw)
{
return cfg80211_secondary_chans_ok(wiphy, center_freq, bw,
IEEE80211_CHAN_DISABLED |
IEEE80211_CHAN_PASSIVE_SCAN |
IEEE80211_CHAN_NO_IBSS |
IEEE80211_CHAN_RADAR);
}
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
{
u32 width;
bool res;
trace_cfg80211_reg_can_beacon(wiphy, chandef);
if (WARN_ON(!cfg80211_chan_def_valid(chandef))) {
trace_cfg80211_return_bool(false);
return false;
}
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
width = 20;
break;
case NL80211_CHAN_WIDTH_40:
width = 40;
break;
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
width = 160;
break;
default:
WARN_ON_ONCE(1);
trace_cfg80211_return_bool(false);
return false;
}
res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width);
if (res && chandef->center_freq2)
res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2,
width);
trace_cfg80211_return_bool(res);
return res;
}
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

View File

@ -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,
@ -378,10 +378,8 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie);
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie);
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
const struct ieee80211_ht_cap *ht_capa_mask); const struct ieee80211_ht_cap *ht_capa_mask);
@ -472,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,
@ -488,6 +483,12 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num); enum nl80211_iftype iftype, int num);
bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef);
bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
u32 prohibited_flags);
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS

View File

@ -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.width = NL80211_CHAN_WIDTH_20_NOHT;
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.width = NL80211_CHAN_WIDTH_20_NOHT;
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) {

View File

@ -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.width = NL80211_CHAN_WIDTH_20_NOHT;;
} }
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->width != NL80211_CHAN_WIDTH_20_NOHT)
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;
} }

View File

@ -579,31 +579,25 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp) unsigned int duration, gfp_t gfp)
{ {
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);
trace_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
duration); nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp);
nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
duration, gfp);
} }
EXPORT_SYMBOL(cfg80211_ready_on_channel); EXPORT_SYMBOL(cfg80211_ready_on_channel);
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
gfp_t gfp) gfp_t gfp)
{ {
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);
trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan, trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
channel_type); nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp);
nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
channel_type, gfp);
} }
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
@ -758,10 +752,8 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie)
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
const struct ieee80211_mgmt *mgmt; const struct ieee80211_mgmt *mgmt;
u16 stype; u16 stype;
@ -855,7 +847,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
/* Transmit the Action frame as requested by user space */ /* Transmit the Action frame as requested by user space */
return rdev_mgmt_tx(rdev, wdev, chan, offchan, return rdev_mgmt_tx(rdev, wdev, chan, offchan,
channel_type, channel_type_valid,
wait, buf, len, no_cck, dont_wait_for_ack, wait, buf, len, no_cck, dont_wait_for_ack,
cookie); cookie);
} }
@ -997,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);
@ -1013,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;

View File

@ -223,8 +223,13 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
.len = 20-1 }, .len = 20-1 },
[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
[NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
@ -1360,51 +1365,139 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
wdev->iftype == NL80211_IFTYPE_P2P_GO; wdev->iftype == NL80211_IFTYPE_P2P_GO;
} }
static bool nl80211_valid_channel_type(struct genl_info *info, static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
enum nl80211_channel_type *channel_type) struct genl_info *info,
struct cfg80211_chan_def *chandef)
{ {
enum nl80211_channel_type tmp; struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
u32 control_freq, width;
if (!info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
return false; return -EINVAL;
tmp = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
if (tmp != NL80211_CHAN_NO_HT &&
tmp != NL80211_CHAN_HT20 &&
tmp != NL80211_CHAN_HT40PLUS &&
tmp != NL80211_CHAN_HT40MINUS)
return false;
if (channel_type) chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
*channel_type = tmp; chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = control_freq;
chandef->center_freq2 = 0;
return true; /* Primary channel not allowed */
if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
return -EINVAL;
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
enum nl80211_channel_type chantype;
chantype = nla_get_u32(
info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
switch (chantype) {
case NL80211_CHAN_NO_HT:
case NL80211_CHAN_HT20:
case NL80211_CHAN_HT40PLUS:
case NL80211_CHAN_HT40MINUS:
cfg80211_chandef_create(chandef, chandef->chan,
chantype);
break;
default:
return -EINVAL;
}
} else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
chandef->width =
nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
chandef->center_freq1 =
nla_get_u32(
info->attrs[NL80211_ATTR_CENTER_FREQ1]);
if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
chandef->center_freq2 =
nla_get_u32(
info->attrs[NL80211_ATTR_CENTER_FREQ2]);
}
ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap;
vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
if (!cfg80211_chan_def_valid(chandef))
return -EINVAL;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20:
if (!ht_cap->ht_supported)
return -EINVAL;
case NL80211_CHAN_WIDTH_20_NOHT:
width = 20;
break;
case NL80211_CHAN_WIDTH_40:
width = 40;
/* quick early regulatory check */
if (chandef->center_freq1 < control_freq &&
chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
return -EINVAL;
if (chandef->center_freq1 > control_freq &&
chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
return -EINVAL;
if (!ht_cap->ht_supported)
return -EINVAL;
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
return -EINVAL;
break;
case NL80211_CHAN_WIDTH_80:
width = 80;
if (!vht_cap->vht_supported)
return -EINVAL;
break;
case NL80211_CHAN_WIDTH_80P80:
width = 80;
if (!vht_cap->vht_supported)
return -EINVAL;
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
return -EINVAL;
break;
case NL80211_CHAN_WIDTH_160:
width = 160;
if (!vht_cap->vht_supported)
return -EINVAL;
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
return -EINVAL;
break;
default:
return -EINVAL;
}
if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1,
width, IEEE80211_CHAN_DISABLED))
return -EINVAL;
if (chandef->center_freq2 &&
!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2,
width, IEEE80211_CHAN_DISABLED))
return -EINVAL;
/* TODO: missing regulatory check on bandwidth */
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 +1507,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 +1838,35 @@ 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)
{
WARN_ON(!cfg80211_chan_def_valid(chandef));
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
chandef->chan->center_freq))
return -ENOBUFS;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_40:
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
cfg80211_get_chandef_type(chandef)))
return -ENOBUFS;
break;
default:
break;
}
if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
return -ENOBUFS;
if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
return -ENOBUFS;
if (chandef->center_freq2 &&
nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
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 +1893,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 +2608,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 +2733,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, &params.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, &params)) } else if (!nl80211_get_ap_channel(rdev, &params))
return -EINVAL; return -EINVAL;
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.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 +2754,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
err = rdev_start_ap(rdev, dev, &params); err = rdev_start_ap(rdev, dev, &params);
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);
} }
@ -2787,29 +2890,52 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
rate = nla_nest_start(msg, attr); rate = nla_nest_start(msg, attr);
if (!rate) if (!rate)
goto nla_put_failure; return false;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info); bitrate = cfg80211_calculate_bitrate(info);
/* report 16-bit bitrate only if we can */ /* report 16-bit bitrate only if we can */
bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
if ((bitrate > 0 && if (bitrate > 0 &&
nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) || nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
(bitrate_compat > 0 && return false;
nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) || if (bitrate_compat > 0 &&
((info->flags & RATE_INFO_FLAGS_MCS) && nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || return false;
((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) || if (info->flags & RATE_INFO_FLAGS_MCS) {
((info->flags & RATE_INFO_FLAGS_SHORT_GI) && if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))) return false;
goto nla_put_failure; if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
return false;
if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
return false;
} else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
return false;
if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
return false;
if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
return false;
if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH &&
nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH))
return false;
if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH &&
nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH))
return false;
if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH &&
nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH))
return false;
if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
return false;
}
nla_nest_end(msg, rate); nla_nest_end(msg, rate);
return true; return true;
nla_put_failure:
return false;
} }
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
@ -5330,8 +5456,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,35 +5491,17 @@ 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; return -EINVAL;
/* Both channels should be able to initiate communication */ if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
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;
if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
@ -5405,7 +5512,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 +5534,8 @@ 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.width != NL80211_CHAN_WIDTH_20_NOHT) &&
no_ht) {
kfree(connkeys); kfree(connkeys);
return -EINVAL; return -EINVAL;
} }
@ -5948,12 +6056,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;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; u32 duration;
u32 freq, duration;
int err; int err;
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
@ -5974,14 +6081,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, &channel_type)) if (err)
return -EINVAL; return err;
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
chan = rdev_freq_to_chan(rdev, freq, channel_type);
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)
@ -5995,8 +6097,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, channel_type, duration, err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
&cookie); duration, &cookie);
if (err) if (err)
goto free_msg; goto free_msg;
@ -6215,10 +6317,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;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
bool channel_type_valid = false;
u32 freq;
int err; int err;
void *hdr = NULL; void *hdr = NULL;
u64 cookie; u64 cookie;
@ -6228,8 +6327,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)
@ -6264,12 +6362,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
} }
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
if (!nl80211_valid_channel_type(info, &channel_type))
return -EINVAL;
channel_type_valid = true;
}
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))
@ -6277,10 +6369,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, channel_type); 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);
@ -6296,8 +6387,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
} }
} }
err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type, err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
channel_type_valid, 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);
@ -6561,21 +6651,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);
@ -8395,7 +8476,6 @@ static void nl80211_send_remain_on_chan_event(
int cmd, struct cfg80211_registered_device *rdev, int cmd, struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie, struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp) unsigned int duration, gfp_t gfp)
{ {
struct sk_buff *msg; struct sk_buff *msg;
@ -8416,7 +8496,8 @@ static void nl80211_send_remain_on_chan_event(
wdev->netdev->ifindex)) || wdev->netdev->ifindex)) ||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) || nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
NL80211_CHAN_NO_HT) ||
nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
goto nla_put_failure; goto nla_put_failure;
@ -8438,23 +8519,20 @@ static void nl80211_send_remain_on_chan_event(
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie, struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp) unsigned int duration, gfp_t gfp)
{ {
nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
rdev, wdev, cookie, chan, rdev, wdev, cookie, chan,
channel_type, duration, gfp); duration, gfp);
} }
void nl80211_send_remain_on_channel_cancel( void nl80211_send_remain_on_channel_cancel(
struct cfg80211_registered_device *rdev, struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
u64 cookie, struct ieee80211_channel *chan, u64 cookie, struct ieee80211_channel *chan, gfp_t gfp)
enum nl80211_channel_type channel_type, gfp_t gfp)
{ {
nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
rdev, wdev, cookie, chan, rdev, wdev, cookie, chan, 0, gfp);
channel_type, 0, gfp);
} }
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
@ -8810,8 +8888,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;
@ -8826,9 +8904,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);

View File

@ -76,13 +76,11 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, u64 cookie, struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp); unsigned int duration, gfp_t gfp);
void nl80211_send_remain_on_channel_cancel( void nl80211_send_remain_on_channel_cancel(
struct cfg80211_registered_device *rdev, struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
u64 cookie, struct ieee80211_channel *chan, u64 cookie, struct ieee80211_channel *chan, gfp_t gfp);
enum nl80211_channel_type channel_type, gfp_t gfp);
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *mac_addr, struct net_device *dev, const u8 *mac_addr,
@ -129,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);

View File

@ -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;
} }
@ -600,14 +599,12 @@ static inline int
rdev_remain_on_channel(struct cfg80211_registered_device *rdev, rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie) unsigned int duration, u64 *cookie)
{ {
int ret; int ret;
trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, channel_type, trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration);
duration);
ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan, ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
channel_type, duration, cookie); duration, cookie);
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
return ret; return ret;
} }
@ -626,17 +623,15 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, const u8 *buf, size_t len,
bool channel_type_valid, unsigned int wait, bool no_cck, bool dont_wait_for_ack, u64 *cookie)
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
int ret; int ret;
trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, channel_type, trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
channel_type_valid, wait, no_cck, dont_wait_for_ack); wait, no_cck, dont_wait_for_ack);
ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
channel_type, channel_type_valid, wait, buf, wait, buf, len, no_cck,
len, no_cck, dont_wait_for_ack, cookie); dont_wait_for_ack, cookie);
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
return ret; return ret;
} }
@ -848,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;
} }

View File

@ -771,6 +771,38 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
return found; return found;
} }
static struct ieee80211_channel *
cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
struct ieee80211_channel *channel)
{
const u8 *tmp;
u32 freq;
int channel_number = -1;
tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
if (tmp && tmp[1] == 1) {
channel_number = tmp[2];
} else {
tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
channel_number = htop->primary_chan;
}
}
if (channel_number < 0)
return channel;
freq = ieee80211_channel_to_frequency(channel_number, channel->band);
channel = ieee80211_get_channel(wiphy, freq);
if (!channel)
return NULL;
if (channel->flags & IEEE80211_CHAN_DISABLED)
return NULL;
return channel;
}
struct cfg80211_bss* struct cfg80211_bss*
cfg80211_inform_bss(struct wiphy *wiphy, cfg80211_inform_bss(struct wiphy *wiphy,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
@ -790,6 +822,10 @@ cfg80211_inform_bss(struct wiphy *wiphy,
(signal < 0 || signal > 100))) (signal < 0 || signal > 100)))
return NULL; return NULL;
channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel);
if (!channel)
return NULL;
res = kzalloc(sizeof(*res) + privsz + ielen, gfp); res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
if (!res) if (!res)
return NULL; return NULL;
@ -839,11 +875,13 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
s32 signal, gfp_t gfp) s32 signal, gfp_t gfp)
{ {
struct cfg80211_internal_bss *res; struct cfg80211_internal_bss *res;
size_t ielen = len - offsetof(struct ieee80211_mgmt, size_t ielen = len - offsetof(struct ieee80211_mgmt,
u.probe_resp.variable); u.probe_resp.variable);
size_t privsz; size_t privsz;
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
offsetof(struct ieee80211_mgmt, u.beacon.variable));
trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
if (WARN_ON(!mgmt)) if (WARN_ON(!mgmt))
@ -861,6 +899,11 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
privsz = wiphy->bss_priv_size; privsz = wiphy->bss_priv_size;
channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
ielen, channel);
if (!channel)
return NULL;
res = kzalloc(sizeof(*res) + privsz + ielen, gfp); res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
if (!res) if (!res)
return NULL; return NULL;

View File

@ -20,29 +20,26 @@
#define MAC_PR_FMT "%pM" #define MAC_PR_FMT "%pM"
#define MAC_PR_ARG(entry_mac) (__entry->entry_mac) #define MAC_PR_ARG(entry_mac) (__entry->entry_mac)
#define WIPHY_ENTRY MAC_ENTRY(wiphy_mac) #define MAXNAME 32
#define WIPHY_ASSIGN MAC_ASSIGN(wiphy_mac, wiphy->perm_addr) #define WIPHY_ENTRY __array(char, wiphy_name, 32)
#define WIPHY_PR_FMT "wiphy " MAC_PR_FMT #define WIPHY_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(wiphy), MAXNAME)
#define WIPHY_PR_ARG MAC_PR_ARG(wiphy_mac) #define WIPHY_PR_FMT "%s"
#define WIPHY_PR_ARG __entry->wiphy_name
#define WDEV_ENTRY __field(u32, id) #define WDEV_ENTRY __field(u32, id)
#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) #define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0)
#define WDEV_PR_FMT ", wdev id: %u" #define WDEV_PR_FMT "wdev(%u)"
#define WDEV_PR_ARG (__entry->id) #define WDEV_PR_ARG (__entry->id)
#define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \ #define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \
MAC_ENTRY(netdev_addr) \ __field(int, ifindex)
__field(int, ifindex)
#define NETDEV_ASSIGN \ #define NETDEV_ASSIGN \
do { \ do { \
memcpy(__entry->name, netdev->name, IFNAMSIZ); \ memcpy(__entry->name, netdev->name, IFNAMSIZ); \
MAC_ASSIGN(netdev_addr, netdev->dev_addr); \
(__entry->ifindex) = (netdev->ifindex); \ (__entry->ifindex) = (netdev->ifindex); \
} while (0) } while (0)
#define NETDEV_PR_FMT ", netdev - name: %s, addr: " MAC_PR_FMT \ #define NETDEV_PR_FMT "netdev:%s(%d)"
", intf index: %d" #define NETDEV_PR_ARG __entry->name, __entry->ifindex
#define NETDEV_PR_ARG (__entry->name), MAC_PR_ARG(netdev_addr), \
(__entry->ifindex)
#define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \ #define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \
__field(u16, dot11MeshConfirmTimeout) \ __field(u16, dot11MeshConfirmTimeout) \
@ -123,9 +120,37 @@
__entry->center_freq = 0; \ __entry->center_freq = 0; \
} \ } \
} while (0) } while (0)
#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(u32, control_freq) \
__field(u32, width) \
__field(u32, center_freq1) \
__field(u32, center_freq2)
#define CHAN_DEF_ASSIGN(chandef) \
do { \
if ((chandef) && (chandef)->chan) { \
__entry->band = (chandef)->chan->band; \
__entry->control_freq = \
(chandef)->chan->center_freq; \
__entry->width = (chandef)->width; \
__entry->center_freq1 = (chandef)->center_freq1;\
__entry->center_freq2 = (chandef)->center_freq2;\
} else { \
__entry->band = 0; \
__entry->control_freq = 0; \
__entry->width = 0; \
__entry->center_freq1 = 0; \
__entry->center_freq2 = 0; \
} \
} while (0)
#define CHAN_DEF_PR_FMT \
"band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u"
#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \
__entry->width, __entry->center_freq1, \
__entry->center_freq2
#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) \
@ -313,7 +338,7 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt,
WIPHY_ASSIGN; WIPHY_ASSIGN;
WDEV_ASSIGN; WDEV_ASSIGN;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
); );
DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev,
@ -340,7 +365,7 @@ TRACE_EVENT(rdev_change_virtual_intf,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->type = type; __entry->type = type;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", type: %d", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", type: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type)
); );
@ -362,7 +387,7 @@ DECLARE_EVENT_CLASS(key_handle,
__entry->key_index = key_index; __entry->key_index = key_index;
__entry->pairwise = pairwise; __entry->pairwise = pairwise;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
); );
@ -403,7 +428,7 @@ TRACE_EVENT(rdev_set_default_key,
__entry->unicast = unicast; __entry->unicast = unicast;
__entry->multicast = multicast; __entry->multicast = multicast;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
BOOL_TO_STR(__entry->unicast), BOOL_TO_STR(__entry->unicast),
BOOL_TO_STR(__entry->multicast)) BOOL_TO_STR(__entry->multicast))
@ -422,7 +447,7 @@ TRACE_EVENT(rdev_set_default_mgmt_key,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->key_index = key_index; __entry->key_index = key_index;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
); );
@ -433,7 +458,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 +471,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;
@ -457,11 +482,11 @@ TRACE_EVENT(rdev_start_ap,
memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
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,
@ -510,7 +535,7 @@ TRACE_EVENT(rdev_change_beacon,
info->probe_resp, info->probe_resp_len); info->probe_resp, info->probe_resp_len);
} }
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
); );
DECLARE_EVENT_CLASS(wiphy_netdev_evt, DECLARE_EVENT_CLASS(wiphy_netdev_evt,
@ -524,7 +549,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_evt,
WIPHY_ASSIGN; WIPHY_ASSIGN;
NETDEV_ASSIGN; NETDEV_ASSIGN;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
); );
DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap, DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap,
@ -602,7 +627,7 @@ DECLARE_EVENT_CLASS(station_add_change,
memcpy(__entry->ht_capa, params->ht_capa, memcpy(__entry->ht_capa, params->ht_capa,
sizeof(struct ieee80211_ht_cap)); sizeof(struct ieee80211_ht_cap));
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
", station flags mask: %u, station flags set: %u, " ", station flags mask: %u, station flags set: %u, "
"station modify mask: %u, listen interval: %d, aid: %u, " "station modify mask: %u, listen interval: %d, aid: %u, "
"plink action: %u, plink state: %u, uapsd queues: %u", "plink action: %u, plink state: %u, uapsd queues: %u",
@ -638,7 +663,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(sta_mac, mac); MAC_ASSIGN(sta_mac, mac);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mac: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac)) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
); );
@ -678,7 +703,7 @@ TRACE_EVENT(rdev_dump_station,
MAC_ASSIGN(sta_mac, mac); MAC_ASSIGN(sta_mac, mac);
__entry->idx = idx; __entry->idx = idx;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
__entry->idx) __entry->idx)
); );
@ -716,7 +741,7 @@ DECLARE_EVENT_CLASS(mpath_evt,
MAC_ASSIGN(dst, dst); MAC_ASSIGN(dst, dst);
MAC_ASSIGN(next_hop, next_hop); MAC_ASSIGN(next_hop, next_hop);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst),
MAC_PR_ARG(next_hop)) MAC_PR_ARG(next_hop))
); );
@ -757,7 +782,7 @@ TRACE_EVENT(rdev_dump_mpath,
MAC_ASSIGN(next_hop, next_hop); MAC_ASSIGN(next_hop, next_hop);
__entry->idx = idx; __entry->idx = idx;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d, destination: " TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
MAC_PR_FMT ", next hop: " MAC_PR_FMT, MAC_PR_FMT ", next hop: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst), WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
MAC_PR_ARG(next_hop)) MAC_PR_ARG(next_hop))
@ -834,7 +859,7 @@ TRACE_EVENT(rdev_update_mesh_config,
MESH_CFG_ASSIGN; MESH_CFG_ASSIGN;
__entry->mask = mask; __entry->mask = mask;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mask: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mask: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask)
); );
@ -853,7 +878,7 @@ TRACE_EVENT(rdev_join_mesh,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MESH_CFG_ASSIGN; MESH_CFG_ASSIGN;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG) WIPHY_PR_ARG, NETDEV_PR_ARG)
); );
@ -879,7 +904,7 @@ TRACE_EVENT(rdev_change_bss,
__entry->ap_isolate = params->ap_isolate; __entry->ap_isolate = params->ap_isolate;
__entry->ht_opmode = params->ht_opmode; __entry->ht_opmode = params->ht_opmode;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", use cts prot: %d, " TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", use cts prot: %d, "
"use short preamble: %d, use short slot time: %d, " "use short preamble: %d, use short slot time: %d, "
"ap isolate: %d, ht opmode: %d", "ap isolate: %d, ht opmode: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot,
@ -909,7 +934,7 @@ TRACE_EVENT(rdev_set_txq_params,
__entry->cwmax = params->cwmax; __entry->cwmax = params->cwmax;
__entry->aifs = params->aifs; __entry->aifs = params->aifs;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop,
__entry->cwmin, __entry->cwmax, __entry->aifs) __entry->cwmin, __entry->cwmax, __entry->aifs)
); );
@ -928,26 +953,24 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel,
NETDEV_ASSIGN; NETDEV_ASSIGN;
CHAN_ASSIGN(chan); CHAN_ASSIGN(chan);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT CHAN_PR_FMT, WIPHY_PR_ARG, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_PR_FMT, WIPHY_PR_ARG,
NETDEV_PR_ARG, CHAN_PR_ARG) NETDEV_PR_ARG, CHAN_PR_ARG)
); );
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,
@ -969,7 +992,7 @@ TRACE_EVENT(rdev_auth,
memset(__entry->bssid, 0, ETH_ALEN); memset(__entry->bssid, 0, ETH_ALEN);
__entry->auth_type = req->auth_type; __entry->auth_type = req->auth_type;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type,
MAC_PR_ARG(bssid)) MAC_PR_ARG(bssid))
); );
@ -997,7 +1020,7 @@ TRACE_EVENT(rdev_assoc,
__entry->use_mfp = req->use_mfp; __entry->use_mfp = req->use_mfp;
__entry->flags = req->flags; __entry->flags = req->flags;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u", ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp), MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp),
@ -1020,7 +1043,7 @@ TRACE_EVENT(rdev_deauth,
MAC_ASSIGN(bssid, req->bssid); MAC_ASSIGN(bssid, req->bssid);
__entry->reason_code = req->reason_code; __entry->reason_code = req->reason_code;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
__entry->reason_code) __entry->reason_code)
); );
@ -1046,7 +1069,7 @@ TRACE_EVENT(rdev_disassoc,
__entry->reason_code = req->reason_code; __entry->reason_code = req->reason_code;
__entry->local_state_change = req->local_state_change; __entry->local_state_change = req->local_state_change;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
", reason: %u, local state change: %s", ", reason: %u, local state change: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
__entry->reason_code, __entry->reason_code,
@ -1067,7 +1090,7 @@ TRACE_EVENT(rdev_mgmt_tx_cancel_wait,
WDEV_ASSIGN; WDEV_ASSIGN;
__entry->cookie = cookie; __entry->cookie = cookie;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu ", TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu ",
WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
); );
@ -1087,7 +1110,7 @@ TRACE_EVENT(rdev_set_power_mgmt,
__entry->enabled = enabled; __entry->enabled = enabled;
__entry->timeout = timeout; __entry->timeout = timeout;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", %senabled, timeout: %d ", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %senabled, timeout: %d ",
WIPHY_PR_ARG, NETDEV_PR_ARG, WIPHY_PR_ARG, NETDEV_PR_ARG,
__entry->enabled ? "" : "not ", __entry->timeout) __entry->enabled ? "" : "not ", __entry->timeout)
); );
@ -1117,7 +1140,7 @@ TRACE_EVENT(rdev_connect,
__entry->wpa_versions = sme->crypto.wpa_versions; __entry->wpa_versions = sme->crypto.wpa_versions;
__entry->flags = sme->flags; __entry->flags = sme->flags;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, "
"flags: %u", "flags: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid,
@ -1142,7 +1165,7 @@ TRACE_EVENT(rdev_set_cqm_rssi_config,
__entry->rssi_thold = rssi_thold; __entry->rssi_thold = rssi_thold;
__entry->rssi_hyst = rssi_hyst; __entry->rssi_hyst = rssi_hyst;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
", rssi_thold: %d, rssi_hyst: %u ", ", rssi_thold: %d, rssi_hyst: %u ",
WIPHY_PR_ARG, NETDEV_PR_ARG, WIPHY_PR_ARG, NETDEV_PR_ARG,
__entry->rssi_thold, __entry->rssi_hyst) __entry->rssi_thold, __entry->rssi_hyst)
@ -1166,7 +1189,7 @@ TRACE_EVENT(rdev_set_cqm_txe_config,
__entry->pkts = pkts; __entry->pkts = pkts;
__entry->intvl = intvl; __entry->intvl = intvl;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts,
__entry->intvl) __entry->intvl)
); );
@ -1185,7 +1208,7 @@ TRACE_EVENT(rdev_disconnect,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->reason_code = reason_code; __entry->reason_code = reason_code;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG,
NETDEV_PR_ARG, __entry->reason_code) NETDEV_PR_ARG, __entry->reason_code)
); );
@ -1206,7 +1229,7 @@ TRACE_EVENT(rdev_join_ibss,
memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
memcpy(__entry->ssid, params->ssid, params->ssid_len); memcpy(__entry->ssid, params->ssid, params->ssid_len);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
); );
@ -1246,7 +1269,7 @@ TRACE_EVENT(rdev_set_tx_power,
__entry->type = type; __entry->type = type;
__entry->mbm = mbm; __entry->mbm = mbm;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", type: %d, mbm: %d", TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d",
WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm) WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm)
); );
@ -1307,7 +1330,7 @@ TRACE_EVENT(rdev_set_bitrate_mask,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(peer, peer); MAC_ASSIGN(peer, peer);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", peer: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
); );
@ -1327,7 +1350,7 @@ TRACE_EVENT(rdev_mgmt_frame_register,
__entry->frame_type = frame_type; __entry->frame_type = frame_type;
__entry->reg = reg; __entry->reg = reg;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", frame_type: %u, reg: %s ", TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ",
WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type, WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,
__entry->reg ? "true" : "false") __entry->reg ? "true" : "false")
); );
@ -1413,7 +1436,7 @@ TRACE_EVENT(rdev_sched_scan_start,
WIPHY_ASSIGN; WIPHY_ASSIGN;
NETDEV_ASSIGN; NETDEV_ASSIGN;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG) WIPHY_PR_ARG, NETDEV_PR_ARG)
); );
@ -1441,7 +1464,7 @@ TRACE_EVENT(rdev_tdls_mgmt,
__entry->status_code = status_code; __entry->status_code = status_code;
memcpy(__get_dynamic_array(buf), buf, len); memcpy(__get_dynamic_array(buf), buf, len);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", action_code: %u, " TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, "
"dialog_token: %u, status_code: %u, buf: %#.2x ", "dialog_token: %u, status_code: %u, buf: %#.2x ",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
__entry->action_code, __entry->dialog_token, __entry->action_code, __entry->dialog_token,
@ -1461,7 +1484,7 @@ TRACE_EVENT(rdev_dump_survey,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->idx = idx; __entry->idx = idx;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx)
); );
@ -1518,7 +1541,7 @@ TRACE_EVENT(rdev_tdls_oper,
MAC_ASSIGN(peer, peer); MAC_ASSIGN(peer, peer);
__entry->oper = oper; __entry->oper = oper;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", oper: %d", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", oper: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper)
); );
@ -1536,7 +1559,7 @@ DECLARE_EVENT_CLASS(rdev_pmksa,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(bssid, pmksa->bssid); MAC_ASSIGN(bssid, pmksa->bssid);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid)) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid))
); );
@ -1554,7 +1577,7 @@ TRACE_EVENT(rdev_probe_client,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(peer, peer); MAC_ASSIGN(peer, peer);
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT, TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
); );
@ -1573,25 +1596,22 @@ DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa,
TRACE_EVENT(rdev_remain_on_channel, TRACE_EVENT(rdev_remain_on_channel,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type, unsigned int duration), unsigned int duration),
TP_ARGS(wiphy, wdev, chan, channel_type, duration), TP_ARGS(wiphy, wdev, chan, duration),
TP_STRUCT__entry( TP_STRUCT__entry(
WIPHY_ENTRY WIPHY_ENTRY
WDEV_ENTRY WDEV_ENTRY
CHAN_ENTRY CHAN_ENTRY
__field(enum nl80211_channel_type, channel_type)
__field(unsigned int, duration) __field(unsigned int, duration)
), ),
TP_fast_assign( TP_fast_assign(
WIPHY_ASSIGN; WIPHY_ASSIGN;
WDEV_ASSIGN; WDEV_ASSIGN;
CHAN_ASSIGN(chan); CHAN_ASSIGN(chan);
__entry->channel_type = channel_type;
__entry->duration = duration; __entry->duration = duration;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", channel type: %d, duration: %u", TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u",
WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->channel_type, WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration)
__entry->duration)
); );
TRACE_EVENT(rdev_return_int_cookie, TRACE_EVENT(rdev_return_int_cookie,
@ -1624,25 +1644,20 @@ TRACE_EVENT(rdev_cancel_remain_on_channel,
WDEV_ASSIGN; WDEV_ASSIGN;
__entry->cookie = cookie; __entry->cookie = cookie;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu", TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu",
WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
); );
TRACE_EVENT(rdev_mgmt_tx, TRACE_EVENT(rdev_mgmt_tx,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, unsigned int wait, bool no_cck, bool dont_wait_for_ack),
bool channel_type_valid, unsigned int wait, bool no_cck, TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack),
bool dont_wait_for_ack),
TP_ARGS(wiphy, wdev, chan, offchan, channel_type, channel_type_valid,
wait, no_cck, dont_wait_for_ack),
TP_STRUCT__entry( TP_STRUCT__entry(
WIPHY_ENTRY WIPHY_ENTRY
WDEV_ENTRY WDEV_ENTRY
CHAN_ENTRY CHAN_ENTRY
__field(bool, offchan) __field(bool, offchan)
__field(enum nl80211_channel_type, channel_type)
__field(bool, channel_type_valid)
__field(unsigned int, wait) __field(unsigned int, wait)
__field(bool, no_cck) __field(bool, no_cck)
__field(bool, dont_wait_for_ack) __field(bool, dont_wait_for_ack)
@ -1652,18 +1667,14 @@ TRACE_EVENT(rdev_mgmt_tx,
WDEV_ASSIGN; WDEV_ASSIGN;
CHAN_ASSIGN(chan); CHAN_ASSIGN(chan);
__entry->offchan = offchan; __entry->offchan = offchan;
__entry->channel_type = channel_type;
__entry->channel_type_valid = channel_type_valid;
__entry->wait = wait; __entry->wait = wait;
__entry->no_cck = no_cck; __entry->no_cck = no_cck;
__entry->dont_wait_for_ack = dont_wait_for_ack; __entry->dont_wait_for_ack = dont_wait_for_ack;
), ),
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", offchan: %s, " TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
"channel type: %d, channel type valid: %s, wait: %u, " " wait: %u, no cck: %s, dont wait for ack: %s",
"no cck: %s, dont wait for ack: %s",
WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG,
BOOL_TO_STR(__entry->offchan), __entry->channel_type, BOOL_TO_STR(__entry->offchan), __entry->wait,
BOOL_TO_STR(__entry->channel_type_valid), __entry->wait,
BOOL_TO_STR(__entry->no_cck), BOOL_TO_STR(__entry->no_cck),
BOOL_TO_STR(__entry->dont_wait_for_ack)) BOOL_TO_STR(__entry->dont_wait_for_ack))
); );
@ -1682,7 +1693,7 @@ TRACE_EVENT(rdev_set_noack_map,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->noack_map = noack_map; __entry->noack_map = noack_map;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", noack_map: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", noack_map: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
); );
@ -1699,7 +1710,7 @@ TRACE_EVENT(rdev_get_et_sset_count,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->sset = sset; __entry->sset = sset;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %d", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
); );
@ -1716,7 +1727,7 @@ TRACE_EVENT(rdev_get_et_strings,
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->sset = sset; __entry->sset = sset;
), ),
TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %u", TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
); );
@ -1725,22 +1736,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,
@ -1819,7 +1833,7 @@ TRACE_EVENT(cfg80211_send_rx_assoc,
MAC_ASSIGN(bssid, bss->bssid); MAC_ASSIGN(bssid, bss->bssid);
CHAN_ASSIGN(bss->channel); CHAN_ASSIGN(bss->channel);
), ),
TP_printk(NETDEV_PR_FMT MAC_PR_FMT CHAN_PR_FMT, TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", " CHAN_PR_FMT,
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
); );
@ -1886,7 +1900,7 @@ TRACE_EVENT(cfg80211_michael_mic_failure,
__entry->key_id = key_id; __entry->key_id = key_id;
memcpy(__entry->tsc, tsc, 6); memcpy(__entry->tsc, tsc, 6);
), ),
TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm",
NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type,
__entry->key_id, __entry->tsc) __entry->key_id, __entry->tsc)
); );
@ -1894,47 +1908,41 @@ TRACE_EVENT(cfg80211_michael_mic_failure,
TRACE_EVENT(cfg80211_ready_on_channel, TRACE_EVENT(cfg80211_ready_on_channel,
TP_PROTO(struct wireless_dev *wdev, u64 cookie, TP_PROTO(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type, unsigned int duration), unsigned int duration),
TP_ARGS(wdev, cookie, chan, channel_type, duration), TP_ARGS(wdev, cookie, chan, duration),
TP_STRUCT__entry( TP_STRUCT__entry(
WDEV_ENTRY WDEV_ENTRY
__field(u64, cookie) __field(u64, cookie)
CHAN_ENTRY CHAN_ENTRY
__field(enum nl80211_channel_type, channel_type)
__field(unsigned int, duration) __field(unsigned int, duration)
), ),
TP_fast_assign( TP_fast_assign(
WDEV_ASSIGN; WDEV_ASSIGN;
__entry->cookie = cookie; __entry->cookie = cookie;
CHAN_ASSIGN(chan); CHAN_ASSIGN(chan);
__entry->channel_type = channel_type;
__entry->duration = duration; __entry->duration = duration;
), ),
TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d, duration: %u", TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", duration: %u",
WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG,
__entry->channel_type, __entry->duration) __entry->duration)
); );
TRACE_EVENT(cfg80211_ready_on_channel_expired, TRACE_EVENT(cfg80211_ready_on_channel_expired,
TP_PROTO(struct wireless_dev *wdev, u64 cookie, TP_PROTO(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan, struct ieee80211_channel *chan),
enum nl80211_channel_type channel_type), TP_ARGS(wdev, cookie, chan),
TP_ARGS(wdev, cookie, chan, channel_type),
TP_STRUCT__entry( TP_STRUCT__entry(
WDEV_ENTRY WDEV_ENTRY
__field(u64, cookie) __field(u64, cookie)
CHAN_ENTRY CHAN_ENTRY
__field(enum nl80211_channel_type, channel_type)
), ),
TP_fast_assign( TP_fast_assign(
WDEV_ASSIGN; WDEV_ASSIGN;
__entry->cookie = cookie; __entry->cookie = cookie;
CHAN_ASSIGN(chan); CHAN_ASSIGN(chan);
__entry->channel_type = channel_type;
), ),
TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d", TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT,
WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG)
__entry->channel_type)
); );
TRACE_EVENT(cfg80211_new_sta, TRACE_EVENT(cfg80211_new_sta,
@ -1951,7 +1959,7 @@ TRACE_EVENT(cfg80211_new_sta,
MAC_ASSIGN(mac_addr, mac_addr); MAC_ASSIGN(mac_addr, mac_addr);
SINFO_ASSIGN; SINFO_ASSIGN;
), ),
TP_printk(NETDEV_PR_FMT MAC_PR_FMT, TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT,
NETDEV_PR_ARG, MAC_PR_ARG(mac_addr)) NETDEV_PR_ARG, MAC_PR_ARG(mac_addr))
); );
@ -2010,40 +2018,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,
@ -2057,7 +2060,7 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(addr, addr); MAC_ASSIGN(addr, addr);
), ),
TP_printk(NETDEV_PR_FMT MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
); );
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
@ -2091,7 +2094,7 @@ TRACE_EVENT(cfg80211_probe_status,
__entry->cookie = cookie; __entry->cookie = cookie;
__entry->acked = acked; __entry->acked = acked;
), ),
TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", cookie: %llu, acked: %s", TP_printk(NETDEV_PR_FMT " addr:" MAC_PR_FMT ", cookie: %llu, acked: %s",
NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie, NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie,
BOOL_TO_STR(__entry->acked)) BOOL_TO_STR(__entry->acked))
); );
@ -2241,7 +2244,7 @@ TRACE_EVENT(cfg80211_get_bss,
__entry->capa_mask = capa_mask; __entry->capa_mask = capa_mask;
__entry->capa_val = capa_val; __entry->capa_val = capa_val;
), ),
TP_printk(WIPHY_PR_FMT CHAN_PR_FMT MAC_PR_FMT ", buf: %#.2x, " TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, "
"capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG, "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG,
MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0], MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0],
__entry->capa_mask, __entry->capa_val) __entry->capa_mask, __entry->capa_val)
@ -2265,7 +2268,7 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
memcpy(__get_dynamic_array(mgmt), mgmt, len); memcpy(__get_dynamic_array(mgmt), mgmt, len);
__entry->signal = signal; __entry->signal = signal;
), ),
TP_printk(WIPHY_PR_FMT CHAN_PR_FMT "signal: %d", TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d",
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal)
); );
@ -2280,7 +2283,7 @@ DECLARE_EVENT_CLASS(cfg80211_bss_evt,
MAC_ASSIGN(bssid, pub->bssid); MAC_ASSIGN(bssid, pub->bssid);
CHAN_ASSIGN(pub->channel); CHAN_ASSIGN(pub->channel);
), ),
TP_printk(MAC_PR_FMT CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG) TP_printk(MAC_PR_FMT ", " CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG)
); );
DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss, DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss,

View File

@ -944,14 +944,86 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
return __mcs2bitrate[rate->mcs]; return __mcs2bitrate[rate->mcs];
} }
static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
{
static const u32 base[4][10] = {
{ 6500000,
13000000,
19500000,
26000000,
39000000,
52000000,
58500000,
65000000,
78000000,
0,
},
{ 13500000,
27000000,
40500000,
54000000,
81000000,
108000000,
121500000,
135000000,
162000000,
180000000,
},
{ 29300000,
58500000,
87800000,
117000000,
175500000,
234000000,
263300000,
292500000,
351000000,
390000000,
},
{ 58500000,
117000000,
175500000,
234000000,
351000000,
468000000,
526500000,
585000000,
702000000,
780000000,
},
};
u32 bitrate;
int idx;
if (WARN_ON_ONCE(rate->mcs > 9))
return 0;
idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH |
RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 :
rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 :
rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0;
bitrate = base[idx][rate->mcs];
bitrate *= rate->nss;
if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
bitrate = (bitrate / 9) * 10;
/* do NOT round down here */
return (bitrate + 50000) / 100000;
}
u32 cfg80211_calculate_bitrate(struct rate_info *rate) u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{ {
int modulation, streams, bitrate; int modulation, streams, bitrate;
if (!(rate->flags & RATE_INFO_FLAGS_MCS)) if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
!(rate->flags & RATE_INFO_FLAGS_VHT_MCS))
return rate->legacy; return rate->legacy;
if (rate->flags & RATE_INFO_FLAGS_60G) if (rate->flags & RATE_INFO_FLAGS_60G)
return cfg80211_calculate_bitrate_60g(rate); return cfg80211_calculate_bitrate_60g(rate);
if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
return cfg80211_calculate_bitrate_vht(rate);
/* the formula below does only work for MCS values smaller than 32 */ /* the formula below does only work for MCS values smaller than 32 */
if (WARN_ON_ONCE(rate->mcs >= 32)) if (WARN_ON_ONCE(rate->mcs >= 32))
@ -980,8 +1052,9 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
} }
EXPORT_SYMBOL(cfg80211_calculate_bitrate); EXPORT_SYMBOL(cfg80211_calculate_bitrate);
unsigned int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
u8 attr, u8 *buf, unsigned int bufsize) enum ieee80211_p2p_attr_id attr,
u8 *buf, unsigned int bufsize)
{ {
u8 *out = buf; u8 *out = buf;
u16 attr_remaining = 0; u16 attr_remaining = 0;

View File

@ -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 = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
int freq, err; int freq, err;
switch (wdev->iftype) { switch (wdev->iftype) {
@ -797,8 +800,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
return freq; return freq;
if (freq == 0) if (freq == 0)
return -EINVAL; return -EINVAL;
chandef.center_freq1 = freq;
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 +814,12 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
return freq; return freq;
if (freq == 0) if (freq == 0)
return -EINVAL; return -EINVAL;
chandef.center_freq1 = freq;
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 +833,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 +845,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:

View File

@ -119,7 +119,16 @@ 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 = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
.center_freq1 = freq,
};
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;
} }