summaryrefslogtreecommitdiff
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c118
1 files changed, 54 insertions, 64 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a77a1470..c12f34813 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,7 +17,6 @@
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
-#include "cfg.h"
#include "rate.h"
#include "mesh.h"
#include "wme.h"
@@ -469,45 +468,6 @@ void sta_set_rate_info_tx(struct sta_info *sta,
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
}
-void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
-{
- rinfo->flags = 0;
-
- if (sta->last_rx_rate_flag & RX_FLAG_HT) {
- rinfo->flags |= RATE_INFO_FLAGS_MCS;
- rinfo->mcs = sta->last_rx_rate_idx;
- } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
- rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
- rinfo->nss = sta->last_rx_rate_vht_nss;
- rinfo->mcs = sta->last_rx_rate_idx;
- } else {
- struct ieee80211_supported_band *sband;
- int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
- u16 brate;
-
- sband = sta->local->hw.wiphy->bands[
- ieee80211_get_sdata_band(sta->sdata)];
- brate = sband->bitrates[sta->last_rx_rate_idx].bitrate;
- rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
- }
-
- if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
- rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
-
- if (sta->last_rx_rate_flag & RX_FLAG_5MHZ)
- rinfo->bw = RATE_INFO_BW_5;
- else if (sta->last_rx_rate_flag & RX_FLAG_10MHZ)
- rinfo->bw = RATE_INFO_BW_10;
- else if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
- rinfo->bw = RATE_INFO_BW_40;
- else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ)
- rinfo->bw = RATE_INFO_BW_80;
- else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ)
- rinfo->bw = RATE_INFO_BW_160;
- else
- rinfo->bw = RATE_INFO_BW_20;
-}
-
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo)
{
@@ -981,7 +941,7 @@ static int sta_apply_auth_flags(struct ieee80211_local *local,
* well. Some drivers require rate control initialized
* before drv_sta_state() is called.
*/
- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+ if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
rate_control_rate_init(sta);
ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
@@ -1120,8 +1080,11 @@ static int sta_apply_parameters(struct ieee80211_local *local,
local->hw.queues >= IEEE80211_NUM_ACS)
sta->sta.wme = set & BIT(NL80211_STA_FLAG_WME);
- /* auth flags will be set later for TDLS stations */
- if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+ /* auth flags will be set later for TDLS,
+ * and for unassociated stations that move to assocaited */
+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+ !((mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) &&
+ (set & BIT(NL80211_STA_FLAG_ASSOCIATED)))) {
ret = sta_apply_auth_flags(local, sta, mask, set);
if (ret)
return ret;
@@ -1135,6 +1098,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
}
if (mask & BIT(NL80211_STA_FLAG_MFP)) {
+ sta->sta.mfp = !!(set & BIT(NL80211_STA_FLAG_MFP));
if (set & BIT(NL80211_STA_FLAG_MFP))
set_sta_flag(sta, WLAN_STA_MFP);
else
@@ -1156,6 +1120,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+ !sdata->u.mgd.tdls_wider_bw_prohibited &&
ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
params->ext_capab_len >= 8 &&
params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED)
@@ -1204,15 +1169,15 @@ static int sta_apply_parameters(struct ieee80211_local *local,
* rc isn't initialized here yet, so ignore it
*/
__ieee80211_vht_handle_opmode(sdata, sta,
- params->opmode_notif,
- band, false);
+ params->opmode_notif, band);
}
if (ieee80211_vif_is_mesh(&sdata->vif))
sta_apply_mesh_params(local, sta, params);
/* set the STA state after all sta info from usermode has been set */
- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) ||
+ set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
ret = sta_apply_auth_flags(local, sta, mask, set);
if (ret)
return ret;
@@ -1254,12 +1219,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
* defaults -- if userspace wants something else we'll
* change it accordingly in sta_apply_parameters()
*/
- if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) {
+ if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
+ !(params->sta_flags_set & (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+ BIT(NL80211_STA_FLAG_ASSOCIATED)))) {
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
- } else {
- sta->sta.tdls = true;
}
+ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ sta->sta.tdls = true;
err = sta_apply_parameters(local, sta, params);
if (err) {
@@ -1268,10 +1235,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
}
/*
- * for TDLS, rate control should be initialized only when
- * rates are known and station is marked authorized
+ * for TDLS and for unassociated station, rate control should be
+ * initialized only when rates are known and station is marked
+ * authorized/associated
*/
- if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+ test_sta_flag(sta, WLAN_STA_ASSOC))
rate_control_rate_init(sta);
layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
@@ -1346,7 +1315,10 @@ static int ieee80211_change_station(struct wiphy *wiphy,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
- statype = CFG80211_STA_AP_CLIENT;
+ if (test_sta_flag(sta, WLAN_STA_ASSOC))
+ statype = CFG80211_STA_AP_CLIENT;
+ else
+ statype = CFG80211_STA_AP_CLIENT_UNASSOC;
break;
default:
err = -EOPNOTSUPP;
@@ -1415,7 +1387,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
- ieee80211_recalc_ps(local, -1);
+ ieee80211_recalc_ps(local);
ieee80211_recalc_ps_vif(sdata);
}
@@ -2037,12 +2009,12 @@ ieee80211_sched_scan_start(struct wiphy *wiphy,
static int
ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wiphy_priv(wiphy);
- if (!sdata->local->ops->sched_scan_stop)
+ if (!local->ops->sched_scan_stop)
return -EOPNOTSUPP;
- return ieee80211_request_sched_scan_stop(sdata);
+ return ieee80211_request_sched_scan_stop(local);
}
static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
@@ -2450,7 +2422,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
- ieee80211_recalc_ps(local, -1);
+ ieee80211_recalc_ps(local);
ieee80211_recalc_ps_vif(sdata);
return 0;
@@ -3481,8 +3453,12 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
goto out_unlock;
}
} else {
- /* for cookie below */
- ack_skb = skb;
+ /* Assign a dummy non-zero cookie, it's not sent to
+ * userspace in this case but we rely on its value
+ * internally in the need_offchan case to distinguish
+ * mgmt-tx from remain-on-channel.
+ */
+ *cookie = 0xffffffff;
}
if (!need_offchan) {
@@ -3522,18 +3498,32 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
u16 frame_type, bool reg)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
switch (frame_type) {
case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
- if (reg)
+ if (reg) {
local->probe_req_reg++;
- else
- local->probe_req_reg--;
+ sdata->vif.probe_req_reg++;
+ } else {
+ if (local->probe_req_reg)
+ local->probe_req_reg--;
+
+ if (sdata->vif.probe_req_reg)
+ sdata->vif.probe_req_reg--;
+ }
if (!local->open_count)
break;
- ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+ 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);
+
+ ieee80211_configure_filter(local);
break;
default:
break;