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, ...@@ -61,24 +61,24 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
switch (chan->band) { switch (chan->band) {
case IEEE80211_BAND_2GHZ: 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)) (tx_chan_width == ATH9K_HT_MACMODE_20))
chanmode = CHANNEL_G_HT20; 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)) (tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_G_HT40PLUS; 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)) (tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_G_HT40MINUS; chanmode = CHANNEL_G_HT40MINUS;
break; break;
case IEEE80211_BAND_5GHZ: 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)) (tx_chan_width == ATH9K_HT_MACMODE_20))
chanmode = CHANNEL_A_HT20; 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)) (tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_A_HT40PLUS; 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)) (tx_chan_width == ATH9K_HT_MACMODE_2040))
chanmode = CHANNEL_A_HT40MINUS; chanmode = CHANNEL_A_HT40MINUS;
break; break;
...@@ -215,24 +215,24 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) ...@@ -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); 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_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ #define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
ht_info->ht_supported = 1; ht_info->ht_supported = true;
ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|(u16)IEEE80211_HT_CAP_SM_PS IEEE80211_HT_CAP_SM_PS |
|(u16)IEEE80211_HT_CAP_SGI_40 IEEE80211_HT_CAP_SGI_40 |
|(u16)IEEE80211_HT_CAP_DSSSCCK40; IEEE80211_HT_CAP_DSSSCCK40;
ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
/* setup supported mcs set */ /* set up supported mcs set */
memset(ht_info->supp_mcs_set, 0, 16); memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
ht_info->supp_mcs_set[0] = 0xff; ht_info->mcs.rx_mask[0] = 0xff;
ht_info->supp_mcs_set[1] = 0xff; ht_info->mcs.rx_mask[1] = 0xff;
ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED; ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
} }
static int ath_rate2idx(struct ath_softc *sc, int rate) static int ath_rate2idx(struct ath_softc *sc, int rate)
...@@ -328,31 +328,28 @@ static u8 parse_mpdudensity(u8 mpdudensity) ...@@ -328,31 +328,28 @@ static u8 parse_mpdudensity(u8 mpdudensity)
static void ath9k_ht_conf(struct ath_softc *sc, static void ath9k_ht_conf(struct ath_softc *sc,
struct ieee80211_bss_conf *bss_conf) struct ieee80211_bss_conf *bss_conf)
{ {
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
struct ath_ht_info *ht_info = &sc->sc_ht_info; struct ath_ht_info *ht_info = &sc->sc_ht_info;
if (bss_conf->assoc_ht) { if (bss_conf->assoc_ht) {
ht_info->ext_chan_offset = ht_info->ext_chan_offset =
bss_conf->ht_bss_conf->bss_cap & 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) && IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
(bss_conf->ht_bss_conf->bss_cap & (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; ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
else else
ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
bss_conf->ht_conf->ampdu_factor); bss_conf->ht_cap->ampdu_factor);
ht_info->mpdudensity = 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, static void ath9k_bss_assoc_info(struct ath_softc *sc,
...@@ -411,7 +408,7 @@ 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; return;
} }
if (hw->conf.ht_conf.ht_supported) if (hw->conf.ht_cap.ht_supported)
sc->sc_ah->ah_channels[pos].chanmode = sc->sc_ah->ah_channels[pos].chanmode =
ath_get_extchanmode(sc, curchan); ath_get_extchanmode(sc, curchan);
else else
...@@ -534,7 +531,7 @@ int _ath_rx_indicate(struct ath_softc *sc, ...@@ -534,7 +531,7 @@ int _ath_rx_indicate(struct ath_softc *sc,
if (an) { if (an) {
ath_rx_input(sc, an, ath_rx_input(sc, an,
hw->conf.ht_conf.ht_supported, hw->conf.ht_cap.ht_supported,
skb, status, &st); skb, status, &st);
} }
if (!an || (st != ATH_RX_CONSUMED)) if (!an || (st != ATH_RX_CONSUMED))
...@@ -943,7 +940,7 @@ static int ath_attach(u16 devid, ...@@ -943,7 +940,7 @@ static int ath_attach(u16 devid,
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
/* Setup HT capabilities for 2.4Ghz*/ /* 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] = hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&sc->sbands[IEEE80211_BAND_2GHZ]; &sc->sbands[IEEE80211_BAND_2GHZ];
...@@ -958,7 +955,7 @@ static int ath_attach(u16 devid, ...@@ -958,7 +955,7 @@ static int ath_attach(u16 devid,
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
/* Setup HT capabilities for 5Ghz*/ /* 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] = hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ]; &sc->sbands[IEEE80211_BAND_5GHZ];
...@@ -1254,7 +1251,7 @@ static int ath9k_config(struct ieee80211_hw *hw, ...@@ -1254,7 +1251,7 @@ static int ath9k_config(struct ieee80211_hw *hw,
(curchan->band == IEEE80211_BAND_2GHZ) ? (curchan->band == IEEE80211_BAND_2GHZ) ?
CHANNEL_G : CHANNEL_A; 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 = sc->sc_ah->ah_channels[pos].chanmode =
ath_get_extchanmode(sc, curchan); ath_get_extchanmode(sc, curchan);
......
...@@ -1838,7 +1838,7 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) ...@@ -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; struct ath_softc *sc = hw->priv;
u32 capflag = 0; 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; capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG;
if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040)
capflag |= ATH_RC_CW40_FLAG; capflag |= ATH_RC_CW40_FLAG;
...@@ -1910,7 +1910,7 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, ...@@ -1910,7 +1910,7 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
*/ */
si = container_of(sta, struct sta_info, sta); si = container_of(sta, struct sta_info, sta);
buffersize = IEEE80211_MIN_AMPDU_BUF << 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]; state = si->ampdu_mlme.tid_state_tx[tidno];
if (state & HT_ADDBA_RECEIVED_MSK) { if (state & HT_ADDBA_RECEIVED_MSK) {
...@@ -1979,7 +1979,7 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, ...@@ -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 */ /* 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)) { if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr); qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf; tid = qc[0] & 0xf;
...@@ -2027,8 +2027,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ...@@ -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); ath_setup_rates(sc, sband, sta, ath_rc_priv);
if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
for (i = 0; i < MCS_SET_SIZE; i++) { for (i = 0; i < 77; i++) {
if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) if (sc->hw->conf.ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX) if (j == ATH_RATE_MAX)
break; break;
......
...@@ -59,7 +59,6 @@ struct ath_softc; ...@@ -59,7 +59,6 @@ struct ath_softc;
#define FALSE 0 #define FALSE 0
#define ATH_RATE_MAX 30 #define ATH_RATE_MAX 30
#define MCS_SET_SIZE 128
enum ieee80211_fixed_rate_mode { enum ieee80211_fixed_rate_mode {
IEEE80211_FIXED_RATE_NONE = 0, IEEE80211_FIXED_RATE_NONE = 0,
......
...@@ -1119,7 +1119,7 @@ int ath_rx_aggr_start(struct ath_softc *sc, ...@@ -1119,7 +1119,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
sband = hw->wiphy->bands[hw->conf.channel->band]; sband = hw->wiphy->bands[hw->conf.channel->band];
buffersize = IEEE80211_MIN_AMPDU_BUF << buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */ sband->ht_cap.ampdu_factor; /* FIXME */
rxtid = &an->an_aggr.rx.tid[tid]; rxtid = &an->an_aggr.rx.tid[tid];
......
...@@ -300,7 +300,7 @@ static int ath_tx_prepare(struct ath_softc *sc, ...@@ -300,7 +300,7 @@ static int ath_tx_prepare(struct ath_softc *sc,
if (ieee80211_is_data(fc) && !txctl->use_minrate) { if (ieee80211_is_data(fc) && !txctl->use_minrate) {
/* Enable HT only for DATA frames and not for EAPOL */ /* 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)); (tx_info->flags & IEEE80211_TX_CTL_AMPDU));
if (is_multicast_ether_addr(hdr->addr1)) { if (is_multicast_ether_addr(hdr->addr1)) {
......
...@@ -1134,10 +1134,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, ...@@ -1134,10 +1134,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s8 is_green = lq_sta->is_green; s8 is_green = lq_sta->is_green;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported) !sta->ht_cap.ht_supported)
return -1; 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) == WLAN_HT_CAP_SM_PS_STATIC)
return -1; return -1;
...@@ -1202,7 +1202,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, ...@@ -1202,7 +1202,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
s32 rate; s32 rate;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported) !sta->ht_cap.ht_supported)
return -1; return -1;
IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); 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, ...@@ -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), * 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. * 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_cap.mcs.rx_mask[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] & 0x1;
lq_sta->active_siso_rate &= ~((u16)0x2); lq_sta->active_siso_rate &= ~((u16)0x2);
lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
/* Same here */ /* Same here */
lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1; lq_sta->active_mimo2_rate = conf->ht_cap.mcs.rx_mask[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] & 0x1;
lq_sta->active_mimo2_rate &= ~((u16)0x2); lq_sta->active_mimo2_rate &= ~((u16)0x2);
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; 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_cap.mcs.rx_mask[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] & 0x1;
lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate &= ~((u16)0x2);
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
......
...@@ -552,7 +552,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) ...@@ -552,7 +552,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
static void iwl4965_ht_conf(struct iwl_priv *priv, static void iwl4965_ht_conf(struct iwl_priv *priv,
struct ieee80211_bss_conf *bss_conf) 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 ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
struct iwl_ht_info *iwl_conf = &priv->current_ht_config; struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
...@@ -573,27 +573,27 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, ...@@ -573,27 +573,27 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
iwl_conf->supported_chan_width = 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 = 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 no above or below channel supplied disable FAT channel */
if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE && if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) { iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) {
iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE; iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
iwl_conf->supported_chan_width = 0; iwl_conf->supported_chan_width = 0;
} }
iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); 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->control_channel = ht_bss_conf->primary_channel;
iwl_conf->tx_chan_width = 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 = 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 = 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("control channel %d\n", iwl_conf->control_channel);
IWL_DEBUG_MAC80211("leave\n"); IWL_DEBUG_MAC80211("leave\n");
......
...@@ -382,10 +382,10 @@ void iwl_reset_qos(struct iwl_priv *priv) ...@@ -382,10 +382,10 @@ void iwl_reset_qos(struct iwl_priv *priv)
} }
EXPORT_SYMBOL(iwl_reset_qos); EXPORT_SYMBOL(iwl_reset_qos);
#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */ #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, 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) enum ieee80211_band band)
{ {
u16 max_bit_rate = 0; u16 max_bit_rate = 0;
...@@ -393,45 +393,46 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ...@@ -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; u8 tx_chains_num = priv->hw_params.tx_chains_num;
ht_info->cap = 0; 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 |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS & ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2)); (WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ; max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.fat_channel & BIT(band)) { if (priv->hw_params.fat_channel & BIT(band)) {
ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH; ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40; ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
ht_info->supp_mcs_set[4] = 0x01; ht_info->mcs.rx_mask[4] = 0x01;
max_bit_rate = MAX_BIT_RATE_40_MHZ; max_bit_rate = MAX_BIT_RATE_40_MHZ;
} }
if (priv->cfg->mod_params->amsdu_size_8K) 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_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_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) if (rx_chains_num >= 2)
ht_info->supp_mcs_set[1] = 0xFF; ht_info->mcs.rx_mask[1] = 0xFF;
if (rx_chains_num >= 3) if (rx_chains_num >= 3)
ht_info->supp_mcs_set[2] = 0xFF; ht_info->mcs.rx_mask[2] = 0xFF;
/* Highest supported Rx data rate */ /* Highest supported Rx data rate */
max_bit_rate *= rx_chains_num; max_bit_rate *= rx_chains_num;
ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF); WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8); ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
/* Tx MCS capabilities */ /* 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) { if (tx_chains_num != rx_chains_num) {
ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF; ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2); 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) ...@@ -495,7 +496,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & IWL_SKU_N) 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); IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ]; sband = &priv->bands[IEEE80211_BAND_2GHZ];
...@@ -505,7 +506,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv) ...@@ -505,7 +506,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT; sband->n_bitrates = IWL_RATE_COUNT;
if (priv->cfg->sku & IWL_SKU_N) 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); IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels; priv->ieee_channels = channels;
...@@ -595,8 +596,8 @@ static void iwlcore_free_geos(struct iwl_priv *priv) ...@@ -595,8 +596,8 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
static bool is_single_rx_stream(struct iwl_priv *priv) static bool is_single_rx_stream(struct iwl_priv *priv)
{ {
return !priv->current_ht_config.is_ht || return !priv->current_ht_config.is_ht ||
((priv->current_ht_config.supp_mcs_set[1] == 0) && ((priv->current_ht_config.mcs.rx_mask[1] == 0) &&
(priv->current_ht_config.supp_mcs_set[2] == 0)); (priv->current_ht_config.mcs.rx_mask[2] == 0));
} }
static u8 iwl_is_channel_extension(struct iwl_priv *priv, static u8 iwl_is_channel_extension(struct iwl_priv *priv,
...@@ -609,10 +610,10 @@ 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)) if (!is_channel_valid(ch_info))
return 0; 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 & return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_ABOVE); 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 & return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_BELOW); IEEE80211_CHAN_NO_FAT_BELOW);
...@@ -620,18 +621,18 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, ...@@ -620,18 +621,18 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
} }
u8 iwl_is_fat_tx_allowed(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; struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
if ((!iwl_ht_conf->is_ht) || if ((!iwl_ht_conf->is_ht) ||
(iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || (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; return 0;
if (sta_ht_inf) { if (sta_ht_inf) {
if ((!sta_ht_inf->ht_supported) || 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; return 0;
} }
...@@ -671,13 +672,13 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) ...@@ -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 */ /* Note: control channel is opposite of extension channel */
switch (ht_info->extension_chan_offset) { 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); rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
break; break;
case IEEE80211_HT_IE_CHA_SEC_BELOW: case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
break; break;
case IEEE80211_HT_IE_CHA_SEC_NONE: case IEEE80211_HT_PARAM_CHA_SEC_NONE:
default: default:
rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
break; break;
...@@ -693,9 +694,9 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) ...@@ -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 " "rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x " "extension channel offset 0x%x "
"control chan %d\n", "control chan %d\n",
ht_info->supp_mcs_set[0], ht_info->mcs.rx_mask[0],
ht_info->supp_mcs_set[1], ht_info->mcs.rx_mask[1],
ht_info->supp_mcs_set[2], ht_info->mcs.rx_mask[2],
le32_to_cpu(rxon->flags), ht_info->ht_protection, le32_to_cpu(rxon->flags), ht_info->ht_protection,
ht_info->extension_chan_offset, ht_info->extension_chan_offset,
ht_info->control_channel); ht_info->control_channel);
......
...@@ -190,7 +190,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv); ...@@ -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); 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); 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, 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_hw_nic_init(struct iwl_priv *priv);
int iwl_setup_mac(struct iwl_priv *priv); int iwl_setup_mac(struct iwl_priv *priv);
int iwl_set_hw_params(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv);
......
...@@ -411,7 +411,7 @@ struct iwl_ht_info { ...@@ -411,7 +411,7 @@ struct iwl_ht_info {
u8 max_amsdu_size; u8 max_amsdu_size;
u8 ampdu_factor; u8 ampdu_factor;
u8 mpdu_density; u8 mpdu_density;
u8 supp_mcs_set[16]; struct ieee80211_mcs_info mcs;
/* BSS related data */ /* BSS related data */
u8 control_channel; u8 control_channel;
u8 extension_chan_offset; u8 extension_chan_offset;
...@@ -585,7 +585,7 @@ struct iwl_addsta_cmd; ...@@ -585,7 +585,7 @@ struct iwl_addsta_cmd;
extern int iwl_send_add_sta(struct iwl_priv *priv, extern int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags); struct iwl_addsta_cmd *sta, u8 flags);
extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, 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 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 int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
extern const u8 iwl_bcast_addr[ETH_ALEN]; 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, ...@@ -550,7 +550,7 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
{ {
struct ieee80211_ht_cap *ht_cap; struct ieee80211_ht_cap *ht_cap;
if (!sband || !sband->ht_info.ht_supported) if (!sband || !sband->ht_cap.ht_supported)
return; return;
if (*left < sizeof(struct ieee80211_ht_cap)) if (*left < sizeof(struct ieee80211_ht_cap))
...@@ -559,12 +559,12 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, ...@@ -559,12 +559,12 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
*pos++ = sizeof(struct ieee80211_ht_cap); *pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (struct ieee80211_ht_cap *) pos; ht_cap = (struct ieee80211_ht_cap *) pos;
ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap); ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16); memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
ht_cap->ampdu_params_info = ht_cap->ampdu_params_info =
(sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) | (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
((sband->ht_info.ampdu_density << 2) & ((sband->ht_cap.ampdu_density << 2) &
IEEE80211_HT_CAP_AMPDU_DENSITY); IEEE80211_HT_AMPDU_PARM_DENSITY);
*left -= sizeof(struct ieee80211_ht_cap); *left -= sizeof(struct ieee80211_ht_cap);
} }
......
...@@ -181,7 +181,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, ...@@ -181,7 +181,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
EXPORT_SYMBOL(iwl_send_add_sta); EXPORT_SYMBOL(iwl_send_add_sta);
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, 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; __le32 sta_flags;
u8 mimo_ps_mode; u8 mimo_ps_mode;
...@@ -229,7 +229,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, ...@@ -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 * 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 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 i;
int sta_id = IWL_INVALID_STATION; 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) ...@@ -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 */ /* Add station to device's station table */
struct ieee80211_conf *conf = &priv->hw->conf; 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) && if ((is_ap) &&
(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
......
...@@ -563,19 +563,18 @@ static int __init init_mac80211_hwsim(void) ...@@ -563,19 +563,18 @@ static int __init init_mac80211_hwsim(void)
data->band.n_channels = ARRAY_SIZE(hwsim_channels); data->band.n_channels = ARRAY_SIZE(hwsim_channels);
data->band.bitrates = data->rates; data->band.bitrates = data->rates;
data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
data->band.ht_info.ht_supported = 1; data->band.ht_cap.ht_supported = true;
data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH | data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40; IEEE80211_HT_CAP_DSSSCCK40;
data->band.ht_info.ampdu_factor = 0x3; data->band.ht_cap.ampdu_factor = 0x3;
data->band.ht_info.ampdu_density = 0x6; data->band.ht_cap.ampdu_density = 0x6;
memset(data->band.ht_info.supp_mcs_set, 0, memset(&data->band.ht_cap.mcs, 0,
sizeof(data->band.ht_info.supp_mcs_set)); sizeof(data->band.ht_cap.mcs));
data->band.ht_info.supp_mcs_set[0] = 0xff; data->band.ht_cap.mcs.rx_mask[0] = 0xff;
data->band.ht_info.supp_mcs_set[1] = 0xff; data->band.ht_cap.mcs.rx_mask[1] = 0xff;
data->band.ht_info.supp_mcs_set[12] = data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
IEEE80211_HT_CAP_MCS_TX_DEFINED;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
err = ieee80211_register_hw(hw); err = ieee80211_register_hw(hw);
......
...@@ -685,28 +685,88 @@ struct ieee80211_bar { ...@@ -685,28 +685,88 @@ struct ieee80211_bar {
#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 #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
#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02
/* value 0 == 1 stream etc */
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
/*
* 802.11n D5.0 20.3.5 / 20.6 says:
* - indices 0 to 7 and 32 are single spatial stream
* - 8 to 31 are multiple spatial streams using equal modulation
* [8..15 for two streams, 16..23 for three and 24..31 for four]
* - remainder are multiple spatial streams using unequal modulation
*/
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \
(IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
/** /**
* struct ieee80211_ht_cap - HT capabilities * struct ieee80211_ht_cap - HT capabilities
* *
* This structure refers to "HT capabilities element" as * This structure is the "HT capabilities element" as
* described in 802.11n draft section 7.3.2.52 * described in 802.11n D5.0 7.3.2.57
*/ */
struct ieee80211_ht_cap { struct ieee80211_ht_cap {
__le16 cap_info; __le16 cap_info;
u8 ampdu_params_info; u8 ampdu_params_info;
u8 supp_mcs_set[16];
/* 16 bytes MCS information */
struct ieee80211_mcs_info mcs;
__le16 extended_ht_cap_info; __le16 extended_ht_cap_info;
__le32 tx_BF_cap_info; __le32 tx_BF_cap_info;
u8 antenna_selection_info; u8 antenna_selection_info;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* 802.11n HT capabilities masks (for cap_info) */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
#define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
/** /**
* struct ieee80211_ht_cap - HT additional information * struct ieee80211_ht_info - HT information
* *
* This structure refers to "HT information element" as * This structure is the "HT information element" as
* described in 802.11n draft section 7.3.2.53 * described in 802.11n D5.0 7.3.2.58
*/ */
struct ieee80211_ht_addt_info { struct ieee80211_ht_info {
u8 control_chan; u8 control_chan;
u8 ht_param; u8 ht_param;
__le16 operation_mode; __le16 operation_mode;
...@@ -714,36 +774,33 @@ struct ieee80211_ht_addt_info { ...@@ -714,36 +774,33 @@ struct ieee80211_ht_addt_info {
u8 basic_set[16]; u8 basic_set[16];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* 802.11n HT capabilities masks */ /* for ht_param */
#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002 #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03
#define IEEE80211_HT_CAP_SM_PS 0x000C #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00
#define IEEE80211_HT_CAP_GRN_FLD 0x0010 #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01
#define IEEE80211_HT_CAP_SGI_20 0x0020 #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03
#define IEEE80211_HT_CAP_SGI_40 0x0040 #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04
#define IEEE80211_HT_CAP_DELAY_BA 0x0400 #define IEEE80211_HT_PARAM_RIFS_MODE 0x08
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0
/* 802.11n HT capability AMPDU settings */
#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03 /* for operation_mode */
#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003
/* 802.11n HT capability MSC set */ #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0
#define IEEE80211_SUPP_MCS_SET_UEQM 4 #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1
#define IEEE80211_HT_CAP_MAX_STREAMS 4 #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2
#define IEEE80211_SUPP_MCS_SET_LEN 10 #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3
/* maximum streams the spec allows */ #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004
#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01 #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010
#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02
#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C /* for stbc_param */
#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040
/* 802.11n HT IE masks */ #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080
#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03 #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100
#define IEEE80211_HT_IE_CHA_SEC_NONE 0x00 #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200
#define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01 #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400
#define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03 #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800
#define IEEE80211_HT_IE_CHA_WIDTH 0x04
#define IEEE80211_HT_IE_HT_PROTECTION 0x0003
#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004
#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010
/* block-ack parameters */ /* block-ack parameters */
#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
...@@ -949,7 +1006,7 @@ enum ieee80211_eid { ...@@ -949,7 +1006,7 @@ enum ieee80211_eid {
WLAN_EID_EXT_SUPP_RATES = 50, WLAN_EID_EXT_SUPP_RATES = 50,
/* 802.11n */ /* 802.11n */
WLAN_EID_HT_CAPABILITY = 45, WLAN_EID_HT_CAPABILITY = 45,
WLAN_EID_HT_EXTRA_INFO = 61, WLAN_EID_HT_INFORMATION = 61,
/* 802.11i */ /* 802.11i */
WLAN_EID_RSN = 48, WLAN_EID_RSN = 48,
WLAN_EID_WPA = 221, WLAN_EID_WPA = 221,
......
...@@ -191,7 +191,7 @@ enum ieee80211_bss_change { ...@@ -191,7 +191,7 @@ enum ieee80211_bss_change {
* @beacon_int: beacon interval * @beacon_int: beacon interval
* @assoc_capability: capabilities taken from assoc resp * @assoc_capability: capabilities taken from assoc resp
* @assoc_ht: association in HT mode * @assoc_ht: association in HT mode
* @ht_conf: ht capabilities * @ht_cap: ht capabilities
* @ht_bss_conf: ht extended capabilities * @ht_bss_conf: ht extended capabilities
* @basic_rates: bitmap of basic rates, each bit stands for an * @basic_rates: bitmap of basic rates, each bit stands for an
* index into the rate table configured by the driver in * index into the rate table configured by the driver in
...@@ -212,7 +212,7 @@ struct ieee80211_bss_conf { ...@@ -212,7 +212,7 @@ struct ieee80211_bss_conf {
u64 basic_rates; u64 basic_rates;
/* ht related data */ /* ht related data */
bool assoc_ht; bool assoc_ht;
struct ieee80211_ht_info *ht_conf; struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_ht_bss_info *ht_bss_conf; struct ieee80211_ht_bss_info *ht_bss_conf;
}; };
...@@ -477,7 +477,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) ...@@ -477,7 +477,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void)
* @antenna_sel_tx: transmit antenna selection, 0: default/diversity, * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
* 1/2: antenna 0/1 * 1/2: antenna 0/1
* @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
* @ht_conf: describes current self configuration of 802.11n HT capabilies * @ht_cap: describes current self configuration of 802.11n HT capabilities
* @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters
* @channel: the channel to tune to * @channel: the channel to tune to
*/ */
...@@ -493,7 +493,7 @@ struct ieee80211_conf { ...@@ -493,7 +493,7 @@ struct ieee80211_conf {
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
struct ieee80211_ht_info ht_conf; struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_ht_bss_info ht_bss_conf; struct ieee80211_ht_bss_info ht_bss_conf;
}; };
...@@ -687,7 +687,7 @@ enum set_key_cmd { ...@@ -687,7 +687,7 @@ enum set_key_cmd {
* @addr: MAC address * @addr: MAC address
* @aid: AID we assigned to the station if we're an AP * @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band) * @supp_rates: Bitmap of supported rates (per band)
* @ht_info: HT capabilities of this STA * @ht_cap: HT capabilities of this STA
* @drv_priv: data area for driver use, will always be aligned to * @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information. * sizeof(void *), size is determined in hw information.
*/ */
...@@ -695,7 +695,7 @@ struct ieee80211_sta { ...@@ -695,7 +695,7 @@ struct ieee80211_sta {
u64 supp_rates[IEEE80211_NUM_BANDS]; u64 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
u16 aid; u16 aid;
struct ieee80211_ht_info ht_info; struct ieee80211_sta_ht_cap ht_cap;
/* must be last */ /* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h> #include <net/cfg80211.h>
/** /**
...@@ -133,23 +134,23 @@ struct ieee80211_rate { ...@@ -133,23 +134,23 @@ struct ieee80211_rate {
}; };
/** /**
* struct ieee80211_ht_info - describing STA's HT capabilities * struct ieee80211_sta_ht_cap - STA's HT capabilities
* *
* This structure describes most essential parameters needed * This structure describes most essential parameters needed
* to describe 802.11n HT capabilities for an STA. * to describe 802.11n HT capabilities for an STA.
* *
* @ht_supported: is HT supported by STA, 0: no, 1: yes * @ht_supported: is HT supported by the STA
* @cap: HT capabilities map as described in 802.11n spec * @cap: HT capabilities map as described in 802.11n spec
* @ampdu_factor: Maximum A-MPDU length factor * @ampdu_factor: Maximum A-MPDU length factor
* @ampdu_density: Minimum A-MPDU spacing * @ampdu_density: Minimum A-MPDU spacing
* @supp_mcs_set: Supported MCS set as described in 802.11n spec * @mcs: Supported MCS rates
*/ */
struct ieee80211_ht_info { struct ieee80211_sta_ht_cap {
u16 cap; /* use IEEE80211_HT_CAP_ */ u16 cap; /* use IEEE80211_HT_CAP_ */
u8 ht_supported; bool ht_supported;
u8 ampdu_factor; u8 ampdu_factor;
u8 ampdu_density; u8 ampdu_density;
u8 supp_mcs_set[16]; struct ieee80211_mcs_info mcs;
}; };
/** /**
...@@ -173,7 +174,7 @@ struct ieee80211_supported_band { ...@@ -173,7 +174,7 @@ struct ieee80211_supported_band {
enum ieee80211_band band; enum ieee80211_band band;
int n_channels; int n_channels;
int n_bitrates; int n_bitrates;
struct ieee80211_ht_info ht_info; struct ieee80211_sta_ht_cap ht_cap;
}; };
/** /**
......
...@@ -633,10 +633,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, ...@@ -633,10 +633,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
sta->sta.supp_rates[local->oper_channel->band] = rates; sta->sta.supp_rates[local->oper_channel->band] = rates;
} }
if (params->ht_capa) { if (params->ht_capa)
ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, ieee80211_ht_cap_ie_to_sta_ht_cap(params->ht_capa,
&sta->sta.ht_info); &sta->sta.ht_cap);
}
if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
switch (params->plink_action) { switch (params->plink_action) {
......
...@@ -20,37 +20,33 @@ ...@@ -20,37 +20,33 @@
#include "sta_info.h" #include "sta_info.h"
#include "wme.h" #include "wme.h"
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_ht_info *ht_info) struct ieee80211_sta_ht_cap *ht_cap)
{ {
if (ht_info == NULL) BUG_ON(!ht_cap);
return -EINVAL;
memset(ht_info, 0, sizeof(*ht_info)); memset(ht_cap, 0, sizeof(*ht_cap));
if (ht_cap_ie) { if (ht_cap_ie) {
u8 ampdu_info = ht_cap_ie->ampdu_params_info; u8 ampdu_info = ht_cap_ie->ampdu_params_info;
ht_info->ht_supported = 1; ht_cap->ht_supported = true;
ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info);
ht_info->ampdu_factor = ht_cap->ampdu_factor =
ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
ht_info->ampdu_density = ht_cap->ampdu_density =
(ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); memcpy(&ht_cap->mcs, &ht_cap_ie->mcs, sizeof(ht_cap->mcs));
} else } else
ht_info->ht_supported = 0; ht_cap->ht_supported = false;
return 0;
} }
int ieee80211_ht_addt_info_ie_to_ht_bss_info( void ieee80211_ht_info_ie_to_ht_bss_info(
struct ieee80211_ht_addt_info *ht_add_info_ie, struct ieee80211_ht_info *ht_add_info_ie,
struct ieee80211_ht_bss_info *bss_info) struct ieee80211_ht_bss_info *bss_info)
{ {
if (bss_info == NULL) BUG_ON(!bss_info);
return -EINVAL;
memset(bss_info, 0, sizeof(*bss_info)); memset(bss_info, 0, sizeof(*bss_info));
...@@ -62,8 +58,119 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( ...@@ -62,8 +58,119 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info(
bss_info->bss_cap = ht_add_info_ie->ht_param; bss_info->bss_cap = ht_add_info_ie->ht_param;
bss_info->bss_op_mode = (u8)(op_mode & 0xff); bss_info->bss_op_mode = (u8)(op_mode & 0xff);
} }
}
/*
* ieee80211_handle_ht should be called only after the operating band
* has been determined as ht configuration depends on the hw's
* HT abilities for a specific band.
*/
u32 ieee80211_handle_ht(struct ieee80211_local *local,
struct ieee80211_sta_ht_cap *req_ht_cap,
struct ieee80211_ht_bss_info *req_bss_cap)
{
struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_supported_band *sband;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_ht_bss_info ht_bss_conf;
u32 changed = 0;
int i;
u8 max_tx_streams;
u8 tx_mcs_set_cap;
bool enable_ht = true;
sband = local->hw.wiphy->bands[conf->channel->band];
memset(&ht_cap, 0, sizeof(ht_cap));
memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
/* HT is not supported */
if (!sband->ht_cap.ht_supported)
enable_ht = false;
/* disable HT */
if (!enable_ht) {
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
changed |= BSS_CHANGED_HT;
conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
conf->ht_cap.ht_supported = false;
return changed;
}
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
changed |= BSS_CHANGED_HT;
conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
ht_cap.ht_supported = true;
ht_cap.cap = req_ht_cap->cap & sband->ht_cap.cap;
ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS;
ht_cap.cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
ht_cap.ampdu_factor = req_ht_cap->ampdu_factor;
ht_cap.ampdu_density = req_ht_cap->ampdu_density;
/* own MCS TX capabilities */
tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
/*
* configure supported Tx MCS according to requested MCS
* (based in most cases on Rx capabilities of peer) and self
* Tx MCS capabilities (as defined by low level driver HW
* Tx capabilities)
*/
/* can we TX with MCS rates? */
if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
goto check_changed;
/* Counting from 0, therefore +1 */
if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF)
max_tx_streams =
((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
else
max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS;
/*
* 802.11n D5.0 20.3.5 / 20.6 says:
* - indices 0 to 7 and 32 are single spatial stream
* - 8 to 31 are multiple spatial streams using equal modulation
* [8..15 for two streams, 16..23 for three and 24..31 for four]
* - remainder are multiple spatial streams using unequal modulation
*/
for (i = 0; i < max_tx_streams; i++)
ht_cap.mcs.rx_mask[i] =
sband->ht_cap.mcs.rx_mask[i] &
req_ht_cap->mcs.rx_mask[i];
if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
i < IEEE80211_HT_MCS_MASK_LEN; i++)
ht_cap.mcs.rx_mask[i] =
sband->ht_cap.mcs.rx_mask[i] &
req_ht_cap->mcs.rx_mask[i];
/* handle MCS rate 32 too */
if (sband->ht_cap.mcs.rx_mask[32/8] &
req_ht_cap->mcs.rx_mask[32/8] & 1)
ht_cap.mcs.rx_mask[32/8] |= 1;
check_changed:
/* if bss configuration changed store the new one */
if (memcmp(&conf->ht_cap, &ht_cap, sizeof(ht_cap)) ||
memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
changed |= BSS_CHANGED_HT;
memcpy(&conf->ht_cap, &ht_cap, sizeof(ht_cap));
memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
}
return 0; return changed;
} }
static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
...@@ -794,7 +901,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, ...@@ -794,7 +901,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
* check if configuration can support the BA policy * check if configuration can support the BA policy
* and if buffer size does not exceeds max value */ * and if buffer size does not exceeds max value */
if (((ba_policy != 1) if (((ba_policy != 1)
&& (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) && (!(conf->ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA)))
|| (buf_size > IEEE80211_MAX_AMPDU_BUF)) { || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
status = WLAN_STATUS_INVALID_QOS_PARAM; status = WLAN_STATUS_INVALID_QOS_PARAM;
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
...@@ -812,7 +919,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, ...@@ -812,7 +919,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
sband = local->hw.wiphy->bands[conf->channel->band]; sband = local->hw.wiphy->bands[conf->channel->band];
buf_size = IEEE80211_MIN_AMPDU_BUF; buf_size = IEEE80211_MIN_AMPDU_BUF;
buf_size = buf_size << sband->ht_info.ampdu_factor; buf_size = buf_size << sband->ht_cap.ampdu_factor;
} }
......
...@@ -817,7 +817,7 @@ struct ieee802_11_elems { ...@@ -817,7 +817,7 @@ struct ieee802_11_elems {
u8 *wmm_info; u8 *wmm_info;
u8 *wmm_param; u8 *wmm_param;
struct ieee80211_ht_cap *ht_cap_elem; struct ieee80211_ht_cap *ht_cap_elem;
struct ieee80211_ht_addt_info *ht_info_elem; struct ieee80211_ht_info *ht_info_elem;
u8 *mesh_config; u8 *mesh_config;
u8 *mesh_id; u8 *mesh_id;
u8 *peer_link; u8 *peer_link;
...@@ -880,9 +880,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) ...@@ -880,9 +880,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
int ieee80211_hw_config(struct ieee80211_local *local); int ieee80211_hw_config(struct ieee80211_local *local);
int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
struct ieee80211_ht_info *req_ht_cap,
struct ieee80211_ht_bss_info *req_bss_cap);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed); u32 changed);
void ieee80211_configure_filter(struct ieee80211_local *local); void ieee80211_configure_filter(struct ieee80211_local *local);
...@@ -963,11 +960,14 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); ...@@ -963,11 +960,14 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
/* HT */ /* HT */
int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_ht_info *ht_info); struct ieee80211_sta_ht_cap *ht_cap);
int ieee80211_ht_addt_info_ie_to_ht_bss_info( void ieee80211_ht_info_ie_to_ht_bss_info(
struct ieee80211_ht_addt_info *ht_add_info_ie, struct ieee80211_ht_info *ht_add_info_ie,
struct ieee80211_ht_bss_info *bss_info); struct ieee80211_ht_bss_info *bss_info);
u32 ieee80211_handle_ht(struct ieee80211_local *local,
struct ieee80211_sta_ht_cap *req_ht_cap,
struct ieee80211_ht_bss_info *req_bss_cap);
void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn);
void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da,
......
...@@ -232,100 +232,6 @@ int ieee80211_hw_config(struct ieee80211_local *local) ...@@ -232,100 +232,6 @@ int ieee80211_hw_config(struct ieee80211_local *local)
return ret; return ret;
} }
/**
* ieee80211_handle_ht should be used only after legacy configuration
* has been determined namely band, as ht configuration depends upon
* the hardware's HT abilities for a _specific_ band.
*/
u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
struct ieee80211_ht_info *req_ht_cap,
struct ieee80211_ht_bss_info *req_bss_cap)
{
struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_supported_band *sband;
struct ieee80211_ht_info ht_conf;
struct ieee80211_ht_bss_info ht_bss_conf;
u32 changed = 0;
int i;
u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS;
u8 tx_mcs_set_cap;
sband = local->hw.wiphy->bands[conf->channel->band];
memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
/* HT is not supported */
if (!sband->ht_info.ht_supported) {
conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
goto out;
}
/* disable HT */
if (!enable_ht) {
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
changed |= BSS_CHANGED_HT;
conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
conf->ht_conf.ht_supported = 0;
goto out;
}
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
changed |= BSS_CHANGED_HT;
conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
ht_conf.ht_supported = 1;
ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS);
ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS;
ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
ht_conf.ampdu_density = req_ht_cap->ampdu_density;
/* Bits 96-100 */
tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12];
/* configure suppoerted Tx MCS according to requested MCS
* (based in most cases on Rx capabilities of peer) and self
* Tx MCS capabilities (as defined by low level driver HW
* Tx capabilities) */
if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED))
goto check_changed;
/* Counting from 0 therfore + 1 */
if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF)
max_tx_streams = ((tx_mcs_set_cap &
IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1;
for (i = 0; i < max_tx_streams; i++)
ht_conf.supp_mcs_set[i] =
sband->ht_info.supp_mcs_set[i] &
req_ht_cap->supp_mcs_set[i];
if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM)
for (i = IEEE80211_SUPP_MCS_SET_UEQM;
i < IEEE80211_SUPP_MCS_SET_LEN; i++)
ht_conf.supp_mcs_set[i] =
sband->ht_info.supp_mcs_set[i] &
req_ht_cap->supp_mcs_set[i];
check_changed:
/* if bss configuration changed store the new one */
if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
changed |= BSS_CHANGED_HT;
memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
}
out:
return changed;
}
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed) u32 changed)
{ {
......
...@@ -236,7 +236,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -236,7 +236,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_mgmt *mgmt; struct ieee80211_mgmt *mgmt;
u8 *pos, *ies, *ht_add_ie; u8 *pos, *ies, *ht_ie;
int i, len, count, rates_len, supp_rates_len; int i, len, count, rates_len, supp_rates_len;
u16 capab; u16 capab;
struct ieee80211_bss *bss; struct ieee80211_bss *bss;
...@@ -393,24 +393,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -393,24 +393,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
/* wmm support is a must to HT */ /* wmm support is a must to HT */
if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
sband->ht_info.ht_supported && sband->ht_cap.ht_supported &&
(ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
struct ieee80211_ht_addt_info *ht_add_info = ht_ie[1] >= sizeof(struct ieee80211_ht_info)) {
(struct ieee80211_ht_addt_info *)ht_add_ie; struct ieee80211_ht_info *ht_info =
u16 cap = sband->ht_info.cap; (struct ieee80211_ht_info *)(ht_ie + 2);
u16 cap = sband->ht_cap.cap;
__le16 tmp; __le16 tmp;
u32 flags = local->hw.conf.channel->flags; u32 flags = local->hw.conf.channel->flags;
switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_IE_CHA_SEC_ABOVE: case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
cap &= ~IEEE80211_HT_CAP_SGI_40; cap &= ~IEEE80211_HT_CAP_SGI_40;
} }
break; break;
case IEEE80211_HT_IE_CHA_SEC_BELOW: case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
cap &= ~IEEE80211_HT_CAP_SGI_40; cap &= ~IEEE80211_HT_CAP_SGI_40;
} }
break; break;
...@@ -424,9 +425,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -424,9 +425,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
memcpy(pos, &tmp, sizeof(u16)); memcpy(pos, &tmp, sizeof(u16));
pos += sizeof(u16); pos += sizeof(u16);
/* TODO: needs a define here for << 2 */ /* TODO: needs a define here for << 2 */
*pos++ = sband->ht_info.ampdu_factor | *pos++ = sband->ht_cap.ampdu_factor |
(sband->ht_info.ampdu_density << 2); (sband->ht_cap.ampdu_density << 2);
memcpy(pos, sband->ht_info.supp_mcs_set, 16); memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
} }
kfree(ifsta->assocreq_ies); kfree(ifsta->assocreq_ies);
...@@ -730,7 +731,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ...@@ -730,7 +731,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
changed |= BSS_CHANGED_HT; changed |= BSS_CHANGED_HT;
sdata->bss_conf.assoc_ht = 1; sdata->bss_conf.assoc_ht = 1;
sdata->bss_conf.ht_conf = &conf->ht_conf; sdata->bss_conf.ht_cap = &conf->ht_cap;
sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
} }
...@@ -850,7 +851,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -850,7 +851,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_HT; changed |= BSS_CHANGED_HT;
sdata->bss_conf.assoc_ht = 0; sdata->bss_conf.assoc_ht = 0;
sdata->bss_conf.ht_conf = NULL; sdata->bss_conf.ht_cap = NULL;
sdata->bss_conf.ht_bss_conf = NULL; sdata->bss_conf.ht_bss_conf = NULL;
ieee80211_led_assoc(local, 0); ieee80211_led_assoc(local, 0);
...@@ -1335,11 +1336,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ...@@ -1335,11 +1336,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
struct ieee80211_ht_bss_info bss_info; struct ieee80211_ht_bss_info bss_info;
ieee80211_ht_cap_ie_to_ht_info( ieee80211_ht_cap_ie_to_sta_ht_cap(
elems.ht_cap_elem, &sta->sta.ht_info); elems.ht_cap_elem, &sta->sta.ht_cap);
ieee80211_ht_addt_info_ie_to_ht_bss_info( ieee80211_ht_info_ie_to_ht_bss_info(
elems.ht_info_elem, &bss_info); elems.ht_info_elem, &bss_info);
ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); ieee80211_handle_ht(local, &sta->sta.ht_cap, &bss_info);
} }
rate_control_rate_init(sta); rate_control_rate_init(sta);
...@@ -1696,9 +1697,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -1696,9 +1697,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
struct ieee80211_ht_bss_info bss_info; struct ieee80211_ht_bss_info bss_info;
ieee80211_ht_addt_info_ie_to_ht_bss_info( ieee80211_ht_info_ie_to_ht_bss_info(
elems.ht_info_elem, &bss_info); elems.ht_info_elem, &bss_info);
changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, changed |= ieee80211_handle_ht(local, &conf->ht_cap,
&bss_info); &bss_info);
} }
......
...@@ -532,8 +532,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, ...@@ -532,8 +532,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
if (elen >= sizeof(struct ieee80211_ht_cap)) if (elen >= sizeof(struct ieee80211_ht_cap))
elems->ht_cap_elem = (void *)pos; elems->ht_cap_elem = (void *)pos;
break; break;
case WLAN_EID_HT_EXTRA_INFO: case WLAN_EID_HT_INFORMATION:
if (elen >= sizeof(struct ieee80211_ht_addt_info)) if (elen >= sizeof(struct ieee80211_ht_info))
elems->ht_info_elem = (void *)pos; elems->ht_info_elem = (void *)pos;
break; break;
case WLAN_EID_MESH_ID: case WLAN_EID_MESH_ID:
......
...@@ -147,7 +147,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, ...@@ -147,7 +147,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev,
sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ];
if (sband) { if (sband) {
is_a = 1; is_a = 1;
is_ht |= sband->ht_info.ht_supported; is_ht |= sband->ht_cap.ht_supported;
} }
sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ];
...@@ -160,7 +160,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, ...@@ -160,7 +160,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev,
if (sband->bitrates[i].bitrate == 60) if (sband->bitrates[i].bitrate == 60)
is_g = 1; is_g = 1;
} }
is_ht |= sband->ht_info.ht_supported; is_ht |= sband->ht_cap.ht_supported;
} }
strcpy(name, "IEEE 802.11"); strcpy(name, "IEEE 802.11");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment