rc.c 51.2 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.
 */

S
Sujith 已提交
18
#include "ath9k.h"
19

20
static const struct ath_rate_table ar5416_11na_ratetable = {
21 22
	42,
	{
S
Sujith 已提交
23
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
24 25
			5400, 0x0b, 0x00, 12,
			0, 2, 1, 0, 0, 0, 0, 0 },
S
Sujith 已提交
26
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
27 28
			7800,  0x0f, 0x00, 18,
			0, 3, 1, 1, 1, 1, 1, 0 },
S
Sujith 已提交
29
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
30 31
			10000, 0x0a, 0x00, 24,
			2, 4, 2, 2, 2, 2, 2, 0 },
S
Sujith 已提交
32
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
33 34
			13900, 0x0e, 0x00, 36,
			2, 6,  2, 3, 3, 3, 3, 0 },
S
Sujith 已提交
35
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
36 37
			17300, 0x09, 0x00, 48,
			4, 10, 3, 4, 4, 4, 4, 0 },
S
Sujith 已提交
38
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
39 40
			23000, 0x0d, 0x00, 72,
			4, 14, 3, 5, 5, 5, 5, 0 },
S
Sujith 已提交
41
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
42 43
			27400, 0x08, 0x00, 96,
			4, 20, 3, 6, 6, 6, 6, 0 },
S
Sujith 已提交
44
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
45 46
			29300, 0x0c, 0x00, 108,
			4, 23, 3, 7, 7, 7, 7, 0 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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,
	{
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
173
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
174 175
			5400, 0x0b, 0x00, 12,
			4, 2, 1, 4, 4, 4, 4, 0 },
S
Sujith 已提交
176
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
177 178
			7800, 0x0f, 0x00, 18,
			4, 3, 1, 5, 5, 5, 5, 0 },
S
Sujith 已提交
179
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
180 181
			10100, 0x0a, 0x00, 24,
			6, 4, 1, 6, 6, 6, 6, 0 },
S
Sujith 已提交
182
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
183 184
			14100,  0x0e, 0x00, 36,
			6, 6, 2, 7, 7, 7, 7, 0 },
S
Sujith 已提交
185
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
186 187
			17700, 0x09, 0x00, 48,
			8, 10, 3, 8, 8, 8, 8, 0 },
S
Sujith 已提交
188
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
189 190
			23700, 0x0d, 0x00, 72,
			8, 14, 3, 9, 9, 9, 9, 0 },
S
Sujith 已提交
191
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
192 193
			27400, 0x08, 0x00, 96,
			8, 20, 3, 10, 10, 10, 10, 0 },
S
Sujith 已提交
194
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
195 196
			30900, 0x0c, 0x00, 108,
			8, 23, 3, 11, 11, 11, 11, 0 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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 },
S
Sujith 已提交
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,
	{
S
Sujith 已提交
308
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
309 310
			5400, 0x0b, 0x00, (0x80|12),
			0, 2, 1, 0, 0 },
S
Sujith 已提交
311
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
312 313
			7800, 0x0f, 0x00, 18,
			0, 3, 1, 1, 0 },
S
Sujith 已提交
314
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
315 316
			10000, 0x0a, 0x00, (0x80|24),
			2, 4, 2, 2, 0 },
S
Sujith 已提交
317
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
318 319
			13900, 0x0e, 0x00, 36,
			2, 6, 2, 3, 0 },
S
Sujith 已提交
320
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
321 322
			17300, 0x09, 0x00, (0x80|48),
			4, 10, 3, 4, 0 },
S
Sujith 已提交
323
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
324 325
			23000, 0x0d, 0x00, 72,
			4, 14, 3, 5, 0 },
S
Sujith 已提交
326
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
327 328
			27400, 0x08, 0x00, 96,
			4, 19, 3, 6, 0 },
S
Sujith 已提交
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,
	{
S
Sujith 已提交
341
		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
342 343
			900, 0x1b, 0x00, 2,
			0, 0, 1, 0, 0 },
S
Sujith 已提交
344
		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
345 346
			1900, 0x1a, 0x04, 4,
			1, 1, 1, 1, 0 },
S
Sujith 已提交
347
		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
348 349
			4900, 0x19, 0x04, 11,
			2, 2, 2, 2, 0 },
S
Sujith 已提交
350
		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
351 352
			8100, 0x18, 0x04, 22,
			3, 3, 2, 3, 0 },
S
Sujith 已提交
353
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
354 355
			5400, 0x0b, 0x00, 12,
			4, 2, 1, 4, 0 },
S
Sujith 已提交
356
		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
357 358
			7800, 0x0f, 0x00, 18,
			4, 3, 1, 5, 0 },
S
Sujith 已提交
359
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
360 361
			10000, 0x0a, 0x00, 24,
			6, 4, 1, 6, 0 },
S
Sujith 已提交
362
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
363 364
			13900, 0x0e, 0x00, 36,
			6, 6, 2, 7, 0 },
S
Sujith 已提交
365
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
366 367
			17300, 0x09, 0x00, 48,
			8, 10, 3, 8, 0 },
S
Sujith 已提交
368
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
369 370
			23000, 0x0d, 0x00, 72,
			8, 14, 3, 9, 0 },
S
Sujith 已提交
371
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
372 373
			27400, 0x08, 0x00, 96,
			8, 19, 3, 10, 0 },
S
Sujith 已提交
374
		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
			29300, 0x0c, 0x00, 108,
			8, 23, 3, 11, 0 },
	},
	50,  /* probe interval */
	50,  /* 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;
	}
}

402
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
S
Sujith 已提交
403
				   struct ath_rate_priv *ath_rc_priv)
404 405 406
{
	u8 i, j, idx, idx_next;

407
	for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
408
		for (j = 0; j <= i-1; j++) {
409 410
			idx = ath_rc_priv->valid_rate_index[j];
			idx_next = ath_rc_priv->valid_rate_index[j+1];
411 412 413

			if (rate_table->info[idx].ratekbps >
				rate_table->info[idx_next].ratekbps) {
414 415
				ath_rc_priv->valid_rate_index[j] = idx_next;
				ath_rc_priv->valid_rate_index[j+1] = idx;
416 417 418 419 420
			}
		}
	}
}

S
Sujith 已提交
421
static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
422 423 424
{
	u8 i;

425
	for (i = 0; i < ath_rc_priv->rate_table_size; i++)
S
Sujith 已提交
426
		ath_rc_priv->valid_rate_index[i] = 0;
427 428
}

S
Sujith 已提交
429
static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
430 431
					   u8 index, int valid_tx_rate)
{
432
	ASSERT(index <= ath_rc_priv->rate_table_size);
S
Sujith 已提交
433
	ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
434 435
}

436 437 438 439 440
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)
441 442 443
{
	u8 i;

444 445 446
	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];
S
Sujith 已提交
447
			return 1;
448 449 450 451 452
		}
	}

	/* No more valid rates */
	*next_idx = 0;
S
Sujith 已提交
453

S
Sujith 已提交
454
	return 0;
455 456 457 458 459 460
}

/* Return true only for single stream */

static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
{
461
	if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
S
Sujith 已提交
462
		return 0;
463
	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
S
Sujith 已提交
464
		return 0;
465
	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
S
Sujith 已提交
466
		return 0;
467 468
	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
		if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
S
Sujith 已提交
469
			return 0;
470
		if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
S
Sujith 已提交
471 472
			return 0;
	return 1;
473 474 475
}

static inline int
476 477 478
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)
479 480 481
{
	int8_t i;

482 483 484
	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];
S
Sujith 已提交
485
			return 1;
486 487
		}
	}
S
Sujith 已提交
488

S
Sujith 已提交
489
	return 0;
490 491
}

S
Sujith 已提交
492
static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
493
				 const struct ath_rate_table *rate_table,
S
Sujith 已提交
494
				 u32 capflag)
495 496 497 498 499
{
	u8 i, hi = 0;
	u32 valid;

	for (i = 0; i < rate_table->rate_cnt; i++) {
500
		valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
S
Sujith 已提交
501 502
			 rate_table->info[i].valid_single_stream :
			 rate_table->info[i].valid);
S
Sujith 已提交
503
		if (valid == 1) {
504 505 506
			u32 phy = rate_table->info[i].phy;
			u8 valid_rate_count = 0;

S
Sujith 已提交
507
			if (!ath_rc_valid_phyrate(phy, capflag, 0))
508 509
				continue;

510
			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
511

512 513
			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
S
Sujith 已提交
514
			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
515 516 517
			hi = A_MAX(hi, i);
		}
	}
S
Sujith 已提交
518

519 520 521
	return hi;
}

S
Sujith 已提交
522
static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
523
				const struct ath_rate_table *rate_table,
S
Sujith 已提交
524 525
				struct ath_rateset *rateset,
				u32 capflag)
526 527 528 529 530 531 532
{
	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;
533 534 535
			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
				     rate_table->info[j].valid_single_stream :
				     rate_table->info[j].valid);
S
Sujith 已提交
536 537
			u8 rate = rateset->rs_rates[i];
			u8 dot11rate = rate_table->info[j].dot11rate;
538 539 540

			/* We allow a rate only if its valid and the
			 * capflag matches one of the validity
S
Sujith 已提交
541
			 * (VALID/VALID_20/VALID_40) flags */
542

S
Sujith 已提交
543 544 545 546
			if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
			    ((valid & WLAN_RC_CAP_MODE(capflag)) ==
			     WLAN_RC_CAP_MODE(capflag)) &&
			    !WLAN_RC_PHY_HT(phy)) {
547 548
				u8 valid_rate_count = 0;

S
Sujith 已提交
549
				if (!ath_rc_valid_phyrate(phy, capflag, 0))
550 551 552
					continue;

				valid_rate_count =
553
					ath_rc_priv->valid_phy_ratecnt[phy];
554

555
				ath_rc_priv->valid_phy_rateidx[phy]
556
					[valid_rate_count] = j;
557
				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
S
Sujith 已提交
558
				ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
559 560 561 562
				hi = A_MAX(hi, j);
			}
		}
	}
S
Sujith 已提交
563

564 565 566
	return hi;
}

S
Sujith 已提交
567
static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
568
				  const struct ath_rate_table *rate_table,
S
Sujith 已提交
569
				  u8 *mcs_set, u32 capflag)
570
{
S
Sujith 已提交
571 572
	struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;

573 574 575
	u8 i, j, hi = 0;

	/* Use intersection of working rates and valid rates */
S
Sujith 已提交
576
	for (i = 0; i < rateset->rs_nrates; i++) {
577 578
		for (j = 0; j < rate_table->rate_cnt; j++) {
			u32 phy = rate_table->info[j].phy;
579
			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
S
Sujith 已提交
580 581
				     rate_table->info[j].valid_single_stream :
				     rate_table->info[j].valid);
S
Sujith 已提交
582 583
			u8 rate = rateset->rs_rates[i];
			u8 dot11rate = rate_table->info[j].dot11rate;
584

S
Sujith 已提交
585
			if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
S
Sujith 已提交
586 587
			    !WLAN_RC_PHY_HT(phy) ||
			    !WLAN_RC_PHY_HT_VALID(valid, capflag))
588 589
				continue;

S
Sujith 已提交
590
			if (!ath_rc_valid_phyrate(phy, capflag, 0))
591 592
				continue;

593 594 595
			ath_rc_priv->valid_phy_rateidx[phy]
				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
S
Sujith 已提交
596
			ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
597 598 599 600
			hi = A_MAX(hi, j);
		}
	}

S
Sujith 已提交
601
	return hi;
602 603
}

604 605 606 607 608
/* Finds the highest rate index we can use */
static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
			         struct ath_rate_priv *ath_rc_priv,
				 const struct ath_rate_table *rate_table,
				 int *is_probing)
609 610 611 612 613
{
	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;

S
Sujith 已提交
614
	*is_probing = 0;
615

616 617 618
	rssi_last = median(ath_rc_priv->rssi_last,
			   ath_rc_priv->rssi_last_prev,
			   ath_rc_priv->rssi_last_prev2);
619 620 621 622 623 624 625 626 627 628 629

	/*
	 * 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);
630
	dt = now_msec - ath_rc_priv->rssi_time;
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648

	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;
649
	maxindex = ath_rc_priv->max_valid_rate-1;
650 651 652 653 654 655 656 657 658 659 660

	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;

661 662
		rate = ath_rc_priv->valid_rate_index[index];
		if (rate > ath_rc_priv->rate_max_phy)
663 664 665 666 667 668 669 670 671 672 673 674 675
			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.
		 */
676
		per_thres = ath_rc_priv->state[rate].per;
677 678 679 680 681 682 683 684 685 686 687 688 689
		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;
690
	ath_rc_priv->rssi_last_lookup = rssi_last;
691 692 693 694 695 696

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

S
Sujith 已提交
697
	if (rate >= ath_rc_priv->rate_max_phy) {
698
		rate = ath_rc_priv->rate_max_phy;
699 700 701

		/* Probe the next allowed phy state */
		if (ath_rc_get_nextvalid_txrate(rate_table,
S
Sujith 已提交
702
					ath_rc_priv, rate, &next_rate) &&
703
		    (now_msec - ath_rc_priv->probe_time >
704
		     rate_table->probe_interval) &&
705
		    (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
706
			rate = next_rate;
707 708 709
			ath_rc_priv->probe_rate = rate;
			ath_rc_priv->probe_time = now_msec;
			ath_rc_priv->hw_maxretry_pktcnt = 0;
S
Sujith 已提交
710
			*is_probing = 1;
711 712 713
		}
	}

714 715
	if (rate > (ath_rc_priv->rate_table_size - 1))
		rate = ath_rc_priv->rate_table_size - 1;
716

717 718 719 720 721 722 723 724 725 726 727 728
	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];
729 730 731 732

	return rate;
}

733
static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
S
Sujith 已提交
734
				   struct ieee80211_tx_rate *rate,
735
				   struct ieee80211_tx_rate_control *txrc,
S
Sujith 已提交
736
				   u8 tries, u8 rix, int rtsctsenable)
737
{
S
Sujith 已提交
738 739 740
	rate->count = tries;
	rate->idx = rix;

741 742 743
	if (txrc->short_preamble)
		rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
	if (txrc->rts || rtsctsenable)
S
Sujith 已提交
744 745 746 747 748 749 750
		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;
751 752
}

753
static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
754
				   const struct ath_rate_table *rate_table,
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
				   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;
}

790
static void ath_rc_ratefind(struct ath_softc *sc,
S
Sujith 已提交
791
			    struct ath_rate_priv *ath_rc_priv,
S
Sujith 已提交
792
			    struct ieee80211_tx_rate_control *txrc)
793
{
794
	const struct ath_rate_table *rate_table;
S
Sujith 已提交
795 796
	struct sk_buff *skb = txrc->skb;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
S
Sujith 已提交
797
	struct ieee80211_tx_rate *rates = tx_info->control.rates;
798 799
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	__le16 fc = hdr->frame_control;
800
	u8 try_per_rate, i = 0, rix, nrix;
S
Sujith 已提交
801
	int is_probe = 0;
802

803 804 805 806 807 808 809 810 811 812 813 814
	/*
	 * 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;

S
Sujith 已提交
815
	rate_table = sc->cur_rate_table;
816
	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
817 818
	nrix = rix;

S
Sujith 已提交
819
	if (is_probe) {
820 821
		/* set one try for probe rates. For the
		 * probes don't enable rts */
822
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
S
Sujith 已提交
823
				       1, nrix, 0);
824 825 826 827

		/* Get the next tried/allowed rate. No RTS for the next series
		 * after the probe rate
		 */
828
		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
829
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
S
Sujith 已提交
830
				       try_per_rate, nrix, 0);
831 832

		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
833 834
	} else {
		/* Set the choosen rate. No RTS for first series entry. */
835
		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
S
Sujith 已提交
836
				       try_per_rate, nrix, 0);
837 838 839
	}

	/* Fill in the other rates for multirate retry */
S
Sujith 已提交
840
	for ( ; i < 4; i++) {
841 842 843 844
		/* Use twice the number of tries for the last MRR segment. */
		if (i + 1 == 4)
			try_per_rate = 4;

845
		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
846
		/* All other rates in the series have RTS enabled */
847
		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
848
				       try_per_rate, nrix, 1);
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
	}

	/*
	 * 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.
	 */
866
	if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
867
	    (conf_is_ht(&sc->hw->conf))) {
S
Sujith 已提交
868
		u8 dot11rate = rate_table->info[rix].dot11rate;
869 870 871
		u8 phy = rate_table->info[rix].phy;
		if (i == 4 &&
		    ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
S
Sujith 已提交
872
		     (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
S
Sujith 已提交
873 874
			rates[3].idx = rates[2].idx;
			rates[3].flags = rates[2].flags;
875 876
		}
	}
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894

	/*
	 * 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);
895 896
}

S
Sujith 已提交
897
static bool ath_rc_update_per(struct ath_softc *sc,
898
			      const struct ath_rate_table *rate_table,
S
Sujith 已提交
899 900 901 902
			      struct ath_rate_priv *ath_rc_priv,
			      struct ath_tx_info_priv *tx_info_priv,
			      int tx_rate, int xretries, int retries,
			      u32 now_msec)
903
{
S
Sujith 已提交
904 905
	bool state_change = false;
	int count;
906 907 908 909 910 911 912 913 914 915 916 917 918 919
	u8 last_per;
	static u32 nretry_to_per_lookup[10] = {
		100 * 0 / 1,
		100 * 1 / 4,
		100 * 1 / 2,
		100 * 3 / 4,
		100 * 4 / 5,
		100 * 5 / 6,
		100 * 6 / 7,
		100 * 7 / 8,
		100 * 8 / 9,
		100 * 9 / 10
	};

920
	last_per = ath_rc_priv->state[tx_rate].per;
921 922 923

	if (xretries) {
		if (xretries == 1) {
924 925 926
			ath_rc_priv->state[tx_rate].per += 30;
			if (ath_rc_priv->state[tx_rate].per > 100)
				ath_rc_priv->state[tx_rate].per = 100;
927 928
		} else {
			/* xretries == 2 */
929
			count = ARRAY_SIZE(nretry_to_per_lookup);
930 931
			if (retries >= count)
				retries = count - 1;
S
Sujith 已提交
932

933
			/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
934
			ath_rc_priv->state[tx_rate].per =
S
Sujith 已提交
935
				(u8)(last_per - (last_per >> 3) + (100 >> 3));
936 937 938 939
		}

		/* xretries == 1 or 2 */

