diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 609 |
1 files changed, 252 insertions, 357 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 81726ee32858..1460116d329f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/wireless.h> | 30 | #include <linux/wireless.h> |
30 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
31 | 32 | ||
@@ -75,104 +76,6 @@ static const u8 ant_toggle_lookup[] = { | |||
75 | /*ANT_ABC -> */ ANT_ABC, | 76 | /*ANT_ABC -> */ ANT_ABC, |
76 | }; | 77 | }; |
77 | 78 | ||
78 | /** | ||
79 | * struct iwl_rate_scale_data -- tx success history for one rate | ||
80 | */ | ||
81 | struct iwl_rate_scale_data { | ||
82 | u64 data; /* bitmap of successful frames */ | ||
83 | s32 success_counter; /* number of frames successful */ | ||
84 | s32 success_ratio; /* per-cent * 128 */ | ||
85 | s32 counter; /* number of frames attempted */ | ||
86 | s32 average_tpt; /* success ratio * expected throughput */ | ||
87 | unsigned long stamp; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | ||
92 | * | ||
93 | * There are two of these in struct iwl_lq_sta, | ||
94 | * one for "active", and one for "search". | ||
95 | */ | ||
96 | struct iwl_scale_tbl_info { | ||
97 | enum iwl_table_type lq_type; | ||
98 | u8 ant_type; | ||
99 | u8 is_SGI; /* 1 = short guard interval */ | ||
100 | u8 is_ht40; /* 1 = 40 MHz channel width */ | ||
101 | u8 is_dup; /* 1 = duplicated data streams */ | ||
102 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | ||
103 | u8 max_search; /* maximun number of tables we can search */ | ||
104 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | ||
105 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
106 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | ||
107 | }; | ||
108 | |||
109 | struct iwl_traffic_load { | ||
110 | unsigned long time_stamp; /* age of the oldest statistics */ | ||
111 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | ||
112 | * slice */ | ||
113 | u32 total; /* total num of packets during the | ||
114 | * last TID_MAX_TIME_DIFF */ | ||
115 | u8 queue_count; /* number of queues that has | ||
116 | * been used since the last cleanup */ | ||
117 | u8 head; /* start of the circular buffer */ | ||
118 | }; | ||
119 | |||
120 | /** | ||
121 | * struct iwl_lq_sta -- driver's rate scaling private structure | ||
122 | * | ||
123 | * Pointer to this gets passed back and forth between driver and mac80211. | ||
124 | */ | ||
125 | struct iwl_lq_sta { | ||
126 | u8 active_tbl; /* index of active table, range 0-1 */ | ||
127 | u8 enable_counter; /* indicates HT mode */ | ||
128 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | ||
129 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | ||
130 | s32 last_tpt; | ||
131 | |||
132 | /* The following determine when to search for a new mode */ | ||
133 | u32 table_count_limit; | ||
134 | u32 max_failure_limit; /* # failed frames before new search */ | ||
135 | u32 max_success_limit; /* # successful frames before new search */ | ||
136 | u32 table_count; | ||
137 | u32 total_failed; /* total failed frames, any/all rates */ | ||
138 | u32 total_success; /* total successful frames, any/all rates */ | ||
139 | u64 flush_timer; /* time staying in mode before new search */ | ||
140 | |||
141 | u8 action_counter; /* # mode-switch actions tried */ | ||
142 | u8 is_green; | ||
143 | u8 is_dup; | ||
144 | enum ieee80211_band band; | ||
145 | u8 ibss_sta_added; | ||
146 | |||
147 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | ||
148 | u32 supp_rates; | ||
149 | u16 active_legacy_rate; | ||
150 | u16 active_siso_rate; | ||
151 | u16 active_mimo2_rate; | ||
152 | u16 active_mimo3_rate; | ||
153 | u16 active_rate_basic; | ||
154 | s8 max_rate_idx; /* Max rate set by user */ | ||
155 | u8 missed_rate_counter; | ||
156 | |||
157 | struct iwl_link_quality_cmd lq; | ||
158 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | ||
159 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | ||
160 | u8 tx_agg_tid_en; | ||
161 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
162 | struct dentry *rs_sta_dbgfs_scale_table_file; | ||
163 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
164 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
165 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | ||
166 | u32 dbg_fixed_rate; | ||
167 | #endif | ||
168 | struct iwl_priv *drv; | ||
169 | |||
170 | /* used to be in sta_info */ | ||
171 | int last_txrate_idx; | ||
172 | /* last tx rate_n_flags */ | ||
173 | u32 last_rate_n_flags; | ||
174 | }; | ||
175 | |||
176 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 79 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
177 | struct sk_buff *skb, | 80 | struct sk_buff *skb, |
178 | struct ieee80211_sta *sta, | 81 | struct ieee80211_sta *sta, |
@@ -190,84 +93,78 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
190 | {} | 93 | {} |
191 | #endif | 94 | #endif |
192 | 95 | ||
193 | /* | 96 | /** |
194 | * Expected throughput metrics for following rates: | 97 | * 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 | 98 | * |
196 | * "G" is the only table that supports CCK (the first 4 rates). | 99 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits |
100 | * | ||
101 | * where invalid entries are zeros. | ||
102 | * | ||
103 | * CCK rates are only valid in legacy table and will only be used in G | ||
104 | * (2.4 GHz) band. | ||
197 | */ | 105 | */ |
198 | 106 | ||
199 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { | 107 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { |
200 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 | 108 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0 |
201 | }; | ||
202 | |||
203 | static s32 expected_tpt_G[IWL_RATE_COUNT] = { | ||
204 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 | ||
205 | }; | ||
206 | |||
207 | static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { | ||
208 | 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 | ||
209 | }; | ||
210 | |||
211 | static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { | ||
212 | 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 | ||
213 | }; | ||
214 | |||
215 | static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { | ||
216 | 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 | ||
217 | }; | ||
218 | |||
219 | static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { | ||
220 | 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 | ||
221 | }; | ||
222 | |||
223 | static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { | ||
224 | 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 | ||
225 | }; | ||
226 | |||
227 | static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { | ||
228 | 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 | ||
229 | }; | 109 | }; |
230 | 110 | ||
231 | static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { | 111 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { |
232 | 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 | 112 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */ |
113 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */ | ||
114 | {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */ | ||
115 | {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */ | ||
233 | }; | 116 | }; |
234 | 117 | ||
235 | static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { | 118 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { |
236 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 | 119 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ |
120 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | ||
121 | {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */ | ||
122 | {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */ | ||
237 | }; | 123 | }; |
238 | 124 | ||
239 | /* Expected throughput metric MIMO3 */ | 125 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
240 | static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { | 126 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */ |
241 | 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 | 127 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */ |
128 | {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */ | ||
129 | {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/ | ||
242 | }; | 130 | }; |
243 | 131 | ||
244 | static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { | 132 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
245 | 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 | 133 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ |
134 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | ||
135 | {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */ | ||
136 | {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */ | ||
246 | }; | 137 | }; |
247 | 138 | ||
248 | static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { | 139 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { |
249 | 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 | 140 | {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */ |
141 | {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */ | ||
142 | {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */ | ||
143 | {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */ | ||
250 | }; | 144 | }; |
251 | 145 | ||
252 | static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { | 146 | static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { |
253 | 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 | 147 | {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */ |
148 | {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */ | ||
149 | {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */ | ||
150 | {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */ | ||
254 | }; | 151 | }; |
255 | 152 | ||
256 | /* mbps, mcs */ | 153 | /* mbps, mcs */ |
257 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 154 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
258 | {"1", ""}, | 155 | { "1", "BPSK DSSS"}, |
259 | {"2", ""}, | 156 | { "2", "QPSK DSSS"}, |
260 | {"5.5", ""}, | 157 | {"5.5", "BPSK CCK"}, |
261 | {"11", ""}, | 158 | { "11", "QPSK CCK"}, |
262 | {"6", "BPSK 1/2"}, | 159 | { "6", "BPSK 1/2"}, |
263 | {"9", "BPSK 1/2"}, | 160 | { "9", "BPSK 1/2"}, |
264 | {"12", "QPSK 1/2"}, | 161 | { "12", "QPSK 1/2"}, |
265 | {"18", "QPSK 3/4"}, | 162 | { "18", "QPSK 3/4"}, |
266 | {"24", "16QAM 1/2"}, | 163 | { "24", "16QAM 1/2"}, |
267 | {"36", "16QAM 3/4"}, | 164 | { "36", "16QAM 3/4"}, |
268 | {"48", "64QAM 2/3"}, | 165 | { "48", "64QAM 2/3"}, |
269 | {"54", "64QAM 3/4"}, | 166 | { "54", "64QAM 3/4"}, |
270 | {"60", "64QAM 5/6"} | 167 | { "60", "64QAM 5/6"}, |
271 | }; | 168 | }; |
272 | 169 | ||
273 | #define MCS_INDEX_PER_STREAM (8) | 170 | #define MCS_INDEX_PER_STREAM (8) |
@@ -402,10 +299,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
402 | struct iwl_lq_sta *lq_data, u8 tid, | 299 | struct iwl_lq_sta *lq_data, u8 tid, |
403 | struct ieee80211_sta *sta) | 300 | struct ieee80211_sta *sta) |
404 | { | 301 | { |
302 | int ret; | ||
303 | |||
405 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 304 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
406 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 305 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
407 | sta->addr, tid); | 306 | sta->addr, tid); |
408 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); | 307 | ret = ieee80211_start_tx_ba_session(sta, tid); |
308 | if (ret == -EAGAIN) { | ||
309 | /* | ||
310 | * driver and mac80211 is out of sync | ||
311 | * this might be cause by reloading firmware | ||
312 | * stop the tx ba session here | ||
313 | */ | ||
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | ||
315 | tid); | ||
316 | ret = ieee80211_stop_tx_ba_session(sta, tid, | ||
317 | WLAN_BACK_INITIATOR); | ||
318 | } | ||
409 | } | 319 | } |
410 | } | 320 | } |
411 | 321 | ||
@@ -436,6 +346,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
436 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
437 | } | 347 | } |
438 | 348 | ||
349 | /* | ||
350 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
351 | * that wraps a NULL pointer check | ||
352 | */ | ||
353 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
354 | { | ||
355 | if (tbl->expected_tpt) | ||
356 | return tbl->expected_tpt[rs_index]; | ||
357 | return 0; | ||
358 | } | ||
359 | |||
439 | /** | 360 | /** |
440 | * rs_collect_tx_data - Update the success/failure sliding window | 361 | * rs_collect_tx_data - Update the success/failure sliding window |
441 | * | 362 | * |
@@ -443,19 +364,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
443 | * at this rate. window->data contains the bitmask of successful | 364 | * at this rate. window->data contains the bitmask of successful |
444 | * packets. | 365 | * packets. |
445 | */ | 366 | */ |
446 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 367 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
447 | int scale_index, s32 tpt, int retries, | 368 | int scale_index, int attempts, int successes) |
448 | int successes) | ||
449 | { | 369 | { |
450 | struct iwl_rate_scale_data *window = NULL; | 370 | struct iwl_rate_scale_data *window = NULL; |
451 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 371 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
452 | s32 fail_count; | 372 | s32 fail_count, tpt; |
453 | 373 | ||
454 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 374 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
455 | return -EINVAL; | 375 | return -EINVAL; |
456 | 376 | ||
457 | /* Select data for current tx bit rate */ | 377 | /* Select window for current tx bit rate */ |
458 | window = &(windows[scale_index]); | 378 | window = &(tbl->win[scale_index]); |
379 | |||
380 | /* Get expected throughput */ | ||
381 | tpt = get_expected_tpt(tbl, scale_index); | ||
459 | 382 | ||
460 | /* | 383 | /* |
461 | * Keep track of only the latest 62 tx frame attempts in this rate's | 384 | * Keep track of only the latest 62 tx frame attempts in this rate's |
@@ -465,7 +388,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 | 388 | * subtract "1" from the success counter (this is the main reason |
466 | * we keep these bitmaps!). | 389 | * we keep these bitmaps!). |
467 | */ | 390 | */ |
468 | while (retries > 0) { | 391 | while (attempts > 0) { |
469 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | 392 | if (window->counter >= IWL_RATE_MAX_WINDOW) { |
470 | 393 | ||
471 | /* remove earliest */ | 394 | /* remove earliest */ |
@@ -480,17 +403,17 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
480 | /* Increment frames-attempted counter */ | 403 | /* Increment frames-attempted counter */ |
481 | window->counter++; | 404 | window->counter++; |
482 | 405 | ||
483 | /* Shift bitmap by one frame (throw away oldest history), | 406 | /* 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; | 407 | window->data <<= 1; |
408 | |||
409 | /* Mark the most recent #successes attempts as successful */ | ||
487 | if (successes > 0) { | 410 | if (successes > 0) { |
488 | window->success_counter++; | 411 | window->success_counter++; |
489 | window->data |= 0x1; | 412 | window->data |= 0x1; |
490 | successes--; | 413 | successes--; |
491 | } | 414 | } |
492 | 415 | ||
493 | retries--; | 416 | attempts--; |
494 | } | 417 | } |
495 | 418 | ||
496 | /* Calculate current success ratio, avoid divide-by-0! */ | 419 | /* Calculate current success ratio, avoid divide-by-0! */ |
@@ -671,7 +594,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
671 | * there are no non-GF stations present in the BSS. | 594 | * there are no non-GF stations present in the BSS. |
672 | */ | 595 | */ |
673 | static inline u8 rs_use_green(struct ieee80211_sta *sta, | 596 | static inline u8 rs_use_green(struct ieee80211_sta *sta, |
674 | struct iwl_ht_info *ht_conf) | 597 | struct iwl_ht_config *ht_conf) |
675 | { | 598 | { |
676 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 599 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
677 | !(ht_conf->non_GF_STA_present); | 600 | !(ht_conf->non_GF_STA_present); |
@@ -821,28 +744,34 @@ out: | |||
821 | } | 744 | } |
822 | 745 | ||
823 | /* | 746 | /* |
747 | * Simple function to compare two rate scale table types | ||
748 | */ | ||
749 | static bool table_type_matches(struct iwl_scale_tbl_info *a, | ||
750 | struct iwl_scale_tbl_info *b) | ||
751 | { | ||
752 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | ||
753 | (a->is_SGI == b->is_SGI); | ||
754 | } | ||
755 | |||
756 | /* | ||
824 | * mac80211 sends us Tx status | 757 | * mac80211 sends us Tx status |
825 | */ | 758 | */ |
826 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | 759 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
827 | struct ieee80211_sta *sta, void *priv_sta, | 760 | struct ieee80211_sta *sta, void *priv_sta, |
828 | struct sk_buff *skb) | 761 | struct sk_buff *skb) |
829 | { | 762 | { |
830 | int status; | 763 | int legacy_success; |
831 | u8 retries; | 764 | int retries; |
832 | int rs_index, mac_index, index = 0; | 765 | int rs_index, mac_index, i; |
833 | struct iwl_lq_sta *lq_sta = priv_sta; | 766 | struct iwl_lq_sta *lq_sta = priv_sta; |
834 | struct iwl_link_quality_cmd *table; | 767 | struct iwl_link_quality_cmd *table; |
835 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 768 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
836 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 769 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
837 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 770 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
838 | struct iwl_rate_scale_data *window = NULL; | ||
839 | struct iwl_rate_scale_data *search_win = NULL; | ||
840 | enum mac80211_rate_control_flags mac_flags; | 771 | enum mac80211_rate_control_flags mac_flags; |
841 | u32 tx_rate; | 772 | u32 tx_rate; |
842 | struct iwl_scale_tbl_info tbl_type; | 773 | struct iwl_scale_tbl_info tbl_type; |
843 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 774 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
844 | u8 active_index = 0; | ||
845 | s32 tpt = 0; | ||
846 | 775 | ||
847 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 776 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
848 | 777 | ||
@@ -850,30 +779,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
850 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 779 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
851 | return; | 780 | return; |
852 | 781 | ||
853 | /* This packet was aggregated but doesn't carry rate scale info */ | 782 | /* This packet was aggregated but doesn't carry status info */ |
854 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 783 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
855 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 784 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
856 | return; | 785 | return; |
857 | 786 | ||
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 | |||
866 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 787 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
867 | !lq_sta->ibss_sta_added) | 788 | !lq_sta->ibss_sta_added) |
868 | goto out; | 789 | 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 | 790 | ||
878 | /* | 791 | /* |
879 | * Ignore this Tx frame response if its initial rate doesn't match | 792 | * Ignore this Tx frame response if its initial rate doesn't match |
@@ -883,6 +796,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 | 796 | * 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). | 797 | * to a new "search" mode (which might become the new "active" mode). |
885 | */ | 798 | */ |
799 | table = &lq_sta->lq; | ||
886 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 800 | 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); | 801 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
888 | if (priv->band == IEEE80211_BAND_5GHZ) | 802 | if (priv->band == IEEE80211_BAND_5GHZ) |
@@ -901,7 +815,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
901 | if (priv->band == IEEE80211_BAND_2GHZ) | 815 | if (priv->band == IEEE80211_BAND_2GHZ) |
902 | mac_index += IWL_FIRST_OFDM_RATE; | 816 | mac_index += IWL_FIRST_OFDM_RATE; |
903 | } | 817 | } |
904 | 818 | /* Here we actually compare this rate to the latest LQ command */ | |
905 | if ((mac_index < 0) || | 819 | if ((mac_index < 0) || |
906 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 820 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
907 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 821 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || |
@@ -911,124 +825,98 @@ 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)) || | 825 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
912 | (rs_index != mac_index)) { | 826 | (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); | 827 | 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 | 828 | /* |
915 | * the same in driver sync up | 829 | * Since rates mis-match, the last LQ command may have failed. |
830 | * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with | ||
831 | * ... driver. | ||
916 | */ | 832 | */ |
917 | lq_sta->missed_rate_counter++; | 833 | lq_sta->missed_rate_counter++; |
918 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 834 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
919 | lq_sta->missed_rate_counter = 0; | 835 | lq_sta->missed_rate_counter = 0; |
920 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 836 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
921 | } | 837 | } |
922 | goto out; | 838 | /* Regardless, ignore this status info for outdated rate */ |
923 | } | 839 | return; |
924 | 840 | } else | |
925 | lq_sta->missed_rate_counter = 0; | 841 | /* Rate did match, so reset the missed_rate_counter */ |
926 | /* Update frame history window with "failure" for each Tx retry. */ | 842 | lq_sta->missed_rate_counter = 0; |
927 | while (retries) { | 843 | |
928 | /* Look up the rate and other info used for each tx attempt. | 844 | /* Figure out if rate scale algorithm is in active or search table */ |
929 | * Each tx attempt steps one entry deeper in the rate table. */ | 845 | if (table_type_matches(&tbl_type, |
930 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 846 | &(lq_sta->lq_info[lq_sta->active_tbl]))) { |
931 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | 847 | curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
932 | &tbl_type, &rs_index); | 848 | other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
933 | 849 | } else if (table_type_matches(&tbl_type, | |
934 | /* If type matches "search" table, | 850 | &lq_sta->lq_info[1 - lq_sta->active_tbl])) { |
935 | * add failure to "search" history */ | 851 | curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
936 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 852 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
937 | (tbl_type.ant_type == search_tbl->ant_type) && | 853 | } else { |
938 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 854 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
939 | if (search_tbl->expected_tpt) | 855 | return; |
940 | tpt = search_tbl->expected_tpt[rs_index]; | ||
941 | else | ||
942 | tpt = 0; | ||
943 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); | ||
944 | |||
945 | /* Else if type matches "current/active" table, | ||
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 | } | ||
956 | |||
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 | } | 856 | } |
965 | 857 | ||
966 | /* | 858 | /* |
967 | * Find (by rate) the history window to update with final Tx attempt; | 859 | * Updating the frame history depends on whether packets were |
968 | * if Tx was successful first try, use original rate, | 860 | * aggregated. |
969 | * else look up the rate that was, finally, successful. | 861 | * |
862 | * For aggregation, all packets were transmitted at the same rate, the | ||
863 | * first index into rate scale table. | ||
970 | */ | 864 | */ |
971 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 865 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
972 | lq_sta->last_rate_n_flags = tx_rate; | 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
973 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
974 | 868 | &rs_index); | |
975 | /* Update frame history window with "success" if Tx got ACKed ... */ | 869 | rs_collect_tx_data(curr_tbl, rs_index, |
976 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); | 870 | info->status.ampdu_ack_len, |
977 | 871 | info->status.ampdu_ack_map); | |
978 | /* If type matches "search" table, | 872 | |
979 | * add final tx status to "search" history */ | 873 | /* Update success/fail counts if not searching for new mode */ |
980 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 874 | if (lq_sta->stay_in_tbl) { |
981 | (tbl_type.ant_type == search_tbl->ant_type) && | ||
982 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | ||
983 | if (search_tbl->expected_tpt) | ||
984 | tpt = search_tbl->expected_tpt[rs_index]; | ||
985 | else | ||
986 | tpt = 0; | ||
987 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
988 | rs_collect_tx_data(search_win, rs_index, tpt, | ||
989 | info->status.ampdu_ack_len, | ||
990 | info->status.ampdu_ack_map); | ||
991 | else | ||
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 | |||
1012 | /* If not searching for new mode, increment success/failed counter | ||
1013 | * ... these help determine when to start searching again */ | ||
1014 | if (lq_sta->stay_in_tbl) { | ||
1015 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | ||
1016 | lq_sta->total_success += info->status.ampdu_ack_map; | 875 | lq_sta->total_success += info->status.ampdu_ack_map; |
1017 | lq_sta->total_failed += | 876 | lq_sta->total_failed += (info->status.ampdu_ack_len - |
1018 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | 877 | info->status.ampdu_ack_map); |
1019 | } else { | 878 | } |
1020 | if (status) | 879 | } else { |
1021 | lq_sta->total_success++; | 880 | /* |
881 | * For legacy, update frame history with for each Tx retry. | ||
882 | */ | ||
883 | retries = info->status.rates[0].count - 1; | ||
884 | /* HW doesn't send more than 15 retries */ | ||
885 | retries = min(retries, 15); | ||
886 | |||
887 | /* The last transmission may have been successful */ | ||
888 | legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); | ||
889 | /* Collect data for each rate used during failed TX attempts */ | ||
890 | for (i = 0; i <= retries; ++i) { | ||
891 | tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags); | ||
892 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | ||
893 | &tbl_type, &rs_index); | ||
894 | /* | ||
895 | * Only collect stats if retried rate is in the same RS | ||
896 | * table as active/search. | ||
897 | */ | ||
898 | if (table_type_matches(&tbl_type, curr_tbl)) | ||
899 | tmp_tbl = curr_tbl; | ||
900 | else if (table_type_matches(&tbl_type, other_tbl)) | ||
901 | tmp_tbl = other_tbl; | ||
1022 | else | 902 | else |
1023 | lq_sta->total_failed++; | 903 | continue; |
904 | rs_collect_tx_data(tmp_tbl, rs_index, 1, | ||
905 | i < retries ? 0 : legacy_success); | ||
906 | } | ||
907 | |||
908 | /* Update success/fail counts if not searching for new mode */ | ||
909 | if (lq_sta->stay_in_tbl) { | ||
910 | lq_sta->total_success += legacy_success; | ||
911 | lq_sta->total_failed += retries + (1 - legacy_success); | ||
1024 | } | 912 | } |
1025 | } | 913 | } |
914 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | ||
915 | lq_sta->last_rate_n_flags = tx_rate; | ||
1026 | 916 | ||
1027 | /* See if there's a better rate or modulation mode to try. */ | 917 | /* See if there's a better rate or modulation mode to try. */ |
1028 | if (sta && sta->supp_rates[sband->band]) | 918 | if (sta && sta->supp_rates[sband->band]) |
1029 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 919 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
1030 | out: | ||
1031 | return; | ||
1032 | } | 920 | } |
1033 | 921 | ||
1034 | /* | 922 | /* |
@@ -1066,43 +954,45 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, | |||
1066 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | 954 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
1067 | struct iwl_scale_tbl_info *tbl) | 955 | struct iwl_scale_tbl_info *tbl) |
1068 | { | 956 | { |
957 | /* Used to choose among HT tables */ | ||
958 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | ||
959 | |||
960 | /* Check for invalid LQ type */ | ||
961 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { | ||
962 | tbl->expected_tpt = expected_tpt_legacy; | ||
963 | return; | ||
964 | } | ||
965 | |||
966 | /* Legacy rates have only one table */ | ||
1069 | if (is_legacy(tbl->lq_type)) { | 967 | if (is_legacy(tbl->lq_type)) { |
1070 | if (!is_a_band(tbl->lq_type)) | 968 | tbl->expected_tpt = expected_tpt_legacy; |
1071 | tbl->expected_tpt = expected_tpt_G; | 969 | return; |
1072 | else | 970 | } |
1073 | tbl->expected_tpt = expected_tpt_A; | 971 | |
1074 | } else if (is_siso(tbl->lq_type)) { | 972 | /* Choose among many HT tables depending on number of streams |
1075 | if (tbl->is_ht40 && !lq_sta->is_dup) | 973 | * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation |
1076 | if (tbl->is_SGI) | 974 | * status */ |
1077 | tbl->expected_tpt = expected_tpt_siso40MHzSGI; | 975 | if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1078 | else | 976 | ht_tbl_pointer = expected_tpt_siso20MHz; |
1079 | tbl->expected_tpt = expected_tpt_siso40MHz; | 977 | else if (is_siso(tbl->lq_type)) |
1080 | else if (tbl->is_SGI) | 978 | ht_tbl_pointer = expected_tpt_siso40MHz; |
1081 | tbl->expected_tpt = expected_tpt_siso20MHzSGI; | 979 | else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1082 | else | 980 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; |
1083 | tbl->expected_tpt = expected_tpt_siso20MHz; | 981 | else if (is_mimo2(tbl->lq_type)) |
1084 | } else if (is_mimo2(tbl->lq_type)) { | 982 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; |
1085 | if (tbl->is_ht40 && !lq_sta->is_dup) | 983 | else if (is_mimo3(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1086 | if (tbl->is_SGI) | 984 | ht_tbl_pointer = expected_tpt_mimo3_20MHz; |
1087 | tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; | 985 | else /* if (is_mimo3(tbl->lq_type)) <-- must be true */ |
1088 | else | 986 | ht_tbl_pointer = expected_tpt_mimo3_40MHz; |
1089 | tbl->expected_tpt = expected_tpt_mimo2_40MHz; | 987 | |
1090 | else if (tbl->is_SGI) | 988 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
1091 | tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; | 989 | tbl->expected_tpt = ht_tbl_pointer[0]; |
1092 | else | 990 | else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */ |
1093 | tbl->expected_tpt = expected_tpt_mimo2_20MHz; | 991 | tbl->expected_tpt = ht_tbl_pointer[1]; |
1094 | } else if (is_mimo3(tbl->lq_type)) { | 992 | else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */ |
1095 | if (tbl->is_ht40 && !lq_sta->is_dup) | 993 | tbl->expected_tpt = ht_tbl_pointer[2]; |
1096 | if (tbl->is_SGI) | 994 | else /* AGG+SGI */ |
1097 | tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; | 995 | tbl->expected_tpt = ht_tbl_pointer[3]; |
1098 | else | ||
1099 | tbl->expected_tpt = expected_tpt_mimo3_40MHz; | ||
1100 | else if (tbl->is_SGI) | ||
1101 | tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; | ||
1102 | else | ||
1103 | tbl->expected_tpt = expected_tpt_mimo3_20MHz; | ||
1104 | } else | ||
1105 | tbl->expected_tpt = expected_tpt_G; | ||
1106 | } | 996 | } |
1107 | 997 | ||
1108 | /* | 998 | /* |
@@ -2077,6 +1967,14 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2077 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | 1967 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
2078 | 1968 | ||
2079 | tid = rs_tl_add_packet(lq_sta, hdr); | 1969 | tid = rs_tl_add_packet(lq_sta, hdr); |
1970 | if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { | ||
1971 | tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; | ||
1972 | if (tid_data->agg.state == IWL_AGG_OFF) | ||
1973 | lq_sta->is_agg = 0; | ||
1974 | else | ||
1975 | lq_sta->is_agg = 1; | ||
1976 | } else | ||
1977 | lq_sta->is_agg = 0; | ||
2080 | 1978 | ||
2081 | /* | 1979 | /* |
2082 | * Select rate-scale / modulation-mode table to work with in | 1980 | * Select rate-scale / modulation-mode table to work with in |
@@ -2177,10 +2075,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2177 | 2075 | ||
2178 | goto out; | 2076 | goto out; |
2179 | } | 2077 | } |
2180 | |||
2181 | /* Else we have enough samples; calculate estimate of | 2078 | /* Else we have enough samples; calculate estimate of |
2182 | * actual average throughput */ | 2079 | * actual average throughput */ |
2183 | 2080 | ||
2081 | /* Sanity-check TPT calculations */ | ||
2184 | BUG_ON(window->average_tpt != ((window->success_ratio * | 2082 | BUG_ON(window->average_tpt != ((window->success_ratio * |
2185 | tbl->expected_tpt[index] + 64) / 128)); | 2083 | tbl->expected_tpt[index] + 64) / 128)); |
2186 | 2084 | ||
@@ -2584,22 +2482,13 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2584 | gfp_t gfp) | 2482 | gfp_t gfp) |
2585 | { | 2483 | { |
2586 | struct iwl_lq_sta *lq_sta; | 2484 | struct iwl_lq_sta *lq_sta; |
2485 | struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2587 | struct iwl_priv *priv; | 2486 | struct iwl_priv *priv; |
2588 | int i, j; | ||
2589 | 2487 | ||
2590 | priv = (struct iwl_priv *)priv_rate; | 2488 | priv = (struct iwl_priv *)priv_rate; |
2591 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); | 2489 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); |
2592 | 2490 | ||
2593 | lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); | 2491 | lq_sta = &sta_priv->lq_sta; |
2594 | |||
2595 | if (lq_sta == NULL) | ||
2596 | return NULL; | ||
2597 | lq_sta->lq.sta_id = 0xff; | ||
2598 | |||
2599 | |||
2600 | for (j = 0; j < LQ_SIZE; j++) | ||
2601 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2602 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2603 | 2492 | ||
2604 | return lq_sta; | 2493 | return lq_sta; |
2605 | } | 2494 | } |
@@ -2613,6 +2502,12 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2613 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2502 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2614 | struct iwl_lq_sta *lq_sta = priv_sta; | 2503 | struct iwl_lq_sta *lq_sta = priv_sta; |
2615 | 2504 | ||
2505 | lq_sta->lq.sta_id = 0xff; | ||
2506 | |||
2507 | for (j = 0; j < LQ_SIZE; j++) | ||
2508 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2509 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2510 | |||
2616 | lq_sta->flush_timer = 0; | 2511 | lq_sta->flush_timer = 0; |
2617 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2512 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2618 | for (j = 0; j < LQ_SIZE; j++) | 2513 | for (j = 0; j < LQ_SIZE; j++) |
@@ -2690,6 +2585,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2690 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); | 2585 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); |
2691 | if (sband->band == IEEE80211_BAND_5GHZ) | 2586 | if (sband->band == IEEE80211_BAND_5GHZ) |
2692 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2587 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2588 | lq_sta->is_agg = 0; | ||
2693 | 2589 | ||
2694 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2590 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2695 | } | 2591 | } |
@@ -2808,7 +2704,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2808 | repeat_rate--; | 2704 | repeat_rate--; |
2809 | } | 2705 | } |
2810 | 2706 | ||
2811 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; | 2707 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2812 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2708 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
2813 | lq_cmd->agg_params.agg_time_limit = | 2709 | lq_cmd->agg_params.agg_time_limit = |
2814 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2710 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
@@ -2827,11 +2723,9 @@ static void rs_free(void *priv_rate) | |||
2827 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, | 2723 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, |
2828 | void *priv_sta) | 2724 | void *priv_sta) |
2829 | { | 2725 | { |
2830 | struct iwl_lq_sta *lq_sta = priv_sta; | ||
2831 | struct iwl_priv *priv __maybe_unused = priv_r; | 2726 | struct iwl_priv *priv __maybe_unused = priv_r; |
2832 | 2727 | ||
2833 | IWL_DEBUG_RATE(priv, "enter\n"); | 2728 | IWL_DEBUG_RATE(priv, "enter\n"); |
2834 | kfree(lq_sta); | ||
2835 | IWL_DEBUG_RATE(priv, "leave\n"); | 2729 | IWL_DEBUG_RATE(priv, "leave\n"); |
2836 | } | 2730 | } |
2837 | 2731 | ||
@@ -2942,8 +2836,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2942 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | 2836 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); |
2943 | desc += sprintf(buff+desc, " %s", | 2837 | desc += sprintf(buff+desc, " %s", |
2944 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2838 | (tbl->is_ht40) ? "40MHz" : "20MHz"); |
2945 | desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", | 2839 | desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "", |
2946 | (lq_sta->is_green) ? "GF enabled" : ""); | 2840 | (lq_sta->is_green) ? "GF enabled" : "", |
2841 | (lq_sta->is_agg) ? "AGG on" : ""); | ||
2947 | } | 2842 | } |
2948 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 2843 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
2949 | lq_sta->last_rate_n_flags); | 2844 | lq_sta->last_rate_n_flags); |
@@ -3076,16 +2971,16 @@ static void rs_add_debugfs(void *priv, void *priv_sta, | |||
3076 | { | 2971 | { |
3077 | struct iwl_lq_sta *lq_sta = priv_sta; | 2972 | struct iwl_lq_sta *lq_sta = priv_sta; |
3078 | lq_sta->rs_sta_dbgfs_scale_table_file = | 2973 | lq_sta->rs_sta_dbgfs_scale_table_file = |
3079 | debugfs_create_file("rate_scale_table", 0600, dir, | 2974 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, |
3080 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 2975 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
3081 | lq_sta->rs_sta_dbgfs_stats_table_file = | 2976 | lq_sta->rs_sta_dbgfs_stats_table_file = |
3082 | debugfs_create_file("rate_stats_table", 0600, dir, | 2977 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
3083 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 2978 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
3084 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = | 2979 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = |
3085 | debugfs_create_file("rate_scale_data", 0600, dir, | 2980 | debugfs_create_file("rate_scale_data", S_IRUSR, dir, |
3086 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); | 2981 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); |
3087 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 2982 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
3088 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, | 2983 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, |
3089 | &lq_sta->tx_agg_tid_en); | 2984 | &lq_sta->tx_agg_tid_en); |
3090 | 2985 | ||
3091 | } | 2986 | } |