Skip to content

Commit

Permalink
mac80211: stop toggling IEEE80211_HT_CAP_SUP_WIDTH_20_40
Browse files Browse the repository at this point in the history
For VHT, many more bandwidth changes are possible. As a first
step, stop toggling the IEEE80211_HT_CAP_SUP_WIDTH_20_40 flag
in the HT capabilities and instead introduce a bandwidth field
indicating the currently usable bandwidth to transmit to the
station. Of course, make all drivers use it.

To achieve this, make ieee80211_ht_cap_ie_to_sta_ht_cap() get
the station as an argument, rather than the new capabilities,
so it can set up the new bandwidth field.

If the station is a VHT station and VHT bandwidth is in use,
also set the bandwidth accordingly.

Doing this allows us to get rid of the supports_40mhz flag as
the HT capabilities now reflect the true capability instead of
the current setting.

While at it, also fix ieee80211_ht_cap_ie_to_sta_ht_cap() to not
ignore HT cap overrides when MCS TX isn't supported (not that it
really happens...)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Feb 15, 2013
1 parent 4a34215 commit e1a0c6b
Show file tree
Hide file tree
Showing 27 changed files with 184 additions and 158 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta)
caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
else if (sta->ht_cap.mcs.rx_mask[1])
caps |= WLAN_RC_DS_FLAG;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
caps |= WLAN_RC_40_FLAG;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
caps |= WLAN_RC_SGI_FLAG;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/dvm/agn.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,

bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_sta_ht_cap *ht_cap);
struct ieee80211_sta *sta);

static inline int iwl_sta_id(struct ieee80211_sta *sta)
{
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/wireless/iwlwifi/dvm/rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate;

if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down Expand Up @@ -1361,7 +1361,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate;

if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down Expand Up @@ -1410,7 +1410,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate;

if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down
19 changes: 5 additions & 14 deletions drivers/net/wireless/iwlwifi/dvm/sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,

bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_sta_ht_cap *ht_cap)
struct ieee80211_sta *sta)
{
if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
return false;
Expand All @@ -183,20 +183,11 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
return false;
#endif

/*
* Remainder of this function checks ht_cap, but if it's
* NULL then we can do HT40 (special case for RXON)
*/
if (!ht_cap)
/* special case for RXON */
if (!sta)
return true;

if (!ht_cap->ht_supported)
return false;

if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
return false;

return true;
return sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}

static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
Expand Down Expand Up @@ -246,7 +237,7 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
*flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);

if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
*flags |= STA_FLG_HT40_EN_MSK;
}

Expand Down
24 changes: 5 additions & 19 deletions drivers/net/wireless/iwlwifi/mvm/rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,23 +1209,9 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
return new_rate;
}

static bool iwl_is_ht40_tx_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta_ht_cap *ht_cap)
static bool iwl_is_ht40_tx_allowed(struct ieee80211_sta *sta)
{
/*
* Remainder of this function checks ht_cap, but if it's
* NULL then we can do HT40 (special case for RXON)
*/
if (!ht_cap)
return true;

if (!ht_cap->ht_supported)
return false;

if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
return false;

return true;
return sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}

