rc.c 52 KB
Newer Older
1
2
/*
 * Copyright (c) 2004 Video54 Technologies, Inc.
3
 * Copyright (c) 2004-2009 Atheros Communications, Inc.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

Sujith's avatar
Sujith committed
18
#include "ath9k.h"
19

20
static const struct ath_rate_table ar5416_11na_ratetable = {
21
22
	42,
	{
Sujith's avatar
Sujith committed
23
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
24
25
			5400, 0x0b, 0x00, 12,
			0, 2, 1, 0, 0, 0, 0, 0 },
Sujith's avatar
Sujith committed
26
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
27
28
			7800,  0x0f, 0x00, 18,
			0, 3, 1, 1, 1, 1, 1, 0 },
Sujith's avatar
Sujith committed
29
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
30
31
			10000, 0x0a, 0x00, 24,
			2, 4, 2, 2, 2, 2, 2, 0 },
Sujith's avatar
Sujith committed
32
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
33
34
			13900, 0x0e, 0x00, 36,
			2, 6,  2, 3, 3, 3, 3, 0 },
Sujith's avatar
Sujith committed
35
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
36
37
			17300, 0x09, 0x00, 48,
			4, 10, 3, 4, 4, 4, 4, 0 },
Sujith's avatar
Sujith committed
38
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
39
40
			23000, 0x0d, 0x00, 72,
			4, 14, 3, 5, 5, 5, 5, 0 },
Sujith's avatar
Sujith committed
41
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
42
43
			27400, 0x08, 0x00, 96,
			4, 20, 3, 6, 6, 6, 6, 0 },
Sujith's avatar
Sujith committed
44
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
45
46
			29300, 0x0c, 0x00, 108,
			4, 23, 3, 7, 7, 7, 7, 0 },
Sujith's avatar
Sujith committed
47
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
48
49
			6400, 0x80, 0x00, 0,
			0, 2, 3, 8, 24, 8, 24, 3216 },
Sujith's avatar
Sujith committed
50
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
51
52
			12700, 0x81, 0x00, 1,
			2, 4, 3, 9, 25, 9, 25, 6434 },
Sujith's avatar
Sujith committed
53
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
54
55
			18800, 0x82, 0x00, 2,
			2, 6, 3, 10, 26, 10, 26, 9650 },
Sujith's avatar
Sujith committed
56
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
57
58
			25000, 0x83, 0x00, 3,
			4, 10, 3, 11, 27, 11, 27, 12868 },
Sujith's avatar
Sujith committed
59
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
60
61
			36700, 0x84, 0x00, 4,
			4, 14, 3, 12, 28, 12, 28, 19304 },
Sujith's avatar
Sujith committed
62
		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
63
64
			48100, 0x85, 0x00, 5,
			4, 20, 3, 13, 29, 13, 29, 25740 },
Sujith's avatar
Sujith committed
65
		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
66
67
			53500, 0x86, 0x00, 6,
			4, 23, 3, 14, 30, 14, 30,  28956 },
Sujith's avatar
Sujith committed
68
		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
69
70
			59000, 0x87, 0x00, 7,
			4, 25, 3, 15, 31, 15, 32, 32180 },
Sujith's avatar
Sujith committed
71
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
72
73
			12700, 0x88, 0x00,
			8, 0, 2, 3, 16, 33, 16, 33, 6430 },
Sujith's avatar
Sujith committed
74
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
75
76
			24800, 0x89, 0x00, 9,
			2, 4, 3, 17, 34, 17, 34, 12860 },
Sujith's avatar
Sujith committed
77
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
78
79
			36600, 0x8a, 0x00, 10,
			2, 6, 3, 18, 35, 18, 35, 19300 },
Sujith's avatar
Sujith committed
80
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
81
82
			48100, 0x8b, 0x00, 11,
			4, 10, 3, 19, 36, 19, 36, 25736 },
Sujith's avatar
Sujith committed
83
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
84
85
			69500, 0x8c, 0x00, 12,
			4, 14, 3, 20, 37, 20, 37, 38600 },
Sujith's avatar
Sujith committed
86
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
87
88
			89500, 0x8d, 0x00, 13,
			4, 20, 3, 21, 38, 21, 38, 51472 },
Sujith's avatar
Sujith committed
89
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
90
91
			98900, 0x8e, 0x00, 14,
			4, 23, 3, 22, 39, 22, 39, 57890 },
Sujith's avatar
Sujith committed
92
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
93
94
			108300, 0x8f, 0x00, 15,
			4, 25, 3, 23, 40, 23, 41, 64320 },
Sujith's avatar
Sujith committed
95
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
96
97
			13200, 0x80, 0x00, 0,
			0, 2, 3, 8, 24, 24, 24, 6684 },
Sujith's avatar
Sujith committed
98
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
99
100
			25900, 0x81, 0x00, 1,
			2, 4, 3, 9, 25, 25, 25, 13368 },
Sujith's avatar
Sujith committed
101
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
102
103
			38600, 0x82, 0x00, 2,
			2, 6, 3, 10, 26, 26, 26, 20052 },
Sujith's avatar
Sujith committed
104
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
105
106
			49800, 0x83, 0x00, 3,
			4, 10, 3, 11, 27, 27, 27, 26738 },
Sujith's avatar
Sujith committed
107
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
108
109
			72200, 0x84, 0x00, 4,
			4, 14, 3, 12, 28, 28, 28, 40104 },
Sujith's avatar
Sujith committed
110
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
111
112
			92900, 0x85, 0x00, 5,
			4, 20, 3, 13, 29, 29, 29, 53476 },
Sujith's avatar
Sujith committed
113
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
114
115
			102700, 0x86, 0x00, 6,
			4, 23, 3, 14, 30, 30, 30, 60156 },
Sujith's avatar
Sujith committed
116
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
117
118
			112000, 0x87, 0x00, 7,
			4, 25, 3, 15, 31, 32, 32, 66840 },
Sujith's avatar
Sujith committed
119
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
120
121
			122000, 0x87, 0x00, 7,
			4, 25, 3, 15, 31, 32, 32, 74200 },
Sujith's avatar
Sujith committed
122
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
123
124
			25800, 0x88, 0x00, 8,
			0, 2, 3, 16, 33, 33, 33, 13360 },
Sujith's avatar
Sujith committed
125
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
126
127
			49800, 0x89, 0x00, 9,
			2, 4, 3, 17, 34, 34, 34, 26720 },
Sujith's avatar
Sujith committed
128
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
129
130
			71900, 0x8a, 0x00, 10,
			2, 6, 3, 18, 35, 35, 35, 40080 },
Sujith's avatar
Sujith committed
131
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
132
133
			92500, 0x8b, 0x00, 11,
			4, 10, 3, 19, 36, 36, 36, 53440 },
Sujith's avatar
Sujith committed
134
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
135
136
			130300, 0x8c, 0x00, 12,
			4, 14, 3, 20, 37, 37, 37, 80160 },
Sujith's avatar
Sujith committed
137
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
138
139
			162800, 0x8d, 0x00, 13,
			4, 20, 3, 21, 38, 38, 38, 106880 },
Sujith's avatar
Sujith committed
140
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
141
142
			178200, 0x8e, 0x00, 14,
			4, 23, 3, 22, 39, 39, 39, 120240 },
Sujith's avatar
Sujith committed
143
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
144
145
			192100, 0x8f, 0x00, 15,
			4, 25, 3, 23, 40, 41, 41, 133600 },
Sujith's avatar
Sujith committed
146
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
147
148
149
150
151
152
153
154
155
156
157
			207000, 0x8f, 0x00, 15,
			4, 25, 3, 23, 40, 41, 41, 148400 },
	},
	50,  /* probe interval */
	50,  /* rssi reduce interval */
	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
};

