diff options
author | Daniel C Halperin <daniel.c.halperin@intel.com> | 2009-09-17 13:43:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-07 16:39:34 -0400 |
commit | 95407aa4d48a8b3a2adf6a110853b544342913bd (patch) | |
tree | 1ba2eb6a31b932a728bc70c235e8535824575a18 /drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |
parent | 4e30cb691b9ba62642cc1594ef08f7439deb5a02 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 230 |
1 files changed, 108 insertions, 122 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 469d56321d88..cd24763d5fde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -821,27 +821,45 @@ out: | |||
821 | } | 821 | } |
822 | 822 | ||
823 | /* | 823 | /* |
824 | * Simple function to compare two rate scale table types | ||
825 | */ | ||
826 | static bool table_type_matches(struct iwl_scale_tbl_info *a, | ||
827 | struct iwl_scale_tbl_info *b) | ||
828 | { | ||
829 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | ||
830 | (a->is_SGI == b->is_SGI); | ||
831 | } | ||
832 | /* | ||
833 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
834 | * that wraps a NULL pointer check | ||
835 | */ | ||
836 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
837 | { | ||
838 | if (tbl->expected_tpt) | ||
839 | return tbl->expected_tpt[rs_index]; | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | /* | ||
824 | * mac80211 sends us Tx status | 844 | * mac80211 sends us Tx status |
825 | */ | 845 | */ |
826 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | 846 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
827 | struct ieee80211_sta *sta, void *priv_sta, | 847 | struct ieee80211_sta *sta, void *priv_sta, |
828 | struct sk_buff *skb) | 848 | struct sk_buff *skb) |
829 | { | 849 | { |
830 | int status; | 850 | int legacy_success; |
831 | u8 retries; | 851 | int retries; |
832 | int rs_index, mac_index, index = 0; | 852 | int rs_index, mac_index, i; |
833 | struct iwl_lq_sta *lq_sta = priv_sta; | 853 | struct iwl_lq_sta *lq_sta = priv_sta; |
834 | struct iwl_link_quality_cmd *table; | 854 | struct iwl_link_quality_cmd *table; |
835 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 855 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
836 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 856 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
837 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 857 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
838 | struct iwl_rate_scale_data *window = NULL; | 858 | struct iwl_rate_scale_data *window = NULL; |
839 | struct iwl_rate_scale_data *search_win = NULL; | ||
840 | enum mac80211_rate_control_flags mac_flags; | 859 | enum mac80211_rate_control_flags mac_flags; |
841 | u32 tx_rate; | 860 | u32 tx_rate; |
842 | struct iwl_scale_tbl_info tbl_type; | 861 | struct iwl_scale_tbl_info tbl_type; |
843 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 862 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl; |
844 | u8 active_index = 0; | ||
845 | s32 tpt = 0; | 863 | s32 tpt = 0; |
846 | 864 | ||
847 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 865 | 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, | |||
855 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 873 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
856 | return; | 874 | return; |
857 | 875 | ||
858 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
859 | retries = 0; | ||
860 | else | ||
861 | retries = info->status.rates[0].count - 1; | ||
862 | |||
863 | if (retries > 15) | ||
864 | retries = 15; | ||
865 | 876 | ||
866 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 877 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
867 | !lq_sta->ibss_sta_added) | 878 | !lq_sta->ibss_sta_added) |
868 | goto out; | 879 | return; |
869 | |||
870 | table = &lq_sta->lq; | ||
871 | active_index = lq_sta->active_tbl; | ||
872 | |||
873 | curr_tbl = &(lq_sta->lq_info[active_index]); | ||
874 | search_tbl = &(lq_sta->lq_info[(1 - active_index)]); | ||
875 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
876 | search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); | ||
877 | 880 | ||
878 | /* | 881 | /* |
879 | * Ignore this Tx frame response if its initial rate doesn't match | 882 | * 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, | |||
883 | * to check "search" mode, or a prior "search" mode after we've moved | 886 | * to check "search" mode, or a prior "search" mode after we've moved |
884 | * to a new "search" mode (which might become the new "active" mode). | 887 | * to a new "search" mode (which might become the new "active" mode). |
885 | */ | 888 | */ |
889 | table = &lq_sta->lq; | ||
886 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 890 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
887 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 891 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
888 | if (priv->band == IEEE80211_BAND_5GHZ) | 892 | if (priv->band == IEEE80211_BAND_5GHZ) |
@@ -901,7 +905,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
901 | if (priv->band == IEEE80211_BAND_2GHZ) | 905 | if (priv->band == IEEE80211_BAND_2GHZ) |
902 | mac_index += IWL_FIRST_OFDM_RATE; | 906 | mac_index += IWL_FIRST_OFDM_RATE; |
903 | } | 907 | } |
904 | 908 | /* Here we actually compare this rate to the latest LQ command */ | |
905 | if ((mac_index < 0) || | 909 | if ((mac_index < 0) || |
906 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 910 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
907 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 911 | (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, | |||
911 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 915 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
912 | (rs_index != mac_index)) { | 916 | (rs_index != mac_index)) { |
913 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); | 917 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); |
914 | /* the last LQ command could failed so the LQ in ucode not | 918 | /* |
915 | * the same in driver sync up | 919 | * Since rates mis-match, the last LQ command may have failed. |
920 | * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with | ||
921 | * ... driver. | ||
916 | */ | 922 | */ |
917 | lq_sta->missed_rate_counter++; | 923 | lq_sta->missed_rate_counter++; |
918 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 924 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
919 | lq_sta->missed_rate_counter = 0; | 925 | lq_sta->missed_rate_counter = 0; |
920 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 926 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
921 | } | 927 | } |
922 | goto out; | 928 | /* Regardless, ignore this status info for outdated rate */ |
929 | return; | ||
930 | } else | ||
931 | /* Rate did match, so reset the missed_rate_counter */ | ||
932 | lq_sta->missed_rate_counter = 0; | ||
933 | |||
934 | /* Figure out if rate scale algorithm is in active or search table */ | ||
935 | if (table_type_matches(&tbl_type, | ||
936 | &(lq_sta->lq_info[lq_sta->active_tbl]))) { | ||
937 | curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
938 | other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
939 | } else if (table_type_matches(&tbl_type, | ||
940 | &lq_sta->lq_info[1 - lq_sta->active_tbl])) { | ||
941 | curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
942 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
943 | } else { | ||
944 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | ||
945 | return; | ||
923 | } | 946 | } |
947 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
924 | 948 | ||
925 | lq_sta->missed_rate_counter = 0; | 949 | /* |
926 | /* Update frame history window with "failure" for each Tx retry. */ | 950 | * Updating the frame history depends on whether packets were |
927 | while (retries) { | 951 | * aggregated. |
928 | /* Look up the rate and other info used for each tx attempt. | 952 | * |
929 | * Each tx attempt steps one entry deeper in the rate table. */ | 953 | * For aggregation, all packets were transmitted at the same rate, the |
930 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 954 | * first index into rate scale table. |
931 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | 955 | */ |
932 | &tbl_type, &rs_index); | 956 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
933 | 957 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | |
934 | /* If type matches "search" table, | 958 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
935 | * add failure to "search" history */ | 959 | &rs_index); |
936 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 960 | tpt = get_expected_tpt(curr_tbl, rs_index); |
937 | (tbl_type.ant_type == search_tbl->ant_type) && | 961 | rs_collect_tx_data(window, rs_index, tpt, |
938 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 962 | info->status.ampdu_ack_len, |
939 | if (search_tbl->expected_tpt) | 963 | info->status.ampdu_ack_map); |
940 | tpt = search_tbl->expected_tpt[rs_index]; | 964 | |
941 | else | 965 | /* Update success/fail counts if not searching for new mode */ |
942 | tpt = 0; | 966 | if (lq_sta->stay_in_tbl) { |
943 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); | 967 | lq_sta->total_success += info->status.ampdu_ack_map; |
944 | 968 | lq_sta->total_failed += (info->status.ampdu_ack_len - | |
945 | /* Else if type matches "current/active" table, | 969 | info->status.ampdu_ack_map); |
946 | * add failure to "current/active" history */ | ||
947 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
948 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
949 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
950 | if (curr_tbl->expected_tpt) | ||
951 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
952 | else | ||
953 | tpt = 0; | ||
954 | rs_collect_tx_data(window, rs_index, tpt, 1, 0); | ||
955 | } | 970 | } |
956 | 971 | } else { | |
957 | /* If not searching for a new mode, increment failed counter | ||
958 | * ... this helps determine when to start searching again */ | ||
959 | if (lq_sta->stay_in_tbl) | ||
960 | lq_sta->total_failed++; | ||
961 | --retries; | ||
962 | index++; | ||
963 | |||
964 | } | ||
965 | |||
966 | /* | 972 | /* |
967 | * Find (by rate) the history window to update with final Tx attempt; | 973 | * For legacy, update frame history with for each Tx retry. |
968 | * if Tx was successful first try, use original rate, | ||
969 | * else look up the rate that was, finally, successful. | ||
970 | */ | 974 | */ |
971 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 975 | retries = info->status.rates[0].count - 1; |
972 | lq_sta->last_rate_n_flags = tx_rate; | 976 | /* HW doesn't send more than 15 retries */ |
973 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 977 | retries = min(retries, 15); |
974 | 978 | ||
975 | /* Update frame history window with "success" if Tx got ACKed ... */ | 979 | /* The last transmission may have been successful */ |
976 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); | 980 | legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
977 | 981 | /* Collect data for each rate used during failed TX attempts */ | |
978 | /* If type matches "search" table, | 982 | for (i = 0; i <= retries; ++i) { |
979 | * add final tx status to "search" history */ | 983 | tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags); |
980 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 984 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, |
981 | (tbl_type.ant_type == search_tbl->ant_type) && | 985 | &tbl_type, &rs_index); |
982 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 986 | /* |
983 | if (search_tbl->expected_tpt) | 987 | * Only collect stats if retried rate is in the same RS |
984 | tpt = search_tbl->expected_tpt[rs_index]; | 988 | * table as active/search. |
985 | else | 989 | */ |
986 | tpt = 0; | 990 | if (table_type_matches(&tbl_type, curr_tbl)) |
987 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | 991 | tpt = get_expected_tpt(curr_tbl, rs_index); |
988 | rs_collect_tx_data(search_win, rs_index, tpt, | 992 | else if (table_type_matches(&tbl_type, other_tbl)) |
989 | info->status.ampdu_ack_len, | 993 | tpt = get_expected_tpt(other_tbl, rs_index); |
990 | info->status.ampdu_ack_map); | 994 | else |
991 | else | 995 | continue; |
992 | rs_collect_tx_data(search_win, rs_index, tpt, | ||
993 | 1, status); | ||
994 | /* Else if type matches "current/active" table, | ||
995 | * add final tx status to "current/active" history */ | ||
996 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
997 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
998 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
999 | if (curr_tbl->expected_tpt) | ||
1000 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
1001 | else | ||
1002 | tpt = 0; | ||
1003 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
1004 | rs_collect_tx_data(window, rs_index, tpt, | ||
1005 | info->status.ampdu_ack_len, | ||
1006 | info->status.ampdu_ack_map); | ||
1007 | else | ||
1008 | rs_collect_tx_data(window, rs_index, tpt, | ||
1009 | 1, status); | ||
1010 | } | ||
1011 | 996 | ||
1012 | /* If not searching for new mode, increment success/failed counter | 997 | /* Constants mean 1 transmission, 0 successes */ |
1013 | * ... these help determine when to start searching again */ | 998 | if (i < retries) |
1014 | if (lq_sta->stay_in_tbl) { | 999 | rs_collect_tx_data(window, rs_index, tpt, 1, |
1015 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | 1000 | 0); |
1016 | lq_sta->total_success += info->status.ampdu_ack_map; | ||
1017 | lq_sta->total_failed += | ||
1018 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | ||
1019 | } else { | ||
1020 | if (status) | ||
1021 | lq_sta->total_success++; | ||
1022 | else | 1001 | else |
1023 | lq_sta->total_failed++; | 1002 | rs_collect_tx_data(window, rs_index, tpt, 1, |
1003 | legacy_success); | ||
1004 | } | ||
1005 | |||
1006 | /* Update success/fail counts if not searching for new mode */ | ||
1007 | if (lq_sta->stay_in_tbl) { | ||
1008 | lq_sta->total_success += legacy_success; | ||
1009 | lq_sta->total_failed += retries + (1 - legacy_success); | ||
1024 | } | 1010 | } |
1025 | } | 1011 | } |
1012 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | ||
1013 | lq_sta->last_rate_n_flags = tx_rate; | ||
1026 | 1014 | ||
1027 | /* See if there's a better rate or modulation mode to try. */ | 1015 | /* See if there's a better rate or modulation mode to try. */ |
1028 | if (sta && sta->supp_rates[sband->band]) | 1016 | if (sta && sta->supp_rates[sband->band]) |
1029 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 1017 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
1030 | out: | ||
1031 | return; | ||
1032 | } | 1018 | } |
1033 | 1019 | ||
1034 | /* | 1020 | /* |