/*
Expand Down Expand Up @@ -1258,7 +1244,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate;

if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down Expand Up @@ -1311,7 +1297,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate;

if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down Expand Up @@ -1356,7 +1342,7 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate;

if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
if (iwl_is_ht40_tx_allowed(sta))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
Expand Down
7 changes: 3 additions & 4 deletions drivers/net/wireless/rtlwifi/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
if (mac->opmode == NL80211_IFTYPE_STATION)
bw_40 = mac->bw_40;
else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC)
bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
mac->opmode == NL80211_IFTYPE_ADHOC)
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;

if (bw_40 && sgi_40)
tcb_desc->use_shortgi = true;
Expand Down Expand Up @@ -634,8 +634,7 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
return;
if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (!(sta->ht_cap.ht_supported) ||
!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
return;
} else if (mac->opmode == NL80211_IFTYPE_STATION) {
if (!mac->bw_40 || !(sta->ht_cap.ht_supported))
Expand Down
5 changes: 2 additions & 3 deletions drivers/net/wireless/rtlwifi/rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,8 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv,
if (txrc->short_preamble)
rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta && (sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40))
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta && (sta->bandwidth >= IEEE80211_STA_RX_BW_40))
rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
} else {
if (mac->bw_40)
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1846,9 +1846,9 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry = NULL;
u32 ratr_bitmap;
u8 ratr_index;
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
? 1 : 0;
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
u8 curshortgi_40mhz = curtxbw_40mhz &&
(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1 : 0;
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
1 : 0;
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}

seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8192de/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1970,8 +1970,7 @@ static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry = NULL;
u32 ratr_bitmap;
u8 ratr_index;
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
? 1 : 0;
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1 : 0;
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8192de/trx.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,7 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8192se/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2085,8 +2085,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry = NULL;
u32 ratr_bitmap;
u8 ratr_index = 0;
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
? 1 : 0;
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1 : 0;
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8192se/trx.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}

seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1866,8 +1866,7 @@ static void rtl8723ae_update_hal_rate_mask(struct ieee80211_hw *hw,
struct rtl_sta_info *sta_entry = NULL;
u32 ratr_bitmap;
u8 ratr_index;
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
? 1 : 0;
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1 : 0;
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,7 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}

seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ti/wl18xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ static void wl18xx_sta_rc_update(struct wl1271 *wl,
struct ieee80211_sta *sta,
u32 changed)
{
bool wide = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
bool wide = sta->bandwidth >= IEEE80211_STA_RX_BW_40;

wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);

Expand Down
24 changes: 23 additions & 1 deletion include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,24 @@ enum ieee80211_sta_state {
IEEE80211_STA_AUTHORIZED,
};

/**
* enum ieee80211_sta_rx_bandwidth - station RX bandwidth
* @IEEE80211_STA_RX_BW_20: station can only receive 20 MHz
* @IEEE80211_STA_RX_BW_40: station can receive up to 40 MHz
* @IEEE80211_STA_RX_BW_80: station can receive up to 80 MHz
* @IEEE80211_STA_RX_BW_160: station can receive up to 160 MHz
* (including 80+80 MHz)
*
* Implementation note: 20 must be zero to be initialized
* correctly, the values must be sorted.
*/
enum ieee80211_sta_rx_bandwidth {
IEEE80211_STA_RX_BW_20 = 0,
IEEE80211_STA_RX_BW_40,
IEEE80211_STA_RX_BW_80,
IEEE80211_STA_RX_BW_160,
};

/**
* struct ieee80211_sta - station table entry
*
Expand All @@ -1218,6 +1236,7 @@ enum ieee80211_sta_state {
* @uapsd_queues: bitmap of queues configured for uapsd. Only valid
* if wme is supported.
* @max_sp: max Service Period. Only valid if wme is supported.
* @bandwidth: current bandwidth the station can receive with
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
Expand All @@ -1228,6 +1247,7 @@ struct ieee80211_sta {
bool wme;
u8 uapsd_queues;
u8 max_sp;
enum ieee80211_sta_rx_bandwidth bandwidth;

/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
Expand Down Expand Up @@ -2086,7 +2106,9 @@ enum ieee80211_frame_release_type {
* enum ieee80211_rate_control_changed - flags to indicate what changed
*
* @IEEE80211_RC_BW_CHANGED: The bandwidth that can be used to transmit
* to this station changed.
* to this station changed. The actual bandwidth is in the station
* information -- for HT20/40 the IEEE80211_HT_CAP_SUP_WIDTH_20_40
* flag changes, for HT and VHT the bandwidth field changes.
* @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed.
* @IEEE80211_RC_SUPP_RATES_CHANGED: The supported rate set of this peer
* changed (in IBSS mode) due to discovering more information about
Expand Down
3 changes: 1 addition & 2 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,

if (params->ht_capa)
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
params->ht_capa,
&sta->sta.ht_cap);
params->ht_capa, sta);

if (params->vht_capa)
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
Expand Down
Loading

0 comments on commit e1a0c6b

Please sign in to comment.