GNU Linux-libre 4.19.207-gnu1
[releases.git] / drivers / staging / rtl8192u / ieee80211 / rtl819x_HTProc.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * As this function is mainly ported from Windows driver, so leave the name
5  * little changed. If any confusion caused, tell me. Created by WB. 2008.05.08
6  */
7 #include "ieee80211.h"
8
9 u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
10
11 u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
12
13 u16 MCS_DATA_RATE[2][2][77] = {
14         {       {13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260,
15                  39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520,
16                  0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195,
17                  195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260,
18                  286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429},                      // Long GI, 20MHz
19                 {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289,
20                  43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578,
21                  0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217,
22                  217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289,
23                  318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477}       },              // Short GI, 20MHz
24         {       {27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540,
25                  81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080,
26                  12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405,
27                  405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540,
28                  594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891},      // Long GI, 40MHz
29                 {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600,
30                  90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200,
31                  13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450,
32                  450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600,
33                  660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990}       }       // Short GI, 40MHz
34 };
35
36 static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
37 static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
38 static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
39 static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
40 static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};       //cosa 03202008
41 static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
42 static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
43 static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
44 static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
45 //static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
46 static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
47 /*
48  * 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we
49  * put the code in other place??
50  * static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
51  */
52 /*
53  *function:  This function update default settings in pHTInfo structure
54  *   input:  PRT_HIGH_THROUGHPUT        pHTInfo
55  *  output:  none
56  *  return:  none
57  *  notice:  These value need be modified if any changes.
58  */
59 void HTUpdateDefaultSetting(struct ieee80211_device *ieee)
60 {
61         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
62         //const typeof( ((struct ieee80211_device *)0)->pHTInfo ) *__mptr = &pHTInfo;
63
64         //printk("pHTinfo:%p, &pHTinfo:%p, mptr:%p,  offsetof:%x\n", pHTInfo, &pHTInfo, __mptr, offsetof(struct ieee80211_device, pHTInfo));
65         //printk("===>ieee:%p,\n", ieee);
66         // ShortGI support
67         pHTInfo->bRegShortGI20MHz = 1;
68         pHTInfo->bRegShortGI40MHz = 1;
69
70         // 40MHz channel support
71         pHTInfo->bRegBW40MHz = 1;
72
73         // CCK rate support in 40MHz channel
74         if (pHTInfo->bRegBW40MHz)
75                 pHTInfo->bRegSuppCCK = 1;
76         else
77                 pHTInfo->bRegSuppCCK = true;
78
79         // AMSDU related
80         pHTInfo->nAMSDU_MaxSize = 7935UL;
81         pHTInfo->bAMSDU_Support = 0;
82
83         // AMPDU related
84         pHTInfo->bAMPDUEnable = 1;
85         pHTInfo->AMPDU_Factor = 2; //// 0: 2n13(8K), 1:2n14(16K), 2:2n15(32K), 3:2n16(64k)
86         pHTInfo->MPDU_Density = 0;// 0: No restriction, 1: 1/8usec, 2: 1/4usec, 3: 1/2usec, 4: 1usec, 5: 2usec, 6: 4usec, 7:8usec
87
88         // MIMO Power Save
89         pHTInfo->SelfMimoPs = 3;// 0: Static Mimo Ps, 1: Dynamic Mimo Ps, 3: No Limitation, 2: Reserved(Set to 3 automatically.)
90         if (pHTInfo->SelfMimoPs == 2)
91                 pHTInfo->SelfMimoPs = 3;
92         // 8190 only. Assign rate operation mode to firmware
93         ieee->bTxDisableRateFallBack = 0;
94         ieee->bTxUseDriverAssingedRate = 0;
95
96 #ifdef  TO_DO_LIST
97         // 8190 only. Assign duration operation mode to firmware
98         pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur;
99 #endif
100         /*
101          * 8190 only, Realtek proprietary aggregation mode
102          * Set MPDUDensity=2,   1: Set MPDUDensity=2(32k)  for Realtek AP and set MPDUDensity=0(8k) for others
103          */
104         pHTInfo->bRegRT2RTAggregation = 1;//0: Set MPDUDensity=2,   1: Set MPDUDensity=2(32k)  for Realtek AP and set MPDUDensity=0(8k) for others
105
106         // For Rx Reorder Control
107         pHTInfo->bRegRxReorderEnable = 1;
108         pHTInfo->RxReorderWinSize = 64;
109         pHTInfo->RxReorderPendingTime = 30;
110
111 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
112         pHTInfo->UsbTxAggrNum = 4;
113 #endif
114 #ifdef USB_RX_AGGREGATION_SUPPORT
115         pHTInfo->UsbRxFwAggrEn = 1;
116         pHTInfo->UsbRxFwAggrPageNum = 24;
117         pHTInfo->UsbRxFwAggrPacketNum = 8;
118         pHTInfo->UsbRxFwAggrTimeout = 16; ////usb rx FW aggregation timeout threshold.It's in units of 64us
119 #endif
120 }
121
122 /*
123  *function:  This function print out each field on HT capability
124  *           IE mainly from (Beacon/ProbeRsp/AssocReq)
125  *   input:  u8*        CapIE       //Capability IE to be printed out
126  *           u8*        TitleString //mainly print out caller function
127  *  output:  none
128  *  return:  none
129  *  notice:  Driver should not print out this message by default.
130  */
131 void HTDebugHTCapability(u8 *CapIE, u8 *TitleString)
132 {
133         static u8       EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};       // For 11n EWC definition, 2007.07.17, by Emily
134         PHT_CAPABILITY_ELE              pCapELE;
135
136         if (!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap))) {
137                 //EWC IE
138                 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __func__);
139                 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]);
140         } else {
141                 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]);
142         }
143         IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Capability>. Called by %s\n", TitleString);
144
145         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth) ? "20MHz" : "20/40MHz");
146         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz) ? "YES" : "NO");
147         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz) ? "YES" : "NO");
148         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC) ? "YES" : "NO");
149         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize) ? "3839" : "7935");
150         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk) ? "YES" : "NO");
151         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor);
152         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMPDU Density = %d\n", pCapELE->MPDUDensity);
153         IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\
154                                 pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]);
155 }
156
157 /*
158  *function:  This function print out each field on HT Information
159  *           IE mainly from (Beacon/ProbeRsp)
160  *   input:  u8*        InfoIE       //Capability IE to be printed out
161  *           u8*        TitleString //mainly print out caller function
162  *  output:  none
163  *  return:  none
164  *  notice:  Driver should not print out this message by default.
165  */
166 void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString)
167 {
168         static u8       EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};      // For 11n EWC definition, 2007.07.17, by Emily
169         PHT_INFORMATION_ELE             pHTInfoEle;
170
171         if (!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo))) {
172                 // Not EWC IE
173                 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __func__);
174                 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]);
175         } else {
176                 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]);
177         }
178
179         IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Information Element>. Called by %s\n", TitleString);
180
181         IEEE80211_DEBUG(IEEE80211_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl);
182         IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSecondary channel =");
183         switch (pHTInfoEle->ExtChlOffset) {
184         case 0:
185                 IEEE80211_DEBUG(IEEE80211_DL_HT, "Not Present\n");
186                 break;
187         case 1:
188                 IEEE80211_DEBUG(IEEE80211_DL_HT, "Upper channel\n");
189                 break;
190         case 2:
191                 IEEE80211_DEBUG(IEEE80211_DL_HT, "Reserved. Eooro!!!\n");
192                 break;
193         case 3:
194                 IEEE80211_DEBUG(IEEE80211_DL_HT, "Lower Channel\n");
195                 break;
196         }
197         IEEE80211_DEBUG(IEEE80211_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth) ? "20Mhz" : "40Mhz");
198
199         IEEE80211_DEBUG(IEEE80211_DL_HT, "\tOperation mode for protection = ");
200         switch (pHTInfoEle->OptMode) {
201         case 0:
202                 IEEE80211_DEBUG(IEEE80211_DL_HT, "No Protection\n");
203                 break;
204         case 1:
205                 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT non-member protection mode\n");
206                 break;
207         case 2:
208                 IEEE80211_DEBUG(IEEE80211_DL_HT, "Suggest to open protection\n");
209                 break;
210         case 3:
211                 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT mixed mode\n");
212                 break;
213         }
214
215         IEEE80211_DEBUG(IEEE80211_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\
216                                 pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]);
217 }
218
219 /*
220  *      Return:         true if station in half n mode and AP supports 40 bw
221  */
222 static bool IsHTHalfNmode40Bandwidth(struct ieee80211_device *ieee)
223 {
224         bool                    retValue = false;
225         PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
226
227         if (!pHTInfo->bCurrentHTSupport)                // wireless is n mode
228                 retValue = false;
229         else if (!pHTInfo->bRegBW40MHz)         // station supports 40 bw
230                 retValue = false;
231         else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))     // station in half n mode
232                 retValue = false;
233         else if (((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) // ap support 40 bw
234                 retValue = true;
235         else
236                 retValue = false;
237
238         return retValue;
239 }
240
241 static bool IsHTHalfNmodeSGI(struct ieee80211_device *ieee, bool is40MHz)
242 {
243         bool                    retValue = false;
244         PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
245
246         if (!pHTInfo->bCurrentHTSupport)                // wireless is n mode
247                 retValue = false;
248         else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))     // station in half n mode
249                 retValue = false;
250         else if (is40MHz) { // ap support 40 bw
251                 if (((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) // ap support 40 bw short GI
252                         retValue = true;
253                 else
254                         retValue = false;
255         } else {
256                 if (((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) // ap support 40 bw short GI
257                         retValue = true;
258                 else
259                         retValue = false;
260         }
261
262         return retValue;
263 }
264
265 u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee,  u8      nMcsRate)
266 {
267         u8      is40MHz;
268         u8      isShortGI;
269
270         is40MHz = (IsHTHalfNmode40Bandwidth(ieee)) ? 1 : 0;
271         isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz)) ? 1 : 0;
272
273         return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate & 0x7f)];
274 }
275
276 u16 HTMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate)
277 {
278         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
279
280         u8      is40MHz = (pHTInfo->bCurBW40MHz) ? 1 : 0;
281         u8      isShortGI = (pHTInfo->bCurBW40MHz) ?
282                                                 ((pHTInfo->bCurShortGI40MHz) ? 1 : 0) :
283                                                 ((pHTInfo->bCurShortGI20MHz) ? 1 : 0);
284         return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate & 0x7f)];
285 }
286
287 /*
288  *function:  This function returns current datarate.
289  *   input:  struct ieee80211_device*   ieee
290  *           u8                         nDataRate
291  *  output:  none
292  *  return:  tx rate
293  *  notice:  quite unsure about how to use this function //wb
294  */
295 u16  TxCountToDataRate(struct ieee80211_device *ieee, u8 nDataRate)
296 {
297         //PRT_HIGH_THROUGHPUT   pHTInfo = ieee->pHTInfo;
298         u16             CCKOFDMRate[12] = {0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c};
299         u8      is40MHz = 0;
300         u8      isShortGI = 0;
301
302         if (nDataRate < 12) {
303                 return CCKOFDMRate[nDataRate];
304         } else {
305                 if (nDataRate >= 0x10 && nDataRate <= 0x1f) { //if(nDataRate > 11 && nDataRate < 28 )
306                         is40MHz = 0;
307                         isShortGI = 0;
308
309                       // nDataRate = nDataRate - 12;
310                 } else if (nDataRate >= 0x20  && nDataRate <= 0x2f) { //(27, 44)
311                         is40MHz = 1;
312                         isShortGI = 0;
313
314                         //nDataRate = nDataRate - 28;
315                 } else if (nDataRate >= 0x30  && nDataRate <= 0x3f) { //(43, 60)
316                         is40MHz = 0;
317                         isShortGI = 1;
318
319                         //nDataRate = nDataRate - 44;
320                 } else if (nDataRate >= 0x40  && nDataRate <= 0x4f) { //(59, 76)
321                         is40MHz = 1;
322                         isShortGI = 1;
323
324                         //nDataRate = nDataRate - 60;
325                 }
326                 return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate & 0xf];
327         }
328 }
329
330 bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee)
331 {
332         bool                    retValue = false;
333         struct ieee80211_network *net = &ieee->current_network;
334
335         if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) ||
336             (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) ||
337             (memcmp(net->bssid, PCI_RALINK, 3) == 0) ||
338             (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) ||
339             (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) ||
340             (net->ralink_cap_exist))
341                 retValue = true;
342         else if ((memcmp(net->bssid, UNKNOWN_BORADCOM, 3) == 0) ||
343                  (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) == 0) ||
344                  (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) == 0) ||
345                  (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3) == 0) ||
346                  (net->broadcom_cap_exist))
347                 retValue = true;
348         else if (net->bssht.bdRT2RTAggregation)
349                 retValue = true;
350         else
351                 retValue = false;
352
353         return retValue;
354 }
355
356 /*
357  *function:  This function returns peer IOT.
358  *   input:  struct ieee80211_device*   ieee
359  *  output:  none
360  *  return:
361  *  notice:
362  */
363 static void HTIOTPeerDetermine(struct ieee80211_device *ieee)
364 {
365         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
366         struct ieee80211_network *net = &ieee->current_network;
367
368         if (net->bssht.bdRT2RTAggregation)
369                 pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
370         else if (net->broadcom_cap_exist)
371                 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
372         else if ((memcmp(net->bssid, UNKNOWN_BORADCOM, 3) == 0) ||
373                  (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) == 0) ||
374                  (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) == 0) ||
375                  (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3) == 0))
376                 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
377         else if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) ||
378                  (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) ||
379                  (memcmp(net->bssid, PCI_RALINK, 3) == 0) ||
380                  (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) ||
381                  (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) ||
382                  net->ralink_cap_exist)
383                 pHTInfo->IOTPeer = HT_IOT_PEER_RALINK;
384         else if (net->atheros_cap_exist)
385                 pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
386         else if (memcmp(net->bssid, CISCO_BROADCOM, 3) == 0)
387                 pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
388         else
389                 pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
390
391         IEEE80211_DEBUG(IEEE80211_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer);
392 }
393
394 /*
395  *function:  Check whether driver should declare received rate up to MCS13
396  *           only since some chipset is not good at receiving MCS14~15 frame
397  *           from some AP.
398  *   input:  struct ieee80211_device*   ieee
399  *           u8 *                       PeerMacAddr
400  *  output:  none
401  *  return:  return 1 if driver should declare MCS13 only(otherwise return 0)
402  */
403 static u8 HTIOTActIsDisableMCS14(struct ieee80211_device *ieee, u8 *PeerMacAddr)
404 {
405         return 0;
406 }
407
408 /*
409  * Function:    HTIOTActIsDisableMCS15
410  *
411  * Overview:    Check whether driver should declare capability of receiving
412  *              MCS15
413  *
414  * Input:
415  *                      PADAPTER                Adapter,
416  *
417  * Output:              None
418  * Return:      true if driver should disable MCS15
419  * 2008.04.15   Emily
420  */
421 static bool HTIOTActIsDisableMCS15(struct ieee80211_device *ieee)
422 {
423         bool retValue = false;
424
425 #ifdef TODO
426         // Apply for 819u only
427 #if (HAL_CODE_BASE == RTL8192)
428
429 #if (DEV_BUS_TYPE == USB_INTERFACE)
430         // Alway disable MCS15 by Jerry Chang's request.by Emily, 2008.04.15
431         retValue = true;
432 #elif (DEV_BUS_TYPE == PCI_INTERFACE)
433         // Enable MCS15 if the peer is Cisco AP. by Emily, 2008.05.12
434 //      if(pBssDesc->bCiscoCapExist)
435 //              retValue = false;
436 //      else
437                 retValue = false;
438 #endif
439 #endif
440 #endif
441         // Jerry Chang suggest that 8190 1x2 does not need to disable MCS15
442
443         return retValue;
444 }
445
446 /*
447  * Function:    HTIOTActIsDisableMCSTwoSpatialStream
448  *
449  * Overview:    Check whether driver should declare capability of receiving
450  *              All 2 ss packets
451  *
452  * Input:
453  *                      PADAPTER                Adapter,
454  *
455  * Output:              None
456  * Return:      true if driver should disable all two spatial stream packet
457  * 2008.04.21   Emily
458  */
459 static bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device *ieee,
460                                                  u8 *PeerMacAddr)
461 {
462 #ifdef TODO
463         // Apply for 819u only
464 #endif
465         return false;
466 }
467
468 /*
469  *function:  Check whether driver should disable EDCA turbo mode
470  *   input:  struct ieee80211_device*   ieee
471  *           u8*                        PeerMacAddr
472  *  output:  none
473  *  return:  return 1 if driver should disable EDCA turbo mode
474  *           (otherwise return 0)
475  */
476 static u8 HTIOTActIsDisableEDCATurbo(struct ieee80211_device *ieee,
477                                      u8 *PeerMacAddr)
478 {       /* default enable EDCA Turbo mode. */
479         return false;
480 }
481
482 /*
483  *function:  Check whether we need to use OFDM to sned MGNT frame for
484  *           broadcom AP
485  *   input:  struct ieee80211_network *network   //current network we live
486  *  output:  none
487  *  return:  return 1 if true
488  */
489 static u8 HTIOTActIsMgntUseCCK6M(struct ieee80211_network *network)
490 {
491         u8      retValue = 0;
492
493         // 2008/01/25 MH Judeg if we need to use OFDM to sned MGNT frame for broadcom AP.
494         // 2008/01/28 MH We must prevent that we select null bssid to link.
495
496         if (network->broadcom_cap_exist)
497                 retValue = 1;
498
499         return retValue;
500 }
501
502 static u8 HTIOTActIsCCDFsync(u8 *PeerMacAddr)
503 {
504         u8      retValue = 0;
505
506         if ((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3) == 0) ||
507             (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) == 0) ||
508             (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) == 0))
509                 retValue = 1;
510
511         return retValue;
512 }
513
514 void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo)
515 {
516         pHTInfo->IOTAction = 0;
517         pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
518 }
519
520 /*
521  *function:  Construct Capablility Element in Beacon... if HTEnable is turned on
522  *   input:  struct ieee80211_device*   ieee
523  *           u8*                     posHTCap //pointer to store Capability Ele
524  *           u8*                     len //store length of CE
525  *           u8                      IsEncrypt //whether encrypt, needed further
526  *  output:  none
527  *  return:  none
528  *  notice:  posHTCap can't be null and should be initialized before.
529  */
530 void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 IsEncrypt)
531 {
532         PRT_HIGH_THROUGHPUT     pHT = ieee->pHTInfo;
533         PHT_CAPABILITY_ELE      pCapELE = NULL;
534         //u8 bIsDeclareMCS13;
535
536         if (!posHTCap || !pHT) {
537                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
538                                 "posHTCap or pHTInfo can't be null in %s\n",
539                                 __func__);
540                 return;
541         }
542         memset(posHTCap, 0, *len);
543         if (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC) {
544                 u8      EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};       // For 11n EWC definition, 2007.07.17, by Emily
545
546                 memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap));
547                 pCapELE = (PHT_CAPABILITY_ELE)&posHTCap[4];
548         } else {
549                 pCapELE = (PHT_CAPABILITY_ELE)posHTCap;
550         }
551
552         //HT capability info
553         pCapELE->AdvCoding              = 0; // This feature is not supported now!!
554         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
555                 pCapELE->ChlWidth = 0;
556         else
557                 pCapELE->ChlWidth = (pHT->bRegBW40MHz ? 1 : 0);
558
559 //      pCapELE->ChlWidth               = (pHT->bRegBW40MHz?1:0);
560         pCapELE->MimoPwrSave            = pHT->SelfMimoPs;
561         pCapELE->GreenField             = 0; // This feature is not supported now!!
562         pCapELE->ShortGI20Mhz           = 1; // We can receive Short GI!!
563         pCapELE->ShortGI40Mhz           = 1; // We can receive Short GI!!
564         //DbgPrint("TX HT cap/info ele BW=%d SG20=%d SG40=%d\n\r",
565         //pCapELE->ChlWidth, pCapELE->ShortGI20Mhz, pCapELE->ShortGI40Mhz);
566         pCapELE->TxSTBC                 = 1;
567         pCapELE->RxSTBC                 = 0;
568         pCapELE->DelayBA                = 0;    // Do not support now!!
569         pCapELE->MaxAMSDUSize           = (MAX_RECEIVE_BUFFER_SIZE >= 7935) ? 1 : 0;
570         pCapELE->DssCCk                 = ((pHT->bRegBW40MHz) ? (pHT->bRegSuppCCK ? 1 : 0) : 0);
571         pCapELE->PSMP                   = 0; // Do not support now!!
572         pCapELE->LSigTxopProtect        = 0; // Do not support now!!
573
574         /*
575          * MAC HT parameters info
576          * TODO: Nedd to take care of this part
577          */
578         IEEE80211_DEBUG(IEEE80211_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
579
580         if (IsEncrypt) {
581                 pCapELE->MPDUDensity    = 7; // 8us
582                 pCapELE->MaxRxAMPDUFactor = 2; // 2 is for 32 K and 3 is 64K
583         } else {
584                 pCapELE->MaxRxAMPDUFactor = 3; // 2 is for 32 K and 3 is 64K
585                 pCapELE->MPDUDensity    = 0; // no density
586         }
587
588         //Supported MCS set
589         memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16);
590         if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15)
591                 pCapELE->MCS[1] &= 0x7f;
592
593         if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14)
594                 pCapELE->MCS[1] &= 0xbf;
595
596         if (pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS)
597                 pCapELE->MCS[1] &= 0x00;
598
599         /*
600          * 2008.06.12
601          * For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7.
602          */
603         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) {
604                 int i;
605
606                 for (i = 1; i < 16; i++)
607                         pCapELE->MCS[i] = 0;
608         }
609
610         //Extended HT Capability Info
611         memset(&pCapELE->ExtHTCapInfo, 0, 2);
612
613         //TXBF Capabilities
614         memset(pCapELE->TxBFCap, 0, 4);
615
616         //Antenna Selection Capabilities
617         pCapELE->ASCap = 0;
618 //add 2 to give space for element ID and len when construct frames
619         if (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
620                 *len = 30 + 2;
621         else
622                 *len = 26 + 2;
623
624 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTCap, *len -2);
625
626         /*
627          * Print each field in detail. Driver should not print out this message
628          * by default
629          */
630 //      HTDebugHTCapability(posHTCap, (u8*)"HTConstructCapability()");
631 }
632
633 /*
634  *function:  Construct Information Element in Beacon... if HTEnable is turned on
635  *   input:  struct ieee80211_device*   ieee
636  *           u8*                     posHTCap //pointer to store Information Ele
637  *           u8*                     len   //store len of
638  *           u8                      IsEncrypt //whether encrypt, needed further
639  *  output:  none
640  *  return:  none
641  *  notice:  posHTCap can't be null and be initialized before.
642  *           Only AP and IBSS sta should do this
643  */
644 void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 IsEncrypt)
645 {
646         PRT_HIGH_THROUGHPUT     pHT = ieee->pHTInfo;
647         PHT_INFORMATION_ELE             pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo;
648
649         if (!posHTInfo || !pHTInfoEle) {
650                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
651                                 "posHTInfo or pHTInfoEle can't be null in %s\n",
652                                 __func__);
653                 return;
654         }
655
656         memset(posHTInfo, 0, *len);
657         if ((ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) { //ap mode is not currently supported
658                 pHTInfoEle->ControlChl                  = ieee->current_network.channel;
659                 pHTInfoEle->ExtChlOffset                = ((!pHT->bRegBW40MHz) ? HT_EXTCHNL_OFFSET_NO_EXT :
660                                                                                         (ieee->current_network.channel <= 6) ?
661                                                                                                 HT_EXTCHNL_OFFSET_UPPER : HT_EXTCHNL_OFFSET_LOWER);
662                 pHTInfoEle->RecommemdedTxWidth  = pHT->bRegBW40MHz;
663                 pHTInfoEle->RIFS                                        = 0;
664                 pHTInfoEle->PSMPAccessOnly              = 0;
665                 pHTInfoEle->SrvIntGranularity           = 0;
666                 pHTInfoEle->OptMode                             = pHT->CurrentOpMode;
667                 pHTInfoEle->NonGFDevPresent             = 0;
668                 pHTInfoEle->DualBeacon                  = 0;
669                 pHTInfoEle->SecondaryBeacon             = 0;
670                 pHTInfoEle->LSigTxopProtectFull         = 0;
671                 pHTInfoEle->PcoActive                           = 0;
672                 pHTInfoEle->PcoPhase                            = 0;
673
674                 memset(pHTInfoEle->BasicMSC, 0, 16);
675
676                 *len = 22 + 2; //same above
677         } else {
678                 //STA should not generate High Throughput Information Element
679                 *len = 0;
680         }
681         //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTInfo, *len - 2);
682         //HTDebugHTInfo(posHTInfo, "HTConstructInforElement");
683 }
684
685 /*
686  * According to experiment, Realtek AP to STA (based on rtl8190) may achieve
687  * best performance if both STA and AP set limitation of aggregation size to
688  * 32K, that is, set AMPDU density to 2 (Ref: IEEE 11n specification).
689  * However, if Realtek STA associates to other AP, STA should set limitation of
690  * aggregation size to 8K, otherwise, performance of traffic stream from STA to
691  * AP will be much less than the traffic stream from AP to STA if both of the
692  * stream runs concurrently at the same time.
693  *
694  *  Frame Format
695  *  Element ID          Length          OUI             Type1           Reserved
696  *  1 byte              1 byte          3 bytes         1 byte          1 byte
697  *
698  *  OUI         = 0x00, 0xe0, 0x4c,
699  *  Type        = 0x02
700  *  Reserved    = 0x00
701  *
702  *  2007.8.21 by Emily
703  */
704 /*
705  *function:  Construct  Information Element in Beacon... in RT2RT condition
706  *   input:  struct ieee80211_device*   ieee
707  *           u8*                  posRT2RTAgg //pointer to store Information Ele
708  *           u8*                  len   //store len
709  *  output:  none
710  *  return:  none
711  *  notice:
712  */
713 void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len)
714 {
715         if (!posRT2RTAgg) {
716                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
717                                 "posRT2RTAgg can't be null in %s\n",
718                                 __func__);
719                 return;
720         }
721         memset(posRT2RTAgg, 0, *len);
722         *posRT2RTAgg++ = 0x00;
723         *posRT2RTAgg++ = 0xe0;
724         *posRT2RTAgg++ = 0x4c;
725         *posRT2RTAgg++ = 0x02;
726         *posRT2RTAgg++ = 0x01;
727         *posRT2RTAgg = 0x10;//*posRT2RTAgg = 0x02;
728
729         if (ieee->bSupportRemoteWakeUp)
730                 *posRT2RTAgg |= 0x08;//RT_HT_CAP_USE_WOW;
731
732         *len = 6 + 2;
733         return;
734 #ifdef TODO
735 #if (HAL_CODE_BASE == RTL8192 && DEV_BUS_TYPE == USB_INTERFACE)
736         /*
737         //Emily. If it is required to Ask Realtek AP to send AMPDU during AES mode, enable this
738            section of code.
739         if(IS_UNDER_11N_AES_MODE(Adapter))
740         {
741                 posRT2RTAgg->octet[5] |= RT_HT_CAP_USE_AMPDU;
742         }else
743         {
744                 posRT2RTAgg->octet[5] &= 0xfb;
745         }
746         */
747 #else
748         // Do Nothing
749 #endif
750
751         posRT2RTAgg->Length = 6;
752 #endif
753 }
754
755 /*
756  *function:  Pick the right Rate Adaptive table to use
757  *   input:  struct ieee80211_device*   ieee
758  *           u8*                      pOperateMCS //A pointer to MCS rate bitmap
759  *  return:  always we return true
760  *  notice:
761  */
762 static u8 HT_PickMCSRate(struct ieee80211_device *ieee, u8 *pOperateMCS)
763 {
764         if (!pOperateMCS) {
765                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
766                                 "pOperateMCS can't be null in %s\n",
767                                 __func__);
768                 return false;
769         }
770
771         switch (ieee->mode) {
772         case IEEE_A:
773         case IEEE_B:
774         case IEEE_G:
775                 //legacy rate routine handled at selectedrate
776
777                 //no MCS rate
778                 memset(pOperateMCS, 0, 16);
779                 break;
780
781         case IEEE_N_24G:        //assume CCK rate ok
782         case IEEE_N_5G:
783                 // Legacy part we only use 6, 5.5,2,1 for N_24G and 6 for N_5G.
784                 // Legacy part shall be handled at SelectRateSet().
785
786                 //HT part
787                 // TODO: may be different if we have different number of antenna
788                 pOperateMCS[0] &= RATE_ADPT_1SS_MASK;   //support MCS 0~7
789                 pOperateMCS[1] &= RATE_ADPT_2SS_MASK;
790                 pOperateMCS[3] &= RATE_ADPT_MCS32_MASK;
791                 break;
792
793         //should never reach here
794         default:
795                 break;
796         }
797
798         return true;
799 }
800
801 /*
802  *      Description:
803  *              This function will get the highest speed rate in input MCS set.
804  *
805  *      /param  Adapter                 Pionter to Adapter entity
806  *                      pMCSRateSet             Pointer to MCS rate bitmap
807  *                      pMCSFilter              Pointer to MCS rate filter
808  *
809  *      /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter.
810  *
811  */
812 /*
813  *function:  This function will get the highest speed rate in input MCS set.
814  *   input:  struct ieee80211_device*   ieee
815  *           u8*                        pMCSRateSet //Pointer to MCS rate bitmap
816  *           u8*                        pMCSFilter //Pointer to MCS rate filter
817  *  return:  Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter
818  *  notice:
819  */
820 u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter)
821 {
822         u8              i, j;
823         u8              bitMap;
824         u8              mcsRate = 0;
825         u8              availableMcsRate[16];
826
827         if (!pMCSRateSet || !pMCSFilter) {
828                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
829                                 "pMCSRateSet or pMCSFilter can't be null in %s\n",
830                                 __func__);
831                 return false;
832         }
833         for (i = 0; i < 16; i++)
834                 availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];
835
836         for (i = 0; i < 16; i++) {
837                 if (availableMcsRate[i] != 0)
838                         break;
839         }
840         if (i == 16)
841                 return false;
842
843         for (i = 0; i < 16; i++) {
844                 if (availableMcsRate[i] != 0) {
845                         bitMap = availableMcsRate[i];
846                         for (j = 0; j < 8; j++) {
847                                 if ((bitMap % 2) != 0) {
848                                         if (HTMcsToDataRate(ieee, (8 * i + j)) > HTMcsToDataRate(ieee, mcsRate))
849                                                 mcsRate = (8 * i + j);
850                                 }
851                                 bitMap >>= 1;
852                         }
853                 }
854         }
855         return (mcsRate | 0x80);
856 }
857
858 /*
859  * 1.Filter our operation rate set with AP's rate set
860  * 2.shall reference channel bandwidth, STBC, Antenna number
861  * 3.generate rate adative table for firmware
862  * David 20060906
863  *
864  * \pHTSupportedCap: the connected STA's supported rate Capability element
865  */
866 static u8 HTFilterMCSRate(struct ieee80211_device *ieee, u8 *pSupportMCS,
867                           u8 *pOperateMCS)
868 {
869         u8 i = 0;
870
871         // filter out operational rate set not supported by AP, the length of it is 16
872         for (i = 0; i <= 15; i++)
873                 pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i] & pSupportMCS[i];
874
875         // TODO: adjust our operational rate set  according to our channel bandwidth, STBC and Antenna number
876         /*
877          * TODO: fill suggested rate adaptive rate index and give firmware info
878          * using Tx command packet we also shall suggested the first start rate
879          * set according to our signal strength
880          */
881         HT_PickMCSRate(ieee, pOperateMCS);
882
883         // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
884         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
885                 pOperateMCS[1] = 0;
886
887         /*
888          * For RTL819X, we support only MCS0~15.
889          * And also, we do not know how to use MCS32 now.
890          */
891         for (i = 2; i <= 15; i++)
892                 pOperateMCS[i] = 0;
893
894         return true;
895 }
896
897 void HTSetConnectBwMode(struct ieee80211_device *ieee, enum ht_channel_width Bandwidth, enum ht_extension_chan_offset   Offset);
898 void HTOnAssocRsp(struct ieee80211_device *ieee)
899 {
900         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
901         PHT_CAPABILITY_ELE              pPeerHTCap = NULL;
902         PHT_INFORMATION_ELE             pPeerHTInfo = NULL;
903         u16     nMaxAMSDUSize = 0;
904         u8      *pMcsFilter = NULL;
905
906         static u8                               EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};               // For 11n EWC definition, 2007.07.17, by Emily
907         static u8                               EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};      // For 11n EWC definition, 2007.07.17, by Emily
908
909         if (!pHTInfo->bCurrentHTSupport) {
910                 IEEE80211_DEBUG(IEEE80211_DL_ERR,
911                                 "<=== %s: HT_DISABLE\n",
912                                 __func__);
913                 return;
914         }
915         IEEE80211_DEBUG(IEEE80211_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
916 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTCapBuf, sizeof(HT_CAPABILITY_ELE));
917 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTInfoBuf, sizeof(HT_INFORMATION_ELE));
918
919 //      HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq");
920 //      HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq");
921         //
922         if (!memcmp(pHTInfo->PeerHTCapBuf, EWC11NHTCap, sizeof(EWC11NHTCap)))
923                 pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
924         else
925                 pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
926
927         if (!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
928                 pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]);
929         else
930                 pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf);
931
932         ////////////////////////////////////////////////////////
933         // Configurations:
934         ////////////////////////////////////////////////////////
935         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE));
936 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTInfo, sizeof(HT_INFORMATION_ELE));
937         // Config Supported Channel Width setting
938         //
939         HTSetConnectBwMode(ieee, (enum ht_channel_width)(pPeerHTCap->ChlWidth), (enum ht_extension_chan_offset)(pPeerHTInfo->ExtChlOffset));
940
941         pHTInfo->bCurTxBW40MHz = (pPeerHTInfo->RecommemdedTxWidth == 1);
942
943         /*
944          * Update short GI/ long GI setting
945          *
946          * TODO:
947          */
948         pHTInfo->bCurShortGI20MHz = pHTInfo->bRegShortGI20MHz &&
949                                     (pPeerHTCap->ShortGI20Mhz == 1);
950         pHTInfo->bCurShortGI40MHz = pHTInfo->bRegShortGI40MHz &&
951                                    (pPeerHTCap->ShortGI40Mhz == 1);
952
953         /*
954          * Config TX STBC setting
955          *
956          * TODO:
957          */
958
959         /*
960          * Config DSSS/CCK  mode in 40MHz mode
961          *
962          * TODO:
963          */
964         pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK &&
965                                (pPeerHTCap->DssCCk == 1);
966
967         /*
968          * Config and configure A-MSDU setting
969          */
970         pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
971
972         nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize == 0) ? 3839 : 7935;
973
974         if (pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize)
975                 pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize;
976         else
977                 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
978         /*
979          * Config A-MPDU setting
980          */
981         pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
982
983         /*
984          * <1> Decide AMPDU Factor
985          * By Emily
986          */
987         if (!pHTInfo->bRegRT2RTAggregation) {
988                 // Decide AMPDU Factor according to protocol handshake
989                 if (pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor)
990                         pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
991                 else
992                         pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
993         } else {
994                 /*
995                  * Set MPDU density to 2 to Realtek AP, and set it to 0 for others
996                  * Replace MPDU factor declared in original association response frame format. 2007.08.20 by Emily
997                  */
998                 if (ieee->current_network.bssht.bdRT2RTAggregation) {
999                         if (ieee->pairwise_key_type != KEY_TYPE_NA)
1000                                 // Realtek may set 32k in security mode and 64k for others
1001                                 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1002                         else
1003                                 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K;
1004                 } else {
1005                         if (pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K)
1006                                 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1007                         else
1008                                 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K;
1009                 }
1010         }
1011
1012         /*
1013          * <2> Set AMPDU Minimum MPDU Start Spacing
1014          * 802.11n 3.0 section 9.7d.3
1015          */
1016         if (pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
1017                 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1018         else
1019                 pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
1020         if (ieee->pairwise_key_type != KEY_TYPE_NA)
1021                 pHTInfo->CurrentMPDUDensity     = 7; // 8us
1022         // Force TX AMSDU
1023
1024         // Lanhsin: mark for tmp to avoid deauth by ap from  s3
1025         //if(memcmp(pMgntInfo->Bssid, NETGEAR834Bv2_BROADCOM, 3)==0)
1026         if (0) {
1027                 pHTInfo->bCurrentAMPDUEnable = false;
1028                 pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE;
1029                 pHTInfo->ForcedAMSDUMaxSize = 7935;
1030
1031                 pHTInfo->IOTAction |=  HT_IOT_ACT_TX_USE_AMSDU_8K;
1032         }
1033
1034         // Rx Reorder Setting
1035         pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable;
1036
1037         /*
1038          * Filter out unsupported HT rate for this AP
1039          * Update RATR table
1040          * This is only for 8190 ,8192 or later product which using firmware to
1041          * handle rate adaptive mechanism.
1042          */
1043
1044         /*
1045          * Handle Ralink AP bad MCS rate set condition. Joseph.
1046          * This fix the bug of Ralink AP. This may be removed in the future.
1047          */
1048         if (pPeerHTCap->MCS[0] == 0)
1049                 pPeerHTCap->MCS[0] = 0xff;
1050
1051         HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet);
1052
1053         /*
1054          * Config MIMO Power Save setting
1055          */
1056         pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave;
1057         if (pHTInfo->PeerMimoPs == MIMO_PS_STATIC)
1058                 pMcsFilter = MCS_FILTER_1SS;
1059         else
1060                 pMcsFilter = MCS_FILTER_ALL;
1061         //WB add for MCS8 bug
1062 //      pMcsFilter = MCS_FILTER_1SS;
1063         ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter);
1064         ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
1065
1066         /*
1067          * Config current operation mode.
1068          */
1069         pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1070 }
1071
1072 void HTSetConnectBwModeCallback(struct ieee80211_device *ieee);
1073 /*
1074  *function:  initialize HT info(struct PRT_HIGH_THROUGHPUT)
1075  *   input:  struct ieee80211_device*   ieee
1076  *  output:  none
1077  *  return:  none
1078  *  notice: This function is called when
1079  *                                  *  (1) MPInitialization Phase
1080  *                                  *  (2) Receiving of Deauthentication from AP
1081  */
1082 // TODO: Should this funciton be called when receiving of Disassociation?
1083 void HTInitializeHTInfo(struct ieee80211_device *ieee)
1084 {
1085         PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1086
1087         /*
1088          * These parameters will be reset when receiving deauthentication packet
1089          */
1090         IEEE80211_DEBUG(IEEE80211_DL_HT, "===========>%s()\n", __func__);
1091         pHTInfo->bCurrentHTSupport = false;
1092
1093         // 40MHz channel support
1094         pHTInfo->bCurBW40MHz = false;
1095         pHTInfo->bCurTxBW40MHz = false;
1096
1097         // Short GI support
1098         pHTInfo->bCurShortGI20MHz = false;
1099         pHTInfo->bCurShortGI40MHz = false;
1100         pHTInfo->bForcedShortGI = false;
1101
1102         /*
1103          * CCK rate support
1104          * This flag is set to true to support CCK rate by default.
1105          * It will be affected by "pHTInfo->bRegSuppCCK" and AP capabilities
1106          * only when associate to 11N BSS.
1107          */
1108         pHTInfo->bCurSuppCCK = true;
1109
1110         // AMSDU related
1111         pHTInfo->bCurrent_AMSDU_Support = false;
1112         pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1113
1114         // AMPUD related
1115         pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1116         pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1117
1118         // Initialize all of the parameters related to 11n
1119         memset(&pHTInfo->SelfHTCap, 0, sizeof(pHTInfo->SelfHTCap));
1120         memset(&pHTInfo->SelfHTInfo, 0, sizeof(pHTInfo->SelfHTInfo));
1121         memset(&pHTInfo->PeerHTCapBuf, 0, sizeof(pHTInfo->PeerHTCapBuf));
1122         memset(&pHTInfo->PeerHTInfoBuf, 0, sizeof(pHTInfo->PeerHTInfoBuf));
1123
1124         pHTInfo->bSwBwInProgress = false;
1125         pHTInfo->ChnlOp = CHNLOP_NONE;
1126
1127         // Set default IEEE spec for Draft N
1128         pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE;
1129
1130         // Realtek proprietary aggregation mode
1131         pHTInfo->bCurrentRT2RTAggregation = false;
1132         pHTInfo->bCurrentRT2RTLongSlotTime = false;
1133         pHTInfo->IOTPeer = 0;
1134         pHTInfo->IOTAction = 0;
1135
1136         //MCS rate initialized here
1137         {
1138                 u8 *RegHTSuppRateSets = &ieee->RegHTSuppRateSet[0];
1139
1140                 RegHTSuppRateSets[0] = 0xFF;    //support MCS 0~7
1141                 RegHTSuppRateSets[1] = 0xFF;    //support MCS 8~15
1142                 RegHTSuppRateSets[4] = 0x01;    //support MCS 32
1143         }
1144 }
1145
1146 /*
1147  *function:  initialize Bss HT structure(struct PBSS_HT)
1148  *   input:  PBSS_HT pBssHT //to be initialized
1149  *  output:  none
1150  *  return:  none
1151  *  notice: This function is called when initialize network structure
1152  */
1153 void HTInitializeBssDesc(PBSS_HT pBssHT)
1154 {
1155         pBssHT->bdSupportHT = false;
1156         memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf));
1157         pBssHT->bdHTCapLen = 0;
1158         memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf));
1159         pBssHT->bdHTInfoLen = 0;
1160
1161         pBssHT->bdHTSpecVer = HT_SPEC_VER_IEEE;
1162
1163         pBssHT->bdRT2RTAggregation = false;
1164         pBssHT->bdRT2RTLongSlotTime = false;
1165 }
1166
1167 /*
1168  *function:  initialize Bss HT structure(struct PBSS_HT)
1169  *   input:  struct ieee80211_device    *ieee
1170  *           struct ieee80211_network   *pNetwork //usually current network
1171  *                                                  we are live in
1172  *  output:  none
1173  *  return:  none
1174  *  notice: This function should ONLY be called before association
1175  */
1176 void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee,       struct ieee80211_network *pNetwork)
1177 {
1178         PRT_HIGH_THROUGHPUT             pHTInfo = ieee->pHTInfo;
1179 //      u16                                             nMaxAMSDUSize;
1180 //      PHT_CAPABILITY_ELE              pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1181 //      PHT_INFORMATION_ELE             pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1182 //      u8*     pMcsFilter;
1183         u8      bIOTAction = 0;
1184
1185         //
1186         //  Save Peer Setting before Association
1187         //
1188         IEEE80211_DEBUG(IEEE80211_DL_HT, "==============>%s()\n", __func__);
1189         /*unmark bEnableHT flag here is the same reason why unmarked in function ieee80211_softmac_new_net. WB 2008.09.10*/
1190 //      if( pHTInfo->bEnableHT &&  pNetwork->bssht.bdSupportHT)
1191         if (pNetwork->bssht.bdSupportHT) {
1192                 pHTInfo->bCurrentHTSupport = true;
1193                 pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
1194
1195                 // Save HTCap and HTInfo information Element
1196                 if (pNetwork->bssht.bdHTCapLen > 0 &&   pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf))
1197                         memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen);
1198
1199                 if (pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf))
1200                         memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen);
1201
1202                 // Check whether RT to RT aggregation mode is enabled
1203                 if (pHTInfo->bRegRT2RTAggregation) {
1204                         pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation;
1205                         pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime;
1206                 } else {
1207                         pHTInfo->bCurrentRT2RTAggregation = false;
1208                         pHTInfo->bCurrentRT2RTLongSlotTime = false;
1209                 }
1210
1211                 // Determine the IOT Peer Vendor.
1212                 HTIOTPeerDetermine(ieee);
1213
1214                 /*
1215                  * Decide IOT Action
1216                  * Must be called after the parameter of pHTInfo->bCurrentRT2RTAggregation is decided
1217                  */
1218                 pHTInfo->IOTAction = 0;
1219                 bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
1220                 if (bIOTAction)
1221                         pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
1222
1223                 bIOTAction = HTIOTActIsDisableMCS15(ieee);
1224                 if (bIOTAction)
1225                         pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15;
1226
1227                 bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee, pNetwork->bssid);
1228                 if (bIOTAction)
1229                         pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS;
1230
1231                 bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid);
1232                 if (bIOTAction)
1233                         pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO;
1234
1235                 bIOTAction = HTIOTActIsMgntUseCCK6M(pNetwork);
1236                 if (bIOTAction)
1237                         pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M;
1238
1239                 bIOTAction = HTIOTActIsCCDFsync(pNetwork->bssid);
1240                 if (bIOTAction)
1241                         pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
1242         } else {
1243                 pHTInfo->bCurrentHTSupport = false;
1244                 pHTInfo->bCurrentRT2RTAggregation = false;
1245                 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1246
1247                 pHTInfo->IOTAction = 0;
1248         }
1249 }
1250
1251 void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee,  struct ieee80211_network *pNetwork)
1252 {
1253         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
1254 //      PHT_CAPABILITY_ELE              pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1255         PHT_INFORMATION_ELE             pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1256
1257         if (pHTInfo->bCurrentHTSupport) {
1258                 /*
1259                  * Config current operation mode.
1260                  */
1261                 if (pNetwork->bssht.bdHTInfoLen != 0)
1262                         pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1263
1264                 /*
1265                  * <TODO: Config according to OBSS non-HT STA present!!>
1266                  */
1267         }
1268 }
1269 EXPORT_SYMBOL(HTUpdateSelfAndPeerSetting);
1270
1271 /*
1272  *function:  check whether HT control field exists
1273  *   input:  struct ieee80211_device    *ieee
1274  *           u8*                        pFrame //coming skb->data
1275  *  output:  none
1276  *  return:  return true if HT control field exists(false otherwise)
1277  *  notice:
1278  */
1279 u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame)
1280 {
1281         if (ieee->pHTInfo->bCurrentHTSupport) {
1282                 if ((IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) {
1283                         IEEE80211_DEBUG(IEEE80211_DL_HT, "HT CONTROL FILED EXIST!!\n");
1284                         return true;
1285                 }
1286         }
1287         return false;
1288 }
1289
1290 /*
1291  * This function set bandwidth mode in protocol layer.
1292  */
1293 void HTSetConnectBwMode(struct ieee80211_device *ieee, enum ht_channel_width Bandwidth, enum ht_extension_chan_offset Offset)
1294 {
1295         PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1296 //      u32 flags = 0;
1297
1298         if (!pHTInfo->bRegBW40MHz)
1299                 return;
1300
1301         // To reduce dummy operation
1302 //      if((pHTInfo->bCurBW40MHz==false && Bandwidth==HT_CHANNEL_WIDTH_20) ||
1303 //         (pHTInfo->bCurBW40MHz==true && Bandwidth==HT_CHANNEL_WIDTH_20_40 && Offset==pHTInfo->CurSTAExtChnlOffset))
1304 //              return;
1305
1306 //      spin_lock_irqsave(&(ieee->bw_spinlock), flags);
1307         if (pHTInfo->bSwBwInProgress) {
1308 //              spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1309                 return;
1310         }
1311         //if in half N mode, set to 20M bandwidth please 09.08.2008 WB.
1312         if (Bandwidth == HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))) {
1313                         // Handle Illegal extension channel offset!!
1314                 if (ieee->current_network.channel < 2 && Offset == HT_EXTCHNL_OFFSET_LOWER)
1315                         Offset = HT_EXTCHNL_OFFSET_NO_EXT;
1316                 if (Offset == HT_EXTCHNL_OFFSET_UPPER || Offset == HT_EXTCHNL_OFFSET_LOWER) {
1317                         pHTInfo->bCurBW40MHz = true;
1318                         pHTInfo->CurSTAExtChnlOffset = Offset;
1319                 } else {
1320                         pHTInfo->bCurBW40MHz = false;
1321                         pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1322                 }
1323         } else {
1324                 pHTInfo->bCurBW40MHz = false;
1325                 pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1326         }
1327
1328         pHTInfo->bSwBwInProgress = true;
1329
1330         /*
1331          * TODO: 2007.7.13 by Emily Wait 2000ms  in order to guarantee that
1332          * switching bandwidth is executed after scan is finished. It is a
1333          * temporal solution because software should ganrantee the last
1334          * operation of switching bandwidth is executed properlly.
1335          */
1336         HTSetConnectBwModeCallback(ieee);
1337
1338 //      spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1339 }
1340
1341 void HTSetConnectBwModeCallback(struct ieee80211_device *ieee)
1342 {
1343         PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1344
1345         IEEE80211_DEBUG(IEEE80211_DL_HT, "======>%s()\n", __func__);
1346
1347         if (pHTInfo->bCurBW40MHz) {
1348                 if (pHTInfo->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_UPPER)
1349                         ieee->set_chan(ieee->dev, ieee->current_network.channel + 2);
1350                 else if (pHTInfo->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_LOWER)
1351                         ieee->set_chan(ieee->dev, ieee->current_network.channel - 2);
1352                 else
1353                         ieee->set_chan(ieee->dev, ieee->current_network.channel);
1354
1355                 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
1356         } else {
1357                 ieee->set_chan(ieee->dev, ieee->current_network.channel);
1358                 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1359         }
1360
1361         pHTInfo->bSwBwInProgress = false;
1362 }