forked from Minki/linux
iwlwifi: use consistent table for tx data collect
When collecting tx data for non-aggregation packets in rate scaling, if the tx data matches "other table", it still uses current table to update the stats and calculate average throughput in function rs_collect_tx_data(). This can mess up the rate scaling data structure and cause a kernel panic in a BUG_ON statement in rs_rate_scale_perform(). To fix this bug, we pass table pointer instead of window pointer (pointed to by table pointer) to function rs_collect_tx_data() so that the table being used is consistent. Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com> Signed-off-by: Henry Zhang <hongx.c.zhang@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
This commit is contained in:
parent
dd48744964
commit
04f2dec1c3
@ -345,6 +345,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
|
|||||||
!!(rate_n_flags & RATE_MCS_ANT_C_MSK);
|
!!(rate_n_flags & RATE_MCS_ANT_C_MSK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rs_collect_tx_data - Update the success/failure sliding window
|
* rs_collect_tx_data - Update the success/failure sliding window
|
||||||
*
|
*
|
||||||
@ -352,19 +363,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
|
|||||||
* at this rate. window->data contains the bitmask of successful
|
* at this rate. window->data contains the bitmask of successful
|
||||||
* packets.
|
* packets.
|
||||||
*/
|
*/
|
||||||
static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
|
static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
|
||||||
int scale_index, s32 tpt, int attempts,
|
int scale_index, int attempts, int successes)
|
||||||
int successes)
|
|
||||||
{
|
{
|
||||||
struct iwl_rate_scale_data *window = NULL;
|
struct iwl_rate_scale_data *window = NULL;
|
||||||
static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
|
static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
|
||||||
s32 fail_count;
|
s32 fail_count, tpt;
|
||||||
|
|
||||||
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
|
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Select window for current tx bit rate */
|
/* Select window for current tx bit rate */
|
||||||
window = &(windows[scale_index]);
|
window = &(tbl->win[scale_index]);
|
||||||
|
|
||||||
|
/* Get expected throughput */
|
||||||
|
tpt = get_expected_tpt(tbl, scale_index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep track of only the latest 62 tx frame attempts in this rate's
|
* Keep track of only the latest 62 tx frame attempts in this rate's
|
||||||
@ -738,16 +751,6 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
|
|||||||
return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
|
return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
|
||||||
(a->is_SGI == b->is_SGI);
|
(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
|
||||||
@ -764,12 +767,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
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;
|
|
||||||
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, *other_tbl;
|
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
|
||||||
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");
|
||||||
|
|
||||||
@ -852,7 +853,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
|
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updating the frame history depends on whether packets were
|
* Updating the frame history depends on whether packets were
|
||||||
@ -865,8 +865,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
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_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
|
||||||
&rs_index);
|
&rs_index);
|
||||||
tpt = get_expected_tpt(curr_tbl, rs_index);
|
rs_collect_tx_data(curr_tbl, rs_index,
|
||||||
rs_collect_tx_data(window, rs_index, tpt,
|
|
||||||
info->status.ampdu_ack_len,
|
info->status.ampdu_ack_len,
|
||||||
info->status.ampdu_ack_map);
|
info->status.ampdu_ack_map);
|
||||||
|
|
||||||
@ -896,19 +895,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||||||
* table as active/search.
|
* table as active/search.
|
||||||
*/
|
*/
|
||||||
if (table_type_matches(&tbl_type, curr_tbl))
|
if (table_type_matches(&tbl_type, curr_tbl))
|
||||||
tpt = get_expected_tpt(curr_tbl, rs_index);
|
tmp_tbl = curr_tbl;
|
||||||
else if (table_type_matches(&tbl_type, other_tbl))
|
else if (table_type_matches(&tbl_type, other_tbl))
|
||||||
tpt = get_expected_tpt(other_tbl, rs_index);
|
tmp_tbl = other_tbl;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
rs_collect_tx_data(tmp_tbl, rs_index, 1,
|
||||||
/* Constants mean 1 transmission, 0 successes */
|
i < retries ? 0 : legacy_success);
|
||||||
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 */
|
/* Update success/fail counts if not searching for new mode */
|
||||||
|
Loading…
Reference in New Issue
Block a user