diff options
author | Abhijeet Kolekar <abhijeet.kolekar@intel.com> | 2009-04-08 11:26:35 -0700 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:54:41 -0400 |
commit | 5bbe233b9bafabc08a5404d54b9fa086e8390fc7 (patch) | |
tree | f0a4a015d2429d9b2aac4c198543e483494d9214 /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | de2b3e864aa908e613dd9912def88af7877d85f3 (diff) | |
download | linux-stable-5bbe233b9bafabc08a5404d54b9fa086e8390fc7.tar.gz linux-stable-5bbe233b9bafabc08a5404d54b9fa086e8390fc7.tar.bz2 linux-stable-5bbe233b9bafabc08a5404d54b9fa086e8390fc7.zip |
iwl3945: use iwl_bss_info_changed
3945 can use iwl_bss_info_changed.
A new lib op is created for post_assoicate to distinguish between
3945 and iwlwifi's post_associate operations.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 84ac1cec6f5b..15691829e023 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2157,6 +2157,142 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; } EXPORT_SYMBOL(iwl_mac_conf_tx); + +static void iwl_ht_conf(struct iwl_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_sta_ht_cap *ht_conf; + struct iwl_ht_info *iwl_conf = &priv->current_ht_config; + struct ieee80211_sta *sta; + + IWL_DEBUG_MAC80211(priv, "enter: \n"); + + if (!iwl_conf->is_ht) + return; + + + /* + * It is totally wrong to base global information on something + * that is valid only when associated, alas, this driver works + * that way and I don't know how to fix it. + */ + + rcu_read_lock(); + sta = ieee80211_find_sta(priv->hw, priv->bssid); + if (!sta) { + rcu_read_unlock(); + return; + } + ht_conf = &sta->ht_cap; + + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) + iwl_conf->sgf |= HT_SHORT_GI_20MHZ; + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) + iwl_conf->sgf |= HT_SHORT_GI_40MHZ; + + iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); + iwl_conf->max_amsdu_size = + !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); + + iwl_conf->supported_chan_width = + !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); + + /* + * 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 (conf_is_ht40_minus(&priv->hw->conf)) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + else if (conf_is_ht40_plus(&priv->hw->conf)) + 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->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 = 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 = + !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + + rcu_read_unlock(); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} + +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) +void iwl_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + } + + if (changes & BSS_CHANGED_HT) { + iwl_ht_conf(priv, bss_conf); + iwl_set_rxon_chain(priv); + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); + /* This should never happen as this function should + * never be called from interrupt context. */ + if (WARN_ON_ONCE(in_interrupt())) + return; + if (bss_conf->assoc) { + priv->assoc_id = bss_conf->aid; + priv->beacon_int = bss_conf->beacon_int; + priv->power_data.dtim_period = bss_conf->dtim_period; + priv->timestamp = bss_conf->timestamp; + priv->assoc_capability = bss_conf->assoc_capability; + + /* we have just associated, don't start scan too early + * leave time for EAPOL exchange to complete + */ + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + mutex_lock(&priv->mutex); + priv->cfg->ops->lib->post_associate(priv); + mutex_unlock(&priv->mutex); + } else { + priv->assoc_id = 0; + IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); + } + } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { + IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); + iwl_send_rxon_assoc(priv); + } + +} +EXPORT_SYMBOL(iwl_bss_info_changed); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |