aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-14 10:58:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:16 -0400
commitae5eb02641233a4e9d1b92d22090f1b1afa14466 (patch)
tree117b7cb5efa3ff1cf714218098fc6db3820ed4e0 /drivers/net/wireless/iwlwifi/iwl-agn.c
parentbda3933a8aceedd03e0dd410844bd310033ca756 (diff)
mac80211: rewrite HT handling
The HT handling has the following deficiencies, which I've (partially) fixed: * it always uses the AP info even if there is no AP, hence has no chance of working as an AP * it pretends to be HW config, but really is per-BSS * channel sanity checking is left to the drivers * it generally lets the driver control too much HT enabling is still wrong with this patch if you have more than one virtual STA mode interface, but that never happens currently. Once WDS, IBSS or AP/VLAN gets HT capabilities, it will also be wrong, see the comment in ieee80211_enable_ht(). Additionally, this fixes a number of bugs: * mac80211: ieee80211_set_disassoc doesn't notify the driver any more since the refactoring * iwl-agn-rs: always uses the HT capabilities from the wrong stuff mac80211 gives it rather than the actual peer STA * ath9k: a number of bugs resulting from the broken HT API I'm not entirely happy with putting the HT capabilities into struct ieee80211_sta as restricted to our own HT TX capabilities, but I see no cleaner solution for now. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 79a24410dd0a..7c3eb3d8f7e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -552,17 +552,30 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
552static void iwl4965_ht_conf(struct iwl_priv *priv, 552static void iwl4965_ht_conf(struct iwl_priv *priv,
553 struct ieee80211_bss_conf *bss_conf) 553 struct ieee80211_bss_conf *bss_conf)
554{ 554{
555 struct ieee80211_sta_ht_cap *ht_conf = bss_conf->ht_cap; 555 struct ieee80211_sta_ht_cap *ht_conf;
556 struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
557 struct iwl_ht_info *iwl_conf = &priv->current_ht_config; 556 struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
557 struct ieee80211_sta *sta;
558 558
559 IWL_DEBUG_MAC80211("enter: \n"); 559 IWL_DEBUG_MAC80211("enter: \n");
560 560
561 iwl_conf->is_ht = bss_conf->assoc_ht;
562
563 if (!iwl_conf->is_ht) 561 if (!iwl_conf->is_ht)
564 return; 562 return;
565 563
564
565 /*
566 * It is totally wrong to base global information on something
567 * that is valid only when associated, alas, this driver works
568 * that way and I don't know how to fix it.
569 */
570
571 rcu_read_lock();
572 sta = ieee80211_find_sta(priv->hw, priv->bssid);
573 if (!sta) {
574 rcu_read_unlock();
575 return;
576 }
577 ht_conf = &sta->ht_cap;
578
566 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) 579 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
567 iwl_conf->sgf |= HT_SHORT_GI_20MHZ; 580 iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
568 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) 581 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
@@ -574,8 +587,8 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
574 587
575 iwl_conf->supported_chan_width = 588 iwl_conf->supported_chan_width =
576 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); 589 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
577 iwl_conf->extension_chan_offset = 590
578 ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 591 iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset;
579 /* If no above or below channel supplied disable FAT channel */ 592 /* If no above or below channel supplied disable FAT channel */
580 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && 593 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
581 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) { 594 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) {
@@ -587,15 +600,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
587 600
588 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); 601 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
589 602
590 iwl_conf->control_channel = ht_bss_conf->primary_channel; 603 iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok;
591 iwl_conf->tx_chan_width =
592 !!(ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
593 iwl_conf->ht_protection = 604 iwl_conf->ht_protection =
594 ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; 605 bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
595 iwl_conf->non_GF_STA_present = 606 iwl_conf->non_GF_STA_present =
596 !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 607 !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
608
609 rcu_read_unlock();
597 610
598 IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
599 IWL_DEBUG_MAC80211("leave\n"); 611 IWL_DEBUG_MAC80211("leave\n");
600} 612}
601 613
@@ -2746,6 +2758,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, u32 changed)
2746 mutex_lock(&priv->mutex); 2758 mutex_lock(&priv->mutex);
2747 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); 2759 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
2748 2760
2761 priv->current_ht_config.is_ht = conf->ht.enabled;
2762
2749 if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { 2763 if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
2750 IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); 2764 IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
2751 goto out; 2765 goto out;
@@ -3104,7 +3118,6 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
3104 } 3118 }
3105 3119
3106 if (changes & BSS_CHANGED_HT) { 3120 if (changes & BSS_CHANGED_HT) {
3107 IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
3108 iwl4965_ht_conf(priv, bss_conf); 3121 iwl4965_ht_conf(priv, bss_conf);
3109 iwl_set_rxon_chain(priv); 3122 iwl_set_rxon_chain(priv);
3110 } 3123 }