940 941
		if (ath_rc_priv->probe_rate == tx_rate)
			ath_rc_priv->probe_rate = 0;
942

S
Sujith 已提交
943
	} else { /* xretries == 0 */
944
		count = ARRAY_SIZE(nretry_to_per_lookup);
945 946
		if (retries >= count)
			retries = count - 1;
S
Sujith 已提交
947

S
Sujith 已提交
948
		if (tx_info_priv->n_bad_frames) {
S
Sujith 已提交
949
			/* new_PER = 7/8*old_PER + 1/8*(currentPER)
950 951 952 953 954 955 956 957 958 959 960
			 * Assuming that n_frames is not 0.  The current PER
			 * from the retries is 100 * retries / (retries+1),
			 * since the first retries attempts failed, and the
			 * next one worked.  For the one that worked,
			 * n_bad_frames subframes out of n_frames wored,
			 * so the PER for that part is
			 * 100 * n_bad_frames / n_frames, and it contributes
			 * 100 * n_bad_frames / (n_frames * (retries+1)) to
			 * the above PER.  The expression below is a
			 * simplified version of the sum of these two terms.
			 */
S
Sujith 已提交
961 962 963 964 965 966 967 968 969 970 971
			if (tx_info_priv->n_frames > 0) {
				int n_frames, n_bad_frames;
				u8 cur_per, new_per;

				n_bad_frames = retries * tx_info_priv->n_frames +
					tx_info_priv->n_bad_frames;
				n_frames = tx_info_priv->n_frames * (retries + 1);
				cur_per = (100 * n_bad_frames / n_frames) >> 3;
				new_per = (u8)(last_per - (last_per >> 3) + cur_per);
				ath_rc_priv->state[tx_rate].per = new_per;
			}
972
		} else {
S
Sujith 已提交
973 974 975
			ath_rc_priv->state[tx_rate].per =
				(u8)(last_per - (last_per >> 3) +
				     (nretry_to_per_lookup[retries] >> 3));
976 977
		}

978 979
		ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
		ath_rc_priv->rssi_last_prev  = ath_rc_priv->rssi_last;
S
Sujith 已提交
980
		ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
981
		ath_rc_priv->rssi_time = now_msec;
982 983 984 985 986

		/*
		 * If we got at most one retry then increase the max rate if
		 * this was a probe.  Otherwise, ignore the probe.
		 */
987
		if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
S
Sujith 已提交
988 989
			if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
				tx_info_priv->n_frames) {
990 991 992 993 994 995 996
				/*
				 * Since we probed with just a single attempt,
				 * any retries means the probe failed.  Also,
				 * if the attempt worked, but more than half
				 * the subframes were bad then also consider
				 * the probe a failure.
				 */
997
				ath_rc_priv->probe_rate = 0;
998 999 1000
			} else {
				u8 probe_rate = 0;

S
Sujith 已提交
1001 1002
				ath_rc_priv->rate_max_phy =
					ath_rc_priv->probe_rate;
1003
				probe_rate = ath_rc_priv->probe_rate;
1004

1005 1006
				if (ath_rc_priv->state[probe_rate].per > 30)
					ath_rc_priv->state[probe_rate].per = 20;
1007

1008
				ath_rc_priv->probe_rate = 0;
1009 1010 1011 1012 1013 1014 1015

				/*
				 * Since this probe succeeded, we allow the next
				 * probe twice as soon.  This allows the maxRate
				 * to move up faster if the probes are
				 * succesful.
				 */
S
Sujith 已提交
1016 1017
				ath_rc_priv->probe_time =
					now_msec - rate_table->probe_interval / 2;
1018 1019 1020 1021 1022 1023 1024 1025 1026
			}
		}

		if (retries > 0) {
			/*
			 * Don't update anything.  We don't know if
			 * this was because of collisions or poor signal.
			 *
			 * Later: if rssi_ack is close to
1027
			 * ath_rc_priv->state[txRate].rssi_thres and we see lots
1028
			 * of retries, then we could increase
1029
			 * ath_rc_priv->state[txRate].rssi_thres.
1030
			 */
1031
			ath_rc_priv->hw_maxretry_pktcnt = 0;
1032
		} else {
S
Sujith 已提交
1033 1034 1035 1036
			int32_t rssi_ackAvg;
			int8_t rssi_thres;
			int8_t rssi_ack_vmin;

1037 1038 1039 1040
			/*
			 * It worked with no retries. First ignore bogus (small)
			 * rssi_ack values.
			 */
1041 1042 1043
			if (tx_rate == ath_rc_priv->rate_max_phy &&
			    ath_rc_priv->hw_maxretry_pktcnt < 255) {
				ath_rc_priv->hw_maxretry_pktcnt++;
1044 1045
			}

S
Sujith 已提交
1046 1047 1048
			if (tx_info_priv->tx.ts_rssi <
			    rate_table->info[tx_rate].rssi_ack_validmin)
				goto exit;
1049

S
Sujith 已提交
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
			/* Average the rssi */
			if (tx_rate != ath_rc_priv->rssi_sum_rate) {
				ath_rc_priv->rssi_sum_rate = tx_rate;
				ath_rc_priv->rssi_sum =
					ath_rc_priv->rssi_sum_cnt = 0;
			}

			ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
			ath_rc_priv->rssi_sum_cnt++;

			if (ath_rc_priv->rssi_sum_cnt < 4)
				goto exit;

			rssi_ackAvg =
				(ath_rc_priv->rssi_sum + 2) / 4;
			rssi_thres =
				ath_rc_priv->state[tx_rate].rssi_thres;
			rssi_ack_vmin =
				rate_table->info[tx_rate].rssi_ack_validmin;

			ath_rc_priv->rssi_sum =
				ath_rc_priv->rssi_sum_cnt = 0;

			/* Now reduce the current rssi threshold */
			if ((rssi_ackAvg < rssi_thres + 2) &&
			    (rssi_thres > rssi_ack_vmin)) {
				ath_rc_priv->state[tx_rate].rssi_thres--;
1077
			}
S
Sujith 已提交
1078 1079

			state_change = true;
1080 1081
		}
	}
S
Sujith 已提交
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
exit:
	return state_change;
}

/* Update PER, RSSI and whatever else that the code thinks it is doing.
   If you can make sense of all this, you really need to go out more. */

static void ath_rc_update_ht(struct ath_softc *sc,
			     struct ath_rate_priv *ath_rc_priv,
			     struct ath_tx_info_priv *tx_info_priv,
			     int tx_rate, int xretries, int retries)
{
#define CHK_RSSI(rate)					\
	((ath_rc_priv->state[(rate)].rssi_thres +	\
	  rate_table->info[(rate)].rssi_ack_deltamin) > \
	 ath_rc_priv->state[(rate)+1].rssi_thres)

	u32 now_msec = jiffies_to_msecs(jiffies);
	int rate;
	u8 last_per;
	bool state_change = false;
1103
	const struct ath_rate_table *rate_table = sc->cur_rate_table;
S
Sujith 已提交
1104 1105 1106 1107
	int size = ath_rc_priv->rate_table_size;

	if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
		return;
1108

S
Sujith 已提交
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
	/* To compensate for some imbalance between ctrl and ext. channel */

	if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
		tx_info_priv->tx.ts_rssi =
			tx_info_priv->tx.ts_rssi < 3 ? 0 :
			tx_info_priv->tx.ts_rssi - 3;

	last_per = ath_rc_priv->state[tx_rate].per;

	/* Update PER first */
	state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
					 tx_info_priv, tx_rate, xretries,
					 retries, now_msec);
1122 1123 1124 1125 1126

	/*
	 * If this rate looks bad (high PER) then stop using it for
	 * a while (except if we are probing).
	 */
1127
	if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
S
Sujith 已提交
1128
	    rate_table->info[tx_rate].ratekbps <=
1129
	    rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
1130 1131
		ath_rc_get_lower_rix(rate_table, ath_rc_priv,
				     (u8)tx_rate, &ath_rc_priv->rate_max_phy);
1132 1133

		/* Don't probe for a little while. */
1134
		ath_rc_priv->probe_time = now_msec;
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
	}

	if (state_change) {
		/*
		 * Make sure the rates above this have higher rssi thresholds.
		 * (Note:  Monotonicity is kept within the OFDM rates and
		 *         within the CCK rates. However, no adjustment is
		 *         made to keep the rssi thresholds monotonically
		 *         increasing between the CCK and OFDM rates.)
		 */
S
Sujith 已提交
1145
		for (rate = tx_rate; rate < size - 1; rate++) {
1146
			if (rate_table->info[rate+1].phy !=
S
Sujith 已提交
1147
			    rate_table->info[tx_rate].phy)
1148 1149
				break;

S
Sujith 已提交
1150
			if (CHK_RSSI(rate)) {
1151
				ath_rc_priv->state[rate+1].rssi_thres =
S
Sujith 已提交
1152 1153
					ath_rc_priv->state[rate].rssi_thres +
					rate_table->info[rate].rssi_ack_deltamin;
1154 1155 1156 1157 1158 1159
			}
		}

		/* Make sure the rates below this have lower rssi thresholds. */
		for (rate = tx_rate - 1; rate >= 0; rate--) {
			if (rate_table->info[rate].phy !=
S
Sujith 已提交
1160
			    rate_table->info[tx_rate].phy)
1161 1162
				break;

S
Sujith 已提交
1163
			if (CHK_RSSI(rate)) {
1164
				if (ath_rc_priv->state[rate+1].rssi_thres <
S
Sujith 已提交
1165
				    rate_table->info[rate].rssi_ack_deltamin)
1166
					ath_rc_priv->state[rate].rssi_thres = 0;
1167
				else {
1168
					ath_rc_priv->state[rate].rssi_thres =
S
Sujith 已提交
1169 1170
					ath_rc_priv->state[rate+1].rssi_thres -
					rate_table->info[rate].rssi_ack_deltamin;
1171 1172
				}

1173
				if (ath_rc_priv->state[rate].rssi_thres <
S
Sujith 已提交
1174
				    rate_table->info[rate].rssi_ack_validmin) {
1175
					ath_rc_priv->state[rate].rssi_thres =
S
Sujith 已提交
1176
					rate_table->info[rate].rssi_ack_validmin;
1177 1178 1179 1180 1181 1182 1183
				}
			}
		}
	}

	/* Make sure the rates below this have lower PER */
	/* Monotonicity is kept only for rates below the current rate. */
1184
	if (ath_rc_priv->state[tx_rate].per < last_per) {
1185 1186
		for (rate = tx_rate - 1; rate >= 0; rate--) {
			if (rate_table->info[rate].phy !=
S
Sujith 已提交
1187
			    rate_table->info[tx_rate].phy)
1188 1189
				break;

1190 1191 1192 1193
			if (ath_rc_priv->state[rate].per >
			    ath_rc_priv->state[rate+1].per) {
				ath_rc_priv->state[rate].per =
					ath_rc_priv->state[rate+1].per;
1194 1195 1196 1197 1198
			}
		}
	}

	/* Maintain monotonicity for rates above the current rate */
S
Sujith 已提交
1199 1200 1201
	for (rate = tx_rate; rate < size - 1; rate++) {
		if (ath_rc_priv->state[rate+1].per <
		    ath_rc_priv->state[rate].per)
1202 1203
			ath_rc_priv->state[rate+1].per =
				ath_rc_priv->state[rate].per;
1204 1205 1206 1207
	}

	/* Every so often, we reduce the thresholds and
	 * PER (different for CCK and OFDM). */
1208
	if (now_msec - ath_rc_priv->rssi_down_time >=
S
Sujith 已提交
1209
	    rate_table->rssi_reduce_interval) {
1210

S
Sujith 已提交
1211
		for (rate = 0; rate < size; rate++) {
1212
			if (ath_rc_priv->state[rate].rssi_thres >
S
Sujith 已提交
1213
			    rate_table->info[rate].rssi_ack_validmin)
1214
				ath_rc_priv->state[rate].rssi_thres -= 1;
1215
		}
1216
		ath_rc_priv->rssi_down_time = now_msec;
1217 1218 1219 1220
	}

	/* Every so often, we reduce the thresholds
	 * and PER (different for CCK and OFDM). */
1221
	if (now_msec - ath_rc_priv->per_down_time >=
S
Sujith 已提交
1222
	    rate_table->rssi_reduce_interval) {
S
Sujith 已提交
1223
		for (rate = 0; rate < size; rate++) {
1224 1225
			ath_rc_priv->state[rate].per =
				7 * ath_rc_priv->state[rate].per / 8;
1226 1227
		}

1228
		ath_rc_priv->per_down_time = now_msec;
1229
	}
S
Sujith 已提交
1230

S
Sujith 已提交
1231 1232
	ath_debug_stat_retries(sc, tx_rate, xretries, retries,
			       ath_rc_priv->state[tx_rate].per);
1233

S
Sujith 已提交
1234 1235 1236
#undef CHK_RSSI
}

1237
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
S
Sujith 已提交
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
				struct ieee80211_tx_rate *rate)
{
	int rix;

	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
		rix = rate_table->info[rate->idx].ht_index;
	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
		rix = rate_table->info[rate->idx].sgi_index;
	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
		rix = rate_table->info[rate->idx].cw40index;
	else
		rix = rate_table->info[rate->idx].base_index;

	return rix;
1253 1254
}

S
Sujith 已提交
1255 1256 1257 1258
static void ath_rc_tx_status(struct ath_softc *sc,
			     struct ath_rate_priv *ath_rc_priv,
			     struct ieee80211_tx_info *tx_info,
			     int final_ts_idx, int xretries, int long_retry)
1259
{
S
Sujith 已提交
1260
	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
1261
	const struct ath_rate_table *rate_table;
S
Sujith 已提交
1262
	struct ieee80211_tx_rate *rates = tx_info->status.rates;
1263
	u8 flags;
S
Sujith 已提交
1264
	u32 i = 0, rix;
1265

S
Sujith 已提交
1266
	rate_table = sc->cur_rate_table;
1267 1268 1269 1270 1271 1272 1273

	/*
	 * If the first rate is not the final index, there
	 * are intermediate rate failures to be processed.
	 */
	if (final_ts_idx != 0) {
		/* Process intermediate rates that failed.*/
S
Sujith 已提交
1274 1275 1276 1277
		for (i = 0; i < final_ts_idx ; i++) {
			if (rates[i].count != 0 && (rates[i].idx >= 0)) {
				flags = rates[i].flags;

1278 1279
				/* If HT40 and we have switched mode from
				 * 40 to 20 => don't update */
S
Sujith 已提交
1280

S
Sujith 已提交
1281
				if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
S
Sujith 已提交
1282
				    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
1283
					return;
S
Sujith 已提交
1284

S
Sujith 已提交
1285
				rix = ath_rc_get_rateindex(rate_table, &rates[i]);
1286
				ath_rc_update_ht(sc, ath_rc_priv,
S
Sujith 已提交
1287
						tx_info_priv, rix,
1288
						xretries ? 1 : 2,
S
Sujith 已提交
1289
						rates[i].count);
1290 1291 1292 1293 1294 1295 1296 1297 1298
			}
		}
	} else {
		/*
		 * Handle the special case of MIMO PS burst, where the second
		 * aggregate is sent out with only one rate and one try.
		 * Treating it as an excessive retry penalizes the rate
		 * inordinately.
		 */
S
Sujith 已提交
1299
		if (rates[0].count == 1 && xretries == 1)
1300 1301 1302
			xretries = 2;
	}

S
Sujith 已提交
1303 1304
	flags = rates[i].flags;

1305
	/* If HT40 and we have switched mode from 40 to 20 => don't update */
S
Sujith 已提交
1306
	if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
S
Sujith 已提交
1307
	    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
1308 1309
		return;

S
Sujith 已提交
1310
	rix = ath_rc_get_rateindex(rate_table, &rates[i]);
S
Sujith 已提交
1311
	ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
S
Sujith 已提交
1312
			 xretries, long_retry);
1313 1314
}

1315 1316 1317 1318 1319
static const
struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
					     enum ieee80211_band band,
					     bool is_ht,
					     bool is_cw_40)
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
{
	int mode = 0;

	switch(band) {
	case IEEE80211_BAND_2GHZ:
		mode = ATH9K_MODE_11G;
		if (is_ht)
			mode = ATH9K_MODE_11NG_HT20;
		if (is_cw_40)
			mode = ATH9K_MODE_11NG_HT40PLUS;
		break;
	case IEEE80211_BAND_5GHZ:
		mode = ATH9K_MODE_11A;
		if (is_ht)
			mode = ATH9K_MODE_11NA_HT20;
		if (is_cw_40)
			mode = ATH9K_MODE_11NA_HT40PLUS;
		break;
	default:
S
Sujith 已提交
1339
		DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
1340 1341 1342 1343 1344
		return NULL;
	}

	BUG_ON(mode >= ATH9K_MODE_MAX);

S
Sujith 已提交
1345
	DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
1346 1347 1348
	return sc->hw_rate_table[mode];
}

1349
static void ath_rc_init(struct ath_softc *sc,
S
Sujith 已提交
1350
			struct ath_rate_priv *ath_rc_priv,
1351
			struct ieee80211_supported_band *sband,
1352
			struct ieee80211_sta *sta,
1353
			const struct ath_rate_table *rate_table)
1354
{
1355 1356
	struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
	u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
1357 1358
	u8 i, j, k, hi = 0, hthi = 0;

1359 1360 1361 1362
	if (!rate_table) {
		DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
		return;
	}
1363

1364 1365
	/* Initial rate table size. Will change depending
	 * on the working rate set */
S
Sujith 已提交
1366
	ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
1367 1368

	/* Initialize thresholds according to the global rate table */
1369
	for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
1370
		ath_rc_priv->state[i].rssi_thres =
1371
			rate_table->info[i].rssi_ack_validmin;
1372
		ath_rc_priv->state[i].per = 0;
1373 1374 1375
	}

	/* Determine the valid rates */
1376
	ath_rc_init_valid_txmask(ath_rc_priv);
1377 1378 1379

	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
		for (j = 0; j < MAX_TX_RATE_PHY; j++)
1380 1381
			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
		ath_rc_priv->valid_phy_ratecnt[i] = 0;
1382 1383 1384 1385
	}

	if (!rateset->rs_nrates) {
		/* No working rate, just initialize valid rates */
S
Sujith 已提交
1386
		hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
1387
					    ath_rc_priv->ht_cap);
1388 1389
	} else {
		/* Use intersection of working rates and valid rates */
S
Sujith 已提交
1390
		hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
1391
					   rateset, ath_rc_priv->ht_cap);
1392
		if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
S
Sujith 已提交
1393
			hthi = ath_rc_setvalid_htrates(ath_rc_priv,
1394 1395 1396
						       rate_table,
						       ht_mcs,
						       ath_rc_priv->ht_cap);
1397 1398 1399 1400
		}
		hi = A_MAX(hi, hthi);
	}

1401 1402
	ath_rc_priv->rate_table_size = hi + 1;
	ath_rc_priv->rate_max_phy = 0;
S
Sujith 已提交
1403
	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
1404 1405

	for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
1406 1407 1408
		for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
			ath_rc_priv->valid_rate_index[k++] =
				ath_rc_priv->valid_phy_rateidx[i][j];
1409 1410
		}

S
Sujith 已提交
1411
		if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
1412
		    || !ath_rc_priv->valid_phy_ratecnt[i])
1413 1414
			continue;

1415
		ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
1416
	}
S
Sujith 已提交
1417 1418
	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
	ASSERT(k <= RATE_TABLE_SIZE);
1419

1420 1421 1422
	ath_rc_priv->max_valid_rate = k;
	ath_rc_sort_validrates(rate_table, ath_rc_priv);
	ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
S
Sujith 已提交
1423
	sc->cur_rate_table = rate_table;
1424 1425 1426

	DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
		ath_rc_priv->ht_cap);
1427 1428
}

1429 1430
static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
			       bool is_cw40, bool is_sgi40)
1431 1432 1433
{
	u8 caps = 0;

1434
	if (sta->ht_cap.ht_supported) {
1435 1436
		caps = WLAN_RC_HT_FLAG;
		if (sc->sc_ah->caps.tx_chainmask != 1 &&
1437 1438 1439 1440
		    ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) {
			if (sta->ht_cap.mcs.rx_mask[1])
				caps |= WLAN_RC_DS_FLAG;
		}
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
		if (is_cw40)
			caps |= WLAN_RC_40_FLAG;
		if (is_sgi40)
			caps |= WLAN_RC_SGI_FLAG;
	}

	return caps;
}

/***********************************/
/* mac80211 Rate Control callbacks */
/***********************************/

1454 1455
static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
			  struct ieee80211_sta *sta, void *priv_sta,
1456 1457 1458
			  struct sk_buff *skb)
{
	struct ath_softc *sc = priv;
S
Sujith 已提交
1459 1460
	struct ath_rate_priv *ath_rc_priv = priv_sta;
	struct ath_tx_info_priv *tx_info_priv = NULL;
1461 1462
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr;
S
Sujith 已提交
1463
	int final_ts_idx, tx_status = 0, is_underrun = 0;
1464 1465 1466 1467
	__le16 fc;

	hdr = (struct ieee80211_hdr *)skb->data;
	fc = hdr->frame_control;
S
Sujith 已提交
1468 1469
	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
	final_ts_idx = tx_info_priv->tx.ts_rateindex;
1470

S
Sujith 已提交
1471
	if (!priv_sta || !ieee80211_is_data(fc) ||
1472
	    !tx_info_priv->update_rc)
S
Sujith 已提交
1473
		goto exit;
1474

S
Sujith 已提交
1475 1476
	if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
		goto exit;
1477

S
Sujith 已提交
1478 1479 1480
	/*
	 * If underrun error is seen assume it as an excessive retry only
	 * if prefetch trigger level have reached the max (0x3f for 5416)
1481
	 * Adjust the long retry as if the frame was tried hw->max_rate_tries
S
Sujith 已提交
1482 1483 1484 1485
	 * times. This affects how ratectrl updates PER for the failed rate.
	 */
	if (tx_info_priv->tx.ts_flags &
	    (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
1486
	    ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
S
Sujith 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495
		tx_status = 1;
		is_underrun = 1;
	}

	if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
	    (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
		tx_status = 1;

	ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
1496
			 (is_underrun) ? sc->hw->max_rate_tries :
S
Sujith 已提交
1497 1498
			 tx_info_priv->tx.ts_longretry);

S
Sujith 已提交
1499
	/* Check if aggregation has to be enabled for this tid */
1500 1501
	if (conf_is_ht(&sc->hw->conf) &&
	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
S
Sujith 已提交
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
		if (ieee80211_is_data_qos(fc)) {
			u8 *qc, tid;
			struct ath_node *an;

			qc = ieee80211_get_qos_ctl(hdr);
			tid = qc[0] & 0xf;
			an = (struct ath_node *)sta->drv_priv;

			if(ath_tx_aggr_check(sc, an, tid))
				ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid);
		}
	}
1514 1515

	ath_debug_stat_rc(sc, skb);
S
Sujith 已提交
1516
exit:
1517
	kfree(tx_info_priv);
1518 1519
}

1520 1521
static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
			 struct ieee80211_tx_rate_control *txrc)
1522
{
1523 1524
	struct ieee80211_supported_band *sband = txrc->sband;
	struct sk_buff *skb = txrc->skb;
1525
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
S
Sujith 已提交
1526
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1527
	struct ath_softc *sc = priv;
S
Sujith 已提交
1528
	struct ath_rate_priv *ath_rc_priv = priv_sta;
1529 1530
	__le16 fc = hdr->frame_control;

1531 1532 1533
	/* lowest rate for management and NO_ACK frames */
	if (!ieee80211_is_data(fc) ||
	    tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) {
S
Sujith 已提交
1534 1535
		tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
		tx_info->control.rates[0].count =
1536 1537
			(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ?
				1 : ATH_MGT_TXMAXTRY;
1538 1539 1540 1541
		return;
	}

	/* Find tx rate for unicast frames */
S
Sujith 已提交
1542
	ath_rc_ratefind(sc, ath_rc_priv, txrc);
1543 1544
}

1545 1546
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
                          struct ieee80211_sta *sta, void *priv_sta)
1547
{
1548
	struct ath_softc *sc = priv;
S
Sujith 已提交
1549
	struct ath_rate_priv *ath_rc_priv = priv_sta;
1550
	const struct ath_rate_table *rate_table = NULL;
1551
	bool is_cw40, is_sgi40;
1552 1553
	int i, j = 0;

S
Sujith 已提交
1554 1555 1556 1557 1558 1559 1560 1561
	for (i = 0; i < sband->n_bitrates; i++) {
		if (sta->supp_rates[sband->band] & BIT(i)) {
			ath_rc_priv->neg_rates.rs_rates[j]
				= (sband->bitrates[i].bitrate * 2) / 10;
			j++;
		}
	}
	ath_rc_priv->neg_rates.rs_nrates = j;
1562

1563
	if (sta->ht_cap.ht_supported) {
S
Sujith 已提交
1564
		for (i = 0, j = 0; i < 77; i++) {
J
Johannes Berg 已提交
1565
			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
S
Sujith 已提交
1566
				ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
1567 1568 1569
			if (j == ATH_RATE_MAX)
				break;
		}
S
Sujith 已提交
1570
		ath_rc_priv->neg_ht_rates.rs_nrates = j;
1571
	}
S
Sujith 已提交
1572

1573 1574 1575 1576 1577 1578
	is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
	is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;

	/* Choose rate table first */

	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
1579
	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
1580 1581 1582 1583 1584 1585 1586 1587 1588
	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
		rate_table = ath_choose_rate_table(sc, sband->band,
						   sta->ht_cap.ht_supported,
						   is_cw40);
	} else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
		/* cur_rate_table would be set on init through config() */
		rate_table = sc->cur_rate_table;
	}

1589
	ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
1590 1591 1592 1593 1594 1595 1596 1597 1598
	ath_rc_init(sc, priv_sta, sband, sta, rate_table);
}

static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
			    struct ieee80211_sta *sta, void *priv_sta,
			    u32 changed)
{
	struct ath_softc *sc = priv;
	struct ath_rate_priv *ath_rc_priv = priv_sta;
1599
	const struct ath_rate_table *rate_table = NULL;
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
	bool oper_cw40 = false, oper_sgi40;
	bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
		true : false;
	bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
		true : false;

	/* FIXME: Handle AP mode later when we support CWM */

	if (changed & IEEE80211_RC_HT_CHANGED) {
		if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
			return;

		if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS ||
		    sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS)
			oper_cw40 = true;

		oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
			true : false;

		if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
			rate_table = ath_choose_rate_table(sc, sband->band,
						   sta->ht_cap.ht_supported,
						   oper_cw40);
1623
			ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
1624 1625 1626 1627 1628 1629 1630 1631
						   oper_cw40, oper_sgi40);
			ath_rc_init(sc, priv_sta, sband, sta, rate_table);

			DPRINTF(sc, ATH_DBG_CONFIG,
				"Operating HT Bandwidth changed to: %d\n",
				sc->hw->conf.channel_type);
		}
	}
1632 1633
}

1634
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
1635
{
1636 1637
	struct ath_wiphy *aphy = hw->priv;
	return aphy->sc;
1638 1639 1640 1641 1642 1643 1644
}

static void ath_rate_free(void *priv)
{
	return;
}

1645
static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
1646 1647
{
	struct ath_softc *sc = priv;
S
Sujith 已提交
1648
	struct ath_rate_priv *rate_priv;
1649

S
Sujith 已提交
1650
	rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
1651
	if (!rate_priv) {
S
Sujith 已提交
1652
		DPRINTF(sc, ATH_DBG_FATAL,
S
Sujith 已提交
1653
			"Unable to allocate private rc structure\n");
1654 1655
		return NULL;
	}
S
Sujith 已提交
1656 1657

	rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
1658
	rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
S
Sujith 已提交
1659

1660 1661 1662
	return rate_priv;
}

1663 1664
static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
			      void *priv_sta)
1665
{
S
Sujith 已提交
1666
	struct ath_rate_priv *rate_priv = priv_sta;
S
Sujith 已提交
1667
	kfree(rate_priv);
1668 1669 1670 1671 1672 1673 1674 1675
}

static struct rate_control_ops ath_rate_ops = {
	.module = NULL,
	.name = "ath9k_rate_control",
	.tx_status = ath_tx_status,
	.get_rate = ath_get_rate,
	.rate_init = ath_rate_init,
1676
	.rate_update = ath_rate_update,
1677 1678 1679
	.alloc = ath_rate_alloc,
	.free = ath_rate_free,
	.alloc_sta = ath_rate_alloc_sta,
1680
	.free_sta = ath_rate_free_sta,
1681 1682
};

S
Sujith 已提交
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
void ath_rate_attach(struct ath_softc *sc)
{
	sc->hw_rate_table[ATH9K_MODE_11A] =
		&ar5416_11a_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11G] =
		&ar5416_11g_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
		&ar5416_11na_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
		&ar5416_11ng_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
		&ar5416_11na_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
		&ar5416_11na_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
		&ar5416_11ng_ratetable;
	sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
		&ar5416_11ng_ratetable;
}

1703 1704 1705 1706 1707 1708 1709 1710 1711
int ath_rate_control_register(void)
{
	return ieee80211_rate_control_register(&ath_rate_ops);
}

void ath_rate_control_unregister(void)
{
	ieee80211_rate_control_unregister(&ath_rate_ops);
}