aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/ibss.c11
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mesh_plink.c7
-rw-r--r--net/mac80211/mlme.c66
-rw-r--r--net/mac80211/rc80211_minstrel.c6
-rw-r--r--net/mac80211/rc80211_minstrel.h15
-rw-r--r--net/mac80211/rx.c11
-rw-r--r--net/mac80211/spectmgmt.c4
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/status.c11
-rw-r--r--net/mac80211/util.c21
-rw-r--r--net/mac80211/vht.c73
15 files changed, 144 insertions, 98 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e75d5c53e97b..169665835b6c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -678,7 +678,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON |
BSS_CHANGED_SSID |
- BSS_CHANGED_P2P_PS;
+ BSS_CHANGED_P2P_PS |
+ BSS_CHANGED_TXPOWER;
int err;
old = sdata_dereference(sdata->u.ap.beacon, sdata);
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 54a189f0393e..eeb0bbd69d98 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -303,8 +303,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
- if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
- sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n");
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
sf += scnprintf(buf + sf, mxln - sf,
"REPORTS_TX_ACK_STATUS\n");
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 509bc157ce55..b606b53a49a7 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1069,9 +1069,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
}
if (sta && rates_updated) {
- drv_sta_rc_update(local, sdata, &sta->sta,
- IEEE80211_RC_SUPP_RATES_CHANGED);
+ u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
+ u8 rx_nss = sta->sta.rx_nss;
+
+ /* Force rx_nss recalculation */
+ sta->sta.rx_nss = 0;
rate_control_rate_init(sta);
+ if (sta->sta.rx_nss != rx_nss)
+ changed |= IEEE80211_RC_NSS_CHANGED;
+
+ drv_sta_rc_update(local, sdata, &sta->sta, changed);
}
rcu_read_unlock();
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cc6e964d9837..4f45cab8b7f1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1704,6 +1704,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
const struct ieee80211_vht_cap *vht_cap_ie,
struct sta_info *sta);
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6ab99da38db9..d9ce33663c73 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -916,10 +916,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
}
}
- WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
- && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
- "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
-
/*
* Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index b488e1859b18..fa94ca15ba95 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -523,6 +523,13 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
sdata->u.mesh.mshcfg.auto_open_plinks &&
rssi_threshold_check(sdata, sta))
changed = mesh_plink_open(sta);
+ else if (sta->plink_state == NL80211_PLINK_LISTEN &&
+ (sdata->u.mesh.user_mpm ||
+ sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED))
+ cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
+ elems->ie_start,
+ elems->total_len,
+ GFP_ATOMIC);
ieee80211_mps_frame_release(sta, elems);
out:
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2c36c4765f47..8354bedc858a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -157,14 +157,18 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct cfg80211_chan_def vht_chandef;
+ struct ieee80211_sta_ht_cap sta_ht_cap;
u32 ht_cfreq, ret;
+ memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
+ ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
+
chandef->chan = channel;
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = channel->center_freq;
chandef->center_freq2 = 0;
- if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) {
+ if (!ht_cap || !ht_oper || !sta_ht_cap.ht_supported) {
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
goto out;
}
@@ -198,7 +202,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
}
/* check 40 MHz support, if we have it */
- if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+ if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
chandef->width = NL80211_CHAN_WIDTH_40;
@@ -1054,8 +1058,6 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
sdata->csa_block_tx = false;
}
- cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
-
sdata->vif.csa_active = false;
ifmgd->csa_waiting_bcn = false;
@@ -1067,6 +1069,8 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
&ifmgd->csa_connection_drop_work);
return;
}
+
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1284,8 +1288,11 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
country_ie_len -= 3;
}
- if (have_chan_pwr)
+ if (have_chan_pwr && pwr_constr_elem)
*pwr_reduction = *pwr_constr_elem;
+ else
+ *pwr_reduction = 0;
+
return have_chan_pwr;
}
@@ -1314,10 +1321,11 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
int chan_pwr = 0, pwr_reduction_80211h = 0;
int pwr_level_cisco, pwr_level_80211h;
int new_ap_level;
+ __le16 capab = mgmt->u.probe_resp.capab_info;
- if (country_ie && pwr_constr_ie &&
- mgmt->u.probe_resp.capab_info &
- cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) {
+ if (country_ie &&
+ (capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) ||
+ capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) {
has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
sdata, channel, country_ie, country_ie_len,
pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
@@ -4197,9 +4205,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss *bss = (void *)cbss->priv;
struct sta_info *new_sta = NULL;
- bool have_sta = false;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_sta_ht_cap sta_ht_cap;
+ bool have_sta = false, is_override = false;
int err;
+ sband = local->hw.wiphy->bands[cbss->channel->band];
+
if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
return -EINVAL;
@@ -4214,25 +4226,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
if (!new_sta)
return -ENOMEM;
}
+
+ memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
+ ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
+
+ is_override = (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) !=
+ (sband->ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+
+ if (new_sta || is_override) {
+ err = ieee80211_prep_channel(sdata, cbss);
+ if (err) {
+ if (new_sta)
+ sta_info_free(local, new_sta);
+ return -EINVAL;
+ }
+ }
+
if (new_sta) {
u32 rates = 0, basic_rates = 0;
bool have_higher_than_11mbit;
int min_rate = INT_MAX, min_rate_index = -1;
struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_supported_band *sband;
const struct cfg80211_bss_ies *ies;
- int shift;
+ int shift = ieee80211_vif_get_shift(&sdata->vif);
u32 rate_flags;
- sband = local->hw.wiphy->bands[cbss->channel->band];
-
- err = ieee80211_prep_channel(sdata, cbss);
- if (err) {
- sta_info_free(local, new_sta);
- return -EINVAL;
- }
- shift = ieee80211_vif_get_shift(&sdata->vif);
-
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
@@ -4668,8 +4687,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
rcu_read_unlock();
+ if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) &&
+ (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
+ "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"))
+ sdata->vif.driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;
+
if (bss->wmm_used && bss->uapsd_supported &&
- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
+ (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD)) {
assoc_data->uapsd = true;
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
} else {
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index d51f6b1c549b..7c86a002df95 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -263,12 +263,12 @@ static inline unsigned int
minstrel_get_retry_count(struct minstrel_rate *mr,
struct ieee80211_tx_info *info)
{
- unsigned int retry = mr->adjusted_retry_count;
+ u8 retry = mr->adjusted_retry_count;
if (info->control.use_rts)
- retry = max(2U, min(mr->stats.retry_count_rtscts, retry));
+ retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry));
else if (info->control.use_cts_prot)
- retry = max(2U, min(mr->retry_count_cts, retry));
+ retry = max_t(u8, 2, min(mr->retry_count_cts, retry));
return retry;
}
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 97eca86a4af0..410efe620c57 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -33,8 +33,8 @@ minstrel_ewma(int old, int new, int weight)
struct minstrel_rate_stats {
/* current / last sampling period attempts/success counters */
- unsigned int attempts, last_attempts;
- unsigned int success, last_success;
+ u16 attempts, last_attempts;
+ u16 success, last_success;
/* total attempts/success counters */
u64 att_hist, succ_hist;
@@ -46,8 +46,8 @@ struct minstrel_rate_stats {
unsigned int cur_prob, probability;
/* maximum retry counts */
- unsigned int retry_count;
- unsigned int retry_count_rtscts;
+ u8 retry_count;
+ u8 retry_count_rtscts;
u8 sample_skipped;
bool retry_updated;
@@ -55,14 +55,15 @@ struct minstrel_rate_stats {
struct minstrel_rate {
int bitrate;
- int rix;
+
+ s8 rix;
+ u8 retry_count_cts;
+ u8 adjusted_retry_count;
unsigned int perfect_tx_time;
unsigned int ack_time;
int sample_limit;
- unsigned int retry_count_cts;
- unsigned int adjusted_retry_count;
struct minstrel_rate_stats stats;
};
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 683b10f46505..fa5d870655a9 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2598,7 +2598,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
struct ieee80211_supported_band *sband;
u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
- enum ieee80211_sta_rx_bandwidth new_bw;
+ enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
/* If it doesn't support 40 MHz it can't change ... */
if (!(rx->sta->sta.ht_cap.cap &
@@ -2606,13 +2606,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
- new_bw = IEEE80211_STA_RX_BW_20;
+ max_bw = IEEE80211_STA_RX_BW_20;
else
- new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
+ max_bw = ieee80211_sta_cap_rx_bw(rx->sta);
+
+ /* set cur_max_bandwidth and recalc sta bw */
+ rx->sta->cur_max_bandwidth = max_bw;
+ new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
if (rx->sta->sta.bandwidth == new_bw)
goto handled;
+ rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
rate_control_rate_update(local, sband, rx->sta,
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index efeba56c913b..06e6ac8cc693 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -34,19 +34,15 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct cfg80211_chan_def new_vht_chandef = {};
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
- const struct ieee80211_ht_operation *ht_oper;
int secondary_channel_offset = -1;
sec_chan_offs = elems->sec_chan_offs;
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
- ht_oper = elems->ht_operation;
if (sta_flags & (IEEE80211_STA_DISABLE_HT |
IEEE80211_STA_DISABLE_40MHZ)) {
sec_chan_offs = NULL;
wide_bw_chansw_ie = NULL;
- /* only used for bandwidth here */
- ht_oper = NULL;
}
if (sta_flags & IEEE80211_STA_DISABLE_VHT)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a42f5b2b024d..db8b07ac6b10 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1243,10 +1243,11 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
* ends the poll/service period.
*/
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
- IEEE80211_TX_CTL_PS_RESPONSE |
IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS;
+ info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
+
if (call_driver)
drv_allow_buffered_frames(local, sta, BIT(tid), 1,
reason, false);
@@ -1395,8 +1396,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
* STA may still remain is PS mode after this frame
* exchange.
*/
- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
- IEEE80211_TX_CTL_PS_RESPONSE;
+ info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+ info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
/*
* Use MoreData flag to indicate whether there are
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index bb146f377ee4..7d4e9307164c 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -664,13 +664,15 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
struct ieee80211_supported_band *sband;
int retry_count;
int rates_idx;
- bool acked;
+ bool acked, noack_success;
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
sband = hw->wiphy->bands[info->band];
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
+
if (pubsta) {
struct sta_info *sta;
@@ -696,7 +698,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
rate_control_tx_status_noskb(local, sband, sta, info);
}
- if (acked) {
+ if (acked || noack_success) {
local->dot11TransmittedFrameCount++;
if (!pubsta)
local->dot11MulticastTransmittedFrameCount++;
@@ -856,10 +858,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
* Fragments are passed to low-level drivers as separate skbs, so these
* are actually fragments, not frames. Update frame counters only for
* the first fragment of the frame. */
- if (info->flags & IEEE80211_TX_STAT_ACK) {
+ if ((info->flags & IEEE80211_TX_STAT_ACK) ||
+ (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) {
if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
local->dot11TransmittedFrameCount++;
- if (is_multicast_ether_addr(hdr->addr1))
+ if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
local->dot11MulticastTransmittedFrameCount++;
if (retry_count > 0)
local->dot11RetryCount++;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 974ebe70f5b0..ad8cb4fb441e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1470,10 +1470,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
/* Check if any channel in this sband supports at least 80 MHz */
for (i = 0; i < sband->n_channels; i++) {
- if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) {
- have_80mhz = true;
- break;
- }
+ if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
+ IEEE80211_CHAN_NO_80MHZ))
+ continue;
+
+ have_80mhz = true;
+ break;
}
if (sband->vht_cap.vht_supported && have_80mhz) {
@@ -1735,6 +1737,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
struct cfg80211_sched_scan_request *sched_scan_req;
bool sched_scan_stopped = false;
+ /* nothing to do if HW shouldn't run */
+ if (!local->open_count)
+ goto wake_up;
+
#ifdef CONFIG_PM
if (local->suspended)
local->resuming = true;
@@ -1756,9 +1762,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
reconfig_due_to_wowlan = true;
}
#endif
- /* everything else happens only if HW was up & running */
- if (!local->open_count)
- goto wake_up;
/*
* Upon resume hardware can sometimes be goofy due to
@@ -2042,7 +2045,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
* If this is for hw restart things are still running.
* We may want to change that later, however.
*/
- if (!local->suspended || reconfig_due_to_wowlan)
+ if (local->open_count && (!local->suspended || reconfig_due_to_wowlan))
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
if (!local->suspended)
@@ -2054,7 +2057,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mb();
local->resuming = false;
- if (!reconfig_due_to_wowlan)
+ if (local->open_count && !reconfig_due_to_wowlan)
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
list_for_each_entry(sdata, &local->interfaces, list) {
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index bc9e8fc48785..85f9596da07b 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -269,51 +269,54 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
}
-enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
{
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- u32 cap = sta->sta.vht_cap.cap;
- enum ieee80211_sta_rx_bandwidth bw;
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
+ u32 cap_width;
- if (!sta->sta.vht_cap.vht_supported) {
- bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
- IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
- goto check_max;
- }
+ if (!vht_cap->vht_supported)
+ return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
+ IEEE80211_STA_RX_BW_40 :
+ IEEE80211_STA_RX_BW_20;
- switch (sdata->vif.bss_conf.chandef.width) {
- default:
- WARN_ON_ONCE(1);
- /* fall through */
+ cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+
+ if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
+ cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ return IEEE80211_STA_RX_BW_160;
+
+ return IEEE80211_STA_RX_BW_80;
+}
+
+static enum ieee80211_sta_rx_bandwidth
+ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
+{
+ switch (width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
- bw = IEEE80211_STA_RX_BW_20;
- break;
+ return IEEE80211_STA_RX_BW_20;
case NL80211_CHAN_WIDTH_40:
- bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
- IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
- break;
+ return IEEE80211_STA_RX_BW_40;
+ case NL80211_CHAN_WIDTH_80:
+ return IEEE80211_STA_RX_BW_80;
case NL80211_CHAN_WIDTH_160:
- if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) ==
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) {
- bw = IEEE80211_STA_RX_BW_160;
- break;
- }
- /* fall through */
case NL80211_CHAN_WIDTH_80P80:
- if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) ==
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) {
- bw = IEEE80211_STA_RX_BW_160;
- break;
- }
- /* fall through */
- case NL80211_CHAN_WIDTH_80:
- bw = IEEE80211_STA_RX_BW_80;
+ return IEEE80211_STA_RX_BW_160;
+ default:
+ WARN_ON_ONCE(1);
+ return IEEE80211_STA_RX_BW_20;
}
+}
+
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
+{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ enum ieee80211_sta_rx_bandwidth bw;
+
+ bw = ieee80211_chan_width_to_rx_bw(sdata->vif.bss_conf.chandef.width);
+ bw = min(bw, ieee80211_sta_cap_rx_bw(sta));
+ bw = min(bw, sta->cur_max_bandwidth);
- check_max:
- if (bw > sta->cur_max_bandwidth)
- bw = sta->cur_max_bandwidth;
return bw;
}