]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-core.c
iwlwifi: clean key table in iwl_clear_stations_table function
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / iwl-core.c
index c72f72579beaeb2f70e2760a695f7b9268a533ab..b346268273adfa36b52830bacd7e9c3040ac8322 100644 (file)
@@ -290,6 +290,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
        priv->num_stations = 0;
        memset(priv->stations, 0, sizeof(priv->stations));
 
+       /* clean ucode key table bit map */
+       priv->ucode_key_table = 0;
+
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 EXPORT_SYMBOL(iwl_clear_stations_table);
@@ -592,12 +595,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
        clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
 
-static u8 is_single_rx_stream(struct iwl_priv *priv)
+static bool is_single_rx_stream(struct iwl_priv *priv)
 {
        return !priv->current_ht_config.is_ht ||
               ((priv->current_ht_config.supp_mcs_set[1] == 0) &&
-               (priv->current_ht_config.supp_mcs_set[2] == 0)) ||
-              priv->ps_mode == IWL_MIMO_PS_STATIC;
+               (priv->current_ht_config.supp_mcs_set[2] == 0));
 }
 
 static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -647,8 +649,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
        struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
        u32 val;
 
-       if (!ht_info->is_ht)
+       if (!ht_info->is_ht) {
+               rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
+                       RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
+                       RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+                       RXON_FLG_FAT_PROT_MSK |
+                       RXON_FLG_HT_PROT_MSK);
                return;
+       }
 
        /* Set up channel bandwidth:  20 MHz only, or 20/40 mixed if fat ok */
        if (iwl_is_fat_tx_allowed(priv, NULL))
@@ -704,33 +712,39 @@ EXPORT_SYMBOL(iwl_set_rxon_ht);
  * 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 iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
-                                       u8 *idle_state, u8 *rx_state)
+static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
 {
-       u8 is_single = is_single_rx_stream(priv);
-       u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1;
+       bool is_single = is_single_rx_stream(priv);
+       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
 
        /* # of Rx chains to use when expecting MIMO. */
        if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC)))
-               *rx_state = 2;
+               return 2;
        else
-               *rx_state = 3;
+               return 3;
+}
 
+static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+       int idle_cnt;
+       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
        /* # Rx chains when idling and maybe trying to save power */
        switch (priv->ps_mode) {
        case IWL_MIMO_PS_STATIC:
        case IWL_MIMO_PS_DYNAMIC:
-               *idle_state = (is_cam) ? 2 : 1;
+               idle_cnt = (is_cam) ? 2 : 1;
                break;
        case IWL_MIMO_PS_NONE:
-               *idle_state = (is_cam) ? *rx_state : 1;
+               idle_cnt = (is_cam) ? active_cnt : 1;
                break;
+       case IWL_MIMO_PS_INVALID:
        default:
-               *idle_state = 1;
+               IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode);
+               WARN_ON(1);
+               idle_cnt = -1;
                break;
        }
-
-       return 0;
+       return idle_cnt;
 }
 
 /**
@@ -741,34 +755,44 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
  */
 void iwl_set_rxon_chain(struct iwl_priv *priv)
 {
-       u8 is_single = is_single_rx_stream(priv);
-       u8 idle_state, rx_state;
-
-       priv->staging_rxon.rx_chain = 0;
-       rx_state = idle_state = 3;
+       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;
+       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. */
-       priv->staging_rxon.rx_chain |=
-                   cpu_to_le16(priv->hw_params.valid_rx_ant <<
-                                                RXON_RX_CHAIN_VALID_POS);
+       rx_chain = priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
 
        /* How many receivers should we use? */
-       iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state);
-       priv->staging_rxon.rx_chain |=
-               cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS);
-       priv->staging_rxon.rx_chain |=
-               cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS);
-
-       if (!is_single && (rx_state >= 2) &&
-           !test_bit(STATUS_POWER_PMI, &priv->status))
+       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 accoridng hw settings */
+       if (priv->hw_params.rx_chains_num < active_rx_cnt)
+               active_rx_cnt = priv->hw_params.rx_chains_num;
+
+       if (priv->hw_params.rx_chains_num < idle_rx_cnt)
+               idle_rx_cnt = priv->hw_params.rx_chains_num;
+
+       rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+       rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
+
+       priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
+
+       if (!is_single && (active_rx_cnt >= 2) && is_cam)
                priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
        else
                priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
 
-       IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
+       IWL_DEBUG_ASSOC("rx_chain=0x%Xi active=%d idle=%d\n",
+                       priv->staging_rxon.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);
 
@@ -935,22 +959,6 @@ err:
 }
 EXPORT_SYMBOL(iwl_init_drv);
 
-void iwl_free_calib_results(struct iwl_priv *priv)
-{
-       kfree(priv->calib_results.lo_res);
-       priv->calib_results.lo_res = NULL;
-       priv->calib_results.lo_res_len = 0;
-
-       kfree(priv->calib_results.tx_iq_res);
-       priv->calib_results.tx_iq_res = NULL;
-       priv->calib_results.tx_iq_res_len = 0;
-
-       kfree(priv->calib_results.tx_iq_perd_res);
-       priv->calib_results.tx_iq_perd_res = NULL;
-       priv->calib_results.tx_iq_perd_res_len = 0;
-}
-EXPORT_SYMBOL(iwl_free_calib_results);
-
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
        int ret = 0;
@@ -978,10 +986,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 }
 EXPORT_SYMBOL(iwl_set_tx_power);
 
-
 void iwl_uninit_drv(struct iwl_priv *priv)
 {
-       iwl_free_calib_results(priv);
+       iwl_calib_free_results(priv);
        iwlcore_free_geos(priv);
        iwl_free_channel_map(priv);
        kfree(priv->scan);