(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
        u8 start_action = tbl->action;
        u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+       u8 tx_chains_num = priv->hw_params.tx_chains_num;
        int ret = 0;
 
        for (; ;) {
                switch (tbl->action) {
-               case IWL_LEGACY_SWITCH_ANTENNA:
+               case IWL_LEGACY_SWITCH_ANTENNA1:
+               case IWL_LEGACY_SWITCH_ANTENNA2:
                        IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n");
 
                        lq_sta->action_counter++;
 
+                       if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
+                                                       tx_chains_num <= 1) ||
+                           (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
+                                                       tx_chains_num <= 2))
+                               break;
+
                        /* Don't change antenna if success has been great */
                        if (window->success_ratio >= IWL_RS_GOOD_RATIO)
                                break;
 
                        if (rs_toggle_antenna(valid_tx_ant,
                                &search_tbl->current_rate, search_tbl)) {
-                               lq_sta->search_better_tbl = 1;
+                               rs_set_expected_tpt_table(lq_sta, search_tbl);
                                goto out;
                        }
                        break;
                        ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
                                                 search_tbl, index);
                        if (!ret) {
-                               lq_sta->search_better_tbl = 1;
                                lq_sta->action_counter = 0;
                                goto out;
                        }
 
                        break;
-               case IWL_LEGACY_SWITCH_MIMO2:
+               case IWL_LEGACY_SWITCH_MIMO2_AB:
+               case IWL_LEGACY_SWITCH_MIMO2_AC:
+               case IWL_LEGACY_SWITCH_MIMO2_BC:
                        IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n");
 
                        /* Set up search table to try MIMO */
                        memcpy(search_tbl, tbl, sz);
                        search_tbl->is_SGI = 0;
-                       search_tbl->ant_type = ANT_AB;/*FIXME:RS*/
-                               /*FIXME:RS:need to check ant validity*/
+
+                       if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB)
+                               search_tbl->ant_type = ANT_AB;
+                       else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
+                               search_tbl->ant_type = ANT_AC;
+                       else
+                               search_tbl->ant_type = ANT_BC;
+
+                       if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+                               break;
+
                        ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
                                                 search_tbl, index);
                        if (!ret) {
-                               lq_sta->search_better_tbl = 1;
                                lq_sta->action_counter = 0;
                                goto out;
                        }
                        break;
                }
                tbl->action++;
-               if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
-                       tbl->action = IWL_LEGACY_SWITCH_ANTENNA;
+               if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+                       tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
 
                if (tbl->action == start_action)
                        break;
 
        }
+       search_tbl->lq_type = LQ_NONE;
        return 0;
 
- out:
+out:
+       lq_sta->search_better_tbl = 1;
        tbl->action++;
-       if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
-               tbl->action = IWL_LEGACY_SWITCH_ANTENNA;
+       if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+               tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
        return 0;
 
 }
                  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
        u8 start_action = tbl->action;
        u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+       u8 tx_chains_num = priv->hw_params.tx_chains_num;
        int ret;
 
        for (;;) {
                lq_sta->action_counter++;
                switch (tbl->action) {
-               case IWL_SISO_SWITCH_ANTENNA:
+               case IWL_SISO_SWITCH_ANTENNA1:
+               case IWL_SISO_SWITCH_ANTENNA2:
                        IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n");
+
+                       if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
+                                                       tx_chains_num <= 1) ||
+                           (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
+                                                       tx_chains_num <= 2))
+                               break;
+
                        if (window->success_ratio >= IWL_RS_GOOD_RATIO)
                                break;
 
                        memcpy(search_tbl, tbl, sz);
                        if (rs_toggle_antenna(valid_tx_ant,
-                                      &search_tbl->current_rate, search_tbl)) {
-                               lq_sta->search_better_tbl = 1;
+                                      &search_tbl->current_rate, search_tbl))
                                goto out;
-                       }
                        break;
-               case IWL_SISO_SWITCH_MIMO2:
+               case IWL_SISO_SWITCH_MIMO2_AB:
+               case IWL_SISO_SWITCH_MIMO2_AC:
+               case IWL_SISO_SWITCH_MIMO2_BC:
                        IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n");
                        memcpy(search_tbl, tbl, sz);
                        search_tbl->is_SGI = 0;
-                       search_tbl->ant_type = ANT_AB; /*FIXME:RS*/
+
+                       if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB)
+                               search_tbl->ant_type = ANT_AB;
+                       else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
+                               search_tbl->ant_type = ANT_AC;
+                       else
+                               search_tbl->ant_type = ANT_BC;
+
+                       if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+                               break;
+
                        ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
                                                 search_tbl, index);
-                       if (!ret) {
-                               lq_sta->search_better_tbl = 1;
+                       if (!ret)
                                goto out;
-                       }
                        break;
                case IWL_SISO_SWITCH_GI:
                        if (!tbl->is_fat &&
                        }
                        search_tbl->current_rate = rate_n_flags_from_tbl(
                                                search_tbl, index, is_green);
-                       lq_sta->search_better_tbl = 1;
                        goto out;
                }
                tbl->action++;
                if (tbl->action > IWL_SISO_SWITCH_GI)
-                       tbl->action = IWL_SISO_SWITCH_ANTENNA;
+                       tbl->action = IWL_SISO_SWITCH_ANTENNA1;
 
                if (tbl->action == start_action)
                        break;
        }
