xref: /titanic_51/usr/src/uts/common/io/arn/arn_rc.c (revision e085f1530a2b52c62d916408e99d66a557855d42)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2004 Video54 Technologies, Inc.
8  * Copyright (c) 2004-2008 Atheros Communications, Inc.
9  *
10  * Permission to use, copy, modify, and/or distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <sys/ddi.h>
25 
26 #include "arn_core.h"
27 
28 static struct ath_rate_table ar5416_11na_ratetable = {
29 	42,
30 	{0},
31 	{
32 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
33 			5400, 0x0b, 0x00, 12,
34 			0, 2, 1, 0, 0, 0, 0, 0 },
35 		{ VALID,	VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
36 			7800,  0x0f, 0x00, 18,
37 			0, 3, 1, 1, 1, 1, 1, 0 },
38 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
39 			10000, 0x0a, 0x00, 24,
40 			2, 4, 2, 2, 2, 2, 2, 0 },
41 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
42 			13900, 0x0e, 0x00, 36,
43 			2, 6,  2, 3, 3, 3, 3, 0 },
44 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
45 			17300, 0x09, 0x00, 48,
46 			4, 10, 3, 4, 4, 4, 4, 0 },
47 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
48 			23000, 0x0d, 0x00, 72,
49 			4, 14, 3, 5, 5, 5, 5, 0 },
50 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
51 			27400, 0x08, 0x00, 96,
52 			4, 20, 3, 6, 6, 6, 6, 0 },
53 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
54 			29300, 0x0c, 0x00, 108,
55 			4, 23, 3, 7, 7, 7, 7, 0 },
56 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
57 			6400, 0x80, 0x00, 0,
58 			0, 2, 3, 8, 24, 8, 24, 3216 },
59 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
60 			12700, 0x81, 0x00, 1,
61 			2, 4, 3, 9, 25, 9, 25, 6434 },
62 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
63 			18800, 0x82, 0x00, 2,
64 			2, 6, 3, 10, 26, 10, 26, 9650 },
65 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
66 			25000, 0x83, 0x00, 3,
67 			4, 10, 3, 11, 27, 11, 27, 12868 },
68 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
69 			36700, 0x84, 0x00, 4,
70 			4, 14, 3, 12, 28, 12, 28, 19304 },
71 		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
72 			48100, 0x85, 0x00, 5,
73 			4, 20, 3, 13, 29, 13, 29, 25740 },
74 		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
75 			53500, 0x86, 0x00, 6,
76 			4, 23, 3, 14, 30, 14, 30,  28956 },
77 		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
78 			59000, 0x87, 0x00, 7,
79 			4, 25, 3, 15, 31, 15, 32, 32180 },
80 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
81 			12700, 0x88, 0x00,
82 			8, 0, 2, 3, 16, 33, 16, 33, 6430 },
83 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
84 			24800, 0x89, 0x00, 9,
85 			2, 4, 3, 17, 34, 17, 34, 12860 },
86 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
87 			36600, 0x8a, 0x00, 10,
88 			2, 6, 3, 18, 35, 18, 35, 19300 },
89 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
90 			48100, 0x8b, 0x00, 11,
91 			4, 10, 3, 19, 36, 19, 36, 25736 },
92 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
93 			69500, 0x8c, 0x00, 12,
94 			4, 14, 3, 20, 37, 20, 37, 38600 },
95 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
96 			89500, 0x8d, 0x00, 13,
97 			4, 20, 3, 21, 38, 21, 38, 51472 },
98 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
99 			98900, 0x8e, 0x00, 14,
100 			4, 23, 3, 22, 39, 22, 39, 57890 },
101 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
102 			108300, 0x8f, 0x00, 15,
103 			4, 25, 3, 23, 40, 23, 41, 64320 },
104 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
105 			13200, 0x80, 0x00, 0,
106 			0, 2, 3, 8, 24, 24, 24, 6684 },
107 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
108 			25900, 0x81, 0x00, 1,
109 			2, 4, 3, 9, 25, 25, 25, 13368 },
110 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
111 			38600, 0x82, 0x00, 2,
112 			2, 6, 3, 10, 26, 26, 26, 20052 },
113 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
114 			49800, 0x83, 0x00, 3,
115 			4, 10, 3, 11, 27, 27, 27, 26738 },
116 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
117 			72200, 0x84, 0x00, 4,
118 			4, 14, 3, 12, 28, 28, 28, 40104 },
119 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
120 			92900, 0x85, 0x00, 5,
121 			4, 20, 3, 13, 29, 29, 29, 53476 },
122 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5Mb */
123 			102700, 0x86, 0x00, 6,
124 			4, 23, 3, 14, 30, 30, 30, 60156 },
125 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
126 			112000, 0x87, 0x00, 7,
127 			4, 25, 3, 15, 31, 32, 32, 66840 },
128 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI,
129 			150000, /* 150Mb */
130 			122000, 0x87, 0x00, 7,
131 			4, 25, 3, 15, 31, 32, 32, 74200 },
132 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
133 			25800, 0x88, 0x00, 8,
134 			0, 2, 3, 16, 33, 33, 33, 13360 },
135 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
136 			49800, 0x89, 0x00, 9,
137 			2, 4, 3, 17, 34, 34, 34, 26720 },
138 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
139 			71900, 0x8a, 0x00, 10,
140 			2, 6, 3, 18, 35, 35, 35, 40080 },
141 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
142 			92500, 0x8b, 0x00, 11,
143 			4, 10, 3, 19, 36, 36, 36, 53440 },
144 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
145 			130300, 0x8c, 0x00, 12,
146 			4, 14, 3, 20, 37, 37, 37, 80160 },
147 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
148 			162800, 0x8d, 0x00, 13,
149 			4, 20, 3, 21, 38, 38, 38, 106880 },
150 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
151 			178200, 0x8e, 0x00, 14,
152 			4, 23, 3, 22, 39, 39, 39, 120240 },
153 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
154 			192100, 0x8f, 0x00, 15,
155 			4, 25, 3, 23, 40, 41, 41, 133600 },
156 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI,
157 			300000, /* 300 Mb */
158 			207000, 0x8f, 0x00, 15,
159 			4, 25, 3, 23, 40, 41, 41, 148400 },
160 	},
161 	50,  /* probe interval */
162 	50,  /* rssi reduce interval */
163 	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
164 };
165 
166 /*
167  * 4ms frame limit not used for NG mode.  The values filled
168  * for HT are the 64K max aggregate limit
169  */
170 
171 static struct ath_rate_table ar5416_11ng_ratetable = {
172 	46,
173 	{0},
174 	{
175 		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
176 			900, 0x1b, 0x00, 2,
177 			0, 0, 1, 0, 0, 0, 0, 0 },
178 		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
179 			1900, 0x1a, 0x04, 4,
180 			1, 1, 1, 1, 1, 1, 1, 0 },
181 		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
182 			4900, 0x19, 0x04, 11,
183 			2, 2, 2, 2, 2, 2, 2, 0 },
184 		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
185 			8100, 0x18, 0x04, 22,
186 			3, 3, 2, 3, 3, 3, 3, 0 },
187 		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
188 			5400, 0x0b, 0x00, 12,
189 			4, 2, 1, 4, 4, 4, 4, 0 },
190 		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
191 			7800, 0x0f, 0x00, 18,
192 			4, 3, 1, 5, 5, 5, 5, 0 },
193 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
194 			10100, 0x0a, 0x00, 24,
195 			6, 4, 1, 6, 6, 6, 6, 0 },
196 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
197 			14100,  0x0e, 0x00, 36,
198 			6, 6, 2, 7, 7, 7, 7, 0 },
199 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
200 			17700, 0x09, 0x00, 48,
201 			8, 10, 3, 8, 8, 8, 8, 0 },
202 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
203 			23700, 0x0d, 0x00, 72,
204 			8, 14, 3, 9, 9, 9, 9, 0 },
205 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
206 			27400, 0x08, 0x00, 96,
207 			8, 20, 3, 10, 10, 10, 10, 0 },
208 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
209 			30900, 0x0c, 0x00, 108,
210 			8, 23, 3, 11, 11, 11, 11, 0 },
211 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
212 			6400, 0x80, 0x00, 0,
213 			4, 2, 3, 12, 28, 12, 28, 3216 },
214 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
215 			12700, 0x81, 0x00, 1,
216 			6, 4, 3, 13, 29, 13, 29, 6434 },
217 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
218 			18800, 0x82, 0x00, 2,
219 			6, 6, 3, 14, 30, 14, 30, 9650 },
220 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
221 			25000, 0x83, 0x00, 3,
222 			8, 10, 3, 15, 31, 15, 31, 12868 },
223 		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
224 			36700, 0x84, 0x00, 4,
225 			8, 14, 3, 16, 32, 16, 32, 19304 },
226 		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
227 			48100, 0x85, 0x00, 5,
228 			8, 20, 3, 17, 33, 17, 33, 25740 },
229 		{ INVALID,  VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
230 			53500, 0x86, 0x00, 6,
231 			8, 23, 3, 18, 34, 18, 34, 28956 },
232 		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
233 			59000, 0x87, 0x00, 7,
234 			8, 25, 3, 19, 35, 19, 36, 32180 },
235 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
236 			12700, 0x88, 0x00, 8,
237 			4, 2, 3, 20, 37, 20, 37, 6430 },
238 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
239 			24800, 0x89, 0x00, 9,
240 			6, 4, 3, 21, 38, 21, 38, 12860 },
241 		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
242 			36600, 0x8a, 0x00, 10,
243 			6, 6, 3, 22, 39, 22, 39, 19300 },
244 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
245 			48100, 0x8b, 0x00, 11,
246 			8, 10, 3, 23, 40, 23, 40, 25736 },
247 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
248 			69500, 0x8c, 0x00, 12,
249 			8, 14, 3, 24, 41, 24, 41, 38600 },
250 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
251 			89500, 0x8d, 0x00, 13,
252 			8, 20, 3, 25, 42, 25, 42, 51472 },
253 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
254 			98900, 0x8e, 0x00, 14,
255 			8, 23, 3, 26, 43, 26, 44, 57890 },
256 		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
257 			108300, 0x8f, 0x00, 15,
258 			8, 25, 3, 27, 44, 27, 45, 64320 },
259 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
260 			13200, 0x80, 0x00, 0,
261 			8, 2, 3, 12, 28, 28, 28, 6684 },
262 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
263 			25900, 0x81, 0x00, 1,
264 			8, 4, 3, 13, 29, 29, 29, 13368 },
265 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
266 			38600, 0x82, 0x00, 2,
267 			8, 6, 3, 14, 30, 30, 30, 20052 },
268 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
269 			49800, 0x83, 0x00, 3,
270 			8, 10, 3, 15, 31, 31, 31, 26738 },
271 		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
272 			72200, 0x84, 0x00, 4,
273 			8, 14, 3, 16, 32, 32, 32, 40104 },
274 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
275 			92900, 0x85, 0x00, 5,
276 			8, 20, 3, 17, 33, 33, 33, 53476 },
277 		{ INVALID,  VALID_40, WLAN_RC_PHY_HT_40_SS,
278 			121500, /* 121.5 Mb */
279 			102700, 0x86, 0x00, 6,
280 			8, 23, 3, 18, 34, 34, 34, 60156 },
281 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
282 			112000, 0x87, 0x00, 7,
283 			8, 23, 3, 19, 35, 36, 36, 66840 },
284 		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI,
285 			150000, /* 150 Mb */
286 			122000, 0x87, 0x00, 7,
287 			8, 25, 3, 19, 35, 36, 36, 74200 },
288 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
289 			25800, 0x88, 0x00, 8,
290 			8, 2, 3, 20, 37, 37, 37, 13360 },
291 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
292 			49800, 0x89, 0x00, 9,
293 			8, 4, 3, 21, 38, 38, 38, 26720 },
294 		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
295 			71900, 0x8a, 0x00, 10,
296 			8, 6, 3, 22, 39, 39, 39, 40080 },
297 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
298 			92500, 0x8b, 0x00, 11,
299 			8, 10, 3, 23, 40, 40, 40, 53440 },
300 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
301 			130300, 0x8c, 0x00, 12,
302 			8, 14, 3, 24, 41, 41, 41, 80160 },
303 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
304 			162800, 0x8d, 0x00, 13,
305 			8, 20, 3, 25, 42, 42, 42, 106880 },
306 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
307 			178200, 0x8e, 0x00, 14,
308 			8, 23, 3, 26, 43, 43, 43, 120240 },
309 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
310 			192100, 0x8f, 0x00, 15,
311 			8, 23, 3, 27, 44, 45, 45, 133600 },
312 		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI,
313 			300000, /* 300 Mb */
314 			207000, 0x8f, 0x00, 15,
315 			8, 25, 3, 27, 44, 45, 45, 148400 },
316 		},
317 	50,  /* probe interval */
318 	50,  /* rssi reduce interval */
319 	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
320 };
321 
322 static struct ath_rate_table ar5416_11a_ratetable = {
323 	8,
324 	{0},
325 	{
326 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
327 			5400, 0x0b, 0x00, (0x80|12),
328 			0, 2, 1, 0, 0 },
329 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
330 			7800, 0x0f, 0x00, 18,
331 			0, 3, 1, 1, 0 },
332 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
333 			10000, 0x0a, 0x00, (0x80|24),
334 			2, 4, 2, 2, 0 },
335 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
336 			13900, 0x0e, 0x00, 36,
337 			2, 6, 2, 3, 0 },
338 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
339 			17300, 0x09, 0x00, (0x80|48),
340 			4, 10, 3, 4, 0 },
341 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
342 			23000, 0x0d, 0x00, 72,
343 			4, 14, 3, 5, 0 },
344 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
345 			27400, 0x08, 0x00, 96,
346 			4, 19, 3, 6, 0 },
347 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
348 			29300, 0x0c, 0x00, 108,
349 			4, 23, 3, 7, 0 },
350 	},
351 	50,  /* probe interval */
352 	50,  /* rssi reduce interval */
353 	0,   /* Phy rates allowed initially */
354 };
355 
356 static struct ath_rate_table ar5416_11g_ratetable = {
357 	12,
358 	{0},
359 	{
360 		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
361 			900, 0x1b, 0x00, 2,
362 			0, 0, 1, 0, 0 },
363 		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
364 			1900, 0x1a, 0x04, 4,
365 			1, 1, 1, 1, 0 },
366 		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
367 			4900, 0x19, 0x04, 11,
368 			2, 2, 2, 2, 0 },
369 		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
370 			8100, 0x18, 0x04, 22,
371 			3, 3, 2, 3, 0 },
372 		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
373 			5400, 0x0b, 0x00, 12,
374 			4, 2, 1, 4, 0 },
375 		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
376 			7800, 0x0f, 0x00, 18,
377 			4, 3, 1, 5, 0 },
378 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
379 			10000, 0x0a, 0x00, 24,
380 			6, 4, 1, 6, 0 },
381 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
382 			13900, 0x0e, 0x00, 36,
383 			6, 6, 2, 7, 0 },
384 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
385 			17300, 0x09, 0x00, 48,
386 			8, 10, 3, 8, 0 },
387 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
388 			23000, 0x0d, 0x00, 72,
389 			8, 14, 3, 9, 0 },
390 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
391 			27400, 0x08, 0x00, 96,
392 			8, 19, 3, 10, 0 },
393 		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
394 			29300, 0x0c, 0x00, 108,
395 			8, 23, 3, 11, 0 },
396 	},
397 	50,  /* probe interval */
398 	50,  /* rssi reduce interval */
399 	0,   /* Phy rates allowed initially */
400 };
401 
402 static struct ath_rate_table ar5416_11b_ratetable = {
403 	4,
404 	{0},
405 	{
406 		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
407 			900, 0x1b,  0x00, (0x80|2),
408 			0, 0, 1, 0, 0 },
409 		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
410 			1800, 0x1a, 0x04, (0x80|4),
411 			1, 1, 1, 1, 0 },
412 		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
413 			4300, 0x19, 0x04, (0x80|11),
414 			1, 2, 2, 2, 0 },
415 		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
416 			7100, 0x18, 0x04, (0x80|22),
417 			1, 4, 100, 3, 0 },
418 	},
419 	100, /* probe interval */
420 	100, /* rssi reduce interval */
421 	0,   /* Phy rates allowed initially */
422 };
423 
424 static void
425 arn_setup_rate_table(struct arn_softc *sc,
426     struct ath_rate_table *rate_table)
427 {
428 	int i;
429 
430 	for (i = 0; i < 256; i++)
431 		rate_table->rateCodeToIndex[i] = (uint8_t)-1;
432 
433 	for (i = 0; i < rate_table->rate_cnt; i++) {
434 		uint8_t code = rate_table->info[i].ratecode;
435 		uint8_t cix = rate_table->info[i].ctrl_rate;
436 		uint8_t sh = rate_table->info[i].short_preamble;
437 
438 		rate_table->rateCodeToIndex[code] = (int)i;
439 		rate_table->rateCodeToIndex[code | sh] = (int)i;
440 
441 		rate_table->info[i].lpAckDuration =
442 		    ath9k_hw_computetxtime(sc->sc_ah, rate_table,
443 		    WLAN_CTRL_FRAME_SIZE,
444 		    cix,
445 		    B_FALSE);
446 		rate_table->info[i].spAckDuration =
447 		    ath9k_hw_computetxtime(sc->sc_ah, rate_table,
448 		    WLAN_CTRL_FRAME_SIZE,
449 		    cix,
450 		    B_TRUE);
451 	}
452 }
453 
454 void
455 arn_rate_attach(struct arn_softc *sc)
456 {
457 	sc->hw_rate_table[ATH9K_MODE_11B] =
458 	    &ar5416_11b_ratetable;
459 	sc->hw_rate_table[ATH9K_MODE_11A] =
460 	    &ar5416_11a_ratetable;
461 	sc->hw_rate_table[ATH9K_MODE_11G] =
462 	    &ar5416_11g_ratetable;
463 	sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
464 	    &ar5416_11na_ratetable;
465 	sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
466 	    &ar5416_11ng_ratetable;
467 	sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
468 	    &ar5416_11na_ratetable;
469 	sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
470 	    &ar5416_11na_ratetable;
471 	sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
472 	    &ar5416_11ng_ratetable;
473 	sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
474 	    &ar5416_11ng_ratetable;
475 
476 	arn_setup_rate_table(sc, &ar5416_11b_ratetable);
477 	arn_setup_rate_table(sc, &ar5416_11a_ratetable);
478 	arn_setup_rate_table(sc, &ar5416_11g_ratetable);
479 	arn_setup_rate_table(sc, &ar5416_11na_ratetable);
480 	arn_setup_rate_table(sc, &ar5416_11ng_ratetable);
481 }
482 
483 void
484 arn_rate_update(struct arn_softc *sc, struct ieee80211_node *in, int32_t rate)
485 {
486 	struct ath_node *an = ATH_NODE(in);
487 	const struct ath_rate_table *rt = sc->sc_currates;
488 	uint8_t rix;
489 
490 	ASSERT(rt != NULL);
491 
492 	in->in_txrate = rate;
493 
494 	/* management/control frames always go at the lowest speed */
495 	an->an_tx_mgtrate = rt->info[0].ratecode;
496 	an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].short_preamble;
497 
498 	ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_update(): "
499 	    "mgtrate=%d mgtratesp=%d\n",
500 	    an->an_tx_mgtrate, an->an_tx_mgtratesp));
501 
502 	/*
503 	 * Before associating a node has no rate set setup
504 	 * so we can't calculate any transmit codes to use.
505 	 * This is ok since we should never be sending anything
506 	 * but management frames and those always go at the
507 	 * lowest hardware rate.
508 	 */
509 	if (in->in_rates.ir_nrates == 0)
510 		goto done;
511 	an->an_tx_rix0 = sc->asc_rixmap[
512 	    in->in_rates.ir_rates[rate] & IEEE80211_RATE_VAL];
513 	an->an_tx_rate0 = rt->info[an->an_tx_rix0].ratecode;
514 	an->an_tx_rate0sp = an->an_tx_rate0 |
515 	    rt->info[an->an_tx_rix0].short_preamble;
516 	if (sc->sc_mrretry) {
517 		/*
518 		 * Hardware supports multi-rate retry; setup two
519 		 * step-down retry rates and make the lowest rate
520 		 * be the ``last chance''.  We use 4, 2, 2, 2 tries
521 		 * respectively (4 is set here, the rest are fixed
522 		 * in the xmit routine).
523 		 */
524 		an->an_tx_try0 = 1 + 3;		/* 4 tries at rate 0 */
525 		if (--rate >= 0) {
526 			rix = sc->asc_rixmap[
527 			    in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
528 			an->an_tx_rate1 = rt->info[rix].ratecode;
529 			an->an_tx_rate1sp = an->an_tx_rate1 |
530 			    rt->info[rix].short_preamble;
531 		} else {
532 			an->an_tx_rate1 = an->an_tx_rate1sp = 0;
533 		}
534 		if (--rate >= 0) {
535 			rix = sc->asc_rixmap[
536 			    in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
537 			an->an_tx_rate2 = rt->info[rix].ratecode;
538 			an->an_tx_rate2sp = an->an_tx_rate2 |
539 			    rt->info[rix].short_preamble;
540 		} else {
541 			an->an_tx_rate2 = an->an_tx_rate2sp = 0;
542 		}
543 		if (rate > 0) {
544 			an->an_tx_rate3 = rt->info[0].ratecode;
545 			an->an_tx_rate3sp =
546 			    an->an_tx_mgtrate | rt->info[0].short_preamble;
547 		} else {
548 			an->an_tx_rate3 = an->an_tx_rate3sp = 0;
549 		}
550 	} else {
551 		an->an_tx_try0 = ATH_TXMAXTRY;  /* max tries at rate 0 */
552 		an->an_tx_rate1 = an->an_tx_rate1sp = 0;
553 		an->an_tx_rate2 = an->an_tx_rate2sp = 0;
554 		an->an_tx_rate3 = an->an_tx_rate3sp = 0;
555 	}
556 done:
557 	an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
558 }
559 
560 /*
561  * Set the starting transmit rate for a node.
562  */
563 void
564 arn_rate_ctl_start(struct arn_softc *sc, struct ieee80211_node *in)
565 {
566 	ieee80211com_t *ic = (ieee80211com_t *)sc;
567 	int32_t srate;
568 
569 	if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
570 		/*
571 		 * No fixed rate is requested. For 11b start with
572 		 * the highest negotiated rate; otherwise, for 11g
573 		 * and 11a, we start "in the middle" at 24Mb or 36Mb.
574 		 */
575 		srate = in->in_rates.ir_nrates - 1;
576 		if (sc->sc_curmode != IEEE80211_MODE_11B) {
577 			/*
578 			 * Scan the negotiated rate set to find the
579 			 * closest rate.
580 			 */
581 			/* NB: the rate set is assumed sorted */
582 			for (; srate >= 0 && IEEE80211_RATE(srate) > 72;
583 			    srate--) {}
584 		}
585 	} else {
586 		/*
587 		 * A fixed rate is to be used; We know the rate is
588 		 * there because the rate set is checked when the
589 		 * station associates.
590 		 */
591 		/* NB: the rate set is assumed sorted */
592 		srate = in->in_rates.ir_nrates - 1;
593 		for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
594 		    srate--) {}
595 	}
596 
597 	ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_ctl_start(): "
598 	    "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate)));
599 
600 	arn_rate_update(sc, in, srate);
601 }
602 
603 void
604 arn_rate_cb(void *arg, struct ieee80211_node *in)
605 {
606 	arn_rate_update((struct arn_softc *)arg, in, 0);
607 }
608 
609 /*
610  * Reset the rate control state for each 802.11 state transition.
611  */
612 void
613 arn_rate_ctl_reset(struct arn_softc *sc, enum ieee80211_state state)
614 {
615 	ieee80211com_t *ic = (ieee80211com_t *)sc;
616 	struct ieee80211_node *in;
617 
618 	if (ic->ic_opmode == IEEE80211_M_STA) {
619 		/*
620 		 * Reset local xmit state; this is really only
621 		 * meaningful when operating in station mode.
622 		 */
623 		in = (struct ieee80211_node *)ic->ic_bss;
624 		if (state == IEEE80211_S_RUN) {
625 			arn_rate_ctl_start(sc, in);
626 		} else {
627 			arn_rate_update(sc, in, 0);
628 		}
629 	} else {
630 		/*
631 		 * When operating as a station the node table holds
632 		 * the AP's that were discovered during scanning.
633 		 * For any other operating mode we want to reset the
634 		 * tx rate state of each node.
635 		 */
636 		ieee80211_iterate_nodes(&ic->ic_sta, arn_rate_cb, sc);
637 		arn_rate_update(sc, ic->ic_bss, 0);
638 	}
639 }
640 
641 /*
642  * Examine and potentially adjust the transmit rate.
643  */
644 void
645 arn_rate_ctl(void *arg, struct ieee80211_node *in)
646 {
647 	struct arn_softc *sc = arg;
648 	struct ath_node *an = ATH_NODE(in);
649 	struct ieee80211_rateset *rs = &in->in_rates;
650 	int32_t mod = 0, nrate, enough;
651 
652 	/*
653 	 * Rate control(very primitive version).
654 	 */
655 	sc->sc_stats.ast_rate_calls++;
656 
657 	enough = (an->an_tx_ok + an->an_tx_err >= 10);
658 
659 	/* no packet reached -> down */
660 	if (an->an_tx_err > 0 && an->an_tx_ok == 0)
661 		mod = -1;
662 
663 	/* all packets needs retry in average -> down */
664 	if (enough && an->an_tx_ok < an->an_tx_retr)
665 		mod = -1;
666 
667 	/* no error and less than 10% of packets needs retry -> up */
668 	if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10)
669 		mod = 1;
670 
671 	nrate = in->in_txrate;
672 	switch (mod) {
673 	case 0:
674 		if (enough && an->an_tx_upper > 0)
675 			an->an_tx_upper--;
676 		break;
677 	case -1:
678 		if (nrate > 0) {
679 			nrate--;
680 			sc->sc_stats.ast_rate_drop++;
681 		}
682 		an->an_tx_upper = 0;
683 		break;
684 	case 1:
685 		if (++an->an_tx_upper < 10)
686 			break;
687 		an->an_tx_upper = 0;
688 		if (nrate + 1 < rs->ir_nrates) {
689 			nrate++;
690 			sc->sc_stats.ast_rate_raise++;
691 		}
692 		break;
693 	}
694 
695 	if (nrate != in->in_txrate) {
696 		ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_ctl(): %dM -> %dM "
697 		    "(%d ok, %d err, %d retr)\n",
698 		    (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2,
699 		    (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2,
700 		    an->an_tx_ok, an->an_tx_err, an->an_tx_retr));
701 		arn_rate_update(sc, in, nrate);
702 	} else if (enough)
703 		an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0;
704 }
705