#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_HT_NUMBER_TRY 3
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
*/
u32 flush_timer; /* time staying in mode before new search */
u8 action_counter; /* # mode-switch actions tried */
- u8 antenna;
- u8 valid_antenna;
u8 is_green;
u8 is_dup;
enum ieee80211_band band;
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
/*
* removes the old data from the statistics. All data that is older than
}
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,
- struct iwl4965_scale_tbl_info *tbl)
+
+/* switch to another antenna/antennas and return 1 */
+/* 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;
- *rate_n_flags ^= (RATE_MCS_ANT_A_MSK|RATE_MCS_ANT_B_MSK);
+ u8 new_ant_type;
+
+ 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 */
table = &lq_sta->lq;
active_index = lq_sta->active_tbl;
- lq_sta->antenna = lq_sta->valid_antenna;
-
curr_tbl = &(lq_sta->lq_info[active_index]);
search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
window = (struct iwl4965_rate_scale_data *)
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.
* Set "stay_in_tbl" flag to prevent any mode switches.
}
#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
*/
return -1;
/* 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;
IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n");
case IWL_LEGACY_SWITCH_ANTENNA:
IWL_DEBUG_RATE("LQ Legacy toggle Antenna\n");
- search_tbl->lq_type = LQ_NONE;
lq_sta->action_counter++;
/* Don't change antenna if success has been great */
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
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 */
memcpy(search_tbl, tbl, sz);
- rs_toggle_antenna(&search_tbl->current_rate,
- search_tbl);
- rs_set_expected_tpt_table(lq_sta, search_tbl);
- lq_sta->search_better_tbl = 1;
- goto out;
+ if (rs_toggle_antenna(valid_tx_ant,
+ &search_tbl->current_rate, search_tbl)) {
+ rs_set_expected_tpt_table(lq_sta, search_tbl);
+ lq_sta->search_better_tbl = 1;
+ goto out;
+ }
case IWL_LEGACY_SWITCH_SISO:
IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n");
/*FIXME:RS: is this really needed for SISO?*/
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break;
- if (!rs_is_other_ant_connected(valid_tx_ant,
- tbl->ant_type))
- break;
memcpy(search_tbl, tbl, sz);
- rs_toggle_antenna(&search_tbl->current_rate,
- search_tbl);
- lq_sta->search_better_tbl = 1;
-
- goto out;
+ if (rs_toggle_antenna(valid_tx_ant,
+ &search_tbl->current_rate, search_tbl)) {
+ lq_sta->search_better_tbl = 1;
+ goto out;
+ }
case IWL_SISO_SWITCH_MIMO2:
IWL_DEBUG_RATE("LQ: SISO switch to MIMO\n");
struct sta_info *sta,
int index)
{
- int ret;
s8 is_green = lq_sta->is_green;
struct iwl4965_scale_tbl_info *tbl =
&(lq_sta->lq_info[lq_sta->active_tbl]);
u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
(sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
+ /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/
+ int ret;
for (;;) {
lq_sta->action_counter++;
struct ieee80211_conf *conf,
struct sta_info *sta)
{
- int i;
struct iwl4965_lq_sta *lq_sta;
struct iwl4965_scale_tbl_info *tbl;
- u8 active_tbl = 0;
int rate_idx;
- u8 use_green = rs_use_green(priv, conf);
+ int i;
u32 rate;
+ u8 use_green = rs_use_green(priv, conf);
+ u8 active_tbl = 0;
+ u8 valid_tx_ant;
if (!sta || !sta->rate_ctrl_priv)
goto out;
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
goto out;
+ valid_tx_ant = priv->hw_params.valid_tx_ant;
+
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
else
tbl->ant_type = ANT_B;
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))
- rs_toggle_antenna(&rate, tbl);
+ if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
+ rs_toggle_antenna(valid_tx_ant, &rate, tbl);
rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green);
tbl->current_rate = rate;
u32 new_rate,
struct iwl_link_quality_cmd *lq_cmd)
{
+ struct iwl4965_scale_tbl_info tbl_type;
int index = 0;
int rate_idx;
int repeat_rate = 0;
- u8 ant_toggle_count = 0;
+ u8 ant_toggle_cnt = 0;
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 */
rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
/* Interpret new_rate (rate_n_flags) */
+ memset(&tbl_type, 0, sizeof(tbl_type));
rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
&tbl_type, &rate_idx);
/* How many times should we repeat the initial rate? */
if (is_legacy(tbl_type.lq_type)) {
- ant_toggle_count = 1;
+ ant_toggle_cnt = 1;
repeat_rate = IWL_NUMBER_TRY;
- } else
+ } else {
repeat_rate = IWL_HT_NUMBER_TRY;
+ }
lq_cmd->general_params.mimo_delimiter =
is_mimo(tbl_type.lq_type) ? 1 : 0;
index++;
repeat_rate--;
+ if (priv)
+ valid_tx_ant = priv->hw_params.valid_tx_ant;
+
/* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) {
/* Repeat initial/next rate.
* For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
if (is_legacy(tbl_type.lq_type)) {
- if (ant_toggle_count <
- NUM_TRY_BEFORE_ANTENNA_TOGGLE)
- ant_toggle_count++;
- else if (priv && rs_is_other_ant_connected(
- priv->hw_params.valid_tx_ant,
- tbl_type.ant_type)) {
- rs_toggle_antenna(&new_rate, &tbl_type);
- ant_toggle_count = 1;
- }
- }
+ if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+ ant_toggle_cnt++;
+ else if (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);
/* How many times should we repeat the next rate? */
if (is_legacy(tbl_type.lq_type)) {
- if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE)
- ant_toggle_count++;
- else if (priv && rs_is_other_ant_connected(
- priv->hw_params.valid_tx_ant,
- tbl_type.ant_type)) {
- rs_toggle_antenna(&new_rate, &tbl_type);
- ant_toggle_count = 1;
- }
+ if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+ ant_toggle_cnt++;
+ else if (priv &&
+ rs_toggle_antenna(valid_tx_ant,
+ &new_rate, &tbl_type))
+ ant_toggle_cnt = 1;
+
repeat_rate = IWL_NUMBER_TRY;
- } else
+ } else {
repeat_rate = IWL_HT_NUMBER_TRY;
+ }
/* Don't allow HT rates after next pass.
* rs_get_lower_rate() will change type to LQ_A or LQ_G. */