aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-10-14 15:32:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:29 -0400
commit76eff18bdc5feaa53f1be33709b67df02f1d55e9 (patch)
treeb532664298ca1ecad5bebf2155fe194d2b0c20dd /drivers
parent961ba60abe02517d0c8252f9befb1478f4e008a4 (diff)
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: Tomas Winkler <tomas.winkler@intel.com> Reviewed-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c57
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c14
6 files changed, 51 insertions, 62 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index ba54613ae63e..67680a74afde 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -283,18 +283,20 @@ struct iwl_cmd_header {
283#define RATE_MCS_SGI_MSK 0x2000 283#define RATE_MCS_SGI_MSK 0x2000
284 284
285/** 285/**
286 * rate_n_flags Tx antenna masks (4965 has 2 transmitters): 286 * rate_n_flags Tx antenna masks
287 * bit14:15 01 B inactive, A active 287 * 4965 has 2 transmitters
288 * 10 B active, A inactive 288 * 5100 has 1 transmitter B
289 * 11 Both active 289 * 5150 has 1 transmitter A
290 * 5300 has 3 transmitters
291 * 5350 has 3 transmitters
292 * bit14:16
290 */ 293 */
291#define RATE_MCS_ANT_POS 14 294#define RATE_MCS_ANT_POS 14
292#define RATE_MCS_ANT_A_MSK 0x04000 295#define RATE_MCS_ANT_A_MSK 0x04000
293#define RATE_MCS_ANT_B_MSK 0x08000 296#define RATE_MCS_ANT_B_MSK 0x08000
294#define RATE_MCS_ANT_C_MSK 0x10000 297#define RATE_MCS_ANT_C_MSK 0x10000
295#define RATE_MCS_ANT_ABC_MSK 0x1C000 298#define RATE_MCS_ANT_ABC_MSK 0x1C000
296 299#define RATE_ANT_NUM 3
297#define RATE_MCS_ANT_INIT_IND 1
298 300
299#define POWER_TABLE_NUM_ENTRIES 33 301#define POWER_TABLE_NUM_ENTRIES 33
300#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 302#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 59dd608b9095..20c7ff382914 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -141,7 +141,17 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
141} 141}
142EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); 142EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
143 143
144 144u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
145{
146 int i;
147 u8 ind = ant;
148 for (i = 0; i < RATE_ANT_NUM - 1; i++) {
149 ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
150 if (priv->hw_params.valid_tx_ant & BIT(ind))
151 return ind;
152 }
153 return ant;
154}
145 155
146const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 156const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
147EXPORT_SYMBOL(iwl_bcast_addr); 157EXPORT_SYMBOL(iwl_bcast_addr);
@@ -938,7 +948,6 @@ int iwl_init_drv(struct iwl_priv *priv)
938 948
939 priv->iw_mode = NL80211_IFTYPE_STATION; 949 priv->iw_mode = NL80211_IFTYPE_STATION;
940 950
941 priv->use_ant_b_for_management_frame = 1; /* start with ant B */
942 priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; 951 priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
943 952
944 /* Choose which receivers/antennas to use */ 953 /* Choose which receivers/antennas to use */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 1a3ad8b1ebdb..a2d8afe92beb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -237,7 +237,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
237int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); 237int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
238int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); 238int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
239int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); 239int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
240
241/***************************************************** 240/*****************************************************
242 * TX power 241 * TX power
243 ****************************************************/ 242 ****************************************************/
@@ -259,6 +258,13 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
259 struct ieee80211_tx_info *info); 258 struct ieee80211_tx_info *info);
260int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); 259int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
261 260
261u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
262
263static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
264{
265 return BIT(ant_idx) << RATE_MCS_ANT_POS;
266}
267
262static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) 268static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
263{ 269{
264 return le32_to_cpu(rate_n_flags) & 0xFF; 270 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);
313void iwl_dump_nic_error_log(struct iwl_priv *priv); 319void iwl_dump_nic_error_log(struct iwl_priv *priv);
314void iwl_dump_nic_event_log(struct iwl_priv *priv); 320void iwl_dump_nic_event_log(struct iwl_priv *priv);
315 321
322
316/*************** DRIVER STATUS FUNCTIONS *****/ 323/*************** DRIVER STATUS FUNCTIONS *****/
317 324
318#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ 325#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c73315f23949..0f57bf40e8d7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -810,12 +810,13 @@ struct iwl_priv {
810 unsigned long scan_start; 810 unsigned long scan_start;
811 unsigned long scan_pass_start; 811 unsigned long scan_pass_start;
812 unsigned long scan_start_tsf; 812 unsigned long scan_start_tsf;
813 struct iwl_scan_cmd *scan;
813 int scan_bands; 814 int scan_bands;
814 int one_direct_scan; 815 int one_direct_scan;
815 u8 direct_ssid_len; 816 u8 direct_ssid_len;
816 u8 direct_ssid[IW_ESSID_MAX_SIZE]; 817 u8 direct_ssid[IW_ESSID_MAX_SIZE];
817 struct iwl_scan_cmd *scan; 818 u8 scan_tx_ant[IEEE80211_NUM_BANDS];
818 u32 scan_tx_ant[IEEE80211_NUM_BANDS]; 819 u8 mgmt_tx_ant;
819 820
820 /* spinlock */ 821 /* spinlock */
821 spinlock_t lock; /* protect general shared data */ 822 spinlock_t lock; /* protect general shared data */
@@ -874,7 +875,6 @@ struct iwl_priv {
874 u16 active_rate_basic; 875 u16 active_rate_basic;
875 876
876 u8 assoc_station_added; 877 u8 assoc_station_added;
877 u8 use_ant_b_for_management_frame; /* Tx antenna selection */
878 u8 start_calib; 878 u8 start_calib;
879 struct iwl_sensitivity_data sensitivity_data; 879 struct iwl_sensitivity_data sensitivity_data;
880 struct iwl_chain_noise_data chain_noise_data; 880 struct iwl_chain_noise_data chain_noise_data;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 78d16bd7b745..86b74571b513 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -64,12 +64,6 @@
64#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) 64#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
65 65
66 66
67static int scan_tx_ant[3] = {
68 RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK
69};
70
71
72
73static int iwl_is_empty_essid(const char *essid, int essid_len) 67static int iwl_is_empty_essid(const char *essid, int essid_len)
74{ 68{
75 /* Single white space is for Linksys APs */ 69 /* Single white space is for Linksys APs */
@@ -455,10 +449,11 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
455 449
456void iwl_init_scan_params(struct iwl_priv *priv) 450void iwl_init_scan_params(struct iwl_priv *priv)
457{ 451{
452 u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
458 if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) 453 if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
459 priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = RATE_MCS_ANT_INIT_IND; 454 priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
460 if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) 455 if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
461 priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = RATE_MCS_ANT_INIT_IND; 456 priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
462} 457}
463 458
464int iwl_scan_initiate(struct iwl_priv *priv) 459int iwl_scan_initiate(struct iwl_priv *priv)
@@ -670,23 +665,6 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
670 return (u16)len; 665 return (u16)len;
671} 666}
672 667
673static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
674{
675 int i, ind;
676
677 ind = priv->scan_tx_ant[band];
678 for (i = 0; i < priv->hw_params.tx_chains_num; i++) {
679 ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1;
680 if (priv->hw_params.valid_tx_ant & (1 << ind)) {
681 priv->scan_tx_ant[band] = ind;
682 break;
683 }
684 }
685 IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
686 return scan_tx_ant[ind];
687}
688
689
690static void iwl_bg_request_scan(struct work_struct *data) 668static void iwl_bg_request_scan(struct work_struct *data)
691{ 669{
692 struct iwl_priv *priv = 670 struct iwl_priv *priv =
@@ -699,11 +677,12 @@ static void iwl_bg_request_scan(struct work_struct *data)
699 struct iwl_scan_cmd *scan; 677 struct iwl_scan_cmd *scan;
700 struct ieee80211_conf *conf = NULL; 678 struct ieee80211_conf *conf = NULL;
701 int ret = 0; 679 int ret = 0;
702 u32 tx_ant; 680 u32 rate_flags = 0;
703 u16 cmd_len; 681 u16 cmd_len;
704 enum ieee80211_band band; 682 enum ieee80211_band band;
705 u8 n_probes = 2; 683 u8 n_probes = 2;
706 u8 rx_chain = priv->hw_params.valid_rx_ant; 684 u8 rx_chain = priv->hw_params.valid_rx_ant;
685 u8 rate;
707 686
708 conf = ieee80211_get_hw_conf(priv->hw); 687 conf = ieee80211_get_hw_conf(priv->hw);
709 688
@@ -822,23 +801,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
822 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { 801 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
823 band = IEEE80211_BAND_2GHZ; 802 band = IEEE80211_BAND_2GHZ;
824 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; 803 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
825 tx_ant = iwl_scan_tx_ant(priv, band); 804 if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) {
826 if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) 805 rate = IWL_RATE_6M_PLCP;
827 scan->tx_cmd.rate_n_flags = 806 } else {
828 iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, 807 rate = IWL_RATE_1M_PLCP;
829 tx_ant); 808 rate_flags = RATE_MCS_CCK_MSK;
830 else 809 }
831 scan->tx_cmd.rate_n_flags =
832 iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
833 tx_ant |
834 RATE_MCS_CCK_MSK);
835 scan->good_CRC_th = 0; 810 scan->good_CRC_th = 0;
836 } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { 811 } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
837 band = IEEE80211_BAND_5GHZ; 812 band = IEEE80211_BAND_5GHZ;
838 tx_ant = iwl_scan_tx_ant(priv, band); 813 rate = IWL_RATE_6M_PLCP;
839 scan->tx_cmd.rate_n_flags =
840 iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
841 tx_ant);
842 scan->good_CRC_th = IWL_GOOD_CRC_TH; 814 scan->good_CRC_th = IWL_GOOD_CRC_TH;
843 815
844 /* Force use of chains B and C (0x6) for scan Rx for 4965 816 /* 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 goto done; 823 goto done;
852 } 824 }
853 825
826 priv->scan_tx_ant[band] =
827 iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
828 rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
829 scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
830
854 /* MIMO is not used here, but value is required */ 831 /* MIMO is not used here, but value is required */
855 scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 832 scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
856 cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | 833 cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 87c955e88427..b047fd156c0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -674,11 +674,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
674 __le16 fc, int sta_id, 674 __le16 fc, int sta_id,
675 int is_hcca) 675 int is_hcca)
676{ 676{
677 u32 rate_flags = 0;
678 int rate_idx;
677 u8 rts_retry_limit = 0; 679 u8 rts_retry_limit = 0;
678 u8 data_retry_limit = 0; 680 u8 data_retry_limit = 0;
679 u8 rate_plcp; 681 u8 rate_plcp;
680 u16 rate_flags = 0;
681 int rate_idx;
682 682
683 rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff, 683 rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
684 IWL_RATE_COUNT - 1); 684 IWL_RATE_COUNT - 1);
@@ -721,14 +721,8 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
721 break; 721 break;
722 } 722 }
723 723
724 /* Alternate between antenna A and B for successive frames */ 724 priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
725 if (priv->use_ant_b_for_management_frame) { 725 rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
726 priv->use_ant_b_for_management_frame = 0;
727 rate_flags |= RATE_MCS_ANT_B_MSK;
728 } else {
729 priv->use_ant_b_for_management_frame = 1;
730 rate_flags |= RATE_MCS_ANT_A_MSK;
731 }
732 } 726 }
733 727
734 tx_cmd->rts_retry_limit = rts_retry_limit; 728 tx_cmd->rts_retry_limit = rts_retry_limit;