Merge tag 'mac80211-next-for-davem-2018-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== We have a fair number of patches, but many of them are from the first bullet here: * EAPoL-over-nl80211 from Denis - this will let us fix some long-standing issues with bridging, races with encryption and more * DFS offload support from the qtnfmac folks * regulatory database changes for the new ETSI adaptivity requirements * various other fixes and small enhancements ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This file is GPLv2 as found in COPYING.
|
||||
*/
|
||||
@@ -925,6 +926,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
*/
|
||||
sdata->control_port_protocol = params->crypto.control_port_ethertype;
|
||||
sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
params->crypto.control_port_over_nl80211;
|
||||
sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
|
||||
¶ms->crypto,
|
||||
sdata->vif.type);
|
||||
@@ -934,6 +937,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
params->crypto.control_port_ethertype;
|
||||
vlan->control_port_no_encrypt =
|
||||
params->crypto.control_port_no_encrypt;
|
||||
vlan->control_port_over_nl80211 =
|
||||
params->crypto.control_port_over_nl80211;
|
||||
vlan->encrypt_headroom =
|
||||
ieee80211_cs_headroom(sdata->local,
|
||||
¶ms->crypto,
|
||||
@@ -2019,6 +2024,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sdata->control_port_over_nl80211 = setup->control_port_over_nl80211;
|
||||
|
||||
/* can mesh use other SMPS modes? */
|
||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||
sdata->needed_rx_chains = sdata->local->rx_chains;
|
||||
@@ -2156,6 +2163,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
|
||||
*/
|
||||
p.uapsd = false;
|
||||
|
||||
ieee80211_regulatory_limit_wmm_params(sdata, &p, params->ac);
|
||||
|
||||
sdata->tx_conf[params->ac] = p;
|
||||
if (drv_conf_tx(local, sdata, params->ac, &p)) {
|
||||
wiphy_debug(local->hw.wiphy,
|
||||
@@ -2313,6 +2322,8 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
|
||||
memcpy(sdata->vif.bss_conf.mcast_rate, rate,
|
||||
sizeof(int) * NUM_NL80211_BANDS);
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MCAST_RATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3786,4 +3797,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_nan_func = ieee80211_add_nan_func,
|
||||
.del_nan_func = ieee80211_del_nan_func,
|
||||
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
|
||||
.tx_control_port = ieee80211_tx_control_port,
|
||||
};
|
||||
|
@@ -466,6 +466,21 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
|
||||
__ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST);
|
||||
}
|
||||
|
||||
enum nl80211_smps_mode
|
||||
ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps)
|
||||
{
|
||||
switch (smps) {
|
||||
case IEEE80211_SMPS_OFF:
|
||||
return NL80211_SMPS_OFF;
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
return NL80211_SMPS_STATIC;
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
return NL80211_SMPS_DYNAMIC;
|
||||
default:
|
||||
return NL80211_SMPS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
|
||||
enum ieee80211_smps_mode smps, const u8 *da,
|
||||
const u8 *bssid)
|
||||
|
@@ -1839,11 +1839,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED
|
||||
| IEEE80211_HT_PARAM_RIFS_MODE;
|
||||
|
||||
changed |= BSS_CHANGED_HT;
|
||||
changed |= BSS_CHANGED_HT | BSS_CHANGED_MCAST_RATE;
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||
sdata->needed_rx_chains = local->rx_chains;
|
||||
sdata->control_port_over_nl80211 = params->control_port_over_nl80211;
|
||||
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -899,6 +900,7 @@ struct ieee80211_sub_if_data {
|
||||
u16 sequence_number;
|
||||
__be16 control_port_protocol;
|
||||
bool control_port_no_encrypt;
|
||||
bool control_port_over_nl80211;
|
||||
int encrypt_headroom;
|
||||
|
||||
atomic_t num_tx_queued;
|
||||
@@ -1734,6 +1736,9 @@ void ieee80211_check_fast_xmit(struct sta_info *sta);
|
||||
void ieee80211_check_fast_xmit_all(struct ieee80211_local *local);
|
||||
void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_clear_fast_xmit(struct sta_info *sta);
|
||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *buf, size_t len,
|
||||
const u8 *dest, __be16 proto, bool unencrypted);
|
||||
|
||||
/* HT */
|
||||
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
|
||||
@@ -1788,6 +1793,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
|
||||
void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
|
||||
|
||||
u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs);
|
||||
enum nl80211_smps_mode
|
||||
ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps);
|
||||
|
||||
/* VHT */
|
||||
void
|
||||
@@ -1814,6 +1821,8 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta_vht_cap *vht_cap);
|
||||
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
|
||||
u16 vht_mask[NL80211_VHT_NSS_MAX]);
|
||||
enum nl80211_chan_width
|
||||
ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta);
|
||||
|
||||
/* Spectrum management */
|
||||
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
|
||||
@@ -1865,6 +1874,9 @@ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */
|
||||
int ieee80211_frame_duration(enum nl80211_band band, size_t len,
|
||||
int rate, int erp, int short_preamble,
|
||||
int shift);
|
||||
void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_tx_queue_params *qparam,
|
||||
int ac);
|
||||
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
|
||||
bool bss_notify, bool enable_qos);
|
||||
void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
|
@@ -519,6 +519,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||
master->control_port_protocol;
|
||||
sdata->control_port_no_encrypt =
|
||||
master->control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
master->control_port_over_nl80211;
|
||||
sdata->vif.cab_queue = master->vif.cab_queue;
|
||||
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
|
||||
sizeof(sdata->vif.hw_queue));
|
||||
|
@@ -126,7 +126,7 @@ static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_sub_if_data *sdata = key->sdata;
|
||||
struct sta_info *sta;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
@@ -162,7 +162,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
||||
if (sta && !sta->uploaded)
|
||||
goto out_unsupported;
|
||||
|
||||
sdata = key->sdata;
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||
/*
|
||||
* The driver doesn't know anything about VLAN interfaces.
|
||||
@@ -214,8 +213,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
||||
/* all of these we can do in software - if driver can */
|
||||
if (ret == 1)
|
||||
return 0;
|
||||
if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL))
|
||||
if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL)) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@@ -554,6 +554,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
NL80211_FEATURE_USERSPACE_MPM |
|
||||
NL80211_FEATURE_FULL_AP_CLIENT_STATE;
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
|
||||
|
||||
if (!ops->hw_scan)
|
||||
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
@@ -930,8 +932,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
}
|
||||
|
||||
/* if low-level driver supports AP, we also support VLAN */
|
||||
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
|
||||
/* if low-level driver supports AP, we also support VLAN.
|
||||
* drivers advertising SW_CRYPTO_CONTROL should enable AP_VLAN
|
||||
* based on their support to transmit SW encrypted packets.
|
||||
*/
|
||||
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP) &&
|
||||
!ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL)) {
|
||||
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
||||
hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
||||
}
|
||||
|
@@ -880,7 +880,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
||||
BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_HT |
|
||||
BSS_CHANGED_BASIC_RATES |
|
||||
BSS_CHANGED_BEACON_INT;
|
||||
BSS_CHANGED_BEACON_INT |
|
||||
BSS_CHANGED_MCAST_RATE;
|
||||
|
||||
local->fif_other_bss++;
|
||||
/* mesh ifaces must set allmulti to forward mcast traffic */
|
||||
|
@@ -1787,12 +1787,14 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
params[ac].acm = acm;
|
||||
params[ac].uapsd = uapsd;
|
||||
|
||||
if (params[ac].cw_min > params[ac].cw_max) {
|
||||
if (params->cw_min == 0 ||
|
||||
params[ac].cw_min > params[ac].cw_max) {
|
||||
sdata_info(sdata,
|
||||
"AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
|
||||
params[ac].cw_min, params[ac].cw_max, aci);
|
||||
return false;
|
||||
}
|
||||
ieee80211_regulatory_limit_wmm_params(sdata, ¶ms[ac], ac);
|
||||
}
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
@@ -2011,8 +2013,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* deauthenticate/disassociate now */
|
||||
if (tx || frame_buf) {
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
|
||||
/*
|
||||
* In multi channel scenarios guarantee that the virtual
|
||||
* interface is granted immediate airtime to transmit the
|
||||
@@ -3307,82 +3307,14 @@ static const u64 care_about_ies =
|
||||
(1ULL << WLAN_EID_HT_OPERATION) |
|
||||
(1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
|
||||
|
||||
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgmt *mgmt, size_t len,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_if_managed *ifmgd,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
struct ieee80211_local *local,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||
size_t baselen;
|
||||
struct ieee802_11_elems elems;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
struct sta_info *sta;
|
||||
u32 changed = 0;
|
||||
bool erp_valid;
|
||||
u8 erp_value = 0;
|
||||
u32 ncrc;
|
||||
u8 *bssid;
|
||||
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
/* Process beacon from the current BSS */
|
||||
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
|
||||
if (baselen > len)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (!chanctx_conf) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
chan = chanctx_conf->def.chan;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
|
||||
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
|
||||
ieee802_11_parse_elems(mgmt->u.beacon.variable,
|
||||
len - baselen, false, &elems);
|
||||
|
||||
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
|
||||
if (elems.tim && !elems.parse_error) {
|
||||
const struct ieee80211_tim_ie *tim_ie = elems.tim;
|
||||
ifmgd->dtim_period = tim_ie->dtim_period;
|
||||
}
|
||||
ifmgd->have_beacon = true;
|
||||
ifmgd->assoc_data->need_beacon = false;
|
||||
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
|
||||
sdata->vif.bss_conf.sync_tsf =
|
||||
le64_to_cpu(mgmt->u.beacon.timestamp);
|
||||
sdata->vif.bss_conf.sync_device_ts =
|
||||
rx_status->device_timestamp;
|
||||
if (elems.tim)
|
||||
sdata->vif.bss_conf.sync_dtim_count =
|
||||
elems.tim->dtim_count;
|
||||
else
|
||||
sdata->vif.bss_conf.sync_dtim_count = 0;
|
||||
}
|
||||
/* continue assoc process */
|
||||
ifmgd->assoc_data->timeout = jiffies;
|
||||
ifmgd->assoc_data->timeout_started = true;
|
||||
run_again(sdata, ifmgd->assoc_data->timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ifmgd->associated ||
|
||||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
|
||||
return;
|
||||
bssid = ifmgd->associated->bssid;
|
||||
|
||||
/* Track average RSSI from the Beacon frames of the current AP */
|
||||
|
||||
if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
|
||||
ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
|
||||
ewma_beacon_signal_init(&ifmgd->ave_beacon_signal);
|
||||
@@ -3469,6 +3401,86 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
sig, GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgmt *mgmt, size_t len,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||
size_t baselen;
|
||||
struct ieee802_11_elems elems;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
struct sta_info *sta;
|
||||
u32 changed = 0;
|
||||
bool erp_valid;
|
||||
u8 erp_value = 0;
|
||||
u32 ncrc;
|
||||
u8 *bssid;
|
||||
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
/* Process beacon from the current BSS */
|
||||
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
|
||||
if (baselen > len)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (!chanctx_conf) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
chan = chanctx_conf->def.chan;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
|
||||
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
|
||||
ieee802_11_parse_elems(mgmt->u.beacon.variable,
|
||||
len - baselen, false, &elems);
|
||||
|
||||
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
|
||||
if (elems.tim && !elems.parse_error) {
|
||||
const struct ieee80211_tim_ie *tim_ie = elems.tim;
|
||||
ifmgd->dtim_period = tim_ie->dtim_period;
|
||||
}
|
||||
ifmgd->have_beacon = true;
|
||||
ifmgd->assoc_data->need_beacon = false;
|
||||
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
|
||||
sdata->vif.bss_conf.sync_tsf =
|
||||
le64_to_cpu(mgmt->u.beacon.timestamp);
|
||||
sdata->vif.bss_conf.sync_device_ts =
|
||||
rx_status->device_timestamp;
|
||||
if (elems.tim)
|
||||
sdata->vif.bss_conf.sync_dtim_count =
|
||||
elems.tim->dtim_count;
|
||||
else
|
||||
sdata->vif.bss_conf.sync_dtim_count = 0;
|
||||
}
|
||||
/* continue assoc process */
|
||||
ifmgd->assoc_data->timeout = jiffies;
|
||||
ifmgd->assoc_data->timeout_started = true;
|
||||
run_again(sdata, ifmgd->assoc_data->timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ifmgd->associated ||
|
||||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
|
||||
return;
|
||||
bssid = ifmgd->associated->bssid;
|
||||
|
||||
if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
|
||||
ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf,
|
||||
local, rx_status);
|
||||
|
||||
if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
|
||||
mlme_dbg_ratelimited(sdata,
|
||||
@@ -4845,6 +4857,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
sdata->control_port_protocol = req->crypto.control_port_ethertype;
|
||||
sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
req->crypto.control_port_over_nl80211;
|
||||
sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
|
||||
sdata->vif.type);
|
||||
|
||||
|
@@ -2245,6 +2245,32 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
|
||||
struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct net_device *dev = sdata->dev;
|
||||
|
||||
if (unlikely((skb->protocol == sdata->control_port_protocol ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
|
||||
sdata->control_port_over_nl80211)) {
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
bool noencrypt = status->flag & RX_FLAG_DECRYPTED;
|
||||
struct ethhdr *ehdr = eth_hdr(skb);
|
||||
|
||||
cfg80211_rx_control_port(dev, skb->data, skb->len,
|
||||
ehdr->h_source,
|
||||
be16_to_cpu(skb->protocol), noencrypt);
|
||||
dev_kfree_skb(skb);
|
||||
} else {
|
||||
/* deliver to local stack */
|
||||
if (rx->napi)
|
||||
napi_gro_receive(rx->napi, skb);
|
||||
else
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* requires that rx->skb is a frame with ethernet header
|
||||
*/
|
||||
@@ -2329,13 +2355,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||
#endif
|
||||
|
||||
if (skb) {
|
||||
/* deliver to local stack */
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
memset(skb->cb, 0, sizeof(skb->cb));
|
||||
if (rx->napi)
|
||||
napi_gro_receive(rx->napi, skb);
|
||||
else
|
||||
netif_receive_skb(skb);
|
||||
|
||||
ieee80211_deliver_skb_to_local_stack(skb, rx);
|
||||
}
|
||||
|
||||
if (xmit_skb) {
|
||||
@@ -2804,7 +2827,8 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
||||
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
|
||||
int sig = 0;
|
||||
|
||||
if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
|
||||
if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) &&
|
||||
!(status->flag & RX_FLAG_NO_SIGNAL_VAL))
|
||||
sig = status->signal;
|
||||
|
||||
cfg80211_report_obss_beacon(rx->local->hw.wiphy,
|
||||
@@ -2882,7 +2906,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
if (rx->sta->sta.smps_mode == smps_mode)
|
||||
goto handled;
|
||||
rx->sta->sta.smps_mode = smps_mode;
|
||||
sta_opmode.smps_mode = smps_mode;
|
||||
sta_opmode.smps_mode =
|
||||
ieee80211_smps_mode_to_smps_mode(smps_mode);
|
||||
sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED;
|
||||
|
||||
sband = rx->local->hw.wiphy->bands[status->band];
|
||||
@@ -2920,7 +2945,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
|
||||
rx->sta->sta.bandwidth = new_bw;
|
||||
sband = rx->local->hw.wiphy->bands[status->band];
|
||||
sta_opmode.bw = new_bw;
|
||||
sta_opmode.bw =
|
||||
ieee80211_sta_rx_bw_to_chan_width(rx->sta);
|
||||
sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
|
||||
|
||||
rate_control_rate_update(local, sband, rx->sta,
|
||||
@@ -3145,7 +3171,8 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
|
||||
* it transmitted were processed or returned.
|
||||
*/
|
||||
|
||||
if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
|
||||
if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) &&
|
||||
!(status->flag & RX_FLAG_NO_SIGNAL_VAL))
|
||||
sig = status->signal;
|
||||
|
||||
if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
|
||||
|
@@ -73,7 +73,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
bool signal_valid;
|
||||
struct ieee80211_sub_if_data *scan_sdata;
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
|
||||
if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
|
||||
bss_meta.signal = 0; /* invalid signal indication */
|
||||
else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
|
||||
bss_meta.signal = rx_status->signal * 100;
|
||||
else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
|
||||
bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
|
||||
|
@@ -4757,3 +4757,49 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_xmit(sdata, NULL, skb);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *buf, size_t len,
|
||||
const u8 *dest, __be16 proto, bool unencrypted)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
struct ethhdr *ehdr;
|
||||
u32 flags;
|
||||
|
||||
/* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE
|
||||
* or Pre-Authentication
|
||||
*/
|
||||
if (proto != sdata->control_port_protocol &&
|
||||
proto != cpu_to_be16(ETH_P_PREAUTH))
|
||||
return -EINVAL;
|
||||
|
||||
if (unencrypted)
|
||||
flags = IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
else
|
||||
flags = 0;
|
||||
|
||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
||||
sizeof(struct ethhdr) + len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom + sizeof(struct ethhdr));
|
||||
|
||||
skb_put_data(skb, buf, len);
|
||||
|
||||
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
||||
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
||||
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
||||
ehdr->h_proto = proto;
|
||||
|
||||
skb->dev = dev;
|
||||
skb->protocol = htons(ETH_P_802_3);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
__ieee80211_subif_start_xmit(skb, skb->dev, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1113,6 +1114,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||
return crc;
|
||||
}
|
||||
|
||||
void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_tx_queue_params
|
||||
*qparam, int ac)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
const struct ieee80211_reg_rule *rrule;
|
||||
struct ieee80211_wmm_ac *wmm_ac;
|
||||
u16 center_freq = 0;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_AP &&
|
||||
sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (chanctx_conf)
|
||||
center_freq = chanctx_conf->def.chan->center_freq;
|
||||
|
||||
if (!center_freq) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
rrule = freq_reg_info(sdata->wdev.wiphy, MHZ_TO_KHZ(center_freq));
|
||||
|
||||
if (IS_ERR_OR_NULL(rrule) || !rrule->wmm_rule) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP)
|
||||
wmm_ac = &rrule->wmm_rule->ap[ac];
|
||||
else
|
||||
wmm_ac = &rrule->wmm_rule->client[ac];
|
||||
qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
|
||||
qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
|
||||
qparam->aifs = max_t(u8, qparam->aifs, wmm_ac->aifsn);
|
||||
qparam->txop = !qparam->txop ? wmm_ac->cot / 32 :
|
||||
min_t(u16, qparam->txop, wmm_ac->cot / 32);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
|
||||
bool bss_notify, bool enable_qos)
|
||||
{
|
||||
@@ -1206,6 +1249,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
|
||||
break;
|
||||
}
|
||||
}
|
||||
ieee80211_regulatory_limit_wmm_params(sdata, &qparam, ac);
|
||||
|
||||
qparam.uapsd = false;
|
||||
|
||||
@@ -1968,7 +2012,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
BSS_CHANGED_CQM |
|
||||
BSS_CHANGED_QOS |
|
||||
BSS_CHANGED_IDLE |
|
||||
BSS_CHANGED_TXPOWER;
|
||||
BSS_CHANGED_TXPOWER |
|
||||
BSS_CHANGED_MCAST_RATE;
|
||||
|
||||
if (sdata->vif.mu_mimo_owner)
|
||||
changed |= BSS_CHANGED_MU_GROUPS;
|
||||
|
@@ -358,6 +358,36 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
|
||||
return NL80211_CHAN_WIDTH_80;
|
||||
}
|
||||
|
||||
enum nl80211_chan_width
|
||||
ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta)
|
||||
{
|
||||
enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.bandwidth;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
|
||||
u32 cap_width;
|
||||
|
||||
switch (cur_bw) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
if (!sta->sta.ht_cap.ht_supported)
|
||||
return NL80211_CHAN_WIDTH_20_NOHT;
|
||||
else
|
||||
return NL80211_CHAN_WIDTH_20;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
return NL80211_CHAN_WIDTH_40;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
return NL80211_CHAN_WIDTH_80;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
cap_width =
|
||||
vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
||||
|
||||
if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
|
||||
return NL80211_CHAN_WIDTH_160;
|
||||
|
||||
return NL80211_CHAN_WIDTH_80P80;
|
||||
default:
|
||||
return NL80211_CHAN_WIDTH_20;
|
||||
}
|
||||
}
|
||||
|
||||
enum ieee80211_sta_rx_bandwidth
|
||||
ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
|
||||
{
|
||||
@@ -484,7 +514,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
new_bw = ieee80211_sta_cur_vht_bw(sta);
|
||||
if (new_bw != sta->sta.bandwidth) {
|
||||
sta->sta.bandwidth = new_bw;
|
||||
sta_opmode.bw = new_bw;
|
||||
sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
|
||||
changed |= IEEE80211_RC_BW_CHANGED;
|
||||
sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
|
||||
}
|
||||
|
Reference in New Issue
Block a user