blob: 59c146cdd0db159c9fbae83ff9f71dfe31d7bf5a [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 ,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700808 struct ath_rc_series *series,
809 u8 tries,
810 u8 rix,
811 int rtsctsenable)
812{
813 series->tries = tries;
814 series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) |
815 (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ?
816 ATH_RC_DS_FLAG : 0) |
817 (WLAN_RC_PHY_40(rate_table->info[rix].phy) ?
818 ATH_RC_CW40_FLAG : 0) |
819 (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ?
820 ATH_RC_SGI_FLAG : 0);
821
822 series->rix = rate_table->info[rix].base_index;
823 series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen;
824}
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,
858 struct ath_rc_series series[], int *is_probe,
859 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;
863
Sujithfe7f4a72008-11-18 09:07:06 +0530864 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700865 rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530866 (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
867 is_probe, is_retry);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700868 nrix = rix;
869
870 if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) {
871 /* set one try for probe rates. For the
872 * probes don't enable rts */
873 ath_rc_rate_set_series(rate_table,
874 &series[i++], 1, nrix, FALSE);
875
876 try_per_rate = (num_tries/num_rates);
877 /* Get the next tried/allowed rate. No RTS for the next series
878 * after the probe rate
879 */
880 nrix = ath_rc_rate_getidx(sc,
881 ath_rc_priv, rate_table, nrix, 1, FALSE);
882 ath_rc_rate_set_series(rate_table,
883 &series[i++], try_per_rate, nrix, 0);
884 } else {
885 try_per_rate = (num_tries/num_rates);
886 /* Set the choosen rate. No RTS for first series entry. */
887 ath_rc_rate_set_series(rate_table,
888 &series[i++], try_per_rate, nrix, FALSE);
889 }
890
891 /* Fill in the other rates for multirate retry */
892 for ( ; i < num_rates; i++) {
893 u8 try_num;
894 u8 min_rate;
895
896 try_num = ((i + 1) == num_rates) ?
897 num_tries - (try_per_rate * i) : try_per_rate ;
898 min_rate = (((i + 1) == num_rates) &&
Sujithdc2222a2008-08-14 13:26:55 +0530899 (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700900
901 nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
Sujithdc2222a2008-08-14 13:26:55 +0530902 rate_table, nrix, 1, min_rate);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700903 /* All other rates in the series have RTS enabled */
904 ath_rc_rate_set_series(rate_table,
Sujithdc2222a2008-08-14 13:26:55 +0530905 &series[i], try_num, nrix, TRUE);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700906 }
907
908 /*
909 * NB:Change rate series to enable aggregation when operating
910 * at lower MCS rates. When first rate in series is MCS2
911 * in HT40 @ 2.4GHz, series should look like:
912 *
913 * {MCS2, MCS1, MCS0, MCS0}.
914 *
915 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
916 * look like:
917 *
918 * {MCS3, MCS2, MCS1, MCS1}
919 *
920 * So, set fourth rate in series to be same as third one for
921 * above conditions.
922 */
Sujith86b89ee2008-08-07 10:54:57 +0530923 if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
Sujithdc2222a2008-08-14 13:26:55 +0530924 (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
925 (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700926 u8 dot11rate = rate_table->info[rix].dot11rate;
927 u8 phy = rate_table->info[rix].phy;
928 if (i == 4 &&
929 ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
Sujithdc2222a2008-08-14 13:26:55 +0530930 (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700931 series[3].rix = series[2].rix;
932 series[3].flags = series[2].flags;
933 series[3].max_4ms_framelen = series[2].max_4ms_framelen;
934 }
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,
946 struct ath_rc_series series[],
947 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,
954 rcflag, series, 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,
1286 struct ath_tx_info_priv *info_priv, int final_ts_idx,
1287 int xretries, int long_retry)
1288{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001289 struct ath_rate_table *rate_table;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001290 struct ath_rc_series rcs[4];
1291 u8 flags;
1292 u32 series = 0, rix;
1293
1294 memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0]));
Sujithfe7f4a72008-11-18 09:07:06 +05301295 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001296 ASSERT(rcs[0].tries != 0);
1297
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++) {
1305 if (rcs[series].tries != 0) {
1306 flags = rcs[series].flags;
1307 /* If HT40 and we have switched mode from
1308 * 40 to 20 => don't update */
1309 if ((flags & ATH_RC_CW40_FLAG) &&
Sujith256b77592008-11-18 09:03:12 +05301310 (ath_rc_priv->rc_phy_mode !=
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001311 (flags & ATH_RC_CW40_FLAG)))
1312 return;
1313 if ((flags & ATH_RC_CW40_FLAG) &&
1314 (flags & ATH_RC_SGI_FLAG))
1315 rix = rate_table->info[
1316 rcs[series].rix].ht_index;
1317 else if (flags & ATH_RC_SGI_FLAG)
1318 rix = rate_table->info[
1319 rcs[series].rix].sgi_index;
1320 else if (flags & ATH_RC_CW40_FLAG)
1321 rix = rate_table->info[
1322 rcs[series].rix].cw40index;
1323 else
1324 rix = rate_table->info[
1325 rcs[series].rix].base_index;
1326 ath_rc_update_ht(sc, ath_rc_priv,
1327 info_priv, rix,
1328 xretries ? 1 : 2,
1329 rcs[series].tries);
1330 }
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 */
1339 if (rcs[0].tries == 1 && xretries == 1)
1340 xretries = 2;
1341 }
1342
1343 flags = rcs[series].flags;
1344 /* If HT40 and we have switched mode from 40 to 20 => don't update */
1345 if ((flags & ATH_RC_CW40_FLAG) &&
Sujith256b77592008-11-18 09:03:12 +05301346 (ath_rc_priv->rc_phy_mode != (flags & ATH_RC_CW40_FLAG)))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001347 return;
1348
1349 if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG))
1350 rix = rate_table->info[rcs[series].rix].ht_index;
1351 else if (flags & ATH_RC_SGI_FLAG)
1352 rix = rate_table->info[rcs[series].rix].sgi_index;
1353 else if (flags & ATH_RC_CW40_FLAG)
1354 rix = rate_table->info[rcs[series].rix].cw40index;
1355 else
1356 rix = rate_table->info[rcs[series].rix].base_index;
1357
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,
1368 struct ath_tx_info_priv *info_priv)
1369{
1370 int final_ts_idx = info_priv->tx.ts_rateindex;
1371 int tx_status = 0, is_underrun = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001372
Sujith2b406f12008-11-18 09:05:35 +05301373 if (info_priv->tx.ts_status & ATH9K_TXERR_FILT)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001374 return;
1375
1376 if (info_priv->tx.ts_rssi > 0) {
1377 ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
Sujithdc2222a2008-08-14 13:26:55 +05301378 info_priv->tx.ts_rssi);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001379 }
1380
1381 /*
1382 * If underrun error is seen assume it as an excessive retry only
1383 * if prefetch trigger level have reached the max (0x3f for 5416)
1384 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
1385 * times. This affects how ratectrl updates PER for the failed rate.
1386 */
1387 if (info_priv->tx.ts_flags &
1388 (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
Sujithfe7f4a72008-11-18 09:07:06 +05301389 ((sc->sc_ah->ah_txTrigLevel) >= rc_priv->tx_triglevel_max)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001390 tx_status = 1;
1391 is_underrun = 1;
1392 }
1393
1394 if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
1395 (info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
1396 tx_status = 1;
1397
1398 ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status,
1399 (is_underrun) ? ATH_11N_TXMAXTRY :
1400 info_priv->tx.ts_longretry);
1401}
1402
Sujith5ddfac32008-11-18 09:06:44 +05301403static void ath_rc_init(struct ath_softc *sc,
1404 struct ath_rate_node *ath_rc_priv,
1405 struct ieee80211_supported_band *sband,
1406 struct ieee80211_sta *sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001407{
1408 struct ath_rate_table *rate_table = NULL;
Sujith5ddfac32008-11-18 09:06:44 +05301409 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1410 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001411 u8 i, j, k, hi = 0, hthi = 0;
1412
Sujithfe7f4a72008-11-18 09:07:06 +05301413 rate_table = sc->hw_rate_table[sc->sc_curmode];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001414
Sujith5ddfac32008-11-18 09:06:44 +05301415 if (sta->ht_cap.ht_supported) {
1416 if (sband->band == IEEE80211_BAND_2GHZ)
Sujithfe7f4a72008-11-18 09:07:06 +05301417 rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301418 else
Sujithfe7f4a72008-11-18 09:07:06 +05301419 rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
Sujith5ddfac32008-11-18 09:06:44 +05301420
1421 ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
1422 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1423 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
1424 }
1425
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001426 /* Initial rate table size. Will change depending
1427 * on the working rate set */
Sujith256b77592008-11-18 09:03:12 +05301428 ath_rc_priv->rate_table_size = MAX_TX_RATE_TBL;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001429
1430 /* Initialize thresholds according to the global rate table */
Sujith5ddfac32008-11-18 09:06:44 +05301431 for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
Sujith256b77592008-11-18 09:03:12 +05301432 ath_rc_priv->state[i].rssi_thres =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001433 rate_table->info[i].rssi_ack_validmin;
Sujith256b77592008-11-18 09:03:12 +05301434 ath_rc_priv->state[i].per = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001435 }
1436
1437 /* Determine the valid rates */
Sujith256b77592008-11-18 09:03:12 +05301438 ath_rc_init_valid_txmask(ath_rc_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001439
1440 for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
1441 for (j = 0; j < MAX_TX_RATE_PHY; j++)
Sujith256b77592008-11-18 09:03:12 +05301442 ath_rc_priv->valid_phy_rateidx[i][j] = 0;
1443 ath_rc_priv->valid_phy_ratecnt[i] = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001444 }
Sujith5ddfac32008-11-18 09:06:44 +05301445 ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001446
1447 /* Set stream capability */
Sujith5ddfac32008-11-18 09:06:44 +05301448 ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001449
1450 if (!rateset->rs_nrates) {
1451 /* No working rate, just initialize valid rates */
1452 hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301453 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001454 } else {
1455 /* Use intersection of working rates and valid rates */
1456 hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table,
Sujith5ddfac32008-11-18 09:06:44 +05301457 rateset, ath_rc_priv->ht_cap);
1458 if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001459 hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv,
1460 rate_table,
1461 ht_mcs,
Sujith5ddfac32008-11-18 09:06:44 +05301462 ath_rc_priv->ht_cap);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001463 }
1464 hi = A_MAX(hi, hthi);
1465 }
1466
Sujith256b77592008-11-18 09:03:12 +05301467 ath_rc_priv->rate_table_size = hi + 1;
1468 ath_rc_priv->rate_max_phy = 0;
1469 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001470
1471 for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
Sujith256b77592008-11-18 09:03:12 +05301472 for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
1473 ath_rc_priv->valid_rate_index[k++] =
1474 ath_rc_priv->valid_phy_rateidx[i][j];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001475 }
1476
1477 if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE)
Sujith256b77592008-11-18 09:03:12 +05301478 || !ath_rc_priv->valid_phy_ratecnt[i])
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001479 continue;
1480
Sujith256b77592008-11-18 09:03:12 +05301481 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001482 }
Sujith256b77592008-11-18 09:03:12 +05301483 ASSERT(ath_rc_priv->rate_table_size <= MAX_TX_RATE_TBL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001484 ASSERT(k <= MAX_TX_RATE_TBL);
1485
Sujith256b77592008-11-18 09:03:12 +05301486 ath_rc_priv->max_valid_rate = k;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001487 /*
1488 * Some third party vendors don't send the supported rate series in
1489 * order. So sorting to make sure its in order, otherwise our RateFind
1490 * Algo will select wrong rates
1491 */
Sujith256b77592008-11-18 09:03:12 +05301492 ath_rc_sort_validrates(rate_table, ath_rc_priv);
1493 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001494}
1495
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001496/* Rate Control callbacks */
Johannes Berg4b7679a2008-09-18 18:14:18 +02001497static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1498 struct ieee80211_sta *sta, void *priv_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001499 struct sk_buff *skb)
1500{
1501 struct ath_softc *sc = priv;
1502 struct ath_tx_info_priv *tx_info_priv;
1503 struct ath_node *an;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001504 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1505 struct ieee80211_hdr *hdr;
1506 __le16 fc;
1507
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001508 hdr = (struct ieee80211_hdr *)skb->data;
1509 fc = hdr->frame_control;
Johannes Berge6a98542008-10-21 12:40:02 +02001510 /* XXX: UGLY HACK!! */
1511 tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001512
Sujithb5aa9bf2008-10-29 10:13:31 +05301513 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001514
Johannes Berge6a98542008-10-21 12:40:02 +02001515 if (tx_info_priv == NULL)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001516 return;
Johannes Berge6a98542008-10-21 12:40:02 +02001517
1518 if (an && priv_sta && ieee80211_is_data(fc))
Johannes Berg4b7679a2008-09-18 18:14:18 +02001519 ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
Johannes Berge6a98542008-10-21 12:40:02 +02001520
1521 kfree(tx_info_priv);
1522 tx_info->control.vif = NULL;
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;
1533 struct ath_tx_info_priv *tx_info_priv;
Johannes Berg4b7679a2008-09-18 18:14:18 +02001534 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001535 struct ath_node *an;
1536 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujithccc75c52008-10-29 10:18:14 +05301537 int is_probe = FALSE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001538 s8 lowest_idx;
1539 __le16 fc = hdr->frame_control;
1540 u8 *qc, tid;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001541
1542 DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
1543
Johannes Berge6a98542008-10-21 12:40:02 +02001544 /* allocate driver private area of tx_info, XXX: UGLY HACK! */
1545 tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
1546 tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
1547 ASSERT(tx_info_priv != NULL);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001548
Johannes Berg4b7679a2008-09-18 18:14:18 +02001549 lowest_idx = rate_lowest_index(sband, sta);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001550 tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
1551 /* lowest rate for management and multicast/broadcast frames */
1552 if (!ieee80211_is_data(fc) ||
Sujithdc2222a2008-08-14 13:26:55 +05301553 is_multicast_ether_addr(hdr->addr1) || !sta) {
Johannes Berge6a98542008-10-21 12:40:02 +02001554 tx_info->control.rates[0].idx = lowest_idx;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001555 return;
1556 }
1557
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001558 /* Find tx rate for unicast frames */
1559 ath_rate_findrate(sc, ath_rc_priv,
1560 ATH_11N_TXMAXTRY, 4,
1561 ATH_RC_PROBE_ALLOWED,
1562 tx_info_priv->rcs,
1563 &is_probe,
1564 false);
Johannes Berge6a98542008-10-21 12:40:02 +02001565#if 0
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001566 if (is_probe)
Johannes Berg4b7679a2008-09-18 18:14:18 +02001567 sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
Johannes Berge6a98542008-10-21 12:40:02 +02001568#endif
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001569
1570 /* Ratecontrol sometimes returns invalid rate index */
1571 if (tx_info_priv->rcs[0].rix != 0xff)
1572 ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix;
1573 else
1574 tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix;
1575
Johannes Berge6a98542008-10-21 12:40:02 +02001576 tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001577
1578 /* Check if aggregation has to be enabled for this tid */
1579
Johannes Bergae5eb022008-10-14 16:58:37 +02001580 if (hw->conf.ht.enabled) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001581 if (ieee80211_is_data_qos(fc)) {
1582 qc = ieee80211_get_qos_ctl(hdr);
1583 tid = qc[0] & 0xf;
Sujithb5aa9bf2008-10-29 10:13:31 +05301584 an = (struct ath_node *)sta->drv_priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001585
Sujithccc75c52008-10-29 10:18:14 +05301586 if(ath_tx_aggr_check(sc, an, tid))
1587 ieee80211_start_tx_ba_session(hw, hdr->addr1, tid);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001588 }
1589 }
1590}
1591
Johannes Berg4b7679a2008-09-18 18:14:18 +02001592static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1593 struct ieee80211_sta *sta, void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001594{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001595 struct ath_softc *sc = priv;
Sujithdc2222a2008-08-14 13:26:55 +05301596 struct ath_rate_node *ath_rc_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001597 int i, j = 0;
1598
Sujith7b4d2732008-11-18 09:04:00 +05301599 for (i = 0; i < sband->n_bitrates; i++) {
1600 if (sta->supp_rates[sband->band] & BIT(i)) {
1601 ath_rc_priv->neg_rates.rs_rates[j]
1602 = (sband->bitrates[i].bitrate * 2) / 10;
1603 j++;
1604 }
1605 }
1606 ath_rc_priv->neg_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001607
Sujitha4510bf2008-10-23 12:15:19 +05301608 if (sta->ht_cap.ht_supported) {
Sujith7b4d2732008-11-18 09:04:00 +05301609 for (i = 0, j = 0; i < 77; i++) {
Johannes Bergae5eb022008-10-14 16:58:37 +02001610 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
Sujithdc2222a2008-08-14 13:26:55 +05301611 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001612 if (j == ATH_RATE_MAX)
1613 break;
1614 }
Sujithdc2222a2008-08-14 13:26:55 +05301615 ath_rc_priv->neg_ht_rates.rs_nrates = j;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001616 }
Sujith7b4d2732008-11-18 09:04:00 +05301617
Sujith5ddfac32008-11-18 09:06:44 +05301618 ath_rc_init(sc, priv_sta, sband, sta);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001619}
1620
Johannes Berg4b7679a2008-09-18 18:14:18 +02001621static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001622{
Johannes Berg4b7679a2008-09-18 18:14:18 +02001623 return hw->priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001624}
1625
1626static void ath_rate_free(void *priv)
1627{
1628 return;
1629}
1630
Johannes Berg4b7679a2008-09-18 18:14:18 +02001631static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001632{
1633 struct ath_softc *sc = priv;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001634 struct ath_rate_node *rate_priv;
1635
Sujithfe605942008-11-18 09:03:36 +05301636 rate_priv = kzalloc(sizeof(struct ath_rate_node), gfp);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001637 if (!rate_priv) {
Sujithdc2222a2008-08-14 13:26:55 +05301638 DPRINTF(sc, ATH_DBG_FATAL,
1639 "%s: Unable to allocate private rc structure\n",
1640 __func__);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001641 return NULL;
1642 }
Sujithfe605942008-11-18 09:03:36 +05301643
Sujithfe605942008-11-18 09:03:36 +05301644 rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
Sujithfe7f4a72008-11-18 09:07:06 +05301645 rate_priv->tx_triglevel_max = sc->sc_ah->ah_caps.tx_triglevel_max;
Sujithdc2222a2008-08-14 13:26:55 +05301646
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001647 return rate_priv;
1648}
1649
Johannes Berg4b7679a2008-09-18 18:14:18 +02001650static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
1651 void *priv_sta)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001652{
1653 struct ath_rate_node *rate_priv = priv_sta;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001654
Sujithfe605942008-11-18 09:03:36 +05301655 kfree(rate_priv);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001656}
1657
1658static struct rate_control_ops ath_rate_ops = {
1659 .module = NULL,
1660 .name = "ath9k_rate_control",
1661 .tx_status = ath_tx_status,
1662 .get_rate = ath_get_rate,
1663 .rate_init = ath_rate_init,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001664 .alloc = ath_rate_alloc,
1665 .free = ath_rate_free,
1666 .alloc_sta = ath_rate_alloc_sta,
Johannes Berg4b7679a2008-09-18 18:14:18 +02001667 .free_sta = ath_rate_free_sta,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001668};
1669
Sujithfe7f4a72008-11-18 09:07:06 +05301670void ath_rate_attach(struct ath_softc *sc)
1671{
1672 sc->hw_rate_table[ATH9K_MODE_11B] =
1673 &ar5416_11b_ratetable;
1674 sc->hw_rate_table[ATH9K_MODE_11A] =
1675 &ar5416_11a_ratetable;
1676 sc->hw_rate_table[ATH9K_MODE_11G] =
1677 &ar5416_11g_ratetable;
1678 sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
1679 &ar5416_11na_ratetable;
1680 sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
1681 &ar5416_11ng_ratetable;
1682 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
1683 &ar5416_11na_ratetable;
1684 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
1685 &ar5416_11na_ratetable;
1686 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
1687 &ar5416_11ng_ratetable;
1688 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
1689 &ar5416_11ng_ratetable;
1690}
1691
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001692int ath_rate_control_register(void)
1693{
1694 return ieee80211_rate_control_register(&ath_rate_ops);
1695}
1696
1697void ath_rate_control_unregister(void)
1698{
1699 ieee80211_rate_control_unregister(&ath_rate_ops);
1700}
1701