/* 4ms frame limit not used for NG mode.  The values filled
 * for HT are the 64K max aggregate limit */

158
static const struct ath_rate_table ar5416_11ng_ratetable = {
159
160
	46,
	{
Sujith's avatar
Sujith committed
161
		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
162
163
			900, 0x1b, 0x00, 2,
			0, 0, 1, 0, 0, 0, 0, 0 },
Sujith's avatar
Sujith committed
164
		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
165
166
			1900, 0x1a, 0x04, 4,
			1, 1, 1, 1, 1, 1, 1, 0 },
Sujith's avatar
Sujith committed
167
		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
168
169
			4900, 0x19, 0x04, 11,
			2, 2, 2, 2, 2, 2, 2, 0 },
Sujith's avatar
Sujith committed
170
		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
171
172
			8100, 0x18, 0x04, 22,
			3, 3, 2, 3, 3, 3, 3, 0 },
Sujith's avatar
Sujith committed
173
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
174
175
			5400, 0x0b, 0x00, 12,
			4, 2, 1, 4, 4, 4, 4, 0 },
Sujith's avatar
Sujith committed
176
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
177
178
			7800, 0x0f, 0x00, 18,
			4, 3, 1, 5, 5, 5, 5, 0 },
Sujith's avatar
Sujith committed
179
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
180
181
			10100, 0x0a, 0x00, 24,
			6, 4, 1, 6, 6, 6, 6, 0 },
Sujith's avatar
Sujith committed
182
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
183
184
			14100,  0x0e, 0x00, 36,
			6, 6, 2, 7, 7, 7, 7, 0 },
Sujith's avatar
Sujith committed
185
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
186
187
			17700, 0x09, 0x00, 48,
			8, 10, 3, 8, 8, 8, 8, 0 },
Sujith's avatar
Sujith committed
188
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
189
190
			23700, 0x0d, 0x00, 72,
			8, 14, 3, 9, 9, 9, 9, 0 },
