iwlwifi: clean up rs_tx_status
Cut down on redundant code, reorganize structure, and add/improve comments. Should contain no functional changes. Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4e30cb691b
commit
95407aa4d4
@ -820,6 +820,26 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
|
|||||||
return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
|
return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple function to compare two rate scale table types
|
||||||
|
*/
|
||||||
|
static bool table_type_matches(struct iwl_scale_tbl_info *a,
|
||||||
|
struct iwl_scale_tbl_info *b)
|
||||||
|
{
|
||||||
|
return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
|
||||||
|
(a->is_SGI == b->is_SGI);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Static function to get the expected throughput from an iwl_scale_tbl_info
|
||||||
|
* that wraps a NULL pointer check
|
||||||
|
*/
|
||||||
|
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
|
||||||
|
{
|
||||||
|
if (tbl->expected_tpt)
|
||||||
|
return tbl->expected_tpt[rs_index];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mac80211 sends us Tx status
|
* mac80211 sends us Tx status
|
||||||
*/
|
*/
|
||||||
@ -827,21 +847,19 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
struct ieee80211_sta *sta, void *priv_sta,
|
struct ieee80211_sta *sta, void *priv_sta,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int status;
|
int legacy_success;
|
||||||
u8 retries;
|
int retries;
|
||||||
int rs_index, mac_index, index = 0;
|
int rs_index, mac_index, i;
|
||||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||||
struct iwl_link_quality_cmd *table;
|
struct iwl_link_quality_cmd *table;
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
struct iwl_rate_scale_data *window = NULL;
|
struct iwl_rate_scale_data *window = NULL;
|
||||||
struct iwl_rate_scale_data *search_win = NULL;
|
|
||||||
enum mac80211_rate_control_flags mac_flags;
|
enum mac80211_rate_control_flags mac_flags;
|
||||||
u32 tx_rate;
|
u32 tx_rate;
|
||||||
struct iwl_scale_tbl_info tbl_type;
|
struct iwl_scale_tbl_info tbl_type;
|
||||||
struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
|
struct iwl_scale_tbl_info *curr_tbl, *other_tbl;
|
||||||
u8 active_index = 0;
|
|
||||||
s32 tpt = 0;
|
s32 tpt = 0;
|
||||||
|
|
||||||
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
|
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
|
||||||
@ -855,25 +873,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
|
||||||
retries = 0;
|
|
||||||
else
|
|
||||||
retries = info->status.rates[0].count - 1;
|
|
||||||
|
|
||||||
if (retries > 15)
|
|
||||||
retries = 15;
|
|
||||||
|
|
||||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
||||||
!lq_sta->ibss_sta_added)
|
!lq_sta->ibss_sta_added)
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
table = &lq_sta->lq;
|
|
||||||
active_index = lq_sta->active_tbl;
|
|
||||||
|
|
||||||
curr_tbl = &(lq_sta->lq_info[active_index]);
|
|
||||||
search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
|
|
||||||
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
|
|
||||||
search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore this Tx frame response if its initial rate doesn't match
|
* Ignore this Tx frame response if its initial rate doesn't match
|
||||||
@ -883,6 +886,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
* to check "search" mode, or a prior "search" mode after we've moved
|
* to check "search" mode, or a prior "search" mode after we've moved
|
||||||
* to a new "search" mode (which might become the new "active" mode).
|
* to a new "search" mode (which might become the new "active" mode).
|
||||||
*/
|
*/
|
||||||
|
table = &lq_sta->lq;
|
||||||
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
|
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
|
||||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
||||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||||
@ -901,7 +905,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
if (priv->band == IEEE80211_BAND_2GHZ)
|
if (priv->band == IEEE80211_BAND_2GHZ)
|
||||||
mac_index += IWL_FIRST_OFDM_RATE;
|
mac_index += IWL_FIRST_OFDM_RATE;
|
||||||
}
|
}
|
||||||
|
/* Here we actually compare this rate to the latest LQ command */
|
||||||
if ((mac_index < 0) ||
|
if ((mac_index < 0) ||
|
||||||
(tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
|
(tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
|
||||||
(tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
|
(tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
|
||||||
@ -911,124 +915,106 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
|
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
|
||||||
(rs_index != mac_index)) {
|
(rs_index != mac_index)) {
|
||||||
IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate);
|
IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate);
|
||||||
/* the last LQ command could failed so the LQ in ucode not
|
/*
|
||||||
* the same in driver sync up
|
* Since rates mis-match, the last LQ command may have failed.
|
||||||
|
* After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
|
||||||
|
* ... driver.
|
||||||
*/
|
*/
|
||||||
lq_sta->missed_rate_counter++;
|
lq_sta->missed_rate_counter++;
|
||||||
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
|
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
|
||||||
lq_sta->missed_rate_counter = 0;
|
lq_sta->missed_rate_counter = 0;
|
||||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
|
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
|
||||||
}
|
}
|
||||||
goto out;
|
/* Regardless, ignore this status info for outdated rate */
|
||||||
}
|
return;
|
||||||
|
} else
|
||||||
lq_sta->missed_rate_counter = 0;
|
/* Rate did match, so reset the missed_rate_counter */
|
||||||
/* Update frame history window with "failure" for each Tx retry. */
|
lq_sta->missed_rate_counter = 0;
|
||||||
while (retries) {
|
|
||||||
/* Look up the rate and other info used for each tx attempt.
|
/* Figure out if rate scale algorithm is in active or search table */
|
||||||
* Each tx attempt steps one entry deeper in the rate table. */
|
if (table_type_matches(&tbl_type,
|
||||||
tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
|
&(lq_sta->lq_info[lq_sta->active_tbl]))) {
|
||||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band,
|
curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||||
&tbl_type, &rs_index);
|
other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
|
||||||
|
} else if (table_type_matches(&tbl_type,
|
||||||
/* If type matches "search" table,
|
&lq_sta->lq_info[1 - lq_sta->active_tbl])) {
|
||||||
* add failure to "search" history */
|
curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
|
||||||
if ((tbl_type.lq_type == search_tbl->lq_type) &&
|
other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||||
(tbl_type.ant_type == search_tbl->ant_type) &&
|
} else {
|
||||||
(tbl_type.is_SGI == search_tbl->is_SGI)) {
|
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
|
||||||
if (search_tbl->expected_tpt)
|
return;
|
||||||
tpt = search_tbl->expected_tpt[rs_index];
|
|
||||||
else
|
|
||||||
tpt = 0;
|
|
||||||
rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
|
|
||||||
|
|
||||||
/* Else if type matches "current/active" table,
|
|
||||||
* add failure to "current/active" history */
|
|
||||||
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
|
|
||||||
(tbl_type.ant_type == curr_tbl->ant_type) &&
|
|
||||||
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
|
|
||||||
if (curr_tbl->expected_tpt)
|
|
||||||
tpt = curr_tbl->expected_tpt[rs_index];
|
|
||||||
else
|
|
||||||
tpt = 0;
|
|
||||||
rs_collect_tx_data(window, rs_index, tpt, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If not searching for a new mode, increment failed counter
|
|
||||||
* ... this helps determine when to start searching again */
|
|
||||||
if (lq_sta->stay_in_tbl)
|
|
||||||
lq_sta->total_failed++;
|
|
||||||
--retries;
|
|
||||||
index++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find (by rate) the history window to update with final Tx attempt;
|
* Updating the frame history depends on whether packets were
|
||||||
* if Tx was successful first try, use original rate,
|
* aggregated.
|
||||||
* else look up the rate that was, finally, successful.
|
*
|
||||||
|
* For aggregation, all packets were transmitted at the same rate, the
|
||||||
|
* first index into rate scale table.
|
||||||
*/
|
*/
|
||||||
tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
|
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
|
||||||
lq_sta->last_rate_n_flags = tx_rate;
|
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
|
||||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
|
||||||
|
&rs_index);
|
||||||
|
tpt = get_expected_tpt(curr_tbl, rs_index);
|
||||||
|
rs_collect_tx_data(window, rs_index, tpt,
|
||||||
|
info->status.ampdu_ack_len,
|
||||||
|
info->status.ampdu_ack_map);
|
||||||
|
|
||||||
/* Update frame history window with "success" if Tx got ACKed ... */
|
/* Update success/fail counts if not searching for new mode */
|
||||||
status = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
if (lq_sta->stay_in_tbl) {
|
||||||
|
|
||||||
/* If type matches "search" table,
|
|
||||||
* add final tx status to "search" history */
|
|
||||||
if ((tbl_type.lq_type == search_tbl->lq_type) &&
|
|
||||||
(tbl_type.ant_type == search_tbl->ant_type) &&
|
|
||||||
(tbl_type.is_SGI == search_tbl->is_SGI)) {
|
|
||||||
if (search_tbl->expected_tpt)
|
|
||||||
tpt = search_tbl->expected_tpt[rs_index];
|
|
||||||
else
|
|
||||||
tpt = 0;
|
|
||||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
|
||||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
|
||||||
info->status.ampdu_ack_len,
|
|
||||||
info->status.ampdu_ack_map);
|
|
||||||
else
|
|
||||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
|
||||||
1, status);
|
|
||||||
/* Else if type matches "current/active" table,
|
|
||||||
* add final tx status to "current/active" history */
|
|
||||||
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
|
|
||||||
(tbl_type.ant_type == curr_tbl->ant_type) &&
|
|
||||||
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
|
|
||||||
if (curr_tbl->expected_tpt)
|
|
||||||
tpt = curr_tbl->expected_tpt[rs_index];
|
|
||||||
else
|
|
||||||
tpt = 0;
|
|
||||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
|
||||||
rs_collect_tx_data(window, rs_index, tpt,
|
|
||||||
info->status.ampdu_ack_len,
|
|
||||||
info->status.ampdu_ack_map);
|
|
||||||
else
|
|
||||||
rs_collect_tx_data(window, rs_index, tpt,
|
|
||||||
1, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If not searching for new mode, increment success/failed counter
|
|
||||||
* ... these help determine when to start searching again */
|
|
||||||
if (lq_sta->stay_in_tbl) {
|
|
||||||
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
|
|
||||||
lq_sta->total_success += info->status.ampdu_ack_map;
|
lq_sta->total_success += info->status.ampdu_ack_map;
|
||||||
lq_sta->total_failed +=
|
lq_sta->total_failed += (info->status.ampdu_ack_len -
|
||||||
(info->status.ampdu_ack_len - info->status.ampdu_ack_map);
|
info->status.ampdu_ack_map);
|
||||||
} else {
|
}
|
||||||
if (status)
|
} else {
|
||||||
lq_sta->total_success++;
|
/*
|
||||||
|
* For legacy, update frame history with for each Tx retry.
|
||||||
|
*/
|
||||||
|
retries = info->status.rates[0].count - 1;
|
||||||
|
/* HW doesn't send more than 15 retries */
|
||||||
|
retries = min(retries, 15);
|
||||||
|
|
||||||
|
/* The last transmission may have been successful */
|
||||||
|
legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||||
|
/* Collect data for each rate used during failed TX attempts */
|
||||||
|
for (i = 0; i <= retries; ++i) {
|
||||||
|
tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
|
||||||
|
rs_get_tbl_info_from_mcs(tx_rate, priv->band,
|
||||||
|
&tbl_type, &rs_index);
|
||||||
|
/*
|
||||||
|
* Only collect stats if retried rate is in the same RS
|
||||||
|
* table as active/search.
|
||||||
|
*/
|
||||||
|
if (table_type_matches(&tbl_type, curr_tbl))
|
||||||
|
tpt = get_expected_tpt(curr_tbl, rs_index);
|
||||||
|
else if (table_type_matches(&tbl_type, other_tbl))
|
||||||
|
tpt = get_expected_tpt(other_tbl, rs_index);
|
||||||
else
|
else
|
||||||
lq_sta->total_failed++;
|
continue;
|
||||||
|
|
||||||
|
/* Constants mean 1 transmission, 0 successes */
|
||||||
|
if (i < retries)
|
||||||
|
rs_collect_tx_data(window, rs_index, tpt, 1,
|
||||||
|
0);
|
||||||
|
else
|
||||||
|
rs_collect_tx_data(window, rs_index, tpt, 1,
|
||||||
|
legacy_success);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update success/fail counts if not searching for new mode */
|
||||||
|
if (lq_sta->stay_in_tbl) {
|
||||||
|
lq_sta->total_success += legacy_success;
|
||||||
|
lq_sta->total_failed += retries + (1 - legacy_success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* The last TX rate is cached in lq_sta; it's set in if/else above */
|
||||||
|
lq_sta->last_rate_n_flags = tx_rate;
|
||||||
|
|
||||||
/* See if there's a better rate or modulation mode to try. */
|
/* See if there's a better rate or modulation mode to try. */
|
||||||
if (sta && sta->supp_rates[sband->band])
|
if (sta && sta->supp_rates[sband->band])
|
||||||
rs_rate_scale_perform(priv, skb, sta, lq_sta);
|
rs_rate_scale_perform(priv, skb, sta, lq_sta);
|
||||||
out:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user