Merge tag 'mac80211-next-for-net-next-2020-04-25' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== One batch of changes, containing: * hwsim improvements from Jouni and myself, to be able to test more scenarios easily * some more HE (802.11ax) support * some initial S1G (sub 1 GHz) work for fractional MHz channels * some (action) frame registration updates to help DPP support * along with other various improvements/fixes ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@@ -448,66 +448,14 @@ static void sta_addba_resp_timer_expired(struct timer_list *t)
|
||||
ieee80211_stop_tx_ba_session(&sta->sta, tid);
|
||||
}
|
||||
|
||||
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||
static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
|
||||
struct tid_ampdu_tx *tid_tx)
|
||||
{
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_ampdu_params params = {
|
||||
.sta = &sta->sta,
|
||||
.action = IEEE80211_AMPDU_TX_START,
|
||||
.tid = tid,
|
||||
.buf_size = 0,
|
||||
.amsdu = false,
|
||||
.timeout = 0,
|
||||
};
|
||||
int ret;
|
||||
struct ieee80211_local *local = sta->local;
|
||||
u8 tid = tid_tx->tid;
|
||||
u16 buf_size;
|
||||
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
|
||||
/*
|
||||
* Start queuing up packets for this aggregation session.
|
||||
* We're going to release them once the driver is OK with
|
||||
* that.
|
||||
*/
|
||||
clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
|
||||
|
||||
ieee80211_agg_stop_txq(sta, tid);
|
||||
|
||||
/*
|
||||
* Make sure no packets are being processed. This ensures that
|
||||
* we have a valid starting sequence number and that in-flight
|
||||
* packets have been flushed out and no packets for this TID
|
||||
* will go into the driver during the ampdu_action call.
|
||||
*/
|
||||
synchronize_net();
|
||||
|
||||
params.ssn = sta->tid_seq[tid] >> 4;
|
||||
ret = drv_ampdu_action(local, sdata, ¶ms);
|
||||
if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
||||
/*
|
||||
* We didn't send the request yet, so don't need to check
|
||||
* here if we already got a response, just mark as driver
|
||||
* ready immediately.
|
||||
*/
|
||||
set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
|
||||
} else if (ret) {
|
||||
ht_dbg(sdata,
|
||||
"BA request denied - HW unavailable for %pM tid %d\n",
|
||||
sta->sta.addr, tid);
|
||||
spin_lock_bh(&sta->lock);
|
||||
ieee80211_agg_splice_packets(sdata, tid_tx, tid);
|
||||
ieee80211_assign_tid_tx(sta, tid, NULL);
|
||||
ieee80211_agg_splice_finish(sdata, tid);
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
ieee80211_agg_start_txq(sta, tid, false);
|
||||
|
||||
kfree_rcu(tid_tx, rcu_head);
|
||||
return;
|
||||
}
|
||||
|
||||
/* activate the timer for the recipient's addBA response */
|
||||
mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
|
||||
ht_dbg(sdata, "activated addBA response timer on %pM tid %d\n",
|
||||
@@ -532,8 +480,75 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||
|
||||
/* send AddBA request */
|
||||
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
|
||||
tid_tx->dialog_token, params.ssn,
|
||||
tid_tx->dialog_token,
|
||||
sta->tid_seq[tid] >> 4,
|
||||
buf_size, tid_tx->timeout);
|
||||
|
||||
WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state));
|
||||
}
|
||||
|
||||
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||
{
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_ampdu_params params = {
|
||||
.sta = &sta->sta,
|
||||
.action = IEEE80211_AMPDU_TX_START,
|
||||
.tid = tid,
|
||||
.buf_size = 0,
|
||||
.amsdu = false,
|
||||
.timeout = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
|
||||
/*
|
||||
* Start queuing up packets for this aggregation session.
|
||||
* We're going to release them once the driver is OK with
|
||||
* that.
|
||||
*/
|
||||
clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
|
||||
|
||||
ieee80211_agg_stop_txq(sta, tid);
|
||||
|
||||
/*
|
||||
* Make sure no packets are being processed. This ensures that
|
||||
* we have a valid starting sequence number and that in-flight
|
||||
* packets have been flushed out and no packets for this TID
|
||||
* will go into the driver during the ampdu_action call.
|
||||
*/
|
||||
synchronize_net();
|
||||
|
||||
params.ssn = sta->tid_seq[tid] >> 4;
|
||||
ret = drv_ampdu_action(local, sdata, ¶ms);
|
||||
if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
|
||||
return;
|
||||
} else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
||||
/*
|
||||
* We didn't send the request yet, so don't need to check
|
||||
* here if we already got a response, just mark as driver
|
||||
* ready immediately.
|
||||
*/
|
||||
set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
|
||||
} else if (ret) {
|
||||
ht_dbg(sdata,
|
||||
"BA request denied - HW unavailable for %pM tid %d\n",
|
||||
sta->sta.addr, tid);
|
||||
spin_lock_bh(&sta->lock);
|
||||
ieee80211_agg_splice_packets(sdata, tid_tx, tid);
|
||||
ieee80211_assign_tid_tx(sta, tid, NULL);
|
||||
ieee80211_agg_splice_finish(sdata, tid);
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
ieee80211_agg_start_txq(sta, tid, false);
|
||||
|
||||
kfree_rcu(tid_tx, rcu_head);
|
||||
return;
|
||||
}
|
||||
|
||||
ieee80211_send_addba_with_timeout(sta, tid_tx);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -754,6 +769,12 @@ void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
|
||||
return;
|
||||
|
||||
if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) {
|
||||
ieee80211_send_addba_with_timeout(sta, tid_tx);
|
||||
/* RESPONSE_RECEIVED state whould trigger the flow again */
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
|
||||
ieee80211_agg_tx_operational(local, sta, tid);
|
||||
}
|
||||
|
@@ -994,7 +994,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
BSS_CHANGED_TWT |
|
||||
BSS_CHANGED_HE_OBSS_PD |
|
||||
BSS_CHANGED_HE_BSS_COLOR;
|
||||
int err;
|
||||
int i, err;
|
||||
int prev_beacon_int;
|
||||
|
||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||
@@ -1085,6 +1085,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
|
||||
IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
||||
|
||||
sdata->beacon_rate_set = false;
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
|
||||
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||
sdata->beacon_rateidx_mask[i] =
|
||||
params->beacon_rate.control[i].legacy;
|
||||
if (sdata->beacon_rateidx_mask[i])
|
||||
sdata->beacon_rate_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
||||
if (err < 0) {
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
@@ -1189,6 +1200,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
ieee80211_free_keys(sdata, true);
|
||||
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
sdata->beacon_rate_set = false;
|
||||
sdata->vif.bss_conf.ssid_len = 0;
|
||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
@@ -1949,6 +1961,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
|
||||
const u8 *old_ie;
|
||||
struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
|
||||
struct ieee80211_sub_if_data, u.mesh);
|
||||
int i;
|
||||
|
||||
/* allocate information elements */
|
||||
new_ie = NULL;
|
||||
@@ -1987,6 +2000,17 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
|
||||
sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
|
||||
sdata->vif.bss_conf.dtim_period = setup->dtim_period;
|
||||
|
||||
sdata->beacon_rate_set = false;
|
||||
if (wiphy_ext_feature_isset(sdata->local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) {
|
||||
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||
sdata->beacon_rateidx_mask[i] =
|
||||
setup->beacon_rate.control[i].legacy;
|
||||
if (sdata->beacon_rateidx_mask[i])
|
||||
sdata->beacon_rate_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3287,6 +3311,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (params->chandef.chan->freq_offset) {
|
||||
/* this may work, but is untested */
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
||||
|
||||
ch_switch.timestamp = 0;
|
||||
@@ -3398,41 +3428,43 @@ int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
|
||||
static void
|
||||
ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
u16 frame_type, bool reg)
|
||||
struct mgmt_frame_regs *upd)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
u32 preq_mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
|
||||
u32 action_mask = BIT(IEEE80211_STYPE_ACTION >> 4);
|
||||
bool global_change, intf_change;
|
||||
|
||||
switch (frame_type) {
|
||||
case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
|
||||
if (reg) {
|
||||
local->probe_req_reg++;
|
||||
sdata->vif.probe_req_reg++;
|
||||
} else {
|
||||
if (local->probe_req_reg)
|
||||
local->probe_req_reg--;
|
||||
global_change =
|
||||
(local->probe_req_reg != !!(upd->global_stypes & preq_mask)) ||
|
||||
(local->rx_mcast_action_reg !=
|
||||
!!(upd->global_mcast_stypes & action_mask));
|
||||
local->probe_req_reg = upd->global_stypes & preq_mask;
|
||||
local->rx_mcast_action_reg = upd->global_mcast_stypes & action_mask;
|
||||
|
||||
if (sdata->vif.probe_req_reg)
|
||||
sdata->vif.probe_req_reg--;
|
||||
}
|
||||
intf_change = (sdata->vif.probe_req_reg !=
|
||||
!!(upd->interface_stypes & preq_mask)) ||
|
||||
(sdata->vif.rx_mcast_action_reg !=
|
||||
!!(upd->interface_mcast_stypes & action_mask));
|
||||
sdata->vif.probe_req_reg = upd->interface_stypes & preq_mask;
|
||||
sdata->vif.rx_mcast_action_reg =
|
||||
upd->interface_mcast_stypes & action_mask;
|
||||
|
||||
if (!local->open_count)
|
||||
break;
|
||||
if (!local->open_count)
|
||||
return;
|
||||
|
||||
if (sdata->vif.probe_req_reg == 1)
|
||||
drv_config_iface_filter(local, sdata, FIF_PROBE_REQ,
|
||||
FIF_PROBE_REQ);
|
||||
else if (sdata->vif.probe_req_reg == 0)
|
||||
drv_config_iface_filter(local, sdata, 0,
|
||||
FIF_PROBE_REQ);
|
||||
if (intf_change && ieee80211_sdata_running(sdata))
|
||||
drv_config_iface_filter(local, sdata,
|
||||
sdata->vif.probe_req_reg ?
|
||||
FIF_PROBE_REQ : 0,
|
||||
FIF_PROBE_REQ);
|
||||
|
||||
if (global_change)
|
||||
ieee80211_configure_filter(local);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
|
||||
@@ -4017,7 +4049,8 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
|
||||
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
|
||||
.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
|
||||
.mgmt_frame_register = ieee80211_mgmt_frame_register,
|
||||
.update_mgmt_frame_registrations =
|
||||
ieee80211_update_mgmt_frame_registrations,
|
||||
.set_antenna = ieee80211_set_antenna,
|
||||
.get_antenna = ieee80211_get_antenna,
|
||||
.set_rekey_data = ieee80211_set_rekey_data,
|
||||
|
@@ -533,6 +533,7 @@ static void ieee80211_del_chanctx(struct ieee80211_local *local,
|
||||
struct cfg80211_chan_def *chandef = &local->_oper_chandef;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = chandef->chan->center_freq;
|
||||
chandef->freq1_offset = chandef->chan->freq_offset;
|
||||
chandef->center_freq2 = 0;
|
||||
|
||||
/* NOTE: Disabling radar is only valid here for
|
||||
|
@@ -236,7 +236,7 @@ IEEE80211_IF_FILE_R(hw_queues);
|
||||
|
||||
/* STA attributes */
|
||||
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
||||
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
|
||||
IEEE80211_IF_FILE(aid, vif.bss_conf.aid, DEC);
|
||||
IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
|
||||
|
||||
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||
|
@@ -57,17 +57,14 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
void
|
||||
ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif,
|
||||
const struct ieee80211_he_operation *he_op_ie_elem)
|
||||
const struct ieee80211_he_operation *he_op_ie)
|
||||
{
|
||||
struct ieee80211_he_operation *he_operation =
|
||||
&vif->bss_conf.he_operation;
|
||||
|
||||
if (!he_op_ie_elem) {
|
||||
memset(he_operation, 0, sizeof(*he_operation));
|
||||
memset(&vif->bss_conf.he_oper, 0, sizeof(vif->bss_conf.he_oper));
|
||||
if (!he_op_ie)
|
||||
return;
|
||||
}
|
||||
|
||||
vif->bss_conf.he_operation = *he_op_ie_elem;
|
||||
vif->bss_conf.he_oper.params = __le32_to_cpu(he_op_ie->he_oper_params);
|
||||
vif->bss_conf.he_oper.nss_set = __le16_to_cpu(he_op_ie->he_mcs_nss_set);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -1758,6 +1758,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (params->chandef.chan->freq_offset) {
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
|
||||
¶ms->chandef,
|
||||
sdata->wdev.iftype);
|
||||
|
@@ -450,8 +450,6 @@ struct ieee80211_if_managed {
|
||||
|
||||
u8 bssid[ETH_ALEN] __aligned(2);
|
||||
|
||||
u16 aid;
|
||||
|
||||
bool powersave; /* powersave requested for this iface */
|
||||
bool broken_ap; /* AP is broken -- turn off powersave */
|
||||
bool have_beacon;
|
||||
@@ -964,6 +962,10 @@ struct ieee80211_sub_if_data {
|
||||
bool rc_has_vht_mcs_mask[NUM_NL80211_BANDS];
|
||||
u16 rc_rateidx_vht_mcs_mask[NUM_NL80211_BANDS][NL80211_VHT_NSS_MAX];
|
||||
|
||||
/* Beacon frame (non-MCS) rate (as a bitmap) */
|
||||
u32 beacon_rateidx_mask[NUM_NL80211_BANDS];
|
||||
bool beacon_rate_set;
|
||||
|
||||
union {
|
||||
struct ieee80211_if_ap ap;
|
||||
struct ieee80211_if_wds wds;
|
||||
@@ -1169,7 +1171,8 @@ struct ieee80211_local {
|
||||
/* number of interfaces with corresponding FIF_ flags */
|
||||
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
|
||||
fif_probe_req;
|
||||
int probe_req_reg;
|
||||
bool probe_req_reg;
|
||||
bool rx_mcast_action_reg;
|
||||
unsigned int filter_flags; /* FIF_* */
|
||||
|
||||
bool wiphy_ciphers_allocated;
|
||||
|
@@ -644,6 +644,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||
local->fif_probe_req++;
|
||||
}
|
||||
|
||||
if (sdata->vif.probe_req_reg)
|
||||
drv_config_iface_filter(local, sdata,
|
||||
FIF_PROBE_REQ,
|
||||
FIF_PROBE_REQ);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||
sdata->vif.type != NL80211_IFTYPE_NAN)
|
||||
changed |= ieee80211_reset_erp_info(sdata);
|
||||
|
@@ -64,6 +64,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
|
||||
if (local->fif_pspoll)
|
||||
new_flags |= FIF_PSPOLL;
|
||||
|
||||
if (local->rx_mcast_action_reg)
|
||||
new_flags |= FIF_MCAST_ACTION;
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
changed_flags = local->filter_flags ^ new_flags;
|
||||
|
||||
@@ -104,13 +107,15 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
chandef.chan = local->tmp_channel;
|
||||
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef.center_freq1 = chandef.chan->center_freq;
|
||||
chandef.freq1_offset = chandef.chan->freq_offset;
|
||||
} else
|
||||
chandef = local->_oper_chandef;
|
||||
|
||||
WARN(!cfg80211_chandef_valid(&chandef),
|
||||
"control:%d MHz width:%d center: %d/%d MHz",
|
||||
chandef.chan->center_freq, chandef.width,
|
||||
chandef.center_freq1, chandef.center_freq2);
|
||||
"control:%d.%03d MHz width:%d center: %d.%03d/%d MHz",
|
||||
chandef.chan->center_freq, chandef.chan->freq_offset,
|
||||
chandef.width, chandef.center_freq1, chandef.freq1_offset,
|
||||
chandef.center_freq2);
|
||||
|
||||
if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
|
@@ -994,6 +994,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
|
||||
/* stop the beacon */
|
||||
ifmsh->mesh_id_len = 0;
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
sdata->beacon_rate_set = false;
|
||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
|
@@ -162,6 +162,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
chandef->chan = channel;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = channel->center_freq;
|
||||
chandef->freq1_offset = channel->freq_offset;
|
||||
|
||||
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
||||
ret = IEEE80211_STA_DISABLE_HT |
|
||||
@@ -396,9 +397,12 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
||||
return 0;
|
||||
|
||||
sdata_info(sdata,
|
||||
"AP %pM changed bandwidth, new config is %d MHz, width %d (%d/%d MHz)\n",
|
||||
ifmgd->bssid, chandef.chan->center_freq, chandef.width,
|
||||
chandef.center_freq1, chandef.center_freq2);
|
||||
"AP %pM changed bandwidth, new config is %d.%03d MHz, "
|
||||
"width %d (%d.%03d/%d MHz)\n",
|
||||
ifmgd->bssid, chandef.chan->center_freq,
|
||||
chandef.chan->freq_offset, chandef.width,
|
||||
chandef.center_freq1, chandef.freq1_offset,
|
||||
chandef.center_freq2);
|
||||
|
||||
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
@@ -1364,10 +1368,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
sdata_info(sdata,
|
||||
"AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
|
||||
"AP %pM switches to unsupported channel "
|
||||
"(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
|
||||
"disconnecting\n",
|
||||
ifmgd->associated->bssid,
|
||||
csa_ie.chandef.chan->center_freq,
|
||||
csa_ie.chandef.chan->freq_offset,
|
||||
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
||||
csa_ie.chandef.freq1_offset,
|
||||
csa_ie.chandef.center_freq2);
|
||||
ieee80211_queue_work(&local->hw,
|
||||
&ifmgd->csa_connection_drop_work);
|
||||
@@ -2948,10 +2956,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (status_code != WLAN_STATUS_SUCCESS) {
|
||||
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
|
||||
|
||||
if (auth_alg == WLAN_AUTH_SAE &&
|
||||
status_code == WLAN_STATUS_ANTI_CLOG_REQUIRED)
|
||||
return;
|
||||
|
||||
sdata_info(sdata, "%pM denied authentication (status %d)\n",
|
||||
mgmt->sa, status_code);
|
||||
ieee80211_destroy_auth_data(sdata, false);
|
||||
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
|
||||
event.u.mlme.status = MLME_DENIED;
|
||||
event.u.mlme.reason = status_code;
|
||||
drv_event_callback(sdata->local, sdata, &event);
|
||||
@@ -3149,15 +3162,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
||||
*have_higher_than_11mbit = true;
|
||||
|
||||
/*
|
||||
* Skip HT and VHT BSS membership selectors since they're not
|
||||
* rates.
|
||||
* Skip HT, VHT and HE BSS membership selectors since they're
|
||||
* not rates.
|
||||
*
|
||||
* Note: Even though the membership selector and the basic
|
||||
* rate flag share the same bit, they are not exactly
|
||||
* the same.
|
||||
*/
|
||||
if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY))
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY) ||
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sband->n_bitrates; j++) {
|
||||
@@ -3249,7 +3263,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
return false;
|
||||
}
|
||||
|
||||
ifmgd->aid = aid;
|
||||
sdata->vif.bss_conf.aid = aid;
|
||||
ifmgd->tdls_chan_switch_prohibited =
|
||||
elems->ext_capab && elems->ext_capab_len >= 5 &&
|
||||
(elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
|
||||
@@ -3384,10 +3398,19 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
sta);
|
||||
|
||||
bss_conf->he_support = sta->sta.he_cap.has_he;
|
||||
if (elems->rsnx && elems->rsnx_len &&
|
||||
(elems->rsnx[0] & WLAN_RSNX_CAPA_PROTECTED_TWT) &&
|
||||
wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_PROTECTED_TWT))
|
||||
bss_conf->twt_protected = true;
|
||||
else
|
||||
bss_conf->twt_protected = false;
|
||||
|
||||
changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
|
||||
} else {
|
||||
bss_conf->he_support = false;
|
||||
bss_conf->twt_requester = false;
|
||||
bss_conf->twt_protected = false;
|
||||
}
|
||||
|
||||
if (bss_conf->he_support) {
|
||||
@@ -3521,9 +3544,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
bss_conf->protected_keep_alive = false;
|
||||
}
|
||||
|
||||
/* set AID and assoc capability,
|
||||
/* set assoc capability (AID was already set earlier),
|
||||
* ieee80211_set_associated() will tell the driver */
|
||||
bss_conf->aid = aid;
|
||||
bss_conf->assoc_capability = capab_info;
|
||||
ieee80211_set_associated(sdata, cbss, changed);
|
||||
|
||||
@@ -3661,7 +3683,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
||||
channel = ieee80211_get_channel_khz(local->hw.wiphy,
|
||||
ieee80211_rx_status_to_khz(rx_status));
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
@@ -3877,7 +3900,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
return;
|
||||
}
|
||||
|
||||
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
|
||||
if (ieee80211_rx_status_to_khz(rx_status) !=
|
||||
ieee80211_channel_to_khz(chanctx_conf->def.chan)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
@@ -3948,7 +3972,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
mgmt->bssid, bssid);
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
|
||||
ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
|
||||
ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
|
||||
if (local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_PS;
|
||||
@@ -5022,8 +5046,16 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
* doesn't happen any more, but keep the workaround so
|
||||
* in case some *other* APs are buggy in different ways
|
||||
* we can connect -- with a warning.
|
||||
* Allow this workaround only in case the AP provided at least
|
||||
* one rate.
|
||||
*/
|
||||
if (!basic_rates && min_rate_index >= 0) {
|
||||
if (min_rate_index < 0) {
|
||||
sdata_info(sdata,
|
||||
"No legacy rates in association response\n");
|
||||
|
||||
sta_info_free(local, new_sta);
|
||||
return -EINVAL;
|
||||
} else if (!basic_rates) {
|
||||
sdata_info(sdata,
|
||||
"No basic rates, using min rate instead\n");
|
||||
basic_rates = BIT(min_rate_index);
|
||||
|
@@ -557,6 +557,10 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
if (channel->freq_offset)
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (local->use_chanctx && !local->ops->remain_on_channel)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*/
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/types.h>
|
||||
@@ -490,7 +491,7 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
|
||||
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
|
||||
tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
|
||||
|
||||
if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) {
|
||||
if (tmp_cck_tp > tmp_mcs_tp) {
|
||||
for(i = 0; i < MAX_THR_RATES; i++) {
|
||||
minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i],
|
||||
tmp_mcs_tp_rate);
|
||||
|
@@ -412,6 +412,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
||||
pos++;
|
||||
|
||||
/* IEEE80211_RADIOTAP_CHANNEL */
|
||||
/* TODO: frequency offset in KHz */
|
||||
put_unaligned_le16(status->freq, pos);
|
||||
pos += 2;
|
||||
if (status->bw == RATE_INFO_BW_10)
|
||||
@@ -1984,8 +1985,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
|
||||
if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
|
||||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
|
||||
NUM_DEFAULT_BEACON_KEYS)
|
||||
NUM_DEFAULT_BEACON_KEYS) {
|
||||
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||
skb->data,
|
||||
skb->len);
|
||||
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
|
||||
}
|
||||
|
||||
rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx);
|
||||
if (!rx->key)
|
||||
@@ -2131,6 +2136,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
/* either the frame has been decrypted or will be dropped */
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
|
||||
if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE))
|
||||
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||
skb->data, skb->len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2411,8 +2420,12 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
|
||||
return -EACCES;
|
||||
}
|
||||
if (unlikely(ieee80211_is_beacon(fc) && rx->key &&
|
||||
ieee80211_get_mmie_keyidx(rx->skb) < 0))
|
||||
ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
|
||||
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||
rx->skb->data,
|
||||
rx->skb->len);
|
||||
return -EACCES;
|
||||
}
|
||||
/*
|
||||
* When using MFP, Action frames are not allowed prior to
|
||||
* having configured keys.
|
||||
|
@@ -275,7 +275,8 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
|
||||
channel = ieee80211_get_channel_khz(local->hw.wiphy,
|
||||
ieee80211_rx_status_to_khz(rx_status));
|
||||
|
||||
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
return;
|
||||
@@ -896,6 +897,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
|
||||
|
||||
local->scan_chandef.chan = chan;
|
||||
local->scan_chandef.center_freq1 = chan->center_freq;
|
||||
local->scan_chandef.freq1_offset = chan->freq_offset;
|
||||
local->scan_chandef.center_freq2 = 0;
|
||||
switch (scan_req->scan_width) {
|
||||
case NL80211_BSS_CHAN_WIDTH_5:
|
||||
|
@@ -3,6 +3,7 @@
|
||||
* Copyright 2002-2005, Devicescape Software, Inc.
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef STA_INFO_H
|
||||
@@ -68,6 +69,8 @@
|
||||
* @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP.
|
||||
* @WLAN_STA_PS_DELIVER: station woke up, but we're still blocking TX
|
||||
* until pending frames are delivered
|
||||
* @WLAN_STA_USES_ENCRYPTION: This station was configured for encryption,
|
||||
* so drop all packets without a key later.
|
||||
*
|
||||
* @NUM_WLAN_STA_FLAGS: number of defined flags
|
||||
*/
|
||||
@@ -116,6 +119,7 @@ enum ieee80211_sta_info_flags {
|
||||
#define HT_AGG_STATE_WANT_STOP 5
|
||||
#define HT_AGG_STATE_START_CB 6
|
||||
#define HT_AGG_STATE_STOP_CB 7
|
||||
#define HT_AGG_STATE_SENT_ADDBA 8
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
enum ieee80211_agg_stop_reason {
|
||||
|
@@ -226,12 +226,11 @@ static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
|
||||
static void
|
||||
ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
u8 *pos = skb_put(skb, 4);
|
||||
|
||||
*pos++ = WLAN_EID_AID;
|
||||
*pos++ = 2; /* len */
|
||||
put_unaligned_le16(ifmgd->aid, pos);
|
||||
put_unaligned_le16(sdata->vif.bss_conf.aid, pos);
|
||||
}
|
||||
|
||||
/* translate numbering in the WMM parameter IE to the mac80211 notation */
|
||||
@@ -1567,6 +1566,10 @@ ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
u32 ch_sw_tm_ie;
|
||||
int ret;
|
||||
|
||||
if (chandef->chan->freq_offset)
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, addr);
|
||||
if (!sta) {
|
||||
|
@@ -37,32 +37,42 @@
|
||||
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
|
||||
|
||||
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
||||
__field(u32, freq_offset) \
|
||||
__field(u32, chan_width) \
|
||||
__field(u32, center_freq1) \
|
||||
__field(u32, freq1_offset) \
|
||||
__field(u32, center_freq2)
|
||||
#define CHANDEF_ASSIGN(c) \
|
||||
__entry->control_freq = (c) ? ((c)->chan ? (c)->chan->center_freq : 0) : 0; \
|
||||
__entry->freq_offset = (c) ? ((c)->chan ? (c)->chan->freq_offset : 0) : 0; \
|
||||
__entry->chan_width = (c) ? (c)->width : 0; \
|
||||
__entry->center_freq1 = (c) ? (c)->center_freq1 : 0; \
|
||||
__entry->freq1_offset = (c) ? (c)->freq1_offset : 0; \
|
||||
__entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
|
||||
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
||||
__entry->center_freq1, __entry->center_freq2
|
||||
#define CHANDEF_PR_FMT " control:%d.%03d MHz width:%d center: %d.%03d/%d MHz"
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->freq_offset, __entry->chan_width, \
|
||||
__entry->center_freq1, __entry->freq1_offset, __entry->center_freq2
|
||||
|
||||
#define MIN_CHANDEF_ENTRY \
|
||||
__field(u32, min_control_freq) \
|
||||
__field(u32, min_freq_offset) \
|
||||
__field(u32, min_chan_width) \
|
||||
__field(u32, min_center_freq1) \
|
||||
__field(u32, min_freq1_offset) \
|
||||
__field(u32, min_center_freq2)
|
||||
|
||||
#define MIN_CHANDEF_ASSIGN(c) \
|
||||
__entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
||||
__entry->min_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0; \
|
||||
__entry->min_chan_width = (c)->width; \
|
||||
__entry->min_center_freq1 = (c)->center_freq1; \
|
||||
__entry->freq1_offset = (c)->freq1_offset; \
|
||||
__entry->min_center_freq2 = (c)->center_freq2;
|
||||
#define MIN_CHANDEF_PR_FMT " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
|
||||
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_chan_width, \
|
||||
__entry->min_center_freq1, __entry->min_center_freq2
|
||||
#define MIN_CHANDEF_PR_FMT " min_control:%d.%03d MHz min_width:%d min_center: %d.%03d/%d MHz"
|
||||
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_freq_offset, \
|
||||
__entry->min_chan_width, \
|
||||
__entry->min_center_freq1, __entry->min_freq1_offset, \
|
||||
__entry->min_center_freq2
|
||||
|
||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||
MIN_CHANDEF_ENTRY \
|
||||
@@ -412,6 +422,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
||||
__field(s32, cqm_rssi_hyst)
|
||||
__field(u32, channel_width)
|
||||
__field(u32, channel_cfreq1)
|
||||
__field(u32, channel_cfreq1_offset)
|
||||
__dynamic_array(u32, arp_addr_list,
|
||||
info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||
IEEE80211_BSS_ARP_ADDR_LIST_LEN :
|
||||
@@ -452,6 +463,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
||||
__entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
|
||||
__entry->channel_width = info->chandef.width;
|
||||
__entry->channel_cfreq1 = info->chandef.center_freq1;
|
||||
__entry->channel_cfreq1_offset = info->chandef.freq1_offset;
|
||||
__entry->arp_addr_cnt = info->arp_addr_cnt;
|
||||
memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
|
||||
sizeof(u32) * (info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||
@@ -1223,6 +1235,7 @@ TRACE_EVENT(drv_remain_on_channel,
|
||||
LOCAL_ENTRY
|
||||
VIF_ENTRY
|
||||
__field(int, center_freq)
|
||||
__field(int, freq_offset)
|
||||
__field(unsigned int, duration)
|
||||
__field(u32, type)
|
||||
),
|
||||
@@ -1231,14 +1244,16 @@ TRACE_EVENT(drv_remain_on_channel,
|
||||
LOCAL_ASSIGN;
|
||||
VIF_ASSIGN;
|
||||
__entry->center_freq = chan->center_freq;
|
||||
__entry->freq_offset = chan->freq_offset;
|
||||
__entry->duration = duration;
|
||||
__entry->type = type;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d",
|
||||
LOCAL_PR_FMT VIF_PR_FMT " freq:%d.%03dMHz duration:%dms type=%d",
|
||||
LOCAL_PR_ARG, VIF_PR_ARG,
|
||||
__entry->center_freq, __entry->duration, __entry->type
|
||||
__entry->center_freq, __entry->freq_offset,
|
||||
__entry->duration, __entry->type
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1546,8 +1561,10 @@ struct trace_vif_entry {
|
||||
|
||||
struct trace_chandef_entry {
|
||||
u32 control_freq;
|
||||
u32 freq_offset;
|
||||
u32 chan_width;
|
||||
u32 center_freq1;
|
||||
u32 freq1_offset;
|
||||
u32 center_freq2;
|
||||
} __packed;
|
||||
|
||||
@@ -1597,18 +1614,26 @@ TRACE_EVENT(drv_switch_vif_chanctx,
|
||||
sizeof(local_vifs[i].vif.vif_name));
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
|
||||
old_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.freq_offset,
|
||||
old_ctx->def.chan->freq_offset);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
|
||||
old_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
|
||||
old_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.freq1_offset,
|
||||
old_ctx->def.freq1_offset);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
|
||||
old_ctx->def.center_freq2);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
|
||||
new_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.freq_offset,
|
||||
new_ctx->def.chan->freq_offset);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
|
||||
new_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
|
||||
new_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.freq1_offset,
|
||||
new_ctx->def.freq1_offset);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
|
||||
new_ctx->def.center_freq2);
|
||||
}
|
||||
|
@@ -4883,7 +4883,10 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
txrc.bss_conf = &sdata->vif.bss_conf;
|
||||
txrc.skb = skb;
|
||||
txrc.reported_rate.idx = -1;
|
||||
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
||||
if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
|
||||
txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
|
||||
else
|
||||
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
||||
txrc.bss = true;
|
||||
rate_control_get_rate(sdata, NULL, &txrc);
|
||||
|
||||
@@ -5006,7 +5009,7 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
|
||||
pspoll = skb_put_zero(skb, sizeof(*pspoll));
|
||||
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
|
||||
IEEE80211_STYPE_PSPOLL);
|
||||
pspoll->aid = cpu_to_le16(ifmgd->aid);
|
||||
pspoll->aid = cpu_to_le16(sdata->vif.bss_conf.aid);
|
||||
|
||||
/* aid in PS-Poll has its two MSBs each set to 1 */
|
||||
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
|
||||
|
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@@ -575,15 +575,21 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
|
||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
|
||||
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
|
||||
break;
|
||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
|
||||
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
|
||||
break;
|
||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
|
||||
if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
|
||||
else
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
|
||||
break;
|
||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
|
||||
/* legacy only, no longer used by newer spec */
|
||||
sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user