Sujith's avatar
Sujith committed
191
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
192
193
			27400, 0x08, 0x00, 96,
			8, 20, 3, 10, 10, 10, 10, 0 },
Sujith's avatar
Sujith committed
194
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
195
196
			30900, 0x0c, 0x00, 108,
			8, 23, 3, 11, 11, 11, 11, 0 },
Sujith's avatar
Sujith committed
197
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
198
199
			6400, 0x80, 0x00, 0,
			4, 2, 3, 12, 28, 12, 28, 3216 },
Sujith's avatar
Sujith committed
200
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
201
202
			12700, 0x81, 0x00, 1,
			6, 4, 3, 13, 29, 13, 29, 6434 },
Sujith's avatar
Sujith committed
203
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
204
205
			18800, 0x82, 0x00, 2,
			6, 6, 3, 14, 30, 14, 30, 9650 },
Sujith's avatar
Sujith committed
206
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
207
208
			25000, 0x83, 0x00, 3,
			8, 10, 3, 15, 31, 15, 31, 12868 },
Sujith's avatar
Sujith committed
209
		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
210
211
			36700, 0x84, 0x00, 4,
			8, 14, 3, 16, 32, 16, 32, 19304 },
Sujith's avatar
Sujith committed
212
		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
213
214
			48100, 0x85, 0x00, 5,
			8, 20, 3, 17, 33, 17, 33, 25740 },
Sujith's avatar
Sujith committed
215
		{ INVALID,  VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
216
217
			53500, 0x86, 0x00, 6,
			8, 23, 3, 18, 34, 18, 34, 28956 },
Sujith's avatar
Sujith committed
218
		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
219
220
			59000, 0x87, 0x00, 7,
			8, 25, 3, 19, 35, 19, 36, 32180 },
Sujith's avatar
Sujith committed
221
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
222
223
			12700, 0x88, 0x00, 8,
			4, 2, 3, 20, 37, 20, 37, 6430 },
Sujith's avatar
Sujith committed
224
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
225
226
			24800, 0x89, 0x00, 9,
			6, 4, 3, 21, 38, 21, 38, 12860 },
Sujith's avatar
Sujith committed
227
		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
228
229
			36600, 0x8a, 0x00, 10,
			6, 6, 3, 22, 39, 22, 39, 19300 },
Sujith's avatar
Sujith committed
230
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
231
232
			48100, 0x8b, 0x00, 11,
			8, 10, 3, 23, 40, 23, 40, 25736 },
Sujith's avatar
Sujith committed
233
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
234
235
			69500, 0x8c, 0x00, 12,
			8, 14, 3, 24, 41, 24, 41, 38600 },
Sujith's avatar
Sujith committed
236
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
237
238
			89500, 0x8d, 0x00, 13,
			8, 20, 3, 25, 42, 25, 42, 51472 },
Sujith's avatar
Sujith committed
239
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
240
241
			98900, 0x8e, 0x00, 14,
			8, 23, 3, 26, 43, 26, 44, 57890 },
Sujith's avatar
Sujith committed
242
		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
243
244
			108300, 0x8f, 0x00, 15,
			8, 25, 3, 27, 44, 27, 45, 64320 },
Sujith's avatar
Sujith committed
245
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
246
247
			13200, 0x80, 0x00, 0,
			8, 2, 3, 12, 28, 28, 28, 6684 },
Sujith's avatar
Sujith committed
248
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
249
250
			25900, 0x81, 0x00, 1,
			8, 4, 3, 13, 29, 29, 29, 13368 },
Sujith's avatar
Sujith committed
251
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
252
253
			38600, 0x82, 0x00, 2,
			8, 6, 3, 14, 30, 30, 30, 20052 },
Sujith's avatar
Sujith committed
254
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
255
256
			49800, 0x83, 0x00, 3,
			8, 10, 3, 15, 31, 31, 31, 26738 },
Sujith's avatar
Sujith committed
257
		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
258
259
			72200, 0x84, 0x00, 4,
			8, 14, 3, 16, 32, 32, 32, 40104 },
Sujith's avatar
Sujith committed
260
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
261
262
			92900, 0x85, 0x00, 5,
			8, 20, 3, 17, 33, 33, 33, 53476 },
Sujith's avatar
Sujith committed
263
		{ INVALID,  VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
264
265
			102700, 0x86, 0x00, 6,
			8, 23, 3, 18, 34, 34, 34, 60156 },
Sujith's avatar
Sujith committed
266
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
267
268
			112000, 0x87, 0x00, 7,
			8, 23, 3, 19, 35, 36, 36, 66840 },
Sujith's avatar
Sujith committed
269
		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
270
271
			122000, 0x87, 0x00, 7,
			8, 25, 3, 19, 35, 36, 36, 74200 },
Sujith's avatar
Sujith committed
272
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
273
274
			25800, 0x88, 0x00, 8,
			8, 2, 3, 20, 37, 37, 37, 13360 },
