blob: 156b245ab9e4d460feb0031f49137854edda3bb7 [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,
28 {
29 { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
30 5400, 0x0b, 0x00, 12,
31 0, 2, 1, 0, 0, 0, 0, 0 },
32 { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
33 7800, 0x0f, 0x00, 18,
34 0, 3, 1, 1, 1, 1, 1, 0 },
35 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
36 10000, 0x0a, 0x00, 24,
37 2, 4, 2, 2, 2, 2, 2, 0 },
38 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
39 13900, 0x0e, 0x00, 36,
40 2, 6, 2, 3, 3, 3, 3, 0 },
41 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
42 17300, 0x09, 0x00, 48,
43 4, 10, 3, 4, 4, 4, 4, 0 },
44 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
45 23000, 0x0d, 0x00, 72,
46 4, 14, 3, 5, 5, 5, 5, 0 },
47 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
48 27400, 0x08, 0x00, 96,
49 4, 20, 3, 6, 6, 6, 6, 0 },
50 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
51 29300, 0x0c, 0x00, 108,
52 4, 23, 3, 7, 7, 7, 7, 0 },
53 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
54 6400, 0x80, 0x00, 0,
55 0, 2, 3, 8, 24, 8, 24, 3216 },
56 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
57 12700, 0x81, 0x00, 1,
58 2, 4, 3, 9, 25, 9, 25, 6434 },
59 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
60 18800, 0x82, 0x00, 2,
61 2, 6, 3, 10, 26, 10, 26, 9650 },
62 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
63 25000, 0x83, 0x00, 3,
64 4, 10, 3, 11, 27, 11, 27, 12868 },
65 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
66 36700, 0x84, 0x00, 4,
67 4, 14, 3, 12, 28, 12, 28, 19304 },
68 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
69 48100, 0x85, 0x00, 5,
70 4, 20, 3, 13, 29, 13, 29, 25740 },
71 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
72 53500, 0x86, 0x00, 6,
73 4, 23, 3, 14, 30, 14, 30, 28956 },
74 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
75 59000, 0x87, 0x00, 7,
76 4, 25, 3, 15, 31, 15, 32, 32180 },
77 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
78 12700, 0x88, 0x00,
79 8, 0, 2, 3, 16, 33, 16, 33, 6430 },
80 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
81 24800, 0x89, 0x00, 9,
82 2, 4, 3, 17, 34, 17, 34, 12860 },
83 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
84 36600, 0x8a, 0x00, 10,
85 2, 6, 3, 18, 35, 18, 35, 19300 },
86 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
87 48100, 0x8b, 0x00, 11,
88 4, 10, 3, 19, 36, 19, 36, 25736 },
89 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
90 69500, 0x8c, 0x00, 12,
91 4, 14, 3, 20, 37, 20, 37, 38600 },
92 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
93 89500, 0x8d, 0x00, 13,
94 4, 20, 3, 21, 38, 21, 38, 51472 },
95 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
96 98900, 0x8e, 0x00, 14,
97 4, 23, 3, 22, 39, 22, 39, 57890 },
98 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
99 108300, 0x8f, 0x00, 15,
100 4, 25, 3, 23, 40, 23, 41, 64320 },
101 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
102 13200, 0x80, 0x00, 0,
103 0, 2, 3, 8, 24, 24, 24, 6684 },
104 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
105 25900, 0x81, 0x00, 1,
106 2, 4, 3, 9, 25, 25, 25, 13368 },
107 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
108 38600, 0x82, 0x00, 2,
109 2, 6, 3, 10, 26, 26, 26, 20052 },
110 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
111 49800, 0x83, 0x00, 3,
112 4, 10, 3, 11, 27, 27, 27, 26738 },
113 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
114 72200, 0x84, 0x00, 4,
115 4, 14, 3, 12, 28, 28, 28, 40104 },
116 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
117 92900, 0x85, 0x00, 5,
118 4, 20, 3, 13, 29, 29, 29, 53476 },
119 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
120 102700, 0x86, 0x00, 6,
121 4, 23, 3, 14, 30, 30, 30, 60156 },
122 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
123 112000, 0x87, 0x00, 7,
124 4, 25, 3, 15, 31, 32, 32, 66840 },
125 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
126 122000, 0x87, 0x00, 7,
127 4, 25, 3, 15, 31, 32, 32, 74200 },
128 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
129 25800, 0x88, 0x00, 8,
130 0, 2, 3, 16, 33, 33, 33, 13360 },
131 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
132 49800, 0x89, 0x00, 9,
133 2, 4, 3, 17, 34, 34, 34, 26720 },
134 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
135 71900, 0x8a, 0x00, 10,
136 2, 6, 3, 18, 35, 35, 35, 40080 },
137 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
138 92500, 0x8b, 0x00, 11,
139 4, 10, 3, 19, 36, 36, 36, 53440 },
140 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
141 130300, 0x8c, 0x00, 12,
142 4, 14, 3, 20, 37, 37, 37, 80160 },
143 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
144 162800, 0x8d, 0x00, 13,
145 4, 20, 3, 21, 38, 38, 38, 106880 },
146 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
147 178200, 0x8e, 0x00, 14,
148 4, 23, 3, 22, 39, 39, 39, 120240 },
149 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
150 192100, 0x8f, 0x00, 15,
151 4, 25, 3, 23, 40, 41, 41, 133600 },
152 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
153 207000, 0x8f, 0x00, 15,
154 4, 25, 3, 23, 40, 41, 41, 148400 },
155 },
156 50, /* probe interval */
157 50, /* rssi reduce interval */
158 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
159};
160
161/* TRUE_ALL - valid for 20/40/Legacy,
162 * TRUE - Legacy only,
163 * TRUE_20 - HT 20 only,
164 * TRUE_40 - HT 40 only */
165
166/* 4ms frame limit not used for NG mode. The values filled
167 * for HT are the 64K max aggregate limit */
168
169static struct ath_rate_table ar5416_11ng_ratetable = {
170 46,
171 {
172 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */
173 900, 0x1b, 0x00, 2,
174 0, 0, 1, 0, 0, 0, 0, 0 },
175 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */
176 1900, 0x1a, 0x04, 4,
177 1, 1, 1, 1, 1, 1, 1, 0 },
178 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
179 4900, 0x19, 0x04, 11,
180 2, 2, 2, 2, 2, 2, 2, 0 },
181 { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */
182 8100, 0x18, 0x04, 22,
183 3, 3, 2, 3, 3, 3, 3, 0 },
184 { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
185 5400, 0x0b, 0x00, 12,
186 4, 2, 1, 4, 4, 4, 4, 0 },
187 { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
188 7800, 0x0f, 0x00, 18,
189 4, 3, 1, 5, 5, 5, 5, 0 },
190 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
191 10100, 0x0a, 0x00, 24,
192 6, 4, 1, 6, 6, 6, 6, 0 },
193 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
194 14100, 0x0e, 0x00, 36,
195 6, 6, 2, 7, 7, 7, 7, 0 },
196 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
197 17700, 0x09, 0x00, 48,
198 8, 10, 3, 8, 8, 8, 8, 0 },
199 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
200 23700, 0x0d, 0x00, 72,
201 8, 14, 3, 9, 9, 9, 9, 0 },
202 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
203 27400, 0x08, 0x00, 96,
204 8, 20, 3, 10, 10, 10, 10, 0 },
205 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
206 30900, 0x0c, 0x00, 108,
207 8, 23, 3, 11, 11, 11, 11, 0 },
208 { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
209 6400, 0x80, 0x00, 0,
210 4, 2, 3, 12, 28, 12, 28, 3216 },
211 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
212 12700, 0x81, 0x00, 1,
213 6, 4, 3, 13, 29, 13, 29, 6434 },
214 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
215 18800, 0x82, 0x00, 2,
216 6, 6, 3, 14, 30, 14, 30, 9650 },
217 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
218 25000, 0x83, 0x00, 3,
219 8, 10, 3, 15, 31, 15, 31, 12868 },
220 { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
221 36700, 0x84, 0x00, 4,
222 8, 14, 3, 16, 32, 16, 32, 19304 },
223 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
224 48100, 0x85, 0x00, 5,
225 8, 20, 3, 17, 33, 17, 33, 25740 },
226 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
227 53500, 0x86, 0x00, 6,
228 8, 23, 3, 18, 34, 18, 34, 28956 },
229 { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
230 59000, 0x87, 0x00, 7,
231 8, 25, 3, 19, 35, 19, 36, 32180 },
232 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
233 12700, 0x88, 0x00, 8,
234 4, 2, 3, 20, 37, 20, 37, 6430 },
235 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
236 24800, 0x89, 0x00, 9,
237 6, 4, 3, 21, 38, 21, 38, 12860 },
238 { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
239 36600, 0x8a, 0x00, 10,
240 6, 6, 3, 22, 39, 22, 39, 19300 },
241 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
242 48100, 0x8b, 0x00, 11,
243 8, 10, 3, 23, 40, 23, 40, 25736 },
244 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
245 69500, 0x8c, 0x00, 12,
246 8, 14, 3, 24, 41, 24, 41, 38600 },
247 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
248 89500, 0x8d, 0x00, 13,
249 8, 20, 3, 25, 42, 25, 42, 51472 },
250 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
251 98900, 0x8e, 0x00, 14,
252 8, 23, 3, 26, 43, 26, 44, 57890 },
253 { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
254 108300, 0x8f, 0x00, 15,
255 8, 25, 3, 27, 44, 27, 45, 64320 },
256 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
257 13200, 0x80, 0x00, 0,
258 8, 2, 3, 12, 28, 28, 28, 6684 },
259 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
260 25900, 0x81, 0x00, 1,
261 8, 4, 3, 13, 29, 29, 29, 13368 },
262 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
263 38600, 0x82, 0x00, 2,
264 8, 6, 3, 14, 30, 30, 30, 20052 },
265 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
266 49800, 0x83, 0x00, 3,
267 8, 10, 3, 15, 31, 31, 31, 26738 },
268 { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
269 72200, 0x84, 0x00, 4,
270 8, 14, 3, 16, 32, 32, 32, 40104 },
271 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
272 92900, 0x85, 0x00, 5,
273 8, 20, 3, 17, 33, 33, 33, 53476 },
274 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
275 102700, 0x86, 0x00, 6,
276 8, 23, 3, 18, 34, 34, 34, 60156 },
277 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
278 112000, 0x87, 0x00, 7,
279 8, 23, 3, 19, 35, 36, 36, 66840 },
280 { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
281 122000, 0x87, 0x00, 7,
282 8, 25, 3, 19, 35, 36, 36, 74200 },
283 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
284 25800, 0x88, 0x00, 8,
285 8, 2, 3, 20, 37, 37, 37, 13360 },
286 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
287 49800, 0x89, 0x00, 9,
288 8, 4, 3, 21, 38, 38, 38, 26720 },
289 { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
290 71900, 0x8a, 0x00, 10,
291 8, 6, 3, 22, 39, 39, 39, 40080 },
292 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
293 92500, 0x8b, 0x00, 11,
294 8, 10, 3, 23, 40, 40, 40, 53440 },
295 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
296 130300, 0x8c, 0x00, 12,
297 8, 14, 3, 24, 41, 41, 41, 80160 },
298 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
299 162800, 0x8d, 0x00, 13,
300 8, 20, 3, 25, 42, 42, 42, 106880 },
301 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
302 178200, 0x8e, 0x00, 14,
303 8, 23, 3, 26, 43, 43, 43, 120240 },
304 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
305 192100, 0x8f, 0x00, 15,
306 8, 23, 3, 27, 44, 45, 45, 133600 },
307 { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
308 207000, 0x8f, 0x00, 15,
309 8, 25, 3, 27, 44, 45, 45, 148400 },
310 },
311 50, /* probe interval */
312 50, /* rssi reduce interval */
313 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
314};
315
316static struct ath_rate_table ar5416_11a_ratetable = {
317 8,
318 {
319 { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
320 5400, 0x0b, 0x00, (0x80|12),
321 0, 2, 1, 0, 0 },
322 { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
323 7800, 0x0f, 0x00, 18,
324 0, 3, 1, 1, 0 },
325 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
326 10000, 0x0a, 0x00, (0x80|24),
327 2, 4, 2, 2, 0 },
328 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
329 13900, 0x0e, 0x00, 36,
330 2, 6, 2, 3, 0 },
331 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
332 17300, 0x09, 0x00, (0x80|48),
333 4, 10, 3, 4, 0 },
334 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
335 23000, 0x0d, 0x00, 72,
336 4, 14, 3, 5, 0 },
337 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
338 27400, 0x08, 0x00, 96,
339 4, 19, 3, 6, 0 },
340 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
341 29300, 0x0c, 0x00, 108,
342 4, 23, 3, 7, 0 },
343 },
344 50, /* probe interval */
345 50, /* rssi reduce interval */
346 0, /* Phy rates allowed initially */
347};
348
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700349static struct ath_rate_table ar5416_11g_ratetable = {
350 12,
351 {
352 { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
353 900, 0x1b, 0x00, 2,
354 0, 0, 1, 0, 0 },
355 { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
356 1900, 0x1a, 0x04, 4,
357 1, 1, 1, 1, 0 },
358 { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
359 4900, 0x19, 0x04, 11,
360 2, 2, 2, 2, 0 },
361 { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
362 8100, 0x18, 0x04, 22,
363 3, 3, 2, 3, 0 },
364 { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
365 5400, 0x0b, 0x00, 12,
366 4, 2, 1, 4, 0 },
367 { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
368 7800, 0x0f, 0x00, 18,
369 4, 3, 1, 5, 0 },
370 { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
371 10000, 0x0a, 0x00, 24,
372 6, 4, 1, 6, 0 },
373 { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
374 13900, 0x0e, 0x00, 36,
375 6, 6, 2, 7, 0 },
376 { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
377 17300, 0x09, 0x00, 48,
378 8, 10, 3, 8, 0 },
379 { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
380 23000, 0x0d, 0x00, 72,
381 8, 14, 3, 9, 0 },
382 { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
383 27400, 0x08, 0x00, 96,
384 8, 19, 3, 10, 0 },
385 { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
386 29300, 0x0c, 0x00, 108,
387 8, 23, 3, 11, 0 },
388 },
389 50, /* probe interval */
390 50, /* rssi reduce interval */
391 0, /* Phy rates allowed initially */
392};
393
394static struct ath_rate_table ar5416_11b_ratetable = {
395 4,
396 {
397 { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
398 900, 0x1b, 0x00, (0x80|2),
399 0, 0, 1, 0, 0 },
400 { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
401 1800, 0x1a, 0x04, (0x80|4),
402 1, 1, 1, 1, 0 },
403 { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
404 4300, 0x19, 0x04, (0x80|11),
405 1, 2, 2, 2, 0 },
406 { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
407 7100, 0x18, 0x04, (0x80|22),
408 1, 4, 100, 3, 0 },
409 },
410 100, /* probe interval */
411 100, /* rssi reduce interval */
412 0, /* Phy rates allowed initially */
413};
414
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700415/*
416 * Return the median of three numbers
417 */
418static inline int8_t median(int8_t a, int8_t b, int8_t c)
419{
420 if (a >= b) {
421 if (b >= c)
422 return b;
423 else if (a > c)
424 return c;
425 else
426 return a;
427 } else {
428 if (a >= c)
429 return a;
430 else if (b >= c)
431 return c;
432 else
433 return b;
434 }
435}
436
Sujithfe7f4a72008-11-18 09:07:06 +0530437static void ath_rc_sort_validrates(struct ath_rate_table *rate_table,
Sujith256b77592008-11-18 09:03:12 +0530438 struct ath_rate_node *ath_rc_priv)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700439{
440 u8 i, j, idx, idx_next;
441
Sujith256b77592008-11-18 09:03:12 +0530442 for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700443 for (j = 0; j <= i-1; j++) {
Sujith256b77592008-11-18 09:03:12 +0530444 idx = ath_rc_priv->valid_rate_index[j];
445 idx_next = ath_rc_priv->valid_rate_index[j+1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700446
447 if (rate_table->info[idx].ratekbps >
448 rate_table->info[idx_next].ratekbps) {
Sujith256b77592008-11-18 09:03:12 +0530449 ath_rc_priv->valid_rate_index[j] = idx_next;
450 ath_rc_priv->valid_rate_index[j+1] = idx;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700451 }
452 }
453 }
454}
455
456/* Access functions for valid_txrate_mask */
457
Sujith256b77592008-11-18 09:03:12 +0530458static void ath_rc_init_valid_txmask(struct ath_rate_node *ath_rc_priv)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700459{
460 u8 i;
461
Sujith256b77592008-11-18 09:03:12 +0530462 for (i = 0; i < ath_rc_priv->rate_table_size; i++)
463 ath_rc_priv->valid_rate_index[i] = FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700464}
465
Sujith256b77592008-11-18 09:03:12 +0530466static inline void ath_rc_set_valid_txmask(struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700467 u8 index, int valid_tx_rate)
468{
Sujith256b77592008-11-18 09:03:12 +0530469 ASSERT(index <= ath_rc_priv->rate_table_size);
470 ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700471}
472
Sujith256b77592008-11-18 09:03:12 +0530473static inline int ath_rc_isvalid_txmask(struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700474 u8 index)
475{
Sujith256b77592008-11-18 09:03:12 +0530476 ASSERT(index <= ath_rc_priv->rate_table_size);
477 return ath_rc_priv->valid_rate_index[index];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700478}
479
480/* Iterators for valid_txrate_mask */
481static inline int
Sujithfe7f4a72008-11-18 09:07:06 +0530482ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
Sujith256b77592008-11-18 09:03:12 +0530483 struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700484 u8 cur_valid_txrate,
485 u8 *next_idx)
486{
487 u8 i;
488
Sujith256b77592008-11-18 09:03:12 +0530489 for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
490 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
491 *next_idx = ath_rc_priv->valid_rate_index[i+1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700492 return TRUE;
493 }
494 }
495
496 /* No more valid rates */
497 *next_idx = 0;
498 return FALSE;
499}
500
501/* Return true only for single stream */
502
503static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
504{
505 if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG))
506 return FALSE;
507 if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
508 return FALSE;
509 if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
510 return FALSE;
511 if (!ignore_cw && WLAN_RC_PHY_HT(phy))
512 if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
513 return FALSE;
514 if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
515 return FALSE;
516 return TRUE;
517}
518
519static inline int
Sujithfe7f4a72008-11-18 09:07:06 +0530520ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
Sujith256b77592008-11-18 09:03:12 +0530521 struct ath_rate_node *ath_rc_priv,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700522 u8 cur_valid_txrate, u8 *next_idx)
523{
524 int8_t i;
525
Sujith256b77592008-11-18 09:03:12 +0530526 for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
527 if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
528 *next_idx = ath_rc_priv->valid_rate_index[i-1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700529 return TRUE;
530 }
531 }
532 return FALSE;
533}
534
535/*
536 * Initialize the Valid Rate Index from valid entries in Rate Table
537 */
538static u8
539ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530540 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700541 u32 capflag)
542{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700543 u8 i, hi = 0;
544 u32 valid;
545
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700546 for (i = 0; i < rate_table->rate_cnt; i++) {
547 valid = (ath_rc_priv->single_stream ?
Sujithdc2222a2008-08-14 13:26:55 +0530548 rate_table->info[i].valid_single_stream :
549 rate_table->info[i].valid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700550 if (valid == TRUE) {
551 u32 phy = rate_table->info[i].phy;
552 u8 valid_rate_count = 0;
553
554 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
555 continue;
556
Sujith256b77592008-11-18 09:03:12 +0530557 valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700558
Sujith256b77592008-11-18 09:03:12 +0530559 ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
560 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
561 ath_rc_set_valid_txmask(ath_rc_priv, i, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700562 hi = A_MAX(hi, i);
563 }
564 }
565 return hi;
566}
567
568/*
569 * Initialize the Valid Rate Index from Rate Set
570 */
571static u8
572ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530573 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700574 struct ath_rateset *rateset,
575 u32 capflag)
576{
577 /* XXX: Clean me up and make identation friendly */
578 u8 i, j, hi = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700579
580 /* Use intersection of working rates and valid rates */
581 for (i = 0; i < rateset->rs_nrates; i++) {
582 for (j = 0; j < rate_table->rate_cnt; j++) {
583 u32 phy = rate_table->info[j].phy;
584 u32 valid = (ath_rc_priv->single_stream ?
585 rate_table->info[j].valid_single_stream :
586 rate_table->info[j].valid);
587
588 /* We allow a rate only if its valid and the
589 * capflag matches one of the validity
590 * (TRUE/TRUE_20/TRUE_40) flags */
591
592 /* XXX: catch the negative of this branch
593 * first and then continue */
594 if (((rateset->rs_rates[i] & 0x7F) ==
595 (rate_table->info[j].dot11rate & 0x7F)) &&
596 ((valid & WLAN_RC_CAP_MODE(capflag)) ==
597 WLAN_RC_CAP_MODE(capflag)) &&
598 !WLAN_RC_PHY_HT(phy)) {
599
600 u8 valid_rate_count = 0;
601
602 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
603 continue;
604
605 valid_rate_count =
Sujith256b77592008-11-18 09:03:12 +0530606 ath_rc_priv->valid_phy_ratecnt[phy];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700607
Sujith256b77592008-11-18 09:03:12 +0530608 ath_rc_priv->valid_phy_rateidx[phy]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700609 [valid_rate_count] = j;
Sujith256b77592008-11-18 09:03:12 +0530610 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
611 ath_rc_set_valid_txmask(ath_rc_priv, j, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700612 hi = A_MAX(hi, j);
613 }
614 }
615 }
616 return hi;
617}
618
619static u8
620ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530621 struct ath_rate_table *rate_table,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700622 u8 *mcs_set, u32 capflag)
623{
624 u8 i, j, hi = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700625
626 /* Use intersection of working rates and valid rates */
627 for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) {
628 for (j = 0; j < rate_table->rate_cnt; j++) {
629 u32 phy = rate_table->info[j].phy;
630 u32 valid = (ath_rc_priv->single_stream ?
Sujithdc2222a2008-08-14 13:26:55 +0530631 rate_table->info[j].valid_single_stream :
632 rate_table->info[j].valid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700633
634 if (((((struct ath_rateset *)
Sujithdc2222a2008-08-14 13:26:55 +0530635 mcs_set)->rs_rates[i] & 0x7F) !=
636 (rate_table->info[j].dot11rate & 0x7F)) ||
637 !WLAN_RC_PHY_HT(phy) ||
638 !WLAN_RC_PHY_HT_VALID(valid, capflag))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700639 continue;
640
641 if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
642 continue;
643
Sujith256b77592008-11-18 09:03:12 +0530644 ath_rc_priv->valid_phy_rateidx[phy]
645 [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
646 ath_rc_priv->valid_phy_ratecnt[phy] += 1;
647 ath_rc_set_valid_txmask(ath_rc_priv, j, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700648 hi = A_MAX(hi, j);
649 }
650 }
651 return hi;
652}
653
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700654u8 ath_rate_findrateix(struct ath_softc *sc,
Sujith102e0572008-10-29 10:15:16 +0530655 u8 dot11rate)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700656{
Sujithfe7f4a72008-11-18 09:07:06 +0530657 struct ath_rate_table *ratetable;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700658 int i;
659
Sujithfe7f4a72008-11-18 09:07:06 +0530660 ratetable = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700661
662 if (WARN_ON(!ratetable))
663 return 0;
664
665 for (i = 0; i < ratetable->rate_cnt; i++) {
666 if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f))
667 return i;
668 }
669
670 return 0;
671}
672
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700673static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
Sujithdc2222a2008-08-14 13:26:55 +0530674 struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530675 struct ath_rate_table *rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530676 int probe_allowed, int *is_probing,
677 int is_retry)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700678{
679 u32 dt, best_thruput, this_thruput, now_msec;
680 u8 rate, next_rate, best_rate, maxindex, minindex;
681 int8_t rssi_last, rssi_reduce = 0, index = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700682
683 *is_probing = FALSE;
684
Sujith256b77592008-11-18 09:03:12 +0530685 rssi_last = median(ath_rc_priv->rssi_last,
686 ath_rc_priv->rssi_last_prev,
687 ath_rc_priv->rssi_last_prev2);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700688
689 /*
690 * Age (reduce) last ack rssi based on how old it is.
691 * The bizarre numbers are so the delta is 160msec,
692 * meaning we divide by 16.
693 * 0msec <= dt <= 25msec: don't derate
694 * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB
695 * 185msec <= dt: derate by 10dB
696 */
697
698 now_msec = jiffies_to_msecs(jiffies);
Sujith256b77592008-11-18 09:03:12 +0530699 dt = now_msec - ath_rc_priv->rssi_time;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700700
701 if (dt >= 185)
702 rssi_reduce = 10;
703 else if (dt >= 25)
704 rssi_reduce = (u8)((dt - 25) >> 4);
705
706 /* Now reduce rssi_last by rssi_reduce */
707 if (rssi_last < rssi_reduce)
708 rssi_last = 0;
709 else
710 rssi_last -= rssi_reduce;
711
712 /*
713 * Now look up the rate in the rssi table and return it.
714 * If no rates match then we return 0 (lowest rate)
715 */
716
717 best_thruput = 0;
Sujith256b77592008-11-18 09:03:12 +0530718 maxindex = ath_rc_priv->max_valid_rate-1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700719
720 minindex = 0;
721 best_rate = minindex;
722
723 /*
724 * Try the higher rate first. It will reduce memory moving time
725 * if we have very good channel characteristics.
726 */
727 for (index = maxindex; index >= minindex ; index--) {
728 u8 per_thres;
729
Sujith256b77592008-11-18 09:03:12 +0530730 rate = ath_rc_priv->valid_rate_index[index];
731 if (rate > ath_rc_priv->rate_max_phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700732 continue;
733
734 /*
735 * For TCP the average collision rate is around 11%,
736 * so we ignore PERs less than this. This is to
737 * prevent the rate we are currently using (whose
738 * PER might be in the 10-15 range because of TCP
739 * collisions) looking worse than the next lower
740 * rate whose PER has decayed close to 0. If we
741 * used to next lower rate, its PER would grow to
742 * 10-15 and we would be worse off then staying
743 * at the current rate.
744 */
Sujith256b77592008-11-18 09:03:12 +0530745 per_thres = ath_rc_priv->state[rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700746 if (per_thres < 12)
747 per_thres = 12;
748
749 this_thruput = rate_table->info[rate].user_ratekbps *
750 (100 - per_thres);
751
752 if (best_thruput <= this_thruput) {
753 best_thruput = this_thruput;
754 best_rate = rate;
755 }
756 }
757
758 rate = best_rate;
759
760 /* if we are retrying for more than half the number
761 * of max retries, use the min rate for the next retry
762 */
763 if (is_retry)
Sujith256b77592008-11-18 09:03:12 +0530764 rate = ath_rc_priv->valid_rate_index[minindex];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700765
Sujith256b77592008-11-18 09:03:12 +0530766 ath_rc_priv->rssi_last_lookup = rssi_last;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700767
768 /*
769 * Must check the actual rate (ratekbps) to account for
770 * non-monoticity of 11g's rate table
771 */
772
Sujith256b77592008-11-18 09:03:12 +0530773 if (rate >= ath_rc_priv->rate_max_phy && probe_allowed) {
774 rate = ath_rc_priv->rate_max_phy;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700775
776 /* Probe the next allowed phy state */
777 /* FIXME:XXXX Check to make sure ratMax is checked properly */
778 if (ath_rc_get_nextvalid_txrate(rate_table,
Sujith256b77592008-11-18 09:03:12 +0530779 ath_rc_priv, rate, &next_rate) &&
780 (now_msec - ath_rc_priv->probe_time >
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700781 rate_table->probe_interval) &&
Sujith256b77592008-11-18 09:03:12 +0530782 (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700783 rate = next_rate;
Sujith256b77592008-11-18 09:03:12 +0530784 ath_rc_priv->probe_rate = rate;
785 ath_rc_priv->probe_time = now_msec;
786 ath_rc_priv->hw_maxretry_pktcnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700787 *is_probing = TRUE;
788 }
789 }
790
791 /*
792 * Make sure rate is not higher than the allowed maximum.
793 * We should also enforce the min, but I suspect the min is
794 * normally 1 rather than 0 because of the rate 9 vs 6 issue
795 * in the old code.
796 */
Sujith256b77592008-11-18 09:03:12 +0530797 if (rate > (ath_rc_priv->rate_table_size - 1))
798 rate = ath_rc_priv->rate_table_size - 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700799
800 ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
Sujithdc2222a2008-08-14 13:26:55 +0530801 (rate_table->info[rate].valid_single_stream &&
802 ath_rc_priv->single_stream));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700803
804 return rate;
805}
806
Sujithfe7f4a72008-11-18 09:07:06 +0530807static void ath_rc_rate_set_series(struct ath_rate_table *rate_table ,
Sujitha8efee42008-11-18 09:07:30 +0530808 struct ieee80211_tx_rate *rate,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700809 u8 tries,
810 u8 rix,
811 int rtsctsenable)
812{
Sujitha8efee42008-11-18 09:07:30 +0530813 rate->count = tries;
814 rate->idx = rix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700815
Sujitha8efee42008-11-18 09:07:30 +0530816 if (rtsctsenable)
817 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
818 if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
819 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
820 if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
821 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
822 if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
823 rate->flags |= IEEE80211_TX_RC_MCS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700824}
825
826static u8 ath_rc_rate_getidx(struct ath_softc *sc,
Sujithdc2222a2008-08-14 13:26:55 +0530827 struct ath_rate_node *ath_rc_priv,
Sujithfe7f4a72008-11-18 09:07:06 +0530828 struct ath_rate_table *rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530829 u8 rix, u16 stepdown,
830 u16 min_rate)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700831{
832 u32 j;
833 u8 nextindex;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700834
835 if (min_rate) {
836 for (j = RATE_TABLE_SIZE; j > 0; j--) {
837 if (ath_rc_get_nextlowervalid_txrate(rate_table,
Sujith256b77592008-11-18 09:03:12 +0530838 ath_rc_priv, rix, &nextindex))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700839 rix = nextindex;
840 else
841 break;
842 }
843 } else {
844 for (j = stepdown; j > 0; j--) {
845 if (ath_rc_get_nextlowervalid_txrate(rate_table,
Sujith256b77592008-11-18 09:03:12 +0530846 ath_rc_priv, rix, &nextindex))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700847 rix = nextindex;
848 else
849 break;
850 }
851 }
852 return rix;
853}
854
855static void ath_rc_ratefind(struct ath_softc *sc,
856 struct ath_rate_node *ath_rc_priv,
857 int num_tries, int num_rates, unsigned int rcflag,
Sujitha8efee42008-11-18 09:07:30 +0530858 struct ieee80211_tx_info *tx_info, int *is_probe,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700859 int is_retry)
860{
861 u8 try_per_rate = 0, i = 0, rix, nrix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700862 struct ath_rate_table *rate_table;
Sujitha8efee42008-11-18 09:07:30 +0530863 struct ieee80211_tx_rate *rates = tx_info->control.rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700864
Sujithfe7f4a72008-11-18 09:07:06 +0530865 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700866 rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530867 (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
868 is_probe, is_retry);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700869 nrix = rix;
870
871 if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) {
872 /* set one try for probe rates. For the
873 * probes don't enable rts */
874 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530875 &rates[i++], 1, nrix, FALSE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700876
877 try_per_rate = (num_tries/num_rates);
878 /* Get the next tried/allowed rate. No RTS for the next series
879 * after the probe rate
880 */
881 nrix = ath_rc_rate_getidx(sc,
882 ath_rc_priv, rate_table, nrix, 1, FALSE);
883 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530884 &rates[i++], try_per_rate, nrix, 0);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700885 } else {
886 try_per_rate = (num_tries/num_rates);
887 /* Set the choosen rate. No RTS for first series entry. */
888 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530889 &rates[i++], try_per_rate, nrix, FALSE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700890 }
891
892 /* Fill in the other rates for multirate retry */
893 for ( ; i < num_rates; i++) {
894 u8 try_num;
895 u8 min_rate;
896
897 try_num = ((i + 1) == num_rates) ?
898 num_tries - (try_per_rate * i) : try_per_rate ;
899 min_rate = (((i + 1) == num_rates) &&
Sujithdc2222a2008-08-14 13:26:55 +0530900 (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700901
902 nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
Sujithdc2222a2008-08-14 13:26:55 +0530903 rate_table, nrix, 1, min_rate);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700904 /* All other rates in the series have RTS enabled */
905 ath_rc_rate_set_series(rate_table,
Sujitha8efee42008-11-18 09:07:30 +0530906 &rates[i], try_num, nrix, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700907 }
908
909 /*
910 * NB:Change rate series to enable aggregation when operating
911 * at lower MCS rates. When first rate in series is MCS2
912 * in HT40 @ 2.4GHz, series should look like:
913 *
914 * {MCS2, MCS1, MCS0, MCS0}.
915 *
916 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
917 * look like:
918 *
919 * {MCS3, MCS2, MCS1, MCS1}
920 *
921 * So, set fourth rate in series to be same as third one for
922 * above conditions.
923 */
Sujith86b89ee2008-08-07 10:54:57 +0530924 if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
Sujithdc2222a2008-08-14 13:26:55 +0530925 (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
926 (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700927 u8 dot11rate = rate_table->info[rix].dot11rate;
928 u8 phy = rate_table->info[rix].phy;
929 if (i == 4 &&
930 ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
Sujithdc2222a2008-08-14 13:26:55 +0530931 (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
Sujitha8efee42008-11-18 09:07:30 +0530932 rates[3].idx = rates[2].idx;
933 rates[3].flags = rates[2].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700934 }
935 }
936}
937
938/*
939 * Return the Tx rate series.
940 */
Sujith5701ed82008-08-26 08:11:26 +0530941static void ath_rate_findrate(struct ath_softc *sc,
942 struct ath_rate_node *ath_rc_priv,
943 int num_tries,
944 int num_rates,
945 unsigned int rcflag,
Sujitha8efee42008-11-18 09:07:30 +0530946 struct ieee80211_tx_info *tx_info,
Sujith5701ed82008-08-26 08:11:26 +0530947 int *is_probe,
948 int is_retry)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700949{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700950 if (!num_rates || !num_tries)
951 return;
952
Sujith2b406f12008-11-18 09:05:35 +0530953 ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates,
Sujitha8efee42008-11-18 09:07:30 +0530954 rcflag, tx_info, is_probe, is_retry);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700955}
956
957static void ath_rc_update_ht(struct ath_softc *sc,
958 struct ath_rate_node *ath_rc_priv,
959 struct ath_tx_info_priv *info_priv,
960 int tx_rate, int xretries, int retries)
961{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700962 u32 now_msec = jiffies_to_msecs(jiffies);
963 int state_change = FALSE, rate, count;
964 u8 last_per;
Sujithfe7f4a72008-11-18 09:07:06 +0530965 struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700966 static u32 nretry_to_per_lookup[10] = {
967 100 * 0 / 1,
968 100 * 1 / 4,
969 100 * 1 / 2,
970 100 * 3 / 4,
971 100 * 4 / 5,
972 100 * 5 / 6,
973 100 * 6 / 7,
974 100 * 7 / 8,
975 100 * 8 / 9,
976 100 * 9 / 10
977 };
978
979 if (!ath_rc_priv)
980 return;
981
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700982 ASSERT(tx_rate >= 0);
983 if (tx_rate < 0)
984 return;
985
986 /* To compensate for some imbalance between ctrl and ext. channel */
987
988 if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
989 info_priv->tx.ts_rssi =
990 info_priv->tx.ts_rssi < 3 ? 0 :
991 info_priv->tx.ts_rssi - 3;
992
Sujith256b77592008-11-18 09:03:12 +0530993 last_per = ath_rc_priv->state[tx_rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700994
995 if (xretries) {
996 /* Update the PER. */
997 if (xretries == 1) {
Sujith256b77592008-11-18 09:03:12 +0530998 ath_rc_priv->state[tx_rate].per += 30;
999 if (ath_rc_priv->state[tx_rate].per > 100)
1000 ath_rc_priv->state[tx_rate].per = 100;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001001 } else {
1002 /* xretries == 2 */
Julia Lawall87c16872008-11-09 17:56:10 +01001003 count = ARRAY_SIZE(nretry_to_per_lookup);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001004 if (retries >= count)
1005 retries = count - 1;
1006 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
Sujith256b77592008-11-18 09:03:12 +05301007 ath_rc_priv->state[tx_rate].per =
1008 (u8)(ath_rc_priv->state[tx_rate].per -
1009 (ath_rc_priv->state[tx_rate].per >> 3) +
Sujithdc2222a2008-08-14 13:26:55 +05301010 ((100) >> 3));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001011 }
1012
1013 /* xretries == 1 or 2 */
1014
Sujith256b77592008-11-18 09:03:12 +05301015 if (ath_rc_priv->probe_rate == tx_rate)
1016 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001017
1018 } else { /* xretries == 0 */
1019 /* Update the PER. */
1020 /* Make sure it doesn't index out of array's bounds. */
Julia Lawall87c16872008-11-09 17:56:10 +01001021 count = ARRAY_SIZE(nretry_to_per_lookup);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001022 if (retries >= count)
1023 retries = count - 1;
1024 if (info_priv->n_bad_frames) {
Sujithdc2222a2008-08-14 13:26:55 +05301025 /* new_PER = 7/8*old_PER + 1/8*(currentPER)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001026 * Assuming that n_frames is not 0. The current PER
1027 * from the retries is 100 * retries / (retries+1),
1028 * since the first retries attempts failed, and the
1029 * next one worked. For the one that worked,
1030 * n_bad_frames subframes out of n_frames wored,
1031 * so the PER for that part is
1032 * 100 * n_bad_frames / n_frames, and it contributes
1033 * 100 * n_bad_frames / (n_frames * (retries+1)) to
1034 * the above PER. The expression below is a
1035 * simplified version of the sum of these two terms.
1036 */
1037 if (info_priv->n_frames > 0)
Sujith256b77592008-11-18 09:03:12 +05301038 ath_rc_priv->state[tx_rate].per
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001039 = (u8)
Sujith256b77592008-11-18 09:03:12 +05301040 (ath_rc_priv->state[tx_rate].per -
1041 (ath_rc_priv->state[tx_rate].per >> 3) +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001042 ((100*(retries*info_priv->n_frames +
1043 info_priv->n_bad_frames) /
1044 (info_priv->n_frames *
1045 (retries+1))) >> 3));
1046 } else {
1047 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
1048
Sujith256b77592008-11-18 09:03:12 +05301049 ath_rc_priv->state[tx_rate].per = (u8)
1050 (ath_rc_priv->state[tx_rate].per -
1051 (ath_rc_priv->state[tx_rate].per >> 3) +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001052 (nretry_to_per_lookup[retries] >> 3));
1053 }
1054
Sujith256b77592008-11-18 09:03:12 +05301055 ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
1056 ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last;
1057 ath_rc_priv->rssi_last = info_priv->tx.ts_rssi;
1058 ath_rc_priv->rssi_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001059
1060 /*
1061 * If we got at most one retry then increase the max rate if
1062 * this was a probe. Otherwise, ignore the probe.
1063 */
1064
Sujith256b77592008-11-18 09:03:12 +05301065 if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001066 if (retries > 0 || 2 * info_priv->n_bad_frames >
1067 info_priv->n_frames) {
1068 /*
1069 * Since we probed with just a single attempt,
1070 * any retries means the probe failed. Also,
1071 * if the attempt worked, but more than half
1072 * the subframes were bad then also consider
1073 * the probe a failure.
1074 */
Sujith256b77592008-11-18 09:03:12 +05301075 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001076 } else {
1077 u8 probe_rate = 0;
1078
Sujith256b77592008-11-18 09:03:12 +05301079 ath_rc_priv->rate_max_phy = ath_rc_priv->probe_rate;
1080 probe_rate = ath_rc_priv->probe_rate;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001081
Sujith256b77592008-11-18 09:03:12 +05301082 if (ath_rc_priv->state[probe_rate].per > 30)
1083 ath_rc_priv->state[probe_rate].per = 20;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001084
Sujith256b77592008-11-18 09:03:12 +05301085 ath_rc_priv->probe_rate = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001086
1087 /*
1088 * Since this probe succeeded, we allow the next
1089 * probe twice as soon. This allows the maxRate
1090 * to move up faster if the probes are
1091 * succesful.
1092 */
Sujith256b77592008-11-18 09:03:12 +05301093 ath_rc_priv->probe_time = now_msec -
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001094 rate_table->probe_interval / 2;
1095 }
1096 }
1097
1098 if (retries > 0) {
1099 /*
1100 * Don't update anything. We don't know if
1101 * this was because of collisions or poor signal.
1102 *
1103 * Later: if rssi_ack is close to
Sujith256b77592008-11-18 09:03:12 +05301104 * ath_rc_priv->state[txRate].rssi_thres and we see lots
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001105 * of retries, then we could increase
Sujith256b77592008-11-18 09:03:12 +05301106 * ath_rc_priv->state[txRate].rssi_thres.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001107 */
Sujith256b77592008-11-18 09:03:12 +05301108 ath_rc_priv->hw_maxretry_pktcnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001109 } else {
1110 /*
1111 * It worked with no retries. First ignore bogus (small)
1112 * rssi_ack values.
1113 */
Sujith256b77592008-11-18 09:03:12 +05301114 if (tx_rate == ath_rc_priv->rate_max_phy &&
1115 ath_rc_priv->hw_maxretry_pktcnt < 255) {
1116 ath_rc_priv->hw_maxretry_pktcnt++;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001117 }
1118
1119 if (info_priv->tx.ts_rssi >=
1120 rate_table->info[tx_rate].rssi_ack_validmin) {
1121 /* Average the rssi */
Sujith256b77592008-11-18 09:03:12 +05301122 if (tx_rate != ath_rc_priv->rssi_sum_rate) {
1123 ath_rc_priv->rssi_sum_rate = tx_rate;
1124 ath_rc_priv->rssi_sum =
1125 ath_rc_priv->rssi_sum_cnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001126 }
1127
Sujith256b77592008-11-18 09:03:12 +05301128 ath_rc_priv->rssi_sum += info_priv->tx.ts_rssi;
1129 ath_rc_priv->rssi_sum_cnt++;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001130
Sujith256b77592008-11-18 09:03:12 +05301131 if (ath_rc_priv->rssi_sum_cnt > 4) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001132 int32_t rssi_ackAvg =
Sujith256b77592008-11-18 09:03:12 +05301133 (ath_rc_priv->rssi_sum + 2) / 4;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001134 int8_t rssi_thres =
Sujith256b77592008-11-18 09:03:12 +05301135 ath_rc_priv->state[tx_rate].
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001136 rssi_thres;
1137 int8_t rssi_ack_vmin =
1138 rate_table->info[tx_rate].
1139 rssi_ack_validmin;
1140
Sujith256b77592008-11-18 09:03:12 +05301141 ath_rc_priv->rssi_sum =
1142 ath_rc_priv->rssi_sum_cnt = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001143
1144 /* Now reduce the current
1145 * rssi threshold. */
1146 if ((rssi_ackAvg < rssi_thres + 2) &&
Sujithdc2222a2008-08-14 13:26:55 +05301147 (rssi_thres > rssi_ack_vmin)) {
Sujith256b77592008-11-18 09:03:12 +05301148 ath_rc_priv->state[tx_rate].
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001149 rssi_thres--;
1150 }
1151
1152 state_change = TRUE;
1153 }
1154 }
1155 }
1156 }
1157
1158 /* For all cases */
1159
1160 /*
1161 * If this rate looks bad (high PER) then stop using it for
1162 * a while (except if we are probing).
1163 */
Sujith256b77592008-11-18 09:03:12 +05301164 if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
Sujithdc2222a2008-08-14 13:26:55 +05301165 rate_table->info[tx_rate].ratekbps <=
Sujith256b77592008-11-18 09:03:12 +05301166 rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
1167 ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
1168 (u8) tx_rate, &ath_rc_priv->rate_max_phy);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001169
1170 /* Don't probe for a little while. */
Sujith256b77592008-11-18 09:03:12 +05301171 ath_rc_priv->probe_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001172 }
1173
1174 if (state_change) {
1175 /*
1176 * Make sure the rates above this have higher rssi thresholds.
1177 * (Note: Monotonicity is kept within the OFDM rates and
1178 * within the CCK rates. However, no adjustment is
1179 * made to keep the rssi thresholds monotonically
1180 * increasing between the CCK and OFDM rates.)
1181 */
1182 for (rate = tx_rate; rate <
Sujith256b77592008-11-18 09:03:12 +05301183 ath_rc_priv->rate_table_size - 1; rate++) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001184 if (rate_table->info[rate+1].phy !=
1185 rate_table->info[tx_rate].phy)
1186 break;
1187
Sujith256b77592008-11-18 09:03:12 +05301188 if (ath_rc_priv->state[rate].rssi_thres +
Sujithdc2222a2008-08-14 13:26:55 +05301189 rate_table->info[rate].rssi_ack_deltamin >
Sujith256b77592008-11-18 09:03:12 +05301190 ath_rc_priv->state[rate+1].rssi_thres) {
1191 ath_rc_priv->state[rate+1].rssi_thres =
1192 ath_rc_priv->state[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301193 rssi_thres +
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001194 rate_table->info[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301195 rssi_ack_deltamin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001196 }
1197 }
1198
1199 /* Make sure the rates below this have lower rssi thresholds. */
1200 for (rate = tx_rate - 1; rate >= 0; rate--) {
1201 if (rate_table->info[rate].phy !=
Sujithdc2222a2008-08-14 13:26:55 +05301202 rate_table->info[tx_rate].phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001203 break;
1204
Sujith256b77592008-11-18 09:03:12 +05301205 if (ath_rc_priv->state[rate].rssi_thres +
Sujithdc2222a2008-08-14 13:26:55 +05301206 rate_table->info[rate].rssi_ack_deltamin >
Sujith256b77592008-11-18 09:03:12 +05301207 ath_rc_priv->state[rate+1].rssi_thres) {
1208 if (ath_rc_priv->state[rate+1].rssi_thres <
Sujithdc2222a2008-08-14 13:26:55 +05301209 rate_table->info[rate].
1210 rssi_ack_deltamin)
Sujith256b77592008-11-18 09:03:12 +05301211 ath_rc_priv->state[rate].rssi_thres = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001212 else {
Sujith256b77592008-11-18 09:03:12 +05301213 ath_rc_priv->state[rate].rssi_thres =
1214 ath_rc_priv->state[rate+1].
Sujithdc2222a2008-08-14 13:26:55 +05301215 rssi_thres -
1216 rate_table->info[rate].
1217 rssi_ack_deltamin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001218 }
1219
Sujith256b77592008-11-18 09:03:12 +05301220 if (ath_rc_priv->state[rate].rssi_thres <
Sujithdc2222a2008-08-14 13:26:55 +05301221 rate_table->info[rate].
1222 rssi_ack_validmin) {
Sujith256b77592008-11-18 09:03:12 +05301223 ath_rc_priv->state[rate].rssi_thres =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001224 rate_table->info[rate].
Sujithdc2222a2008-08-14 13:26:55 +05301225 rssi_ack_validmin;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001226 }
1227 }
1228 }
1229 }
1230
1231 /* Make sure the rates below this have lower PER */
1232 /* Monotonicity is kept only for rates below the current rate. */
Sujith256b77592008-11-18 09:03:12 +05301233 if (ath_rc_priv->state[tx_rate].per < last_per) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001234 for (rate = tx_rate - 1; rate >= 0; rate--) {
1235 if (rate_table->info[rate].phy !=
Sujithdc2222a2008-08-14 13:26:55 +05301236 rate_table->info[tx_rate].phy)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001237 break;
1238
Sujith256b77592008-11-18 09:03:12 +05301239 if (ath_rc_priv->state[rate].per >
1240 ath_rc_priv->state[rate+1].per) {
1241 ath_rc_priv->state[rate].per =
1242 ath_rc_priv->state[rate+1].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001243 }
1244 }
1245 }
1246
1247 /* Maintain monotonicity for rates above the current rate */
Sujith256b77592008-11-18 09:03:12 +05301248 for (rate = tx_rate; rate < ath_rc_priv->rate_table_size - 1; rate++) {
1249 if (ath_rc_priv->state[rate+1].per < ath_rc_priv->state[rate].per)
1250 ath_rc_priv->state[rate+1].per =
1251 ath_rc_priv->state[rate].per;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001252 }
1253
1254 /* Every so often, we reduce the thresholds and
1255 * PER (different for CCK and OFDM). */
Sujith256b77592008-11-18 09:03:12 +05301256 if (now_msec - ath_rc_priv->rssi_down_time >=
Sujithdc2222a2008-08-14 13:26:55 +05301257 rate_table->rssi_reduce_interval) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001258
Sujith256b77592008-11-18 09:03:12 +05301259 for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
1260 if (ath_rc_priv->state[rate].rssi_thres >
Sujithdc2222a2008-08-14 13:26:55 +05301261 rate_table->info[rate].rssi_ack_validmin)
Sujith256b77592008-11-18 09:03:12 +05301262 ath_rc_priv->state[rate].rssi_thres -= 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001263 }
Sujith256b77592008-11-18 09:03:12 +05301264 ath_rc_priv->rssi_down_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001265 }
1266
1267 /* Every so often, we reduce the thresholds
1268 * and PER (different for CCK and OFDM). */
Sujith256b77592008-11-18 09:03:12 +05301269 if (now_msec - ath_rc_priv->per_down_time >=
Sujithdc2222a2008-08-14 13:26:55 +05301270 rate_table->rssi_reduce_interval) {
Sujith256b77592008-11-18 09:03:12 +05301271 for (rate = 0; rate < ath_rc_priv->rate_table_size; rate++) {
1272 ath_rc_priv->state[rate].per =
1273 7 * ath_rc_priv->state[rate].per / 8;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001274 }
1275
Sujith256b77592008-11-18 09:03:12 +05301276 ath_rc_priv->per_down_time = now_msec;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001277 }
1278}
1279
1280/*
1281 * This routine is called in rate control callback tx_status() to give
1282 * the status of previous frames.
1283 */
1284static void ath_rc_update(struct ath_softc *sc,
1285 struct ath_rate_node *ath_rc_priv,
Sujitha8efee42008-11-18 09:07:30 +05301286 struct ieee80211_tx_info *tx_info, int final_ts_idx,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001287 int xretries, int long_retry)
1288{
Sujitha8efee42008-11-18 09:07:30 +05301289 struct ath_tx_info_priv *info_priv =
1290 (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001291 struct ath_rate_table *rate_table;
Sujitha8efee42008-11-18 09:07:30 +05301292 struct ieee80211_tx_rate *rates = tx_info->status.rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001293 u8 flags;
1294 u32 series = 0, rix;
1295
Sujithfe7f4a72008-11-18 09:07:06 +05301296 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001297
1298 /*
1299 * If the first rate is not the final index, there
1300 * are intermediate rate failures to be processed.
1301 */
1302 if (final_ts_idx != 0) {
1303 /* Process intermediate rates that failed.*/
1304 for (series = 0; series < final_ts_idx ; series++) {
Sujitha8efee42008-11-18 09:07:30 +05301305 if (rates[series].count != 0) {
1306 flags = rates[series].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001307 /* If HT40 and we have switched mode from
1308 * 40 to 20 => don't update */
Sujitha8efee42008-11-18 09:07:30 +05301309 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
Sujith256b77592008-11-18 09:03:12 +05301310 (ath_rc_priv->rc_phy_mode !=
Sujitha8efee42008-11-18 09:07:30 +05301311 (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001312 return;
Sujitha8efee42008-11-18 09:07:30 +05301313 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1314 (flags & IEEE80211_TX_RC_SHORT_GI))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001315 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301316 rates[series].idx].ht_index;
1317 else if (flags & IEEE80211_TX_RC_SHORT_GI)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001318 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301319 rates[series].idx].sgi_index;
1320 else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001321 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301322 rates[series].idx].cw40index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001323 else
1324 rix = rate_table->info[
Sujitha8efee42008-11-18 09:07:30 +05301325 rates[series].idx].base_index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001326 ath_rc_update_ht(sc, ath_rc_priv,
1327 info_priv, rix,
1328 xretries ? 1 : 2,
Sujitha8efee42008-11-18 09:07:30 +05301329 rates[series].count);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001330 }
1331 }
1332 } else {
1333 /*
1334 * Handle the special case of MIMO PS burst, where the second
1335 * aggregate is sent out with only one rate and one try.
1336 * Treating it as an excessive retry penalizes the rate
1337 * inordinately.
1338 */
Sujitha8efee42008-11-18 09:07:30 +05301339 if (rates[0].count == 1 && xretries == 1)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001340 xretries = 2;
1341 }
1342
Sujitha8efee42008-11-18 09:07:30 +05301343 flags = rates[series].flags;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001344 /* If HT40 and we have switched mode from 40 to 20 => don't update */
Sujitha8efee42008-11-18 09:07:30 +05301345 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1346 (ath_rc_priv->rc_phy_mode != (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001347 return;
1348
Sujitha8efee42008-11-18 09:07:30 +05301349 if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && (flags & IEEE80211_TX_RC_SHORT_GI))
1350 rix = rate_table->info[rates[series].idx].ht_index;
1351 else if (flags & IEEE80211_TX_RC_SHORT_GI)
1352 rix = rate_table->info[rates[series].idx].sgi_index;
1353 else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1354 rix = rate_table->info[rates[series].idx].cw40index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001355 else
Sujitha8efee42008-11-18 09:07:30 +05301356 rix = rate_table->info[rates[series].idx].base_index;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001357
1358 ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix,
1359 xretries, long_retry);
1360}
1361
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001362/*
1363 * Process a tx descriptor for a completed transmit (success or failure).
1364 */
1365static void ath_rate_tx_complete(struct ath_softc *sc,
1366 struct ath_node *an,
1367 struct ath_rate_node *rc_priv,
Sujitha8efee42008-11-18 09:07:30 +05301368 struct ieee80211_tx_info *tx_info)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001369{
Sujitha8efee42008-11-18 09:07:30 +05301370 struct ath_tx_info_priv *info_priv =
1371 (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001372 int final_ts_idx = info_priv->tx.ts_rateindex;
1373 int tx_status = 0, is_underrun = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001374
Sujith2b406f12008-11-18 09:05:35 +05301375 if (info_priv->tx.ts_status & ATH9K_TXERR_FILT)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001376 return;
1377
1378 if (info_priv->tx.ts_rssi > 0) {
1379 ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
Sujithdc2222a2008-08-14 13:26:55 +05301380 info_priv->tx.ts_rssi);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001381 }
1382
1383 /*
1384 * If underrun error is seen assume it as an excessive retry only
1385 * if prefetch trigger level have reached the max (0x3f for 5416)
1386 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
1387 * times. This affects how ratectrl updates PER for the failed rate.
1388 */
1389 if (info_priv->tx.ts_flags &
1390 (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
Sujithfe7f4a72008-11-18 09:07:06 +05301391 ((sc->sc_ah->ah_txTrigLevel) >= rc_priv->tx_triglevel_max)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001392 tx_status = 1;
1393 is_underrun = 1;
1394 }
1395
1396 if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
1397 (info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
1398 tx_status = 1;
1399
Sujitha8efee42008-11-18 09:07:30 +05301400 ath_rc_update(sc, rc_priv, tx_info, final_ts_idx, tx_status,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001401 (is_underrun) ? ATH_11N_TXMAXTRY :
1402 info_priv->tx.ts_longretry);
1403}
1404
Sujith5ddfac32008-11-18 09:06:44 +05301405static void ath_rc_init(struct ath_softc *sc,
1406 struct ath_rate_node *ath_rc_priv,
1407 struct ieee80211_supported_band *sband,
1408 struct ieee80211_sta *sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001409{
1410 struct ath_rate_table *rate_table = NULL;
Sujith5ddfac32008-11-18 09:06:44 +05301411 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1412 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001413 u8 i, j, k, hi = 0, hthi = 0;
1414
Sujithfe7f4a72008-11-18 09:07:06 +05301415 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001416
Sujith5ddfac32008-11-18 09:06:44 +05301417 if (sta->ht_cap.ht_supported) {
1418 if (sband->band == IEEE80211_BAND_2GHZ)
Sujithfe7f4a72008-11-18 09:07:06 +05301419 rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301420 else
Sujithfe7f4a72008-11-18 09:07:06 +05301421 rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301422
1423 ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
1424 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1425 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
1426 }
1427
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001428 /* Initial rate table size. Will change depending
1429 * on the working rate set */
Sujith256b77592008-11-18 09:03:12 +05301430 ath_rc_priv->rate_table_size = MAX_TX_RATE_TBL;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001431
1432 /* Initialize thresholds according to the global rate table */
Sujith5ddfac32008-11-18 09:06:44 +05301433 for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
Sujith256b77592008-11-18 09:03:12 +05301434 ath_rc_priv->state[i].rssi_thres =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001435 rate_table->info[i].rssi_ack_validmin;
Sujith256b77592008-11-18 09:03:12 +05301436 ath_rc_priv->state[i].per = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001437 }
1438
1439 /* Determine the valid rates */
Sujith256b77592008-11-18 09:03:12 +05301440 ath_rc_init_valid_txmask(ath_rc_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001441
1442 for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
1443 for (j = 0; j < MAX_TX_RATE_PHY; j++)
Sujith256b77592008-11-18 09:03:12 +05301444 ath_rc_priv->valid_phy_rateidx[i][j] = 0;
1445 ath_rc_priv->valid_phy_ratecnt[i] = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001446 }
Sujith5ddfac32008-11-18 09:06:44 +05301447 ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001448
1449 /* Set stream capability */
Sujith5ddfac32008-11-18 09:06:44 +05301450 ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001451
1452 if (!rateset->rs_nrates) {
1453 /* No working rate, just initialize valid rates */
1454 hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301455 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001456 } else {
1457 /* Use intersection of working rates and valid rates */
1458 hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301459 rateset, ath_rc_priv->ht_cap);
1460 if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001461 hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv,
1462 rate_table,
1463 ht_mcs,
Sujith5ddfac32008-11-18 09:06:44 +05301464 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001465 }
1466 hi = A_MAX(hi, hthi);
1467 }
1468
Sujith256b77592008-11-18 09:03:12 +05301469 ath_rc_priv->rate_table_size = hi + 1;
1470 ath_rc_priv->rate_max_phy = 0;
1471 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001472
1473 for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
Sujith256b77592008-11-18 09:03:12 +05301474 for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
1475 ath_rc_priv->valid_rate_index[k++] =
1476 ath_rc_priv->valid_phy_rateidx[i][j];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001477 }
1478
1479 if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE)
Sujith256b77592008-11-18 09:03:12 +05301480 || !ath_rc_priv->valid_phy_ratecnt[i])
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001481 continue;
1482
Sujith256b77592008-11-18 09:03:12 +05301483 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001484 }
Sujith256b77592008-11-18 09:03:12 +05301485 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001486 ASSERT(k <= MAX_TX_RATE_TBL);
1487
Sujith256b77592008-11-18 09:03:12 +05301488 ath_rc_priv->max_valid_rate = k;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001489 /*
1490 * Some third party vendors don't send the supported rate series in
1491 * order. So sorting to make sure its in order, otherwise our RateFind
1492 * Algo will select wrong rates
1493 */
Sujith256b77592008-11-18 09:03:12 +05301494 ath_rc_sort_validrates(rate_table, ath_rc_priv);
1495 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001496}
1497
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001498/* Rate Control callbacks */
Johannes Berg4b7679a2008-09-18 18:14:18 +02001499static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1500 struct ieee80211_sta *sta, void *priv_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001501 struct sk_buff *skb)
1502{
1503 struct ath_softc *sc = priv;
1504 struct ath_tx_info_priv *tx_info_priv;
1505 struct ath_node *an;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001506 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1507 struct ieee80211_hdr *hdr;
1508 __le16 fc;
1509
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001510 hdr = (struct ieee80211_hdr *)skb->data;
1511 fc = hdr->frame_control;
Sujitha8efee42008-11-18 09:07:30 +05301512 tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001513
Sujithb5aa9bf2008-10-29 10:13:31 +05301514 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001515
Johannes Berge6a98542008-10-21 12:40:02 +02001516 if (tx_info_priv == NULL)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001517 return;
Johannes Berge6a98542008-10-21 12:40:02 +02001518
1519 if (an && priv_sta && ieee80211_is_data(fc))
Sujitha8efee42008-11-18 09:07:30 +05301520 ath_rate_tx_complete(sc, an, priv_sta, tx_info);
Johannes Berge6a98542008-10-21 12:40:02 +02001521
1522 kfree(tx_info_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001523}
1524
Johannes Berge6a98542008-10-21 12:40:02 +02001525static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
1526 struct ieee80211_tx_rate_control *txrc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001527{
Johannes Berge6a98542008-10-21 12:40:02 +02001528 struct ieee80211_supported_band *sband = txrc->sband;
1529 struct sk_buff *skb = txrc->skb;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001530 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Johannes Berg4b7679a2008-09-18 18:14:18 +02001531 struct ath_softc *sc = priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001532 struct ieee80211_hw *hw = sc->hw;
Johannes Berg4b7679a2008-09-18 18:14:18 +02001533 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001534 struct ath_node *an;
1535 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujithccc75c52008-10-29 10:18:14 +05301536 int is_probe = FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001537 __le16 fc = hdr->frame_control;
1538 u8 *qc, tid;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001539
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001540 /* lowest rate for management and multicast/broadcast frames */
Sujitha8efee42008-11-18 09:07:30 +05301541 if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
1542 tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
1543 tx_info->control.rates[0].count =
1544 is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001545 return;
1546 }
1547
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001548 /* Find tx rate for unicast frames */
1549 ath_rate_findrate(sc, ath_rc_priv,
1550 ATH_11N_TXMAXTRY, 4,
1551 ATH_RC_PROBE_ALLOWED,
Sujitha8efee42008-11-18 09:07:30 +05301552 tx_info,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001553 &is_probe,
1554 false);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001555
1556 /* Check if aggregation has to be enabled for this tid */
Johannes Bergae5eb022008-10-14 16:58:37 +02001557 if (hw->conf.ht.enabled) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001558 if (ieee80211_is_data_qos(fc)) {
1559 qc = ieee80211_get_qos_ctl(hdr);
1560 tid = qc[0] & 0xf;
Sujithb5aa9bf2008-10-29 10:13:31 +05301561 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001562
Sujithccc75c52008-10-29 10:18:14 +05301563 if(ath_tx_aggr_check(sc, an, tid))
1564 ieee80211_start_tx_ba_session(hw, hdr->addr1, tid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001565 }
1566 }
1567}
1568
Johannes Berg4b7679a2008-09-18 18:14:18 +02001569static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1570 struct ieee80211_sta *sta, void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001571{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001572 struct ath_softc *sc = priv;
Sujithdc2222a2008-08-14 13:26:55 +05301573 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001574 int i, j = 0;
1575
Sujith7b4d2732008-11-18 09:04:00 +05301576 for (i = 0; i < sband->n_bitrates; i++) {
1577 if (sta->supp_rates[sband->band] & BIT(i)) {
1578 ath_rc_priv->neg_rates.rs_rates[j]
1579 = (sband->bitrates[i].bitrate * 2) / 10;
1580 j++;
1581 }
1582 }
1583 ath_rc_priv->neg_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001584
Sujitha4510bf2008-10-23 12:15:19 +05301585 if (sta->ht_cap.ht_supported) {
Sujith7b4d2732008-11-18 09:04:00 +05301586 for (i = 0, j = 0; i < 77; i++) {
Johannes Bergae5eb022008-10-14 16:58:37 +02001587 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
Sujithdc2222a2008-08-14 13:26:55 +05301588 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001589 if (j == ATH_RATE_MAX)
1590 break;
1591 }
Sujithdc2222a2008-08-14 13:26:55 +05301592 ath_rc_priv->neg_ht_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001593 }
Sujith7b4d2732008-11-18 09:04:00 +05301594
Sujith5ddfac32008-11-18 09:06:44 +05301595 ath_rc_init(sc, priv_sta, sband, sta);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001596}
1597
Johannes Berg4b7679a2008-09-18 18:14:18 +02001598static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001599{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001600 return hw->priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001601}
1602
1603static void ath_rate_free(void *priv)
1604{
1605 return;
1606}
1607
Johannes Berg4b7679a2008-09-18 18:14:18 +02001608static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001609{
1610 struct ath_softc *sc = priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001611 struct ath_rate_node *rate_priv;
1612
Sujithfe605942008-11-18 09:03:36 +05301613 rate_priv = kzalloc(sizeof(struct ath_rate_node), gfp);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001614 if (!rate_priv) {
Sujithdc2222a2008-08-14 13:26:55 +05301615 DPRINTF(sc, ATH_DBG_FATAL,
1616 "%s: Unable to allocate private rc structure\n",
1617 __func__);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001618 return NULL;
1619 }
Sujithfe605942008-11-18 09:03:36 +05301620
Sujithfe605942008-11-18 09:03:36 +05301621 rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
Sujithfe7f4a72008-11-18 09:07:06 +05301622 rate_priv->tx_triglevel_max = sc->sc_ah->ah_caps.tx_triglevel_max;
Sujithdc2222a2008-08-14 13:26:55 +05301623
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001624 return rate_priv;
1625}
1626
Johannes Berg4b7679a2008-09-18 18:14:18 +02001627static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
1628 void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001629{
1630 struct ath_rate_node *rate_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001631
Sujithfe605942008-11-18 09:03:36 +05301632 kfree(rate_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001633}
1634
1635static struct rate_control_ops ath_rate_ops = {
1636 .module = NULL,
1637 .name = "ath9k_rate_control",
1638 .tx_status = ath_tx_status,
1639 .get_rate = ath_get_rate,
1640 .rate_init = ath_rate_init,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001641 .alloc = ath_rate_alloc,
1642 .free = ath_rate_free,
1643 .alloc_sta = ath_rate_alloc_sta,
Johannes Berg4b7679a2008-09-18 18:14:18 +02001644 .free_sta = ath_rate_free_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001645};
1646
Sujithfe7f4a72008-11-18 09:07:06 +05301647void ath_rate_attach(struct ath_softc *sc)
1648{
1649 sc->hw_rate_table[ATH9K_MODE_11B] =
1650 &ar5416_11b_ratetable;
1651 sc->hw_rate_table[ATH9K_MODE_11A] =
1652 &ar5416_11a_ratetable;
1653 sc->hw_rate_table[ATH9K_MODE_11G] =
1654 &ar5416_11g_ratetable;
1655 sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
1656 &ar5416_11na_ratetable;
1657 sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
1658 &ar5416_11ng_ratetable;
1659 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
1660 &ar5416_11na_ratetable;
1661 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
1662 &ar5416_11na_ratetable;
1663 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
1664 &ar5416_11ng_ratetable;
1665 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
1666 &ar5416_11ng_ratetable;
1667}
1668
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001669int ath_rate_control_register(void)
1670{
1671 return ieee80211_rate_control_register(&ath_rate_ops);
1672}
1673
1674void ath_rate_control_unregister(void)
1675{
1676 ieee80211_rate_control_unregister(&ath_rate_ops);
1677}
1678