From 094d05dc32fc2930e381189a942016e5561775d9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 12 Dec 2008 11:57:43 +0530 Subject: mac80211: Fix HT channel selection HT management is done differently for AP and STA modes, unify to just the ->config() callback since HT is fundamentally a PHY property and cannot be per-BSS. Rename enum nl80211_sec_chan_offset as nl80211_channel_type to denote the channel type ( NO_HT, HT20, HT40+, HT40- ). Signed-off-by: Johannes Berg Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 123 ++++++++------------------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 +++-- drivers/net/wireless/mac80211_hwsim.c | 6 +- 3 files changed, 44 insertions(+), 103 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 02e1771bb27..e22fea18bad 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -623,37 +623,40 @@ static int ath_get_channel(struct ath_softc *sc, return -1; } -/* ext_chan_offset: (-1, 0, 1) (below, none, above) */ - static u32 ath_get_extchanmode(struct ath_softc *sc, struct ieee80211_channel *chan, - int ext_chan_offset, - enum ath9k_ht_macmode tx_chan_width) + enum nl80211_channel_type channel_type) { u32 chanmode = 0; switch (chan->band) { case IEEE80211_BAND_2GHZ: - if ((ext_chan_offset == 0) && - (tx_chan_width == ATH9K_HT_MACMODE_20)) + switch(channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: chanmode = CHANNEL_G_HT20; - if ((ext_chan_offset == 1) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) + break; + case NL80211_CHAN_HT40PLUS: chanmode = CHANNEL_G_HT40PLUS; - if ((ext_chan_offset == -1) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) + break; + case NL80211_CHAN_HT40MINUS: chanmode = CHANNEL_G_HT40MINUS; + break; + } break; case IEEE80211_BAND_5GHZ: - if ((ext_chan_offset == 0) && - (tx_chan_width == ATH9K_HT_MACMODE_20)) + switch(channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: chanmode = CHANNEL_A_HT20; - if ((ext_chan_offset == 1) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) + break; + case NL80211_CHAN_HT40PLUS: chanmode = CHANNEL_A_HT40PLUS; - if ((ext_chan_offset == -1) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) + break; + case NL80211_CHAN_HT40MINUS: chanmode = CHANNEL_A_HT40MINUS; + break; + } break; default: break; @@ -829,45 +832,15 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; } -static void ath9k_ht_conf(struct ath_softc *sc, - struct ieee80211_bss_conf *bss_conf) -{ - if (sc->hw->conf.ht.enabled) { - if (bss_conf->ht.width_40_ok) - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; - else - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - - ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width); - - DPRINTF(sc, ATH_DBG_CONFIG, - "BSS Changed HT, chanwidth: %d\n", sc->tx_chan_width); - } -} - -static inline int ath_sec_offset(u8 ext_offset) -{ - if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) - return 0; - else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) - return 1; - else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) - return -1; - - return 0; -} - static void ath9k_bss_assoc_info(struct ath_softc *sc, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) { - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_channel *curchan = hw->conf.channel; struct ath_vap *avp = (void *)vif->drv_priv; - int pos; if (bss_conf->assoc) { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d\n", bss_conf->aid); + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, sc->sc_curbssid); /* New association, store aid */ if (avp->av_opmode == NL80211_IFTYPE_STATION) { @@ -886,40 +859,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; - /* Update chainmask */ - ath_update_chainmask(sc, hw->conf.ht.enabled); - - DPRINTF(sc, ATH_DBG_CONFIG, - "bssid %pM aid 0x%x\n", - sc->sc_curbssid, sc->sc_curaid); - - pos = ath_get_channel(sc, curchan); - if (pos == -1) { - DPRINTF(sc, ATH_DBG_FATAL, - "Invalid channel: %d\n", curchan->center_freq); - return; - } - - if (hw->conf.ht.enabled) { - int offset = - ath_sec_offset(bss_conf->ht.secondary_channel_offset); - sc->tx_chan_width = (bss_conf->ht.width_40_ok) ? - ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; - - sc->sc_ah->ah_channels[pos].chanmode = - ath_get_extchanmode(sc, curchan, - offset, sc->tx_chan_width); - } else { - sc->sc_ah->ah_channels[pos].chanmode = - (curchan->band == IEEE80211_BAND_2GHZ) ? - CHANNEL_G : CHANNEL_A; - } - - /* set h/w channel */ - if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) - DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel: %d\n", - curchan->center_freq); - /* Start ANI */ mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); @@ -2146,7 +2085,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_softc *sc = hw->priv; struct ieee80211_conf *conf = &hw->conf; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | + IEEE80211_CONF_CHANGE_HT)) { struct ieee80211_channel *curchan = hw->conf.channel; int pos; @@ -2165,25 +2105,23 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; - if ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) && - (conf->ht.enabled)) { - sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ? - ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; + if (conf->ht.enabled) { + if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS || + conf->ht.channel_type == NL80211_CHAN_HT40MINUS) + sc->tx_chan_width = ATH9K_HT_MACMODE_2040; sc->sc_ah->ah_channels[pos].chanmode = ath_get_extchanmode(sc, curchan, - conf->ht.sec_chan_offset, - sc->tx_chan_width); + conf->ht.channel_type); } if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); return -EINVAL; } - } - if (changed & IEEE80211_CONF_CHANGE_HT) ath_update_chainmask(sc, conf->ht.enabled); + } if (changed & IEEE80211_CONF_CHANGE_POWER) sc->sc_config.txpowlimit = 2 * conf->power_level; @@ -2417,9 +2355,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; } - if (changed & BSS_CHANGED_HT) - ath9k_ht_conf(sc, bss_conf); - if (changed & BSS_CHANGED_ASSOC) { DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2f5e86e1291..bbc1c8052ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -515,19 +515,27 @@ static void iwl_ht_conf(struct iwl_priv *priv, iwl_conf->supported_chan_width = !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset; + /* + * XXX: The HT configuration needs to be moved into iwl_mac_config() + * to be done there correctly. + */ + + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + /* If no above or below channel supplied disable FAT channel */ 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->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) iwl_conf->supported_chan_width = 0; - } iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok; + iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; iwl_conf->ht_protection = bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; iwl_conf->non_GF_STA_present = diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fd5a537ac51..f83d69e813d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -495,11 +495,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - printk(KERN_DEBUG " %s: HT: sec_ch_offs=%d width_40_ok=%d " - "op_mode=%d\n", + printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", wiphy_name(hw->wiphy), - info->ht.secondary_channel_offset, - info->ht.width_40_ok, info->ht.operation_mode); + info->ht.operation_mode); } if (changed & BSS_CHANGED_BASIC_RATES) { -- cgit v1.2.3