Sujith's avatar
Sujith committed
275
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
276
277
			49800, 0x89, 0x00, 9,
			8, 4, 3, 21, 38, 38, 38, 26720 },
Sujith's avatar
Sujith committed
278
		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
279
280
			71900, 0x8a, 0x00, 10,
			8, 6, 3, 22, 39, 39, 39, 40080 },
Sujith's avatar
Sujith committed
281
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
282
283
			92500, 0x8b, 0x00, 11,
			8, 10, 3, 23, 40, 40, 40, 53440 },
Sujith's avatar
Sujith committed
284
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
285
286
			130300, 0x8c, 0x00, 12,
			8, 14, 3, 24, 41, 41, 41, 80160 },
Sujith's avatar
Sujith committed
287
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
288
289
			162800, 0x8d, 0x00, 13,
			8, 20, 3, 25, 42, 42, 42, 106880 },
Sujith's avatar
Sujith committed
290
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
291
292
			178200, 0x8e, 0x00, 14,
			8, 23, 3, 26, 43, 43, 43, 120240 },
Sujith's avatar
Sujith committed
293
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
294
295
			192100, 0x8f, 0x00, 15,
			8, 23, 3, 27, 44, 45, 45, 133600 },
Sujith's avatar
Sujith committed
296
		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
297
298
299
300
301
302
303
304
			207000, 0x8f, 0x00, 15,
			8, 25, 3, 27, 44, 45, 45, 148400 },
		},
	50,  /* probe interval */
	50,  /* rssi reduce interval */
	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
};

305
static const struct ath_rate_table ar5416_11a_ratetable = {
306
307
	8,
	{
Sujith's avatar
Sujith committed
308
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
309
310
			5400, 0x0b, 0x00, (0x80|12),
			0, 2, 1, 0, 0 },
Sujith's avatar
Sujith committed
311
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
312
313
			7800, 0x0f, 0x00, 18,
			0, 3, 1, 1, 0 },
Sujith's avatar
Sujith committed
314
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
315
316
			10000, 0x0a, 0x00, (0x80|24),
			2, 4, 2, 2, 0 },
Sujith's avatar
Sujith committed
317
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
318
319
			13900, 0x0e, 0x00, 36,
			2, 6, 2, 3, 0 },
Sujith's avatar
Sujith committed
320
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
321
322
			17300, 0x09, 0x00, (0x80|48),
			4, 10, 3, 4, 0 },
Sujith's avatar
Sujith committed
323
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
324
325
			23000, 0x0d, 0x00, 72,
			4, 14, 3, 5, 0 },
Sujith's avatar
Sujith committed
326
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
327
328
			27400, 0x08, 0x00, 96,
			4, 19, 3, 6, 0 },
Sujith's avatar
Sujith committed
329
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
330
331
332
333
334
335
336
337
			29300, 0x0c, 0x00, 108,
			4, 23, 3, 7, 0 },
	},
	50,  /* probe interval */
	50,  /* rssi reduce interval */
	0,   /* Phy rates allowed initially */
};

338
static const struct ath_rate_table ar5416_11g_ratetable = {
339
340
	12,
	{
Sujith's avatar
Sujith committed
341
		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
342
343
			900, 0x1b, 0x00, 2,
			0, 0, 1, 0, 0 },
Sujith's avatar
Sujith committed
344
		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
345
346
			1900, 0x1a, 0x04, 4,
			1, 1, 1, 1, 0 },
Sujith's avatar
Sujith committed
347
		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
348
349
			4900, 0x19, 0x04, 11,
			2, 2, 2, 2, 0 },
Sujith's avatar
Sujith committed
350
		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
351
352
			8100, 0x18, 0x04, 22,
			3, 3, 2, 3, 0 },
Sujith's avatar
Sujith committed
353
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
354
355
			5400, 0x0b, 0x00, 12,
			4, 2, 1, 4, 0 },
Sujith's avatar
Sujith committed
356
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
357
358
			7800, 0x0f, 0x00, 18,
			4, 3, 1, 5, 0 },
Sujith's avatar
Sujith committed
359
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
360
361
			10000, 0x0a, 0x00, 24,
			6, 4, 1, 6, 0 },
Sujith's avatar
Sujith committed
362
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
363
364
			13900, 0x0e, 0x00, 36,
			6, 6, 2, 7, 0 },
Sujith's avatar
Sujith committed
365
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
366
367
			17300, 0x09, 0x00, 48,
			8, 10, 3, 8, 0 },
Sujith's avatar
Sujith committed
368
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
369
370
			23000, 0x0d, 0x00, 72,
			8, 14, 3, 9, 0 },
Sujith's avatar
Sujith committed
371
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
372
373
			27400, 0x08, 0x00, 96,
			8, 19, 3, 10, 0 },
