aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-core.c
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-05-22 14:01:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-22 14:06:05 -0400
commita2b0f02e4795bfde5f11720a10af8923cb98b654 (patch)
tree1d2cad3ff20f43ba51aace00a8c2c627fe013581 /drivers/net/wireless/iwlwifi/iwl-core.c
parenta9c146b369cd8facbbbec7d8b31440f6eaa43e03 (diff)
iwlwifi: support "pure 40MHz" in RXON command
Fix the bug when using 11n "pure 40MHz" mode cause uCode crashing by adding support for "pure 40MHz" in RX_ON command flag. the "mode" field (bits 25:26) has value of 0-3 0 = 20 MHz only 1 = 40MHz only 2 = Mixed 3 = Reserved Control Channel ID (bit 22) is valid only in Mixed mode. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@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.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c7cbb2e80903..a15f7955845b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -617,19 +617,23 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
617 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; 617 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
618 618
619 if ((!iwl_ht_conf->is_ht) || 619 if ((!iwl_ht_conf->is_ht) ||
620 (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || 620 (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ))
621 (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
622 return 0; 621 return 0;
623 622
623 /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
624 * the bit will not set if it is pure 40MHz case
625 */
624 if (sta_ht_inf) { 626 if (sta_ht_inf) {
625 if ((!sta_ht_inf->ht_supported) || 627 if (!sta_ht_inf->ht_supported)
626 (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
627 return 0; 628 return 0;
628 } 629 }
629 630
630 return iwl_is_channel_extension(priv, priv->band, 631 if (iwl_ht_conf->ht_protection & IEEE80211_HT_OP_MODE_PROTECTION_20MHZ)
631 le16_to_cpu(priv->staging_rxon.channel), 632 return 1;
632 iwl_ht_conf->extension_chan_offset); 633 else
634 return iwl_is_channel_extension(priv, priv->band,
635 le16_to_cpu(priv->staging_rxon.channel),
636 iwl_ht_conf->extension_chan_offset);
633} 637}
634EXPORT_SYMBOL(iwl_is_fat_tx_allowed); 638EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
635 639
@@ -799,42 +803,51 @@ EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
799void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) 803void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
800{ 804{
801 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 805 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
802 u32 val;
803 806
804 if (!ht_info->is_ht) { 807 if (!ht_info->is_ht) {
805 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 808 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
806 RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
807 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 809 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
808 RXON_FLG_FAT_PROT_MSK | 810 RXON_FLG_FAT_PROT_MSK |
809 RXON_FLG_HT_PROT_MSK); 811 RXON_FLG_HT_PROT_MSK);
810 return; 812 return;
811 } 813 }
812 814
813 /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ 815 /* FIXME: if the definition of ht_protection changed, the "translation"
814 if (iwl_is_fat_tx_allowed(priv, NULL)) 816 * will be needed for rxon->flags
815 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK; 817 */
816 else 818 rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
817 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 819
818 RXON_FLG_CHANNEL_MODE_PURE_40_MSK); 820 /* Set up channel bandwidth:
819 821 * 20 MHz only, 20/40 mixed or pure 40 if fat ok */
820 /* Note: control channel is opposite of extension channel */ 822 /* clear the HT channel mode before set the mode */
821 switch (ht_info->extension_chan_offset) { 823 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
822 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 824 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
823 rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); 825 if (iwl_is_fat_tx_allowed(priv, NULL)) {
824 break; 826 /* pure 40 fat */
825 case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 827 if (rxon->flags & RXON_FLG_FAT_PROT_MSK)
826 rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; 828 rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
827 break; 829 else {
828 case IEEE80211_HT_PARAM_CHA_SEC_NONE: 830 /* Note: control channel is opposite of extension channel */
829 default: 831 switch (ht_info->extension_chan_offset) {
830 rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; 832 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
831 break; 833 rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
834 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
835 break;
836 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
837 rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
838 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
839 break;
840 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
841 default:
842 /* channel location only valid if in Mixed mode */
843 IWL_ERR(priv, "invalid extension channel offset\n");
844 break;
845 }
846 }
847 } else {
848 rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
832 } 849 }
833 850
834 val = ht_info->ht_protection;
835
836 rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
837
838 if (priv->cfg->ops->hcmd->set_rxon_chain) 851 if (priv->cfg->ops->hcmd->set_rxon_chain)
839 priv->cfg->ops->hcmd->set_rxon_chain(priv); 852 priv->cfg->ops->hcmd->set_rxon_chain(priv);
840 853
@@ -1122,8 +1135,9 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
1122 priv->staging_rxon.cck_basic_rates = 1135 priv->staging_rxon.cck_basic_rates =
1123 (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; 1136 (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
1124 1137
1125 priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 1138 /* clear both MIX and PURE40 mode flag */
1126 RXON_FLG_CHANNEL_MODE_PURE_40_MSK); 1139 priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
1140 RXON_FLG_CHANNEL_MODE_PURE_40);
1127 memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); 1141 memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
1128 memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); 1142 memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
1129 priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; 1143 priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;