Commit 76eff18b authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville

iwlwifi: unify tx antenna toggling

TX antenna toggling is requested for management frames in tx and
scanning. I addition toggling in scanning was incorrect;
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Reviewed-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 961ba60a
......@@ -283,18 +283,20 @@ struct iwl_cmd_header {
#define RATE_MCS_SGI_MSK 0x2000
/**
* rate_n_flags Tx antenna masks (4965 has 2 transmitters):
* bit14:15 01 B inactive, A active
* 10 B active, A inactive
* 11 Both active
* rate_n_flags Tx antenna masks
* 4965 has 2 transmitters
* 5100 has 1 transmitter B
* 5150 has 1 transmitter A
* 5300 has 3 transmitters
* 5350 has 3 transmitters
* bit14:16
*/
#define RATE_MCS_ANT_POS 14
#define RATE_MCS_ANT_A_MSK 0x04000
#define RATE_MCS_ANT_B_MSK 0x08000
#define RATE_MCS_ANT_C_MSK 0x10000
#define RATE_MCS_ANT_ABC_MSK 0x1C000
#define RATE_MCS_ANT_INIT_IND 1
#define RATE_ANT_NUM 3
#define POWER_TABLE_NUM_ENTRIES 33
#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
......
......@@ -141,7 +141,17 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
}
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
{
int i;
u8 ind = ant;
for (i = 0; i < RATE_ANT_NUM - 1; i++) {
ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
if (priv->hw_params.valid_tx_ant & BIT(ind))
return ind;
}
return ant;
}
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(iwl_bcast_addr);
......@@ -938,7 +948,6 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->use_ant_b_for_management_frame = 1; /* start with ant B */
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
/* Choose which receivers/antennas to use */
......
......@@ -237,7 +237,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
/*****************************************************
* TX power
****************************************************/
......@@ -259,6 +258,13 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info);
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
{
return BIT(ant_idx) << RATE_MCS_ANT_POS;
}
static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
{
return le32_to_cpu(rate_n_flags) & 0xFF;
......@@ -313,6 +319,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv);
/*************** DRIVER STATUS FUNCTIONS *****/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
......
......@@ -810,12 +810,13 @@ struct iwl_priv {
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
struct iwl_scan_cmd *scan;
int scan_bands;
int one_direct_scan;
u8 direct_ssid_len;
u8 direct_ssid[IW_ESSID_MAX_SIZE];
struct iwl_scan_cmd *scan;
u32 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
/* spinlock */
spinlock_t lock; /* protect general shared data */
......@@ -874,7 +875,6 @@ struct iwl_priv {
u16 active_rate_basic;
u8 assoc_station_added;
u8 use_ant_b_for_management_frame; /* Tx antenna selection */
u8 start_calib;
struct iwl_sensitivity_data sensitivity_data;
struct iwl_chain_noise_data chain_noise_data;
......
......@@ -64,12 +64,6 @@
#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
static int scan_tx_ant[3] = {
RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK
};
static int iwl_is_empty_essid(const char *essid, int essid_len)
{
/* Single white space is for Linksys APs */
......@@ -455,10 +449,11 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
void iwl_init_scan_params(struct iwl_priv *priv)
{
u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = RATE_MCS_ANT_INIT_IND;
priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = RATE_MCS_ANT_INIT_IND;
priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
}
int iwl_scan_initiate(struct iwl_priv *priv)
......@@ -670,23 +665,6 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
return (u16)len;
}
static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
{
int i, ind;
ind = priv->scan_tx_ant[band];
for (i = 0; i < priv->hw_params.tx_chains_num; i++) {
ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1;
if (priv->hw_params.valid_tx_ant & (1 << ind)) {
priv->scan_tx_ant[band] = ind;
break;
}
}
IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
return scan_tx_ant[ind];
}
static void iwl_bg_request_scan(struct work_struct *data)
{
struct iwl_priv *priv =
......@@ -699,11 +677,12 @@ static void iwl_bg_request_scan(struct work_struct *data)
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
int ret = 0;
u32 tx_ant;
u32 rate_flags = 0;
u16 cmd_len;
enum ieee80211_band band;
u8 n_probes = 2;
u8 rx_chain = priv->hw_params.valid_rx_ant;
u8 rate;
conf = ieee80211_get_hw_conf(priv->hw);
......@@ -822,23 +801,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
band = IEEE80211_BAND_2GHZ;
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
tx_ant = iwl_scan_tx_ant(priv, band);
if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK)
scan->tx_cmd.rate_n_flags =
iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
tx_ant);
else
scan->tx_cmd.rate_n_flags =
iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
tx_ant |
RATE_MCS_CCK_MSK);
if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) {
rate = IWL_RATE_6M_PLCP;
} else {
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
}
scan->good_CRC_th = 0;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
band = IEEE80211_BAND_5GHZ;
tx_ant = iwl_scan_tx_ant(priv, band);
scan->tx_cmd.rate_n_flags =
iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
tx_ant);
rate = IWL_RATE_6M_PLCP;
scan->good_CRC_th = IWL_GOOD_CRC_TH;
/* Force use of chains B and C (0x6) for scan Rx for 4965
......@@ -851,6 +823,11 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
priv->scan_tx_ant[band] =
iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
/* MIMO is not used here, but value is required */
scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
......
......@@ -674,11 +674,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
__le16 fc, int sta_id,
int is_hcca)
{
u32 rate_flags = 0;
int rate_idx;
u8 rts_retry_limit = 0;
u8 data_retry_limit = 0;
u8 rate_plcp;
u16 rate_flags = 0;
int rate_idx;
rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
IWL_RATE_COUNT - 1);
......@@ -721,14 +721,8 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
break;
}
/* Alternate between antenna A and B for successive frames */
if (priv->use_ant_b_for_management_frame) {
priv->use_ant_b_for_management_frame = 0;
rate_flags |= RATE_MCS_ANT_B_MSK;
} else {
priv->use_ant_b_for_management_frame = 1;
rate_flags |= RATE_MCS_ANT_A_MSK;
}
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
}
tx_cmd->rts_retry_limit = rts_retry_limit;
......
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