Sujith's avatar
Sujith committed
374
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
375
376
377
378
379
380
381
382
			29300, 0x0c, 0x00, 108,
			8, 23, 3, 11, 0 },
	},
	50,  /* probe interval */
	50,  /* rssi reduce interval */
	0,   /* Phy rates allowed initially */
};

383
static const struct ath_rate_table ar5416_11b_ratetable = {
384
385
	4,
	{
Sujith's avatar
Sujith committed
386
		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
387
388
			900, 0x1b,  0x00, (0x80|2),
			0, 0, 1, 0, 0 },
Sujith's avatar
Sujith committed
389
		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
390
391
			1800, 0x1a, 0x04, (0x80|4),
			1, 1, 1, 1, 0 },
Sujith's avatar
Sujith committed
392
		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
393
394
			4300, 0x19, 0x04, (0x80|11),
			1, 2, 2, 2, 0 },
Sujith's avatar
Sujith committed
395
		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
			7100, 0x18, 0x04, (0x80|22),
			1, 4, 100, 3, 0 },
	},
	100, /* probe interval */
	100, /* rssi reduce interval */
	0,   /* Phy rates allowed initially */
};

static inline int8_t median(int8_t a, int8_t b, int8_t c)
{
	if (a >= b) {
		if (b >= c)
			return b;
		else if (a > c)
			return c;
		else
			return a;
	} else {
		if (a >= c)
			return a;
		else if (b >= c)
			return c;
		else
			return b;
	}
}

423
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
424
				   struct ath_rate_priv *ath_rc_priv)
425
426
427
{
	u8 i, j, idx, idx_next;

428
	for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
429
		for (j = 0; j <= i-1; j++) {
430
431
			idx = ath_rc_priv->valid_rate_index[j];
			idx_next = ath_rc_priv->valid_rate_index[j+1];
432
433
434

			if (rate_table->info[idx].ratekbps >
				rate_table->info[idx_next].ratekbps) {
435
436
				ath_rc_priv->valid_rate_index[j] = idx_next;
				ath_rc_priv->valid_rate_index[j+1] = idx;
437
438
439
440
441
			}
		}
	}
}

Sujith's avatar
Sujith committed
442
static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
443
444
445
{
	u8 i;

446
	for (i = 0; i < ath_rc_priv->rate_table_size; i++)
Sujith's avatar
Sujith committed
447
		ath_rc_priv->valid_rate_index[i] = 0;
448
449
}

Sujith's avatar
Sujith committed
450
static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
451
452
					   u8 index, int valid_tx_rate)
{
453
	ASSERT(index <= ath_rc_priv->rate_table_size);
Sujith's avatar
Sujith committed
454
	ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
455
456
}

Sujith's avatar
Sujith committed
457
static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
458
459
					u8 index)
{
460
461
	ASSERT(index <= ath_rc_priv->rate_table_size);
	return ath_rc_priv->valid_rate_index[index];
462
463
}

464
465
466
467
468
static inline
int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
				struct ath_rate_priv *ath_rc_priv,
				u8 cur_valid_txrate,
				u8 *next_idx)
469
470
471
{
	u8 i;

472
473
474
	for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
			*next_idx = ath_rc_priv->valid_rate_index[i+1];
Sujith's avatar
Sujith committed
475
			return 1;
476
477
478
479
480
		}
	}

	/* No more valid rates */
	*next_idx = 0;
Sujith's avatar
Sujith committed
481

Sujith's avatar
Sujith committed
482
	return 0;
483
484
485
486
487
488
}

/* Return true only for single stream */

static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
{
489
	if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
Sujith's avatar
Sujith committed
490
		return 0;
491
	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
Sujith's avatar
Sujith committed
492
		return 0;
493
	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
Sujith's avatar
Sujith committed
494
		return 0;
495
496
	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
		if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
Sujith's avatar
Sujith committed
497
			return 0;
498
		if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
Sujith's avatar
Sujith committed
499
500
			return 0;
	return 1;
501
502
503
}

static inline int
504
505
506
ath_rc_get_lower_rix(const struct ath_rate_table *rate_table,
		     struct ath_rate_priv *ath_rc_priv,
		     u8 cur_valid_txrate, u8 *next_idx)
507
508
509
{
	int8_t i;

510
511
512
	for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
			*next_idx = ath_rc_priv->valid_rate_index[i-1];
Sujith's avatar
Sujith committed
513
			return 1;
514
515
		}
	}
Sujith's avatar
Sujith committed
516

Sujith's avatar
Sujith committed
517
	return 0;
518
519
}

Sujith's avatar
Sujith committed
520
static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
521
				 const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
522
				 u32 capflag)
