container_of(work, struct iwl_priv, bt_traffic_change_work);
        int smps_request = -1;
 
+       IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+                      priv->bt_traffic_load);
+
        switch (priv->bt_traffic_load) {
        case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
                smps_request = IEEE80211_SMPS_AUTOMATIC;
 
        mutex_lock(&priv->mutex);
 
+       if (priv->cfg->ops->lib->update_chain_flags)
+               priv->cfg->ops->lib->update_chain_flags(priv);
+
        if (smps_request != -1 &&
            priv->vif && priv->vif->type == NL80211_IFTYPE_STATION)
                ieee80211_request_smps(priv->vif, smps_request);
        struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
        struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 };
        struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
+       u8 last_traffic_load;
 
        IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
        IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
        IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n", coex->bt_ci_compliance);
        iwlagn_print_uartmsg(priv, uart_msg);
 
+       last_traffic_load = priv->notif_bt_traffic_load;
        priv->notif_bt_traffic_load = coex->bt_traffic_load;
-
        if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-               if (coex->bt_traffic_load != priv->bt_traffic_load) {
-                       priv->bt_traffic_load = coex->bt_traffic_load;
-
+               if (priv->bt_status != coex->bt_status ||
+                   last_traffic_load != coex->bt_traffic_load) {
+                       if (coex->bt_status) {
+                               /* BT on */
+                               if (!priv->bt_ch_announce)
+                                       priv->bt_traffic_load =
+                                               IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+                               else
+                                       priv->bt_traffic_load =
+                                               coex->bt_traffic_load;
+                       } else {
+                               /* BT off */
+                               priv->bt_traffic_load =
+                                       IWL_BT_COEX_TRAFFIC_LOAD_NONE;
+                       }
+                       priv->bt_status = coex->bt_status;
                        queue_work(priv->workqueue,
                                   &priv->bt_traffic_change_work);
                }
-
                if (priv->bt_sco_active !=
                    (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) {
                        priv->bt_sco_active = uart_msg->frame3 &
 
                                   struct iwl_lq_sta *lq_sta);
 static void rs_fill_link_cmd(struct iwl_priv *priv,
                             struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
-static void rs_stay_in_table(struct iwl_lq_sta *lq_sta);
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
 
 
 #ifdef CONFIG_MAC80211_DEBUGFS
                 * no matching table found, let's by-pass the data collection
                 * and continue to perform rate scale to find the rate table
                 */
-               rs_stay_in_table(lq_sta);
+               rs_stay_in_table(lq_sta, true);
                goto done;
        }
 
                break;
        case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
                /* avoid antenna B unless MIMO */
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
                if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
                        tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
                break;
        case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
        case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
                /* avoid antenna B and MIMO */
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
                if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
                    tbl->action != IWL_LEGACY_SWITCH_SISO)
-                       tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+                       tbl->action = IWL_LEGACY_SWITCH_SISO;
                break;
        default:
                IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
                        tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
                else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
                        tbl->action = IWL_LEGACY_SWITCH_SISO;
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
        }
 
        start_action = tbl->action;
                                break;
 
                        /* Don't change antenna if success has been great */
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+                       if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+                           !priv->bt_full_concurrent &&
+                           priv->bt_traffic_load ==
+                                       IWL_BT_COEX_TRAFFIC_LOAD_NONE)
                                break;
 
                        /* Set up search table to try other antenna */
                break;
        case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
                /* avoid antenna B unless MIMO */
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
                if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
                        tbl->action = IWL_SISO_SWITCH_ANTENNA1;
                break;
        case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
        case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
                /* avoid antenna B and MIMO */
-               if (tbl->action >= IWL_SISO_SWITCH_ANTENNA2 &&
-                   tbl->action != IWL_SISO_SWITCH_GI)
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+               if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
                        tbl->action = IWL_SISO_SWITCH_ANTENNA1;
                break;
        default:
        }
 
        /* configure as 1x1 if bt full concurrency */
-       if (priv->bt_full_concurrent &&
-           tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
-               tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+       if (priv->bt_full_concurrent) {
+               valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+               if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
+                       tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+       }
 
        start_action = tbl->action;
        for (;;) {
                case IWL_SISO_SWITCH_ANTENNA1:
                case IWL_SISO_SWITCH_ANTENNA2:
                        IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n");
-
                        if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
-                                                       tx_chains_num <= 1) ||
+                                               tx_chains_num <= 1) ||
                            (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
-                                                       tx_chains_num <= 2))
+                                               tx_chains_num <= 2))
                                break;
 
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+                       if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+                           !priv->bt_full_concurrent &&
+                           priv->bt_traffic_load ==
+                                       IWL_BT_COEX_TRAFFIC_LOAD_NONE)
                                break;
 
                        memcpy(search_tbl, tbl, sz);
        case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
        case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
                /* avoid antenna B and MIMO */
-               if (tbl->action == IWL_MIMO2_SWITCH_MIMO3_ABC)
-                       tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+               if (tbl->action != IWL_MIMO2_SWITCH_SISO_A)
+                       tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+               break;
        case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
                /* avoid antenna B unless MIMO */
