-#endif /* CONFIG_IWL4965_HT */
-
-/**
- * iwl4965_add_station - Initialize a station's hardware rate table
- *
- * The uCode's station table contains a table of fallback rates
- * for automatic fallback during transmission.
- *
- * NOTE: This sets up a default set of values. These will be replaced later
- * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
- * rc80211_simple.
- *
- * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
- * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
- * which requires station table entry to exist).
- */
-void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
-{
- int i, r;
- struct iwl_link_quality_cmd link_cmd = {
- .reserved1 = 0,
- };
- u16 rate_flags;
-
- /* Set up the rate scaling to start at selected rate, fall back
- * all the way down to 1M in IEEE order, and then spin on 1M */
- if (is_ap)
- r = IWL_RATE_54M_INDEX;
- else if (priv->band == IEEE80211_BAND_5GHZ)
- r = IWL_RATE_6M_INDEX;
- else
- r = IWL_RATE_1M_INDEX;
-
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
- rate_flags = 0;
- if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
- rate_flags |= RATE_MCS_CCK_MSK;
-
- /* Use Tx antenna B only */
- rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
-
- link_cmd.rs_table[i].rate_n_flags =
- iwl4965_hw_set_rate_n_flags(iwl4965_rates[r].plcp, rate_flags);
- r = iwl4965_get_prev_ieee_rate(r);
- }
-
- link_cmd.general_params.single_stream_ant_msk = 2;
- link_cmd.general_params.dual_stream_ant_msk = 3;
- link_cmd.agg_params.agg_dis_start_th = 3;
- link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
-
- /* Update the rate scaling for control frame Tx to AP */
- link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
-
- iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
- sizeof(link_cmd), &link_cmd, NULL);
-}
-
-#ifdef CONFIG_IWL4965_HT
-
-static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel, u8 extension_chan_offset)
-{
- const struct iwl_channel_info *ch_info;
-
- ch_info = iwl_get_channel_info(priv, band, channel);
- if (!is_channel_valid(ch_info))
- return 0;
-
- if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
- return 0;
-
- if ((ch_info->fat_extension_channel == extension_chan_offset) ||
- (ch_info->fat_extension_channel == HT_IE_EXT_CHANNEL_MAX))
- return 1;
-
- return 0;
-}
-
-static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_ht_info *sta_ht_inf)
-{
- struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
-
- if ((!iwl_ht_conf->is_ht) ||
- (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
- (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
- return 0;
-
- if (sta_ht_inf) {
- if ((!sta_ht_inf->ht_supported) ||
- (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
- return 0;
- }
-
- return (iwl4965_is_channel_extension(priv, priv->band,
- iwl_ht_conf->control_channel,
- iwl_ht_conf->extension_chan_offset));
-}
-
-void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
-{
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
- u32 val;
-
- if (!ht_info->is_ht)
- return;
-
- /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
- if (iwl4965_is_fat_tx_allowed(priv, NULL))
- rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
- else
- rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
- RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
-
- if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
- IWL_DEBUG_ASSOC("control diff than current %d %d\n",
- le16_to_cpu(rxon->channel),
- ht_info->control_channel);
- rxon->channel = cpu_to_le16(ht_info->control_channel);
- return;
- }
-
- /* Note: control channel is opposite of extension channel */
- switch (ht_info->extension_chan_offset) {
- case IWL_EXT_CHANNEL_OFFSET_ABOVE:
- rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- break;
- case IWL_EXT_CHANNEL_OFFSET_BELOW:
- rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- break;
- case IWL_EXT_CHANNEL_OFFSET_NONE:
- default:
- rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
- break;
- }
-
- val = ht_info->ht_protection;
-
- rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
-
- iwl_set_rxon_chain(priv);
-
- IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
- "rxon flags 0x%X operation mode :0x%X "
- "extension channel offset 0x%x "
- "control chan %d\n",
- ht_info->supp_mcs_set[0],
- ht_info->supp_mcs_set[1],
- ht_info->supp_mcs_set[2],
- le32_to_cpu(rxon->flags), ht_info->ht_protection,
- ht_info->extension_chan_offset,
- ht_info->control_channel);
- return;
-}
-
-void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf)
-{
- __le32 sta_flags;
- u8 mimo_ps_mode;
-
- if (!sta_ht_inf || !sta_ht_inf->ht_supported)
- goto done;
-
- mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2;
-
- sta_flags = priv->stations[index].sta.station_flags;
-
- sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
-
- switch (mimo_ps_mode) {
- case WLAN_HT_CAP_MIMO_PS_STATIC:
- sta_flags |= STA_FLG_MIMO_DIS_MSK;
- break;
- case WLAN_HT_CAP_MIMO_PS_DYNAMIC:
- sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
- break;
- case WLAN_HT_CAP_MIMO_PS_DISABLED:
- break;
- default:
- IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
- break;
- }
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
-
- if (iwl4965_is_fat_tx_allowed(priv, sta_ht_inf))
- sta_flags |= STA_FLG_FAT_EN_MSK;
- else
- sta_flags &= ~STA_FLG_FAT_EN_MSK;
-
- priv->stations[index].sta.station_flags = sta_flags;
- done:
- return;
-}
-