523
524
525
526
527
{
	u8 i, hi = 0;
	u32 valid;

	for (i = 0; i < rate_table->rate_cnt; i++) {
528
		valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
Sujith's avatar
Sujith committed
529
530
			 rate_table->info[i].valid_single_stream :
			 rate_table->info[i].valid);
Sujith's avatar
Sujith committed
531
		if (valid == 1) {
532
533
534
			u32 phy = rate_table->info[i].phy;
			u8 valid_rate_count = 0;

Sujith's avatar
Sujith committed
535
			if (!ath_rc_valid_phyrate(phy, capflag, 0))
536
537
				continue;

538
			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
539

540
541
			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
Sujith's avatar
Sujith committed
542
			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
543
544
545
			hi = A_MAX(hi, i);
		}
	}
Sujith's avatar
Sujith committed
546

547
548
549
	return hi;
}

Sujith's avatar
Sujith committed
550
static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
551
				const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
552
553
				struct ath_rateset *rateset,
				u32 capflag)
554
555
556
557
558
559
560
{
	u8 i, j, hi = 0;

	/* Use intersection of working rates and valid rates */
	for (i = 0; i < rateset->rs_nrates; i++) {
		for (j = 0; j < rate_table->rate_cnt; j++) {
			u32 phy = rate_table->info[j].phy;
561
562
563
			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
				     rate_table->info[j].valid_single_stream :
				     rate_table->info[j].valid);
Sujith's avatar
Sujith committed
564
565
			u8 rate = rateset->rs_rates[i];
			u8 dot11rate = rate_table->info[j].dot11rate;
566
567
568

			/* We allow a rate only if its valid and the
			 * capflag matches one of the validity
Sujith's avatar
Sujith committed
569
			 * (VALID/VALID_20/VALID_40) flags */
570

Sujith's avatar
Sujith committed
571
572
573
574
			if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
			    ((valid & WLAN_RC_CAP_MODE(capflag)) ==
			     WLAN_RC_CAP_MODE(capflag)) &&
			    !WLAN_RC_PHY_HT(phy)) {
575
576
				u8 valid_rate_count = 0;

Sujith's avatar
Sujith committed
577
				if (!ath_rc_valid_phyrate(phy, capflag, 0))
578
579
580
					continue;

				valid_rate_count =
581
					ath_rc_priv->valid_phy_ratecnt[phy];
582

583
				ath_rc_priv->valid_phy_rateidx[phy]
584
					[valid_rate_count] = j;
585
				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
Sujith's avatar
Sujith committed
586
				ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
587
588
589
590
				hi = A_MAX(hi, j);
			}
		}
	}
Sujith's avatar
Sujith committed
591

592
593
594
	return hi;
}

Sujith's avatar
Sujith committed
595
static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
596
				  const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
597
				  u8 *mcs_set, u32 capflag)
598
{
Sujith's avatar
Sujith committed
599
600
	struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;

601
602
603
	u8 i, j, hi = 0;

	/* Use intersection of working rates and valid rates */
Sujith's avatar
Sujith committed
604
	for (i = 0; i < rateset->rs_nrates; i++) {
605
606
		for (j = 0; j < rate_table->rate_cnt; j++) {
			u32 phy = rate_table->info[j].phy;
607
			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
Sujith's avatar
Sujith committed
608
609
				     rate_table->info[j].valid_single_stream :
				     rate_table->info[j].valid);
Sujith's avatar
Sujith committed
610
611
			u8 rate = rateset->rs_rates[i];
			u8 dot11rate = rate_table->info[j].dot11rate;
612

Sujith's avatar
Sujith committed
613
			if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
Sujith's avatar
Sujith committed
614
615
			    !WLAN_RC_PHY_HT(phy) ||
			    !WLAN_RC_PHY_HT_VALID(valid, capflag))
616
617
				continue;

Sujith's avatar
Sujith committed
618
			if (!ath_rc_valid_phyrate(phy, capflag, 0))
619
620
				continue;

621
622
623
			ath_rc_priv->valid_phy_rateidx[phy]
				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
Sujith's avatar
Sujith committed
624
			ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
625
626
627
628
			hi = A_MAX(hi, j);
		}
	}

Sujith's avatar
Sujith committed
629
	return hi;
630
631
632
}

static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
Sujith's avatar
Sujith committed
633
			     struct ath_rate_priv *ath_rc_priv,
634
			     const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
635
			     int *is_probing)
