|
@@ -439,12 +439,6 @@ void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
|
|
EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
|
|
EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
|
|
|
|
|
|
|
|
|
|
-static bool is_single_rx_stream(struct iwl_priv *priv)
|
|
|
|
-{
|
|
|
|
- return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
|
|
|
|
- priv->current_ht_config.single_chain_sufficient;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static bool iwl_is_channel_extension(struct iwl_priv *priv,
|
|
static bool iwl_is_channel_extension(struct iwl_priv *priv,
|
|
enum ieee80211_band band,
|
|
enum ieee80211_band band,
|
|
u16 channel, u8 extension_chan_offset)
|
|
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)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(iwl_set_rxon_ht);
|
|
EXPORT_SYMBOL(iwl_set_rxon_ht);
|
|
|
|
|
|
-#define IWL_NUM_RX_CHAINS_MULTIPLE 3
|
|
|
|
-#define IWL_NUM_RX_CHAINS_SINGLE 2
|
|
|
|
-#define IWL_NUM_IDLE_CHAINS_DUAL 2
|
|
|
|
-#define IWL_NUM_IDLE_CHAINS_SINGLE 1
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * Determine how many receiver/antenna chains to use.
|
|
|
|
- *
|
|
|
|
- * More provides better reception via diversity. Fewer saves power
|
|
|
|
- * at the expense of throughput, but only when not in powersave to
|
|
|
|
- * start with.
|
|
|
|
- *
|
|
|
|
- * MIMO (dual stream) requires at least 2, but works better with 3.
|
|
|
|
- * This does not determine *which* chains to use, just how many.
|
|
|
|
- */
|
|
|
|
-static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
|
|
|
-{
|
|
|
|
- if (priv->cfg->bt_params &&
|
|
|
|
- priv->cfg->bt_params->advanced_bt_coexist &&
|
|
|
|
- (priv->bt_full_concurrent ||
|
|
|
|
- priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
|
|
|
- /*
|
|
|
|
- * only use chain 'A' in bt high traffic load or
|
|
|
|
- * full concurrency mode
|
|
|
|
- */
|
|
|
|
- return IWL_NUM_RX_CHAINS_SINGLE;
|
|
|
|
- }
|
|
|
|
- /* # of Rx chains to use when expecting MIMO. */
|
|
|
|
- if (is_single_rx_stream(priv))
|
|
|
|
- return IWL_NUM_RX_CHAINS_SINGLE;
|
|
|
|
- else
|
|
|
|
- return IWL_NUM_RX_CHAINS_MULTIPLE;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * When we are in power saving mode, unless device support spatial
|
|
|
|
- * multiplexing power save, use the active count for rx chain count.
|
|
|
|
- */
|
|
|
|
-static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
|
|
|
|
-{
|
|
|
|
- /* # Rx chains when idling, depending on SMPS mode */
|
|
|
|
- switch (priv->current_ht_config.smps) {
|
|
|
|
- case IEEE80211_SMPS_STATIC:
|
|
|
|
- case IEEE80211_SMPS_DYNAMIC:
|
|
|
|
- return IWL_NUM_IDLE_CHAINS_SINGLE;
|
|
|
|
- case IEEE80211_SMPS_OFF:
|
|
|
|
- return active_cnt;
|
|
|
|
- default:
|
|
|
|
- WARN(1, "invalid SMPS mode %d",
|
|
|
|
- priv->current_ht_config.smps);
|
|
|
|
- return active_cnt;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/* up to 4 chains */
|
|
|
|
-static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
|
|
|
|
-{
|
|
|
|
- u8 res;
|
|
|
|
- res = (chain_bitmap & BIT(0)) >> 0;
|
|
|
|
- res += (chain_bitmap & BIT(1)) >> 1;
|
|
|
|
- res += (chain_bitmap & BIT(2)) >> 2;
|
|
|
|
- res += (chain_bitmap & BIT(3)) >> 3;
|
|
|
|
- return res;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
|
|
|
|
- *
|
|
|
|
- * Selects how many and which Rx receivers/antennas/chains to use.
|
|
|
|
- * This should not be used for scan command ... it puts data in wrong place.
|
|
|
|
- */
|
|
|
|
-void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|
|
|
-{
|
|
|
|
- bool is_single = is_single_rx_stream(priv);
|
|
|
|
- bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
|
|
|
|
- u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
|
|
|
|
- u32 active_chains;
|
|
|
|
- u16 rx_chain;
|
|
|
|
-
|
|
|
|
- /* Tell uCode which antennas are actually connected.
|
|
|
|
- * Before first association, we assume all antennas are connected.
|
|
|
|
- * Just after first association, iwl_chain_noise_calibration()
|
|
|
|
- * checks which antennas actually *are* connected. */
|
|
|
|
- if (priv->chain_noise_data.active_chains)
|
|
|
|
- active_chains = priv->chain_noise_data.active_chains;
|
|
|
|
- else
|
|
|
|
- active_chains = priv->hw_params.valid_rx_ant;
|
|
|
|
-
|
|
|
|
- if (priv->cfg->bt_params &&
|
|
|
|
- priv->cfg->bt_params->advanced_bt_coexist &&
|
|
|
|
- (priv->bt_full_concurrent ||
|
|
|
|
- priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
|
|
|
- /*
|
|
|
|
- * only use chain 'A' in bt high traffic load or
|
|
|
|
- * full concurrency mode
|
|
|
|
- */
|
|
|
|
- active_chains = first_antenna(active_chains);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
|
|
|
|
-
|
|
|
|
- /* How many receivers should we use? */
|
|
|
|
- active_rx_cnt = iwl_get_active_rx_chain_count(priv);
|
|
|
|
- idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /* correct rx chain count according hw settings
|
|
|
|
- * and chain noise calibration
|
|
|
|
- */
|
|
|
|
- valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
|
|
|
|
- if (valid_rx_cnt < active_rx_cnt)
|
|
|
|
- active_rx_cnt = valid_rx_cnt;
|
|
|
|
-
|
|
|
|
- if (valid_rx_cnt < idle_rx_cnt)
|
|
|
|
- idle_rx_cnt = valid_rx_cnt;
|
|
|
|
-
|
|
|
|
- rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
|
|
|
|
- rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
|
|
|
|
-
|
|
|
|
- ctx->staging.rx_chain = cpu_to_le16(rx_chain);
|
|
|
|
-
|
|
|
|
- if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
|
|
|
|
- ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
|
|
|
- else
|
|
|
|
- ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
|
|
|
|
-
|
|
|
|
- IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
|
|
|
|
- ctx->staging.rx_chain,
|
|
|
|
- active_rx_cnt, idle_rx_cnt);
|
|
|
|
-
|
|
|
|
- WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
|
|
|
|
- active_rx_cnt < idle_rx_cnt);
|
|
|
|
-}
|
|
|
|
-EXPORT_SYMBOL(iwl_set_rxon_chain);
|
|
|
|
-
|
|
|
|
/* Return valid, unused, channel for a passive scan to reset the RF */
|
|
/* Return valid, unused, channel for a passive scan to reset the RF */
|
|
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
|
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
|
enum ieee80211_band band)
|
|
enum ieee80211_band band)
|