Commit 07bc28ed authored by Guy Cohen's avatar Guy Cohen Committed by John W. Linville

iwlwifi: more RS improvements

Main changes:
1. no need to re-calculate expected_tpt when only toggling antenna
2. changing the code to be more strict on input and status of variables
3. enhanced debug prints
4. move to search table only if improving tpt
       (don't move if SR is improved but tpt is not)
Signed-off-by: default avatarGuy Cohen <guy.cohen@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f935a6da
...@@ -178,8 +178,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -178,8 +178,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
struct sta_info *sta); struct sta_info *sta);
static void rs_fill_link_cmd(const struct iwl_priv *priv, static void rs_fill_link_cmd(const struct iwl_priv *priv,
struct iwl4965_lq_sta *lq_sta, struct iwl4965_lq_sta *lq_sta,
u32 rate_n_flags, u32 rate_n_flags);
struct iwl_link_quality_cmd *tbl);
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
...@@ -1320,7 +1319,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ...@@ -1320,7 +1319,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
lq_sta->action_counter++; lq_sta->action_counter++;
/* Don't change antenna if success has been great */ /* Don't change antenna if success has been great */
/*FIXME:RS:not sure this is really needed*/
if (window->success_ratio >= IWL_RS_GOOD_RATIO) if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break; break;
...@@ -1329,7 +1327,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ...@@ -1329,7 +1327,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
if (rs_toggle_antenna(valid_tx_ant, if (rs_toggle_antenna(valid_tx_ant,
&search_tbl->current_rate, search_tbl)) { &search_tbl->current_rate, search_tbl)) {
rs_set_expected_tpt_table(lq_sta, search_tbl);
lq_sta->search_better_tbl = 1; lq_sta->search_better_tbl = 1;
goto out; goto out;
} }
...@@ -1410,7 +1407,6 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, ...@@ -1410,7 +1407,6 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
switch (tbl->action) { switch (tbl->action) {
case IWL_SISO_SWITCH_ANTENNA: case IWL_SISO_SWITCH_ANTENNA:
IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n"); IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n");
/*FIXME:RS: is this really needed for SISO?*/
if (window->success_ratio >= IWL_RS_GOOD_RATIO) if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break; break;
...@@ -1738,27 +1734,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1738,27 +1734,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (!rate_scale_index_msk) if (!rate_scale_index_msk)
rate_scale_index_msk = rate_mask; rate_scale_index_msk = rate_mask;
/* If current rate is no longer supported on current association, if (!((1 << index) & rate_scale_index_msk)) {
* or user changed preferences for rates, find a new supported rate. */ IWL_ERROR("Current Rate is not valid\n");
if (index < 0 || !((1 << index) & rate_scale_index_msk)) { return;
index = IWL_INVALID_VALUE;
update_lq = 1;
/* get the highest available rate */
for (i = 0; i <= IWL_RATE_COUNT; i++) {
if ((1 << i) & rate_scale_index_msk)
index = i;
}
if (index == IWL_INVALID_VALUE) {
IWL_WARNING("Can not find a suitable rate\n");
return;
}
} }
/* Get expected throughput table and history window for current rate */ /* Get expected throughput table and history window for current rate */
if (!tbl->expected_tpt) if (!tbl->expected_tpt) {
rs_set_expected_tpt_table(lq_sta, tbl); IWL_ERROR("tbl->expected_tpt is NULL\n");
return;
}
window = &(tbl->win[index]); window = &(tbl->win[index]);
...@@ -1770,10 +1755,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1770,10 +1755,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
* in current association (use new rate found above). * in current association (use new rate found above).
*/ */
fail_count = window->counter - window->success_counter; fail_count = window->counter - window->success_counter;
if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && if ((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) {
|| (tbl->expected_tpt == NULL)) { IWL_DEBUG_RATE("LQ: still below TH. succ=%d total=%d "
IWL_DEBUG_RATE("LQ: still below TH succ %d total %d "
"for index %d\n", "for index %d\n",
window->success_counter, window->counter, index); window->success_counter, window->counter, index);
...@@ -1784,44 +1768,51 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1784,44 +1768,51 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
* or search for a new one? */ * or search for a new one? */
rs_stay_in_table(lq_sta); rs_stay_in_table(lq_sta);
/* Set up new rate table in uCode, if needed */
if (update_lq) {
rate = rate_n_flags_from_tbl(tbl, index, is_green);
rs_fill_link_cmd(priv, lq_sta, rate, &lq_sta->lq);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
}
goto out; goto out;
/* Else we have enough samples; calculate estimate of /* Else we have enough samples; calculate estimate of
* actual average throughput */ * actual average throughput */
} else } else {
window->average_tpt = ((window->success_ratio * /*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); tbl->expected_tpt[index] + 64) / 128);
}
}
/* If we are searching for better modulation mode, check success. */ /* If we are searching for better modulation mode, check success. */
if (lq_sta->search_better_tbl) { if (lq_sta->search_better_tbl) {
int success_limit = IWL_RATE_SCALE_SWITCH;
/* If good success, continue using the "search" mode; /* If good success, continue using the "search" mode;
* no need to send new link quality command, since we're * no need to send new link quality command, since we're
* continuing to use the setup that we've been trying. */ * continuing to use the setup that we've been trying. */
if ((window->success_ratio > success_limit) || if (window->average_tpt > lq_sta->last_tpt) {
(window->average_tpt > lq_sta->last_tpt)) {
if (!is_legacy(tbl->lq_type)) { IWL_DEBUG_RATE("LQ: SWITCHING TO CURRENT TABLE "
IWL_DEBUG_RATE("LQ: we are switching to HT" "suc=%d cur-tpt=%d old-tpt=%d\n",
" rate suc %d current tpt %d" window->success_ratio,
" old tpt %d\n", window->average_tpt,
window->success_ratio, lq_sta->last_tpt);
window->average_tpt,
lq_sta->last_tpt); if (!is_legacy(tbl->lq_type))
lq_sta->enable_counter = 1; lq_sta->enable_counter = 1;
}
/* Swap tables; "search" becomes "active" */ /* Swap tables; "search" becomes "active" */
lq_sta->active_tbl = active_tbl; lq_sta->active_tbl = active_tbl;
current_tpt = window->average_tpt; current_tpt = window->average_tpt;
/* Else poor success; go back to mode in "active" table */ /* Else poor success; go back to mode in "active" table */
} else { } else {
IWL_DEBUG_RATE("LQ: GOING BACK TO THE OLD TABLE "
"suc=%d cur-tpt=%d old-tpt=%d\n",
window->success_ratio,
window->average_tpt,
lq_sta->last_tpt);
/* Nullify "search" table */ /* Nullify "search" table */
tbl->lq_type = LQ_NONE; tbl->lq_type = LQ_NONE;
...@@ -1836,7 +1827,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1836,7 +1827,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
/* Need to set up a new rate table in uCode */ /* Need to set up a new rate table in uCode */
update_lq = 1; update_lq = 1;
IWL_DEBUG_RATE("XXY GO BACK TO OLD TABLE\n");
} }
/* Either way, we've made a decision; modulation mode /* Either way, we've made a decision; modulation mode
...@@ -1952,7 +1942,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1952,7 +1942,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
/* Replace uCode's rate table for the destination station. */ /* Replace uCode's rate table for the destination station. */
if (update_lq) { if (update_lq) {
rate = rate_n_flags_from_tbl(tbl, index, is_green); rate = rate_n_flags_from_tbl(tbl, index, is_green);
rs_fill_link_cmd(priv, lq_sta, rate, &lq_sta->lq); rs_fill_link_cmd(priv, lq_sta, rate);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
} }
...@@ -1991,8 +1981,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -1991,8 +1981,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n", IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n",
tbl->current_rate, index); tbl->current_rate, index);
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate, rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
&lq_sta->lq);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
} }
...@@ -2109,7 +2098,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2109,7 +2098,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green);
tbl->current_rate = rate; tbl->current_rate = rate;
rs_set_expected_tpt_table(lq_sta, tbl); rs_set_expected_tpt_table(lq_sta, tbl);
rs_fill_link_cmd(NULL, lq_sta, rate, &lq_sta->lq); rs_fill_link_cmd(NULL, lq_sta, rate);
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
out: out:
return; return;
...@@ -2220,7 +2209,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, ...@@ -2220,7 +2209,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
for (i = 0; i < IWL_RATE_COUNT; i++) for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
IWL_DEBUG_RATE("rate scale global init\n"); IWL_DEBUG_RATE("LQ: *** rate scale global init ***\n");
/* TODO: what is a good starting rate for STA? About middle? Maybe not /* TODO: what is a good starting rate for STA? About middle? Maybe not
* the lowest or the highest rate.. Could consider using RSSI from * the lowest or the highest rate.. Could consider using RSSI from
* previous packets? Need to have IEEE 802.1X auth succeed immediately * previous packets? Need to have IEEE 802.1X auth succeed immediately
...@@ -2292,11 +2281,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, ...@@ -2292,11 +2281,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate &= ~((u16)0x2);
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
IWL_DEBUG_RATE("SISO RATE %X MIMO2 RATE %X MIMO3 RATE %X\n", IWL_DEBUG_RATE("SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n",
lq_sta->active_siso_rate, lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate, lq_sta->active_mimo2_rate,
lq_sta->active_mimo3_rate); lq_sta->active_mimo3_rate);
/* These values will be overriden later */
lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
/* as default allow aggregation for all tids */ /* as default allow aggregation for all tids */
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
#endif /*CONFIG_IWL4965_HT*/ #endif /*CONFIG_IWL4965_HT*/
...@@ -2312,8 +2305,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, ...@@ -2312,8 +2305,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
static void rs_fill_link_cmd(const struct iwl_priv *priv, static void rs_fill_link_cmd(const struct iwl_priv *priv,
struct iwl4965_lq_sta *lq_sta, struct iwl4965_lq_sta *lq_sta,
u32 new_rate, u32 new_rate)
struct iwl_link_quality_cmd *lq_cmd)
{ {
struct iwl4965_scale_tbl_info tbl_type; struct iwl4965_scale_tbl_info tbl_type;
int index = 0; int index = 0;
...@@ -2322,6 +2314,7 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2322,6 +2314,7 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
u8 ant_toggle_cnt = 0; u8 ant_toggle_cnt = 0;
u8 use_ht_possible = 1; u8 use_ht_possible = 1;
u8 valid_tx_ant = 0; u8 valid_tx_ant = 0;
struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
/* Override starting rate (index 0) if needed for debug purposes */ /* Override starting rate (index 0) if needed for debug purposes */
rs_dbgfs_set_mcs(lq_sta, &new_rate, index); rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
...@@ -2345,13 +2338,13 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2345,13 +2338,13 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
/* Fill 1st table entry (index 0) */ /* Fill 1st table entry (index 0) */
lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
/*FIXME:RS*/ if (num_of_ant(tbl_type.ant_type) == 1) {
if (is_mimo(tbl_type.lq_type) || (tbl_type.ant_type == ANT_A)) lq_cmd->general_params.single_stream_ant_msk =
lq_cmd->general_params.single_stream_ant_msk tbl_type.ant_type;
= LINK_QUAL_ANT_A_MSK; } else if (num_of_ant(tbl_type.ant_type) == 2) {
else lq_cmd->general_params.dual_stream_ant_msk =
lq_cmd->general_params.single_stream_ant_msk tbl_type.ant_type;
= LINK_QUAL_ANT_B_MSK; } /* otherwise we don't modify the existing value */
index++; index++;
repeat_rate--; repeat_rate--;
...@@ -2425,7 +2418,6 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2425,7 +2418,6 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
repeat_rate--; repeat_rate--;
} }
lq_cmd->general_params.dual_stream_ant_msk = 3;
lq_cmd->agg_params.agg_dis_start_th = 3; lq_cmd->agg_params.agg_dis_start_th = 3;
lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
} }
...@@ -2512,8 +2504,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, ...@@ -2512,8 +2504,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
if (lq_sta->dbg_fixed_rate) { if (lq_sta->dbg_fixed_rate) {
rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate, rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
&lq_sta->lq);
iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
} }
......
...@@ -2047,7 +2047,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, ...@@ -2047,7 +2047,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
goto drop; goto drop;
} }
IWL_DEBUG_RATE("station Id %d\n", sta_id); IWL_DEBUG_TX("station Id %d\n", sta_id);
qc = ieee80211_get_qos_ctrl(hdr); qc = ieee80211_get_qos_ctrl(hdr);
if (qc) { if (qc) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment