diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/rc.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/rc.c | 1495 |
1 files changed, 0 insertions, 1495 deletions
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c deleted file mode 100644 index d829bb62a3fc..000000000000 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ /dev/null | |||
@@ -1,1495 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004 Video54 Technologies, Inc. | ||
3 | * Copyright (c) 2004-2011 Atheros Communications, Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <linux/slab.h> | ||
19 | #include <linux/export.h> | ||
20 | |||
21 | #include "ath9k.h" | ||
22 | |||
23 | static const struct ath_rate_table ar5416_11na_ratetable = { | ||
24 | 68, | ||
25 | 8, /* MCS start */ | ||
26 | { | ||
27 | [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, | ||
28 | 5400, 0, 12 }, /* 6 Mb */ | ||
29 | [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, | ||
30 | 7800, 1, 18 }, /* 9 Mb */ | ||
31 | [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, | ||
32 | 10000, 2, 24 }, /* 12 Mb */ | ||
33 | [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, | ||
34 | 13900, 3, 36 }, /* 18 Mb */ | ||
35 | [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, | ||
36 | 17300, 4, 48 }, /* 24 Mb */ | ||
37 | [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, | ||
38 | 23000, 5, 72 }, /* 36 Mb */ | ||
39 | [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, | ||
40 | 27400, 6, 96 }, /* 48 Mb */ | ||
41 | [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, | ||
42 | 29300, 7, 108 }, /* 54 Mb */ | ||
43 | [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500, | ||
44 | 6400, 0, 0 }, /* 6.5 Mb */ | ||
45 | [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, | ||
46 | 12700, 1, 1 }, /* 13 Mb */ | ||
47 | [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, | ||
48 | 18800, 2, 2 }, /* 19.5 Mb */ | ||
49 | [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, | ||
50 | 25000, 3, 3 }, /* 26 Mb */ | ||
51 | [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, | ||
52 | 36700, 4, 4 }, /* 39 Mb */ | ||
53 | [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, | ||
54 | 48100, 5, 5 }, /* 52 Mb */ | ||
55 | [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, | ||
56 | 53500, 6, 6 }, /* 58.5 Mb */ | ||
57 | [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, | ||
58 | 59000, 7, 7 }, /* 65 Mb */ | ||
59 | [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, | ||
60 | 65400, 7, 7 }, /* 75 Mb */ | ||
61 | [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, | ||
62 | 12700, 8, 8 }, /* 13 Mb */ | ||
63 | [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, | ||
64 | 24800, 9, 9 }, /* 26 Mb */ | ||
65 | [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, | ||
66 | 36600, 10, 10 }, /* 39 Mb */ | ||
67 | [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, | ||
68 | 48100, 11, 11 }, /* 52 Mb */ | ||
69 | [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, | ||
70 | 69500, 12, 12 }, /* 78 Mb */ | ||
71 | [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, | ||
72 | 89500, 13, 13 }, /* 104 Mb */ | ||
73 | [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, | ||
74 | 98900, 14, 14 }, /* 117 Mb */ | ||
75 | [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, | ||
76 | 108300, 15, 15 }, /* 130 Mb */ | ||
77 | [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, | ||
78 | 120000, 15, 15 }, /* 144.4 Mb */ | ||
79 | [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, | ||
80 | 17400, 16, 16 }, /* 19.5 Mb */ | ||
81 | [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, | ||
82 | 35100, 17, 17 }, /* 39 Mb */ | ||
83 | [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, | ||
84 | 52600, 18, 18 }, /* 58.5 Mb */ | ||
85 | [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, | ||
86 | 70400, 19, 19 }, /* 78 Mb */ | ||
87 | [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, | ||
88 | 104900, 20, 20 }, /* 117 Mb */ | ||
89 | [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, | ||
90 | 115800, 20, 20 }, /* 130 Mb*/ | ||
91 | [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, | ||
92 | 137200, 21, 21 }, /* 156 Mb */ | ||
93 | [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, | ||
94 | 151100, 21, 21 }, /* 173.3 Mb */ | ||
95 | [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, | ||
96 | 152800, 22, 22 }, /* 175.5 Mb */ | ||
97 | [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, | ||
98 | 168400, 22, 22 }, /* 195 Mb*/ | ||
99 | [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, | ||
100 | 168400, 23, 23 }, /* 195 Mb */ | ||
101 | [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, | ||
102 | 185000, 23, 23 }, /* 216.7 Mb */ | ||
103 | [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, | ||
104 | 13200, 0, 0 }, /* 13.5 Mb*/ | ||
105 | [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, | ||
106 | 25900, 1, 1 }, /* 27.0 Mb*/ | ||
107 | [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, | ||
108 | 38600, 2, 2 }, /* 40.5 Mb*/ | ||
109 | [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, | ||
110 | 49800, 3, 3 }, /* 54 Mb */ | ||
111 | [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, | ||
112 | 72200, 4, 4 }, /* 81 Mb */ | ||
113 | [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000, | ||
114 | 92900, 5, 5 }, /* 108 Mb */ | ||
115 | [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, | ||
116 | 102700, 6, 6 }, /* 121.5 Mb*/ | ||
117 | [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, | ||
118 | 112000, 7, 7 }, /* 135 Mb */ | ||
119 | [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, | ||
120 | 122000, 7, 7 }, /* 150 Mb */ | ||
121 | [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, | ||
122 | 25800, 8, 8 }, /* 27 Mb */ | ||
123 | [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, | ||
124 | 49800, 9, 9 }, /* 54 Mb */ | ||
125 | [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, | ||
126 | 71900, 10, 10 }, /* 81 Mb */ | ||
127 | [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, | ||
128 | 92500, 11, 11 }, /* 108 Mb */ | ||
129 | [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, | ||
130 | 130300, 12, 12 }, /* 162 Mb */ | ||
131 | [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, | ||
132 | 162800, 13, 13 }, /* 216 Mb */ | ||
133 | [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, | ||
134 | 178200, 14, 14 }, /* 243 Mb */ | ||
135 | [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, | ||
136 | 192100, 15, 15 }, /* 270 Mb */ | ||
137 | [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, | ||
138 | 207000, 15, 15 }, /* 300 Mb */ | ||
139 | [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, | ||
140 | 36100, 16, 16 }, /* 40.5 Mb */ | ||
141 | [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, | ||
142 | 72900, 17, 17 }, /* 81 Mb */ | ||
143 | [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, | ||
144 | 108300, 18, 18 }, /* 121.5 Mb */ | ||
145 | [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, | ||
146 | 142000, 19, 19 }, /* 162 Mb */ | ||
147 | [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, | ||
148 | 205100, 20, 20 }, /* 243 Mb */ | ||
149 | [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, | ||
150 | 224700, 20, 20 }, /* 270 Mb */ | ||
151 | [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, | ||
152 | 263100, 21, 21 }, /* 324 Mb */ | ||
153 | [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, | ||
154 | 288000, 21, 21 }, /* 360 Mb */ | ||
155 | [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, | ||
156 | 290700, 22, 22 }, /* 364.5 Mb */ | ||
157 | [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, | ||
158 | 317200, 22, 22 }, /* 405 Mb */ | ||
159 | [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, | ||
160 | 317200, 23, 23 }, /* 405 Mb */ | ||
161 | [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, | ||
162 | 346400, 23, 23 }, /* 450 Mb */ | ||
163 | }, | ||
164 | 50, /* probe interval */ | ||
165 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | ||
166 | }; | ||
167 | |||
168 | /* 4ms frame limit not used for NG mode. The values filled | ||
169 | * for HT are the 64K max aggregate limit */ | ||
170 | |||
171 | static const struct ath_rate_table ar5416_11ng_ratetable = { | ||
172 | 72, | ||
173 | 12, /* MCS start */ | ||
174 | { | ||
175 | [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000, | ||
176 | 900, 0, 2 }, /* 1 Mb */ | ||
177 | [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000, | ||
178 | 1900, 1, 4 }, /* 2 Mb */ | ||
179 | [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500, | ||
180 | 4900, 2, 11 }, /* 5.5 Mb */ | ||
181 | [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000, | ||
182 | 8100, 3, 22 }, /* 11 Mb */ | ||
183 | [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, | ||
184 | 5400, 4, 12 }, /* 6 Mb */ | ||
185 | [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, | ||
186 | 7800, 5, 18 }, /* 9 Mb */ | ||
187 | [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, | ||
188 | 10100, 6, 24 }, /* 12 Mb */ | ||
189 | [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, | ||
190 | 14100, 7, 36 }, /* 18 Mb */ | ||
191 | [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, | ||
192 | 17700, 8, 48 }, /* 24 Mb */ | ||
193 | [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, | ||
194 | 23700, 9, 72 }, /* 36 Mb */ | ||
195 | [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, | ||
196 | 27400, 10, 96 }, /* 48 Mb */ | ||
197 | [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, | ||
198 | 30900, 11, 108 }, /* 54 Mb */ | ||
199 | [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500, | ||
200 | 6400, 0, 0 }, /* 6.5 Mb */ | ||
201 | [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, | ||
202 | 12700, 1, 1 }, /* 13 Mb */ | ||
203 | [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, | ||
204 | 18800, 2, 2 }, /* 19.5 Mb*/ | ||
205 | [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, | ||
206 | 25000, 3, 3 }, /* 26 Mb */ | ||
207 | [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, | ||
208 | 36700, 4, 4 }, /* 39 Mb */ | ||
209 | [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, | ||
210 | 48100, 5, 5 }, /* 52 Mb */ | ||
211 | [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, | ||
212 | 53500, 6, 6 }, /* 58.5 Mb */ | ||
213 | [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, | ||
214 | 59000, 7, 7 }, /* 65 Mb */ | ||
215 | [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, | ||
216 | 65400, 7, 7 }, /* 65 Mb*/ | ||
217 | [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, | ||
218 | 12700, 8, 8 }, /* 13 Mb */ | ||
219 | [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, | ||
220 | 24800, 9, 9 }, /* 26 Mb */ | ||
221 | [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, | ||
222 | 36600, 10, 10 }, /* 39 Mb */ | ||
223 | [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, | ||
224 | 48100, 11, 11 }, /* 52 Mb */ | ||
225 | [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, | ||
226 | 69500, 12, 12 }, /* 78 Mb */ | ||
227 | [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, | ||
228 | 89500, 13, 13 }, /* 104 Mb */ | ||
229 | [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, | ||
230 | 98900, 14, 14 }, /* 117 Mb */ | ||
231 | [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, | ||
232 | 108300, 15, 15 }, /* 130 Mb */ | ||
233 | [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, | ||
234 | 120000, 15, 15 }, /* 144.4 Mb */ | ||
235 | [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, | ||
236 | 17400, 16, 16 }, /* 19.5 Mb */ | ||
237 | [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, | ||
238 | 35100, 17, 17 }, /* 39 Mb */ | ||
239 | [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, | ||
240 | 52600, 18, 18 }, /* 58.5 Mb */ | ||
241 | [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, | ||
242 | 70400, 19, 19 }, /* 78 Mb */ | ||
243 | [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, | ||
244 | 104900, 20, 20 }, /* 117 Mb */ | ||
245 | [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, | ||
246 | 115800, 20, 20 }, /* 130 Mb */ | ||
247 | [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, | ||
248 | 137200, 21, 21 }, /* 156 Mb */ | ||
249 | [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, | ||
250 | 151100, 21, 21 }, /* 173.3 Mb */ | ||
251 | [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, | ||
252 | 152800, 22, 22 }, /* 175.5 Mb */ | ||
253 | [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, | ||
254 | 168400, 22, 22 }, /* 195 Mb */ | ||
255 | [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, | ||
256 | 168400, 23, 23 }, /* 195 Mb */ | ||
257 | [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, | ||
258 | 185000, 23, 23 }, /* 216.7 Mb */ | ||
259 | [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, | ||
260 | 13200, 0, 0 }, /* 13.5 Mb */ | ||
261 | [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, | ||
262 | 25900, 1, 1 }, /* 27.0 Mb */ | ||
263 | [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, | ||
264 | 38600, 2, 2 }, /* 40.5 Mb */ | ||
265 | [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, | ||
266 | 49800, 3, 3 }, /* 54 Mb */ | ||
267 | [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, | ||
268 | 72200, 4, 4 }, /* 81 Mb */ | ||
269 | [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000, | ||
270 | 92900, 5, 5 }, /* 108 Mb */ | ||
271 | [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, | ||
272 | 102700, 6, 6 }, /* 121.5 Mb */ | ||
273 | [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, | ||
274 | 112000, 7, 7 }, /* 135 Mb */ | ||
275 | [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, | ||
276 | 122000, 7, 7 }, /* 150 Mb */ | ||
277 | [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, | ||
278 | 25800, 8, 8 }, /* 27 Mb */ | ||
279 | [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, | ||
280 | 49800, 9, 9 }, /* 54 Mb */ | ||
281 | [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, | ||
282 | 71900, 10, 10 }, /* 81 Mb */ | ||
283 | [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, | ||
284 | 92500, 11, 11 }, /* 108 Mb */ | ||
285 | [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, | ||
286 | 130300, 12, 12 }, /* 162 Mb */ | ||
287 | [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, | ||
288 | 162800, 13, 13 }, /* 216 Mb */ | ||
289 | [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, | ||
290 | 178200, 14, 14 }, /* 243 Mb */ | ||
291 | [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, | ||
292 | 192100, 15, 15 }, /* 270 Mb */ | ||
293 | [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, | ||
294 | 207000, 15, 15 }, /* 300 Mb */ | ||
295 | [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, | ||
296 | 36100, 16, 16 }, /* 40.5 Mb */ | ||
297 | [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, | ||
298 | 72900, 17, 17 }, /* 81 Mb */ | ||
299 | [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, | ||
300 | 108300, 18, 18 }, /* 121.5 Mb */ | ||
301 | [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, | ||
302 | 142000, 19, 19 }, /* 162 Mb */ | ||
303 | [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, | ||
304 | 205100, 20, 20 }, /* 243 Mb */ | ||
305 | [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, | ||
306 | 224700, 20, 20 }, /* 270 Mb */ | ||
307 | [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, | ||
308 | 263100, 21, 21 }, /* 324 Mb */ | ||
309 | [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, | ||
310 | 288000, 21, 21 }, /* 360 Mb */ | ||
311 | [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, | ||
312 | 290700, 22, 22 }, /* 364.5 Mb */ | ||
313 | [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, | ||
314 | 317200, 22, 22 }, /* 405 Mb */ | ||
315 | [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, | ||
316 | 317200, 23, 23 }, /* 405 Mb */ | ||
317 | [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, | ||
318 | 346400, 23, 23 }, /* 450 Mb */ | ||
319 | }, | ||
320 | 50, /* probe interval */ | ||
321 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | ||
322 | }; | ||
323 | |||
324 | static const struct ath_rate_table ar5416_11a_ratetable = { | ||
325 | 8, | ||
326 | 0, | ||
327 | { | ||
328 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | ||
329 | 5400, 0, 12}, | ||
330 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | ||
331 | 7800, 1, 18}, | ||
332 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | ||
333 | 10000, 2, 24}, | ||
334 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | ||
335 | 13900, 3, 36}, | ||
336 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | ||
337 | 17300, 4, 48}, | ||
338 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | ||
339 | 23000, 5, 72}, | ||
340 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | ||
341 | 27400, 6, 96}, | ||
342 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | ||
343 | 29300, 7, 108}, | ||
344 | }, | ||
345 | 50, /* probe interval */ | ||
346 | 0, /* Phy rates allowed initially */ | ||
347 | }; | ||
348 | |||
349 | static const struct ath_rate_table ar5416_11g_ratetable = { | ||
350 | 12, | ||
351 | 0, | ||
352 | { | ||
353 | { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ | ||
354 | 900, 0, 2}, | ||
355 | { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ | ||
356 | 1900, 1, 4}, | ||
357 | { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ | ||
358 | 4900, 2, 11}, | ||
359 | { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ | ||
360 | 8100, 3, 22}, | ||
361 | { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | ||
362 | 5400, 4, 12}, | ||
363 | { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | ||
364 | 7800, 5, 18}, | ||
365 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | ||
366 | 10000, 6, 24}, | ||
367 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | ||
368 | 13900, 7, 36}, | ||
369 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | ||
370 | 17300, 8, 48}, | ||
371 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | ||
372 | 23000, 9, 72}, | ||
373 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | ||
374 | 27400, 10, 96}, | ||
375 | { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | ||
376 | 29300, 11, 108}, | ||
377 | }, | ||
378 | 50, /* probe interval */ | ||
379 | 0, /* Phy rates allowed initially */ | ||
380 | }; | ||
381 | |||
382 | static int ath_rc_get_rateindex(struct ath_rate_priv *ath_rc_priv, | ||
383 | struct ieee80211_tx_rate *rate) | ||
384 | { | ||
385 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
386 | int rix, i, idx = 0; | ||
387 | |||
388 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) | ||
389 | return rate->idx; | ||
390 | |||
391 | for (i = 0; i < ath_rc_priv->max_valid_rate; i++) { | ||
392 | idx = ath_rc_priv->valid_rate_index[i]; | ||
393 | |||
394 | if (WLAN_RC_PHY_HT(rate_table->info[idx].phy) && | ||
395 | rate_table->info[idx].ratecode == rate->idx) | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | rix = idx; | ||
400 | |||
401 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
402 | rix++; | ||
403 | |||
404 | return rix; | ||
405 | } | ||
406 | |||
407 | static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv) | ||
408 | { | ||
409 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
410 | u8 i, j, idx, idx_next; | ||
411 | |||
412 | for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { | ||
413 | for (j = 0; j <= i-1; j++) { | ||
414 | idx = ath_rc_priv->valid_rate_index[j]; | ||
415 | idx_next = ath_rc_priv->valid_rate_index[j+1]; | ||
416 | |||
417 | if (rate_table->info[idx].ratekbps > | ||
418 | rate_table->info[idx_next].ratekbps) { | ||
419 | ath_rc_priv->valid_rate_index[j] = idx_next; | ||
420 | ath_rc_priv->valid_rate_index[j+1] = idx; | ||
421 | } | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | |||
426 | static inline | ||
427 | int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | ||
428 | struct ath_rate_priv *ath_rc_priv, | ||
429 | u8 cur_valid_txrate, | ||
430 | u8 *next_idx) | ||
431 | { | ||
432 | u8 i; | ||
433 | |||
434 | for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { | ||
435 | if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { | ||
436 | *next_idx = ath_rc_priv->valid_rate_index[i+1]; | ||
437 | return 1; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | /* No more valid rates */ | ||
442 | *next_idx = 0; | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | /* Return true only for single stream */ | ||
448 | |||
449 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | ||
450 | { | ||
451 | if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) | ||
452 | return 0; | ||
453 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) | ||
454 | return 0; | ||
455 | if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG)) | ||
456 | return 0; | ||
457 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) | ||
458 | return 0; | ||
459 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) | ||
460 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) | ||
461 | return 0; | ||
462 | return 1; | ||
463 | } | ||
464 | |||
465 | static inline int | ||
466 | ath_rc_get_lower_rix(struct ath_rate_priv *ath_rc_priv, | ||
467 | u8 cur_valid_txrate, u8 *next_idx) | ||
468 | { | ||
469 | int8_t i; | ||
470 | |||
471 | for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { | ||
472 | if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { | ||
473 | *next_idx = ath_rc_priv->valid_rate_index[i-1]; | ||
474 | return 1; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv) | ||
482 | { | ||
483 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
484 | u8 i, hi = 0; | ||
485 | |||
486 | for (i = 0; i < rate_table->rate_cnt; i++) { | ||
487 | if (rate_table->info[i].rate_flags & RC_LEGACY) { | ||
488 | u32 phy = rate_table->info[i].phy; | ||
489 | u8 valid_rate_count = 0; | ||
490 | |||
491 | if (!ath_rc_valid_phyrate(phy, ath_rc_priv->ht_cap, 0)) | ||
492 | continue; | ||
493 | |||
494 | valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; | ||
495 | |||
496 | ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; | ||
497 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; | ||
498 | ath_rc_priv->valid_rate_index[i] = true; | ||
499 | hi = i; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | return hi; | ||
504 | } | ||
505 | |||
506 | static inline bool ath_rc_check_legacy(u8 rate, u8 dot11rate, u16 rate_flags, | ||
507 | u32 phy, u32 capflag) | ||
508 | { | ||
509 | if (rate != dot11rate || WLAN_RC_PHY_HT(phy)) | ||
510 | return false; | ||
511 | |||
512 | if ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != WLAN_RC_CAP_MODE(capflag)) | ||
513 | return false; | ||
514 | |||
515 | if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) | ||
516 | return false; | ||
517 | |||
518 | return true; | ||
519 | } | ||
520 | |||
521 | static inline bool ath_rc_check_ht(u8 rate, u8 dot11rate, u16 rate_flags, | ||
522 | u32 phy, u32 capflag) | ||
523 | { | ||
524 | if (rate != dot11rate || !WLAN_RC_PHY_HT(phy)) | ||
525 | return false; | ||
526 | |||
527 | if (!WLAN_RC_PHY_HT_VALID(rate_flags, capflag)) | ||
528 | return false; | ||
529 | |||
530 | if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) | ||
531 | return false; | ||
532 | |||
533 | return true; | ||
534 | } | ||
535 | |||
536 | static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, bool legacy) | ||
537 | { | ||
538 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
539 | struct ath_rateset *rateset; | ||
540 | u32 phy, capflag = ath_rc_priv->ht_cap; | ||
541 | u16 rate_flags; | ||
542 | u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; | ||
543 | |||
544 | if (legacy) | ||
545 | rateset = &ath_rc_priv->neg_rates; | ||
546 | else | ||
547 | rateset = &ath_rc_priv->neg_ht_rates; | ||
548 | |||
549 | for (i = 0; i < rateset->rs_nrates; i++) { | ||
550 | for (j = 0; j < rate_table->rate_cnt; j++) { | ||
551 | phy = rate_table->info[j].phy; | ||
552 | rate_flags = rate_table->info[j].rate_flags; | ||
553 | rate = rateset->rs_rates[i]; | ||
554 | dot11rate = rate_table->info[j].dot11rate; | ||
555 | |||
556 | if (legacy && | ||
557 | !ath_rc_check_legacy(rate, dot11rate, | ||
558 | rate_flags, phy, capflag)) | ||
559 | continue; | ||
560 | |||
561 | if (!legacy && | ||
562 | !ath_rc_check_ht(rate, dot11rate, | ||
563 | rate_flags, phy, capflag)) | ||
564 | continue; | ||
565 | |||
566 | if (!ath_rc_valid_phyrate(phy, capflag, 0)) | ||
567 | continue; | ||
568 | |||
569 | valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; | ||
570 | ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; | ||
571 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; | ||
572 | ath_rc_priv->valid_rate_index[j] = true; | ||
573 | hi = max(hi, j); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | return hi; | ||
578 | } | ||
579 | |||
580 | static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv, | ||
581 | int *is_probing) | ||
582 | { | ||
583 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
584 | u32 best_thruput, this_thruput, now_msec; | ||
585 | u8 rate, next_rate, best_rate, maxindex, minindex; | ||
586 | int8_t index = 0; | ||
587 | |||
588 | now_msec = jiffies_to_msecs(jiffies); | ||
589 | *is_probing = 0; | ||
590 | best_thruput = 0; | ||
591 | maxindex = ath_rc_priv->max_valid_rate-1; | ||
592 | minindex = 0; | ||
593 | best_rate = minindex; | ||
594 | |||
595 | /* | ||
596 | * Try the higher rate first. It will reduce memory moving time | ||
597 | * if we have very good channel characteristics. | ||
598 | */ | ||
599 | for (index = maxindex; index >= minindex ; index--) { | ||
600 | u8 per_thres; | ||
601 | |||
602 | rate = ath_rc_priv->valid_rate_index[index]; | ||
603 | if (rate > ath_rc_priv->rate_max_phy) | ||
604 | continue; | ||
605 | |||
606 | /* | ||
607 | * For TCP the average collision rate is around 11%, | ||
608 | * so we ignore PERs less than this. This is to | ||
609 | * prevent the rate we are currently using (whose | ||
610 | * PER might be in the 10-15 range because of TCP | ||
611 | * collisions) looking worse than the next lower | ||
612 | * rate whose PER has decayed close to 0. If we | ||
613 | * used to next lower rate, its PER would grow to | ||
614 | * 10-15 and we would be worse off then staying | ||
615 | * at the current rate. | ||
616 | */ | ||
617 | per_thres = ath_rc_priv->per[rate]; | ||
618 | if (per_thres < 12) | ||
619 | per_thres = 12; | ||
620 | |||
621 | this_thruput = rate_table->info[rate].user_ratekbps * | ||
622 | (100 - per_thres); | ||
623 | |||
624 | if (best_thruput <= this_thruput) { | ||
625 | best_thruput = this_thruput; | ||
626 | best_rate = rate; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | rate = best_rate; | ||
631 | |||
632 | /* | ||
633 | * Must check the actual rate (ratekbps) to account for | ||
634 | * non-monoticity of 11g's rate table | ||
635 | */ | ||
636 | |||
637 | if (rate >= ath_rc_priv->rate_max_phy) { | ||
638 | rate = ath_rc_priv->rate_max_phy; | ||
639 | |||
640 | /* Probe the next allowed phy state */ | ||
641 | if (ath_rc_get_nextvalid_txrate(rate_table, | ||
642 | ath_rc_priv, rate, &next_rate) && | ||
643 | (now_msec - ath_rc_priv->probe_time > | ||
644 | rate_table->probe_interval) && | ||
645 | (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { | ||
646 | rate = next_rate; | ||
647 | ath_rc_priv->probe_rate = rate; | ||
648 | ath_rc_priv->probe_time = now_msec; | ||
649 | ath_rc_priv->hw_maxretry_pktcnt = 0; | ||
650 | *is_probing = 1; | ||
651 | } | ||
652 | } | ||
653 | |||
654 | if (rate > (ath_rc_priv->rate_table_size - 1)) | ||
655 | rate = ath_rc_priv->rate_table_size - 1; | ||
656 | |||
657 | if (RC_TS_ONLY(rate_table->info[rate].rate_flags) && | ||
658 | (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG)) | ||
659 | return rate; | ||
660 | |||
661 | if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) && | ||
662 | (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG))) | ||
663 | return rate; | ||
664 | |||
665 | if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags)) | ||
666 | return rate; | ||
667 | |||
668 | /* This should not happen */ | ||
669 | WARN_ON_ONCE(1); | ||
670 | |||
671 | rate = ath_rc_priv->valid_rate_index[0]; | ||
672 | |||
673 | return rate; | ||
674 | } | ||
675 | |||
676 | static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, | ||
677 | struct ieee80211_tx_rate *rate, | ||
678 | struct ieee80211_tx_rate_control *txrc, | ||
679 | u8 tries, u8 rix, int rtsctsenable) | ||
680 | { | ||
681 | rate->count = tries; | ||
682 | rate->idx = rate_table->info[rix].ratecode; | ||
683 | |||
684 | if (txrc->rts || rtsctsenable) | ||
685 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; | ||
686 | |||
687 | if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) { | ||
688 | rate->flags |= IEEE80211_TX_RC_MCS; | ||
689 | if (WLAN_RC_PHY_40(rate_table->info[rix].phy) && | ||
690 | conf_is_ht40(&txrc->hw->conf)) | ||
691 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
692 | if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) | ||
693 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | static void ath_rc_rate_set_rtscts(struct ath_softc *sc, | ||
698 | const struct ath_rate_table *rate_table, | ||
699 | struct ieee80211_tx_info *tx_info) | ||
700 | { | ||
701 | struct ieee80211_bss_conf *bss_conf; | ||
702 | |||
703 | if (!tx_info->control.vif) | ||
704 | return; | ||
705 | /* | ||
706 | * For legacy frames, mac80211 takes care of CTS protection. | ||
707 | */ | ||
708 | if (!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
709 | return; | ||
710 | |||
711 | bss_conf = &tx_info->control.vif->bss_conf; | ||
712 | |||
713 | if (!bss_conf->basic_rates) | ||
714 | return; | ||
715 | |||
716 | /* | ||
717 | * For now, use the lowest allowed basic rate for HT frames. | ||
718 | */ | ||
719 | tx_info->control.rts_cts_rate_idx = __ffs(bss_conf->basic_rates); | ||
720 | } | ||
721 | |||
722 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | ||
723 | struct ieee80211_tx_rate_control *txrc) | ||
724 | { | ||
725 | struct ath_softc *sc = priv; | ||
726 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
727 | const struct ath_rate_table *rate_table; | ||
728 | struct sk_buff *skb = txrc->skb; | ||
729 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
730 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | ||
731 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
732 | __le16 fc = hdr->frame_control; | ||
733 | u8 try_per_rate, i = 0, rix; | ||
734 | int is_probe = 0; | ||
735 | |||
736 | if (rate_control_send_low(sta, priv_sta, txrc)) | ||
737 | return; | ||
738 | |||
739 | /* | ||
740 | * For Multi Rate Retry we use a different number of | ||
741 | * retry attempt counts. This ends up looking like this: | ||
742 | * | ||
743 | * MRR[0] = 4 | ||
744 | * MRR[1] = 4 | ||
745 | * MRR[2] = 4 | ||
746 | * MRR[3] = 8 | ||
747 | * | ||
748 | */ | ||
749 | try_per_rate = 4; | ||
750 | |||
751 | rate_table = ath_rc_priv->rate_table; | ||
752 | rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe); | ||
753 | |||
754 | if (conf_is_ht(&sc->hw->conf) && | ||
755 | (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) | ||
756 | tx_info->flags |= IEEE80211_TX_CTL_LDPC; | ||
757 | |||
758 | if (conf_is_ht(&sc->hw->conf) && | ||
759 | (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) | ||
760 | tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT); | ||
761 | |||
762 | if (is_probe) { | ||
763 | /* | ||
764 | * Set one try for probe rates. For the | ||
765 | * probes don't enable RTS. | ||
766 | */ | ||
767 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | ||
768 | 1, rix, 0); | ||
769 | /* | ||
770 | * Get the next tried/allowed rate. | ||
771 | * No RTS for the next series after the probe rate. | ||
772 | */ | ||
773 | ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); | ||
774 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | ||
775 | try_per_rate, rix, 0); | ||
776 | |||
777 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
778 | } else { | ||
779 | /* | ||
780 | * Set the chosen rate. No RTS for first series entry. | ||
781 | */ | ||
782 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | ||
783 | try_per_rate, rix, 0); | ||
784 | } | ||
785 | |||
786 | for ( ; i < 4; i++) { | ||
787 | /* | ||
788 | * Use twice the number of tries for the last MRR segment. | ||
789 | */ | ||
790 | if (i + 1 == 4) | ||
791 | try_per_rate = 8; | ||
792 | |||
793 | ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); | ||
794 | |||
795 | /* | ||
796 | * All other rates in the series have RTS enabled. | ||
797 | */ | ||
798 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, | ||
799 | try_per_rate, rix, 1); | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * NB:Change rate series to enable aggregation when operating | ||
804 | * at lower MCS rates. When first rate in series is MCS2 | ||
805 | * in HT40 @ 2.4GHz, series should look like: | ||
806 | * | ||
807 | * {MCS2, MCS1, MCS0, MCS0}. | ||
808 | * | ||
809 | * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should | ||
810 | * look like: | ||
811 | * | ||
812 | * {MCS3, MCS2, MCS1, MCS1} | ||
813 | * | ||
814 | * So, set fourth rate in series to be same as third one for | ||
815 | * above conditions. | ||
816 | */ | ||
817 | if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) && | ||
818 | (conf_is_ht(&sc->hw->conf))) { | ||
819 | u8 dot11rate = rate_table->info[rix].dot11rate; | ||
820 | u8 phy = rate_table->info[rix].phy; | ||
821 | if (i == 4 && | ||
822 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || | ||
823 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { | ||
824 | rates[3].idx = rates[2].idx; | ||
825 | rates[3].flags = rates[2].flags; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * Force hardware to use computed duration for next | ||
831 | * fragment by disabling multi-rate retry, which | ||
832 | * updates duration based on the multi-rate duration table. | ||
833 | * | ||
834 | * FIXME: Fix duration | ||
835 | */ | ||
836 | if (ieee80211_has_morefrags(fc) || | ||
837 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { | ||
838 | rates[1].count = rates[2].count = rates[3].count = 0; | ||
839 | rates[1].idx = rates[2].idx = rates[3].idx = 0; | ||
840 | rates[0].count = ATH_TXMAXTRY; | ||
841 | } | ||
842 | |||
843 | ath_rc_rate_set_rtscts(sc, rate_table, tx_info); | ||
844 | } | ||
845 | |||
846 | static void ath_rc_update_per(struct ath_softc *sc, | ||
847 | const struct ath_rate_table *rate_table, | ||
848 | struct ath_rate_priv *ath_rc_priv, | ||
849 | struct ieee80211_tx_info *tx_info, | ||
850 | int tx_rate, int xretries, int retries, | ||
851 | u32 now_msec) | ||
852 | { | ||
853 | int count, n_bad_frames; | ||
854 | u8 last_per; | ||
855 | static const u32 nretry_to_per_lookup[10] = { | ||
856 | 100 * 0 / 1, | ||
857 | 100 * 1 / 4, | ||
858 | 100 * 1 / 2, | ||
859 | 100 * 3 / 4, | ||
860 | 100 * 4 / 5, | ||
861 | 100 * 5 / 6, | ||
862 | 100 * 6 / 7, | ||
863 | 100 * 7 / 8, | ||
864 | 100 * 8 / 9, | ||
865 | 100 * 9 / 10 | ||
866 | }; | ||
867 | |||
868 | last_per = ath_rc_priv->per[tx_rate]; | ||
869 | n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len; | ||
870 | |||
871 | if (xretries) { | ||
872 | if (xretries == 1) { | ||
873 | ath_rc_priv->per[tx_rate] += 30; | ||
874 | if (ath_rc_priv->per[tx_rate] > 100) | ||
875 | ath_rc_priv->per[tx_rate] = 100; | ||
876 | } else { | ||
877 | /* xretries == 2 */ | ||
878 | count = ARRAY_SIZE(nretry_to_per_lookup); | ||
879 | if (retries >= count) | ||
880 | retries = count - 1; | ||
881 | |||
882 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | ||
883 | ath_rc_priv->per[tx_rate] = | ||
884 | (u8)(last_per - (last_per >> 3) + (100 >> 3)); | ||
885 | } | ||
886 | |||
887 | /* xretries == 1 or 2 */ | ||
888 | |||
889 | if (ath_rc_priv->probe_rate == tx_rate) | ||
890 | ath_rc_priv->probe_rate = 0; | ||
891 | |||
892 | } else { /* xretries == 0 */ | ||
893 | count = ARRAY_SIZE(nretry_to_per_lookup); | ||
894 | if (retries >= count) | ||
895 | retries = count - 1; | ||
896 | |||
897 | if (n_bad_frames) { | ||
898 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) | ||
899 | * Assuming that n_frames is not 0. The current PER | ||
900 | * from the retries is 100 * retries / (retries+1), | ||
901 | * since the first retries attempts failed, and the | ||
902 | * next one worked. For the one that worked, | ||
903 | * n_bad_frames subframes out of n_frames wored, | ||
904 | * so the PER for that part is | ||
905 | * 100 * n_bad_frames / n_frames, and it contributes | ||
906 | * 100 * n_bad_frames / (n_frames * (retries+1)) to | ||
907 | * the above PER. The expression below is a | ||
908 | * simplified version of the sum of these two terms. | ||
909 | */ | ||
910 | if (tx_info->status.ampdu_len > 0) { | ||
911 | int n_frames, n_bad_tries; | ||
912 | u8 cur_per, new_per; | ||
913 | |||
914 | n_bad_tries = retries * tx_info->status.ampdu_len + | ||
915 | n_bad_frames; | ||
916 | n_frames = tx_info->status.ampdu_len * (retries + 1); | ||
917 | cur_per = (100 * n_bad_tries / n_frames) >> 3; | ||
918 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); | ||
919 | ath_rc_priv->per[tx_rate] = new_per; | ||
920 | } | ||
921 | } else { | ||
922 | ath_rc_priv->per[tx_rate] = | ||
923 | (u8)(last_per - (last_per >> 3) + | ||
924 | (nretry_to_per_lookup[retries] >> 3)); | ||
925 | } | ||
926 | |||
927 | |||
928 | /* | ||
929 | * If we got at most one retry then increase the max rate if | ||
930 | * this was a probe. Otherwise, ignore the probe. | ||
931 | */ | ||
932 | if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { | ||
933 | if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) { | ||
934 | /* | ||
935 | * Since we probed with just a single attempt, | ||
936 | * any retries means the probe failed. Also, | ||
937 | * if the attempt worked, but more than half | ||
938 | * the subframes were bad then also consider | ||
939 | * the probe a failure. | ||
940 | */ | ||
941 | ath_rc_priv->probe_rate = 0; | ||
942 | } else { | ||
943 | u8 probe_rate = 0; | ||
944 | |||
945 | ath_rc_priv->rate_max_phy = | ||
946 | ath_rc_priv->probe_rate; | ||
947 | probe_rate = ath_rc_priv->probe_rate; | ||
948 | |||
949 | if (ath_rc_priv->per[probe_rate] > 30) | ||
950 | ath_rc_priv->per[probe_rate] = 20; | ||
951 | |||
952 | ath_rc_priv->probe_rate = 0; | ||
953 | |||
954 | /* | ||
955 | * Since this probe succeeded, we allow the next | ||
956 | * probe twice as soon. This allows the maxRate | ||
957 | * to move up faster if the probes are | ||
958 | * successful. | ||
959 | */ | ||
960 | ath_rc_priv->probe_time = | ||
961 | now_msec - rate_table->probe_interval / 2; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | if (retries > 0) { | ||
966 | /* | ||
967 | * Don't update anything. We don't know if | ||
968 | * this was because of collisions or poor signal. | ||
969 | */ | ||
970 | ath_rc_priv->hw_maxretry_pktcnt = 0; | ||
971 | } else { | ||
972 | /* | ||
973 | * It worked with no retries. First ignore bogus (small) | ||
974 | * rssi_ack values. | ||
975 | */ | ||
976 | if (tx_rate == ath_rc_priv->rate_max_phy && | ||
977 | ath_rc_priv->hw_maxretry_pktcnt < 255) { | ||
978 | ath_rc_priv->hw_maxretry_pktcnt++; | ||
979 | } | ||
980 | |||
981 | } | ||
982 | } | ||
983 | } | ||
984 | |||
985 | static void ath_rc_update_ht(struct ath_softc *sc, | ||
986 | struct ath_rate_priv *ath_rc_priv, | ||
987 | struct ieee80211_tx_info *tx_info, | ||
988 | int tx_rate, int xretries, int retries) | ||
989 | { | ||
990 | u32 now_msec = jiffies_to_msecs(jiffies); | ||
991 | int rate; | ||
992 | u8 last_per; | ||
993 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
994 | int size = ath_rc_priv->rate_table_size; | ||
995 | |||
996 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) | ||
997 | return; | ||
998 | |||
999 | last_per = ath_rc_priv->per[tx_rate]; | ||
1000 | |||
1001 | /* Update PER first */ | ||
1002 | ath_rc_update_per(sc, rate_table, ath_rc_priv, | ||
1003 | tx_info, tx_rate, xretries, | ||
1004 | retries, now_msec); | ||
1005 | |||
1006 | /* | ||
1007 | * If this rate looks bad (high PER) then stop using it for | ||
1008 | * a while (except if we are probing). | ||
1009 | */ | ||
1010 | if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && | ||
1011 | rate_table->info[tx_rate].ratekbps <= | ||
1012 | rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { | ||
1013 | ath_rc_get_lower_rix(ath_rc_priv, (u8)tx_rate, | ||
1014 | &ath_rc_priv->rate_max_phy); | ||
1015 | |||
1016 | /* Don't probe for a little while. */ | ||
1017 | ath_rc_priv->probe_time = now_msec; | ||
1018 | } | ||
1019 | |||
1020 | /* Make sure the rates below this have lower PER */ | ||
1021 | /* Monotonicity is kept only for rates below the current rate. */ | ||
1022 | if (ath_rc_priv->per[tx_rate] < last_per) { | ||
1023 | for (rate = tx_rate - 1; rate >= 0; rate--) { | ||
1024 | |||
1025 | if (ath_rc_priv->per[rate] > | ||
1026 | ath_rc_priv->per[rate+1]) { | ||
1027 | ath_rc_priv->per[rate] = | ||
1028 | ath_rc_priv->per[rate+1]; | ||
1029 | } | ||
1030 | } | ||
1031 | } | ||
1032 | |||
1033 | /* Maintain monotonicity for rates above the current rate */ | ||
1034 | for (rate = tx_rate; rate < size - 1; rate++) { | ||
1035 | if (ath_rc_priv->per[rate+1] < | ||
1036 | ath_rc_priv->per[rate]) | ||
1037 | ath_rc_priv->per[rate+1] = | ||
1038 | ath_rc_priv->per[rate]; | ||
1039 | } | ||
1040 | |||
1041 | /* Every so often, we reduce the thresholds | ||
1042 | * and PER (different for CCK and OFDM). */ | ||
1043 | if (now_msec - ath_rc_priv->per_down_time >= | ||
1044 | rate_table->probe_interval) { | ||
1045 | for (rate = 0; rate < size; rate++) { | ||
1046 | ath_rc_priv->per[rate] = | ||
1047 | 7 * ath_rc_priv->per[rate] / 8; | ||
1048 | } | ||
1049 | |||
1050 | ath_rc_priv->per_down_time = now_msec; | ||
1051 | } | ||
1052 | |||
1053 | ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries, | ||
1054 | ath_rc_priv->per[tx_rate]); | ||
1055 | |||
1056 | } | ||
1057 | |||
1058 | static void ath_rc_tx_status(struct ath_softc *sc, | ||
1059 | struct ath_rate_priv *ath_rc_priv, | ||
1060 | struct sk_buff *skb) | ||
1061 | { | ||
1062 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1063 | struct ieee80211_tx_rate *rates = tx_info->status.rates; | ||
1064 | struct ieee80211_tx_rate *rate; | ||
1065 | int final_ts_idx = 0, xretries = 0, long_retry = 0; | ||
1066 | u8 flags; | ||
1067 | u32 i = 0, rix; | ||
1068 | |||
1069 | for (i = 0; i < sc->hw->max_rates; i++) { | ||
1070 | rate = &tx_info->status.rates[i]; | ||
1071 | if (rate->idx < 0 || !rate->count) | ||
1072 | break; | ||
1073 | |||
1074 | final_ts_idx = i; | ||
1075 | long_retry = rate->count - 1; | ||
1076 | } | ||
1077 | |||
1078 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) | ||
1079 | xretries = 1; | ||
1080 | |||
1081 | /* | ||
1082 | * If the first rate is not the final index, there | ||
1083 | * are intermediate rate failures to be processed. | ||
1084 | */ | ||
1085 | if (final_ts_idx != 0) { | ||
1086 | for (i = 0; i < final_ts_idx ; i++) { | ||
1087 | if (rates[i].count != 0 && (rates[i].idx >= 0)) { | ||
1088 | flags = rates[i].flags; | ||
1089 | |||
1090 | /* If HT40 and we have switched mode from | ||
1091 | * 40 to 20 => don't update */ | ||
1092 | |||
1093 | if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && | ||
1094 | !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) | ||
1095 | return; | ||
1096 | |||
1097 | rix = ath_rc_get_rateindex(ath_rc_priv, &rates[i]); | ||
1098 | ath_rc_update_ht(sc, ath_rc_priv, tx_info, | ||
1099 | rix, xretries ? 1 : 2, | ||
1100 | rates[i].count); | ||
1101 | } | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | flags = rates[final_ts_idx].flags; | ||
1106 | |||
1107 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ | ||
1108 | if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && | ||
1109 | !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) | ||
1110 | return; | ||
1111 | |||
1112 | rix = ath_rc_get_rateindex(ath_rc_priv, &rates[final_ts_idx]); | ||
1113 | ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry); | ||
1114 | ath_debug_stat_rc(ath_rc_priv, rix); | ||
1115 | } | ||
1116 | |||
1117 | static const | ||
1118 | struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, | ||
1119 | enum ieee80211_band band, | ||
1120 | bool is_ht) | ||
1121 | { | ||
1122 | switch(band) { | ||
1123 | case IEEE80211_BAND_2GHZ: | ||
1124 | if (is_ht) | ||
1125 | return &ar5416_11ng_ratetable; | ||
1126 | return &ar5416_11g_ratetable; | ||
1127 | case IEEE80211_BAND_5GHZ: | ||
1128 | if (is_ht) | ||
1129 | return &ar5416_11na_ratetable; | ||
1130 | return &ar5416_11a_ratetable; | ||
1131 | default: | ||
1132 | return NULL; | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1136 | static void ath_rc_init(struct ath_softc *sc, | ||
1137 | struct ath_rate_priv *ath_rc_priv) | ||
1138 | { | ||
1139 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; | ||
1140 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; | ||
1141 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1142 | u8 i, j, k, hi = 0, hthi = 0; | ||
1143 | |||
1144 | ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; | ||
1145 | |||
1146 | for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { | ||
1147 | ath_rc_priv->per[i] = 0; | ||
1148 | ath_rc_priv->valid_rate_index[i] = 0; | ||
1149 | } | ||
1150 | |||
1151 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { | ||
1152 | for (j = 0; j < RATE_TABLE_SIZE; j++) | ||
1153 | ath_rc_priv->valid_phy_rateidx[i][j] = 0; | ||
1154 | ath_rc_priv->valid_phy_ratecnt[i] = 0; | ||
1155 | } | ||
1156 | |||
1157 | if (!rateset->rs_nrates) { | ||
1158 | hi = ath_rc_init_validrates(ath_rc_priv); | ||
1159 | } else { | ||
1160 | hi = ath_rc_setvalid_rates(ath_rc_priv, true); | ||
1161 | |||
1162 | if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) | ||
1163 | hthi = ath_rc_setvalid_rates(ath_rc_priv, false); | ||
1164 | |||
1165 | hi = max(hi, hthi); | ||
1166 | } | ||
1167 | |||
1168 | ath_rc_priv->rate_table_size = hi + 1; | ||
1169 | ath_rc_priv->rate_max_phy = 0; | ||
1170 | WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); | ||
1171 | |||
1172 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { | ||
1173 | for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { | ||
1174 | ath_rc_priv->valid_rate_index[k++] = | ||
1175 | ath_rc_priv->valid_phy_rateidx[i][j]; | ||
1176 | } | ||
1177 | |||
1178 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) || | ||
1179 | !ath_rc_priv->valid_phy_ratecnt[i]) | ||
1180 | continue; | ||
1181 | |||
1182 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; | ||
1183 | } | ||
1184 | WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); | ||
1185 | WARN_ON(k > RATE_TABLE_SIZE); | ||
1186 | |||
1187 | ath_rc_priv->max_valid_rate = k; | ||
1188 | ath_rc_sort_validrates(ath_rc_priv); | ||
1189 | ath_rc_priv->rate_max_phy = (k > 4) ? | ||
1190 | ath_rc_priv->valid_rate_index[k-4] : | ||
1191 | ath_rc_priv->valid_rate_index[k-1]; | ||
1192 | |||
1193 | ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n", | ||
1194 | ath_rc_priv->ht_cap); | ||
1195 | } | ||
1196 | |||
1197 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta) | ||
1198 | { | ||
1199 | u8 caps = 0; | ||
1200 | |||
1201 | if (sta->ht_cap.ht_supported) { | ||
1202 | caps = WLAN_RC_HT_FLAG; | ||
1203 | if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2]) | ||
1204 | caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; | ||
1205 | else if (sta->ht_cap.mcs.rx_mask[1]) | ||
1206 | caps |= WLAN_RC_DS_FLAG; | ||
1207 | if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) { | ||
1208 | caps |= WLAN_RC_40_FLAG; | ||
1209 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) | ||
1210 | caps |= WLAN_RC_SGI_FLAG; | ||
1211 | } else { | ||
1212 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) | ||
1213 | caps |= WLAN_RC_SGI_FLAG; | ||
1214 | } | ||
1215 | } | ||
1216 | |||
1217 | return caps; | ||
1218 | } | ||
1219 | |||
1220 | static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta, | ||
1221 | u8 tidno) | ||
1222 | { | ||
1223 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1224 | struct ath_atx_tid *txtid; | ||
1225 | |||
1226 | if (!sta->ht_cap.ht_supported) | ||
1227 | return false; | ||
1228 | |||
1229 | txtid = ATH_AN_2_TID(an, tidno); | ||
1230 | return !txtid->active; | ||
1231 | } | ||
1232 | |||
1233 | |||
1234 | /***********************************/ | ||
1235 | /* mac80211 Rate Control callbacks */ | ||
1236 | /***********************************/ | ||
1237 | |||
1238 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | ||
1239 | struct ieee80211_sta *sta, void *priv_sta, | ||
1240 | struct sk_buff *skb) | ||
1241 | { | ||
1242 | struct ath_softc *sc = priv; | ||
1243 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
1244 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1245 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1246 | __le16 fc = hdr->frame_control; | ||
1247 | |||
1248 | if (!priv_sta || !ieee80211_is_data(fc)) | ||
1249 | return; | ||
1250 | |||
1251 | /* This packet was aggregated but doesn't carry status info */ | ||
1252 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1253 | !(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1254 | return; | ||
1255 | |||
1256 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) | ||
1257 | return; | ||
1258 | |||
1259 | ath_rc_tx_status(sc, ath_rc_priv, skb); | ||
1260 | |||
1261 | /* Check if aggregation has to be enabled for this tid */ | ||
1262 | if (conf_is_ht(&sc->hw->conf) && | ||
1263 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
1264 | if (ieee80211_is_data_qos(fc) && | ||
1265 | skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { | ||
1266 | u8 *qc, tid; | ||
1267 | |||
1268 | qc = ieee80211_get_qos_ctl(hdr); | ||
1269 | tid = qc[0] & 0xf; | ||
1270 | |||
1271 | if(ath_tx_aggr_check(sc, sta, tid)) | ||
1272 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
1273 | } | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | ||
1278 | struct cfg80211_chan_def *chandef, | ||
1279 | struct ieee80211_sta *sta, void *priv_sta) | ||
1280 | { | ||
1281 | struct ath_softc *sc = priv; | ||
1282 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1283 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
1284 | int i, j = 0; | ||
1285 | u32 rate_flags = ieee80211_chandef_rate_flags(&sc->hw->conf.chandef); | ||
1286 | |||
1287 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1288 | if (sta->supp_rates[sband->band] & BIT(i)) { | ||
1289 | if ((rate_flags & sband->bitrates[i].flags) | ||
1290 | != rate_flags) | ||
1291 | continue; | ||
1292 | |||
1293 | ath_rc_priv->neg_rates.rs_rates[j] | ||
1294 | = (sband->bitrates[i].bitrate * 2) / 10; | ||
1295 | j++; | ||
1296 | } | ||
1297 | } | ||
1298 | ath_rc_priv->neg_rates.rs_nrates = j; | ||
1299 | |||
1300 | if (sta->ht_cap.ht_supported) { | ||
1301 | for (i = 0, j = 0; i < 77; i++) { | ||
1302 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) | ||
1303 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; | ||
1304 | if (j == ATH_RATE_MAX) | ||
1305 | break; | ||
1306 | } | ||
1307 | ath_rc_priv->neg_ht_rates.rs_nrates = j; | ||
1308 | } | ||
1309 | |||
1310 | ath_rc_priv->rate_table = ath_choose_rate_table(sc, sband->band, | ||
1311 | sta->ht_cap.ht_supported); | ||
1312 | if (!ath_rc_priv->rate_table) { | ||
1313 | ath_err(common, "No rate table chosen\n"); | ||
1314 | return; | ||
1315 | } | ||
1316 | |||
1317 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); | ||
1318 | ath_rc_init(sc, priv_sta); | ||
1319 | } | ||
1320 | |||
1321 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | ||
1322 | struct cfg80211_chan_def *chandef, | ||
1323 | struct ieee80211_sta *sta, void *priv_sta, | ||
1324 | u32 changed) | ||
1325 | { | ||
1326 | struct ath_softc *sc = priv; | ||
1327 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
1328 | |||
1329 | if (changed & IEEE80211_RC_BW_CHANGED) { | ||
1330 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); | ||
1331 | ath_rc_init(sc, priv_sta); | ||
1332 | |||
1333 | ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, | ||
1334 | "Operating Bandwidth changed to: %d\n", | ||
1335 | sc->hw->conf.chandef.width); | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1339 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | ||
1340 | |||
1341 | void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) | ||
1342 | { | ||
1343 | struct ath_rc_stats *stats; | ||
1344 | |||
1345 | stats = &rc->rcstats[final_rate]; | ||
1346 | stats->success++; | ||
1347 | } | ||
1348 | |||
1349 | void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, | ||
1350 | int xretries, int retries, u8 per) | ||
1351 | { | ||
1352 | struct ath_rc_stats *stats = &rc->rcstats[rix]; | ||
1353 | |||
1354 | stats->xretries += xretries; | ||
1355 | stats->retries += retries; | ||
1356 | stats->per = per; | ||
1357 | } | ||
1358 | |||
1359 | static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | ||
1360 | size_t count, loff_t *ppos) | ||
1361 | { | ||
1362 | struct ath_rate_priv *rc = file->private_data; | ||
1363 | char *buf; | ||
1364 | unsigned int len = 0, max; | ||
1365 | int rix; | ||
1366 | ssize_t retval; | ||
1367 | |||
1368 | if (rc->rate_table == NULL) | ||
1369 | return 0; | ||
1370 | |||
1371 | max = 80 + rc->rate_table_size * 1024 + 1; | ||
1372 | buf = kmalloc(max, GFP_KERNEL); | ||
1373 | if (buf == NULL) | ||
1374 | return -ENOMEM; | ||
1375 | |||
1376 | len += sprintf(buf, "%6s %6s %6s " | ||
1377 | "%10s %10s %10s %10s\n", | ||
1378 | "HT", "MCS", "Rate", | ||
1379 | "Success", "Retries", "XRetries", "PER"); | ||
1380 | |||
1381 | for (rix = 0; rix < rc->max_valid_rate; rix++) { | ||
1382 | u8 i = rc->valid_rate_index[rix]; | ||
1383 | u32 ratekbps = rc->rate_table->info[i].ratekbps; | ||
1384 | struct ath_rc_stats *stats = &rc->rcstats[i]; | ||
1385 | char mcs[5]; | ||
1386 | char htmode[5]; | ||
1387 | int used_mcs = 0, used_htmode = 0; | ||
1388 | |||
1389 | if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { | ||
1390 | used_mcs = scnprintf(mcs, 5, "%d", | ||
1391 | rc->rate_table->info[i].ratecode); | ||
1392 | |||
1393 | if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) | ||
1394 | used_htmode = scnprintf(htmode, 5, "HT40"); | ||
1395 | else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) | ||
1396 | used_htmode = scnprintf(htmode, 5, "HT20"); | ||
1397 | else | ||
1398 | used_htmode = scnprintf(htmode, 5, "????"); | ||
1399 | } | ||
1400 | |||
1401 | mcs[used_mcs] = '\0'; | ||
1402 | htmode[used_htmode] = '\0'; | ||
1403 | |||
1404 | len += scnprintf(buf + len, max - len, | ||
1405 | "%6s %6s %3u.%d: " | ||
1406 | "%10u %10u %10u %10u\n", | ||
1407 | htmode, | ||
1408 | mcs, | ||
1409 | ratekbps / 1000, | ||
1410 | (ratekbps % 1000) / 100, | ||
1411 | stats->success, | ||
1412 | stats->retries, | ||
1413 | stats->xretries, | ||
1414 | stats->per); | ||
1415 | } | ||
1416 | |||
1417 | if (len > max) | ||
1418 | len = max; | ||
1419 | |||
1420 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1421 | kfree(buf); | ||
1422 | return retval; | ||
1423 | } | ||
1424 | |||
1425 | static const struct file_operations fops_rcstat = { | ||
1426 | .read = read_file_rcstat, | ||
1427 | .open = simple_open, | ||
1428 | .owner = THIS_MODULE | ||
1429 | }; | ||
1430 | |||
1431 | static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, | ||
1432 | struct dentry *dir) | ||
1433 | { | ||
1434 | struct ath_rate_priv *rc = priv_sta; | ||
1435 | rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO, | ||
1436 | dir, rc, &fops_rcstat); | ||
1437 | } | ||
1438 | |||
1439 | static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta) | ||
1440 | { | ||
1441 | struct ath_rate_priv *rc = priv_sta; | ||
1442 | debugfs_remove(rc->debugfs_rcstats); | ||
1443 | } | ||
1444 | |||
1445 | #endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */ | ||
1446 | |||
1447 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | ||
1448 | { | ||
1449 | return hw->priv; | ||
1450 | } | ||
1451 | |||
1452 | static void ath_rate_free(void *priv) | ||
1453 | { | ||
1454 | return; | ||
1455 | } | ||
1456 | |||
1457 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | ||
1458 | { | ||
1459 | return kzalloc(sizeof(struct ath_rate_priv), gfp); | ||
1460 | } | ||
1461 | |||
1462 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, | ||
1463 | void *priv_sta) | ||
1464 | { | ||
1465 | struct ath_rate_priv *rate_priv = priv_sta; | ||
1466 | kfree(rate_priv); | ||
1467 | } | ||
1468 | |||
1469 | static struct rate_control_ops ath_rate_ops = { | ||
1470 | .module = NULL, | ||
1471 | .name = "ath9k_rate_control", | ||
1472 | .tx_status = ath_tx_status, | ||
1473 | .get_rate = ath_get_rate, | ||
1474 | .rate_init = ath_rate_init, | ||
1475 | .rate_update = ath_rate_update, | ||
1476 | .alloc = ath_rate_alloc, | ||
1477 | .free = ath_rate_free, | ||
1478 | .alloc_sta = ath_rate_alloc_sta, | ||
1479 | .free_sta = ath_rate_free_sta, | ||
1480 | |||
1481 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | ||
1482 | .add_sta_debugfs = ath_rate_add_sta_debugfs, | ||
1483 | .remove_sta_debugfs = ath_rate_remove_sta_debugfs, | ||
1484 | #endif | ||
1485 | }; | ||
1486 | |||
1487 | int ath_rate_control_register(void) | ||
1488 | { | ||
1489 | return ieee80211_rate_control_register(&ath_rate_ops); | ||
1490 | } | ||
1491 | |||
1492 | void ath_rate_control_unregister(void) | ||
1493 | { | ||
1494 | ieee80211_rate_control_unregister(&ath_rate_ops); | ||
1495 | } | ||