636
637
638
639
640
{
	u32 dt, best_thruput, this_thruput, now_msec;
	u8 rate, next_rate, best_rate, maxindex, minindex;
	int8_t  rssi_last, rssi_reduce = 0, index = 0;

Sujith's avatar
Sujith committed
641
	*is_probing = 0;
642

643
644
645
	rssi_last = median(ath_rc_priv->rssi_last,
			   ath_rc_priv->rssi_last_prev,
			   ath_rc_priv->rssi_last_prev2);
646
647
648
649
650
651
652
653
654
655
656

	/*
	 * Age (reduce) last ack rssi based on how old it is.
	 * The bizarre numbers are so the delta is 160msec,
	 * meaning we divide by 16.
	 *   0msec   <= dt <= 25msec:   don't derate
	 *   25msec  <= dt <= 185msec:  derate linearly from 0 to 10dB
	 *   185msec <= dt:             derate by 10dB
	 */

	now_msec = jiffies_to_msecs(jiffies);
657
	dt = now_msec - ath_rc_priv->rssi_time;
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

	if (dt >= 185)
		rssi_reduce = 10;
	else if (dt >= 25)
		rssi_reduce = (u8)((dt - 25) >> 4);

	/* Now reduce rssi_last by rssi_reduce */
	if (rssi_last < rssi_reduce)
		rssi_last = 0;
	else
		rssi_last -= rssi_reduce;

	/*
	 * Now look up the rate in the rssi table and return it.
	 * If no rates match then we return 0 (lowest rate)
	 */

	best_thruput = 0;
676
	maxindex = ath_rc_priv->max_valid_rate-1;
677
678
679
680
681
682
683
684
685
686
687

	minindex = 0;
	best_rate = minindex;

	/*
	 * Try the higher rate first. It will reduce memory moving time
	 * if we have very good channel characteristics.
	 */
	for (index = maxindex; index >= minindex ; index--) {
		u8 per_thres;

688
689
		rate = ath_rc_priv->valid_rate_index[index];
		if (rate > ath_rc_priv->rate_max_phy)
690
691
692
693
694
695
696
697
698
699
700
701
702
			continue;

		/*
		 * For TCP the average collision rate is around 11%,
		 * so we ignore PERs less than this.  This is to
		 * prevent the rate we are currently using (whose
		 * PER might be in the 10-15 range because of TCP
		 * collisions) looking worse than the next lower
		 * rate whose PER has decayed close to 0.  If we
		 * used to next lower rate, its PER would grow to
		 * 10-15 and we would be worse off then staying
		 * at the current rate.
		 */
703
		per_thres = ath_rc_priv->state[rate].per;
704
705
706
707
708
709
710
711
712
713
714
715
716
		if (per_thres < 12)
			per_thres = 12;

		this_thruput = rate_table->info[rate].user_ratekbps *
			(100 - per_thres);

		if (best_thruput <= this_thruput) {
			best_thruput = this_thruput;
			best_rate    = rate;
		}
	}

	rate = best_rate;
717
	ath_rc_priv->rssi_last_lookup = rssi_last;
718
719
720
721
722
723

	/*
	 * Must check the actual rate (ratekbps) to account for
	 * non-monoticity of 11g's rate table
	 */

Sujith's avatar
Sujith committed
724
	if (rate >= ath_rc_priv->rate_max_phy) {
725
		rate = ath_rc_priv->rate_max_phy;
726
727
728

		/* Probe the next allowed phy state */
		if (ath_rc_get_nextvalid_txrate(rate_table,
Sujith's avatar
Sujith committed
729
					ath_rc_priv, rate, &next_rate) &&
730
		    (now_msec - ath_rc_priv->probe_time >
731
		     rate_table->probe_interval) &&
732
		    (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
733
			rate = next_rate;
734
735
736
			ath_rc_priv->probe_rate = rate;
			ath_rc_priv->probe_time = now_msec;
			ath_rc_priv->hw_maxretry_pktcnt = 0;
Sujith's avatar
Sujith committed
737
			*is_probing = 1;
738
739
740
		}
	}

741
742
	if (rate > (ath_rc_priv->rate_table_size - 1))
		rate = ath_rc_priv->rate_table_size - 1;
743

744
745
746
747
748
749
750
751
752
753
754
755
	if (rate_table->info[rate].valid &&
	    (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
		return rate;

	if (rate_table->info[rate].valid_single_stream &&
	    !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG));
		return rate;

	/* This should not happen */
	WARN_ON(1);

	rate = ath_rc_priv->valid_rate_index[0];
756
757
758
759

	return rate;
}

760
static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
761
				   struct ieee80211_tx_rate *rate,
762
				   struct ieee80211_tx_rate_control *txrc,
Sujith's avatar
Sujith committed
763
				   u8 tries, u8 rix, int rtsctsenable)
764
{
Sujith's avatar
Sujith committed
765
766
767
	rate->count = tries;
	rate->idx = rix;

768
769
770
	if (txrc->short_preamble)
		rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
	if (txrc->rts || rtsctsenable)
Sujith's avatar
Sujith committed
771
772
773
774
775
776
777
		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
	if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
		rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
	if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
		rate->flags |= IEEE80211_TX_RC_SHORT_GI;
	if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
		rate->flags |= IEEE80211_TX_RC_MCS;
778
779
}

780
static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
781
				   const struct ath_rate_table *rate_table,
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
				   struct ieee80211_tx_info *tx_info)
{
	struct ieee80211_tx_rate *rates = tx_info->control.rates;
	int i = 0, rix = 0, cix, enable_g_protection = 0;

