All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit d9fe60de authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

802.11: clean up/fix HT support

This patch cleans up a number of things:
 * the unusable definition of the HT capabilities/HT information
   information elements
 * variable names that are hard to understand
 * mac80211: move ieee80211_handle_ht to ht.c and remove the unused
             enable_ht parameter
 * mac80211: fix bug with MCS rate 32 in ieee80211_handle_ht
 * mac80211: fix bug with casting the result of ieee80211_bss_get_ie
             to an information element _contents_ rather than the
             whole element, add size checking (another out-of-bounds
             access bug fixed!)
 * mac80211: remove some unused return values in favour of BUG_ON
             checking
 * a few minor other things
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 40333e4f
......@@ -61,24 +61,24 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
switch (chan->band) {
case IEEE80211_BAND_2GHZ:
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
(tx_chan_width == ATH9K_HT_MACMODE_20))
chanmode = CHANNEL_G_HT20;
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
(tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_G_HT40PLUS;
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
(tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_G_HT40MINUS;
break;
case IEEE80211_BAND_5GHZ:
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
(tx_chan_width == ATH9K_HT_MACMODE_20))
chanmode = CHANNEL_A_HT20;
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
(tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_A_HT40PLUS;
if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
(tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_A_HT40MINUS;
break;
......@@ -215,24 +215,24 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
ath_key_reset(sc, key->keyidx, freeslot);
}
static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
{
#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
ht_info->ht_supported = 1;
ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
|(u16)IEEE80211_HT_CAP_SM_PS
|(u16)IEEE80211_HT_CAP_SGI_40
|(u16)IEEE80211_HT_CAP_DSSSCCK40;
ht_info->ht_supported = true;
ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_SM_PS |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
/* setup supported mcs set */
memset(ht_info->supp_mcs_set, 0, 16);
ht_info->supp_mcs_set[0] = 0xff;
ht_info->supp_mcs_set[1] = 0xff;
ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
ht_info->mcs.rx_mask[0] = 0xff;
ht_info->mcs.rx_mask[1] = 0xff;
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
static int ath_rate2idx(struct ath_softc *sc, int rate)
......@@ -328,31 +328,28 @@ static u8 parse_mpdudensity(u8 mpdudensity)
static void ath9k_ht_conf(struct ath_softc *sc,
struct ieee80211_bss_conf *bss_conf)
{
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
struct ath_ht_info *ht_info = &sc->sc_ht_info;
if (bss_conf->assoc_ht) {
ht_info->ext_chan_offset =
bss_conf->ht_bss_conf->bss_cap &
IEEE80211_HT_IE_CHA_SEC_OFFSET;
IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
if (!(bss_conf->ht_conf->cap &
if (!(bss_conf->ht_cap->cap &
IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
(bss_conf->ht_bss_conf->bss_cap &
IEEE80211_HT_IE_CHA_WIDTH))
IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
else
ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
bss_conf->ht_conf->ampdu_factor);
bss_conf->ht_cap->ampdu_factor);
ht_info->mpdudensity =
parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
parse_mpdudensity(bss_conf->ht_cap->ampdu_density);
}
#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
}
static void ath9k_bss_assoc_info(struct ath_softc *sc,
......@@ -411,7 +408,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
return;
}
if (hw->conf.ht_conf.ht_supported)
if (hw->conf.ht_cap.ht_supported)
sc->sc_ah->ah_channels[pos].chanmode =
ath_get_extchanmode(sc, curchan);
else
......@@ -534,7 +531,7 @@ int _ath_rx_indicate(struct ath_softc *sc,
if (an) {
ath_rx_input(sc, an,
hw->conf.ht_conf.ht_supported,
hw->conf.ht_cap.ht_supported,
skb, status, &st);
}
if (!an || (st != ATH_RX_CONSUMED))
......@@ -943,7 +940,7 @@ static int ath_attach(u16 devid,
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
/* Setup HT capabilities for 2.4Ghz*/
setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&sc->sbands[IEEE80211_BAND_2GHZ];
......@@ -958,7 +955,7 @@ static int ath_attach(u16 devid,
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
/* Setup HT capabilities for 5Ghz*/
setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
......@@ -1254,7 +1251,7 @@ static int ath9k_config(struct ieee80211_hw *hw,
(curchan->band == IEEE80211_BAND_2GHZ) ?
CHANNEL_G : CHANNEL_A;
if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
if (sc->sc_curaid && hw->conf.ht_cap.ht_supported)
sc->sc_ah->ah_channels[pos].chanmode =
ath_get_extchanmode(sc, curchan);
......
......@@ -1838,7 +1838,7 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
struct ath_softc *sc = hw->priv;
u32 capflag = 0;
if (hw->conf.ht_conf.ht_supported) {
if (hw->conf.ht_cap.ht_supported) {
capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG;
if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040)
capflag |= ATH_RC_CW40_FLAG;
......@@ -1910,7 +1910,7 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
*/
si = container_of(sta, struct sta_info, sta);
buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */
sband->ht_cap.ampdu_factor; /* FIXME */
state = si->ampdu_mlme.tid_state_tx[tidno];
if (state & HT_ADDBA_RECEIVED_MSK) {
......@@ -1979,7 +1979,7 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
/* Check if aggregation has to be enabled for this tid */
if (hw->conf.ht_conf.ht_supported) {
if (hw->conf.ht_cap.ht_supported) {
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
......@@ -2027,8 +2027,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
ath_setup_rates(sc, sband, sta, ath_rc_priv);
if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
for (i = 0; i < MCS_SET_SIZE; i++) {
if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
for (i = 0; i < 77; i++) {
if (sc->hw->conf.ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX)
break;
......
......@@ -59,7 +59,6 @@ struct ath_softc;
#define FALSE 0
#define ATH_RATE_MAX 30
#define MCS_SET_SIZE 128
enum ieee80211_fixed_rate_mode {
IEEE80211_FIXED_RATE_NONE = 0,
......
......@@ -1119,7 +1119,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
sband = hw->wiphy->bands[hw->conf.channel->band];
buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */
sband->ht_cap.ampdu_factor; /* FIXME */
rxtid = &an->an_aggr.rx.tid[tid];
......
......@@ -300,7 +300,7 @@ static int ath_tx_prepare(struct ath_softc *sc,
if (ieee80211_is_data(fc) && !txctl->use_minrate) {
/* Enable HT only for DATA frames and not for EAPOL */
txctl->ht = (hw->conf.ht_conf.ht_supported &&
txctl->ht = (hw->conf.ht_cap.ht_supported &&
(tx_info->flags & IEEE80211_TX_CTL_AMPDU));
if (is_multicast_ether_addr(hdr->addr1)) {
......
......@@ -1134,10 +1134,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s8 is_green = lq_sta->is_green;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported)
!sta->ht_cap.ht_supported)
return -1;
if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
== WLAN_HT_CAP_SM_PS_STATIC)
return -1;
......@@ -1202,7 +1202,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
s32 rate;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported)
!sta->ht_cap.ht_supported)
return -1;
IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
......@@ -2238,19 +2238,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
* supp_rates[] does not; shift to convert format, force 9 MBits off.
*/
lq_sta->active_siso_rate = conf->ht_conf.supp_mcs_set[0] << 1;
lq_sta->active_siso_rate |= conf->ht_conf.supp_mcs_set[0] & 0x1;
lq_sta->active_siso_rate = conf->ht_cap.mcs.rx_mask[0] << 1;
lq_sta->active_siso_rate |= conf->ht_cap.mcs.rx_mask[0] & 0x1;
lq_sta->active_siso_rate &= ~((u16)0x2);
lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
/* Same here */
lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1;
lq_sta->active_mimo2_rate |= conf->ht_conf.supp_mcs_set[1] & 0x1;
lq_sta->active_mimo2_rate = conf->ht_cap.mcs.rx_mask[1] << 1;
lq_sta->active_mimo2_rate |= conf->ht_cap.mcs.rx_mask[1] & 0x1;
lq_sta->active_mimo2_rate &= ~((u16)0x2);
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
lq_sta->active_mimo3_rate = conf->ht_conf.supp_mcs_set[2] << 1;
lq_sta->active_mimo3_rate |= conf->ht_conf.supp_mcs_set[2] & 0x1;
lq_sta->active_mimo3_rate = conf->ht_cap.mcs.rx_mask[2] << 1;
lq_sta->active_mimo3_rate |= conf->ht_cap.mcs.rx_mask[2] & 0x1;
lq_sta->active_mimo3_rate &= ~((u16)0x2);
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
......
......@@ -552,7 +552,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
static void iwl4965_ht_conf(struct iwl_priv *priv,
struct ieee80211_bss_conf *bss_conf)
{
struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
struct ieee80211_sta_ht_cap *ht_conf = bss_conf->ht_cap;
struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
......@@ -573,27 +573,27 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
iwl_conf->supported_chan_width =
!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
iwl_conf->extension_chan_offset =
ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
/* If no above or below channel supplied disable FAT channel */
if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE &&
iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) {
iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE;
if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) {
iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
iwl_conf->supported_chan_width = 0;
}
iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
iwl_conf->control_channel = ht_bss_conf->primary_channel;
iwl_conf->tx_chan_width =
!!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
!!(ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
iwl_conf->ht_protection =
ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_PROTECTION;
iwl_conf->non_GF_STA_present =
!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
IWL_DEBUG_MAC80211("leave\n");
......
......@@ -382,10 +382,10 @@ void iwl_reset_qos(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_reset_qos);
#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */
#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
struct ieee80211_ht_info *ht_info,
struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band)
{
u16 max_bit_rate = 0;
......@@ -393,45 +393,46 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
u8 tx_chains_num = priv->hw_params.tx_chains_num;
ht_info->cap = 0;
memset(ht_info->supp_mcs_set, 0, 16);
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
ht_info->ht_supported = 1;
ht_info->ht_supported = true;
ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS &
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.fat_channel & BIT(band)) {
ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
ht_info->supp_mcs_set[4] = 0x01;
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
ht_info->mcs.rx_mask[4] = 0x01;
max_bit_rate = MAX_BIT_RATE_40_MHZ;
}
if (priv->cfg->mod_params->amsdu_size_8K)
ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
ht_info->supp_mcs_set[0] = 0xFF;
ht_info->mcs.rx_mask[0] = 0xFF;
if (rx_chains_num >= 2)
ht_info->supp_mcs_set[1] = 0xFF;
ht_info->mcs.rx_mask[1] = 0xFF;
if (rx_chains_num >= 3)
ht_info->supp_mcs_set[2] = 0xFF;
ht_info->mcs.rx_mask[2] = 0xFF;
/* Highest supported Rx data rate */
max_bit_rate *= rx_chains_num;
ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF);
ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8);
WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
/* Tx MCS capabilities */
ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
if (tx_chains_num != rx_chains_num) {
ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF;
ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2);
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
}
}
......@@ -495,7 +496,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & IWL_SKU_N)
iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ];
......@@ -505,7 +506,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT;
if (priv->cfg->sku & IWL_SKU_N)
iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels;
......@@ -595,8 +596,8 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
static bool is_single_rx_stream(struct iwl_priv *priv)
{
return !priv->current_ht_config.is_ht ||
((priv->current_ht_config.supp_mcs_set[1] == 0) &&
(priv->current_ht_config.supp_mcs_set[2] == 0));
((priv->current_ht_config.mcs.rx_mask[1] == 0) &&
(priv->current_ht_config.mcs.rx_mask[2] == 0));
}
static u8 iwl_is_channel_extension(struct iwl_priv *priv,
......@@ -609,10 +610,10 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
if (!is_channel_valid(ch_info))
return 0;
if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE)
if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_ABOVE);
else if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW)
else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_BELOW);
......@@ -620,18 +621,18 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
}
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
struct ieee80211_ht_info *sta_ht_inf)
struct ieee80211_sta_ht_cap *sta_ht_inf)
{
struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
if ((!iwl_ht_conf->is_ht) ||
(iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
(iwl_ht_conf->extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE))
(iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
return 0;
if (sta_ht_inf) {
if ((!sta_ht_inf->ht_supported) ||
(!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
(!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
return 0;
}
......@@ -671,13 +672,13 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
/* Note: control channel is opposite of extension channel */
switch (ht_info->extension_chan_offset) {
case IEEE80211_HT_IE_CHA_SEC_ABOVE:
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
break;
case IEEE80211_HT_IE_CHA_SEC_BELOW:
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
break;
case IEEE80211_HT_IE_CHA_SEC_NONE:
case IEEE80211_HT_PARAM_CHA_SEC_NONE:
default:
rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
break;
......@@ -693,9 +694,9 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
"rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x "
"control chan %d\n",
ht_info->supp_mcs_set[0],
ht_info->supp_mcs_set[1],
ht_info->supp_mcs_set[2],
ht_info->mcs.rx_mask[0],
ht_info->mcs.rx_mask[1],
ht_info->mcs.rx_mask[2],
le32_to_cpu(rxon->flags), ht_info->ht_protection,
ht_info->extension_chan_offset,
ht_info->control_channel);
......
......@@ -190,7 +190,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
struct ieee80211_ht_info *sta_ht_inf);
struct ieee80211_sta_ht_cap *sta_ht_inf);
int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_setup_mac(struct iwl_priv *priv);
int iwl_set_hw_params(struct iwl_priv *priv);
......
......@@ -411,7 +411,7 @@ struct iwl_ht_info {
u8 max_amsdu_size;
u8 ampdu_factor;
u8 mpdu_density;
u8 supp_mcs_set[16];
struct ieee80211_mcs_info mcs;
/* BSS related data */
u8 control_channel;
u8 extension_chan_offset;
......@@ -585,7 +585,7 @@ struct iwl_addsta_cmd;
extern int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags);
extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
int is_ap, u8 flags, struct ieee80211_ht_info *ht_info);
int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
extern const u8 iwl_bcast_addr[ETH_ALEN];
......
......@@ -550,7 +550,7 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
{
struct ieee80211_ht_cap *ht_cap;
if (!sband || !sband->ht_info.ht_supported)
if (!sband || !sband->ht_cap.ht_supported)
return;
if (*left < sizeof(struct ieee80211_ht_cap))
......@@ -559,12 +559,12 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
*pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (struct ieee80211_ht_cap *) pos;
ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
ht_cap->ampdu_params_info =
(sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
((sband->ht_info.ampdu_density << 2) &
IEEE80211_HT_CAP_AMPDU_DENSITY);
(sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
((sband->ht_cap.ampdu_density << 2) &
IEEE80211_HT_AMPDU_PARM_DENSITY);
*left -= sizeof(struct ieee80211_ht_cap);
}
......
......@@ -181,7 +181,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
EXPORT_SYMBOL(iwl_send_add_sta);
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
struct ieee80211_ht_info *sta_ht_inf)
struct ieee80211_sta_ht_cap *sta_ht_inf)
{
__le32 sta_flags;
u8 mimo_ps_mode;
......@@ -229,7 +229,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
* iwl_add_station_flags - Add station to tables in driver and device
*/
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
u8 flags, struct ieee80211_ht_info *ht_info)
u8 flags, struct ieee80211_sta_ht_cap *ht_info)
{
int i;
int sta_id = IWL_INVALID_STATION;
......@@ -894,7 +894,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
/* Add station to device's station table */
struct ieee80211_conf *conf = &priv->hw->conf;
struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
struct ieee80211_sta_ht_cap *cur_ht_config = &conf->ht_cap;
if ((is_ap) &&
(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
......
......@@ -563,19 +563,18 @@ static int __init init_mac80211_hwsim(void)
data->band.n_channels = ARRAY_SIZE(hwsim_channels);
data->band.bitrates = data->rates;
data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
data->band.ht_info.ht_supported = 1;
data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
data->band.ht_cap.ht_supported = true;
data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
data->band.ht_info.ampdu_factor = 0x3;
data->band.ht_info.ampdu_density = 0x6;
memset(data->band.ht_info.supp_mcs_set, 0,
sizeof(data->band.ht_info.supp_mcs_set));
data->band.ht_info.supp_mcs_set[0] = 0xff;
data->band.ht_info.supp_mcs_set[1] = 0xff;
data->band.ht_info.supp_mcs_set[12] =
IEEE80211_HT_CAP_MCS_TX_DEFINED;
data->band.ht_cap.ampdu_factor = 0x3;
data->band.ht_cap.ampdu_density = 0x6;
memset(&data->band.ht_cap.mcs, 0,
sizeof(data->band.ht_cap.mcs));
data->band.ht_cap.mcs.rx_mask[0] = 0xff;
data->band.ht_cap.mcs.rx_mask[1] = 0xff;
data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
err = ieee80211_register_hw(hw);
......
......@@ -685,28 +685,88 @@ struct ieee80211_bar {
#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004
#define IEEE80211_HT_MCS_MASK_LEN 10
/**
* struct ieee80211_mcs_info - MCS information
* @rx_mask: RX mask
* @rx_highest: highest supported RX rate
* @tx_params: TX parameters
*/
struct ieee80211_mcs_info {
u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
__le16 rx_highest;
u8 tx_params;
u8 reserved[3];
} __attribute__((packed));
/* 802.11n HT capability MSC set */
#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff
#define IEEE80211_HT_MCS_TX_DEFINED 0x01