summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c113
1 files changed, 71 insertions, 42 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 687b534d83d0..e78f3f0592d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -82,7 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
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
@@ -900,7 +900,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
* 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;
}
@@ -1334,15 +1334,17 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
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);
@@ -1362,6 +1364,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
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;
@@ -1379,7 +1382,10 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
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 */
@@ -1503,14 +1509,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
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:
@@ -1525,9 +1532,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
}
/* 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 (;;) {
@@ -1536,14 +1545,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
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);
@@ -1670,13 +1681,13 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
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:
@@ -1840,16 +1851,14 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
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);
@@ -1996,7 +2005,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
* 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;
@@ -2027,7 +2036,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
* 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))) {
@@ -2243,7 +2253,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
/* 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;
}
@@ -2392,16 +2402,25 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
(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) {
@@ -2440,7 +2459,7 @@ lq_update:
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:
@@ -2786,6 +2805,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
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;
@@ -2800,8 +2825,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
/* 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) {
@@ -2811,7 +2835,6 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
index++;
repeat_rate--;
-
if (priv) {
if (priv->bt_full_concurrent)
valid_tx_ant = ANT_A;
@@ -2832,7 +2855,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
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);
@@ -2847,6 +2870,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
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. */
OpenPOWER on IntegriCloud