diff options
| author | Shanyu Zhao <shanyu.zhao@intel.com> | 2010-03-19 16:34:45 -0400 |
|---|---|---|
| committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-04-02 14:12:37 -0400 |
| commit | 04f2dec1c3d375c4072613880f28f43b66524876 (patch) | |
| tree | f0544c88fc1205197df3680a33fe75098bf50074 | |
| parent | dd48744964296b5713032ea1d66eb9e3d990e287 (diff) | |
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>
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8bf7c20b9d39..be00cb3b1d0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
| @@ -345,6 +345,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 345 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 345 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | /* | ||
| 349 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 350 | * that wraps a NULL pointer check | ||
| 351 | */ | ||
| 352 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 353 | { | ||
| 354 | if (tbl->expected_tpt) | ||
| 355 | return tbl->expected_tpt[rs_index]; | ||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 348 | /** | 359 | /** |
| 349 | * rs_collect_tx_data - Update the success/failure sliding window | 360 | * rs_collect_tx_data - Update the success/failure sliding window |
| 350 | * | 361 | * |
| @@ -352,19 +363,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
| 352 | * at this rate. window->data contains the bitmask of successful | 363 | * at this rate. window->data contains the bitmask of successful |
| 353 | * packets. | 364 | * packets. |
| 354 | */ | 365 | */ |
| 355 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 366 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
| 356 | int scale_index, s32 tpt, int attempts, | 367 | int scale_index, int attempts, int successes) |
| 357 | int successes) | ||
| 358 | { | 368 | { |
| 359 | struct iwl_rate_scale_data *window = NULL; | 369 | struct iwl_rate_scale_data *window = NULL; |
| 360 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 370 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
| 361 | s32 fail_count; | 371 | s32 fail_count, tpt; |
| 362 | 372 | ||
| 363 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 373 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
| 364 | return -EINVAL; | 374 | return -EINVAL; |
| 365 | 375 | ||
| 366 | /* Select window for current tx bit rate */ | 376 | /* Select window for current tx bit rate */ |
| 367 | window = &(windows[scale_index]); | 377 | window = &(tbl->win[scale_index]); |
| 378 | |||
| 379 | /* Get expected throughput */ | ||
| 380 | tpt = get_expected_tpt(tbl, scale_index); | ||
| 368 | 381 | ||
| 369 | /* | 382 | /* |
| 370 | * Keep track of only the latest 62 tx frame attempts in this rate's | 383 | * 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, | |||
| 738 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | 751 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && |
| 739 | (a->is_SGI == b->is_SGI); | 752 | (a->is_SGI == b->is_SGI); |
| 740 | } | 753 | } |
| 741 | /* | ||
| 742 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
| 743 | * that wraps a NULL pointer check | ||
| 744 | */ | ||
| 745 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
| 746 | { | ||
| 747 | if (tbl->expected_tpt) | ||
| 748 | return tbl->expected_tpt[rs_index]; | ||
| 749 | return 0; | ||
| 750 | } | ||
| 751 | 754 | ||
| 752 | /* | 755 | /* |
| 753 | * mac80211 sends us Tx status | 756 | * mac80211 sends us Tx status |
| @@ -764,12 +767,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 764 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 767 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 765 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 768 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
| 766 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 769 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 767 | struct iwl_rate_scale_data *window = NULL; | ||
| 768 | enum mac80211_rate_control_flags mac_flags; | 770 | enum mac80211_rate_control_flags mac_flags; |
| 769 | u32 tx_rate; | 771 | u32 tx_rate; |
| 770 | struct iwl_scale_tbl_info tbl_type; | 772 | struct iwl_scale_tbl_info tbl_type; |
| 771 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl; | 773 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
| 772 | s32 tpt = 0; | ||
| 773 | 774 | ||
| 774 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 775 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
| 775 | 776 | ||
| @@ -852,7 +853,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 852 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | 853 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
| 853 | return; | 854 | return; |
| 854 | } | 855 | } |
| 855 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
| 856 | 856 | ||
| 857 | /* | 857 | /* |
| 858 | * Updating the frame history depends on whether packets were | 858 | * 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, | |||
| 865 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 865 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
| 866 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, | 866 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
| 867 | &rs_index); | 867 | &rs_index); |
| 868 | tpt = get_expected_tpt(curr_tbl, rs_index); | 868 | rs_collect_tx_data(curr_tbl, rs_index, |
| 869 | rs_collect_tx_data(window, rs_index, tpt, | ||
| 870 | info->status.ampdu_ack_len, | 869 | info->status.ampdu_ack_len, |
| 871 | info->status.ampdu_ack_map); | 870 | info->status.ampdu_ack_map); |
| 872 | 871 | ||
| @@ -896,19 +895,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
| 896 | * table as active/search. | 895 | * table as active/search. |
| 897 | */ | 896 | */ |
| 898 | if (table_type_matches(&tbl_type, curr_tbl)) | 897 | if (table_type_matches(&tbl_type, curr_tbl)) |
| 899 | tpt = get_expected_tpt(curr_tbl, rs_index); | 898 | tmp_tbl = curr_tbl; |
| 900 | else if (table_type_matches(&tbl_type, other_tbl)) | 899 | else if (table_type_matches(&tbl_type, other_tbl)) |
| 901 | tpt = get_expected_tpt(other_tbl, rs_index); | 900 | tmp_tbl = other_tbl; |
| 902 | else | 901 | else |
| 903 | continue; | 902 | continue; |
| 904 | 903 | rs_collect_tx_data(tmp_tbl, rs_index, 1, | |
| 905 | /* Constants mean 1 transmission, 0 successes */ | 904 | i < retries ? 0 : legacy_success); |
| 906 | if (i < retries) | ||
| 907 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 908 | 0); | ||
| 909 | else | ||
| 910 | rs_collect_tx_data(window, rs_index, tpt, 1, | ||
| 911 | legacy_success); | ||
| 912 | } | 905 | } |
| 913 | 906 | ||
| 914 | /* Update success/fail counts if not searching for new mode */ | 907 | /* Update success/fail counts if not searching for new mode */ |
