aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-09-22 12:01:58 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2010-10-07 18:49:34 -0400
commit5de33068a2f841536ca8632534e3e193d5b2607f (patch)
tree7e94cf905b7eacfbab73a6774d9930f6546954f8 /drivers/net/wireless
parent8289e07b8a4b588e167bc84f93419458fd6efa3e (diff)
iwlwifi: move chain settings to agn
The core module doesn't need to carry around the code for chain settings that is used for HT drivers (agn) only. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c140
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c141
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
6 files changed, 144 insertions, 145 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index e161f5d7044d..20626c997b4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2217,7 +2217,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
2217static struct iwl_hcmd_ops iwl4965_hcmd = { 2217static struct iwl_hcmd_ops iwl4965_hcmd = {
2218 .rxon_assoc = iwl4965_send_rxon_assoc, 2218 .rxon_assoc = iwl4965_send_rxon_assoc,
2219 .commit_rxon = iwlagn_commit_rxon, 2219 .commit_rxon = iwlagn_commit_rxon,
2220 .set_rxon_chain = iwl_set_rxon_chain, 2220 .set_rxon_chain = iwlagn_set_rxon_chain,
2221 .send_bt_config = iwl_send_bt_config, 2221 .send_bt_config = iwl_send_bt_config,
2222}; 2222};
2223 2223
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 634177d827d3..ffb2f4111ad0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -361,7 +361,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)
361struct iwl_hcmd_ops iwlagn_hcmd = { 361struct iwl_hcmd_ops iwlagn_hcmd = {
362 .rxon_assoc = iwlagn_send_rxon_assoc, 362 .rxon_assoc = iwlagn_send_rxon_assoc,
363 .commit_rxon = iwlagn_commit_rxon, 363 .commit_rxon = iwlagn_commit_rxon,
364 .set_rxon_chain = iwl_set_rxon_chain, 364 .set_rxon_chain = iwlagn_set_rxon_chain,
365 .set_tx_ant = iwlagn_send_tx_ant_config, 365 .set_tx_ant = iwlagn_send_tx_ant_config,
366 .send_bt_config = iwl_send_bt_config, 366 .send_bt_config = iwl_send_bt_config,
367 .set_pan_params = iwlagn_set_pan_params, 367 .set_pan_params = iwlagn_set_pan_params,
@@ -370,7 +370,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = {
370struct iwl_hcmd_ops iwlagn_bt_hcmd = { 370struct iwl_hcmd_ops iwlagn_bt_hcmd = {
371 .rxon_assoc = iwlagn_send_rxon_assoc, 371 .rxon_assoc = iwlagn_send_rxon_assoc,
372 .commit_rxon = iwlagn_commit_rxon, 372 .commit_rxon = iwlagn_commit_rxon,
373 .set_rxon_chain = iwl_set_rxon_chain, 373 .set_rxon_chain = iwlagn_set_rxon_chain,
374 .set_tx_ant = iwlagn_send_tx_ant_config, 374 .set_tx_ant = iwlagn_send_tx_ant_config,
375 .send_bt_config = iwlagn_send_advance_bt_config, 375 .send_bt_config = iwlagn_send_advance_bt_config,
376 .set_pan_params = iwlagn_set_pan_params, 376 .set_pan_params = iwlagn_set_pan_params,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3fa2c5c3706a..0b45bced9c0c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -2065,3 +2065,143 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
2065{ 2065{
2066 cancel_work_sync(&priv->bt_traffic_change_work); 2066 cancel_work_sync(&priv->bt_traffic_change_work);
2067} 2067}
2068
2069static bool is_single_rx_stream(struct iwl_priv *priv)
2070{
2071 return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
2072 priv->current_ht_config.single_chain_sufficient;
2073}
2074
2075#define IWL_NUM_RX_CHAINS_MULTIPLE 3
2076#define IWL_NUM_RX_CHAINS_SINGLE 2
2077#define IWL_NUM_IDLE_CHAINS_DUAL 2
2078#define IWL_NUM_IDLE_CHAINS_SINGLE 1
2079
2080/*
2081 * Determine how many receiver/antenna chains to use.
2082 *
2083 * More provides better reception via diversity. Fewer saves power
2084 * at the expense of throughput, but only when not in powersave to
2085 * start with.
2086 *
2087 * MIMO (dual stream) requires at least 2, but works better with 3.
2088 * This does not determine *which* chains to use, just how many.
2089 */
2090static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
2091{
2092 if (priv->cfg->bt_params &&
2093 priv->cfg->bt_params->advanced_bt_coexist &&
2094 (priv->bt_full_concurrent ||
2095 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
2096 /*
2097 * only use chain 'A' in bt high traffic load or
2098 * full concurrency mode
2099 */
2100 return IWL_NUM_RX_CHAINS_SINGLE;
2101 }
2102 /* # of Rx chains to use when expecting MIMO. */
2103 if (is_single_rx_stream(priv))
2104 return IWL_NUM_RX_CHAINS_SINGLE;
2105 else
2106 return IWL_NUM_RX_CHAINS_MULTIPLE;
2107}
2108
2109/*
2110 * When we are in power saving mode, unless device support spatial
2111 * multiplexing power save, use the active count for rx chain count.
2112 */
2113static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
2114{
2115 /* # Rx chains when idling, depending on SMPS mode */
2116 switch (priv->current_ht_config.smps) {
2117 case IEEE80211_SMPS_STATIC:
2118 case IEEE80211_SMPS_DYNAMIC:
2119 return IWL_NUM_IDLE_CHAINS_SINGLE;
2120 case IEEE80211_SMPS_OFF:
2121 return active_cnt;
2122 default:
2123 WARN(1, "invalid SMPS mode %d",
2124 priv->current_ht_config.smps);
2125 return active_cnt;
2126 }
2127}
2128
2129/* up to 4 chains */
2130static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
2131{
2132 u8 res;
2133 res = (chain_bitmap & BIT(0)) >> 0;
2134 res += (chain_bitmap & BIT(1)) >> 1;
2135 res += (chain_bitmap & BIT(2)) >> 2;
2136 res += (chain_bitmap & BIT(3)) >> 3;
2137 return res;
2138}
2139
2140/**
2141 * iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
2142 *
2143 * Selects how many and which Rx receivers/antennas/chains to use.
2144 * This should not be used for scan command ... it puts data in wrong place.
2145 */
2146void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
2147{
2148 bool is_single = is_single_rx_stream(priv);
2149 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
2150 u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
2151 u32 active_chains;
2152 u16 rx_chain;
2153
2154 /* Tell uCode which antennas are actually connected.
2155 * Before first association, we assume all antennas are connected.
2156 * Just after first association, iwl_chain_noise_calibration()
2157 * checks which antennas actually *are* connected. */
2158 if (priv->chain_noise_data.active_chains)
2159 active_chains = priv->chain_noise_data.active_chains;
2160 else
2161 active_chains = priv->hw_params.valid_rx_ant;
2162
2163 if (priv->cfg->bt_params &&
2164 priv->cfg->bt_params->advanced_bt_coexist &&
2165 (priv->bt_full_concurrent ||
2166 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
2167 /*
2168 * only use chain 'A' in bt high traffic load or
2169 * full concurrency mode
2170 */
2171 active_chains = first_antenna(active_chains);
2172 }
2173
2174 rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
2175
2176 /* How many receivers should we use? */
2177 active_rx_cnt = iwl_get_active_rx_chain_count(priv);
2178 idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
2179
2180
2181 /* correct rx chain count according hw settings
2182 * and chain noise calibration
2183 */
2184 valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
2185 if (valid_rx_cnt < active_rx_cnt)
2186 active_rx_cnt = valid_rx_cnt;
2187
2188 if (valid_rx_cnt < idle_rx_cnt)
2189 idle_rx_cnt = valid_rx_cnt;
2190
2191 rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
2192 rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
2193
2194 ctx->staging.rx_chain = cpu_to_le16(rx_chain);
2195
2196 if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
2197 ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
2198 else
2199 ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
2200
2201 IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
2202 ctx->staging.rx_chain,
2203 active_rx_cnt, idle_rx_cnt);
2204
2205 WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
2206 active_rx_cnt < idle_rx_cnt);
2207}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 960fe2e5e579..5d5cacb54eb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -131,6 +131,7 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
131 131
132/* RXON */ 132/* RXON */
133int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 133int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
134void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
134 135
135/* uCode */ 136/* uCode */
136int iwlagn_load_ucode(struct iwl_priv *priv); 137int iwlagn_load_ucode(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 516c55ae38aa..dd7c3cbd2f6b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -439,12 +439,6 @@ void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
439EXPORT_SYMBOL(iwlcore_tx_cmd_protection); 439EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
440 440
441 441
442static bool is_single_rx_stream(struct iwl_priv *priv)
443{
444 return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
445 priv->current_ht_config.single_chain_sufficient;
446}
447
448static bool iwl_is_channel_extension(struct iwl_priv *priv, 442static bool iwl_is_channel_extension(struct iwl_priv *priv,
449 enum ieee80211_band band, 443 enum ieee80211_band band,
450 u16 channel, u8 extension_chan_offset) 444 u16 channel, u8 extension_chan_offset)
@@ -834,141 +828,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
834} 828}
835EXPORT_SYMBOL(iwl_set_rxon_ht); 829EXPORT_SYMBOL(iwl_set_rxon_ht);
836 830
837#define IWL_NUM_RX_CHAINS_MULTIPLE 3
838#define IWL_NUM_RX_CHAINS_SINGLE 2
839#define IWL_NUM_IDLE_CHAINS_DUAL 2
840#define IWL_NUM_IDLE_CHAINS_SINGLE 1
841
842/*
843 * Determine how many receiver/antenna chains to use.
844 *
845 * More provides better reception via diversity. Fewer saves power
846 * at the expense of throughput, but only when not in powersave to
847 * start with.
848 *
849 * MIMO (dual stream) requires at least 2, but works better with 3.
850 * This does not determine *which* chains to use, just how many.
851 */
852static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
853{
854 if (priv->cfg->bt_params &&
855 priv->cfg->bt_params->advanced_bt_coexist &&
856 (priv->bt_full_concurrent ||
857 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
858 /*
859 * only use chain 'A' in bt high traffic load or
860 * full concurrency mode
861 */
862 return IWL_NUM_RX_CHAINS_SINGLE;
863 }
864 /* # of Rx chains to use when expecting MIMO. */
865 if (is_single_rx_stream(priv))
866 return IWL_NUM_RX_CHAINS_SINGLE;
867 else
868 return IWL_NUM_RX_CHAINS_MULTIPLE;
869}
870
871/*
872 * When we are in power saving mode, unless device support spatial
873 * multiplexing power save, use the active count for rx chain count.
874 */
875static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
876{
877 /* # Rx chains when idling, depending on SMPS mode */
878 switch (priv->current_ht_config.smps) {
879 case IEEE80211_SMPS_STATIC:
880 case IEEE80211_SMPS_DYNAMIC:
881 return IWL_NUM_IDLE_CHAINS_SINGLE;
882 case IEEE80211_SMPS_OFF:
883 return active_cnt;
884 default:
885 WARN(1, "invalid SMPS mode %d",
886 priv->current_ht_config.smps);
887 return active_cnt;
888 }
889}
890
891/* up to 4 chains */
892static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
893{
894 u8 res;
895 res = (chain_bitmap & BIT(0)) >> 0;
896 res += (chain_bitmap & BIT(1)) >> 1;
897 res += (chain_bitmap & BIT(2)) >> 2;
898 res += (chain_bitmap & BIT(3)) >> 3;
899 return res;
900}
901
902/**
903 * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
904 *
905 * Selects how many and which Rx receivers/antennas/chains to use.
906 * This should not be used for scan command ... it puts data in wrong place.
907 */
908void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
909{
910 bool is_single = is_single_rx_stream(priv);
911 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
912 u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
913 u32 active_chains;
914 u16 rx_chain;
915
916 /* Tell uCode which antennas are actually connected.
917 * Before first association, we assume all antennas are connected.
918 * Just after first association, iwl_chain_noise_calibration()
919 * checks which antennas actually *are* connected. */
920 if (priv->chain_noise_data.active_chains)
921 active_chains = priv->chain_noise_data.active_chains;
922 else
923 active_chains = priv->hw_params.valid_rx_ant;
924
925 if (priv->cfg->bt_params &&
926 priv->cfg->bt_params->advanced_bt_coexist &&
927 (priv->bt_full_concurrent ||
928 priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
929 /*
930 * only use chain 'A' in bt high traffic load or
931 * full concurrency mode
932 */
933 active_chains = first_antenna(active_chains);
934 }
935
936 rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
937
938 /* How many receivers should we use? */
939 active_rx_cnt = iwl_get_active_rx_chain_count(priv);
940 idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
941
942
943 /* correct rx chain count according hw settings
944 * and chain noise calibration
945 */
946 valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
947 if (valid_rx_cnt < active_rx_cnt)
948 active_rx_cnt = valid_rx_cnt;
949
950 if (valid_rx_cnt < idle_rx_cnt)
951 idle_rx_cnt = valid_rx_cnt;
952
953 rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
954 rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
955
956 ctx->staging.rx_chain = cpu_to_le16(rx_chain);
957
958 if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
959 ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
960 else
961 ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
962
963 IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
964 ctx->staging.rx_chain,
965 active_rx_cnt, idle_rx_cnt);
966
967 WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
968 active_rx_cnt < idle_rx_cnt);
969}
970EXPORT_SYMBOL(iwl_set_rxon_chain);
971
972/* Return valid, unused, channel for a passive scan to reset the RF */ 831/* Return valid, unused, channel for a passive scan to reset the RF */
973u8 iwl_get_single_channel_number(struct iwl_priv *priv, 832u8 iwl_get_single_channel_number(struct iwl_priv *priv,
974 enum ieee80211_band band) 833 enum ieee80211_band band)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 09908f604e28..50a3c26e1412 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -407,7 +407,6 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
407 int hw_decrypt); 407 int hw_decrypt);
408int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 408int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
409int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 409int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
410void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
411int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, 410int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
412 struct iwl_rxon_context *ctx); 411 struct iwl_rxon_context *ctx);
413void iwl_set_flags_for_band(struct iwl_priv *priv, 412void iwl_set_flags_for_band(struct iwl_priv *priv,