diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2008-10-14 15:32:45 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:29 -0400 |
commit | 76eff18bdc5feaa53f1be33709b67df02f1d55e9 (patch) | |
tree | b532664298ca1ecad5bebf2155fe194d2b0c20dd /drivers | |
parent | 961ba60abe02517d0c8252f9befb1478f4e008a4 (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.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 14 |
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 | } |
142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
143 | 143 | ||
144 | 144 | u8 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 | ||
146 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 156 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
147 | EXPORT_SYMBOL(iwl_bcast_addr); | 157 | EXPORT_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); | |||
237 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 237 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
238 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 238 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
239 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); | 239 | int 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); |
260 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | 259 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); |
261 | 260 | ||
261 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); | ||
262 | |||
263 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) | ||
264 | { | ||
265 | return BIT(ant_idx) << RATE_MCS_ANT_POS; | ||
266 | } | ||
267 | |||
262 | static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) | 268 | static 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); | |||
313 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 319 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
314 | void iwl_dump_nic_event_log(struct iwl_priv *priv); | 320 | void 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 | ||
67 | static 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 | |||
73 | static int iwl_is_empty_essid(const char *essid, int essid_len) | 67 | static 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 | ||
456 | void iwl_init_scan_params(struct iwl_priv *priv) | 450 | void 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 | ||
464 | int iwl_scan_initiate(struct iwl_priv *priv) | 459 | int 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 | ||
673 | static 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 | |||
690 | static void iwl_bg_request_scan(struct work_struct *data) | 668 | static 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; |