-               if (tbl->action == IWL_MIMO2_SWITCH_ANTENNA2)
-                       tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
-               else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
+               if (tbl->action == IWL_MIMO2_SWITCH_SISO_B ||
+                   tbl->action == IWL_MIMO2_SWITCH_SISO_C)
                        tbl->action = IWL_MIMO2_SWITCH_SISO_A;
                break;
        default:
        case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
        case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
                /* avoid antenna B and MIMO */
-               if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB ||
-                   tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC ||
-                   tbl->action == IWL_MIMO3_SWITCH_MIMO2_BC)
+               if (tbl->action != IWL_MIMO3_SWITCH_SISO_A)
                        tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+               break;
        case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
                /* avoid antenna B unless MIMO */
-               if (tbl->action == IWL_MIMO3_SWITCH_SISO_B)
+               if (tbl->action == IWL_MIMO3_SWITCH_SISO_B ||
+                   tbl->action == IWL_MIMO3_SWITCH_SISO_C)
                        tbl->action = IWL_MIMO3_SWITCH_SISO_A;
-               else if (tbl->action == IWL_MIMO3_SWITCH_ANTENNA2)
-                       tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
                break;
        default:
                IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
  * 2) # times calling this function
  * 3) elapsed time in this mode (not used, for now)
  */
-static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 {
        struct iwl_scale_tbl_info *tbl;
        int i;
                 * allow a new search.  Also (below) reset all bitmaps and
                 * stats in active history.
                 */
-               if ((lq_sta->total_failed > lq_sta->max_failure_limit) ||
+               if (force_search ||
+                   (lq_sta->total_failed > lq_sta->max_failure_limit) ||
                    (lq_sta->total_success > lq_sta->max_success_limit) ||
                    ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
                     && (flush_interval_passed))) {
 
                /* Should we stay with this modulation mode,
                 * or search for a new one? */
-               rs_stay_in_table(lq_sta);
+               rs_stay_in_table(lq_sta, false);
 
                goto out;
        }
                (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
                scale_action = -1;
 
-       if (lq_sta->last_bt_traffic > priv->bt_traffic_load) {
-               lq_sta->last_bt_traffic = priv->bt_traffic_load;
-               /*
-                * don't set scale_action, don't want to scale up if
-                * the rate scale doesn't otherwise think that is a
-                * good idea.
-                */
-       } else if (lq_sta->last_bt_traffic < priv->bt_traffic_load) {
-               lq_sta->last_bt_traffic = priv->bt_traffic_load;
-               scale_action = -1;
+       if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+            (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+               if (lq_sta->last_bt_traffic > priv->bt_traffic_load) {
+                       /*
+                        * don't set scale_action, don't want to scale up if
+                        * the rate scale doesn't otherwise think that is a
+                        * good idea.
+                        */
+               } else if (lq_sta->last_bt_traffic <= priv->bt_traffic_load) {
+                       scale_action = -1;
+               }
+       }
+       lq_sta->last_bt_traffic = priv->bt_traffic_load;
+
+       if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+            (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+               /* search for a new modulation */
+               rs_stay_in_table(lq_sta, true);
+               goto lq_update;
        }
 
        switch (scale_action) {
        if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
                /* Should we stay with this modulation mode,
                 * or search for a new one? */
-               rs_stay_in_table(lq_sta);
+         rs_stay_in_table(lq_sta, false);
        }
        /*
         * Search for new modulation mode if we're:
        rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
                                  &tbl_type, &rate_idx);
 
+       if (priv && priv->bt_full_concurrent) {
+               /* 1x1 only */
+               tbl_type.ant_type =
+                       first_antenna(priv->hw_params.valid_tx_ant);
+       }
+
        /* How many times should we repeat the initial rate? */
        if (is_legacy(tbl_type.lq_type)) {
                ant_toggle_cnt = 1;
        /* Fill 1st table entry (index 0) */
        lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
 
-       if (num_of_ant(tbl_type.ant_type) == 1 ||
-           (priv && priv->bt_full_concurrent)) {
+       if (num_of_ant(tbl_type.ant_type) == 1) {
                lq_cmd->general_params.single_stream_ant_msk =
                                                tbl_type.ant_type;
        } else if (num_of_ant(tbl_type.ant_type) == 2) {
 
        index++;
        repeat_rate--;
-
        if (priv) {
                if (priv->bt_full_concurrent)
                        valid_tx_ant = ANT_A;
                                         rs_toggle_antenna(valid_tx_ant,
                                                        &new_rate, &tbl_type))
                                        ant_toggle_cnt = 1;
-}
+                       }
 
                        /* Override next rate if needed for debug purposes */
                        rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
                rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
                                                &rate_idx);
 
+               if (priv && priv->bt_full_concurrent) {
+                       /* 1x1 only */
+                       tbl_type.ant_type =
+                               first_antenna(priv->hw_params.valid_tx_ant);
+               }
+
                /* Indicate to uCode which entries might be MIMO.
                 * If initial rate was MIMO, this will finally end up
                 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */