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

iwlwifi: rate scale restructure toggle_antenna functions

This patch add support for toggeling of A/B/C and AB/BC/AC
antennas
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 eecd6e57
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#define RS_NAME "iwl-4965-rs" #define RS_NAME "iwl-4965-rs"
#define NUM_TRY_BEFORE_ANTENNA_TOGGLE 1 #define NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_NUMBER_TRY 1 #define IWL_NUMBER_TRY 1
#define IWL_HT_NUMBER_TRY 3 #define IWL_HT_NUMBER_TRY 3
...@@ -64,6 +64,17 @@ static u8 rs_ht_to_legacy[] = { ...@@ -64,6 +64,17 @@ static u8 rs_ht_to_legacy[] = {
IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
}; };
static const u8 ant_toggle_lookup[] = {
/*ANT_NONE -> */ ANT_NONE,
/*ANT_A -> */ ANT_B,
/*ANT_B -> */ ANT_C,
/*ANT_AB -> */ ANT_BC,
/*ANT_C -> */ ANT_A,
/*ANT_AC -> */ ANT_AB,
/*ANT_BC -> */ ANT_AC,
/*ANT_ABC -> */ ANT_ABC,
};
/** /**
* struct iwl4965_rate_scale_data -- tx success history for one rate * struct iwl4965_rate_scale_data -- tx success history for one rate
*/ */
...@@ -131,8 +142,6 @@ struct iwl4965_lq_sta { ...@@ -131,8 +142,6 @@ struct iwl4965_lq_sta {
u32 flush_timer; /* time staying in mode before new search */ u32 flush_timer; /* time staying in mode before new search */
u8 action_counter; /* # mode-switch actions tried */ u8 action_counter; /* # mode-switch actions tried */
u8 antenna;
u8 valid_antenna;
u8 is_green; u8 is_green;
u8 is_dup; u8 is_dup;
enum ieee80211_band band; enum ieee80211_band band;
...@@ -243,6 +252,11 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) ...@@ -243,6 +252,11 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
window->stamp = 0; window->stamp = 0;
} }
static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
{
return ((ant_type & valid_antenna) == ant_type);
}
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
/* /*
* removes the old data from the statistics. All data that is older than * removes the old data from the statistics. All data that is older than
...@@ -576,12 +590,33 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, ...@@ -576,12 +590,33 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
} }
return 0; return 0;
} }
/* FIXME:RS: need to toggle also ANT_C, and also AB,AC,BC */
static inline void rs_toggle_antenna(u32 *rate_n_flags, /* switch to another antenna/antennas and return 1 */
struct iwl4965_scale_tbl_info *tbl) /* if no other valid antenna found, return 0 */
static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
struct iwl4965_scale_tbl_info *tbl)
{ {
tbl->ant_type ^= ANT_AB; u8 new_ant_type;
*rate_n_flags ^= (RATE_MCS_ANT_A_MSK|RATE_MCS_ANT_B_MSK);
if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
return 0;
if (!rs_is_valid_ant(valid_ant, tbl->ant_type))
return 0;
new_ant_type = ant_toggle_lookup[tbl->ant_type];
while ((new_ant_type != tbl->ant_type) &&
!rs_is_valid_ant(valid_ant, new_ant_type))
new_ant_type = ant_toggle_lookup[new_ant_type];
if (new_ant_type == tbl->ant_type)
return 0;
tbl->ant_type = new_ant_type;
*rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
*rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
return 1;
} }
/* FIXME:RS: in 4965 we don't use greenfield at all */ /* FIXME:RS: in 4965 we don't use greenfield at all */
...@@ -796,8 +831,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, ...@@ -796,8 +831,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
table = &lq_sta->lq; table = &lq_sta->lq;
active_index = lq_sta->active_tbl; active_index = lq_sta->active_tbl;
lq_sta->antenna = lq_sta->valid_antenna;
curr_tbl = &(lq_sta->lq_info[active_index]); curr_tbl = &(lq_sta->lq_info[active_index]);
search_tbl = &(lq_sta->lq_info[(1 - active_index)]); search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
window = (struct iwl4965_rate_scale_data *) window = (struct iwl4965_rate_scale_data *)
...@@ -946,22 +979,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, ...@@ -946,22 +979,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
return; return;
} }
static inline u8 rs_is_ant_connected(u8 valid_antenna, u8 ant_type)
{
return ((ant_type & valid_antenna) == ant_type);
}
/*FIXME:RS: this function should be replaced*/
static u8 rs_is_other_ant_connected(u8 valid_antenna, u8 ant_type)
{
if (ant_type == ANT_B)
return rs_is_ant_connected(valid_antenna, ANT_A);
else
return rs_is_ant_connected(valid_antenna, ANT_B);
return 0;
}
/* /*
* Begin a period of staying with a selected modulation mode. * Begin a period of staying with a selected modulation mode.
* Set "stay_in_tbl" flag to prevent any mode switches. * Set "stay_in_tbl" flag to prevent any mode switches.
...@@ -1128,12 +1145,6 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, ...@@ -1128,12 +1145,6 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
} }
#endif /* CONFIG_IWL4965_HT */ #endif /* CONFIG_IWL4965_HT */
/*FIXME:RS:this function should be replaced*/
static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
{
return (rs_is_ant_connected(valid_antenna, ANT_AB));
}
/* /*
* Set up search table for MIMO * Set up search table for MIMO
*/ */
...@@ -1156,7 +1167,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, ...@@ -1156,7 +1167,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
return -1; return -1;
/* Need both Tx chains/antennas to support MIMO */ /* Need both Tx chains/antennas to support MIMO */
if (!rs_is_both_ant_supp(priv->hw_params.valid_tx_ant)) if (priv->hw_params.tx_chains_num < 2)
return -1; return -1;
IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n"); IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n");
...@@ -1302,7 +1313,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ...@@ -1302,7 +1313,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
case IWL_LEGACY_SWITCH_ANTENNA: case IWL_LEGACY_SWITCH_ANTENNA:
IWL_DEBUG_RATE("LQ Legacy toggle Antenna\n"); IWL_DEBUG_RATE("LQ Legacy toggle Antenna\n");
search_tbl->lq_type = LQ_NONE;
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 */
...@@ -1310,19 +1320,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv, ...@@ -1310,19 +1320,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
if (window->success_ratio >= IWL_RS_GOOD_RATIO) if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break; break;
/* Don't change antenna if other one is not connected */
if (!rs_is_other_ant_connected(valid_tx_ant,
tbl->ant_type))
break;
/* Set up search table to try other antenna */ /* Set up search table to try other antenna */
memcpy(search_tbl, tbl, sz); memcpy(search_tbl, tbl, sz);
rs_toggle_antenna(&search_tbl->current_rate, if (rs_toggle_antenna(valid_tx_ant,
search_tbl); &search_tbl->current_rate, search_tbl)) {
rs_set_expected_tpt_table(lq_sta, 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;
}
case IWL_LEGACY_SWITCH_SISO: case IWL_LEGACY_SWITCH_SISO:
IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n"); IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n");
...@@ -1403,16 +1409,13 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, ...@@ -1403,16 +1409,13 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
/*FIXME:RS: is this really needed for SISO?*/ /*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;
if (!rs_is_other_ant_connected(valid_tx_ant,
tbl->ant_type))
break;
memcpy(search_tbl, tbl, sz); memcpy(search_tbl, tbl, sz);
rs_toggle_antenna(&search_tbl->current_rate, if (rs_toggle_antenna(valid_tx_ant,
search_tbl); &search_tbl->current_rate, search_tbl)) {
lq_sta->search_better_tbl = 1; lq_sta->search_better_tbl = 1;
goto out;
goto out; }
case IWL_SISO_SWITCH_MIMO2: case IWL_SISO_SWITCH_MIMO2:
IWL_DEBUG_RATE("LQ: SISO switch to MIMO\n"); IWL_DEBUG_RATE("LQ: SISO switch to MIMO\n");
...@@ -1473,7 +1476,6 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, ...@@ -1473,7 +1476,6 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
struct sta_info *sta, struct sta_info *sta,
int index) int index)
{ {
int ret;
s8 is_green = lq_sta->is_green; s8 is_green = lq_sta->is_green;
struct iwl4965_scale_tbl_info *tbl = struct iwl4965_scale_tbl_info *tbl =
&(lq_sta->lq_info[lq_sta->active_tbl]); &(lq_sta->lq_info[lq_sta->active_tbl]);
...@@ -1482,6 +1484,8 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, ...@@ -1482,6 +1484,8 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
(sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action; u8 start_action = tbl->action;
/*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/
int ret;
for (;;) { for (;;) {
lq_sta->action_counter++; lq_sta->action_counter++;
...@@ -2057,13 +2061,14 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2057,13 +2061,14 @@ static void rs_initialize_lq(struct iwl_priv *priv,
struct ieee80211_conf *conf, struct ieee80211_conf *conf,
struct sta_info *sta) struct sta_info *sta)
{ {
int i;
struct iwl4965_lq_sta *lq_sta; struct iwl4965_lq_sta *lq_sta;
struct iwl4965_scale_tbl_info *tbl; struct iwl4965_scale_tbl_info *tbl;
u8 active_tbl = 0;
int rate_idx; int rate_idx;
u8 use_green = rs_use_green(priv, conf); int i;
u32 rate; u32 rate;
u8 use_green = rs_use_green(priv, conf);
u8 active_tbl = 0;
u8 valid_tx_ant;
if (!sta || !sta->rate_ctrl_priv) if (!sta || !sta->rate_ctrl_priv)
goto out; goto out;
...@@ -2075,6 +2080,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2075,6 +2080,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
goto out; goto out;
valid_tx_ant = priv->hw_params.valid_tx_ant;
if (!lq_sta->search_better_tbl) if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl; active_tbl = lq_sta->active_tbl;
else else
...@@ -2095,8 +2102,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2095,8 +2102,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
tbl->ant_type = ANT_B; tbl->ant_type = ANT_B;
rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx); rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
if (!rs_is_ant_connected(priv->hw_params.valid_tx_ant, tbl->ant_type)) if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
rs_toggle_antenna(&rate, tbl); rs_toggle_antenna(valid_tx_ant, &rate, tbl);
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;
...@@ -2307,26 +2314,29 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2307,26 +2314,29 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
u32 new_rate, u32 new_rate,
struct iwl_link_quality_cmd *lq_cmd) struct iwl_link_quality_cmd *lq_cmd)
{ {
struct iwl4965_scale_tbl_info tbl_type;
int index = 0; int index = 0;
int rate_idx; int rate_idx;
int repeat_rate = 0; int repeat_rate = 0;
u8 ant_toggle_count = 0; u8 ant_toggle_cnt = 0;
u8 use_ht_possible = 1; u8 use_ht_possible = 1;
struct iwl4965_scale_tbl_info tbl_type = { 0 }; u8 valid_tx_ant = 0;
/* 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);
/* Interpret new_rate (rate_n_flags) */ /* Interpret new_rate (rate_n_flags) */
memset(&tbl_type, 0, sizeof(tbl_type));
rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
&tbl_type, &rate_idx); &tbl_type, &rate_idx);
/* How many times should we repeat the initial rate? */ /* How many times should we repeat the initial rate? */
if (is_legacy(tbl_type.lq_type)) { if (is_legacy(tbl_type.lq_type)) {
ant_toggle_count = 1; ant_toggle_cnt = 1;
repeat_rate = IWL_NUMBER_TRY; repeat_rate = IWL_NUMBER_TRY;
} else } else {
repeat_rate = IWL_HT_NUMBER_TRY; repeat_rate = IWL_HT_NUMBER_TRY;
}
lq_cmd->general_params.mimo_delimiter = lq_cmd->general_params.mimo_delimiter =
is_mimo(tbl_type.lq_type) ? 1 : 0; is_mimo(tbl_type.lq_type) ? 1 : 0;
...@@ -2345,6 +2355,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2345,6 +2355,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
index++; index++;
repeat_rate--; repeat_rate--;
if (priv)
valid_tx_ant = priv->hw_params.valid_tx_ant;
/* Fill rest of rate table */ /* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) { while (index < LINK_QUAL_MAX_RETRY_NUM) {
/* Repeat initial/next rate. /* Repeat initial/next rate.
...@@ -2352,16 +2365,13 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2352,16 +2365,13 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
* For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
if (is_legacy(tbl_type.lq_type)) { if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_count < if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
NUM_TRY_BEFORE_ANTENNA_TOGGLE) ant_toggle_cnt++;
ant_toggle_count++; else if (priv &&
else if (priv && rs_is_other_ant_connected( rs_toggle_antenna(valid_tx_ant,
priv->hw_params.valid_tx_ant, &new_rate, &tbl_type))
tbl_type.ant_type)) { ant_toggle_cnt = 1;
rs_toggle_antenna(&new_rate, &tbl_type); }
ant_toggle_count = 1;
}
}
/* Override next rate if needed for debug purposes */ /* Override next rate if needed for debug purposes */
rs_dbgfs_set_mcs(lq_sta, &new_rate, index); rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
...@@ -2388,17 +2398,17 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, ...@@ -2388,17 +2398,17 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
/* How many times should we repeat the next rate? */ /* How many times should we repeat the next rate? */
if (is_legacy(tbl_type.lq_type)) { if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE) if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
ant_toggle_count++; ant_toggle_cnt++;
else if (priv && rs_is_other_ant_connected( else if (priv &&
priv->hw_params.valid_tx_ant, rs_toggle_antenna(valid_tx_ant,
tbl_type.ant_type)) { &new_rate, &tbl_type))
rs_toggle_antenna(&new_rate, &tbl_type); ant_toggle_cnt = 1;
ant_toggle_count = 1;
}
repeat_rate = IWL_NUMBER_TRY; repeat_rate = IWL_NUMBER_TRY;
} else } else {
repeat_rate = IWL_HT_NUMBER_TRY; repeat_rate = IWL_HT_NUMBER_TRY;
}
/* Don't allow HT rates after next pass. /* Don't allow HT rates after next pass.
* rs_get_lower_rate() will change type to LQ_A or LQ_G. */ * rs_get_lower_rate() will change type to LQ_A or LQ_G. */
......
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