	/* get the cix for the lowest valid rix */
	for (i = 3; i >= 0; i--) {
		if (rates[i].count && (rates[i].idx >= 0)) {
			rix = rates[i].idx;
			break;
		}
	}
	cix = rate_table->info[rix].ctrl_rate;

	/* All protection frames are transmited at 2Mb/s for 802.11g,
	 * otherwise we transmit them at 1Mb/s */
	if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
	    !conf_is_ht(&sc->hw->conf))
		enable_g_protection = 1;

	/*
	 * If 802.11g protection is enabled, determine whether to use RTS/CTS or
	 * just CTS.  Note that this is only done for OFDM/HT unicast frames.
	 */
	if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
	    !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
	    (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
	     WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
		rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
		cix = rate_table->info[enable_g_protection].ctrl_rate;
	}

	tx_info->control.rts_cts_rate_idx = cix;
}

817
static void ath_rc_ratefind(struct ath_softc *sc,
Sujith's avatar
Sujith committed
818
			    struct ath_rate_priv *ath_rc_priv,
Sujith's avatar
Sujith committed
819
			    struct ieee80211_tx_rate_control *txrc)
820
{
821
	const struct ath_rate_table *rate_table;
Sujith's avatar
Sujith committed
822
823
	struct sk_buff *skb = txrc->skb;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujith's avatar
Sujith committed
824
	struct ieee80211_tx_rate *rates = tx_info->control.rates;
825
826
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	__le16 fc = hdr->frame_control;
827
	u8 try_per_rate, i = 0, rix, nrix;
Sujith's avatar
Sujith committed
828
	int is_probe = 0;
829

830
831
832
833
834
835
836
837
838
839
840
841
	/*
	 * For Multi Rate Retry we use a different number of
	 * retry attempt counts. This ends up looking like this:
	 *
	 * MRR[0] = 2
	 * MRR[1] = 2
	 * MRR[2] = 2
	 * MRR[3] = 4
	 *
	 */
	try_per_rate = sc->hw->max_rate_tries;

842
	rate_table = sc->cur_rate_table;
Sujith's avatar
Sujith committed
843
	rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe);
844
845
	nrix = rix;

Sujith's avatar
Sujith committed
846
	if (is_probe) {
847
848
		/* set one try for probe rates. For the
		 * probes don't enable rts */
849
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
Sujith's avatar
Sujith committed
850
				       1, nrix, 0);
851
852
853
854

		/* Get the next tried/allowed rate. No RTS for the next series
		 * after the probe rate
		 */
855
		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
856
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
Sujith's avatar
Sujith committed
857
				       try_per_rate, nrix, 0);
858
859

		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
860
861
	} else {
		/* Set the choosen rate. No RTS for first series entry. */
862
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
Sujith's avatar
Sujith committed
863
				       try_per_rate, nrix, 0);
864
865
866
	}

	/* Fill in the other rates for multirate retry */
Sujith's avatar
Sujith committed
867
	for ( ; i < 4; i++) {
868
869
870
871
		/* Use twice the number of tries for the last MRR segment. */
		if (i + 1 == 4)
			try_per_rate = 4;

872
		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
873
		/* All other rates in the series have RTS enabled */
874
		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
875
				       try_per_rate, nrix, 1);
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
	}

	/*
	 * NB:Change rate series to enable aggregation when operating
	 * at lower MCS rates. When first rate in series is MCS2
	 * in HT40 @ 2.4GHz, series should look like:
	 *
	 * {MCS2, MCS1, MCS0, MCS0}.
	 *
	 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
	 * look like:
	 *
	 * {MCS3, MCS2, MCS1, MCS1}
	 *
	 * So, set fourth rate in series to be same as third one for
	 * above conditions.
	 */
893
	if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
894
	    (conf_is_ht(&sc->hw->conf))) {
895
		u8 dot11rate = rate_table->info[rix].dot11rate;
896
897
898
		u8 phy = rate_table->info[rix].phy;
		if (i == 4 &&
		    ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
Sujith's avatar
Sujith committed
899
		     (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
Sujith's avatar
Sujith committed
900
901
			rates[3].idx = rates[2].idx;
			rates[3].flags = rates[2].flags;
902
903
		}
	}
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921

	/*
	 * Force hardware to use computed duration for next
	 * fragment by disabling multi-rate retry, which
	 * updates duration based on the multi-rate duration table.
	 *
	 * FIXME: Fix duration
	 */
	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
	    (ieee80211_has_morefrags(fc) ||
	     (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) {
		rates[1].count = rates[2].count = rates[3].count = 0;
		rates[1].idx = rates[2].idx = rates[3].idx = 0;
		rates[0].count = ATH_TXMAXTRY;
	}

	/* Setup RTS/CTS */
	ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
922
923
}

Sujith's avatar
Sujith committed
924
static bool ath_rc_update_per(struct ath_softc *sc,
925
			      const struct ath_rate_table *rate_table,
Sujith's avatar
Sujith committed
926
927