blob: bf637aa7ddab98df94843fb84479be6455952ace [file] [log] [blame]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001/*
2 * Copyright (c) 2004 Video54 Technologies, Inc.
3 * Copyright (c) 2004-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * Atheros rate control algorithm
20 */
21
22#include "core.h"
Johannes Berg4b7679a2008-09-18 18:14:18 +020023/* FIXME: remove this include! */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070024#include "../net/mac80211/rate.h"
25
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070026static struct ath_rate_table ar5416_11na_ratetable = {
27 42,
Sujithe63835b2008-11-18 09:07:53 +053028 {0},
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070029 {
30 { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
31 5400, 0x0b, 0x00, 12,
32 0, 2, 1, 0, 0, 0, 0, 0 },
33 { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
34 7800, 0x0f, 0x00, 18,
35 0, 3, 1, 1, 1, 1, 1, 0 },
36 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
37 10000, 0x0a, 0x00, 24,
38 2, 4, 2, 2, 2, 2, 2, 0 },
39 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
40 13900, 0x0e, 0x00, 36,
41 2, 6, 2, 3, 3, 3, 3, 0 },
42 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
43 17300, 0x09, 0x00, 48,
44 4, 10, 3, 4, 4, 4, 4, 0 },
45 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
46 23000, 0x0d, 0x00, 72,
47 4, 14, 3, 5, 5, 5, 5, 0 },
48 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
49 27400, 0x08, 0x00, 96,
50 4, 20, 3, 6, 6, 6, 6, 0 },
51 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
52 29300, 0x0c, 0x00, 108,
53 4, 23, 3, 7, 7, 7, 7, 0 },
54 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
55 6400, 0x80, 0x00, 0,
56 0, 2, 3, 8, 24, 8, 24, 3216 },
57 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
58 12700, 0x81, 0x00, 1,
59 2, 4, 3, 9, 25, 9, 25, 6434 },
60 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
61 18800, 0x82, 0x00, 2,
62 2, 6, 3, 10, 26, 10, 26, 9650 },
63 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
64 25000, 0x83, 0x00, 3,
65 4, 10, 3, 11, 27, 11, 27, 12868 },
66 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
67 36700, 0x84, 0x00, 4,
68 4, 14, 3, 12, 28, 12, 28, 19304 },
69 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
70 48100, 0x85, 0x00, 5,
71 4, 20, 3, 13, 29, 13, 29, 25740 },
72 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
73 53500, 0x86, 0x00, 6,
74 4, 23, 3, 14, 30, 14, 30, 28956 },
75 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
76 59000, 0x87, 0x00, 7,
77 4, 25, 3, 15, 31, 15, 32, 32180 },
78 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
79 12700, 0x88, 0x00,
80 8, 0, 2, 3, 16, 33, 16, 33, 6430 },
81 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
82 24800, 0x89, 0x00, 9,
83 2, 4, 3, 17, 34, 17, 34, 12860 },
84 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
85 36600, 0x8a, 0x00, 10,
86 2, 6, 3, 18, 35, 18, 35, 19300 },
87 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
88 48100, 0x8b, 0x00, 11,
89 4, 10, 3, 19, 36, 19, 36, 25736 },
90 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
91 69500, 0x8c, 0x00, 12,
92 4, 14, 3, 20, 37, 20, 37, 38600 },
93 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
94 89500, 0x8d, 0x00, 13,
95 4, 20, 3, 21, 38, 21, 38, 51472 },
96 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
97 98900, 0x8e, 0x00, 14,
98 4, 23, 3, 22, 39, 22, 39, 57890 },
99 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
100 108300, 0x8f, 0x00, 15,
101 4, 25, 3, 23, 40, 23, 41, 64320 },
102 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
103 13200, 0x80, 0x00, 0,
104 0, 2, 3, 8, 24, 24, 24, 6684 },
105 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
106 25900, 0x81, 0x00, 1,
107 2, 4, 3, 9, 25, 25, 25, 13368 },
108 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
109 38600, 0x82, 0x00, 2,
110 2, 6, 3, 10, 26, 26, 26, 20052 },
111 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
112 49800, 0x83, 0x00, 3,
113 4, 10, 3, 11, 27, 27, 27, 26738 },
114 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
115 72200, 0x84, 0x00, 4,
116 4, 14, 3, 12, 28, 28, 28, 40104 },
117 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
118 92900, 0x85, 0x00, 5,
119 4, 20, 3, 13, 29, 29, 29, 53476 },
120 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
121 102700, 0x86, 0x00, 6,
122 4, 23, 3, 14, 30, 30, 30, 60156 },
123 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
124 112000, 0x87, 0x00, 7,
125 4, 25, 3, 15, 31, 32, 32, 66840 },
126 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
127 122000, 0x87, 0x00, 7,
128 4, 25, 3, 15, 31, 32, 32, 74200 },
129 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
130 25800, 0x88, 0x00, 8,
131 0, 2, 3, 16, 33, 33, 33, 13360 },
132 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
133 49800, 0x89, 0x00, 9,
134 2, 4, 3, 17, 34, 34, 34, 26720 },
135 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
136 71900, 0x8a, 0x00, 10,
137 2, 6, 3, 18, 35, 35, 35, 40080 },
138 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
139 92500, 0x8b, 0x00, 11,
140 4, 10, 3, 19, 36, 36, 36, 53440 },
141 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
142 130300, 0x8c, 0x00, 12,
143 4, 14, 3, 20, 37, 37, 37, 80160 },
144 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
145 162800, 0x8d, 0x00, 13,
146 4, 20, 3, 21, 38, 38, 38, 106880 },
147 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
148 178200, 0x8e, 0x00, 14,
149 4, 23, 3, 22, 39, 39, 39, 120240 },
150 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
151 192100, 0x8f, 0x00, 15,
152 4, 25, 3, 23, 40, 41, 41, 133600 },
153 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
154 207000, 0x8f, 0x00, 15,
155 4, 25, 3, 23, 40, 41, 41, 148400 },
156 },
157 50, /* probe interval */
158 50, /* rssi reduce interval */
159 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
160};
161
162/* TRUE_ALL - valid for 20/40/Legacy,
163 * TRUE - Legacy only,
164 * TRUE_20 - HT 20 only,
165 * TRUE_40 - HT 40 only */
166
167/* 4ms frame limit not used for NG mode. The values filled
168 * for HT are the 64K max aggregate limit */
169
170static struct ath_rate_table ar5416_11ng_ratetable = {
171 46,
Sujithe63835b2008-11-18 09:07:53 +0530172 {0},
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700173 {
174 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */
175 900, 0x1b, 0x00, 2,
176 0, 0, 1, 0, 0, 0, 0, 0 },
177 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */
178 1900, 0x1a, 0x04, 4,
179 1, 1, 1, 1, 1, 1, 1, 0 },
180 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
181 4900, 0x19, 0x04, 11,
182 2, 2, 2, 2, 2, 2, 2, 0 },
183 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */
184 8100, 0x18, 0x04, 22,
185 3, 3, 2, 3, 3, 3, 3, 0 },
186 { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
187 5400, 0x0b, 0x00, 12,
188 4, 2, 1, 4, 4, 4, 4, 0 },
189 { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
190 7800, 0x0f, 0x00, 18,
191 4, 3, 1, 5, 5, 5, 5, 0 },
192 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
193 10100, 0x0a, 0x00, 24,
194 6, 4, 1, 6, 6, 6, 6, 0 },
195 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
196 14100, 0x0e, 0x00, 36,
197 6, 6, 2, 7, 7, 7, 7, 0 },
198 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
199 17700, 0x09, 0x00, 48,
200 8, 10, 3, 8, 8, 8, 8, 0 },
201 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
202 23700, 0x0d, 0x00, 72,
203 8, 14, 3, 9, 9, 9, 9, 0 },
204 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
205 27400, 0x08, 0x00, 96,
206 8, 20, 3, 10, 10, 10, 10, 0 },
207 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
208 30900, 0x0c, 0x00, 108,
209 8, 23, 3, 11, 11, 11, 11, 0 },
210 { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
211 6400, 0x80, 0x00, 0,
212 4, 2, 3, 12, 28, 12, 28, 3216 },
213 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
214 12700, 0x81, 0x00, 1,
215 6, 4, 3, 13, 29, 13, 29, 6434 },
216 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
217 18800, 0x82, 0x00, 2,
218 6, 6, 3, 14, 30, 14, 30, 9650 },
219 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
220 25000, 0x83, 0x00, 3,
221 8, 10, 3, 15, 31, 15, 31, 12868 },
222 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
223 36700, 0x84, 0x00, 4,
224 8, 14, 3, 16, 32, 16, 32, 19304 },
225 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
226 48100, 0x85, 0x00, 5,
227 8, 20, 3, 17, 33, 17, 33, 25740 },
228 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
229 53500, 0x86, 0x00, 6,
230 8, 23, 3, 18, 34, 18, 34, 28956 },
231 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
232 59000, 0x87, 0x00, 7,
233 8, 25, 3, 19, 35, 19, 36, 32180 },
234 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
235 12700, 0x88, 0x00, 8,
236 4, 2, 3, 20, 37, 20, 37, 6430 },
237 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
238 24800, 0x89, 0x00, 9,
239 6, 4, 3, 21, 38, 21, 38, 12860 },
240 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
241 36600, 0x8a, 0x00, 10,
242 6, 6, 3, 22, 39, 22, 39, 19300 },
243 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
244 48100, 0x8b, 0x00, 11,
245 8, 10, 3, 23, 40, 23, 40, 25736 },
246 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
247 69500, 0x8c, 0x00, 12,
248 8, 14, 3, 24, 41, 24, 41, 38600 },
249 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
250 89500, 0x8d, 0x00, 13,
251 8, 20, 3, 25, 42, 25, 42, 51472 },
252 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
253 98900, 0x8e, 0x00, 14,
254 8, 23, 3, 26, 43, 26, 44, 57890 },
255 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
256 108300, 0x8f, 0x00, 15,
257 8, 25, 3, 27, 44, 27, 45, 64320 },
258 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
259 13200, 0x80, 0x00, 0,
260 8, 2, 3, 12, 28, 28, 28, 6684 },
261 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
262 25900, 0x81, 0x00, 1,
263 8, 4, 3, 13, 29, 29, 29, 13368 },
264 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
265 38600, 0x82, 0x00, 2,
266 8, 6, 3, 14, 30, 30, 30, 20052 },
267 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
268 49800, 0x83, 0x00, 3,
269 8, 10, 3, 15, 31, 31, 31, 26738 },
270 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
271 72200, 0x84, 0x00, 4,
272 8, 14, 3, 16, 32, 32, 32, 40104 },
273 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
274 92900, 0x85, 0x00, 5,
275 8, 20, 3, 17, 33, 33, 33, 53476 },
276 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
277 102700, 0x86, 0x00, 6,
278 8, 23, 3, 18, 34, 34, 34, 60156 },
279 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
280 112000, 0x87, 0x00, 7,
281 8, 23, 3, 19, 35, 36, 36, 66840 },
282 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
283 122000, 0x87, 0x00, 7,
284 8, 25, 3, 19, 35, 36, 36, 74200 },
285 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
286 25800, 0x88, 0x00, 8,
287 8, 2, 3, 20, 37, 37, 37, 13360 },
288 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
289 49800, 0x89, 0x00, 9,
290 8, 4, 3, 21, 38, 38, 38, 26720 },
291 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
292 71900, 0x8a, 0x00, 10,
293 8, 6, 3, 22, 39, 39, 39, 40080 },
294 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
295 92500, 0x8b, 0x00, 11,
296 8, 10, 3, 23, 40, 40, 40, 53440 },
297 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
298 130300, 0x8c, 0x00, 12,
299 8, 14, 3, 24, 41, 41, 41, 80160 },
300 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
301 162800, 0x8d, 0x00, 13,
302 8, 20, 3, 25, 42, 42, 42, 106880 },
303 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
304 178200, 0x8e, 0x00, 14,
305 8, 23, 3, 26, 43, 43, 43, 120240 },
306 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
307 192100, 0x8f, 0x00, 15,
308 8, 23, 3, 27, 44, 45, 45, 133600 },
309 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
310 207000, 0x8f, 0x00, 15,
311 8, 25, 3, 27, 44, 45, 45, 148400 },
312 },
313 50, /* probe interval */
314 50, /* rssi reduce interval */
315 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
316};
317
318static struct ath_rate_table ar5416_11a_ratetable = {
319 8,
Sujithe63835b2008-11-18 09:07:53 +0530320 {0},
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700321 {
322 { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
323 5400, 0x0b, 0x00, (0x80|12),
324 0, 2, 1, 0, 0 },
325 { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
326 7800, 0x0f, 0x00, 18,
327 0, 3, 1, 1, 0 },
328 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
329 10000, 0x0a, 0x00, (0x80|24),
330 2, 4, 2, 2, 0 },
331 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
332 13900, 0x0e, 0x00, 36,
333 2, 6, 2, 3, 0 },
334 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
335 17300, 0x09, 0x00, (0x80|48),
336 4, 10, 3, 4, 0 },
337 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
338 23000, 0x0d, 0x00, 72,
339 4, 14, 3, 5, 0 },
340 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
341 27400, 0x08, 0x00, 96,
342 4, 19, 3, 6, 0 },
343 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
344 29300, 0x0c, 0x00, 108,
345 4, 23, 3, 7, 0 },
346 },
347 50, /* probe interval */
348 50, /* rssi reduce interval */
349 0, /* Phy rates allowed initially */
350};
351
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700352static struct ath_rate_table ar5416_11g_ratetable = {
353 12,
Sujithe63835b2008-11-18 09:07:53 +0530354 {0},
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700355 {
356 { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
357 900, 0x1b, 0x00, 2,
358 0, 0, 1, 0, 0 },
359 { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
360 1900, 0x1a, 0x04, 4,
361 1, 1, 1, 1, 0 },
362 { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
363 4900, 0x19, 0x04, 11,
364 2, 2, 2, 2, 0 },
365 { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
366 8100, 0x18, 0x04, 22,
367 3, 3, 2, 3, 0 },
368 { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
369 5400, 0x0b, 0x00, 12,
370 4, 2, 1, 4, 0 },
371 { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
372 7800, 0x0f, 0x00, 18,
373 4, 3, 1, 5, 0 },
374 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
375 10000, 0x0a, 0x00, 24,
376 6, 4, 1, 6, 0 },
377 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
378 13900, 0x0e, 0x00, 36,
379 6, 6, 2, 7, 0 },
380 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
381 17300, 0x09, 0x00, 48,
382 8, 10, 3, 8, 0 },
383 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
384 23000, 0x0d, 0x00, 72,
385 8, 14, 3, 9, 0 },
386 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
387 27400, 0x08, 0x00, 96,
388 8, 19, 3, 10, 0 },
389 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
390 29300, 0x0c, 0x00, 108,
391 8, 23, 3, 11, 0 },
392 },
393 50, /* probe interval */
394 50, /* rssi reduce interval */
395 0, /* Phy rates allowed initially */
396};
397
398static struct ath_rate_table ar5416_11b_ratetable = {
399 4,
Sujithe63835b2008-11-18 09:07:53 +0530400 {0},
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700401 {
402 { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
403 900, 0x1b, 0x00, (0x80|2),
404 0, 0, 1, 0, 0 },
405 { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
406 1800, 0x1a, 0x04, (0x80|4),
407 1, 1, 1, 1, 0 },
408 { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
409 4300, 0x19, 0x04, (0x80|11),
410 1, 2, 2, 2, 0 },
411 { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
412 7100, 0x18, 0x04, (0x80|22),
413 1, 4, 100, 3, 0 },
414 },
415 100, /* probe interval */
416 100, /* rssi reduce interval */
417 0, /* Phy rates allowed initially */
418};
419
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700420/*
421 * Return the median of three numbers
422 */
423static inline int8_t median(int8_t a, int8_t b, int8_t c)
424{
425 if (a >= b) {
426 if (b >= c)
427 return b;
428 else if (a > c)
429 return c;
430 else
431 return a;
432 } else {
433 if (a >= c)
434 return a;
435 else if (b >= c)
436 return c;
437 else
438 return b;
439 }
440}
441
Sujithfe7f4a72008-11-18 09:07:06 +0530442static void ath_rc_sort_validrates(struct ath_rate_table *rate_table,
Sujith256b7752008-11-18 09:03:12 +0530443 struct ath_rate_node *ath_rc_priv)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700444{
445 u8 i, j, idx, idx_next;
446
Sujith256b7752008-11-18 09:03:12 +0530447 for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700448 for (j = 0; j <= i-1; j++) {
Sujith256b7752008-11-18 09:03:12 +0530449 idx = ath_rc_priv->valid_rate_index[j];
450 idx_next = ath_rc_priv->valid_rate_index[j+1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700451
452 if (rate_table->info[idx].ratekbps >
453 rate_table->info[idx_next].ratekbps) {
Sujith256b7752008-11-18 09:03:12 +0530454 ath_rc_priv->valid_rate_index[j] = idx_next;
455 ath_rc_priv->valid_rate_index[j+1] = idx;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700456 }
457 }
458 }
459}
460
461/* Access functions for valid_txrate_mask */
462
Sujith256b7752008-11-18 09:03:12 +0530463static void ath_rc_init_valid_txmask(struct ath_rate_node *ath_rc_priv)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700464{
465 u8 i;
466
Sujith256b7752008-11-18 09:03:12 +0530467 for (i = 0; i < ath_rc_priv->rate_table_size; i++)
468 ath_rc_priv->valid_rate_index[i] = FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700469}
470
Sujith256b7752008-11-18 09:03:12 +0530471static inline void ath_rc_set_valid_txmask(struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700472 u8 index, int valid_tx_rate)
473{
Sujith256b7752008-11-18 09:03:12 +0530474 ASSERT(index <= ath_rc_priv->rate_table_size);
475 ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700476}
477
Sujith256b7752008-11-18 09:03:12 +0530478static inline int ath_rc_isvalid_txmask(struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700479 u8 index)
480{
Sujith256b7752008-11-18 09:03:12 +0530481 ASSERT(index <= ath_rc_priv->rate_table_size);
482 return ath_rc_priv->valid_rate_index[index];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700483}
484
485/* Iterators for valid_txrate_mask */
486static inline int
Sujithfe7f4a72008-11-18 09:07:06 +0530487ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
Sujith256b7752008-11-18 09:03:12 +0530488 struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700489 u8 cur_valid_txrate,
490 u8 *next_idx)
491{
492 u8 i;
493
Sujith256b7752008-11-18 09:03:12 +0530494 for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
495 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
496 *next_idx = ath_rc_priv->valid_rate_index[i+1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700497 return TRUE;
498 }
499 }
500
501 /* No more valid rates */
502 *next_idx = 0;
503 return FALSE;
504}
505
506/* Return true only for single stream */
507
508static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
509{
510 if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG))
511 return FALSE;
512 if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
513 return FALSE;
514 if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
515 return FALSE;
516 if (!ignore_cw && WLAN_RC_PHY_HT(phy))
517 if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
518 return FALSE;
519 if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
520 return FALSE;
521 return TRUE;
522}
523
524static inline int
Sujithfe7f4a72008-11-18 09:07:06 +0530525ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
Sujith256b7752008-11-18 09:03:12 +0530526 struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700527 u8 cur_valid_txrate, u8 *next_idx)
528{
529 int8_t i;
530
Sujith256b7752008-11-18 09:03:12 +0530531 for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
532 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
533 *next_idx = ath_rc_priv->valid_rate_index[i-1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700534 return TRUE;
535 }
536 }
537 return FALSE;
538}
539
540/*
541 * Initialize the Valid Rate Index from valid entries in Rate Table
542 */
543static u8
544ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530545 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700546 u32 capflag)
547{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700548 u8 i, hi = 0;
549 u32 valid;
550
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700551 for (i = 0; i < rate_table->rate_cnt; i++) {
552 valid = (ath_rc_priv->single_stream ?
Sujithdc2222a2008-08-14 13:26:55 +0530553 rate_table->info[i].valid_single_stream :
554 rate_table->info[i].valid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700555 if (valid == TRUE) {
556 u32 phy = rate_table->info[i].phy;
557 u8 valid_rate_count = 0;
558
559 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
560 continue;
561
Sujith256b7752008-11-18 09:03:12 +0530562 valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700563
Sujith256b7752008-11-18 09:03:12 +0530564 ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
565 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
566 ath_rc_set_valid_txmask(ath_rc_priv, i, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700567 hi = A_MAX(hi, i);
568 }
569 }
570 return hi;
571}
572
573/*
574 * Initialize the Valid Rate Index from Rate Set
575 */
576static u8
577ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530578 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700579 struct ath_rateset *rateset,
580 u32 capflag)
581{
582 /* XXX: Clean me up and make identation friendly */
583 u8 i, j, hi = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700584
585 /* Use intersection of working rates and valid rates */
586 for (i = 0; i < rateset->rs_nrates; i++) {
587 for (j = 0; j < rate_table->rate_cnt; j++) {
588 u32 phy = rate_table->info[j].phy;
589 u32 valid = (ath_rc_priv->single_stream ?
590 rate_table->info[j].valid_single_stream :
591 rate_table->info[j].valid);
592
593 /* We allow a rate only if its valid and the
594 * capflag matches one of the validity
595 * (TRUE/TRUE_20/TRUE_40) flags */
596
597 /* XXX: catch the negative of this branch
598 * first and then continue */
599 if (((rateset->rs_rates[i] & 0x7F) ==
600 (rate_table->info[j].dot11rate & 0x7F)) &&
601 ((valid & WLAN_RC_CAP_MODE(capflag)) ==
602 WLAN_RC_CAP_MODE(capflag)) &&
603 !WLAN_RC_PHY_HT(phy)) {
604
605 u8 valid_rate_count = 0;
606
607 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
608 continue;
609
610 valid_rate_count =
Sujith256b7752008-11-18 09:03:12 +0530611 ath_rc_priv->valid_phy_ratecnt[phy];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700612
Sujith256b7752008-11-18 09:03:12 +0530613 ath_rc_priv->valid_phy_rateidx[phy]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700614 [valid_rate_count] = j;
Sujith256b7752008-11-18 09:03:12 +0530615 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
616 ath_rc_set_valid_txmask(ath_rc_priv, j, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700617 hi = A_MAX(hi, j);
618 }
619 }
620 }
621 return hi;
622}
623
624static u8
625ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530626 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700627 u8 *mcs_set, u32 capflag)
628{
629 u8 i, j, hi = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700630
631 /* Use intersection of working rates and valid rates */
632 for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) {
633 for (j = 0; j < rate_table->rate_cnt; j++) {
634 u32 phy = rate_table->info[j].phy;
635 u32 valid = (ath_rc_priv->single_stream ?
Sujithdc2222a2008-08-14 13:26:55 +0530636 rate_table->info[j].valid_single_stream :
637 rate_table->info[j].valid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700638
639 if (((((struct ath_rateset *)
Sujithdc2222a2008-08-14 13:26:55 +0530640 mcs_set)->rs_rates[i] & 0x7F) !=
641 (rate_table->info[j].dot11rate & 0x7F)) ||
642 !WLAN_RC_PHY_HT(phy) ||
643 !WLAN_RC_PHY_HT_VALID(valid, capflag))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700644 continue;
645
646 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
647 continue;
648
Sujith256b7752008-11-18 09:03:12 +0530649 ath_rc_priv->valid_phy_rateidx[phy]
650 [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
651 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
652 ath_rc_set_valid_txmask(ath_rc_priv, j, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700653 hi = A_MAX(hi, j);
654 }
655 }
656 return hi;
657}
658
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700659u8 ath_rate_findrateix(struct ath_softc *sc,
Sujith102e0572008-10-29 10:15:16 +0530660 u8 dot11rate)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700661{
Sujithfe7f4a72008-11-18 09:07:06 +0530662 struct ath_rate_table *ratetable;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700663 int i;
664
Sujithfe7f4a72008-11-18 09:07:06 +0530665 ratetable = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700666
667 if (WARN_ON(!ratetable))
668 return 0;
669
670 for (i = 0; i < ratetable->rate_cnt; i++) {
671 if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f))
672 return i;
673 }
674
675 return 0;
676}
677
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700678static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
Sujithdc2222a2008-08-14 13:26:55 +0530679 struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530680 struct ath_rate_table *rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530681 int probe_allowed, int *is_probing,
682 int is_retry)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700683{
684 u32 dt, best_thruput, this_thruput, now_msec;
685 u8 rate, next_rate, best_rate, maxindex, minindex;
686 int8_t rssi_last, rssi_reduce = 0, index = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700687
688 *is_probing = FALSE;
689
Sujith256b7752008-11-18 09:03:12 +0530690 rssi_last = median(ath_rc_priv->rssi_last,
691 ath_rc_priv->rssi_last_prev,
692 ath_rc_priv->rssi_last_prev2);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700693
694 /*
695 * Age (reduce) last ack rssi based on how old it is.
696 * The bizarre numbers are so the delta is 160msec,
697 * meaning we divide by 16.
698 * 0msec <= dt <= 25msec: don't derate
699 * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB
700 * 185msec <= dt: derate by 10dB
701 */
702
703 now_msec = jiffies_to_msecs(jiffies);
Sujith256b7752008-11-18 09:03:12 +0530704 dt = now_msec - ath_rc_priv->rssi_time;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700705
706 if (dt >= 185)
707 rssi_reduce = 10;
708 else if (dt >= 25)
709 rssi_reduce = (u8)((dt - 25) >> 4);
710
711 /* Now reduce rssi_last by rssi_reduce */
712 if (rssi_last < rssi_reduce)
713 rssi_last = 0;
714 else
715 rssi_last -= rssi_reduce;
716
717 /*
718 * Now look up the rate in the rssi table and return it.
719 * If no rates match then we return 0 (lowest rate)
720 */
721
722 best_thruput = 0;
Sujith256b7752008-11-18 09:03:12 +0530723 maxindex = ath_rc_priv->max_valid_rate-1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700724
725 minindex = 0;
726 best_rate = minindex;
727
728 /*
729 * Try the higher rate first. It will reduce memory moving time
730 * if we have very good channel characteristics.
731 */
732 for (index = maxindex; index >= minindex ; index--) {
733 u8 per_thres;
734
Sujith256b7752008-11-18 09:03:12 +0530735 rate = ath_rc_priv->valid_rate_index[index];
736 if (rate > ath_rc_priv->rate_max_phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700737 continue;
738
739 /*
740 * For TCP the average collision rate is around 11%,
741 * so we ignore PERs less than this. This is to
742 * prevent the rate we are currently using (whose
743 * PER might be in the 10-15 range because of TCP
744 * collisions) looking worse than the next lower
745 * rate whose PER has decayed close to 0. If we
746 * used to next lower rate, its PER would grow to
747 * 10-15 and we would be worse off then staying
748 * at the current rate.
749 */
Sujith256b7752008-11-18 09:03:12 +0530750 per_thres = ath_rc_priv->state[rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700751 if (per_thres < 12)
752 per_thres = 12;
753
754 this_thruput = rate_table->info[rate].user_ratekbps *
755 (100 - per_thres);
756
757 if (best_thruput <= this_thruput) {
758 best_thruput = this_thruput;
759 best_rate = rate;
760 }
761 }
762
763 rate = best_rate;
764
765 /* if we are retrying for more than half the number
766 * of max retries, use the min rate for the next retry
767 */
768 if (is_retry)
Sujith256b7752008-11-18 09:03:12 +0530769 rate = ath_rc_priv->valid_rate_index[minindex];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700770
Sujith256b7752008-11-18 09:03:12 +0530771 ath_rc_priv->rssi_last_lookup = rssi_last;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700772
773 /*
774 * Must check the actual rate (ratekbps) to account for
775 * non-monoticity of 11g's rate table
776 */
777
Sujith256b7752008-11-18 09:03:12 +0530778 if (rate >= ath_rc_priv->rate_max_phy && probe_allowed) {
779 rate = ath_rc_priv->rate_max_phy;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700780
781 /* Probe the next allowed phy state */
782 /* FIXME:XXXX Check to make sure ratMax is checked properly */
783 if (ath_rc_get_nextvalid_txrate(rate_table,
Sujith256b7752008-11-18 09:03:12 +0530784 ath_rc_priv, rate, &next_rate) &&
785 (now_msec - ath_rc_priv->probe_time >
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700786 rate_table->probe_interval) &&
Sujith256b7752008-11-18 09:03:12 +0530787 (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700788 rate = next_rate;
Sujith256b7752008-11-18 09:03:12 +0530789 ath_rc_priv->probe_rate = rate;
790 ath_rc_priv->probe_time = now_msec;
791 ath_rc_priv->hw_maxretry_pktcnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700792 *is_probing = TRUE;
793 }
794 }
795
796 /*
797 * Make sure rate is not higher than the allowed maximum.
798 * We should also enforce the min, but I suspect the min is
799 * normally 1 rather than 0 because of the rate 9 vs 6 issue
800 * in the old code.
801 */
Sujith256b7752008-11-18 09:03:12 +0530802 if (rate > (ath_rc_priv->rate_table_size - 1))
803 rate = ath_rc_priv->rate_table_size - 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700804
805 ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
Sujithdc2222a2008-08-14 13:26:55 +0530806 (rate_table->info[rate].valid_single_stream &&
807 ath_rc_priv->single_stream));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700808
809 return rate;
810}
811
Sujithfe7f4a72008-11-18 09:07:06 +0530812static void ath_rc_rate_set_series(struct ath_rate_table *rate_table ,
Sujitha8efee42008-11-18 09:07:30 +0530813 struct ieee80211_tx_rate *rate,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700814 u8 tries,
815 u8 rix,
816 int rtsctsenable)
817{
Sujitha8efee42008-11-18 09:07:30 +0530818 rate->count = tries;
819 rate->idx = rix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700820
Sujitha8efee42008-11-18 09:07:30 +0530821 if (rtsctsenable)
822 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
823 if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
824 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
825 if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
826 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
827 if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
828 rate->flags |= IEEE80211_TX_RC_MCS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700829}
830
831static u8 ath_rc_rate_getidx(struct ath_softc *sc,
Sujithdc2222a2008-08-14 13:26:55 +0530832 struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530833 struct ath_rate_table *rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530834 u8 rix, u16 stepdown,
835 u16 min_rate)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700836{
837 u32 j;
838 u8 nextindex;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700839
840 if (min_rate) {
841 for (j = RATE_TABLE_SIZE; j > 0; j--) {
842 if (ath_rc_get_nextlowervalid_txrate(rate_table,
Sujith256b7752008-11-18 09:03:12 +0530843 ath_rc_priv, rix, &nextindex))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700844 rix = nextindex;
845 else
846 break;
847 }
848 } else {
849 for (j = stepdown; j > 0; j--) {
850 if (ath_rc_get_nextlowervalid_txrate(rate_table,
Sujith256b7752008-11-18 09:03:12 +0530851 ath_rc_priv, rix, &nextindex))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700852 rix = nextindex;
853 else
854 break;
855 }
856 }
857 return rix;
858}
859
860static void ath_rc_ratefind(struct ath_softc *sc,
861 struct ath_rate_node *ath_rc_priv,
862 int num_tries, int num_rates, unsigned int rcflag,
Sujitha8efee42008-11-18 09:07:30 +0530863 struct ieee80211_tx_info *tx_info, int *is_probe,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700864 int is_retry)
865{
866 u8 try_per_rate = 0, i = 0, rix, nrix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700867 struct ath_rate_table *rate_table;
Sujitha8efee42008-11-18 09:07:30 +0530868 struct ieee80211_tx_rate *rates = tx_info->control.rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700869
Sujithfe7f4a72008-11-18 09:07:06 +0530870 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700871 rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530872 (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
873 is_probe, is_retry);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700874 nrix = rix;
875
876 if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) {
877 /* set one try for probe rates. For the
878 * probes don't enable rts */
879 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530880 &rates[i++], 1, nrix, FALSE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700881
882 try_per_rate = (num_tries/num_rates);
883 /* Get the next tried/allowed rate. No RTS for the next series
884 * after the probe rate
885 */
886 nrix = ath_rc_rate_getidx(sc,
887 ath_rc_priv, rate_table, nrix, 1, FALSE);
888 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530889 &rates[i++], try_per_rate, nrix, 0);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700890 } else {
891 try_per_rate = (num_tries/num_rates);
892 /* Set the choosen rate. No RTS for first series entry. */
893 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530894 &rates[i++], try_per_rate, nrix, FALSE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700895 }
896
897 /* Fill in the other rates for multirate retry */
898 for ( ; i < num_rates; i++) {
899 u8 try_num;
900 u8 min_rate;
901
902 try_num = ((i + 1) == num_rates) ?
903 num_tries - (try_per_rate * i) : try_per_rate ;
904 min_rate = (((i + 1) == num_rates) &&
Sujithdc2222a2008-08-14 13:26:55 +0530905 (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700906
907 nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
Sujithdc2222a2008-08-14 13:26:55 +0530908 rate_table, nrix, 1, min_rate);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700909 /* All other rates in the series have RTS enabled */
910 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530911 &rates[i], try_num, nrix, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700912 }
913
914 /*
915 * NB:Change rate series to enable aggregation when operating
916 * at lower MCS rates. When first rate in series is MCS2
917 * in HT40 @ 2.4GHz, series should look like:
918 *
919 * {MCS2, MCS1, MCS0, MCS0}.
920 *
921 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
922 * look like:
923 *
924 * {MCS3, MCS2, MCS1, MCS1}
925 *
926 * So, set fourth rate in series to be same as third one for
927 * above conditions.
928 */
Sujith86b89ee2008-08-07 10:54:57 +0530929 if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
Sujithdc2222a2008-08-14 13:26:55 +0530930 (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
931 (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700932 u8 dot11rate = rate_table->info[rix].dot11rate;
933 u8 phy = rate_table->info[rix].phy;
934 if (i == 4 &&
935 ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
Sujithdc2222a2008-08-14 13:26:55 +0530936 (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
Sujitha8efee42008-11-18 09:07:30 +0530937 rates[3].idx = rates[2].idx;
938 rates[3].flags = rates[2].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700939 }
940 }
941}
942
943/*
944 * Return the Tx rate series.
945 */
Sujith5701ed82008-08-26 08:11:26 +0530946static void ath_rate_findrate(struct ath_softc *sc,
947 struct ath_rate_node *ath_rc_priv,
948 int num_tries,
949 int num_rates,
950 unsigned int rcflag,
Sujitha8efee42008-11-18 09:07:30 +0530951 struct ieee80211_tx_info *tx_info,
Sujith5701ed82008-08-26 08:11:26 +0530952 int *is_probe,
953 int is_retry)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700954{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700955 if (!num_rates || !num_tries)
956 return;
957
Sujith2b406f12008-11-18 09:05:35 +0530958 ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates,
Sujitha8efee42008-11-18 09:07:30 +0530959 rcflag, tx_info, is_probe, is_retry);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700960}
961
962static void ath_rc_update_ht(struct ath_softc *sc,
963 struct ath_rate_node *ath_rc_priv,
964 struct ath_tx_info_priv *info_priv,
965 int tx_rate, int xretries, int retries)
966{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700967 u32 now_msec = jiffies_to_msecs(jiffies);
968 int state_change = FALSE, rate, count;
969 u8 last_per;
Sujithfe7f4a72008-11-18 09:07:06 +0530970 struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700971 static u32 nretry_to_per_lookup[10] = {
972 100 * 0 / 1,
973 100 * 1 / 4,
974 100 * 1 / 2,
975 100 * 3 / 4,
976 100 * 4 / 5,
977 100 * 5 / 6,
978 100 * 6 / 7,
979 100 * 7 / 8,
980 100 * 8 / 9,
981 100 * 9 / 10
982 };
983
984 if (!ath_rc_priv)
985 return;
986
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700987 ASSERT(tx_rate >= 0);
988 if (tx_rate < 0)
989 return;
990
991 /* To compensate for some imbalance between ctrl and ext. channel */
992
993 if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
994 info_priv->tx.ts_rssi =
995 info_priv->tx.ts_rssi < 3 ? 0 :
996 info_priv->tx.ts_rssi - 3;
997
Sujith256b7752008-11-18 09:03:12 +0530998 last_per = ath_rc_priv->state[tx_rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700999
1000 if (xretries) {
1001 /* Update the PER. */
1002 if (xretries == 1) {
Sujith256b7752008-11-18 09:03:12 +05301003 ath_rc_priv->state[tx_rate].per += 30;
1004 if (ath_rc_priv->state[tx_rate].per > 100)
1005 ath_rc_priv->state[tx_rate].per = 100;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001006 } else {
1007 /* xretries == 2 */
Julia Lawall87c16872008-11-09 17:56:10 +01001008 count = ARRAY_SIZE(nretry_to_per_lookup);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001009 if (retries >= count)
1010 retries = count - 1;
1011 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
Sujith256b7752008-11-18 09:03:12 +05301012 ath_rc_priv->state[tx_rate].per =
1013 (u8)(ath_rc_priv->state[tx_rate].per -
1014 (ath_rc_priv->state[tx_rate].per >> 3) +
Sujithdc2222a2008-08-14 13:26:55 +05301015 ((100) >> 3));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001016 }
1017
1018 /* xretries == 1 or 2 */
1019
Sujith256b7752008-11-18 09:03:12 +05301020 if (ath_rc_priv->probe_rate == tx_rate)
1021 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001022
1023 } else { /* xretries == 0 */
1024 /* Update the PER. */
1025 /* Make sure it doesn't index out of array's bounds. */
Julia Lawall87c16872008-11-09 17:56:10 +01001026 count = ARRAY_SIZE(nretry_to_per_lookup);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001027 if (retries >= count)
1028 retries = count - 1;
1029 if (info_priv->n_bad_frames) {
Sujithdc2222a2008-08-14 13:26:55 +05301030 /* new_PER = 7/8*old_PER + 1/8*(currentPER)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001031 * Assuming that n_frames is not 0. The current PER
1032 * from the retries is 100 * retries / (retries+1),
1033 * since the first retries attempts failed, and the
1034 * next one worked. For the one that worked,
1035 * n_bad_frames subframes out of n_frames wored,
1036 * so the PER for that part is
1037 * 100 * n_bad_frames / n_frames, and it contributes
1038 * 100 * n_bad_frames / (n_frames * (retries+1)) to
1039 * the above PER. The expression below is a
1040 * simplified version of the sum of these two terms.
1041 */
1042 if (info_priv->n_frames > 0)
Sujith256b7752008-11-18 09:03:12 +05301043 ath_rc_priv->state[tx_rate].per
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001044 = (u8)
Sujith256b7752008-11-18 09:03:12 +05301045 (ath_rc_priv->state[tx_rate].per -
1046 (ath_rc_priv->state[tx_rate].per >> 3) +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001047 ((100*(retries*info_priv->n_frames +
1048 info_priv->n_bad_frames) /
1049 (info_priv->n_frames *
1050 (retries+1))) >> 3));
1051 } else {
1052 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
1053
Sujith256b7752008-11-18 09:03:12 +05301054 ath_rc_priv->state[tx_rate].per = (u8)
1055 (ath_rc_priv->state[tx_rate].per -
1056 (ath_rc_priv->state[tx_rate].per >> 3) +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001057 (nretry_to_per_lookup[retries] >> 3));
1058 }
1059
Sujith256b7752008-11-18 09:03:12 +05301060 ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
1061 ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last;
1062 ath_rc_priv->rssi_last = info_priv->tx.ts_rssi;
1063 ath_rc_priv->rssi_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001064
1065 /*
1066 * If we got at most one retry then increase the max rate if
1067 * this was a probe. Otherwise, ignore the probe.
1068 */
1069
Sujith256b7752008-11-18 09:03:12 +05301070 if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001071 if (retries > 0 || 2 * info_priv->n_bad_frames >
1072 info_priv->n_frames) {
1073 /*
1074 * Since we probed with just a single attempt,
1075 * any retries means the probe failed. Also,
1076 * if the attempt worked, but more than half
1077 * the subframes were bad then also consider
1078 * the probe a failure.
1079 */
Sujith256b7752008-11-18 09:03:12 +05301080 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001081 } else {
1082 u8 probe_rate = 0;
1083
Sujith256b7752008-11-18 09:03:12 +05301084 ath_rc_priv->rate_max_phy = ath_rc_priv->probe_rate;
1085 probe_rate = ath_rc_priv->probe_rate;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001086
Sujith256b7752008-11-18 09:03:12 +05301087 if (ath_rc_priv->state[probe_rate].per > 30)
1088 ath_rc_priv->state[probe_rate].per = 20;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001089
Sujith256b7752008-11-18 09:03:12 +05301090 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001091
1092 /*
1093 * Since this probe succeeded, we allow the next
1094 * probe twice as soon. This allows the maxRate
1095 * to move up faster if the probes are
1096 * succesful.
1097 */
Sujith256b7752008-11-18 09:03:12 +05301098 ath_rc_priv->probe_time = now_msec -
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001099 rate_table->probe_interval / 2;
1100 }
1101 }
1102
1103 if (retries > 0) {
1104 /*
1105 * Don't update anything. We don't know if
1106 * this was because of collisions or poor signal.
1107 *
1108 * Later: if rssi_ack is close to
Sujith256b7752008-11-18 09:03:12 +05301109 * ath_rc_priv->state[txRate].rssi_thres and we see lots
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001110 * of retries, then we could increase
Sujith256b7752008-11-18 09:03:12 +05301111 * ath_rc_priv->state[txRate].rssi_thres.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001112 */
Sujith256b7752008-11-18 09:03:12 +05301113 ath_rc_priv->hw_maxretry_pktcnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001114 } else {
1115 /*
1116 * It worked with no retries. First ignore bogus (small)
1117 * rssi_ack values.
1118 */
Sujith256b7752008-11-18 09:03:12 +05301119 if (tx_rate == ath_rc_priv->rate_max_phy &&
1120 ath_rc_priv->hw_maxretry_pktcnt < 255) {
1121 ath_rc_priv->hw_maxretry_pktcnt++;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001122 }
1123
1124 if (info_priv->tx.ts_rssi >=
1125 rate_table->info[tx_rate].rssi_ack_validmin) {
1126 /* Average the rssi */
Sujith256b7752008-11-18 09:03:12 +05301127 if (tx_rate != ath_rc_priv->rssi_sum_rate) {
1128 ath_rc_priv->rssi_sum_rate = tx_rate;
1129 ath_rc_priv->rssi_sum =
1130 ath_rc_priv->rssi_sum_cnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001131 }
1132
Sujith256b7752008-11-18 09:03:12 +05301133 ath_rc_priv->rssi_sum += info_priv->tx.ts_rssi;
1134 ath_rc_priv->rssi_sum_cnt++;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001135
Sujith256b7752008-11-18 09:03:12 +05301136 if (ath_rc_priv->rssi_sum_cnt > 4) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001137 int32_t rssi_ackAvg =
Sujith256b7752008-11-18 09:03:12 +05301138 (ath_rc_priv->rssi_sum + 2) / 4;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001139 int8_t rssi_thres =
Sujith256b7752008-11-18 09:03:12 +05301140 ath_rc_priv->state[tx_rate].
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001141 rssi_thres;
1142 int8_t rssi_ack_vmin =
1143 rate_table->info[tx_rate].
1144 rssi_ack_validmin;
1145
Sujith256b7752008-11-18 09:03:12 +05301146 ath_rc_priv->rssi_sum =
1147 ath_rc_priv->rssi_sum_cnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001148
1149 /* Now reduce the current
1150 * rssi threshold. */
1151 if ((rssi_ackAvg < rssi_thres + 2) &&
Sujithdc2222a2008-08-14 13:26:55 +05301152 (rssi_thres > rssi_ack_vmin)) {
Sujith256b7752008-11-18 09:03:12 +05301153 ath_rc_priv->state[tx_rate].
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001154 rssi_thres--;
1155 }
1156
1157 state_change = TRUE;
1158 }
1159 }
1160 }
1161 }
1162
1163 /* For all cases */
1164
1165 /*
1166 * If this rate looks bad (high PER) then stop using it for
1167 * a while (except if we are probing).
1168 */
Sujith256b7752008-11-18 09:03:12 +05301169 if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
Sujithdc2222a2008-08-14 13:26:55 +05301170 rate_table->info[tx_rate].ratekbps <=
Sujith256b7752008-11-18 09:03:12 +05301171 rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
1172 ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
1173 (u8) tx_rate, &ath_rc_priv->rate_max_phy);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001174
1175 /* Don't probe for a little while. */
Sujith256b7752008-11-18 09:03:12 +05301176 ath_rc_priv->probe_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001177 }
1178
1179 if (state_change) {
1180 /*
1181 * Make sure the rates above this have higher rssi thresholds.
1182 * (Note: Monotonicity is kept within the OFDM rates and
1183 * within the CCK rates. However, no adjustment is
1184 * made to keep the rssi thresholds monotonically
1185 * increasing between the CCK and OFDM rates.)
1186 */
1187 for (rate = tx_rate; rate <
Sujith256b7752008-11-18 09:03:12 +05301188 ath_rc_priv->rate_table_size - 1; rate++) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001189 if (rate_table->info[rate+1].phy !=
1190 rate_table->info[tx_rate].phy)
1191 break;
1192
Sujith256b7752008-11-18 09:03:12 +05301193 if (ath_rc_priv->state[rate].rssi_thres +
Sujithdc2222a2008-08-14 13:26:55 +05301194 rate_table->info[rate].rssi_ack_deltamin >
Sujith256b7752008-11-18 09:03:12 +05301195 ath_rc_priv->state[rate+1].rssi_thres) {
1196 ath_rc_priv->state[rate+1].rssi_thres =
1197 ath_rc_priv->state[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301198 rssi_thres +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001199 rate_table->info[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301200 rssi_ack_deltamin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001201 }
1202 }
1203
1204 /* Make sure the rates below this have lower rssi thresholds. */
1205 for (rate = tx_rate - 1; rate >= 0; rate--) {
1206 if (rate_table->info[rate].phy !=
Sujithdc2222a2008-08-14 13:26:55 +05301207 rate_table->info[tx_rate].phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001208 break;
1209
Sujith256b7752008-11-18 09:03:12 +05301210 if (ath_rc_priv->state[rate].rssi_thres +
Sujithdc2222a2008-08-14 13:26:55 +05301211 rate_table->info[rate].rssi_ack_deltamin >
Sujith256b7752008-11-18 09:03:12 +05301212 ath_rc_priv->state[rate+1].rssi_thres) {
1213 if (ath_rc_priv->state[rate+1].rssi_thres <
Sujithdc2222a2008-08-14 13:26:55 +05301214 rate_table->info[rate].
1215 rssi_ack_deltamin)
Sujith256b7752008-11-18 09:03:12 +05301216 ath_rc_priv->state[rate].rssi_thres = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001217 else {
Sujith256b7752008-11-18 09:03:12 +05301218 ath_rc_priv->state[rate].rssi_thres =
1219 ath_rc_priv->state[rate+1].
Sujithdc2222a2008-08-14 13:26:55 +05301220 rssi_thres -
1221 rate_table->info[rate].
1222 rssi_ack_deltamin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001223 }
1224
Sujith256b7752008-11-18 09:03:12 +05301225 if (ath_rc_priv->state[rate].rssi_thres <
Sujithdc2222a2008-08-14 13:26:55 +05301226 rate_table->info[rate].
1227 rssi_ack_validmin) {
Sujith256b7752008-11-18 09:03:12 +05301228 ath_rc_priv->state[rate].rssi_thres =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001229 rate_table->info[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301230 rssi_ack_validmin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001231 }
1232 }
1233 }
1234 }
1235
1236 /* Make sure the rates below this have lower PER */
1237 /* Monotonicity is kept only for rates below the current rate. */
Sujith256b7752008-11-18 09:03:12 +05301238 if (ath_rc_priv->state[tx_rate].per < last_per) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001239 for (rate = tx_rate - 1; rate >= 0; rate--) {
1240 if (rate_table->info[rate].phy !=
Sujithdc2222a2008-08-14 13:26:55 +05301241 rate_table->info[tx_rate].phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001242 break;
1243
Sujith256b7752008-11-18 09:03:12 +05301244 if (ath_rc_priv->state[rate].per >
1245 ath_rc_priv->state[rate+1].per) {
1246 ath_rc_priv->state[rate].per =
1247 ath_rc_priv->state[rate+1].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001248 }
1249 }
1250 }
1251
1252 /* Maintain monotonicity for rates above the current rate */
Sujith256b7752008-11-18 09:03:12 +05301253 for (rate = tx_rate; rate < ath_rc_priv->rate_table_size - 1; rate++) {
1254 if (ath_rc_priv->state[rate+1].per < ath_rc_priv->state[rate].per)
1255 ath_rc_priv->state[rate+1].per =
1256 ath_rc_priv->state[rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001257 }
1258
1259 /* Every so often, we reduce the thresholds and
1260 * PER (different for CCK and OFDM). */
Sujith256b7752008-11-18 09:03:12 +05301261 if (now_msec - ath_rc_priv->rssi_down_time >=
Sujithdc2222a2008-08-14 13:26:55 +05301262 rate_table->rssi_reduce_interval) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001263
Sujith256b7752008-11-18 09:03:12 +05301264 for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
1265 if (ath_rc_priv->state[rate].rssi_thres >
Sujithdc2222a2008-08-14 13:26:55 +05301266 rate_table->info[rate].rssi_ack_validmin)
Sujith256b7752008-11-18 09:03:12 +05301267 ath_rc_priv->state[rate].rssi_thres -= 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001268 }
Sujith256b7752008-11-18 09:03:12 +05301269 ath_rc_priv->rssi_down_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001270 }
1271
1272 /* Every so often, we reduce the thresholds
1273 * and PER (different for CCK and OFDM). */
Sujith256b7752008-11-18 09:03:12 +05301274 if (now_msec - ath_rc_priv->per_down_time >=
Sujithdc2222a2008-08-14 13:26:55 +05301275 rate_table->rssi_reduce_interval) {
Sujith256b7752008-11-18 09:03:12 +05301276 for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
1277 ath_rc_priv->state[rate].per =
1278 7 * ath_rc_priv->state[rate].per / 8;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001279 }
1280
Sujith256b7752008-11-18 09:03:12 +05301281 ath_rc_priv->per_down_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001282 }
1283}
1284
1285/*
1286 * This routine is called in rate control callback tx_status() to give
1287 * the status of previous frames.
1288 */
1289static void ath_rc_update(struct ath_softc *sc,
1290 struct ath_rate_node *ath_rc_priv,
Sujitha8efee42008-11-18 09:07:30 +05301291 struct ieee80211_tx_info *tx_info, int final_ts_idx,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001292 int xretries, int long_retry)
1293{
Sujitha8efee42008-11-18 09:07:30 +05301294 struct ath_tx_info_priv *info_priv =
1295 (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001296 struct ath_rate_table *rate_table;
Sujitha8efee42008-11-18 09:07:30 +05301297 struct ieee80211_tx_rate *rates = tx_info->status.rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001298 u8 flags;
1299 u32 series = 0, rix;
1300
Sujithfe7f4a72008-11-18 09:07:06 +05301301 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001302
1303 /*
1304 * If the first rate is not the final index, there
1305 * are intermediate rate failures to be processed.
1306 */
1307 if (final_ts_idx != 0) {
1308 /* Process intermediate rates that failed.*/
1309 for (series = 0; series < final_ts_idx ; series++) {
Sujithe63835b2008-11-18 09:07:53 +05301310 if (rates[series].count != 0 && (rates[series].idx >= 0)) {
Sujitha8efee42008-11-18 09:07:30 +05301311 flags = rates[series].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001312 /* If HT40 and we have switched mode from
1313 * 40 to 20 => don't update */
Sujitha8efee42008-11-18 09:07:30 +05301314 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
Sujithe63835b2008-11-18 09:07:53 +05301315 (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001316 return;
Sujithe63835b2008-11-18 09:07:53 +05301317
Sujitha8efee42008-11-18 09:07:30 +05301318 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1319 (flags & IEEE80211_TX_RC_SHORT_GI))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001320 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301321 rates[series].idx].ht_index;
1322 else if (flags & IEEE80211_TX_RC_SHORT_GI)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001323 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301324 rates[series].idx].sgi_index;
1325 else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001326 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301327 rates[series].idx].cw40index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001328 else
1329 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301330 rates[series].idx].base_index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001331 ath_rc_update_ht(sc, ath_rc_priv,
1332 info_priv, rix,
1333 xretries ? 1 : 2,
Sujitha8efee42008-11-18 09:07:30 +05301334 rates[series].count);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001335 }
1336 }
1337 } else {
1338 /*
1339 * Handle the special case of MIMO PS burst, where the second
1340 * aggregate is sent out with only one rate and one try.
1341 * Treating it as an excessive retry penalizes the rate
1342 * inordinately.
1343 */
Sujitha8efee42008-11-18 09:07:30 +05301344 if (rates[0].count == 1 && xretries == 1)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001345 xretries = 2;
1346 }
1347
Sujitha8efee42008-11-18 09:07:30 +05301348 flags = rates[series].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001349 /* If HT40 and we have switched mode from 40 to 20 => don't update */
Sujitha8efee42008-11-18 09:07:30 +05301350 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
Sujithe63835b2008-11-18 09:07:53 +05301351 (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001352 return;
Sujithe63835b2008-11-18 09:07:53 +05301353 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001354
Sujitha8efee42008-11-18 09:07:30 +05301355 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && (flags & IEEE80211_TX_RC_SHORT_GI))
1356 rix = rate_table->info[rates[series].idx].ht_index;
1357 else if (flags & IEEE80211_TX_RC_SHORT_GI)
1358 rix = rate_table->info[rates[series].idx].sgi_index;
1359 else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1360 rix = rate_table->info[rates[series].idx].cw40index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001361 else
Sujitha8efee42008-11-18 09:07:30 +05301362 rix = rate_table->info[rates[series].idx].base_index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001363
1364 ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix,
1365 xretries, long_retry);
1366}
1367
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001368/*
1369 * Process a tx descriptor for a completed transmit (success or failure).
1370 */
1371static void ath_rate_tx_complete(struct ath_softc *sc,
1372 struct ath_node *an,
1373 struct ath_rate_node *rc_priv,
Sujitha8efee42008-11-18 09:07:30 +05301374 struct ieee80211_tx_info *tx_info)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001375{
Sujitha8efee42008-11-18 09:07:30 +05301376 struct ath_tx_info_priv *info_priv =
1377 (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001378 int final_ts_idx = info_priv->tx.ts_rateindex;
1379 int tx_status = 0, is_underrun = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001380
Sujith2b406f12008-11-18 09:05:35 +05301381 if (info_priv->tx.ts_status & ATH9K_TXERR_FILT)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001382 return;
1383
1384 if (info_priv->tx.ts_rssi > 0) {
1385 ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
Sujithdc2222a2008-08-14 13:26:55 +05301386 info_priv->tx.ts_rssi);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001387 }
1388
1389 /*
1390 * If underrun error is seen assume it as an excessive retry only
1391 * if prefetch trigger level have reached the max (0x3f for 5416)
1392 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
1393 * times. This affects how ratectrl updates PER for the failed rate.
1394 */
1395 if (info_priv->tx.ts_flags &
1396 (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
Sujithfe7f4a72008-11-18 09:07:06 +05301397 ((sc->sc_ah->ah_txTrigLevel) >= rc_priv->tx_triglevel_max)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001398 tx_status = 1;
1399 is_underrun = 1;
1400 }
1401
1402 if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
1403 (info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
1404 tx_status = 1;
1405
Sujitha8efee42008-11-18 09:07:30 +05301406 ath_rc_update(sc, rc_priv, tx_info, final_ts_idx, tx_status,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001407 (is_underrun) ? ATH_11N_TXMAXTRY :
1408 info_priv->tx.ts_longretry);
1409}
1410
Sujith5ddfac32008-11-18 09:06:44 +05301411static void ath_rc_init(struct ath_softc *sc,
1412 struct ath_rate_node *ath_rc_priv,
1413 struct ieee80211_supported_band *sband,
1414 struct ieee80211_sta *sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001415{
1416 struct ath_rate_table *rate_table = NULL;
Sujith5ddfac32008-11-18 09:06:44 +05301417 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1418 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001419 u8 i, j, k, hi = 0, hthi = 0;
1420
Sujithfe7f4a72008-11-18 09:07:06 +05301421 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001422
Sujith5ddfac32008-11-18 09:06:44 +05301423 if (sta->ht_cap.ht_supported) {
1424 if (sband->band == IEEE80211_BAND_2GHZ)
Sujithfe7f4a72008-11-18 09:07:06 +05301425 rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301426 else
Sujithfe7f4a72008-11-18 09:07:06 +05301427 rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301428
1429 ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
1430 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1431 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
1432 }
1433
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001434 /* Initial rate table size. Will change depending
1435 * on the working rate set */
Sujith256b7752008-11-18 09:03:12 +05301436 ath_rc_priv->rate_table_size = MAX_TX_RATE_TBL;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001437
1438 /* Initialize thresholds according to the global rate table */
Sujith5ddfac32008-11-18 09:06:44 +05301439 for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
Sujith256b7752008-11-18 09:03:12 +05301440 ath_rc_priv->state[i].rssi_thres =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001441 rate_table->info[i].rssi_ack_validmin;
Sujith256b7752008-11-18 09:03:12 +05301442 ath_rc_priv->state[i].per = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001443 }
1444
1445 /* Determine the valid rates */
Sujith256b7752008-11-18 09:03:12 +05301446 ath_rc_init_valid_txmask(ath_rc_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001447
1448 for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
1449 for (j = 0; j < MAX_TX_RATE_PHY; j++)
Sujith256b7752008-11-18 09:03:12 +05301450 ath_rc_priv->valid_phy_rateidx[i][j] = 0;
1451 ath_rc_priv->valid_phy_ratecnt[i] = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001452 }
Sujith5ddfac32008-11-18 09:06:44 +05301453 ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001454
1455 /* Set stream capability */
Sujith5ddfac32008-11-18 09:06:44 +05301456 ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001457
1458 if (!rateset->rs_nrates) {
1459 /* No working rate, just initialize valid rates */
1460 hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301461 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001462 } else {
1463 /* Use intersection of working rates and valid rates */
1464 hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301465 rateset, ath_rc_priv->ht_cap);
1466 if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001467 hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv,
1468 rate_table,
1469 ht_mcs,
Sujith5ddfac32008-11-18 09:06:44 +05301470 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001471 }
1472 hi = A_MAX(hi, hthi);
1473 }
1474
Sujith256b7752008-11-18 09:03:12 +05301475 ath_rc_priv->rate_table_size = hi + 1;
1476 ath_rc_priv->rate_max_phy = 0;
1477 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001478
1479 for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
Sujith256b7752008-11-18 09:03:12 +05301480 for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
1481 ath_rc_priv->valid_rate_index[k++] =
1482 ath_rc_priv->valid_phy_rateidx[i][j];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001483 }
1484
1485 if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE)
Sujith256b7752008-11-18 09:03:12 +05301486 || !ath_rc_priv->valid_phy_ratecnt[i])
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001487 continue;
1488
Sujith256b7752008-11-18 09:03:12 +05301489 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001490 }
Sujith256b7752008-11-18 09:03:12 +05301491 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001492 ASSERT(k <= MAX_TX_RATE_TBL);
1493
Sujith256b7752008-11-18 09:03:12 +05301494 ath_rc_priv->max_valid_rate = k;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001495 /*
1496 * Some third party vendors don't send the supported rate series in
1497 * order. So sorting to make sure its in order, otherwise our RateFind
1498 * Algo will select wrong rates
1499 */
Sujith256b7752008-11-18 09:03:12 +05301500 ath_rc_sort_validrates(rate_table, ath_rc_priv);
1501 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001502}
1503
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001504/* Rate Control callbacks */
Johannes Berg4b7679a2008-09-18 18:14:18 +02001505static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1506 struct ieee80211_sta *sta, void *priv_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001507 struct sk_buff *skb)
1508{
1509 struct ath_softc *sc = priv;
1510 struct ath_tx_info_priv *tx_info_priv;
1511 struct ath_node *an;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001512 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1513 struct ieee80211_hdr *hdr;
1514 __le16 fc;
1515
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001516 hdr = (struct ieee80211_hdr *)skb->data;
1517 fc = hdr->frame_control;
Sujitha8efee42008-11-18 09:07:30 +05301518 tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001519
Sujithb5aa9bf2008-10-29 10:13:31 +05301520 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001521
Johannes Berge6a98542008-10-21 12:40:02 +02001522 if (tx_info_priv == NULL)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001523 return;
Johannes Berge6a98542008-10-21 12:40:02 +02001524
1525 if (an && priv_sta && ieee80211_is_data(fc))
Sujitha8efee42008-11-18 09:07:30 +05301526 ath_rate_tx_complete(sc, an, priv_sta, tx_info);
Johannes Berge6a98542008-10-21 12:40:02 +02001527
1528 kfree(tx_info_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001529}
1530
Johannes Berge6a98542008-10-21 12:40:02 +02001531static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
1532 struct ieee80211_tx_rate_control *txrc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001533{
Johannes Berge6a98542008-10-21 12:40:02 +02001534 struct ieee80211_supported_band *sband = txrc->sband;
1535 struct sk_buff *skb = txrc->skb;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001536 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Johannes Berg4b7679a2008-09-18 18:14:18 +02001537 struct ath_softc *sc = priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001538 struct ieee80211_hw *hw = sc->hw;
Johannes Berg4b7679a2008-09-18 18:14:18 +02001539 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001540 struct ath_node *an;
1541 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujithccc75c52008-10-29 10:18:14 +05301542 int is_probe = FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001543 __le16 fc = hdr->frame_control;
1544 u8 *qc, tid;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001545
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001546 /* lowest rate for management and multicast/broadcast frames */
Sujitha8efee42008-11-18 09:07:30 +05301547 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
1548 tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
1549 tx_info->control.rates[0].count =
1550 is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001551 return;
1552 }
1553
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001554 /* Find tx rate for unicast frames */
1555 ath_rate_findrate(sc, ath_rc_priv,
1556 ATH_11N_TXMAXTRY, 4,
1557 ATH_RC_PROBE_ALLOWED,
Sujitha8efee42008-11-18 09:07:30 +05301558 tx_info,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001559 &is_probe,
1560 false);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001561
1562 /* Check if aggregation has to be enabled for this tid */
Johannes Bergae5eb022008-10-14 16:58:37 +02001563 if (hw->conf.ht.enabled) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001564 if (ieee80211_is_data_qos(fc)) {
1565 qc = ieee80211_get_qos_ctl(hdr);
1566 tid = qc[0] & 0xf;
Sujithb5aa9bf2008-10-29 10:13:31 +05301567 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001568
Sujithccc75c52008-10-29 10:18:14 +05301569 if(ath_tx_aggr_check(sc, an, tid))
1570 ieee80211_start_tx_ba_session(hw, hdr->addr1, tid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001571 }
1572 }
1573}
1574
Johannes Berg4b7679a2008-09-18 18:14:18 +02001575static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1576 struct ieee80211_sta *sta, void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001577{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001578 struct ath_softc *sc = priv;
Sujithdc2222a2008-08-14 13:26:55 +05301579 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001580 int i, j = 0;
1581
Sujith7b4d2732008-11-18 09:04:00 +05301582 for (i = 0; i < sband->n_bitrates; i++) {
1583 if (sta->supp_rates[sband->band] & BIT(i)) {
1584 ath_rc_priv->neg_rates.rs_rates[j]
1585 = (sband->bitrates[i].bitrate * 2) / 10;
1586 j++;
1587 }
1588 }
1589 ath_rc_priv->neg_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001590
Sujitha4510bf2008-10-23 12:15:19 +05301591 if (sta->ht_cap.ht_supported) {
Sujith7b4d2732008-11-18 09:04:00 +05301592 for (i = 0, j = 0; i < 77; i++) {
Johannes Bergae5eb022008-10-14 16:58:37 +02001593 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
Sujithdc2222a2008-08-14 13:26:55 +05301594 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001595 if (j == ATH_RATE_MAX)
1596 break;
1597 }
Sujithdc2222a2008-08-14 13:26:55 +05301598 ath_rc_priv->neg_ht_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001599 }
Sujith7b4d2732008-11-18 09:04:00 +05301600
Sujith5ddfac32008-11-18 09:06:44 +05301601 ath_rc_init(sc, priv_sta, sband, sta);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001602}
1603
Johannes Berg4b7679a2008-09-18 18:14:18 +02001604static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001605{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001606 return hw->priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001607}
1608
1609static void ath_rate_free(void *priv)
1610{
1611 return;
1612}
1613
Johannes Berg4b7679a2008-09-18 18:14:18 +02001614static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001615{
1616 struct ath_softc *sc = priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001617 struct ath_rate_node *rate_priv;
1618
Sujithfe605942008-11-18 09:03:36 +05301619 rate_priv = kzalloc(sizeof(struct ath_rate_node), gfp);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001620 if (!rate_priv) {
Sujithdc2222a2008-08-14 13:26:55 +05301621 DPRINTF(sc, ATH_DBG_FATAL,
1622 "%s: Unable to allocate private rc structure\n",
1623 __func__);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001624 return NULL;
1625 }
Sujithfe605942008-11-18 09:03:36 +05301626
Sujithfe605942008-11-18 09:03:36 +05301627 rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
Sujithfe7f4a72008-11-18 09:07:06 +05301628 rate_priv->tx_triglevel_max = sc->sc_ah->ah_caps.tx_triglevel_max;
Sujithdc2222a2008-08-14 13:26:55 +05301629
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001630 return rate_priv;
1631}
1632
Johannes Berg4b7679a2008-09-18 18:14:18 +02001633static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
1634 void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001635{
1636 struct ath_rate_node *rate_priv = priv_sta;
Sujithfe605942008-11-18 09:03:36 +05301637 kfree(rate_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001638}
1639
1640static struct rate_control_ops ath_rate_ops = {
1641 .module = NULL,
1642 .name = "ath9k_rate_control",
1643 .tx_status = ath_tx_status,
1644 .get_rate = ath_get_rate,
1645 .rate_init = ath_rate_init,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001646 .alloc = ath_rate_alloc,
1647 .free = ath_rate_free,
1648 .alloc_sta = ath_rate_alloc_sta,
Johannes Berg4b7679a2008-09-18 18:14:18 +02001649 .free_sta = ath_rate_free_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001650};
1651
Sujithe63835b2008-11-18 09:07:53 +05301652static void ath_setup_rate_table(struct ath_softc *sc,
1653 struct ath_rate_table *rate_table)
1654{
1655 int i;
1656
1657 for (i = 0; i < 256; i++)
1658 rate_table->rateCodeToIndex[i] = (u8)-1;
1659
1660 for (i = 0; i < rate_table->rate_cnt; i++) {
1661 u8 code = rate_table->info[i].ratecode;
1662 u8 cix = rate_table->info[i].ctrl_rate;
1663 u8 sh = rate_table->info[i].short_preamble;
1664
1665 rate_table->rateCodeToIndex[code] = i;
1666 rate_table->rateCodeToIndex[code | sh] = i;
1667
1668 rate_table->info[i].lpAckDuration =
1669 ath9k_hw_computetxtime(sc->sc_ah, rate_table,
1670 WLAN_CTRL_FRAME_SIZE,
1671 cix,
1672 false);
1673 rate_table->info[i].spAckDuration =
1674 ath9k_hw_computetxtime(sc->sc_ah, rate_table,
1675 WLAN_CTRL_FRAME_SIZE,
1676 cix,
1677 true);
1678 }
1679}
1680
Sujithfe7f4a72008-11-18 09:07:06 +05301681void ath_rate_attach(struct ath_softc *sc)
1682{
1683 sc->hw_rate_table[ATH9K_MODE_11B] =
1684 &ar5416_11b_ratetable;
1685 sc->hw_rate_table[ATH9K_MODE_11A] =
1686 &ar5416_11a_ratetable;
1687 sc->hw_rate_table[ATH9K_MODE_11G] =
1688 &ar5416_11g_ratetable;
1689 sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
1690 &ar5416_11na_ratetable;
1691 sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
1692 &ar5416_11ng_ratetable;
1693 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
1694 &ar5416_11na_ratetable;
1695 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
1696 &ar5416_11na_ratetable;
1697 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
1698 &ar5416_11ng_ratetable;
1699 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
1700 &ar5416_11ng_ratetable;
Sujithe63835b2008-11-18 09:07:53 +05301701
1702 ath_setup_rate_table(sc, &ar5416_11b_ratetable);
1703 ath_setup_rate_table(sc, &ar5416_11a_ratetable);
1704 ath_setup_rate_table(sc, &ar5416_11g_ratetable);
1705 ath_setup_rate_table(sc, &ar5416_11na_ratetable);
1706 ath_setup_rate_table(sc, &ar5416_11ng_ratetable);
Sujithfe7f4a72008-11-18 09:07:06 +05301707}
1708
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001709int ath_rate_control_register(void)
1710{
1711 return ieee80211_rate_control_register(&ath_rate_ops);
1712}
1713
1714void ath_rate_control_unregister(void)
1715{
1716 ieee80211_rate_control_unregister(&ath_rate_ops);
1717}