+       search_tbl->lq_type = LQ_NONE;
        return 0;
 
  out:
+       lq_sta->search_better_tbl = 1;
        tbl->action++;
        if (tbl->action > IWL_SISO_SWITCH_GI)
-               tbl->action = IWL_SISO_SWITCH_ANTENNA;
+               tbl->action = IWL_SISO_SWITCH_ANTENNA1;
        return 0;
 }
 
        struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
        struct iwl_scale_tbl_info *search_tbl =
                                &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+       struct iwl_rate_scale_data *window = &(tbl->win[index]);
        u32 sz = (sizeof(struct iwl_scale_tbl_info) -
                  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
        u8 start_action = tbl->action;
-       /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/
+       u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+       u8 tx_chains_num = priv->hw_params.tx_chains_num;
        int ret;
 
        for (;;) {
                lq_sta->action_counter++;
                switch (tbl->action) {
-               case IWL_MIMO_SWITCH_ANTENNA_A:
-               case IWL_MIMO_SWITCH_ANTENNA_B:
+               case IWL_MIMO2_SWITCH_ANTENNA1:
+               case IWL_MIMO2_SWITCH_ANTENNA2:
+                       IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n");
+
+                       if (tx_chains_num <= 2)
+                               break;
+
+                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+                               break;
+
+                       memcpy(search_tbl, tbl, sz);
+                       if (rs_toggle_antenna(valid_tx_ant,
+                                      &search_tbl->current_rate, search_tbl))
+                               goto out;
+                       break;
+               case IWL_MIMO2_SWITCH_SISO_A:
+               case IWL_MIMO2_SWITCH_SISO_B:
+               case IWL_MIMO2_SWITCH_SISO_C:
                        IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n");
 
                        /* Set up new search table for SISO */
                        memcpy(search_tbl, tbl, sz);
 
-                       /*FIXME:RS:need to check ant validity + C*/
-                       if (tbl->action == IWL_MIMO_SWITCH_ANTENNA_A)
+                       if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
                                search_tbl->ant_type = ANT_A;
-                       else
+                       else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
                                search_tbl->ant_type = ANT_B;
+                       else
+                               search_tbl->ant_type = ANT_C;
+
+                       if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+                               break;
 
                        ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
                                                 search_tbl, index);
-                       if (!ret) {
-                               lq_sta->search_better_tbl = 1;
+                       if (!ret)
                                goto out;
-                       }
+
                        break;
 
-               case IWL_MIMO_SWITCH_GI:
+               case IWL_MIMO2_SWITCH_GI:
                        if (!tbl->is_fat &&
                                !(priv->current_ht_config.sgf &
                                                HT_SHORT_GI_20MHZ))
                        }
                        search_tbl->current_rate = rate_n_flags_from_tbl(
                                                search_tbl, index, is_green);
-                       lq_sta->search_better_tbl = 1;
                        goto out;
 
                }
                tbl->action++;
-               if (tbl->action > IWL_MIMO_SWITCH_GI)
-                       tbl->action = IWL_MIMO_SWITCH_ANTENNA_A;
+               if (tbl->action > IWL_MIMO2_SWITCH_GI)
+                       tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
 
                if (tbl->action == start_action)
                        break;
        }
-
+       search_tbl->lq_type = LQ_NONE;
        return 0;
  out:
+       lq_sta->search_better_tbl = 1;
        tbl->action++;
-       if (tbl->action > IWL_MIMO_SWITCH_GI)
-               tbl->action = IWL_MIMO_SWITCH_ANTENNA_A;
+       if (tbl->action > IWL_MIMO2_SWITCH_GI)
+               tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
        return 0;
 
 }
                rs_stay_in_table(lq_sta);
 
                goto out;
+       }
 
        /* Else we have enough samples; calculate estimate of
         * actual average throughput */
-       } else {
-               /*FIXME:RS remove this else if we don't get this error*/
-               if (window->average_tpt != ((window->success_ratio *
-                               tbl->expected_tpt[index] + 64) / 128)) {
-                       IWL_ERROR("expected_tpt should have been calculated"
-                                                               " by now\n");
-                       window->average_tpt = ((window->success_ratio *
-                                       tbl->expected_tpt[index] + 64) / 128);
-               }
-       }
+
+       BUG_ON(window->average_tpt != ((window->success_ratio *
+                       tbl->expected_tpt[index] + 64) / 128));
 
        /* If we are searching for better modulation mode, check success. */
        if (lq_sta->search_better_tbl) {
                 * continuing to use the setup that we've been trying. */
                if (window->average_tpt > lq_sta->last_tpt) {
 
-                       IWL_DEBUG_RATE("LQ: SWITCHING TO CURRENT TABLE "
+                       IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE "
                                        "suc=%d cur-tpt=%d old-tpt=%d\n",
                                        window->success_ratio,
                                        window->average_tpt,
                for (i = 0; i < IWL_RATE_COUNT; i++)
                        rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
 
-       IWL_DEBUG_RATE("LQ: *** rate scale global init ***\n");
+       IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n");
        /* TODO: what is a good starting rate for STA? About middle? Maybe not
         * the lowest or the highest rate.. Could consider using RSSI from
         * previous packets? Need to have IEEE 802.1X auth succeed immediately