1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. |
4 | * |
5 | * Contact Information: wlanfae <wlanfae@realtek.com> |
6 | */ |
7 | #include "rtllib.h" |
8 | #include "rtl819x_HT.h" |
9 | u8 MCS_FILTER_ALL[16] = { |
10 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
11 | 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
12 | }; |
13 | |
14 | u8 MCS_FILTER_1SS[16] = { |
15 | 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, |
16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
17 | ; |
18 | |
19 | u16 MCS_DATA_RATE[2][2][77] = { |
20 | {{13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, |
21 | 260, 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, |
22 | 468, 520, 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, |
23 | 182, 208, 156, 195, 195, 234, 273, 273, 312, 130, 156, 181, 156, |
24 | 181, 208, 234, 208, 234, 260, 260, 286, 195, 234, 273, 234, 273, |
25 | 312, 351, 312, 351, 390, 390, 429}, |
26 | {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, |
27 | 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, |
28 | 578, 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, |
29 | 173, 217, 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, |
30 | 231, 260, 289, 289, 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, |
31 | 433, 433, 477} }, |
32 | {{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, |
33 | 540, 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, |
34 | 864, 972, 1080, 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, |
35 | 378, 378, 432, 324, 405, 405, 486, 567, 567, 648, 270, 324, 378, 324, |
36 | 378, 432, 486, 432, 486, 540, 540, 594, 405, 486, 567, 486, 567, 648, |
37 | 729, 648, 729, 810, 810, 891}, |
38 | {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, |
39 | 600, 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, |
40 | 960, 1080, 1200, 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, |
41 | 420, 420, 480, 360, 450, 450, 540, 630, 630, 720, 300, 360, 420, 360, |
42 | 420, 480, 540, 480, 540, 600, 600, 660, 450, 540, 630, 540, 630, 720, |
43 | 810, 720, 810, 900, 900, 990} } |
44 | }; |
45 | |
46 | static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf}; |
47 | |
48 | static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70}; |
49 | |
50 | static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e}; |
51 | |
52 | static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; |
53 | |
54 | static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf}; |
55 | |
56 | static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc}; |
57 | |
58 | static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e}; |
59 | |
60 | static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02}; |
61 | |
62 | static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0}; |
63 | |
64 | static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91}; |
65 | |
66 | static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94}; |
67 | |
68 | static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4}; |
69 | |
70 | void ht_update_default_setting(struct rtllib_device *ieee) |
71 | { |
72 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
73 | |
74 | ht_info->bRegShortGI20MHz = 1; |
75 | ht_info->bRegShortGI40MHz = 1; |
76 | |
77 | ht_info->bRegBW40MHz = 1; |
78 | |
79 | if (ht_info->bRegBW40MHz) |
80 | ht_info->bRegSuppCCK = 1; |
81 | else |
82 | ht_info->bRegSuppCCK = true; |
83 | |
84 | ht_info->nAMSDU_MaxSize = 7935UL; |
85 | ht_info->bAMSDU_Support = 0; |
86 | |
87 | ht_info->bAMPDUEnable = 1; |
88 | ht_info->AMPDU_Factor = 2; |
89 | ht_info->MPDU_Density = 0; |
90 | |
91 | ht_info->self_mimo_ps = 3; |
92 | if (ht_info->self_mimo_ps == 2) |
93 | ht_info->self_mimo_ps = 3; |
94 | ieee->tx_dis_rate_fallback = 0; |
95 | ieee->tx_use_drv_assinged_rate = 0; |
96 | |
97 | ieee->bTxEnableFwCalcDur = 1; |
98 | |
99 | ht_info->reg_rt2rt_aggregation = 1; |
100 | |
101 | ht_info->reg_rx_reorder_enable = 1; |
102 | ht_info->rx_reorder_win_size = 64; |
103 | ht_info->rx_reorder_pending_time = 30; |
104 | } |
105 | |
106 | static u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate) |
107 | { |
108 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
109 | |
110 | u8 is40MHz = (ht_info->bCurBW40MHz) ? 1 : 0; |
111 | u8 isShortGI = (ht_info->bCurBW40MHz) ? |
112 | ((ht_info->bCurShortGI40MHz) ? 1 : 0) : |
113 | ((ht_info->bCurShortGI20MHz) ? 1 : 0); |
114 | return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate & 0x7f)]; |
115 | } |
116 | |
117 | u16 TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate) |
118 | { |
119 | u16 CCKOFDMRate[12] = {0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, |
120 | 0x24, 0x30, 0x48, 0x60, 0x6c}; |
121 | u8 is40MHz = 0; |
122 | u8 isShortGI = 0; |
123 | |
124 | if (nDataRate < 12) |
125 | return CCKOFDMRate[nDataRate]; |
126 | if (nDataRate >= 0x10 && nDataRate <= 0x1f) { |
127 | is40MHz = 0; |
128 | isShortGI = 0; |
129 | } else if (nDataRate >= 0x20 && nDataRate <= 0x2f) { |
130 | is40MHz = 1; |
131 | isShortGI = 0; |
132 | } else if (nDataRate >= 0x30 && nDataRate <= 0x3f) { |
133 | is40MHz = 0; |
134 | isShortGI = 1; |
135 | } else if (nDataRate >= 0x40 && nDataRate <= 0x4f) { |
136 | is40MHz = 1; |
137 | isShortGI = 1; |
138 | } |
139 | return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate & 0xf]; |
140 | } |
141 | |
142 | bool IsHTHalfNmodeAPs(struct rtllib_device *ieee) |
143 | { |
144 | bool retValue = false; |
145 | struct rtllib_network *net = &ieee->current_network; |
146 | |
147 | if ((memcmp(p: net->bssid, q: BELKINF5D8233V1_RALINK, size: 3) == 0) || |
148 | (memcmp(p: net->bssid, q: BELKINF5D82334V3_RALINK, size: 3) == 0) || |
149 | (memcmp(p: net->bssid, q: PCI_RALINK, size: 3) == 0) || |
150 | (memcmp(p: net->bssid, q: EDIMAX_RALINK, size: 3) == 0) || |
151 | (memcmp(p: net->bssid, q: AIRLINK_RALINK, size: 3) == 0) || |
152 | (net->ralink_cap_exist)) |
153 | retValue = true; |
154 | else if (!memcmp(p: net->bssid, q: UNKNOWN_BORADCOM, size: 3) || |
155 | !memcmp(p: net->bssid, q: LINKSYSWRT330_LINKSYSWRT300_BROADCOM, size: 3) || |
156 | !memcmp(p: net->bssid, q: LINKSYSWRT350_LINKSYSWRT150_BROADCOM, size: 3) || |
157 | (net->broadcom_cap_exist)) |
158 | retValue = true; |
159 | else if (net->bssht.bd_rt2rt_aggregation) |
160 | retValue = true; |
161 | else |
162 | retValue = false; |
163 | |
164 | return retValue; |
165 | } |
166 | |
167 | static void HTIOTPeerDetermine(struct rtllib_device *ieee) |
168 | { |
169 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
170 | struct rtllib_network *net = &ieee->current_network; |
171 | |
172 | if (net->bssht.bd_rt2rt_aggregation) { |
173 | ht_info->IOTPeer = HT_IOT_PEER_REALTEK; |
174 | if (net->bssht.rt2rt_ht_mode & RT_HT_CAP_USE_92SE) |
175 | ht_info->IOTPeer = HT_IOT_PEER_REALTEK_92SE; |
176 | if (net->bssht.rt2rt_ht_mode & RT_HT_CAP_USE_SOFTAP) |
177 | ht_info->IOTPeer = HT_IOT_PEER_92U_SOFTAP; |
178 | } else if (net->broadcom_cap_exist) { |
179 | ht_info->IOTPeer = HT_IOT_PEER_BROADCOM; |
180 | } else if (!memcmp(p: net->bssid, q: UNKNOWN_BORADCOM, size: 3) || |
181 | !memcmp(p: net->bssid, q: LINKSYSWRT330_LINKSYSWRT300_BROADCOM, size: 3) || |
182 | !memcmp(p: net->bssid, q: LINKSYSWRT350_LINKSYSWRT150_BROADCOM, size: 3)) { |
183 | ht_info->IOTPeer = HT_IOT_PEER_BROADCOM; |
184 | } else if ((memcmp(p: net->bssid, q: BELKINF5D8233V1_RALINK, size: 3) == 0) || |
185 | (memcmp(p: net->bssid, q: BELKINF5D82334V3_RALINK, size: 3) == 0) || |
186 | (memcmp(p: net->bssid, q: PCI_RALINK, size: 3) == 0) || |
187 | (memcmp(p: net->bssid, q: EDIMAX_RALINK, size: 3) == 0) || |
188 | (memcmp(p: net->bssid, q: AIRLINK_RALINK, size: 3) == 0) || |
189 | net->ralink_cap_exist) { |
190 | ht_info->IOTPeer = HT_IOT_PEER_RALINK; |
191 | } else if ((net->atheros_cap_exist) || |
192 | (memcmp(p: net->bssid, q: DLINK_ATHEROS_1, size: 3) == 0) || |
193 | (memcmp(p: net->bssid, q: DLINK_ATHEROS_2, size: 3) == 0)) { |
194 | ht_info->IOTPeer = HT_IOT_PEER_ATHEROS; |
195 | } else if ((memcmp(p: net->bssid, q: CISCO_BROADCOM, size: 3) == 0) || |
196 | net->cisco_cap_exist) { |
197 | ht_info->IOTPeer = HT_IOT_PEER_CISCO; |
198 | } else if ((memcmp(p: net->bssid, q: LINKSYS_MARVELL_4400N, size: 3) == 0) || |
199 | net->marvell_cap_exist) { |
200 | ht_info->IOTPeer = HT_IOT_PEER_MARVELL; |
201 | } else if (net->airgo_cap_exist) { |
202 | ht_info->IOTPeer = HT_IOT_PEER_AIRGO; |
203 | } else { |
204 | ht_info->IOTPeer = HT_IOT_PEER_UNKNOWN; |
205 | } |
206 | |
207 | netdev_dbg(ieee->dev, "IOTPEER: %x\n" , ht_info->IOTPeer); |
208 | } |
209 | |
210 | static u8 HTIOTActIsMgntUseCCK6M(struct rtllib_device *ieee, |
211 | struct rtllib_network *network) |
212 | { |
213 | u8 retValue = 0; |
214 | |
215 | if (ieee->ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) |
216 | retValue = 1; |
217 | |
218 | return retValue; |
219 | } |
220 | |
221 | static u8 HTIOTActIsCCDFsync(struct rtllib_device *ieee) |
222 | { |
223 | u8 retValue = 0; |
224 | |
225 | if (ieee->ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) |
226 | retValue = 1; |
227 | return retValue; |
228 | } |
229 | |
230 | static void HTIOTActDetermineRaFunc(struct rtllib_device *ieee, bool bPeerRx2ss) |
231 | { |
232 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
233 | |
234 | ht_info->iot_ra_func &= HT_IOT_RAFUNC_DISABLE_ALL; |
235 | |
236 | if (ht_info->IOTPeer == HT_IOT_PEER_RALINK && !bPeerRx2ss) |
237 | ht_info->iot_ra_func |= HT_IOT_RAFUNC_PEER_1R; |
238 | |
239 | if (ht_info->iot_action & HT_IOT_ACT_AMSDU_ENABLE) |
240 | ht_info->iot_ra_func |= HT_IOT_RAFUNC_TX_AMSDU; |
241 | } |
242 | |
243 | void HTResetIOTSetting(struct rt_hi_throughput *ht_info) |
244 | { |
245 | ht_info->iot_action = 0; |
246 | ht_info->IOTPeer = HT_IOT_PEER_UNKNOWN; |
247 | ht_info->iot_ra_func = 0; |
248 | } |
249 | |
250 | void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap, |
251 | u8 *len, u8 IsEncrypt, bool bAssoc) |
252 | { |
253 | struct rt_hi_throughput *pHT = ieee->ht_info; |
254 | struct ht_capab_ele *pCapELE = NULL; |
255 | |
256 | if (!posHTCap || !pHT) { |
257 | netdev_warn(dev: ieee->dev, |
258 | format: "%s(): posHTCap and ht_info are null\n" , __func__); |
259 | return; |
260 | } |
261 | memset(posHTCap, 0, *len); |
262 | |
263 | if ((bAssoc) && (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)) { |
264 | static const u8 EWC11NHTCap[] = { 0x00, 0x90, 0x4c, 0x33 }; |
265 | |
266 | memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap)); |
267 | pCapELE = (struct ht_capab_ele *)&posHTCap[4]; |
268 | *len = 30 + 2; |
269 | } else { |
270 | pCapELE = (struct ht_capab_ele *)posHTCap; |
271 | *len = 26 + 2; |
272 | } |
273 | |
274 | pCapELE->AdvCoding = 0; |
275 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) |
276 | pCapELE->ChlWidth = 0; |
277 | else |
278 | pCapELE->ChlWidth = (pHT->bRegBW40MHz ? 1 : 0); |
279 | |
280 | pCapELE->MimoPwrSave = pHT->self_mimo_ps; |
281 | pCapELE->GreenField = 0; |
282 | pCapELE->ShortGI20Mhz = 1; |
283 | pCapELE->ShortGI40Mhz = 1; |
284 | |
285 | pCapELE->TxSTBC = 1; |
286 | pCapELE->RxSTBC = 0; |
287 | pCapELE->DelayBA = 0; |
288 | pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE >= 7935) ? 1 : 0; |
289 | pCapELE->DssCCk = ((pHT->bRegBW40MHz) ? (pHT->bRegSuppCCK ? 1 : 0) : 0); |
290 | pCapELE->PSMP = 0; |
291 | pCapELE->LSigTxopProtect = 0; |
292 | |
293 | netdev_dbg(ieee->dev, |
294 | "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n" , |
295 | pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk); |
296 | |
297 | if (IsEncrypt) { |
298 | pCapELE->MPDUDensity = 7; |
299 | pCapELE->MaxRxAMPDUFactor = 2; |
300 | } else { |
301 | pCapELE->MaxRxAMPDUFactor = 3; |
302 | pCapELE->MPDUDensity = 0; |
303 | } |
304 | |
305 | memcpy(pCapELE->MCS, ieee->reg_dot11ht_oper_rate_set, 16); |
306 | memset(&pCapELE->ExtHTCapInfo, 0, 2); |
307 | memset(pCapELE->TxBFCap, 0, 4); |
308 | |
309 | pCapELE->ASCap = 0; |
310 | |
311 | if (bAssoc) { |
312 | if (pHT->iot_action & HT_IOT_ACT_DISABLE_MCS15) |
313 | pCapELE->MCS[1] &= 0x7f; |
314 | |
315 | if (pHT->iot_action & HT_IOT_ACT_DISABLE_MCS14) |
316 | pCapELE->MCS[1] &= 0xbf; |
317 | |
318 | if (pHT->iot_action & HT_IOT_ACT_DISABLE_ALL_2SS) |
319 | pCapELE->MCS[1] &= 0x00; |
320 | |
321 | if (pHT->iot_action & HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI) |
322 | pCapELE->ShortGI40Mhz = 0; |
323 | |
324 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) { |
325 | pCapELE->ChlWidth = 0; |
326 | pCapELE->MCS[1] = 0; |
327 | } |
328 | } |
329 | } |
330 | |
331 | void HTConstructInfoElement(struct rtllib_device *ieee, u8 *posHTInfo, |
332 | u8 *len, u8 IsEncrypt) |
333 | { |
334 | struct ht_info_ele *pHTInfoEle = (struct ht_info_ele *)posHTInfo; |
335 | |
336 | if (!posHTInfo || !pHTInfoEle) { |
337 | netdev_warn(dev: ieee->dev, |
338 | format: "%s(): posHTInfo and pHTInfoEle are null\n" , |
339 | __func__); |
340 | return; |
341 | } |
342 | |
343 | memset(posHTInfo, 0, *len); |
344 | *len = 0; |
345 | } |
346 | |
347 | void HTConstructRT2RTAggElement(struct rtllib_device *ieee, u8 *posRT2RTAgg, |
348 | u8 *len) |
349 | { |
350 | if (!posRT2RTAgg) { |
351 | netdev_warn(dev: ieee->dev, format: "%s(): posRT2RTAgg is null\n" , __func__); |
352 | return; |
353 | } |
354 | memset(posRT2RTAgg, 0, *len); |
355 | *posRT2RTAgg++ = 0x00; |
356 | *posRT2RTAgg++ = 0xe0; |
357 | *posRT2RTAgg++ = 0x4c; |
358 | *posRT2RTAgg++ = 0x02; |
359 | *posRT2RTAgg++ = 0x01; |
360 | |
361 | *posRT2RTAgg = 0x30; |
362 | |
363 | if (ieee->bSupportRemoteWakeUp) |
364 | *posRT2RTAgg |= RT_HT_CAP_USE_WOW; |
365 | |
366 | *len = 6 + 2; |
367 | } |
368 | |
369 | static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS) |
370 | { |
371 | u8 i; |
372 | |
373 | if (!pOperateMCS) { |
374 | netdev_warn(dev: ieee->dev, format: "%s(): pOperateMCS is null\n" , __func__); |
375 | return false; |
376 | } |
377 | |
378 | switch (ieee->mode) { |
379 | case WIRELESS_MODE_B: |
380 | case WIRELESS_MODE_G: |
381 | for (i = 0; i <= 15; i++) |
382 | pOperateMCS[i] = 0; |
383 | break; |
384 | case WIRELESS_MODE_N_24G: |
385 | pOperateMCS[0] &= RATE_ADPT_1SS_MASK; |
386 | pOperateMCS[1] &= RATE_ADPT_2SS_MASK; |
387 | pOperateMCS[3] &= RATE_ADPT_MCS32_MASK; |
388 | break; |
389 | default: |
390 | break; |
391 | } |
392 | |
393 | return true; |
394 | } |
395 | |
396 | u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet, |
397 | u8 *pMCSFilter) |
398 | { |
399 | u8 i, j; |
400 | u8 bitMap; |
401 | u8 mcsRate = 0; |
402 | u8 availableMcsRate[16]; |
403 | |
404 | if (!pMCSRateSet || !pMCSFilter) { |
405 | netdev_warn(dev: ieee->dev, |
406 | format: "%s(): pMCSRateSet and pMCSFilter are null\n" , |
407 | __func__); |
408 | return false; |
409 | } |
410 | for (i = 0; i < 16; i++) |
411 | availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i]; |
412 | |
413 | for (i = 0; i < 16; i++) { |
414 | if (availableMcsRate[i] != 0) |
415 | break; |
416 | } |
417 | if (i == 16) |
418 | return false; |
419 | |
420 | for (i = 0; i < 16; i++) { |
421 | if (availableMcsRate[i] != 0) { |
422 | bitMap = availableMcsRate[i]; |
423 | for (j = 0; j < 8; j++) { |
424 | if ((bitMap % 2) != 0) { |
425 | if (HTMcsToDataRate(ieee, nMcsRate: (8 * i + j)) > |
426 | HTMcsToDataRate(ieee, nMcsRate: mcsRate)) |
427 | mcsRate = 8 * i + j; |
428 | } |
429 | bitMap >>= 1; |
430 | } |
431 | } |
432 | } |
433 | return mcsRate | 0x80; |
434 | } |
435 | |
436 | static u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS, |
437 | u8 *pOperateMCS) |
438 | { |
439 | u8 i; |
440 | |
441 | for (i = 0; i <= 15; i++) |
442 | pOperateMCS[i] = ieee->reg_dot11tx_ht_oper_rate_set[i] & |
443 | pSupportMCS[i]; |
444 | |
445 | HT_PickMCSRate(ieee, pOperateMCS); |
446 | |
447 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) |
448 | pOperateMCS[1] = 0; |
449 | |
450 | for (i = 2; i <= 15; i++) |
451 | pOperateMCS[i] = 0; |
452 | |
453 | return true; |
454 | } |
455 | |
456 | void HTSetConnectBwMode(struct rtllib_device *ieee, |
457 | enum ht_channel_width bandwidth, |
458 | enum ht_extchnl_offset Offset); |
459 | |
460 | void HTOnAssocRsp(struct rtllib_device *ieee) |
461 | { |
462 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
463 | struct ht_capab_ele *pPeerHTCap = NULL; |
464 | struct ht_info_ele *pPeerHTInfo = NULL; |
465 | u16 nMaxAMSDUSize = 0; |
466 | u8 *pMcsFilter = NULL; |
467 | |
468 | static const u8 EWC11NHTCap[] = { 0x00, 0x90, 0x4c, 0x33 }; |
469 | static const u8 EWC11NHTInfo[] = { 0x00, 0x90, 0x4c, 0x34 }; |
470 | |
471 | if (!ht_info->current_ht_support) { |
472 | netdev_warn(dev: ieee->dev, format: "%s(): HT_DISABLE\n" , __func__); |
473 | return; |
474 | } |
475 | netdev_dbg(ieee->dev, "%s(): HT_ENABLE\n" , __func__); |
476 | |
477 | if (!memcmp(p: ht_info->PeerHTCapBuf, q: EWC11NHTCap, size: sizeof(EWC11NHTCap))) |
478 | pPeerHTCap = (struct ht_capab_ele *)(&ht_info->PeerHTCapBuf[4]); |
479 | else |
480 | pPeerHTCap = (struct ht_capab_ele *)(ht_info->PeerHTCapBuf); |
481 | |
482 | if (!memcmp(p: ht_info->PeerHTInfoBuf, q: EWC11NHTInfo, size: sizeof(EWC11NHTInfo))) |
483 | pPeerHTInfo = (struct ht_info_ele *) |
484 | (&ht_info->PeerHTInfoBuf[4]); |
485 | else |
486 | pPeerHTInfo = (struct ht_info_ele *)(ht_info->PeerHTInfoBuf); |
487 | |
488 | #ifdef VERBOSE_DEBUG |
489 | print_hex_dump_bytes("%s: " , __func__, DUMP_PREFIX_NONE, |
490 | pPeerHTCap, sizeof(struct ht_capab_ele)); |
491 | #endif |
492 | HTSetConnectBwMode(ieee, bandwidth: (enum ht_channel_width)(pPeerHTCap->ChlWidth), |
493 | Offset: (enum ht_extchnl_offset)(pPeerHTInfo->ExtChlOffset)); |
494 | ht_info->cur_tx_bw40mhz = ((pPeerHTInfo->RecommemdedTxWidth == 1) ? |
495 | true : false); |
496 | |
497 | ht_info->bCurShortGI20MHz = ((ht_info->bRegShortGI20MHz) ? |
498 | ((pPeerHTCap->ShortGI20Mhz == 1) ? |
499 | true : false) : false); |
500 | ht_info->bCurShortGI40MHz = ((ht_info->bRegShortGI40MHz) ? |
501 | ((pPeerHTCap->ShortGI40Mhz == 1) ? |
502 | true : false) : false); |
503 | |
504 | ht_info->bCurSuppCCK = ((ht_info->bRegSuppCCK) ? |
505 | ((pPeerHTCap->DssCCk == 1) ? true : |
506 | false) : false); |
507 | |
508 | ht_info->bCurrent_AMSDU_Support = ht_info->bAMSDU_Support; |
509 | |
510 | nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize == 0) ? 3839 : 7935; |
511 | |
512 | if (ht_info->nAMSDU_MaxSize > nMaxAMSDUSize) |
513 | ht_info->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize; |
514 | else |
515 | ht_info->nCurrent_AMSDU_MaxSize = ht_info->nAMSDU_MaxSize; |
516 | |
517 | ht_info->bCurrentAMPDUEnable = ht_info->bAMPDUEnable; |
518 | if (ieee->rtllib_ap_sec_type && |
519 | (ieee->rtllib_ap_sec_type(ieee) & (SEC_ALG_WEP | SEC_ALG_TKIP))) { |
520 | if ((ht_info->IOTPeer == HT_IOT_PEER_ATHEROS) || |
521 | (ht_info->IOTPeer == HT_IOT_PEER_UNKNOWN)) |
522 | ht_info->bCurrentAMPDUEnable = false; |
523 | } |
524 | |
525 | if (!ht_info->reg_rt2rt_aggregation) { |
526 | if (ht_info->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor) |
527 | ht_info->CurrentAMPDUFactor = |
528 | pPeerHTCap->MaxRxAMPDUFactor; |
529 | else |
530 | ht_info->CurrentAMPDUFactor = ht_info->AMPDU_Factor; |
531 | |
532 | } else { |
533 | if (ieee->current_network.bssht.bd_rt2rt_aggregation) { |
534 | if (ieee->pairwise_key_type != KEY_TYPE_NA) |
535 | ht_info->CurrentAMPDUFactor = |
536 | pPeerHTCap->MaxRxAMPDUFactor; |
537 | else |
538 | ht_info->CurrentAMPDUFactor = HT_AGG_SIZE_64K; |
539 | } else { |
540 | ht_info->CurrentAMPDUFactor = min_t(u32, pPeerHTCap->MaxRxAMPDUFactor, |
541 | HT_AGG_SIZE_32K); |
542 | } |
543 | } |
544 | ht_info->current_mpdu_density = max_t(u8, ht_info->MPDU_Density, |
545 | pPeerHTCap->MPDUDensity); |
546 | if (ht_info->iot_action & HT_IOT_ACT_TX_USE_AMSDU_8K) { |
547 | ht_info->bCurrentAMPDUEnable = false; |
548 | ht_info->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE; |
549 | } |
550 | ht_info->cur_rx_reorder_enable = ht_info->reg_rx_reorder_enable; |
551 | |
552 | if (pPeerHTCap->MCS[0] == 0) |
553 | pPeerHTCap->MCS[0] = 0xff; |
554 | |
555 | HTIOTActDetermineRaFunc(ieee, bPeerRx2ss: ((pPeerHTCap->MCS[1]) != 0)); |
556 | |
557 | HTFilterMCSRate(ieee, pSupportMCS: pPeerHTCap->MCS, pOperateMCS: ieee->dot11ht_oper_rate_set); |
558 | |
559 | ht_info->peer_mimo_ps = pPeerHTCap->MimoPwrSave; |
560 | if (ht_info->peer_mimo_ps == MIMO_PS_STATIC) |
561 | pMcsFilter = MCS_FILTER_1SS; |
562 | else |
563 | pMcsFilter = MCS_FILTER_ALL; |
564 | ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, |
565 | pMCSRateSet: ieee->dot11ht_oper_rate_set, |
566 | pMCSFilter: pMcsFilter); |
567 | ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; |
568 | |
569 | ht_info->current_op_mode = pPeerHTInfo->OptMode; |
570 | } |
571 | |
572 | void HTInitializeHTInfo(struct rtllib_device *ieee) |
573 | { |
574 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
575 | |
576 | ht_info->current_ht_support = false; |
577 | |
578 | ht_info->bCurBW40MHz = false; |
579 | ht_info->cur_tx_bw40mhz = false; |
580 | |
581 | ht_info->bCurShortGI20MHz = false; |
582 | ht_info->bCurShortGI40MHz = false; |
583 | ht_info->forced_short_gi = false; |
584 | |
585 | ht_info->bCurSuppCCK = true; |
586 | |
587 | ht_info->bCurrent_AMSDU_Support = false; |
588 | ht_info->nCurrent_AMSDU_MaxSize = ht_info->nAMSDU_MaxSize; |
589 | ht_info->current_mpdu_density = ht_info->MPDU_Density; |
590 | ht_info->CurrentAMPDUFactor = ht_info->AMPDU_Factor; |
591 | |
592 | memset((void *)(&ht_info->SelfHTCap), 0, |
593 | sizeof(ht_info->SelfHTCap)); |
594 | memset((void *)(&ht_info->SelfHTInfo), 0, |
595 | sizeof(ht_info->SelfHTInfo)); |
596 | memset((void *)(&ht_info->PeerHTCapBuf), 0, |
597 | sizeof(ht_info->PeerHTCapBuf)); |
598 | memset((void *)(&ht_info->PeerHTInfoBuf), 0, |
599 | sizeof(ht_info->PeerHTInfoBuf)); |
600 | |
601 | ht_info->sw_bw_in_progress = false; |
602 | |
603 | ht_info->ePeerHTSpecVer = HT_SPEC_VER_IEEE; |
604 | |
605 | ht_info->current_rt2rt_aggregation = false; |
606 | ht_info->current_rt2rt_long_slot_time = false; |
607 | ht_info->RT2RT_HT_Mode = (enum rt_ht_capability)0; |
608 | |
609 | ht_info->IOTPeer = 0; |
610 | ht_info->iot_action = 0; |
611 | ht_info->iot_ra_func = 0; |
612 | |
613 | { |
614 | u8 *RegHTSuppRateSets = &ieee->reg_ht_supp_rate_set[0]; |
615 | |
616 | RegHTSuppRateSets[0] = 0xFF; |
617 | RegHTSuppRateSets[1] = 0xFF; |
618 | RegHTSuppRateSets[4] = 0x01; |
619 | } |
620 | } |
621 | |
622 | void HTInitializeBssDesc(struct bss_ht *pBssHT) |
623 | { |
624 | pBssHT->bd_support_ht = false; |
625 | memset(pBssHT->bd_ht_cap_buf, 0, sizeof(pBssHT->bd_ht_cap_buf)); |
626 | pBssHT->bd_ht_cap_len = 0; |
627 | memset(pBssHT->bd_ht_info_buf, 0, sizeof(pBssHT->bd_ht_info_buf)); |
628 | pBssHT->bd_ht_info_len = 0; |
629 | |
630 | pBssHT->bd_ht_spec_ver = HT_SPEC_VER_IEEE; |
631 | |
632 | pBssHT->bd_rt2rt_aggregation = false; |
633 | pBssHT->bd_rt2rt_long_slot_time = false; |
634 | pBssHT->rt2rt_ht_mode = (enum rt_ht_capability)0; |
635 | } |
636 | |
637 | void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee, |
638 | struct rtllib_network *pNetwork) |
639 | { |
640 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
641 | u8 bIOTAction = 0; |
642 | |
643 | /* unmark enable_ht flag here is the same reason why unmarked in |
644 | * function rtllib_softmac_new_net. WB 2008.09.10 |
645 | */ |
646 | if (pNetwork->bssht.bd_support_ht) { |
647 | ht_info->current_ht_support = true; |
648 | ht_info->ePeerHTSpecVer = pNetwork->bssht.bd_ht_spec_ver; |
649 | |
650 | if (pNetwork->bssht.bd_ht_cap_len > 0 && |
651 | pNetwork->bssht.bd_ht_cap_len <= sizeof(ht_info->PeerHTCapBuf)) |
652 | memcpy(ht_info->PeerHTCapBuf, |
653 | pNetwork->bssht.bd_ht_cap_buf, |
654 | pNetwork->bssht.bd_ht_cap_len); |
655 | |
656 | if (pNetwork->bssht.bd_ht_info_len > 0 && |
657 | pNetwork->bssht.bd_ht_info_len <= |
658 | sizeof(ht_info->PeerHTInfoBuf)) |
659 | memcpy(ht_info->PeerHTInfoBuf, |
660 | pNetwork->bssht.bd_ht_info_buf, |
661 | pNetwork->bssht.bd_ht_info_len); |
662 | |
663 | if (ht_info->reg_rt2rt_aggregation) { |
664 | ht_info->current_rt2rt_aggregation = |
665 | pNetwork->bssht.bd_rt2rt_aggregation; |
666 | ht_info->current_rt2rt_long_slot_time = |
667 | pNetwork->bssht.bd_rt2rt_long_slot_time; |
668 | ht_info->RT2RT_HT_Mode = pNetwork->bssht.rt2rt_ht_mode; |
669 | } else { |
670 | ht_info->current_rt2rt_aggregation = false; |
671 | ht_info->current_rt2rt_long_slot_time = false; |
672 | ht_info->RT2RT_HT_Mode = (enum rt_ht_capability)0; |
673 | } |
674 | |
675 | HTIOTPeerDetermine(ieee); |
676 | |
677 | ht_info->iot_action = 0; |
678 | bIOTAction = HTIOTActIsMgntUseCCK6M(ieee, network: pNetwork); |
679 | if (bIOTAction) |
680 | ht_info->iot_action |= HT_IOT_ACT_MGNT_USE_CCK_6M; |
681 | bIOTAction = HTIOTActIsCCDFsync(ieee); |
682 | if (bIOTAction) |
683 | ht_info->iot_action |= HT_IOT_ACT_CDD_FSYNC; |
684 | } else { |
685 | ht_info->current_ht_support = false; |
686 | ht_info->current_rt2rt_aggregation = false; |
687 | ht_info->current_rt2rt_long_slot_time = false; |
688 | ht_info->RT2RT_HT_Mode = (enum rt_ht_capability)0; |
689 | |
690 | ht_info->iot_action = 0; |
691 | ht_info->iot_ra_func = 0; |
692 | } |
693 | } |
694 | |
695 | void HT_update_self_and_peer_setting(struct rtllib_device *ieee, |
696 | struct rtllib_network *pNetwork) |
697 | { |
698 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
699 | struct ht_info_ele *pPeerHTInfo = |
700 | (struct ht_info_ele *)pNetwork->bssht.bd_ht_info_buf; |
701 | |
702 | if (ht_info->current_ht_support) { |
703 | if (pNetwork->bssht.bd_ht_info_len != 0) |
704 | ht_info->current_op_mode = pPeerHTInfo->OptMode; |
705 | } |
706 | } |
707 | EXPORT_SYMBOL(HT_update_self_and_peer_setting); |
708 | |
709 | u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame) |
710 | { |
711 | if (ieee->ht_info->current_ht_support) { |
712 | if ((IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) { |
713 | netdev_dbg(ieee->dev, "HT CONTROL FILED EXIST!!\n" ); |
714 | return true; |
715 | } |
716 | } |
717 | return false; |
718 | } |
719 | |
720 | static void HTSetConnectBwModeCallback(struct rtllib_device *ieee) |
721 | { |
722 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
723 | |
724 | if (ht_info->bCurBW40MHz) { |
725 | if (ht_info->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_UPPER) |
726 | ieee->set_chan(ieee->dev, |
727 | ieee->current_network.channel + 2); |
728 | else if (ht_info->CurSTAExtChnlOffset == |
729 | HT_EXTCHNL_OFFSET_LOWER) |
730 | ieee->set_chan(ieee->dev, |
731 | ieee->current_network.channel - 2); |
732 | else |
733 | ieee->set_chan(ieee->dev, |
734 | ieee->current_network.channel); |
735 | |
736 | ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20_40, |
737 | ht_info->CurSTAExtChnlOffset); |
738 | } else { |
739 | ieee->set_chan(ieee->dev, ieee->current_network.channel); |
740 | ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20, |
741 | HT_EXTCHNL_OFFSET_NO_EXT); |
742 | } |
743 | |
744 | ht_info->sw_bw_in_progress = false; |
745 | } |
746 | |
747 | void HTSetConnectBwMode(struct rtllib_device *ieee, |
748 | enum ht_channel_width bandwidth, |
749 | enum ht_extchnl_offset Offset) |
750 | { |
751 | struct rt_hi_throughput *ht_info = ieee->ht_info; |
752 | |
753 | if (!ht_info->bRegBW40MHz) |
754 | return; |
755 | |
756 | if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) |
757 | bandwidth = HT_CHANNEL_WIDTH_20; |
758 | |
759 | if (ht_info->sw_bw_in_progress) { |
760 | pr_info("%s: sw_bw_in_progress!!\n" , __func__); |
761 | return; |
762 | } |
763 | if (bandwidth == HT_CHANNEL_WIDTH_20_40) { |
764 | if (ieee->current_network.channel < 2 && |
765 | Offset == HT_EXTCHNL_OFFSET_LOWER) |
766 | Offset = HT_EXTCHNL_OFFSET_NO_EXT; |
767 | if (Offset == HT_EXTCHNL_OFFSET_UPPER || |
768 | Offset == HT_EXTCHNL_OFFSET_LOWER) { |
769 | ht_info->bCurBW40MHz = true; |
770 | ht_info->CurSTAExtChnlOffset = Offset; |
771 | } else { |
772 | ht_info->bCurBW40MHz = false; |
773 | ht_info->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; |
774 | } |
775 | } else { |
776 | ht_info->bCurBW40MHz = false; |
777 | ht_info->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; |
778 | } |
779 | |
780 | netdev_dbg(ieee->dev, "%s():ht_info->bCurBW40MHz:%x\n" , __func__, |
781 | ht_info->bCurBW40MHz); |
782 | |
783 | ht_info->sw_bw_in_progress = true; |
784 | |
785 | HTSetConnectBwModeCallback(ieee); |
786 | } |
787 | |