aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDaniel C Halperin <daniel.c.halperin@intel.com>2009-09-17 13:43:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:34 -0400
commite3949d62861b3fdef19e80080d670aa1153a23c4 (patch)
tree2c0b584b4f42cb0e762dca8cbf280cf50b290fe4 /drivers/net/wireless
parent91a55ae60168847c3c8ab348f10d517407052b71 (diff)
iwlwifi: add aggregation tables to the rate scaling algorithm
Current rate scale algorithm fluctuates between different MIMO modes fairly rapidly, causing widely varying performance. These fluctuations occur because in the rate_scale tables for expected throughput the values are not very different for different modes. However, when aggregation is turned on and MAC overhead is reduced, the expected throughput for different MIMO modes grows and different modes have vastly different performance. Add expected throughput tables for this case. We also need to keep track of aggregation status per-station, so we add the "is_agg" field to struct lq_sta. Also includes cleanup of comments and variable names in/around the affected code. 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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c223
1 files changed, 115 insertions, 108 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index cd24763d5fde..e6c35e07f41b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -171,6 +171,8 @@ struct iwl_lq_sta {
171 int last_txrate_idx; 171 int last_txrate_idx;
172 /* last tx rate_n_flags */ 172 /* last tx rate_n_flags */
173 u32 last_rate_n_flags; 173 u32 last_rate_n_flags;
174 /* packets destined for this STA are aggregated */
175 u8 is_agg;
174}; 176};
175 177
176static void rs_rate_scale_perform(struct iwl_priv *priv, 178static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -190,84 +192,78 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
190{} 192{}
191#endif 193#endif
192 194
193/* 195/**
194 * Expected throughput metrics for following rates: 196 * The following tables contain the expected throughput metrics for all rates
195 * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits 197 *
196 * "G" is the only table that supports CCK (the first 4 rates). 198 * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
199 *
200 * where invalid entries are zeros.
201 *
202 * CCK rates are only valid in legacy table and will only be used in G
203 * (2.4 GHz) band.
197 */ 204 */
198 205
199static s32 expected_tpt_A[IWL_RATE_COUNT] = { 206static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
200 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 207 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
201};
202
203static s32 expected_tpt_G[IWL_RATE_COUNT] = {
204 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186
205};
206
207static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = {
208 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202
209};
210
211static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = {
212 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211
213};
214
215static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = {
216 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251
217};
218
219static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = {
220 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257
221}; 208};
222 209
223static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { 210static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
224 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 211 {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */
212 {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */
213 {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */
214 {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
225}; 215};
226 216
227static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { 217static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
228 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 218 {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
219 {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
220 {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
221 {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
229}; 222};
230 223
231static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { 224static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
232 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 225 {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
226 {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
227 {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
228 {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
233}; 229};
234 230
235static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { 231static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
236 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 232 {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
233 {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
234 {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
235 {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
237}; 236};
238 237
239/* Expected throughput metric MIMO3 */ 238static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
240static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { 239 {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */
241 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 240 {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */
241 {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */
242 {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */
242}; 243};
243 244
244static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { 245static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
245 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 246 {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */
246}; 247 {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */
247 248 {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */
248static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { 249 {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */
249 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297
250};
251
252static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = {
253 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300
254}; 250};
255 251
256/* mbps, mcs */ 252/* mbps, mcs */
257const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { 253const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
258 {"1", ""}, 254 { "1", "BPSK DSSS"},
259 {"2", ""}, 255 { "2", "QPSK DSSS"},
260 {"5.5", ""}, 256 {"5.5", "BPSK CCK"},
261 {"11", ""}, 257 { "11", "QPSK CCK"},
262 {"6", "BPSK 1/2"}, 258 { "6", "BPSK 1/2"},
263 {"9", "BPSK 1/2"}, 259 { "9", "BPSK 1/2"},
264 {"12", "QPSK 1/2"}, 260 { "12", "QPSK 1/2"},
265 {"18", "QPSK 3/4"}, 261 { "18", "QPSK 3/4"},
266 {"24", "16QAM 1/2"}, 262 { "24", "16QAM 1/2"},
267 {"36", "16QAM 3/4"}, 263 { "36", "16QAM 3/4"},
268 {"48", "64QAM 2/3"}, 264 { "48", "64QAM 2/3"},
269 {"54", "64QAM 3/4"}, 265 { "54", "64QAM 3/4"},
270 {"60", "64QAM 5/6"} 266 { "60", "64QAM 5/6"},
271}; 267};
272 268
273#define MCS_INDEX_PER_STREAM (8) 269#define MCS_INDEX_PER_STREAM (8)
@@ -444,7 +440,7 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
444 * packets. 440 * packets.
445 */ 441 */
446static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, 442static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
447 int scale_index, s32 tpt, int retries, 443 int scale_index, s32 tpt, int attempts,
448 int successes) 444 int successes)
449{ 445{
450 struct iwl_rate_scale_data *window = NULL; 446 struct iwl_rate_scale_data *window = NULL;
@@ -454,7 +450,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
454 if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) 450 if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
455 return -EINVAL; 451 return -EINVAL;
456 452
457 /* Select data for current tx bit rate */ 453 /* Select window for current tx bit rate */
458 window = &(windows[scale_index]); 454 window = &(windows[scale_index]);
459 455
460 /* 456 /*
@@ -465,7 +461,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
465 * subtract "1" from the success counter (this is the main reason 461 * subtract "1" from the success counter (this is the main reason
466 * we keep these bitmaps!). 462 * we keep these bitmaps!).
467 */ 463 */
468 while (retries > 0) { 464 while (attempts > 0) {
469 if (window->counter >= IWL_RATE_MAX_WINDOW) { 465 if (window->counter >= IWL_RATE_MAX_WINDOW) {
470 466
471 /* remove earliest */ 467 /* remove earliest */
@@ -480,17 +476,17 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
480 /* Increment frames-attempted counter */ 476 /* Increment frames-attempted counter */
481 window->counter++; 477 window->counter++;
482 478
483 /* Shift bitmap by one frame (throw away oldest history), 479 /* Shift bitmap by one frame to throw away oldest history */
484 * OR in "1", and increment "success" if this
485 * frame was successful. */
486 window->data <<= 1; 480 window->data <<= 1;
481
482 /* Mark the most recent #successes attempts as successful */
487 if (successes > 0) { 483 if (successes > 0) {
488 window->success_counter++; 484 window->success_counter++;
489 window->data |= 0x1; 485 window->data |= 0x1;
490 successes--; 486 successes--;
491 } 487 }
492 488
493 retries--; 489 attempts--;
494 } 490 }
495 491
496 /* Calculate current success ratio, avoid divide-by-0! */ 492 /* Calculate current success ratio, avoid divide-by-0! */
@@ -868,12 +864,11 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
868 info->flags & IEEE80211_TX_CTL_NO_ACK) 864 info->flags & IEEE80211_TX_CTL_NO_ACK)
869 return; 865 return;
870 866
871 /* This packet was aggregated but doesn't carry rate scale info */ 867 /* This packet was aggregated but doesn't carry status info */
872 if ((info->flags & IEEE80211_TX_CTL_AMPDU) && 868 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
873 !(info->flags & IEEE80211_TX_STAT_AMPDU)) 869 !(info->flags & IEEE80211_TX_STAT_AMPDU))
874 return; 870 return;
875 871
876
877 if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && 872 if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
878 !lq_sta->ibss_sta_added) 873 !lq_sta->ibss_sta_added)
879 return; 874 return;
@@ -1052,43 +1047,45 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
1052static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, 1047static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1053 struct iwl_scale_tbl_info *tbl) 1048 struct iwl_scale_tbl_info *tbl)
1054{ 1049{
1050 /* Used to choose among HT tables */
1051 s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
1052
1053 /* Check for invalid LQ type */
1054 if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
1055 tbl->expected_tpt = expected_tpt_legacy;
1056 return;
1057 }
1058
1059 /* Legacy rates have only one table */
1055 if (is_legacy(tbl->lq_type)) { 1060 if (is_legacy(tbl->lq_type)) {
1056 if (!is_a_band(tbl->lq_type)) 1061 tbl->expected_tpt = expected_tpt_legacy;
1057 tbl->expected_tpt = expected_tpt_G; 1062 return;
1058 else 1063 }
1059 tbl->expected_tpt = expected_tpt_A; 1064
1060 } else if (is_siso(tbl->lq_type)) { 1065 /* Choose among many HT tables depending on number of streams
1061 if (tbl->is_ht40 && !lq_sta->is_dup) 1066 * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation
1062 if (tbl->is_SGI) 1067 * status */
1063 tbl->expected_tpt = expected_tpt_siso40MHzSGI; 1068 if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
1064 else 1069 ht_tbl_pointer = expected_tpt_siso20MHz;
1065 tbl->expected_tpt = expected_tpt_siso40MHz; 1070 else if (is_siso(tbl->lq_type))
1066 else if (tbl->is_SGI) 1071 ht_tbl_pointer = expected_tpt_siso40MHz;
1067 tbl->expected_tpt = expected_tpt_siso20MHzSGI; 1072 else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
1068 else 1073 ht_tbl_pointer = expected_tpt_mimo2_20MHz;
1069 tbl->expected_tpt = expected_tpt_siso20MHz; 1074 else if (is_mimo2(tbl->lq_type))
1070 } else if (is_mimo2(tbl->lq_type)) { 1075 ht_tbl_pointer = expected_tpt_mimo2_40MHz;
1071 if (tbl->is_ht40 && !lq_sta->is_dup) 1076 else if (is_mimo3(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
1072 if (tbl->is_SGI) 1077 ht_tbl_pointer = expected_tpt_mimo3_20MHz;
1073 tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; 1078 else /* if (is_mimo3(tbl->lq_type)) <-- must be true */
1074 else 1079 ht_tbl_pointer = expected_tpt_mimo3_40MHz;
1075 tbl->expected_tpt = expected_tpt_mimo2_40MHz; 1080
1076 else if (tbl->is_SGI) 1081 if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */
1077 tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; 1082 tbl->expected_tpt = ht_tbl_pointer[0];
1078 else 1083 else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */
1079 tbl->expected_tpt = expected_tpt_mimo2_20MHz; 1084 tbl->expected_tpt = ht_tbl_pointer[1];
1080 } else if (is_mimo3(tbl->lq_type)) { 1085 else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */
1081 if (tbl->is_ht40 && !lq_sta->is_dup) 1086 tbl->expected_tpt = ht_tbl_pointer[2];
1082 if (tbl->is_SGI) 1087 else /* AGG+SGI */
1083 tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; 1088 tbl->expected_tpt = ht_tbl_pointer[3];
1084 else
1085 tbl->expected_tpt = expected_tpt_mimo3_40MHz;
1086 else if (tbl->is_SGI)
1087 tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI;
1088 else
1089 tbl->expected_tpt = expected_tpt_mimo3_20MHz;
1090 } else
1091 tbl->expected_tpt = expected_tpt_G;
1092} 1089}
1093 1090
1094/* 1091/*
@@ -2063,6 +2060,14 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2063 lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; 2060 lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
2064 2061
2065 tid = rs_tl_add_packet(lq_sta, hdr); 2062 tid = rs_tl_add_packet(lq_sta, hdr);
2063 if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
2064 tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
2065 if (tid_data->agg.state == IWL_AGG_OFF)
2066 lq_sta->is_agg = 0;
2067 else
2068 lq_sta->is_agg = 1;
2069 } else
2070 lq_sta->is_agg = 0;
2066 2071
2067 /* 2072 /*
2068 * Select rate-scale / modulation-mode table to work with in 2073 * Select rate-scale / modulation-mode table to work with in
@@ -2163,10 +2168,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2163 2168
2164 goto out; 2169 goto out;
2165 } 2170 }
2166
2167 /* Else we have enough samples; calculate estimate of 2171 /* Else we have enough samples; calculate estimate of
2168 * actual average throughput */ 2172 * actual average throughput */
2169 2173
2174 /* Sanity-check TPT calculations */
2170 BUG_ON(window->average_tpt != ((window->success_ratio * 2175 BUG_ON(window->average_tpt != ((window->success_ratio *
2171 tbl->expected_tpt[index] + 64) / 128)); 2176 tbl->expected_tpt[index] + 64) / 128));
2172 2177
@@ -2676,6 +2681,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
2676 lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); 2681 lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
2677 if (sband->band == IEEE80211_BAND_5GHZ) 2682 if (sband->band == IEEE80211_BAND_5GHZ)
2678 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; 2683 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
2684 lq_sta->is_agg = 0;
2679 2685
2680 rs_initialize_lq(priv, conf, sta, lq_sta); 2686 rs_initialize_lq(priv, conf, sta, lq_sta);
2681} 2687}
@@ -2928,8 +2934,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
2928 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); 2934 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
2929 desc += sprintf(buff+desc, " %s", 2935 desc += sprintf(buff+desc, " %s",
2930 (tbl->is_ht40) ? "40MHz" : "20MHz"); 2936 (tbl->is_ht40) ? "40MHz" : "20MHz");
2931 desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", 2937 desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "",
2932 (lq_sta->is_green) ? "GF enabled" : ""); 2938 (lq_sta->is_green) ? "GF enabled" : "",
2939 (lq_sta->is_agg) ? "AGG on" : "");
2933 } 2940 }
2934 desc += sprintf(buff+desc, "last tx rate=0x%X\n", 2941 desc += sprintf(buff+desc, "last tx rate=0x%X\n",
2935 lq_sta->last_rate_n_flags); 2942 lq_sta->last_rate_n_flags);