Commit fd105e79 authored by Ron Rindjunsky's avatar Ron Rindjunsky Committed by David S. Miller

iwlwifi: 802.11n comply HT self configuration flow with mac80211 framework

This patch conforms HW configuration changes according to new mac80211's
HT framework
Signed-off-by: default avatarRon Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 8fb88032
...@@ -87,8 +87,8 @@ static int is_fat_channel(__le32 rxon_flags) ...@@ -87,8 +87,8 @@ static int is_fat_channel(__le32 rxon_flags)
static u8 is_single_stream(struct iwl4965_priv *priv) static u8 is_single_stream(struct iwl4965_priv *priv)
{ {
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht || if (!priv->current_ht_config.is_ht ||
(priv->active_rate_ht[1] == 0) || (priv->current_ht_config.supp_mcs_set[1] == 0) ||
(priv->ps_mode == IWL_MIMO_PS_STATIC)) (priv->ps_mode == IWL_MIMO_PS_STATIC))
return 1; return 1;
#else #else
...@@ -4541,27 +4541,27 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode, ...@@ -4541,27 +4541,27 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
} }
static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
const struct sta_ht_info *ht_info) struct ieee80211_ht_info *sta_ht_inf)
{ {
struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ) 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_AUTO))
return 0; return 0;
if (ht_info->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) if (sta_ht_inf) {
return 0; if ((!sta_ht_inf->ht_supported) ||
(!sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH))
if (ht_info->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)
return 0; return 0;
}
/* no fat tx allowed on 2.4GHZ */
if (priv->phymode != MODE_IEEE80211A)
return 0;
return (iwl4965_is_channel_extension(priv, priv->phymode, return (iwl4965_is_channel_extension(priv, priv->phymode,
ht_info->control_channel, iwl_ht_conf->control_channel,
ht_info->extension_chan_offset)); iwl_ht_conf->extension_chan_offset));
} }
void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info) void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
{ {
struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
u32 val; u32 val;
...@@ -4570,7 +4570,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info) ...@@ -4570,7 +4570,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info)
return; return;
/* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
if (iwl4965_is_fat_tx_allowed(priv, ht_info)) if (iwl4965_is_fat_tx_allowed(priv, NULL))
rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK; rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
else else
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
...@@ -4600,20 +4600,18 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info) ...@@ -4600,20 +4600,18 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info)
break; break;
} }
val = ht_info->operating_mode; val = ht_info->ht_protection;
rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS); rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
priv->active_rate_ht[0] = ht_info->supp_rates[0];
priv->active_rate_ht[1] = ht_info->supp_rates[1];
iwl4965_set_rxon_chain(priv); iwl4965_set_rxon_chain(priv);
IWL_DEBUG_ASSOC("supported HT rate 0x%X %X " IWL_DEBUG_ASSOC("supported HT rate 0x%X %X "
"rxon flags 0x%X operation mode :0x%X " "rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x " "extension channel offset 0x%x "
"control chan %d\n", "control chan %d\n",
priv->active_rate_ht[0], priv->active_rate_ht[1], ht_info->supp_mcs_set[0], ht_info->supp_mcs_set[1],
le32_to_cpu(rxon->flags), ht_info->operating_mode, le32_to_cpu(rxon->flags), ht_info->ht_protection,
ht_info->extension_chan_offset, ht_info->extension_chan_offset,
ht_info->control_channel); ht_info->control_channel);
return; return;
......
...@@ -766,7 +766,6 @@ extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel); ...@@ -766,7 +766,6 @@ extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index); extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
struct iwl4965_priv; struct iwl4965_priv;
struct sta_ht_info;
/* /*
* Forward declare iwl-4965.c functions for iwl-base.c * Forward declare iwl-4965.c functions for iwl-base.c
...@@ -779,9 +778,6 @@ extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, ...@@ -779,9 +778,6 @@ extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
u16 byte_cnt); u16 byte_cnt);
extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr,
int is_ap); int is_ap);
extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
struct sta_ht_info *ht_info);
extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv); extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv);
extern int iwl4965_tx_cmd(struct iwl4965_priv *priv, struct iwl4965_cmd *out_cmd, extern int iwl4965_tx_cmd(struct iwl4965_priv *priv, struct iwl4965_cmd *out_cmd,
u8 sta_id, dma_addr_t txcmd_phys, u8 sta_id, dma_addr_t txcmd_phys,
...@@ -803,6 +799,8 @@ extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); ...@@ -803,6 +799,8 @@ extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
int mode); int mode);
extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
struct iwl_ht_info *ht_info);
#ifdef CONFIG_IWL4965_HT_AGG #ifdef CONFIG_IWL4965_HT_AGG
extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
u16 tid, u16 *start_seq_num); u16 tid, u16 *start_seq_num);
......
...@@ -2111,7 +2111,7 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force) ...@@ -2111,7 +2111,7 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
QOS_PARAM_FLG_UPDATE_EDCA_MSK; QOS_PARAM_FLG_UPDATE_EDCA_MSK;
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
if (priv->is_ht_enabled && priv->current_assoc_ht.is_ht) if (priv->current_ht_config.is_ht)
priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
#endif /* CONFIG_IWL4965_HT */ #endif /* CONFIG_IWL4965_HT */
...@@ -7304,13 +7304,8 @@ static void iwl4965_bg_post_associate(struct work_struct *data) ...@@ -7304,13 +7304,8 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
if (priv->is_ht_enabled && priv->current_assoc_ht.is_ht) if (priv->current_ht_config.is_ht)
iwl4965_set_rxon_ht(priv, &priv->current_assoc_ht); iwl4965_set_rxon_ht(priv, &priv->current_ht_config);
else {
priv->active_rate_ht[0] = 0;
priv->active_rate_ht[1] = 0;
priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
}
#endif /* CONFIG_IWL4965_HT*/ #endif /* CONFIG_IWL4965_HT*/
iwl4965_set_rxon_chain(priv); iwl4965_set_rxon_chain(priv);
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
...@@ -8112,7 +8107,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) ...@@ -8112,7 +8107,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
priv->lq_mngr.lq_ready = 0; priv->lq_mngr.lq_ready = 0;
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
memset(&priv->current_assoc_ht, 0, sizeof(struct sta_ht_info)); memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
#ifdef CONFIG_IWL4965_HT_AGG #ifdef CONFIG_IWL4965_HT_AGG
/* if (priv->lq_mngr.agg_ctrl.granted_ba) /* if (priv->lq_mngr.agg_ctrl.granted_ba)
...@@ -8232,132 +8227,61 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk ...@@ -8232,132 +8227,61 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
} }
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
union ht_cap_info {
struct {
u16 advanced_coding_cap :1;
u16 supported_chan_width_set :1;
u16 mimo_power_save_mode :2;
u16 green_field :1;
u16 short_GI20 :1;
u16 short_GI40 :1;
u16 tx_stbc :1;
u16 rx_stbc :1;
u16 beam_forming :1;
u16 delayed_ba :1;
u16 maximal_amsdu_size :1;
u16 cck_mode_at_40MHz :1;
u16 psmp_support :1;
u16 stbc_ctrl_frame_support :1;
u16 sig_txop_protection_support :1;
};
u16 val;
} __attribute__ ((packed));
union ht_param_info{
struct {
u8 max_rx_ampdu_factor :2;
u8 mpdu_density :3;
u8 reserved :3;
};
u8 val;
} __attribute__ ((packed));
union ht_exra_param_info {
struct {
u8 ext_chan_offset :2;
u8 tx_chan_width :1;
u8 rifs_mode :1;
u8 controlled_access_only :1;
u8 service_interval_granularity :3;
};
u8 val;
} __attribute__ ((packed));
union ht_operation_mode{
struct {
u16 op_mode :2;
u16 non_GF :1;
u16 reserved :13;
};
u16 val;
} __attribute__ ((packed));
static void iwl4965_ht_info_fill(struct ieee80211_conf *conf,
static int sta_ht_info_init(struct ieee80211_ht_capability *ht_cap, struct iwl4965_priv *priv)
struct ieee80211_ht_additional_info *ht_extra,
struct sta_ht_info *ht_info_ap,
struct sta_ht_info *ht_info)
{ {
union ht_cap_info cap; struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
union ht_operation_mode op_mode; struct ieee80211_ht_info *ht_conf = &conf->ht_conf;
union ht_param_info param_info; struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf;
union ht_exra_param_info extra_param_info;
IWL_DEBUG_MAC80211("enter: \n"); IWL_DEBUG_MAC80211("enter: \n");
if (!ht_info) { if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) {
IWL_DEBUG_MAC80211("leave: ht_info is NULL\n"); iwl_conf->is_ht = 0;
return -1; return;
} }
if (ht_cap) { iwl_conf->is_ht = 1;
cap.val = (u16) le16_to_cpu(ht_cap->capabilities_info); priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
param_info.val = ht_cap->mac_ht_params_info;
ht_info->is_ht = 1; if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
if (cap.short_GI20) iwl_conf->sgf |= 0x1;
ht_info->sgf |= 0x1; if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
if (cap.short_GI40) iwl_conf->sgf |= 0x2;
ht_info->sgf |= 0x2;
ht_info->is_green_field = cap.green_field; iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
ht_info->max_amsdu_size = cap.maximal_amsdu_size; iwl_conf->max_amsdu_size =
ht_info->supported_chan_width = cap.supported_chan_width_set; !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
ht_info->tx_mimo_ps_mode = cap.mimo_power_save_mode; iwl_conf->supported_chan_width =
memcpy(ht_info->supp_rates, ht_cap->supported_mcs_set, 16); !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
iwl_conf->tx_mimo_ps_mode =
ht_info->ampdu_factor = param_info.max_rx_ampdu_factor; (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
ht_info->mpdu_density = param_info.mpdu_density; memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
IWL_DEBUG_MAC80211("SISO mask 0x%X MIMO mask 0x%X \n", iwl_conf->control_channel = ht_bss_conf->primary_channel;
ht_cap->supported_mcs_set[0], iwl_conf->extension_chan_offset =
ht_cap->supported_mcs_set[1]); ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
iwl_conf->tx_chan_width =
if (ht_info_ap) { !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
ht_info->control_channel = ht_info_ap->control_channel; iwl_conf->ht_protection =
ht_info->extension_chan_offset = ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
ht_info_ap->extension_chan_offset; iwl_conf->non_GF_STA_present =
ht_info->tx_chan_width = ht_info_ap->tx_chan_width; !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
ht_info->operating_mode = ht_info_ap->operating_mode;
}
if (ht_extra) {
extra_param_info.val = ht_extra->ht_param;
ht_info->control_channel = ht_extra->control_chan;
ht_info->extension_chan_offset =
extra_param_info.ext_chan_offset;
ht_info->tx_chan_width = extra_param_info.tx_chan_width;
op_mode.val = (u16)
le16_to_cpu(ht_extra->operation_mode);
ht_info->operating_mode = op_mode.op_mode;
IWL_DEBUG_MAC80211("control channel %d\n",
ht_extra->control_chan);
}
} else
ht_info->is_ht = 0;
IWL_DEBUG_MAC80211("control channel %d\n",
iwl_conf->control_channel);
IWL_DEBUG_MAC80211("leave\n"); IWL_DEBUG_MAC80211("leave\n");
return 0;
} }
static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
struct ieee80211_ht_capability *ht_cap, struct ieee80211_conf *conf)
struct ieee80211_ht_additional_info *ht_extra)
{ {
struct iwl4965_priv *priv = hw->priv; struct iwl4965_priv *priv = hw->priv;
int rs;
IWL_DEBUG_MAC80211("enter: \n"); IWL_DEBUG_MAC80211("enter: \n");
rs = sta_ht_info_init(ht_cap, ht_extra, NULL, &priv->current_assoc_ht); iwl4965_ht_info_fill(conf, priv);
iwl4965_set_rxon_chain(priv); iwl4965_set_rxon_chain(priv);
if (priv && priv->assoc_id && if (priv && priv->assoc_id &&
...@@ -8372,10 +8296,8 @@ static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, ...@@ -8372,10 +8296,8 @@ static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
IWL_DEBUG_MAC80211("leave: control channel %d\n", IWL_DEBUG_MAC80211("leave:\n");
ht_extra->control_chan); return 0;
return rs;
} }
static void iwl4965_set_ht_capab(struct ieee80211_hw *hw, static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
...@@ -8400,23 +8322,6 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw, ...@@ -8400,23 +8322,6 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
IEEE80211_HT_CAP_AMPDU_DENSITY); IEEE80211_HT_CAP_AMPDU_DENSITY);
} }
static void iwl4965_mac_get_ht_capab(struct ieee80211_hw *hw,
struct ieee80211_ht_capability *ht_cap)
{
u8 use_wide_channel = 1;
struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter: \n");
if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
use_wide_channel = 0;
/* no fat tx allowed on 2.4GHZ */
if (priv->phymode != MODE_IEEE80211A)
use_wide_channel = 0;
iwl4965_set_ht_capab(hw, ht_cap, use_wide_channel);
IWL_DEBUG_MAC80211("leave: \n");
}
#endif /*CONFIG_IWL4965_HT*/ #endif /*CONFIG_IWL4965_HT*/
/***************************************************************************** /*****************************************************************************
...@@ -9134,7 +9039,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { ...@@ -9134,7 +9039,6 @@ static struct ieee80211_ops iwl4965_hw_ops = {
.erp_ie_changed = iwl4965_mac_erp_ie_changed, .erp_ie_changed = iwl4965_mac_erp_ie_changed,
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
.conf_ht = iwl4965_mac_conf_ht, .conf_ht = iwl4965_mac_conf_ht,
.get_ht_capab = iwl4965_mac_get_ht_capab,
#ifdef CONFIG_IWL4965_HT_AGG #ifdef CONFIG_IWL4965_HT_AGG
.ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start, .ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start,
.ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop, .ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment