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 { ...@@ -283,18 +283,20 @@ struct iwl_cmd_header {
#define RATE_MCS_SGI_MSK 0x2000 #define RATE_MCS_SGI_MSK 0x2000
/** /**
* rate_n_flags Tx antenna masks (4965 has 2 transmitters): * rate_n_flags Tx antenna masks
* bit14:15 01 B inactive, A active * 4965 has 2 transmitters
* 10 B active, A inactive * 5100 has 1 transmitter B
* 11 Both active * 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_POS 14
#define RATE_MCS_ANT_A_MSK 0x04000 #define RATE_MCS_ANT_A_MSK 0x04000
#define RATE_MCS_ANT_B_MSK 0x08000 #define RATE_MCS_ANT_B_MSK 0x08000
#define RATE_MCS_ANT_C_MSK 0x10000 #define RATE_MCS_ANT_C_MSK 0x10000
#define RATE_MCS_ANT_ABC_MSK 0x1C000 #define RATE_MCS_ANT_ABC_MSK 0x1C000
#define RATE_ANT_NUM 3
#define RATE_MCS_ANT_INIT_IND 1
#define POWER_TABLE_NUM_ENTRIES 33 #define POWER_TABLE_NUM_ENTRIES 33
#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
......
...@@ -141,7 +141,17 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) ...@@ -141,7 +141,17 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
} }
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); 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 }; const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(iwl_bcast_addr); EXPORT_SYMBOL(iwl_bcast_addr);
...@@ -938,7 +948,6 @@ int iwl_init_drv(struct iwl_priv *priv) ...@@ -938,7 +948,6 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION; 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; priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
/* Choose which receivers/antennas to use */ /* 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); ...@@ -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_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_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); int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
/***************************************************** /*****************************************************
* TX power * TX power
****************************************************/ ****************************************************/
...@@ -259,6 +258,13 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, ...@@ -259,6 +258,13 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info); struct ieee80211_tx_info *info);
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); 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) static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
{ {
return le32_to_cpu(rate_n_flags) & 0xFF; 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); ...@@ -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_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv);
/*************** DRIVER STATUS FUNCTIONS *****/ /*************** DRIVER STATUS FUNCTIONS *****/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ #define STATUS_HCMD_ACTIVE 0 /* host command in progress */
......
...@@ -810,12 +810,13 @@ struct iwl_priv { ...@@ -810,12 +810,13 @@ struct iwl_priv {
unsigned long scan_start; unsigned long scan_start;
unsigned long scan_pass_start; unsigned long scan_pass_start;
unsigned long scan_start_tsf; unsigned long scan_start_tsf;
struct iwl_scan_cmd *scan;
int scan_bands; int scan_bands;
int one_direct_scan; int one_direct_scan;
u8 direct_ssid_len; u8 direct_ssid_len;
u8 direct_ssid[IW_ESSID_MAX_SIZE]; u8 direct_ssid[IW_ESSID_MAX_SIZE];
struct iwl_scan_cmd *scan; u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u32 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant;
/* spinlock */ /* spinlock */
spinlock_t lock; /* protect general shared data */ spinlock_t lock; /* protect general shared data */
...@@ -874,7 +875,6 @@ struct iwl_priv { ...@@ -874,7 +875,6 @@ struct iwl_priv {
u16 active_rate_basic; u16 active_rate_basic;
u8 assoc_station_added; u8 assoc_station_added;
u8 use_ant_b_for_management_frame; /* Tx antenna selection */
u8 start_calib; u8 start_calib;
struct iwl_sensitivity_data sensitivity_data; struct iwl_sensitivity_data sensitivity_data;
struct iwl_chain_noise_data chain_noise_data; struct iwl_chain_noise_data chain_noise_data;
......
...@@ -64,12 +64,6 @@ ...@@ -64,12 +64,6 @@
#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) #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) static int iwl_is_empty_essid(const char *essid, int essid_len)
{ {
/* Single white space is for Linksys APs */ /* Single white space is for Linksys APs */
...@@ -455,10 +449,11 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, ...@@ -455,10 +449,11 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
void iwl_init_scan_params(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]) 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]) 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) int iwl_scan_initiate(struct iwl_priv *priv)
...@@ -670,23 +665,6 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -670,23 +665,6 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
return (u16)len; 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) static void iwl_bg_request_scan(struct work_struct *data)
{ {
struct iwl_priv *priv = struct iwl_priv *priv =
...@@ -699,11 +677,12 @@ static void iwl_bg_request_scan(struct work_struct *data) ...@@ -699,11 +677,12 @@ static void iwl_bg_request_scan(struct work_struct *data)
struct iwl_scan_cmd *scan; struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL; struct ieee80211_conf *conf = NULL;
int ret = 0; int ret = 0;
u32 tx_ant; u32 rate_flags = 0;
u16 cmd_len; u16 cmd_len;
enum ieee80211_band band; enum ieee80211_band band;
u8 n_probes = 2; u8 n_probes = 2;
u8 rx_chain = priv->hw_params.valid_rx_ant; u8 rx_chain = priv->hw_params.valid_rx_ant;
u8 rate;
conf = ieee80211_get_hw_conf(priv->hw); conf = ieee80211_get_hw_conf(priv->hw);
...@@ -822,23 +801,16 @@ static void iwl_bg_request_scan(struct work_struct *data) ...@@ -822,23 +801,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
band = IEEE80211_BAND_2GHZ; band = IEEE80211_BAND_2GHZ;
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; 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) {
if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) rate = IWL_RATE_6M_PLCP;
scan->tx_cmd.rate_n_flags = } else {
iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, rate = IWL_RATE_1M_PLCP;
tx_ant); rate_flags = RATE_MCS_CCK_MSK;
else }
scan->tx_cmd.rate_n_flags =
iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
tx_ant |
RATE_MCS_CCK_MSK);
scan->good_CRC_th = 0; scan->good_CRC_th = 0;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
band = IEEE80211_BAND_5GHZ; band = IEEE80211_BAND_5GHZ;
tx_ant = iwl_scan_tx_ant(priv, band); rate = IWL_RATE_6M_PLCP;
scan->tx_cmd.rate_n_flags =
iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
tx_ant);
scan->good_CRC_th = IWL_GOOD_CRC_TH; scan->good_CRC_th = IWL_GOOD_CRC_TH;
/* Force use of chains B and C (0x6) for scan Rx for 4965 /* 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) ...@@ -851,6 +823,11 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done; 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 */ /* MIMO is not used here, but value is required */
scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
......
...@@ -674,11 +674,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, ...@@ -674,11 +674,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
__le16 fc, int sta_id, __le16 fc, int sta_id,
int is_hcca) int is_hcca)
{ {
u32 rate_flags = 0;
int rate_idx;
u8 rts_retry_limit = 0; u8 rts_retry_limit = 0;
u8 data_retry_limit = 0; u8 data_retry_limit = 0;
u8 rate_plcp; u8 rate_plcp;
u16 rate_flags = 0;
int rate_idx;
rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff, rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
IWL_RATE_COUNT - 1); IWL_RATE_COUNT - 1);
...@@ -721,14 +721,8 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, ...@@ -721,14 +721,8 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
break; break;
} }
/* Alternate between antenna A and B for successive frames */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
if (priv->use_ant_b_for_management_frame) { rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
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;
}
} }
tx_cmd->rts_retry_limit = rts_retry_limit; 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