aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2015-01-30 06:40:02 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-02-23 15:08:07 -0500
commit929e6edea5ef8fd3d2324ba4ce5736be7d52b9d8 (patch)
tree6de7ee31fa41899e07c6b20af025bd6a55eda942 /drivers/net/wireless/iwlwifi
parentf5af19d10d151c5a2afae3306578f485c244db25 (diff)
iwlwifi: mvm: rs: better match tx response rate to the LQ table
Currently rs uses the info in mac80211 tx status which is a translation of the actual rate coming up from the FW in the tx response. This is matched up against the LQ table first rate to make sure this tx frame used the current LQ table. Instead of using the translated mac80211 info it's easier and cleaner to just pass the actual tx response rate in the driver private data and use that for matching. This becomes even more important once the FW begins to decide on its own whether to use STBC/BFER/SISO. Signed-off-by: Eyal Shapira <eyalx.shapira@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c119
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c4
2 files changed, 47 insertions, 76 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 194bd1f939ca..1e8243411f20 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -1001,10 +1001,19 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
1001 rs_get_lower_rate_in_column(lq_sta, rate); 1001 rs_get_lower_rate_in_column(lq_sta, rate);
1002} 1002}
1003 1003
1004/* Simple function to compare two rate scale table types */ 1004/* Check if both rates are identical */
1005static inline bool rs_rate_match(struct rs_rate *a, 1005static inline bool rs_rate_equal(struct rs_rate *a,
1006 struct rs_rate *b) 1006 struct rs_rate *b)
1007{ 1007{
1008 return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) &&
1009 (a->ldpc == b->ldpc) && (a->index == b->index) &&
1010 (a->ant == b->ant);
1011}
1012
1013/* Check if both rates share the same column */
1014static inline bool rs_rate_column_match(struct rs_rate *a,
1015 struct rs_rate *b)
1016{
1008 bool ant_match; 1017 bool ant_match;
1009 1018
1010 if (a->stbc) 1019 if (a->stbc)
@@ -1016,18 +1025,6 @@ static inline bool rs_rate_match(struct rs_rate *a,
1016 && ant_match; 1025 && ant_match;
1017} 1026}
1018 1027
1019static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
1020{
1021 if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1022 return RATE_MCS_CHAN_WIDTH_40;
1023 else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
1024 return RATE_MCS_CHAN_WIDTH_80;
1025 else if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
1026 return RATE_MCS_CHAN_WIDTH_160;
1027
1028 return RATE_MCS_CHAN_WIDTH_20;
1029}
1030
1031static u8 rs_get_tid(struct ieee80211_hdr *hdr) 1028static u8 rs_get_tid(struct ieee80211_hdr *hdr)
1032{ 1029{
1033 u8 tid = IWL_MAX_TID_COUNT; 1030 u8 tid = IWL_MAX_TID_COUNT;
@@ -1048,13 +1045,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1048{ 1045{
1049 int legacy_success; 1046 int legacy_success;
1050 int retries; 1047 int retries;
1051 int mac_index, i; 1048 int i;
1052 struct iwl_lq_cmd *table; 1049 struct iwl_lq_cmd *table;
1053 enum mac80211_rate_control_flags mac_flags; 1050 u32 lq_hwrate;
1054 u32 ucode_rate; 1051 struct rs_rate lq_rate, tx_resp_rate;
1055 struct rs_rate rate;
1056 struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; 1052 struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
1057 u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; 1053 u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0];
1054 u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
1058 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1055 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1059 struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; 1056 struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
1060 1057
@@ -1079,39 +1076,6 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1079 !(info->flags & IEEE80211_TX_STAT_AMPDU)) 1076 !(info->flags & IEEE80211_TX_STAT_AMPDU))
1080 return; 1077 return;
1081 1078
1082 /*
1083 * Ignore this Tx frame response if its initial rate doesn't match
1084 * that of latest Link Quality command. There may be stragglers
1085 * from a previous Link Quality command, but we're no longer interested
1086 * in those; they're either from the "active" mode while we're trying
1087 * to check "search" mode, or a prior "search" mode after we've moved
1088 * to a new "search" mode (which might become the new "active" mode).
1089 */
1090 table = &lq_sta->lq;
1091 ucode_rate = le32_to_cpu(table->rs_table[0]);
1092 rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
1093 if (info->band == IEEE80211_BAND_5GHZ)
1094 rate.index -= IWL_FIRST_OFDM_RATE;
1095 mac_flags = info->status.rates[0].flags;
1096 mac_index = info->status.rates[0].idx;
1097 /* For HT packets, map MCS to PLCP */
1098 if (mac_flags & IEEE80211_TX_RC_MCS) {
1099 /* Remove # of streams */
1100 mac_index &= RATE_HT_MCS_RATE_CODE_MSK;
1101 if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
1102 mac_index++;
1103 /*
1104 * mac80211 HT index is always zero-indexed; we need to move
1105 * HT OFDM rates after CCK rates in 2.4 GHz band
1106 */
1107 if (info->band == IEEE80211_BAND_2GHZ)
1108 mac_index += IWL_FIRST_OFDM_RATE;
1109 } else if (mac_flags & IEEE80211_TX_RC_VHT_MCS) {
1110 mac_index &= RATE_VHT_MCS_RATE_CODE_MSK;
1111 if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
1112 mac_index++;
1113 }
1114
1115 if (time_after(jiffies, 1079 if (time_after(jiffies,
1116 (unsigned long)(lq_sta->last_tx + 1080 (unsigned long)(lq_sta->last_tx +
1117 (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) { 1081 (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
@@ -1126,21 +1090,24 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1126 } 1090 }
1127 lq_sta->last_tx = jiffies; 1091 lq_sta->last_tx = jiffies;
1128 1092
1093 /* Ignore this Tx frame response if its initial rate doesn't match
1094 * that of latest Link Quality command. There may be stragglers
1095 * from a previous Link Quality command, but we're no longer interested
1096 * in those; they're either from the "active" mode while we're trying
1097 * to check "search" mode, or a prior "search" mode after we've moved
1098 * to a new "search" mode (which might become the new "active" mode).
1099 */
1100 table = &lq_sta->lq;
1101 lq_hwrate = le32_to_cpu(table->rs_table[0]);
1102 rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate);
1103 rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate);
1104
1129 /* Here we actually compare this rate to the latest LQ command */ 1105 /* Here we actually compare this rate to the latest LQ command */
1130 if ((mac_index < 0) || 1106 if (!rs_rate_equal(&tx_resp_rate, &lq_rate)) {
1131 (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
1132 (rate.bw != rs_ch_width_from_mac_flags(mac_flags)) ||
1133 (rate.ant != info->status.antenna) ||
1134 (!!(ucode_rate & RATE_MCS_HT_MSK) !=
1135 !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
1136 (!!(ucode_rate & RATE_MCS_VHT_MSK) !=
1137 !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) ||
1138 (!!(ucode_rate & RATE_HT_MCS_GF_MSK) !=
1139 !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
1140 (rate.index != mac_index)) {
1141 IWL_DEBUG_RATE(mvm, 1107 IWL_DEBUG_RATE(mvm,
1142 "initial rate %d does not match %d (0x%x)\n", 1108 "initial tx resp rate 0x%x does not match 0x%x\n",
1143 mac_index, rate.index, ucode_rate); 1109 tx_resp_hwrate, lq_hwrate);
1110
1144 /* 1111 /*
1145 * Since rates mis-match, the last LQ command may have failed. 1112 * Since rates mis-match, the last LQ command may have failed.
1146 * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with 1113 * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
@@ -1168,14 +1135,14 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1168 other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); 1135 other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
1169 } 1136 }
1170 1137
1171 if (WARN_ON_ONCE(!rs_rate_match(&rate, &curr_tbl->rate))) { 1138 if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
1172 IWL_DEBUG_RATE(mvm, 1139 IWL_DEBUG_RATE(mvm,
1173 "Neither active nor search matches tx rate\n"); 1140 "Neither active nor search matches tx rate\n");
1174 tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); 1141 tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
1175 rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE"); 1142 rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
1176 tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); 1143 tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
1177 rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH"); 1144 rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
1178 rs_dump_rate(mvm, &rate, "ACTUAL"); 1145 rs_dump_rate(mvm, &lq_rate, "ACTUAL");
1179 1146
1180 /* 1147 /*
1181 * no matching table found, let's by-pass the data collection 1148 * no matching table found, let's by-pass the data collection
@@ -1200,9 +1167,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1200 if (info->status.ampdu_ack_len == 0) 1167 if (info->status.ampdu_ack_len == 0)
1201 info->status.ampdu_len = 1; 1168 info->status.ampdu_len = 1;
1202 1169
1203 ucode_rate = le32_to_cpu(table->rs_table[0]); 1170 rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index,
1204 rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
1205 rs_collect_tx_data(mvm, lq_sta, curr_tbl, rate.index,
1206 info->status.ampdu_len, 1171 info->status.ampdu_len,
1207 info->status.ampdu_ack_len, 1172 info->status.ampdu_ack_len,
1208 reduced_txp); 1173 reduced_txp);
@@ -1225,21 +1190,23 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1225 legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); 1190 legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
1226 /* Collect data for each rate used during failed TX attempts */ 1191 /* Collect data for each rate used during failed TX attempts */
1227 for (i = 0; i <= retries; ++i) { 1192 for (i = 0; i <= retries; ++i) {
1228 ucode_rate = le32_to_cpu(table->rs_table[i]); 1193 lq_hwrate = le32_to_cpu(table->rs_table[i]);
1229 rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); 1194 rs_rate_from_ucode_rate(lq_hwrate, info->band,
1195 &lq_rate);
1230 /* 1196 /*
1231 * Only collect stats if retried rate is in the same RS 1197 * Only collect stats if retried rate is in the same RS
1232 * table as active/search. 1198 * table as active/search.
1233 */ 1199 */
1234 if (rs_rate_match(&rate, &curr_tbl->rate)) 1200 if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
1235 tmp_tbl = curr_tbl; 1201 tmp_tbl = curr_tbl;
1236 else if (rs_rate_match(&rate, &other_tbl->rate)) 1202 else if (rs_rate_column_match(&lq_rate,
1203 &other_tbl->rate))
1237 tmp_tbl = other_tbl; 1204 tmp_tbl = other_tbl;
1238 else 1205 else
1239 continue; 1206 continue;
1240 1207
1241 rs_collect_tx_data(mvm, lq_sta, tmp_tbl, rate.index, 1, 1208 rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index,
1242 i < retries ? 0 : legacy_success, 1209 1, i < retries ? 0 : legacy_success,
1243 reduced_txp); 1210 reduced_txp);
1244 } 1211 }
1245 1212
@@ -1250,7 +1217,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
1250 } 1217 }
1251 } 1218 }
1252 /* The last TX rate is cached in lq_sta; it's set in if/else above */ 1219 /* The last TX rate is cached in lq_sta; it's set in if/else above */
1253 lq_sta->last_rate_n_flags = ucode_rate; 1220 lq_sta->last_rate_n_flags = lq_hwrate;
1254 IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); 1221 IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
1255done: 1222done:
1256 /* See if there's a better rate or modulation mode to try. */ 1223 /* See if there's a better rate or modulation mode to try. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 07304e1fd64a..7906b97c81b9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -664,6 +664,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
664 info->status.rates[0].count = tx_resp->failure_frame + 1; 664 info->status.rates[0].count = tx_resp->failure_frame + 1;
665 iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), 665 iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
666 info); 666 info);
667 info->status.status_driver_data[1] =
668 (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
667 669
668 /* Single frame failure in an AMPDU queue => send BAR */ 670 /* Single frame failure in an AMPDU queue => send BAR */
669 if (txq_id >= mvm->first_agg_queue && 671 if (txq_id >= mvm->first_agg_queue &&
@@ -909,6 +911,8 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info,
909 info->status.tx_time = tid_data->tx_time; 911 info->status.tx_time = tid_data->tx_time;
910 info->status.status_driver_data[0] = 912 info->status.status_driver_data[0] =
911 (void *)(uintptr_t)tid_data->reduced_tpc; 913 (void *)(uintptr_t)tid_data->reduced_tpc;
914 info->status.status_driver_data[1] =
915 (void *)(uintptr_t)tid_data->rate_n_flags;
912} 916}
913 917
914int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, 918int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,