8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / core / rtw_ap.c
1 /******************************************************************************\r
2  *\r
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.\r
4  *                                        \r
5  * This program is free software; you can redistribute it and/or modify it\r
6  * under the terms of version 2 of the GNU General Public License as\r
7  * published by the Free Software Foundation.\r
8  *\r
9  * This program is distributed in the hope that it will be useful, but WITHOUT\r
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
12  * more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along with\r
15  * this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA\r
17  *\r
18  *\r
19  ******************************************************************************/\r
20 #define _RTW_AP_C_\r
21 \r
22 #include <drv_types.h>\r
23 \r
24 \r
25 #ifdef CONFIG_AP_MODE\r
26 \r
27 extern unsigned char    RTW_WPA_OUI[];\r
28 extern unsigned char    WMM_OUI[];\r
29 extern unsigned char    WPS_OUI[];\r
30 extern unsigned char    P2P_OUI[];\r
31 extern unsigned char    WFD_OUI[];\r
32 \r
33 void init_mlme_ap_info(_adapter *padapter)\r
34 {\r
35         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
36         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
37         struct sta_priv *pstapriv = &padapter->stapriv; \r
38         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
39         \r
40 \r
41         _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);        \r
42 \r
43         //for ACL \r
44         _rtw_init_queue(&pacl_list->acl_node_q);\r
45 \r
46         //pmlmeext->bstart_bss = _FALSE;\r
47 \r
48         start_ap_mode(padapter);\r
49 }\r
50 \r
51 void free_mlme_ap_info(_adapter *padapter)\r
52 {\r
53         _irqL irqL;\r
54         struct sta_info *psta=NULL;\r
55         struct sta_priv *pstapriv = &padapter->stapriv;\r
56         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
57         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
58         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
59 \r
60         //stop_ap_mode(padapter);\r
61 \r
62         pmlmepriv->update_bcn = _FALSE;\r
63         pmlmeext->bstart_bss = _FALSE;  \r
64         \r
65         rtw_sta_flush(padapter);\r
66 \r
67         pmlmeinfo->state = _HW_STATE_NOLINK_;\r
68 \r
69         //free_assoc_sta_resources\r
70         rtw_free_all_stainfo(padapter);\r
71 \r
72         //free bc/mc sta_info\r
73         psta = rtw_get_bcmc_stainfo(padapter);  \r
74         //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                \r
75         rtw_free_stainfo(padapter, psta);\r
76         //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
77         \r
78 \r
79         _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);\r
80         \r
81 }\r
82 \r
83 static void update_BCNTIM(_adapter *padapter)\r
84 {\r
85         struct sta_priv *pstapriv = &padapter->stapriv;\r
86         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
87         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
88         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);\r
89         unsigned char *pie = pnetwork_mlmeext->IEs;\r
90 \r
91         //DBG_871X("%s\n", __FUNCTION__);\r
92         \r
93         //update TIM IE\r
94         //if(pstapriv->tim_bitmap)\r
95         if(_TRUE)\r
96         {\r
97                 u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
98                 u16 tim_bitmap_le;\r
99                 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;        \r
100         \r
101                 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);\r
102 \r
103                 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);\r
104                 if (p != NULL && tim_ielen>0)\r
105                 {\r
106                         tim_ielen += 2;\r
107                         \r
108                         premainder_ie = p+tim_ielen;\r
109 \r
110                         tim_ie_offset = (sint)(p -pie);\r
111                         \r
112                         remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;\r
113 \r
114                         //append TIM IE from dst_ie offset\r
115                         dst_ie = p;\r
116                 }\r
117                 else\r
118                 {\r
119                         tim_ielen = 0;\r
120 \r
121                         //calucate head_len             \r
122                         offset = _FIXED_IE_LENGTH_;\r
123 \r
124                         /* get ssid_ie len */\r
125                         p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));\r
126                         if (p != NULL)\r
127                                 offset += tmp_len+2;\r
128 \r
129                         // get supported rates len\r
130                         p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));     \r
131                         if (p !=  NULL) \r
132                         {                       \r
133                                 offset += tmp_len+2;\r
134                         }\r
135 \r
136                         //DS Parameter Set IE, len=3    \r
137                         offset += 3;\r
138 \r
139                         premainder_ie = pie + offset;\r
140 \r
141                         remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;      \r
142 \r
143                         //append TIM IE from offset\r
144                         dst_ie = pie + offset;\r
145                         \r
146                 }\r
147 \r
148                 \r
149                 if(remainder_ielen>0)\r
150                 {\r
151                         pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
152                         if(pbackup_remainder_ie && premainder_ie)\r
153                                 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
154                 }               \r
155                 \r
156                 *dst_ie++=_TIM_IE_;\r
157 \r
158                 if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))                      \r
159                         tim_ielen = 5;\r
160                 else\r
161                         tim_ielen = 4;\r
162 \r
163                 *dst_ie++= tim_ielen;\r
164                 \r
165                 *dst_ie++=0;//DTIM count\r
166                 *dst_ie++=1;//DTIM peroid\r
167                 \r
168                 if(pstapriv->tim_bitmap&BIT(0))//for bc/mc frames\r
169                         *dst_ie++ = BIT(0);//bitmap ctrl \r
170                 else\r
171                         *dst_ie++ = 0;\r
172 \r
173                 if(tim_ielen==4)\r
174                 {\r
175                         u8 pvb=0;\r
176                         \r
177                         if(pstapriv->tim_bitmap&0x00fe)\r
178                                 pvb = (u8)tim_bitmap_le;\r
179                         else if(pstapriv->tim_bitmap&0xff00)                    \r
180                                 pvb = (u8)(tim_bitmap_le>>8);\r
181                         else\r
182                                 pvb = (u8)tim_bitmap_le;\r
183 \r
184                         *dst_ie++ = pvb;\r
185                         \r
186                 }       \r
187                 else if(tim_ielen==5)\r
188                 {\r
189                         _rtw_memcpy(dst_ie, &tim_bitmap_le, 2);\r
190                         dst_ie+=2;                              \r
191                 }       \r
192                 \r
193                 //copy remainder IE\r
194                 if(pbackup_remainder_ie)\r
195                 {\r
196                         _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
197 \r
198                         rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
199                 }       \r
200 \r
201                 offset =  (uint)(dst_ie - pie);\r
202                 pnetwork_mlmeext->IELength = offset + remainder_ielen;\r
203         \r
204         }\r
205 }\r
206 \r
207 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)\r
208 {\r
209         PNDIS_802_11_VARIABLE_IEs       pIE;\r
210         u8      bmatch = _FALSE;\r
211         u8      *pie = pnetwork->IEs;\r
212         u8      *p=NULL, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
213         u32     i, offset, ielen, ie_offset, remainder_ielen = 0;\r
214 \r
215         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)\r
216         {\r
217                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);\r
218 \r
219                 if (pIE->ElementID > index)\r
220                 {\r
221                         break;\r
222                 }\r
223                 else if(pIE->ElementID == index) // already exist the same IE\r
224                 {\r
225                         p = (u8 *)pIE;\r
226                         ielen = pIE->Length;\r
227                         bmatch = _TRUE;\r
228                         break;\r
229                 }\r
230 \r
231                 p = (u8 *)pIE;\r
232                 ielen = pIE->Length;\r
233                 i += (pIE->Length + 2);\r
234         }\r
235 \r
236         if (p != NULL && ielen>0)\r
237         {\r
238                 ielen += 2;\r
239                 \r
240                 premainder_ie = p+ielen;\r
241 \r
242                 ie_offset = (sint)(p -pie);\r
243                 \r
244                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
245 \r
246                 if(bmatch)\r
247                         dst_ie = p;\r
248                 else\r
249                         dst_ie = (p+ielen);\r
250         }\r
251 \r
252         if(dst_ie == NULL)\r
253                 return;\r
254 \r
255         if(remainder_ielen>0)\r
256         {\r
257                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
258                 if(pbackup_remainder_ie && premainder_ie)\r
259                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
260         }\r
261 \r
262         *dst_ie++=index;\r
263         *dst_ie++=len;\r
264 \r
265         _rtw_memcpy(dst_ie, data, len);\r
266         dst_ie+=len;\r
267 \r
268         //copy remainder IE\r
269         if(pbackup_remainder_ie)\r
270         {\r
271                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
272 \r
273                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
274         }\r
275 \r
276         offset =  (uint)(dst_ie - pie);\r
277         pnetwork->IELength = offset + remainder_ielen;\r
278 }\r
279 \r
280 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)\r
281 {\r
282         u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
283         uint offset, ielen, ie_offset, remainder_ielen = 0;\r
284         u8      *pie = pnetwork->IEs;\r
285 \r
286         p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);\r
287         if (p != NULL && ielen>0)\r
288         {\r
289                 ielen += 2;\r
290                 \r
291                 premainder_ie = p+ielen;\r
292 \r
293                 ie_offset = (sint)(p -pie);\r
294                 \r
295                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
296 \r
297                 dst_ie = p;\r
298         }\r
299         else {\r
300                 return;\r
301         }\r
302 \r
303         if(remainder_ielen>0)\r
304         {\r
305                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
306                 if(pbackup_remainder_ie && premainder_ie)\r
307                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
308         }\r
309 \r
310         //copy remainder IE\r
311         if(pbackup_remainder_ie)\r
312         {\r
313                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
314 \r
315                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
316         }\r
317 \r
318         offset =  (uint)(dst_ie - pie);\r
319         pnetwork->IELength = offset + remainder_ielen;\r
320 }\r
321 \r
322 \r
323 u8 chk_sta_is_alive(struct sta_info *psta);\r
324 u8 chk_sta_is_alive(struct sta_info *psta)\r
325 {\r
326         u8 ret = _FALSE;\r
327         #ifdef DBG_EXPIRATION_CHK\r
328         DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"\r
329                 , MAC_ARG(psta->hwaddr)\r
330                 , psta->rssi_stat.UndecoratedSmoothedPWDB\r
331                 //, STA_RX_PKTS_ARG(psta)\r
332                 , STA_RX_PKTS_DIFF_ARG(psta)\r
333                 , psta->expire_to\r
334                 , psta->state&WIFI_SLEEP_STATE?"PS, ":""\r
335                 , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""\r
336                 , psta->sleepq_len\r
337         );\r
338         #endif\r
339 \r
340         //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))\r
341         if((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))\r
342         {\r
343                 #if 0\r
344                 if(psta->state&WIFI_SLEEP_STATE)\r
345                         ret = _TRUE;\r
346                 #endif\r
347         }\r
348         else\r
349         {\r
350                 ret = _TRUE;\r
351         }\r
352 \r
353         sta_update_last_rx_pkts(psta);\r
354 \r
355         return ret;\r
356 }\r
357 \r
358 void    expire_timeout_chk(_adapter *padapter)\r
359 {\r
360         _irqL irqL;\r
361         _list   *phead, *plist;\r
362         u8 updated = _FALSE;\r
363         struct sta_info *psta=NULL;     \r
364         struct sta_priv *pstapriv = &padapter->stapriv;\r
365         u8 chk_alive_num = 0;\r
366         char chk_alive_list[NUM_STA];\r
367         int i;\r
368 \r
369 \r
370         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
371         \r
372         phead = &pstapriv->auth_list;\r
373         plist = get_next(phead);\r
374         \r
375         //check auth_queue\r
376         #ifdef DBG_EXPIRATION_CHK\r
377         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
378                 DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"\r
379                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);\r
380         }\r
381         #endif\r
382         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
383         {\r
384                 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);\r
385 \r
386                 plist = get_next(plist);\r
387 \r
388 \r
389 #ifdef CONFIG_ATMEL_RC_PATCH\r
390                 if (_TRUE == _rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->hwaddr), ETH_ALEN))\r
391                         continue;\r
392                 if (psta->flag_atmel_rc)\r
393                         continue;\r
394 #endif\r
395                 if(psta->expire_to>0)\r
396                 {\r
397                         psta->expire_to--;\r
398                         if (psta->expire_to == 0)\r
399                         {\r
400                                 rtw_list_delete(&psta->auth_list);\r
401                                 pstapriv->auth_list_cnt--;\r
402                                 \r
403                                 DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",\r
404                                         psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);\r
405                                 \r
406                                 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
407                                 \r
408                                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);        \r
409                                 rtw_free_stainfo(padapter, psta);\r
410                                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); \r
411                                 \r
412                                 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
413                         }       \r
414                 }       \r
415                 \r
416         }\r
417 \r
418         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
419         psta = NULL;\r
420         \r
421 \r
422         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
423         \r
424         phead = &pstapriv->asoc_list;\r
425         plist = get_next(phead);\r
426 \r
427         //check asoc_queue\r
428         #ifdef DBG_EXPIRATION_CHK\r
429         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
430                 DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"\r
431                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);\r
432         }\r
433         #endif\r
434         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
435         {\r
436                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
437                 plist = get_next(plist);\r
438 #ifdef CONFIG_ATMEL_RC_PATCH\r
439                 DBG_871X("%s:%d  psta=%p, %02x,%02x||%02x,%02x  \n\n", __func__,  __LINE__,\r
440                         psta,pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->hwaddr[0], psta->hwaddr[5]);\r
441                 if (_TRUE == _rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->hwaddr), ETH_ALEN))\r
442                         continue;               \r
443                 if (psta->flag_atmel_rc)\r
444                         continue;\r
445                 DBG_871X("%s: debug line:%d \n", __func__, __LINE__);\r
446 #endif\r
447 #ifdef CONFIG_AUTO_AP_MODE\r
448                 if(psta->isrc)\r
449                         continue;\r
450 #endif\r
451                 if (chk_sta_is_alive(psta) || !psta->expire_to) {\r
452                         psta->expire_to = pstapriv->expire_to;\r
453                         psta->keep_alive_trycnt = 0;\r
454                         #ifdef CONFIG_TX_MCAST2UNI\r
455                         psta->under_exist_checking = 0;\r
456                         #endif  // CONFIG_TX_MCAST2UNI\r
457                 } else {\r
458                         psta->expire_to--;\r
459                 }\r
460 \r
461 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
462 #ifdef CONFIG_80211N_HT\r
463 #ifdef CONFIG_TX_MCAST2UNI\r
464                 if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {\r
465                         // check sta by delba(addba) for 11n STA \r
466                         // ToDo: use CCX report to check for all STAs\r
467                         //DBG_871X("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking);\r
468                         \r
469                                 if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {\r
470                                 DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
471                                 psta->under_exist_checking = 0;\r
472                                 psta->expire_to = 0;\r
473                         } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {\r
474                                 DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
475                                 psta->under_exist_checking = 1;\r
476                                 //tear down TX AMPDU\r
477                                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
478                                 psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
479                                 psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
480                         }\r
481                 }\r
482 #endif //CONFIG_TX_MCAST2UNI\r
483 #endif //CONFIG_80211N_HT\r
484 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
485 \r
486                 if (psta->expire_to <= 0)\r
487                 {\r
488                         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
489 \r
490                         if (padapter->registrypriv.wifi_spec == 1)\r
491                         {\r
492                                 psta->expire_to = pstapriv->expire_to;\r
493                                 continue;\r
494                         }\r
495 \r
496 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
497 #ifdef CONFIG_80211N_HT\r
498 \r
499 #define KEEP_ALIVE_TRYCNT (3)\r
500 \r
501                         if(psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT)\r
502                         {                               \r
503                                 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
504                                         psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
505                                 else\r
506                                         psta->keep_alive_trycnt = 0;\r
507                                 \r
508                         }\r
509                         else if((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
510                         {\r
511                                 psta->keep_alive_trycnt = 0;\r
512                         }                       \r
513                         if((psta->htpriv.ht_option==_TRUE) && (psta->htpriv.ampdu_enable==_TRUE)) \r
514                         {\r
515                                 uint priority = 1; //test using BK\r
516                                 u8 issued=0;                            \r
517                 \r
518                                 //issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1;\r
519                                 issued |= (psta->htpriv.candidate_tid_bitmap>>priority)&0x1;\r
520 \r
521                                 if(0==issued)\r
522                                 {\r
523                                         if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
524                                         {\r
525                                                 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);\r
526 \r
527                                                 if (psta->state & WIFI_SLEEP_STATE) \r
528                                                         psta->expire_to = 2; // 2x2=4 sec\r
529                                                 else\r
530                                                         psta->expire_to = 1; // 2 sec\r
531                                         \r
532                                                 psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
533                                         \r
534                                                 //add_ba_hdl(padapter, (u8*)paddbareq_parm);\r
535 \r
536                                                 DBG_871X("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
537 \r
538                                                 issue_addba_req(padapter, psta->hwaddr, (u8)priority);\r
539                 \r
540                                                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);\r
541                                                 \r
542                                                 psta->keep_alive_trycnt++;                                              \r
543 \r
544                                                 continue;\r
545                                         }                       \r
546                                 }                                       \r
547                         }\r
548                         if(psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
549                         {\r
550                                 psta->keep_alive_trycnt = 0;\r
551                                 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
552                                 DBG_871X("change to another methods to check alive if staion is at ps mode\n");\r
553                         }       \r
554                         \r
555 #endif //CONFIG_80211N_HT\r
556 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK \r
557                         if (psta->state & WIFI_SLEEP_STATE) {\r
558                                 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {\r
559                                         //to check if alive by another methods if staion is at ps mode.                                 \r
560                                         psta->expire_to = pstapriv->expire_to;\r
561                                         psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
562 \r
563                                         //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));\r
564 \r
565                                         //to update bcn with tim_bitmap for this station\r
566                                         pstapriv->tim_bitmap |= BIT(psta->aid);\r
567                                         update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
568 \r
569                                         if(!pmlmeext->active_keep_alive_check)\r
570                                                 continue;\r
571                                 }\r
572                         }\r
573                         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
574                         if (pmlmeext->active_keep_alive_check) {\r
575                                 int stainfo_offset;\r
576 \r
577                                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
578                                 if (stainfo_offset_valid(stainfo_offset)) {\r
579                                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
580                                 }\r
581 \r
582                                 continue;\r
583                         }\r
584                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
585                         rtw_list_delete(&psta->asoc_list);\r
586                         pstapriv->asoc_list_cnt--;\r
587                         DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
588                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);\r
589                 }       \r
590                 else\r
591                 {\r
592                         /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */\r
593                         if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)\r
594                                 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)\r
595                         ){\r
596                                 DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__\r
597                                         , MAC_ARG(psta->hwaddr)\r
598                                         , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);\r
599                                 wakeup_sta_to_xmit(padapter, psta);\r
600                         }\r
601                 }\r
602         }\r
603 \r
604         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
605 \r
606 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
607 if (chk_alive_num) {\r
608 \r
609         u8 backup_oper_channel=0;\r
610         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
611         /* switch to correct channel of current network  before issue keep-alive frames */\r
612         if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {\r
613                 backup_oper_channel = rtw_get_oper_ch(padapter);\r
614                 SelectChannel(padapter, pmlmeext->cur_channel);\r
615         }\r
616 \r
617         /* issue null data to check sta alive*/\r
618         for (i = 0; i < chk_alive_num; i++) {\r
619                 int ret = _FAIL;\r
620 \r
621                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
622 #ifdef CONFIG_ATMEL_RC_PATCH\r
623                 if (_TRUE == _rtw_memcmp(  pstapriv->atmel_rc_pattern, psta->hwaddr, ETH_ALEN))\r
624                         continue;\r
625                 if (psta->flag_atmel_rc)\r
626                         continue;\r
627 #endif\r
628                 if(!(psta->state &_FW_LINKED))\r
629                         continue;               \r
630         \r
631                 if (psta->state & WIFI_SLEEP_STATE)\r
632                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);\r
633                 else\r
634                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);\r
635 \r
636                 psta->keep_alive_trycnt++;\r
637                 if (ret == _SUCCESS)\r
638                 {\r
639                         DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));\r
640                         psta->expire_to = pstapriv->expire_to;\r
641                         psta->keep_alive_trycnt = 0;\r
642                         continue;\r
643                 }\r
644                 else if (psta->keep_alive_trycnt <= 3)\r
645                 {\r
646                         DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
647                         psta->expire_to = 1;\r
648                         continue;\r
649                 }\r
650 \r
651                 psta->keep_alive_trycnt = 0;\r
652                 DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
653                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
654                 if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {\r
655                         rtw_list_delete(&psta->asoc_list);\r
656                         pstapriv->asoc_list_cnt--;\r
657                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);\r
658                 }\r
659                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
660 \r
661         }\r
662 \r
663         if (backup_oper_channel>0) /* back to the original operation channel */\r
664                 SelectChannel(padapter, backup_oper_channel);\r
665 }\r
666 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
667 \r
668         associated_clients_update(padapter, updated);\r
669 }\r
670 \r
671 void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)\r
672 {       \r
673         int i;\r
674         u8 rf_type;\r
675         unsigned char sta_band = 0, shortGIrate = _FALSE;\r
676         unsigned int tx_ra_bitmap=0;\r
677         struct ht_priv  *psta_ht = NULL;\r
678         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
679         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
680 \r
681 #ifdef CONFIG_80211N_HT\r
682         if(psta)\r
683                 psta_ht = &psta->htpriv;\r
684         else\r
685                 return;\r
686 #endif //CONFIG_80211N_HT\r
687 \r
688         if(!(psta->state & _FW_LINKED))\r
689                 return;\r
690 \r
691 #if 0//gtest\r
692         if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)\r
693         {\r
694                 //is this a 2r STA?\r
695                 if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))\r
696                 {\r
697                         priv->pshare->has_2r_sta |= BIT(pstat->aid);\r
698                         if(rtw_read16(padapter, 0x102501f6) != 0xffff)\r
699                         {\r
700                                 rtw_write16(padapter, 0x102501f6, 0xffff);\r
701                                 reset_1r_sta_RA(priv, 0xffff);\r
702                                 Switch_1SS_Antenna(priv, 3);\r
703                         }\r
704                 }\r
705                 else// bg or 1R STA? \r
706                 { \r
707                         if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)\r
708                         {\r
709                                 if(rtw_read16(padapter, 0x102501f6) != 0x7777)\r
710                                 { // MCS7 SGI\r
711                                         rtw_write16(padapter, 0x102501f6,0x7777);\r
712                                         reset_1r_sta_RA(priv, 0x7777);\r
713                                         Switch_1SS_Antenna(priv, 2);\r
714                                 }\r
715                         }\r
716                 }\r
717                 \r
718         }\r
719 \r
720         if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) \r
721         {\r
722                 if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)\r
723                         pstat->rssi_level = 1;\r
724                 else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||\r
725                         ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&\r
726                         (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&\r
727                         (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))\r
728                         pstat->rssi_level = 2;\r
729                 else\r
730                         pstat->rssi_level = 3;\r
731         }\r
732 \r
733         // rate adaptive by rssi\r
734         if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)\r
735         {\r
736                 if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))\r
737                 {\r
738                         switch (pstat->rssi_level) {\r
739                                 case 1:\r
740                                         pstat->tx_ra_bitmap &= 0x100f0000;\r
741                                         break;\r
742                                 case 2:\r
743                                         pstat->tx_ra_bitmap &= 0x100ff000;\r
744                                         break;\r
745                                 case 3:\r
746                                         if (priv->pshare->is_40m_bw)\r
747                                                 pstat->tx_ra_bitmap &= 0x100ff005;\r
748                                         else\r
749                                                 pstat->tx_ra_bitmap &= 0x100ff001;\r
750 \r
751                                         break;\r
752                         }\r
753                 }\r
754                 else \r
755                 {\r
756                         switch (pstat->rssi_level) {\r
757                                 case 1:\r
758                                         pstat->tx_ra_bitmap &= 0x1f0f0000;\r
759                                         break;\r
760                                 case 2:\r
761                                         pstat->tx_ra_bitmap &= 0x1f0ff000;\r
762                                         break;\r
763                                 case 3:\r
764                                         if (priv->pshare->is_40m_bw)\r
765                                                 pstat->tx_ra_bitmap &= 0x000ff005;\r
766                                         else\r
767                                                 pstat->tx_ra_bitmap &= 0x000ff001;\r
768 \r
769                                         break;\r
770                         }\r
771 \r
772                         // Don't need to mask high rates due to new rate adaptive parameters\r
773                         //if (pstat->is_broadcom_sta)           // use MCS12 as the highest rate vs. Broadcom sta\r
774                         //      pstat->tx_ra_bitmap &= 0x81ffffff;\r
775 \r
776                         // NIC driver will report not supporting MCS15 and MCS14 in asoc req\r
777                         //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)\r
778                         //      pstat->tx_ra_bitmap &= 0x83ffffff;              // if Realtek 1x2 sta, don't use MCS15 and MCS14\r
779                 }\r
780         }\r
781         else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))\r
782         {\r
783                 switch (pstat->rssi_level) {\r
784                         case 1:\r
785                                 pstat->tx_ra_bitmap &= 0x00000f00;\r
786                                 break;\r
787                         case 2:\r
788                                 pstat->tx_ra_bitmap &= 0x00000ff0;\r
789                                 break;\r
790                         case 3:\r
791                                 pstat->tx_ra_bitmap &= 0x00000ff5;\r
792                                 break;\r
793                 }\r
794         }\r
795         else \r
796         {\r
797                 pstat->tx_ra_bitmap &= 0x0000000d;\r
798         }\r
799 \r
800         // disable tx short GI when station cannot rx MCS15(AP is 2T2R)\r
801         // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)\r
802         // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate\r
803         if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||\r
804                  (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))\r
805         {\r
806                 pstat->tx_ra_bitmap &= ~BIT(28);        \r
807         }\r
808 #endif\r
809 \r
810         rtw_hal_update_sta_rate_mask(padapter, psta);\r
811         tx_ra_bitmap = psta->ra_mask;\r
812 \r
813         shortGIrate = query_ra_short_GI(psta);\r
814 \r
815         if ( pcur_network->Configuration.DSConfig > 14 ) {\r
816                 \r
817                 if (tx_ra_bitmap & 0xffff000)\r
818                         sta_band |= WIRELESS_11_5N ;\r
819 \r
820                 if (tx_ra_bitmap & 0xff0)\r
821                         sta_band |= WIRELESS_11A;\r
822 \r
823                 // 5G band\r
824                 #ifdef CONFIG_80211AC_VHT\r
825                 if (psta->vhtpriv.vht_option)  {\r
826                         sta_band = WIRELESS_11_5AC;\r
827                 }               \r
828                 #endif\r
829                 \r
830         } else {\r
831                 if (tx_ra_bitmap & 0xffff000)\r
832                         sta_band |= WIRELESS_11_24N;\r
833 \r
834                 if (tx_ra_bitmap & 0xff0)\r
835                         sta_band |= WIRELESS_11G;\r
836 \r
837                 if (tx_ra_bitmap & 0x0f)\r
838                         sta_band |= WIRELESS_11B;\r
839         }\r
840 \r
841         psta->wireless_mode = sta_band;\r
842         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);\r
843         \r
844         if (psta->aid < NUM_STA) \r
845         {\r
846                 u8      arg[4] = {0};\r
847 \r
848                 arg[0] = psta->mac_id;\r
849                 arg[1] = psta->raid;\r
850                 arg[2] = shortGIrate;\r
851                 arg[3] = psta->init_rate;\r
852 \r
853                 DBG_871X("%s=> mac_id:%d , raid:%d , shortGIrate=%d, bitmap=0x%x\n", \r
854                         __FUNCTION__ , psta->mac_id, psta->raid ,shortGIrate, tx_ra_bitmap);\r
855 \r
856                 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);\r
857         }\r
858         else \r
859         {\r
860                 DBG_871X("station aid %d exceed the max number\n", psta->aid);\r
861         }\r
862 \r
863 }\r
864 \r
865 void update_bmc_sta(_adapter *padapter)\r
866 {\r
867         _irqL   irqL;\r
868         unsigned char   network_type;\r
869         int supportRateNum = 0;\r
870         unsigned int tx_ra_bitmap=0;\r
871         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
872         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
873         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);  \r
874         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
875         struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);\r
876 \r
877         if(psta)\r
878         {\r
879                 psta->aid = 0;//default set to 0\r
880 \r
881                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;\r
882 \r
883                 psta->qos_option = 0;\r
884 #ifdef CONFIG_80211N_HT \r
885                 psta->htpriv.ht_option = _FALSE;\r
886 #endif //CONFIG_80211N_HT\r
887 \r
888                 psta->ieee8021x_blocked = 0;\r
889 \r
890                 _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
891 \r
892                 //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.\r
893 \r
894                 //prepare for add_RATid         \r
895                 supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);\r
896                 network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);\r
897                 if (IsSupportedTxCCK(network_type)) {\r
898                         network_type = WIRELESS_11B;\r
899                 }\r
900                 else if (network_type == WIRELESS_INVALID) { // error handling\r
901                         if ( pcur_network->Configuration.DSConfig > 14 )\r
902                                 network_type = WIRELESS_11A;\r
903                         else\r
904                                 network_type = WIRELESS_11B;\r
905                 }\r
906                 update_sta_basic_rate(psta, network_type);\r
907                 psta->wireless_mode = network_type;\r
908 \r
909                 rtw_hal_update_sta_rate_mask(padapter, psta);\r
910                 tx_ra_bitmap = psta->ra_mask;\r
911 \r
912                 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);\r
913 \r
914                 //ap mode\r
915                 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);\r
916 \r
917                 //if(pHalData->fw_ractrl == _TRUE)\r
918                 {\r
919                         u8      arg[4] = {0};\r
920 \r
921                         arg[0] = psta->mac_id;\r
922                         arg[1] = psta->raid;\r
923                         arg[2] = 0;\r
924                         arg[3] = psta->init_rate;\r
925 \r
926                         DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%x\n", \r
927                                 __FUNCTION__ , psta->mac_id, psta->raid , tx_ra_bitmap);\r
928 \r
929                         rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);\r
930                 }\r
931 \r
932                 rtw_sta_media_status_rpt(padapter, psta, 1);\r
933 \r
934                 _enter_critical_bh(&psta->lock, &irqL);\r
935                 psta->state = _FW_LINKED;\r
936                 _exit_critical_bh(&psta->lock, &irqL);\r
937 \r
938         }\r
939         else\r
940         {\r
941                 DBG_871X("add_RATid_bmc_sta error!\n");\r
942         }\r
943                 \r
944 }\r
945 \r
946 //notes:\r
947 //AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode \r
948 //MAC_ID = AID+1 for sta in ap/adhoc mode \r
949 //MAC_ID = 1 for bc/mc for sta/ap/adhoc\r
950 //MAC_ID = 0 for bssid for sta/ap/adhoc\r
951 //CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;\r
952 \r
953 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)\r
954 {       \r
955         _irqL   irqL;\r
956         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
957         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
958         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
959 #ifdef CONFIG_80211N_HT\r
960         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
961         struct ht_priv  *phtpriv_sta = &psta->htpriv;\r
962 #endif //CONFIG_80211N_HT\r
963         u8      cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;\r
964         //set intf_tag to if1\r
965         //psta->intf_tag = 0;\r
966 \r
967         DBG_871X("%s\n",__FUNCTION__);\r
968 \r
969         //psta->mac_id = psta->aid+4;\r
970         //psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(),\r
971                                                        //release macid when call rtw_free_stainfo()\r
972 \r
973         //ap mode\r
974         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);\r
975         \r
976         if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\r
977                 psta->ieee8021x_blocked = _TRUE;\r
978         else\r
979                 psta->ieee8021x_blocked = _FALSE;\r
980         \r
981 \r
982         //update sta's cap\r
983         \r
984         //ERP\r
985         VCS_update(padapter, psta);\r
986 #ifdef CONFIG_80211N_HT \r
987         //HT related cap\r
988         if(phtpriv_sta->ht_option)\r
989         {\r
990                 //check if sta supports rx ampdu\r
991                 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;\r
992 \r
993                 phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;\r
994         \r
995                 // bwmode\r
996                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))\r
997                 {                       \r
998                         psta->bw_mode = CHANNEL_WIDTH_40;\r
999                 }\r
1000                 else\r
1001                 {                       \r
1002                         psta->bw_mode = CHANNEL_WIDTH_20;\r
1003                 }               \r
1004 \r
1005                 if(pmlmeext->cur_bwmode < psta->bw_mode)\r
1006                 {\r
1007                         psta->bw_mode = pmlmeext->cur_bwmode;\r
1008                 }\r
1009 \r
1010                 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;\r
1011 \r
1012 \r
1013                 //check if sta support s Short GI 20M \r
1014                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
1015                 {\r
1016                         phtpriv_sta->sgi_20m = _TRUE;\r
1017                 }\r
1018                 \r
1019                 //check if sta support s Short GI 40M \r
1020                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
1021                 {\r
1022                         if(psta->bw_mode == CHANNEL_WIDTH_40) //according to psta->bw_mode\r
1023                                 phtpriv_sta->sgi_40m = _TRUE;\r
1024                         else\r
1025                                 phtpriv_sta->sgi_40m = _FALSE;\r
1026                 }\r
1027 \r
1028                 psta->qos_option = _TRUE;\r
1029 \r
1030                 // B0 Config LDPC Coding Capability\r
1031                 if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && \r
1032                         GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1033                 {\r
1034                         SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));\r
1035                         DBG_871X("Enable HT Tx LDPC for STA(%d)\n",psta->aid);\r
1036                 }\r
1037 \r
1038                 // B7 B8 B9 Config STBC setting\r
1039                 if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&\r
1040                         GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)))\r
1041                 {\r
1042                         SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX) );\r
1043                         DBG_871X("Enable HT Tx STBC for STA(%d)\n",psta->aid);\r
1044                 }\r
1045 \r
1046 #ifdef CONFIG_BEAMFORMING\r
1047                 // Config Tx beamforming setting\r
1048                 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && \r
1049                         GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1050                 {\r
1051                         SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);\r
1052                 }\r
1053 \r
1054                 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&\r
1055                         GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1056                 {\r
1057                         SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);\r
1058                 }\r
1059 \r
1060                 if (cur_beamform_cap) {\r
1061                         DBG_871X("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->aid, cur_beamform_cap);\r
1062                 }\r
1063 #endif //CONFIG_BEAMFORMING\r
1064         }\r
1065         else\r
1066         {\r
1067                 phtpriv_sta->ampdu_enable = _FALSE;\r
1068                 \r
1069                 phtpriv_sta->sgi_20m = _FALSE;\r
1070                 phtpriv_sta->sgi_40m = _FALSE;\r
1071                 psta->bw_mode = CHANNEL_WIDTH_20;\r
1072                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1073         }\r
1074 \r
1075         phtpriv_sta->ldpc_cap = cur_ldpc_cap;\r
1076         phtpriv_sta->stbc_cap = cur_stbc_cap;\r
1077         phtpriv_sta->beamform_cap = cur_beamform_cap;\r
1078 \r
1079         //Rx AMPDU\r
1080         send_delba(padapter, 0, psta->hwaddr);// recipient\r
1081         \r
1082         //TX AMPDU\r
1083         send_delba(padapter, 1, psta->hwaddr);// // originator\r
1084         phtpriv_sta->agg_enable_bitmap = 0x0;//reset\r
1085         phtpriv_sta->candidate_tid_bitmap = 0x0;//reset\r
1086 #endif //CONFIG_80211N_HT\r
1087 \r
1088 #ifdef CONFIG_80211AC_VHT\r
1089         update_sta_vht_info_apmode(padapter, psta);\r
1090 #endif\r
1091 \r
1092         update_ldpc_stbc_cap(psta);\r
1093 \r
1094         //todo: init other variables\r
1095         \r
1096         _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
1097 \r
1098 \r
1099         //add ratid\r
1100         //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()\r
1101 \r
1102 \r
1103         _enter_critical_bh(&psta->lock, &irqL);\r
1104         psta->state |= _FW_LINKED;\r
1105         _exit_critical_bh(&psta->lock, &irqL);\r
1106         \r
1107 \r
1108 }\r
1109 \r
1110 static void update_ap_info(_adapter *padapter, struct sta_info *psta)\r
1111 {\r
1112         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1113         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
1114         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1115         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1116 #ifdef CONFIG_80211N_HT\r
1117         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
1118 #endif //CONFIG_80211N_HT\r
1119 \r
1120 \r
1121         psta->wireless_mode = pmlmeext->cur_wireless_mode;\r
1122 \r
1123         psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);\r
1124         _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);\r
1125 \r
1126 #ifdef CONFIG_80211N_HT \r
1127         //HT related cap\r
1128         if(phtpriv_ap->ht_option)\r
1129         {\r
1130                 //check if sta supports rx ampdu\r
1131                 //phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable;\r
1132 \r
1133                 //check if sta support s Short GI 20M\r
1134                 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
1135                 {\r
1136                         phtpriv_ap->sgi_20m = _TRUE;\r
1137                 }\r
1138                 //check if sta support s Short GI 40M\r
1139                 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
1140                 {\r
1141                         phtpriv_ap->sgi_40m = _TRUE;\r
1142                 }\r
1143 \r
1144                 psta->qos_option = _TRUE;\r
1145         }\r
1146         else\r
1147         {\r
1148                 phtpriv_ap->ampdu_enable = _FALSE;\r
1149                 \r
1150                 phtpriv_ap->sgi_20m = _FALSE;\r
1151                 phtpriv_ap->sgi_40m = _FALSE;\r
1152         }\r
1153 \r
1154         psta->bw_mode = pmlmeext->cur_bwmode;\r
1155         phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;\r
1156 \r
1157         phtpriv_ap->agg_enable_bitmap = 0x0;//reset\r
1158         phtpriv_ap->candidate_tid_bitmap = 0x0;//reset\r
1159 \r
1160         _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));\r
1161 \r
1162 #ifdef CONFIG_80211AC_VHT\r
1163         _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));\r
1164 #endif //CONFIG_80211AC_VHT\r
1165 \r
1166 #endif //CONFIG_80211N_HT\r
1167 }\r
1168 \r
1169 static void update_hw_ht_param(_adapter *padapter)\r
1170 {\r
1171         unsigned char           max_AMPDU_len;\r
1172         unsigned char           min_MPDU_spacing;\r
1173         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1174         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
1175         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1176         \r
1177         DBG_871X("%s\n", __FUNCTION__);\r
1178         \r
1179 \r
1180         //handle A-MPDU parameter field\r
1181         /*      \r
1182                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k\r
1183                 AMPDU_para [4:2]:Min MPDU Start Spacing \r
1184         */\r
1185         max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;  \r
1186         \r
1187         min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;        \r
1188 \r
1189         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));\r
1190 \r
1191         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));\r
1192 \r
1193         //\r
1194         // Config SM Power Save setting\r
1195         //\r
1196         pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;\r
1197         if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)\r
1198         {\r
1199                 /*u8 i;\r
1200                 //update the MCS rates\r
1201                 for (i = 0; i < 16; i++)\r
1202                 {\r
1203                         pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];\r
1204                 }*/\r
1205                 DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);\r
1206         }\r
1207 \r
1208         //\r
1209         // Config current HT Protection mode.\r
1210         //\r
1211         //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;\r
1212 \r
1213 }\r
1214 \r
1215 void start_bss_network(_adapter *padapter, u8 *pbuf)\r
1216 {\r
1217         u8 *p;\r
1218         u8 val8, cur_channel, cur_bwmode, cur_ch_offset;\r
1219         u16 bcn_interval;\r
1220         u32     acparm; \r
1221         int     ie_len; \r
1222         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1223         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1224         struct security_priv* psecuritypriv=&(padapter->securitypriv);  \r
1225         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
1226         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1227         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1228         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);\r
1229         struct HT_info_element *pht_info=NULL;\r
1230 #ifdef CONFIG_P2P\r
1231         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);\r
1232 #endif //CONFIG_P2P\r
1233         u8      cbw40_enable=0;\r
1234         u8      change_band = _FALSE;\r
1235         \r
1236         //DBG_871X("%s\n", __FUNCTION__);\r
1237 \r
1238         bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;       \r
1239         cur_channel = pnetwork->Configuration.DSConfig;\r
1240         cur_bwmode = CHANNEL_WIDTH_20;\r
1241         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1242         \r
1243 \r
1244         //check if there is wps ie, \r
1245         //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,\r
1246         //and at first time the security ie ( RSN/WPA IE) will not include in beacon.\r
1247         if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))\r
1248         {\r
1249                 pmlmeext->bstart_bss = _TRUE;\r
1250         }\r
1251 \r
1252         //todo: update wmm, ht cap\r
1253         //pmlmeinfo->WMM_enable;\r
1254         //pmlmeinfo->HT_enable;\r
1255         if(pmlmepriv->qospriv.qos_option)\r
1256                 pmlmeinfo->WMM_enable = _TRUE;\r
1257 #ifdef CONFIG_80211N_HT\r
1258         if(pmlmepriv->htpriv.ht_option)\r
1259         {\r
1260                 pmlmeinfo->WMM_enable = _TRUE;\r
1261                 pmlmeinfo->HT_enable = _TRUE;\r
1262                 //pmlmeinfo->HT_info_enable = _TRUE;\r
1263                 //pmlmeinfo->HT_caps_enable = _TRUE;\r
1264 \r
1265                 update_hw_ht_param(padapter);\r
1266         }\r
1267 #endif //#CONFIG_80211N_HT\r
1268 \r
1269 #ifdef CONFIG_80211AC_VHT\r
1270         if(pmlmepriv->vhtpriv.vht_option) {\r
1271                 pmlmeinfo->VHT_enable = _TRUE;\r
1272                 update_hw_vht_param(padapter);\r
1273         }\r
1274 #endif //CONFIG_80211AC_VHT\r
1275 \r
1276         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1277         {\r
1278                 //WEP Key will be set before this function, do not clear CAM.\r
1279                 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))\r
1280                         flush_all_cam_entry(padapter);  //clear CAM\r
1281         }       \r
1282 \r
1283         //set MSR to AP_Mode            \r
1284         Set_MSR(padapter, _HW_STATE_AP_);       \r
1285                 \r
1286         //Set BSSID REG\r
1287         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);\r
1288 \r
1289         //Set EDCA param reg\r
1290 #ifdef CONFIG_CONCURRENT_MODE\r
1291         acparm = 0x005ea42b;\r
1292 #else\r
1293         acparm = 0x002F3217; // VO\r
1294 #endif\r
1295         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));\r
1296         acparm = 0x005E4317; // VI\r
1297         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));\r
1298         //acparm = 0x00105320; // BE\r
1299         acparm = 0x005ea42b;\r
1300         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));\r
1301         acparm = 0x0000A444; // BK\r
1302         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));\r
1303 \r
1304         //Set Security\r
1305         val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;\r
1306         rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));\r
1307 \r
1308         //Beacon Control related register\r
1309         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));\r
1310 \r
1311         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);\r
1312 \r
1313 #if 0\r
1314         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1315         {\r
1316                 //u32 initialgain;\r
1317 \r
1318                 //initialgain = 0x1e;\r
1319 \r
1320 \r
1321                 //disable dynamic functions, such as high power, DIG\r
1322                 //Save_DM_Func_Flag(padapter);\r
1323                 //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);\r
1324                 \r
1325                 //turn on all dynamic functions \r
1326                 /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);*/\r
1327 \r
1328                 //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));\r
1329         \r
1330         }\r
1331 #endif\r
1332 #ifdef CONFIG_80211N_HT\r
1333         //set channel, bwmode   \r
1334         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
1335         if( p && ie_len)\r
1336         {\r
1337                 pht_info = (struct HT_info_element *)(p+2);\r
1338 \r
1339                 if (cur_channel > 14) {\r
1340                         if ((pregpriv->bw_mode & 0xf0) > 0)\r
1341                                 cbw40_enable = 1;\r
1342                 } else {\r
1343                         if ((pregpriv->bw_mode & 0x0f) > 0)\r
1344                                 cbw40_enable = 1;\r
1345                 }\r
1346 \r
1347                 if ((cbw40_enable) &&    (pht_info->infos[0] & BIT(2)))\r
1348                 {\r
1349                         //switch to the 40M Hz mode\r
1350                         //pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;\r
1351                         cur_bwmode = CHANNEL_WIDTH_40;\r
1352                         switch (pht_info->infos[0] & 0x3)\r
1353                         {\r
1354                                 case 1:\r
1355                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;\r
1356                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;\r
1357                                         break;\r
1358                         \r
1359                                 case 3:\r
1360                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;\r
1361                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;                                    \r
1362                                         break;\r
1363                                 \r
1364                                 default:\r
1365                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1366                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1367                                         break;\r
1368                         }               \r
1369                                                 \r
1370                 }\r
1371                                         \r
1372         }\r
1373 #endif //CONFIG_80211N_HT\r
1374 \r
1375 #ifdef CONFIG_80211AC_VHT\r
1376         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
1377         if( p && ie_len)\r
1378         {\r
1379                 if(GET_VHT_OPERATION_ELE_CHL_WIDTH(p+2) >= 1) {\r
1380                         cur_bwmode = CHANNEL_WIDTH_80;\r
1381                 }\r
1382         }\r
1383 #endif\r
1384 \r
1385 #ifdef CONFIG_CONCURRENT_MODE\r
1386         //TODO: need to judge the phy parameters on concurrent mode for single phy\r
1387         concurrent_set_ap_chbw(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
1388 #else //!CONFIG_CONCURRENT_MODE\r
1389         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
1390         DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);\r
1391         pmlmeext->cur_channel = cur_channel;    \r
1392         pmlmeext->cur_bwmode = cur_bwmode;\r
1393         pmlmeext->cur_ch_offset = cur_ch_offset;\r
1394 #endif //!CONFIG_CONCURRENT_MODE\r
1395 \r
1396         pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;\r
1397 \r
1398         //let pnetwork_mlmeext == pnetwork_mlme.\r
1399         _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);\r
1400 \r
1401         //update cur_wireless_mode\r
1402         update_wireless_mode(padapter);\r
1403 \r
1404         //update RRSR after set channel and bandwidth\r
1405         UpdateBrateTbl(padapter, pnetwork->SupportedRates);\r
1406         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);\r
1407 \r
1408         //udpate capability after cur_wireless_mode updated\r
1409         update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork));\r
1410 \r
1411 \r
1412 #ifdef CONFIG_P2P\r
1413         _rtw_memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);   \r
1414         pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;\r
1415 #endif //CONFIG_P2P\r
1416 \r
1417         if(_TRUE == pmlmeext->bstart_bss)\r
1418         {\r
1419                 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
1420 \r
1421 #ifndef CONFIG_INTERRUPT_BASED_TXBCN //other case will  tx beacon when bcn interrupt coming in.\r
1422 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
1423                 //issue beacon frame\r
1424                 if(send_beacon(padapter)==_FAIL)\r
1425                 {\r
1426                         DBG_871X("issue_beacon, fail!\n");\r
1427                 }\r
1428 #endif \r
1429 #endif //!CONFIG_INTERRUPT_BASED_TXBCN\r
1430                 \r
1431         }\r
1432 \r
1433 \r
1434         //update bc/mc sta_info\r
1435         update_bmc_sta(padapter);\r
1436         \r
1437         //pmlmeext->bstart_bss = _TRUE;\r
1438         \r
1439 }\r
1440 \r
1441 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf,  int len)\r
1442 {\r
1443         int ret=_SUCCESS;\r
1444         u8 *p;\r
1445         u8 *pHT_caps_ie=NULL;\r
1446         u8 *pHT_info_ie=NULL;\r
1447         struct sta_info *psta = NULL;\r
1448         u16 cap, ht_cap=_FALSE;\r
1449         uint ie_len = 0;\r
1450         int group_cipher, pairwise_cipher;      \r
1451         u8      channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];\r
1452         int supportRateNum = 0;\r
1453         u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};\r
1454         u8 wps_oui[4]={0x0,0x50,0xf2,0x04};\r
1455         u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};        \r
1456         struct registry_priv *pregistrypriv = &padapter->registrypriv;  \r
1457         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1458         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1459         WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
1460         struct sta_priv *pstapriv = &padapter->stapriv;\r
1461         u8 *ie = pbss_network->IEs;\r
1462         u8 vht_cap=_FALSE;\r
1463 \r
1464         /* SSID */\r
1465         /* Supported rates */\r
1466         /* DS Params */\r
1467         /* WLAN_EID_COUNTRY */\r
1468         /* ERP Information element */\r
1469         /* Extended supported rates */\r
1470         /* WPA/WPA2 */\r
1471         /* Wi-Fi Wireless Multimedia Extensions */\r
1472         /* ht_capab, ht_oper */\r
1473         /* WPS IE */\r
1474 \r
1475         DBG_871X("%s, len=%d\n", __FUNCTION__, len);\r
1476 \r
1477         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)\r
1478                 return _FAIL;\r
1479 \r
1480 \r
1481         if(len>MAX_IE_SZ)\r
1482                 return _FAIL;\r
1483         \r
1484         pbss_network->IELength = len;\r
1485 \r
1486         _rtw_memset(ie, 0, MAX_IE_SZ);\r
1487         \r
1488         _rtw_memcpy(ie, pbuf, pbss_network->IELength);\r
1489 \r
1490 \r
1491         if(pbss_network->InfrastructureMode!=Ndis802_11APMode)\r
1492                 return _FAIL;\r
1493 \r
1494         pbss_network->Rssi = 0;\r
1495 \r
1496         _rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);\r
1497         \r
1498         //beacon interval\r
1499         p = rtw_get_beacon_interval_from_ie(ie);//ie + 8;       // 8: TimeStamp, 2: Beacon Interval 2:Capability\r
1500         //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);\r
1501         pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);\r
1502         \r
1503         //capability\r
1504         //cap = *(unsigned short *)rtw_get_capability_from_ie(ie);\r
1505         //cap = le16_to_cpu(cap);\r
1506         cap = RTW_GET_LE16(ie);\r
1507 \r
1508         //SSID\r
1509         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));\r
1510         if(p && ie_len>0)\r
1511         {\r
1512                 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));\r
1513                 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);\r
1514                 pbss_network->Ssid.SsidLength = ie_len;\r
1515         }       \r
1516 \r
1517         //chnnel\r
1518         channel = 0;\r
1519         pbss_network->Configuration.Length = 0;\r
1520         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1521         if(p && ie_len>0)\r
1522                 channel = *(p + 2);\r
1523 \r
1524         pbss_network->Configuration.DSConfig = channel;\r
1525 \r
1526         \r
1527         _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);\r
1528         // get supported rates\r
1529         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));   \r
1530         if (p !=  NULL) \r
1531         {\r
1532                 _rtw_memcpy(supportRate, p+2, ie_len);  \r
1533                 supportRateNum = ie_len;\r
1534         }\r
1535         \r
1536         //get ext_supported rates\r
1537         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); \r
1538         if (p !=  NULL)\r
1539         {\r
1540                 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);\r
1541                 supportRateNum += ie_len;\r
1542         \r
1543         }\r
1544 \r
1545         network_type = rtw_check_network_type(supportRate, supportRateNum, channel);\r
1546 \r
1547         rtw_set_supported_rate(pbss_network->SupportedRates, network_type);\r
1548 \r
1549 \r
1550         //parsing ERP_IE\r
1551         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1552         if(p && ie_len>0)\r
1553         {\r
1554                 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);\r
1555         }\r
1556 \r
1557         //update privacy/security\r
1558         if (cap & BIT(4))\r
1559                 pbss_network->Privacy = 1;\r
1560         else\r
1561                 pbss_network->Privacy = 0;\r
1562 \r
1563         psecuritypriv->wpa_psk = 0;\r
1564 \r
1565         //wpa2\r
1566         group_cipher = 0; pairwise_cipher = 0;\r
1567         psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1568         psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;     \r
1569         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));            \r
1570         if(p && ie_len>0)\r
1571         {\r
1572                 if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1573                 {\r
1574                         psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1575                         \r
1576                         psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1577                         psecuritypriv->wpa_psk |= BIT(1);\r
1578 \r
1579                         psecuritypriv->wpa2_group_cipher = group_cipher;\r
1580                         psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;\r
1581 #if 0\r
1582                         switch(group_cipher)\r
1583                         {\r
1584                                 case WPA_CIPHER_NONE:                           \r
1585                                 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1586                                 break;\r
1587                                 case WPA_CIPHER_WEP40:                          \r
1588                                 psecuritypriv->wpa2_group_cipher = _WEP40_;\r
1589                                 break;\r
1590                                 case WPA_CIPHER_TKIP:                           \r
1591                                 psecuritypriv->wpa2_group_cipher = _TKIP_;\r
1592                                 break;\r
1593                                 case WPA_CIPHER_CCMP:                           \r
1594                                 psecuritypriv->wpa2_group_cipher = _AES_;                               \r
1595                                 break;\r
1596                                 case WPA_CIPHER_WEP104:                                 \r
1597                                 psecuritypriv->wpa2_group_cipher = _WEP104_;\r
1598                                 break;\r
1599                         }\r
1600 \r
1601                         switch(pairwise_cipher)\r
1602                         {\r
1603                                 case WPA_CIPHER_NONE:                   \r
1604                                 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;\r
1605                                 break;\r
1606                                 case WPA_CIPHER_WEP40:                  \r
1607                                 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;\r
1608                                 break;\r
1609                                 case WPA_CIPHER_TKIP:                           \r
1610                                 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;\r
1611                                 break;\r
1612                                 case WPA_CIPHER_CCMP:                   \r
1613                                 psecuritypriv->wpa2_pairwise_cipher = _AES_;\r
1614                                 break;\r
1615                                 case WPA_CIPHER_WEP104:                                 \r
1616                                 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;\r
1617                                 break;\r
1618                         }\r
1619 #endif                  \r
1620                 }\r
1621                 \r
1622         }\r
1623 \r
1624         //wpa\r
1625         ie_len = 0;\r
1626         group_cipher = 0; pairwise_cipher = 0;\r
1627         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1628         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;      \r
1629         for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1630         {\r
1631                 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));           \r
1632                 if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))\r
1633                 {\r
1634                         if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1635                         {\r
1636                                 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1637                                 \r
1638                                 psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1639 \r
1640                                 psecuritypriv->wpa_psk |= BIT(0);\r
1641 \r
1642                                 psecuritypriv->wpa_group_cipher = group_cipher;\r
1643                                 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;\r
1644 \r
1645 #if 0\r
1646                                 switch(group_cipher)\r
1647                                 {\r
1648                                         case WPA_CIPHER_NONE:                                   \r
1649                                         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1650                                         break;\r
1651                                         case WPA_CIPHER_WEP40:                                  \r
1652                                         psecuritypriv->wpa_group_cipher = _WEP40_;\r
1653                                         break;\r
1654                                         case WPA_CIPHER_TKIP:                                   \r
1655                                         psecuritypriv->wpa_group_cipher = _TKIP_;\r
1656                                         break;\r
1657                                         case WPA_CIPHER_CCMP:                                   \r
1658                                         psecuritypriv->wpa_group_cipher = _AES_;                                \r
1659                                         break;\r
1660                                         case WPA_CIPHER_WEP104:                                 \r
1661                                         psecuritypriv->wpa_group_cipher = _WEP104_;\r
1662                                         break;\r
1663                                 }\r
1664 \r
1665                                 switch(pairwise_cipher)\r
1666                                 {\r
1667                                         case WPA_CIPHER_NONE:                                   \r
1668                                         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;\r
1669                                         break;\r
1670                                         case WPA_CIPHER_WEP40:                                  \r
1671                                         psecuritypriv->wpa_pairwise_cipher = _WEP40_;\r
1672                                         break;\r
1673                                         case WPA_CIPHER_TKIP:                                   \r
1674                                         psecuritypriv->wpa_pairwise_cipher = _TKIP_;\r
1675                                         break;\r
1676                                         case WPA_CIPHER_CCMP:                                   \r
1677                                         psecuritypriv->wpa_pairwise_cipher = _AES_;\r
1678                                         break;\r
1679                                         case WPA_CIPHER_WEP104:                                 \r
1680                                         psecuritypriv->wpa_pairwise_cipher = _WEP104_;\r
1681                                         break;\r
1682                                 }\r
1683 #endif                          \r
1684                         }\r
1685 \r
1686                         break;\r
1687                         \r
1688                 }\r
1689                         \r
1690                 if ((p == NULL) || (ie_len == 0))\r
1691                 {\r
1692                                 break;\r
1693                 }\r
1694                 \r
1695         }\r
1696 \r
1697         //wmm\r
1698         ie_len = 0;\r
1699         pmlmepriv->qospriv.qos_option = 0;\r
1700         if(pregistrypriv->wmm_enable)\r
1701         {\r
1702                 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1703                 {                       \r
1704                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); \r
1705                         if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) \r
1706                         {\r
1707                                 pmlmepriv->qospriv.qos_option = 1;      \r
1708 \r
1709                                 *(p+8) |= BIT(7);//QoS Info, support U-APSD\r
1710                                 \r
1711                                 /* disable all ACM bits since the WMM admission control is not supported */\r
1712                                 *(p + 10) &= ~BIT(4); /* BE */\r
1713                                 *(p + 14) &= ~BIT(4); /* BK */\r
1714                                 *(p + 18) &= ~BIT(4); /* VI */\r
1715                                 *(p + 22) &= ~BIT(4); /* VO */\r
1716                                 \r
1717                                 break;                          \r
1718                         }\r
1719                         \r
1720                         if ((p == NULL) || (ie_len == 0))\r
1721                         {\r
1722                                 break;\r
1723                         }                       \r
1724                 }               \r
1725         }\r
1726 #ifdef CONFIG_80211N_HT\r
1727         //parsing HT_CAP_IE\r
1728         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1729         if(p && ie_len>0)\r
1730         {\r
1731                 u8 rf_type=0;\r
1732                 HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor=MAX_AMPDU_FACTOR_64K;\r
1733                 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);\r
1734 \r
1735                 if (0) {\r
1736                         DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));\r
1737                         dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);\r
1738                 }\r
1739 \r
1740                 pHT_caps_ie=p;\r
1741 \r
1742                 ht_cap = _TRUE;\r
1743                 network_type |= WIRELESS_11_24N;\r
1744 \r
1745                 rtw_ht_use_default_setting(padapter);\r
1746 \r
1747                 /* Update HT Capabilities Info field */\r
1748                 if (pmlmepriv->htpriv.sgi_20m == _FALSE)\r
1749                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);\r
1750 \r
1751                 if (pmlmepriv->htpriv.sgi_40m == _FALSE)\r
1752                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);\r
1753 \r
1754                 if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))\r
1755                 {\r
1756                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);\r
1757                 }\r
1758 \r
1759                 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))\r
1760                 {\r
1761                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);\r
1762                 }               \r
1763 \r
1764                 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))\r
1765                 {\r
1766                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);\r
1767                 }\r
1768 \r
1769                 /* Update A-MPDU Parameters field */\r
1770                 pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY);\r
1771 \r
1772                 if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||\r
1773                         (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))\r
1774                 {\r
1775                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));\r
1776                 }       \r
1777                 else\r
1778                 {\r
1779                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);    \r
1780                 }       \r
1781 \r
1782                 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);\r
1783                 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); //set  Max Rx AMPDU size  to 64K\r
1784 \r
1785                 /* Update Supported MCS Set field */\r
1786                 {\r
1787                         int i;\r
1788 \r
1789                         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));\r
1790 \r
1791                         /* RX MCS Bitmask */\r
1792                         switch(rf_type)\r
1793                         {\r
1794                                 case RF_1T1R:\r
1795                                 case RF_1T2R: //?\r
1796                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);\r
1797                                         break;\r
1798                                 case RF_2T2R:\r
1799                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);\r
1800                                         break;\r
1801                                 case RF_3T3R:\r
1802                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);\r
1803                                         break;\r
1804                                 default:\r
1805                                         DBG_871X("[warning] rf_type %d is not expected\n", rf_type);\r
1806                         }\r
1807                         for (i = 0; i < 10; i++)\r
1808                                 *(HT_CAP_ELE_RX_MCS_MAP(pht_cap)+i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];\r
1809                 }\r
1810 \r
1811 #ifdef CONFIG_BEAMFORMING\r
1812                 // Use registry value to enable HT Beamforming.\r
1813                 // ToDo: use configure file to set these capability.\r
1814                 pht_cap->tx_BF_cap_info = 0;\r
1815 \r
1816                 // HT Beamformer\r
1817                 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE))\r
1818                 {\r
1819                         // Transmit NDP Capable\r
1820                         SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);\r
1821                         // Explicit Compressed Steering Capable\r
1822                         SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);\r
1823                         // Compressed Steering Number Antennas\r
1824                         SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);\r
1825                 }\r
1826 \r
1827                 // HT Beamformee\r
1828                 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))\r
1829                 {\r
1830                         // Receive NDP Capable\r
1831                         SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);\r
1832                         // Explicit Compressed Beamforming Feedback Capable\r
1833                         SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);\r
1834                 }\r
1835 #endif //CONFIG_BEAMFORMING\r
1836 \r
1837                 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);\r
1838 \r
1839                 if (0) {\r
1840                         DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));\r
1841                         dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);\r
1842                 }\r
1843         }\r
1844 \r
1845         //parsing HT_INFO_IE\r
1846         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1847         if(p && ie_len>0)\r
1848         {\r
1849                 pHT_info_ie=p;\r
1850         }\r
1851 #endif //CONFIG_80211N_HT\r
1852         switch(network_type)\r
1853         {\r
1854                 case WIRELESS_11B:\r
1855                         pbss_network->NetworkTypeInUse = Ndis802_11DS;\r
1856                         break;  \r
1857                 case WIRELESS_11G:\r
1858                 case WIRELESS_11BG:\r
1859              case WIRELESS_11G_24N:\r
1860                 case WIRELESS_11BG_24N:\r
1861                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
1862                         break;\r
1863                 case WIRELESS_11A:\r
1864                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;\r
1865                         break;\r
1866                 default :\r
1867                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
1868                         break;\r
1869         }\r
1870         \r
1871         pmlmepriv->cur_network.network_type = network_type;\r
1872 \r
1873 #ifdef CONFIG_80211N_HT\r
1874         pmlmepriv->htpriv.ht_option = _FALSE;\r
1875 \r
1876         if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||\r
1877                       (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))\r
1878         {       \r
1879                 //todo:\r
1880                 //ht_cap = _FALSE;\r
1881         }\r
1882                       \r
1883         //ht_cap        \r
1884         if(pregistrypriv->ht_enable && ht_cap==_TRUE)\r
1885         {               \r
1886                 pmlmepriv->htpriv.ht_option = _TRUE;\r
1887                 pmlmepriv->qospriv.qos_option = 1;\r
1888 \r
1889                 if(pregistrypriv->ampdu_enable==1)\r
1890                 {\r
1891                         pmlmepriv->htpriv.ampdu_enable = _TRUE;\r
1892                 }\r
1893 \r
1894                 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);\r
1895                 \r
1896                 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);\r
1897         }\r
1898 #endif\r
1899 \r
1900 #ifdef CONFIG_80211AC_VHT\r
1901 \r
1902         //Parsing VHT CAP IE\r
1903         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1904         if(p && ie_len>0)\r
1905         {       \r
1906                 vht_cap = _TRUE; \r
1907         }\r
1908         //Parsing VHT OPERATION IE\r
1909         \r
1910 \r
1911         pmlmepriv->vhtpriv.vht_option = _FALSE;\r
1912         // if channel in 5G band, then add vht ie .\r
1913         if ((pbss_network->Configuration.DSConfig > 14) && \r
1914                 (pmlmepriv->htpriv.ht_option == _TRUE) &&\r
1915                 (pregistrypriv->vht_enable)) \r
1916         {\r
1917                 if(vht_cap == _TRUE)\r
1918                 {\r
1919                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
1920                 }\r
1921                 else if(pregistrypriv->vht_enable == 2) // auto enabled\r
1922                 {\r
1923                         u8      cap_len, operation_len;\r
1924 \r
1925                         rtw_vht_use_default_setting(padapter);\r
1926 \r
1927                         // VHT Capabilities element\r
1928                         cap_len = rtw_build_vht_cap_ie(padapter, pbss_network->IEs + pbss_network->IELength);\r
1929                         pbss_network->IELength += cap_len;\r
1930 \r
1931                         // VHT Operation element\r
1932                         operation_len = rtw_build_vht_operation_ie(padapter, pbss_network->IEs + pbss_network->IELength, pbss_network->Configuration.DSConfig);\r
1933                         pbss_network->IELength += operation_len;\r
1934 \r
1935                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
1936                 }               \r
1937         }\r
1938 #endif //CONFIG_80211AC_VHT\r
1939 \r
1940         pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pbss_network);\r
1941 \r
1942         //issue beacon to start bss network\r
1943         //start_bss_network(padapter, (u8*)pbss_network);\r
1944         rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);\r
1945                         \r
1946 \r
1947         //alloc sta_info for ap itself\r
1948         psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
1949         if(!psta)\r
1950         {\r
1951                 psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
1952                 if (psta == NULL) \r
1953                 { \r
1954                         return _FAIL;\r
1955                 }       \r
1956         }\r
1957 \r
1958         // update AP's sta info \r
1959         update_ap_info(padapter, psta);\r
1960         \r
1961         psta->state |= WIFI_AP_STATE;           //Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724  \r
1962         rtw_indicate_connect( padapter);\r
1963 \r
1964         pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon\r
1965                 \r
1966         //update bc/mc sta_info\r
1967         //update_bmc_sta(padapter);\r
1968 \r
1969         return ret;\r
1970 \r
1971 }\r
1972 \r
1973 void rtw_set_macaddr_acl(_adapter *padapter, int mode)\r
1974 {\r
1975         struct sta_priv *pstapriv = &padapter->stapriv;\r
1976         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
1977 \r
1978         DBG_871X("%s, mode=%d\n", __func__, mode);\r
1979 \r
1980         pacl_list->mode = mode;\r
1981 }\r
1982 \r
1983 int rtw_acl_add_sta(_adapter *padapter, u8 *addr)\r
1984 {\r
1985         _irqL irqL;\r
1986         _list   *plist, *phead;\r
1987         u8 added = _FALSE;\r
1988         int i, ret=0;\r
1989         struct rtw_wlan_acl_node *paclnode;\r
1990         struct sta_priv *pstapriv = &padapter->stapriv;\r
1991         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
1992         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
1993 \r
1994         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
1995 \r
1996         if((NUM_ACL-1) < pacl_list->num)\r
1997                 return (-1);    \r
1998 \r
1999 \r
2000         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2001 \r
2002         phead = get_list_head(pacl_node_q);\r
2003         plist = get_next(phead);\r
2004                 \r
2005         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
2006         {\r
2007                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
2008                 plist = get_next(plist);\r
2009 \r
2010                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))\r
2011                 {\r
2012                         if(paclnode->valid == _TRUE)\r
2013                         {\r
2014                                 added = _TRUE;\r
2015                                 DBG_871X("%s, sta has been added\n", __func__);\r
2016                                 break;\r
2017                         }\r
2018                 }               \r
2019         }\r
2020         \r
2021         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2022 \r
2023 \r
2024         if(added == _TRUE)\r
2025                 return ret;\r
2026         \r
2027 \r
2028         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2029 \r
2030         for(i=0; i< NUM_ACL; i++)\r
2031         {\r
2032                 paclnode = &pacl_list->aclnode[i];\r
2033 \r
2034                 if(paclnode->valid == _FALSE)\r
2035                 {\r
2036                         _rtw_init_listhead(&paclnode->list);\r
2037         \r
2038                         _rtw_memcpy(paclnode->addr, addr, ETH_ALEN);\r
2039                 \r
2040                         paclnode->valid = _TRUE;\r
2041 \r
2042                         rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));\r
2043         \r
2044                         pacl_list->num++;\r
2045 \r
2046                         break;\r
2047                 }\r
2048         }\r
2049 \r
2050         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
2051         \r
2052         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2053 \r
2054         return ret;\r
2055 }\r
2056 \r
2057 int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)\r
2058 {\r
2059         _irqL irqL;\r
2060         _list   *plist, *phead;\r
2061         int i, ret=0;\r
2062         struct rtw_wlan_acl_node *paclnode;\r
2063         struct sta_priv *pstapriv = &padapter->stapriv;\r
2064         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
2065         _queue  *pacl_node_q =&pacl_list->acl_node_q;\r
2066         u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };    //Baddr is used for clearing acl_list\r
2067 \r
2068         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
2069 \r
2070         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2071 \r
2072         phead = get_list_head(pacl_node_q);\r
2073         plist = get_next(phead);\r
2074                 \r
2075         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
2076         {\r
2077                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
2078                 plist = get_next(plist);\r
2079 \r
2080                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN) || _rtw_memcmp(baddr, addr, ETH_ALEN))\r
2081                 {\r
2082                         if(paclnode->valid == _TRUE)\r
2083                         {\r
2084                                 paclnode->valid = _FALSE;\r
2085 \r
2086                                 rtw_list_delete(&paclnode->list);\r
2087                                 \r
2088                                 pacl_list->num--;\r
2089                         }\r
2090                 }               \r
2091         }\r
2092         \r
2093         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2094 \r
2095         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
2096         \r
2097         return ret;\r
2098 \r
2099 }\r
2100 \r
2101 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)\r
2102 {\r
2103         struct cmd_obj*                 ph2c;\r
2104         struct set_stakey_parm  *psetstakey_para;\r
2105         struct cmd_priv                         *pcmdpriv=&padapter->cmdpriv;   \r
2106         u8      res=_SUCCESS;\r
2107 \r
2108         ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
2109         if ( ph2c == NULL){\r
2110                 res= _FAIL;\r
2111                 goto exit;\r
2112         }\r
2113 \r
2114         psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));\r
2115         if(psetstakey_para==NULL){\r
2116                 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));\r
2117                 res=_FAIL;\r
2118                 goto exit;\r
2119         }\r
2120 \r
2121         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);\r
2122 \r
2123 \r
2124         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;\r
2125 \r
2126         _rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);     \r
2127         \r
2128         _rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);\r
2129 \r
2130         \r
2131         res = rtw_enqueue_cmd(pcmdpriv, ph2c);  \r
2132 \r
2133 exit:\r
2134 \r
2135         return res;\r
2136         \r
2137 }\r
2138 \r
2139 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)\r
2140 {\r
2141         u8 keylen;\r
2142         struct cmd_obj* pcmd;\r
2143         struct setkey_parm *psetkeyparm;\r
2144         struct cmd_priv *pcmdpriv=&(padapter->cmdpriv); \r
2145         int res=_SUCCESS;\r
2146 \r
2147         //DBG_871X("%s\n", __FUNCTION__);\r
2148         \r
2149         pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
2150         if(pcmd==NULL){\r
2151                 res= _FAIL;\r
2152                 goto exit;\r
2153         }\r
2154         psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));\r
2155         if(psetkeyparm==NULL){\r
2156                 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));\r
2157                 res= _FAIL;\r
2158                 goto exit;\r
2159         }\r
2160 \r
2161         _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));\r
2162                 \r
2163         psetkeyparm->keyid=(u8)keyid;\r
2164         if (is_wep_enc(alg))\r
2165                 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);\r
2166 \r
2167         psetkeyparm->algorithm = alg;\r
2168 \r
2169         psetkeyparm->set_tx = set_tx;\r
2170 \r
2171         switch(alg)\r
2172         {\r
2173                 case _WEP40_:                                   \r
2174                         keylen = 5;\r
2175                         break;\r
2176                 case _WEP104_:\r
2177                         keylen = 13;                    \r
2178                         break;\r
2179                 case _TKIP_:\r
2180                 case _TKIP_WTMIC_:\r
2181                 case _AES_:\r
2182                 default:\r
2183                         keylen = 16;\r
2184         }\r
2185 \r
2186         _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);\r
2187         \r
2188         pcmd->cmdcode = _SetKey_CMD_;\r
2189         pcmd->parmbuf = (u8 *)psetkeyparm;   \r
2190         pcmd->cmdsz =  (sizeof(struct setkey_parm));  \r
2191         pcmd->rsp = NULL;\r
2192         pcmd->rspsz = 0;\r
2193 \r
2194 \r
2195         _rtw_init_listhead(&pcmd->list);\r
2196 \r
2197         res = rtw_enqueue_cmd(pcmdpriv, pcmd);\r
2198 \r
2199 exit:\r
2200 \r
2201         return res;\r
2202 }\r
2203 \r
2204 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)\r
2205 {\r
2206         DBG_871X("%s\n", __FUNCTION__);\r
2207 \r
2208         return rtw_ap_set_key(padapter, key, alg, keyid, 1);\r
2209 }\r
2210 \r
2211 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)\r
2212 {\r
2213         u8 alg;\r
2214 \r
2215         switch(keylen)\r
2216         {\r
2217                 case 5:\r
2218                         alg =_WEP40_;                   \r
2219                         break;\r
2220                 case 13:\r
2221                         alg =_WEP104_;                  \r
2222                         break;\r
2223                 default:\r
2224                         alg =_NO_PRIVACY_;                      \r
2225         }\r
2226 \r
2227         DBG_871X("%s\n", __FUNCTION__);\r
2228 \r
2229         return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);\r
2230 }\r
2231 \r
2232 #ifdef CONFIG_NATIVEAP_MLME\r
2233 \r
2234 static void update_bcn_fixed_ie(_adapter *padapter)\r
2235 {\r
2236         DBG_871X("%s\n", __FUNCTION__);\r
2237 \r
2238 }\r
2239 \r
2240 static void update_bcn_erpinfo_ie(_adapter *padapter)\r
2241 {\r
2242         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2243         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2244         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2245         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2246         unsigned char *p, *ie = pnetwork->IEs;\r
2247         u32 len = 0;\r
2248 \r
2249         DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);\r
2250 \r
2251         if(!pmlmeinfo->ERP_enable)\r
2252                 return;\r
2253 \r
2254         //parsing ERP_IE\r
2255         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));\r
2256         if(p && len>0)\r
2257         {\r
2258                 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;\r
2259 \r
2260                 if (pmlmepriv->num_sta_non_erp == 1)\r
2261                         pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;\r
2262                 else\r
2263                         pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);\r
2264 \r
2265                 if(pmlmepriv->num_sta_no_short_preamble > 0)\r
2266                         pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;\r
2267                 else\r
2268                         pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);\r
2269         \r
2270                 ERP_IE_handler(padapter, pIE);\r
2271         }\r
2272         \r
2273 }\r
2274 \r
2275 static void update_bcn_htcap_ie(_adapter *padapter)\r
2276 {\r
2277         DBG_871X("%s\n", __FUNCTION__);\r
2278 \r
2279 }\r
2280 \r
2281 static void update_bcn_htinfo_ie(_adapter *padapter)\r
2282 {       \r
2283         DBG_871X("%s\n", __FUNCTION__);\r
2284 \r
2285 }\r
2286 \r
2287 static void update_bcn_rsn_ie(_adapter *padapter)\r
2288 {\r
2289         DBG_871X("%s\n", __FUNCTION__);\r
2290 \r
2291 }\r
2292 \r
2293 static void update_bcn_wpa_ie(_adapter *padapter)\r
2294 {\r
2295         DBG_871X("%s\n", __FUNCTION__);\r
2296 \r
2297 }\r
2298 \r
2299 static void update_bcn_wmm_ie(_adapter *padapter)\r
2300 {\r
2301         DBG_871X("%s\n", __FUNCTION__);\r
2302         \r
2303 }\r
2304 \r
2305 static void update_bcn_wps_ie(_adapter *padapter)\r
2306 {\r
2307         u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;\r
2308         uint wps_ielen=0, wps_offset, remainder_ielen;\r
2309         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2310         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2311         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2312         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2313         unsigned char *ie = pnetwork->IEs;\r
2314         u32 ielen = pnetwork->IELength;\r
2315 \r
2316 \r
2317         DBG_871X("%s\n", __FUNCTION__);\r
2318 \r
2319         pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);\r
2320         \r
2321         if(pwps_ie==NULL || wps_ielen==0)\r
2322                 return;\r
2323 \r
2324         pwps_ie_src = pmlmepriv->wps_beacon_ie;\r
2325         if(pwps_ie_src == NULL)\r
2326                 return;\r
2327 \r
2328         wps_offset = (uint)(pwps_ie-ie);\r
2329 \r
2330         premainder_ie = pwps_ie + wps_ielen;\r
2331 \r
2332         remainder_ielen = ielen - wps_offset - wps_ielen;\r
2333 \r
2334         if(remainder_ielen>0)\r
2335         {\r
2336                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
2337                 if(pbackup_remainder_ie)\r
2338                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
2339         }\r
2340 \r
2341         wps_ielen = (uint)pwps_ie_src[1];//to get ie data len\r
2342         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)\r
2343         {\r
2344                 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);\r
2345                 pwps_ie += (wps_ielen+2);\r
2346 \r
2347                 if(pbackup_remainder_ie)\r
2348                         _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);\r
2349 \r
2350                 //update IELength\r
2351                 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;\r
2352         }\r
2353 \r
2354         if(pbackup_remainder_ie)\r
2355                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
2356         \r
2357         // deal with the case without set_tx_beacon_cmd() in update_beacon() \r
2358 #if defined( CONFIG_INTERRUPT_BASED_TXBCN ) || defined( CONFIG_PCI_HCI )\r
2359         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)\r
2360         {\r
2361                 u8 sr = 0;\r
2362                 rtw_get_wps_attr_content(pwps_ie_src,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);\r
2363         \r
2364                 if( sr ) {\r
2365                         set_fwstate(pmlmepriv, WIFI_UNDER_WPS);\r
2366                         DBG_871X("%s, set WIFI_UNDER_WPS\n", __func__);\r
2367                 }\r
2368         }\r
2369 #endif\r
2370 }\r
2371 \r
2372 static void update_bcn_p2p_ie(_adapter *padapter)\r
2373 {\r
2374 \r
2375 }\r
2376 \r
2377 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)\r
2378 {\r
2379         DBG_871X("%s\n", __FUNCTION__);\r
2380 \r
2381         if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))\r
2382         {\r
2383                 update_bcn_wpa_ie(padapter);\r
2384         }\r
2385         else if(_rtw_memcmp(WMM_OUI, oui, 4))\r
2386         {\r
2387                 update_bcn_wmm_ie(padapter);\r
2388         }\r
2389         else if(_rtw_memcmp(WPS_OUI, oui, 4))\r
2390         {\r
2391                 update_bcn_wps_ie(padapter);\r
2392         }\r
2393         else if(_rtw_memcmp(P2P_OUI, oui, 4))\r
2394         {\r
2395                 update_bcn_p2p_ie(padapter);\r
2396         }\r
2397         else\r
2398         {\r
2399                 DBG_871X("unknown OUI type!\n");\r
2400         }\r
2401         \r
2402         \r
2403 }\r
2404 \r
2405 void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, const char *tag)\r
2406 {\r
2407         _irqL irqL;\r
2408         struct mlme_priv *pmlmepriv;\r
2409         struct mlme_ext_priv    *pmlmeext;\r
2410         //struct mlme_ext_info  *pmlmeinfo;\r
2411         \r
2412         //DBG_871X("%s\n", __FUNCTION__);\r
2413 \r
2414         if(!padapter)\r
2415                 return;\r
2416 \r
2417         pmlmepriv = &(padapter->mlmepriv);\r
2418         pmlmeext = &(padapter->mlmeextpriv);\r
2419         //pmlmeinfo = &(pmlmeext->mlmext_info);\r
2420 \r
2421         if(_FALSE == pmlmeext->bstart_bss)\r
2422                 return;\r
2423 \r
2424         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);\r
2425 \r
2426         switch(ie_id)\r
2427         {\r
2428                 case 0xFF:\r
2429 \r
2430                         update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability\r
2431                         \r
2432                         break;\r
2433         \r
2434                 case _TIM_IE_:\r
2435                         \r
2436                         update_BCNTIM(padapter);\r
2437                         \r
2438                         break;\r
2439 \r
2440                 case _ERPINFO_IE_:\r
2441 \r
2442                         update_bcn_erpinfo_ie(padapter);\r
2443 \r
2444                         break;\r
2445 \r
2446                 case _HT_CAPABILITY_IE_:\r
2447 \r
2448                         update_bcn_htcap_ie(padapter);\r
2449                         \r
2450                         break;\r
2451 \r
2452                 case _RSN_IE_2_:\r
2453 \r
2454                         update_bcn_rsn_ie(padapter);\r
2455 \r
2456                         break;\r
2457                         \r
2458                 case _HT_ADD_INFO_IE_:\r
2459 \r
2460                         update_bcn_htinfo_ie(padapter);\r
2461                         \r
2462                         break;\r
2463         \r
2464                 case _VENDOR_SPECIFIC_IE_:\r
2465 \r
2466                         update_bcn_vendor_spec_ie(padapter, oui);\r
2467                         \r
2468                         break;\r
2469                         \r
2470                 default:\r
2471                         break;\r
2472         }\r
2473 \r
2474         pmlmepriv->update_bcn = _TRUE;\r
2475         \r
2476         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);          \r
2477         \r
2478 #ifndef CONFIG_INTERRUPT_BASED_TXBCN \r
2479 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
2480         if(tx)\r
2481         {\r
2482                 //send_beacon(padapter);//send_beacon must execute on TSR level\r
2483                 if (0)\r
2484                         DBG_871X(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);\r
2485                 set_tx_beacon_cmd(padapter);\r
2486         }\r
2487 #else\r
2488         {       \r
2489                 //PCI will issue beacon when BCN interrupt occurs.              \r
2490         }\r
2491 #endif\r
2492 #endif //!CONFIG_INTERRUPT_BASED_TXBCN\r
2493         \r
2494 }\r
2495 \r
2496 #ifdef CONFIG_80211N_HT\r
2497 \r
2498 /*\r
2499 op_mode\r
2500 Set to 0 (HT pure) under the followign conditions\r
2501         - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or\r
2502         - all STAs in the BSS are 20 MHz HT in 20 MHz BSS\r
2503 Set to 1 (HT non-member protection) if there may be non-HT STAs\r
2504         in both the primary and the secondary channel\r
2505 Set to 2 if only HT STAs are associated in BSS,\r
2506         however and at least one 20 MHz HT STA is associated\r
2507 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated\r
2508         (currently non-GF HT station is considered as non-HT STA also)\r
2509 */\r
2510 static int rtw_ht_operation_update(_adapter *padapter)\r
2511 {\r
2512         u16 cur_op_mode, new_op_mode;\r
2513         int op_mode_changes = 0;\r
2514         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2515         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
2516 \r
2517         if(pmlmepriv->htpriv.ht_option == _TRUE) \r
2518                 return 0;\r
2519         \r
2520         //if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)\r
2521         //      return 0;\r
2522 \r
2523         DBG_871X("%s current operation mode=0x%X\n",\r
2524                    __FUNCTION__, pmlmepriv->ht_op_mode);\r
2525 \r
2526         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)\r
2527             && pmlmepriv->num_sta_ht_no_gf) {\r
2528                 pmlmepriv->ht_op_mode |=\r
2529                         HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
2530                 op_mode_changes++;\r
2531         } else if ((pmlmepriv->ht_op_mode &\r
2532                     HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&\r
2533                    pmlmepriv->num_sta_ht_no_gf == 0) {\r
2534                 pmlmepriv->ht_op_mode &=\r
2535                         ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
2536                 op_mode_changes++;\r
2537         }\r
2538 \r
2539         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
2540             (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {\r
2541                 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
2542                 op_mode_changes++;\r
2543         } else if ((pmlmepriv->ht_op_mode &\r
2544                     HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
2545                    (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {\r
2546                 pmlmepriv->ht_op_mode &=\r
2547                         ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
2548                 op_mode_changes++;\r
2549         }\r
2550 \r
2551         /* Note: currently we switch to the MIXED op mode if HT non-greenfield\r
2552          * station is associated. Probably it's a theoretical case, since\r
2553          * it looks like all known HT STAs support greenfield.\r
2554          */\r
2555         new_op_mode = 0;\r
2556         if (pmlmepriv->num_sta_no_ht ||\r
2557             (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))\r
2558                 new_op_mode = OP_MODE_MIXED;\r
2559         else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)\r
2560                  && pmlmepriv->num_sta_ht_20mhz)\r
2561                 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;\r
2562         else if (pmlmepriv->olbc_ht)\r
2563                 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;\r
2564         else\r
2565                 new_op_mode = OP_MODE_PURE;\r
2566 \r
2567         cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
2568         if (cur_op_mode != new_op_mode) {\r
2569                 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
2570                 pmlmepriv->ht_op_mode |= new_op_mode;\r
2571                 op_mode_changes++;\r
2572         }\r
2573 \r
2574         DBG_871X("%s new operation mode=0x%X changes=%d\n",\r
2575                    __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);\r
2576 \r
2577         return op_mode_changes;\r
2578         \r
2579 }\r
2580 \r
2581 #endif /* CONFIG_80211N_HT */\r
2582 \r
2583 void associated_clients_update(_adapter *padapter, u8 updated)\r
2584 {\r
2585         //update associcated stations cap.\r
2586         if(updated == _TRUE)\r
2587         {\r
2588                 _irqL irqL;\r
2589                 _list   *phead, *plist;\r
2590                 struct sta_info *psta=NULL;     \r
2591                 struct sta_priv *pstapriv = &padapter->stapriv;\r
2592                         \r
2593                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2594                 \r
2595                 phead = &pstapriv->asoc_list;\r
2596                 plist = get_next(phead);\r
2597                 \r
2598                 //check asoc_queue\r
2599                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
2600                 {\r
2601                         psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2602                 \r
2603                         plist = get_next(plist);\r
2604 \r
2605                         VCS_update(padapter, psta);             \r
2606                 }\r
2607 \r
2608                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2609 \r
2610         }               \r
2611 \r
2612 }\r
2613 \r
2614 /* called > TSR LEVEL for USB or SDIO Interface*/\r
2615 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)\r
2616 {\r
2617         u8 beacon_updated = _FALSE;\r
2618         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2619         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
2620 \r
2621         \r
2622 #if 0\r
2623         if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&\r
2624             !psta->no_short_preamble_set) {\r
2625                 psta->no_short_preamble_set = 1;\r
2626                 pmlmepriv->num_sta_no_short_preamble++;\r
2627                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2628                      (pmlmepriv->num_sta_no_short_preamble == 1))\r
2629                         ieee802_11_set_beacons(hapd->iface);\r
2630         }\r
2631 #endif\r
2632 \r
2633 \r
2634         if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))    \r
2635         {\r
2636                 if(!psta->no_short_preamble_set)\r
2637                 {\r
2638                         psta->no_short_preamble_set = 1;\r
2639                         \r
2640                         pmlmepriv->num_sta_no_short_preamble++;\r
2641                         \r
2642                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2643                                 (pmlmepriv->num_sta_no_short_preamble == 1))\r
2644                         {\r
2645                                 beacon_updated = _TRUE;\r
2646                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2647                         }       \r
2648                         \r
2649                 }\r
2650         }\r
2651         else\r
2652         {\r
2653                 if(psta->no_short_preamble_set)\r
2654                 {\r
2655                         psta->no_short_preamble_set = 0;\r
2656                         \r
2657                         pmlmepriv->num_sta_no_short_preamble--;\r
2658                         \r
2659                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2660                                 (pmlmepriv->num_sta_no_short_preamble == 0))\r
2661                         {\r
2662                                 beacon_updated = _TRUE;\r
2663                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2664                         }       \r
2665                         \r
2666                 }\r
2667         }\r
2668 \r
2669 #if 0\r
2670         if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {\r
2671                 psta->nonerp_set = 1;\r
2672                 pmlmepriv->num_sta_non_erp++;\r
2673                 if (pmlmepriv->num_sta_non_erp == 1)\r
2674                         ieee802_11_set_beacons(hapd->iface);\r
2675         }\r
2676 #endif\r
2677 \r
2678         if(psta->flags & WLAN_STA_NONERP)\r
2679         {\r
2680                 if(!psta->nonerp_set)\r
2681                 {\r
2682                         psta->nonerp_set = 1;\r
2683                         \r
2684                         pmlmepriv->num_sta_non_erp++;\r
2685                         \r
2686                         if (pmlmepriv->num_sta_non_erp == 1)\r
2687                         {\r
2688                                 beacon_updated = _TRUE;\r
2689                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2690                         }       \r
2691                 }\r
2692                 \r
2693         }\r
2694         else\r
2695         {\r
2696                 if(psta->nonerp_set)\r
2697                 {\r
2698                         psta->nonerp_set = 0;\r
2699                         \r
2700                         pmlmepriv->num_sta_non_erp--;\r
2701                         \r
2702                         if (pmlmepriv->num_sta_non_erp == 0)\r
2703                         {\r
2704                                 beacon_updated = _TRUE;\r
2705                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2706                         }       \r
2707                 }\r
2708                 \r
2709         }\r
2710 \r
2711 \r
2712 #if 0\r
2713         if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&\r
2714             !psta->no_short_slot_time_set) {\r
2715                 psta->no_short_slot_time_set = 1;\r
2716                 pmlmepriv->num_sta_no_short_slot_time++;\r
2717                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2718                     (pmlmepriv->num_sta_no_short_slot_time == 1))\r
2719                         ieee802_11_set_beacons(hapd->iface);\r
2720         }\r
2721 #endif\r
2722 \r
2723         if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))\r
2724         {\r
2725                 if(!psta->no_short_slot_time_set)\r
2726                 {\r
2727                         psta->no_short_slot_time_set = 1;\r
2728                         \r
2729                         pmlmepriv->num_sta_no_short_slot_time++;\r
2730                         \r
2731                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2732                                  (pmlmepriv->num_sta_no_short_slot_time == 1))\r
2733                         {\r
2734                                 beacon_updated = _TRUE;\r
2735                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2736                         }                       \r
2737                         \r
2738                 }\r
2739         }\r
2740         else\r
2741         {\r
2742                 if(psta->no_short_slot_time_set)\r
2743                 {\r
2744                         psta->no_short_slot_time_set = 0;\r
2745                         \r
2746                         pmlmepriv->num_sta_no_short_slot_time--;\r
2747                         \r
2748                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2749                                  (pmlmepriv->num_sta_no_short_slot_time == 0))\r
2750                         {\r
2751                                 beacon_updated = _TRUE;\r
2752                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2753                         }                       \r
2754                 }\r
2755         }       \r
2756         \r
2757 #ifdef CONFIG_80211N_HT\r
2758 \r
2759         if (psta->flags & WLAN_STA_HT) \r
2760         {\r
2761                 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);\r
2762                         \r
2763                 DBG_871X("HT: STA " MAC_FMT " HT Capabilities "\r
2764                            "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);\r
2765 \r
2766                 if (psta->no_ht_set) {\r
2767                         psta->no_ht_set = 0;\r
2768                         pmlmepriv->num_sta_no_ht--;\r
2769                 }\r
2770                 \r
2771                 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {\r
2772                         if (!psta->no_ht_gf_set) {\r
2773                                 psta->no_ht_gf_set = 1;\r
2774                                 pmlmepriv->num_sta_ht_no_gf++;\r
2775                         }\r
2776                         DBG_871X("%s STA " MAC_FMT " - no "\r
2777                                    "greenfield, num of non-gf stations %d\n",\r
2778                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2779                                    pmlmepriv->num_sta_ht_no_gf);\r
2780                 }\r
2781                 \r
2782                 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {\r
2783                         if (!psta->ht_20mhz_set) {\r
2784                                 psta->ht_20mhz_set = 1;\r
2785                                 pmlmepriv->num_sta_ht_20mhz++;\r
2786                         }\r
2787                         DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "\r
2788                                    "num of 20MHz HT STAs %d\n",\r
2789                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2790                                    pmlmepriv->num_sta_ht_20mhz);\r
2791                 }\r
2792                 \r
2793         } \r
2794         else \r
2795         {\r
2796                 if (!psta->no_ht_set) {\r
2797                         psta->no_ht_set = 1;\r
2798                         pmlmepriv->num_sta_no_ht++;\r
2799                 }\r
2800                 if(pmlmepriv->htpriv.ht_option == _TRUE) {              \r
2801                         DBG_871X("%s STA " MAC_FMT\r
2802                                    " - no HT, num of non-HT stations %d\n",\r
2803                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2804                                    pmlmepriv->num_sta_no_ht);\r
2805                 }\r
2806         }\r
2807 \r
2808         if (rtw_ht_operation_update(padapter) > 0)\r
2809         {\r
2810                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
2811                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
2812         }       \r
2813         \r
2814 #endif /* CONFIG_80211N_HT */\r
2815 \r
2816         //update associcated stations cap.\r
2817         associated_clients_update(padapter,  beacon_updated);\r
2818 \r
2819         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
2820 \r
2821 }\r
2822 \r
2823 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)\r
2824 {\r
2825         u8 beacon_updated = _FALSE;\r
2826         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2827         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
2828 \r
2829         if(!psta)\r
2830                 return beacon_updated;\r
2831 \r
2832         if (psta->no_short_preamble_set) {\r
2833                 psta->no_short_preamble_set = 0;\r
2834                 pmlmepriv->num_sta_no_short_preamble--;\r
2835                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
2836                     && pmlmepriv->num_sta_no_short_preamble == 0)\r
2837                 {\r
2838                         beacon_updated = _TRUE;\r
2839                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2840                 }       \r
2841         }       \r
2842 \r
2843         if (psta->nonerp_set) {\r
2844                 psta->nonerp_set = 0;           \r
2845                 pmlmepriv->num_sta_non_erp--;\r
2846                 if (pmlmepriv->num_sta_non_erp == 0)\r
2847                 {\r
2848                         beacon_updated = _TRUE;\r
2849                         update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2850                 }       \r
2851         }\r
2852 \r
2853         if (psta->no_short_slot_time_set) {\r
2854                 psta->no_short_slot_time_set = 0;\r
2855                 pmlmepriv->num_sta_no_short_slot_time--;\r
2856                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
2857                     && pmlmepriv->num_sta_no_short_slot_time == 0)\r
2858                 {\r
2859                         beacon_updated = _TRUE;\r
2860                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2861                 }       \r
2862         }\r
2863         \r
2864 #ifdef CONFIG_80211N_HT\r
2865 \r
2866         if (psta->no_ht_gf_set) {\r
2867                 psta->no_ht_gf_set = 0;\r
2868                 pmlmepriv->num_sta_ht_no_gf--;\r
2869         }\r
2870 \r
2871         if (psta->no_ht_set) {\r
2872                 psta->no_ht_set = 0;\r
2873                 pmlmepriv->num_sta_no_ht--;\r
2874         }\r
2875 \r
2876         if (psta->ht_20mhz_set) {\r
2877                 psta->ht_20mhz_set = 0;\r
2878                 pmlmepriv->num_sta_ht_20mhz--;\r
2879         }\r
2880 \r
2881         if (rtw_ht_operation_update(padapter) > 0)\r
2882         {\r
2883                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
2884                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
2885         }\r
2886         \r
2887 #endif /* CONFIG_80211N_HT */\r
2888 \r
2889         //update associcated stations cap.\r
2890         //associated_clients_update(padapter,  beacon_updated); //move it to avoid deadlock\r
2891 \r
2892         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
2893 \r
2894         return beacon_updated;\r
2895 \r
2896 }\r
2897 \r
2898 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason)\r
2899 {\r
2900         _irqL irqL;\r
2901         u8 beacon_updated = _FALSE;\r
2902         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2903         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2904         struct sta_priv *pstapriv = &padapter->stapriv;\r
2905 \r
2906         if(!psta)\r
2907                 return beacon_updated;\r
2908 \r
2909         if (active == _TRUE)\r
2910         {\r
2911 #ifdef CONFIG_80211N_HT\r
2912                 //tear down Rx AMPDU\r
2913                 send_delba(padapter, 0, psta->hwaddr);// recipient\r
2914         \r
2915                 //tear down TX AMPDU\r
2916                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
2917                 \r
2918 #endif //CONFIG_80211N_HT\r
2919 \r
2920                 issue_deauth(padapter, psta->hwaddr, reason);\r
2921         }\r
2922 \r
2923 #ifdef CONFIG_BEAMFORMING\r
2924         beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->hwaddr, ETH_ALEN, 1);\r
2925 #endif\r
2926 \r
2927         psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
2928         psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
2929 \r
2930 \r
2931         //report_del_sta_event(padapter, psta->hwaddr, reason);\r
2932 \r
2933         //clear cam entry / key\r
2934         rtw_clearstakey_cmd(padapter, psta, _TRUE);\r
2935 \r
2936 \r
2937         _enter_critical_bh(&psta->lock, &irqL);\r
2938         psta->state &= ~_FW_LINKED;\r
2939         _exit_critical_bh(&psta->lock, &irqL);\r
2940 \r
2941         #ifdef CONFIG_IOCTL_CFG80211\r
2942         if (1) {\r
2943                 #ifdef COMPAT_KERNEL_RELEASE\r
2944                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
2945                 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2946                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
2947                 #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2948                 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */\r
2949                 #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2950         } else\r
2951         #endif //CONFIG_IOCTL_CFG80211\r
2952         {\r
2953                 rtw_indicate_sta_disassoc_event(padapter, psta);\r
2954         }\r
2955 \r
2956         report_del_sta_event(padapter, psta->hwaddr, reason);\r
2957 \r
2958         beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);\r
2959 \r
2960         //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                                        \r
2961         rtw_free_stainfo(padapter, psta);\r
2962         //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
2963         \r
2964 \r
2965         return beacon_updated;\r
2966 \r
2967 }\r
2968 \r
2969 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)\r
2970 {\r
2971         _irqL irqL;\r
2972         _list   *phead, *plist;\r
2973         int ret=0;      \r
2974         struct sta_info *psta = NULL;   \r
2975         struct sta_priv *pstapriv = &padapter->stapriv;\r
2976         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2977         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2978         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
2979 \r
2980         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
2981                 return ret;\r
2982 \r
2983         DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",\r
2984                 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);\r
2985 \r
2986         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2987         phead = &pstapriv->asoc_list;\r
2988         plist = get_next(phead);\r
2989         \r
2990         /* for each sta in asoc_queue */\r
2991         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
2992         {               \r
2993                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2994                 plist = get_next(plist);\r
2995 \r
2996                 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);\r
2997                 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);\r
2998         }\r
2999         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3000 \r
3001         issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);\r
3002 \r
3003         return ret;\r
3004 }\r
3005 \r
3006 int rtw_sta_flush(_adapter *padapter)\r
3007 {\r
3008         _irqL irqL;\r
3009         _list   *phead, *plist;\r
3010         int ret=0;      \r
3011         struct sta_info *psta = NULL;   \r
3012         struct sta_priv *pstapriv = &padapter->stapriv;\r
3013         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3014         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3015         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
3016 \r
3017         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
3018                 return ret;\r
3019 \r
3020         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));\r
3021         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3022         phead = &pstapriv->asoc_list;\r
3023         plist = get_next(phead);\r
3024 \r
3025         //free sta asoc_queue\r
3026         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
3027         {\r
3028                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3029                 \r
3030                 plist = get_next(plist);\r
3031 \r
3032                 rtw_list_delete(&psta->asoc_list);\r
3033                 pstapriv->asoc_list_cnt--;\r
3034 \r
3035                 //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3036                 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);\r
3037                 //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3038         }\r
3039         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3040 \r
3041 \r
3042         issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);\r
3043 \r
3044         associated_clients_update(padapter, _TRUE);\r
3045 \r
3046         return ret;\r
3047 \r
3048 }\r
3049 \r
3050 /* called > TSR LEVEL for USB or SDIO Interface*/\r
3051 void sta_info_update(_adapter *padapter, struct sta_info *psta)\r
3052 {       \r
3053         int flags = psta->flags;\r
3054         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3055         \r
3056                                 \r
3057         //update wmm cap.\r
3058         if(WLAN_STA_WME&flags)\r
3059                 psta->qos_option = 1;\r
3060         else\r
3061                 psta->qos_option = 0;\r
3062 \r
3063         if(pmlmepriv->qospriv.qos_option == 0)  \r
3064                 psta->qos_option = 0;\r
3065 \r
3066                 \r
3067 #ifdef CONFIG_80211N_HT         \r
3068         //update 802.11n ht cap.\r
3069         if(WLAN_STA_HT&flags)\r
3070         {\r
3071                 psta->htpriv.ht_option = _TRUE;\r
3072                 psta->qos_option = 1;   \r
3073         }\r
3074         else            \r
3075         {\r
3076                 psta->htpriv.ht_option = _FALSE;\r
3077         }\r
3078                 \r
3079         if(pmlmepriv->htpriv.ht_option == _FALSE)       \r
3080                 psta->htpriv.ht_option = _FALSE;\r
3081 #endif\r
3082 \r
3083 #ifdef CONFIG_80211AC_VHT\r
3084         //update 802.11AC vht cap.\r
3085         if(WLAN_STA_VHT&flags)\r
3086         {\r
3087                 psta->vhtpriv.vht_option = _TRUE;\r
3088         }\r
3089         else            \r
3090         {\r
3091                 psta->vhtpriv.vht_option = _FALSE;\r
3092         }\r
3093 \r
3094         if(pmlmepriv->vhtpriv.vht_option == _FALSE)\r
3095                 psta->vhtpriv.vht_option = _FALSE;\r
3096 #endif  \r
3097 \r
3098 \r
3099         update_sta_info_apmode(padapter, psta);\r
3100                 \r
3101 \r
3102 }\r
3103 \r
3104 /* called >= TSR LEVEL for USB or SDIO Interface*/\r
3105 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)\r
3106 {\r
3107         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3108         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3109 \r
3110         if(psta->state & _FW_LINKED)\r
3111         {\r
3112                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;\r
3113         \r
3114                 //add ratid\r
3115                 add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT\r
3116         }       \r
3117 }\r
3118 /* restore hw setting from sw data structures */\r
3119 void rtw_ap_restore_network(_adapter *padapter)\r
3120 {\r
3121         struct mlme_priv *mlmepriv = &padapter->mlmepriv;\r
3122         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
3123         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3124         struct sta_priv * pstapriv = &padapter->stapriv;\r
3125         struct sta_info *psta;\r
3126         struct security_priv* psecuritypriv=&(padapter->securitypriv);\r
3127         _irqL irqL;\r
3128         _list   *phead, *plist;\r
3129         u8 chk_alive_num = 0;\r
3130         char chk_alive_list[NUM_STA];\r
3131         int i;\r
3132 \r
3133         rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);\r
3134 \r
3135         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);\r
3136 \r
3137         start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);\r
3138 \r
3139         if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
3140                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
3141         {\r
3142                 /* restore group key, WEP keys is restored in ips_leave() */\r
3143                 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);\r
3144         }\r
3145 \r
3146         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3147         \r
3148         phead = &pstapriv->asoc_list;\r
3149         plist = get_next(phead);\r
3150 \r
3151         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {\r
3152                 int stainfo_offset;\r
3153 \r
3154                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3155                 plist = get_next(plist);\r
3156 \r
3157                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
3158                 if (stainfo_offset_valid(stainfo_offset)) {\r
3159                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
3160                 }\r
3161         }\r
3162 \r
3163         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3164 \r
3165         for (i = 0; i < chk_alive_num; i++) {\r
3166                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
3167 \r
3168                 if (psta == NULL) {\r
3169                         DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));\r
3170                 } else if (psta->state &_FW_LINKED) {\r
3171                         rtw_sta_media_status_rpt(padapter, psta, 1);\r
3172                         Update_RA_Entry(padapter, psta);\r
3173                         //pairwise key\r
3174                         /* per sta pairwise key and settings */\r
3175                         if(     (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
3176                                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
3177                         {\r
3178                                 rtw_setstakey_cmd(padapter, psta, UNICAST_KEY,_FALSE);\r
3179                         }                       \r
3180                 }\r
3181         }\r
3182 \r
3183 }\r
3184 \r
3185 void start_ap_mode(_adapter *padapter)\r
3186 {\r
3187         int i;\r
3188         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3189         struct sta_priv *pstapriv = &padapter->stapriv;\r
3190         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3191         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3192         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
3193         \r
3194         pmlmepriv->update_bcn = _FALSE;\r
3195         \r
3196         //init_mlme_ap_info(padapter);\r
3197         pmlmeext->bstart_bss = _FALSE;\r
3198 \r
3199         pmlmepriv->num_sta_non_erp = 0;\r
3200 \r
3201         pmlmepriv->num_sta_no_short_slot_time = 0;\r
3202 \r
3203         pmlmepriv->num_sta_no_short_preamble = 0;\r
3204 \r
3205         pmlmepriv->num_sta_ht_no_gf = 0;\r
3206 #ifdef CONFIG_80211N_HT\r
3207         pmlmepriv->num_sta_no_ht = 0;\r
3208 #endif //CONFIG_80211N_HT\r
3209         pmlmeinfo->HT_info_enable =0;\r
3210         pmlmeinfo->HT_caps_enable=0;\r
3211         pmlmeinfo->HT_enable=0;\r
3212         \r
3213         pmlmepriv->num_sta_ht_20mhz = 0;\r
3214         pmlmepriv->olbc = _FALSE;\r
3215         pmlmepriv->olbc_ht = _FALSE;\r
3216         \r
3217 #ifdef CONFIG_80211N_HT\r
3218         pmlmepriv->ht_op_mode = 0;\r
3219 #endif\r
3220 \r
3221         for(i=0; i<NUM_STA; i++)\r
3222                 pstapriv->sta_aid[i] = NULL;\r
3223 \r
3224 /* to avoid memory leak issue, don't set to NULL directly\r
3225         pmlmepriv->wps_beacon_ie = NULL;        \r
3226         pmlmepriv->wps_probe_resp_ie = NULL;\r
3227         pmlmepriv->wps_assoc_resp_ie = NULL;\r
3228         \r
3229         pmlmepriv->p2p_beacon_ie = NULL;\r
3230         pmlmepriv->p2p_probe_resp_ie = NULL;\r
3231 */\r
3232         \r
3233         //for ACL \r
3234         _rtw_init_listhead(&(pacl_list->acl_node_q.queue));\r
3235         pacl_list->num = 0;\r
3236         pacl_list->mode = 0;\r
3237         for(i = 0; i < NUM_ACL; i++)\r
3238         {               \r
3239                 _rtw_init_listhead(&pacl_list->aclnode[i].list);\r
3240                 pacl_list->aclnode[i].valid = _FALSE;\r
3241         }\r
3242 \r
3243 }\r
3244 \r
3245 void stop_ap_mode(_adapter *padapter)\r
3246 {\r
3247         _irqL irqL;\r
3248         _list   *phead, *plist;\r
3249         struct rtw_wlan_acl_node *paclnode;\r
3250         struct sta_info *psta=NULL;\r
3251         struct sta_priv *pstapriv = &padapter->stapriv;\r
3252         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3253         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;        \r
3254         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
3255         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
3256 \r
3257         pmlmepriv->update_bcn = _FALSE;\r
3258         pmlmeext->bstart_bss = _FALSE;\r
3259         padapter->netif_up = _FALSE;\r
3260         //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);\r
3261         \r
3262         //reset and init security priv , this can refine with rtw_reset_securitypriv\r
3263         _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));\r
3264         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;\r
3265         padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;\r
3266 \r
3267         //for ACL\r
3268         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
3269         phead = get_list_head(pacl_node_q);\r
3270         plist = get_next(phead);                \r
3271         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
3272         {\r
3273                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
3274                 plist = get_next(plist);\r
3275 \r
3276                 if(paclnode->valid == _TRUE)\r
3277                 {\r
3278                         paclnode->valid = _FALSE;\r
3279 \r
3280                         rtw_list_delete(&paclnode->list);\r
3281                                 \r
3282                         pacl_list->num--;               \r
3283                 }               \r
3284         }       \r
3285         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
3286         \r
3287         DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);\r
3288         \r
3289         rtw_sta_flush(padapter);\r
3290 \r
3291         //free_assoc_sta_resources      \r
3292         rtw_free_all_stainfo(padapter);\r
3293         \r
3294         psta = rtw_get_bcmc_stainfo(padapter);\r
3295         //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                \r
3296         rtw_free_stainfo(padapter, psta);\r
3297         //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
3298         \r
3299         rtw_init_bcmc_stainfo(padapter);        \r
3300 \r
3301         rtw_free_mlme_priv_ie_data(pmlmepriv);\r
3302 \r
3303 #ifdef CONFIG_BT_COEXIST\r
3304         rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect \r
3305 #endif  \r
3306 \r
3307 }\r
3308 \r
3309 #endif //CONFIG_NATIVEAP_MLME\r
3310 \r
3311 #ifdef CONFIG_CONCURRENT_MODE\r
3312 void concurrent_set_ap_chbw(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)\r
3313 {\r
3314         u8 *p;\r
3315         int     ie_len=0;\r
3316         u8 cur_channel, cur_bwmode, cur_ch_offset, change_band;\r
3317         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3318         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
3319         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
3320         struct HT_info_element *pht_info=NULL;\r
3321         \r
3322         cur_channel = channel;\r
3323         cur_bwmode = bwmode;\r
3324         cur_ch_offset = channel_offset;\r
3325         change_band = _FALSE;\r
3326         \r
3327         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3328         if( p && ie_len)\r
3329         {\r
3330                 pht_info = (struct HT_info_element *)(p+2);\r
3331         }\r
3332 \r
3333         \r
3334         if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))\r
3335         {\r
3336                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3337         }\r
3338         else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)\r
3339         {\r
3340                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;            \r
3341                 struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;\r
3342 \r
3343                 //To sync cur_channel/cur_bwmode/cur_ch_offset with buddy adapter\r
3344                 DBG_871X(ADPT_FMT" is at linked state\n", ADPT_ARG(pbuddy_adapter));\r
3345                 DBG_871X(ADPT_FMT": CH=%d, BW=%d, offset=%d\n", ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);\r
3346                 DBG_871X(ADPT_FMT": CH=%d, BW=%d, offset=%d\n", ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);\r
3347 \r
3348                 if((cur_channel <= 14 && pbuddy_mlmeext->cur_channel >= 36) ||\r
3349                         (cur_channel >= 36 && pbuddy_mlmeext->cur_channel <= 14))\r
3350                         change_band = _TRUE;\r
3351 \r
3352                 cur_channel = pbuddy_mlmeext->cur_channel;\r
3353 \r
3354 #ifdef CONFIG_80211AC_VHT\r
3355                 if(cur_bwmode == CHANNEL_WIDTH_80)\r
3356                 {\r
3357                         u8 *pvht_cap_ie, *pvht_op_ie;\r
3358                         int vht_cap_ielen, vht_op_ielen;\r
3359                         \r
3360                         pvht_cap_ie = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3361                         pvht_op_ie = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3362                                                 \r
3363                         if(pbuddy_mlmeext->cur_channel <= 14) // downgrade to 20/40Mhz\r
3364                         {\r
3365                                 //modify vht cap ie\r
3366                                 if( pvht_cap_ie && vht_cap_ielen)\r
3367                                 {\r
3368                                         SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvht_cap_ie+2, 0);\r
3369                                 }\r
3370                                 \r
3371                                 //modify vht op ie\r
3372                                 if( pvht_op_ie && vht_op_ielen)\r
3373                                 {\r
3374                                         SET_VHT_OPERATION_ELE_CHL_WIDTH(pvht_op_ie+2, 0); //change to 20/40Mhz\r
3375                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, 0);\r
3376                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pvht_op_ie+2, 0);\r
3377                                         //SET_VHT_OPERATION_ELE_BASIC_MCS_SET(p+2, 0xFFFF);                                     \r
3378                                         cur_bwmode = CHANNEL_WIDTH_40;\r
3379                                 }               \r
3380                         }\r
3381                         else\r
3382                         {\r
3383                                 u8      center_freq;\r
3384                                 \r
3385                                 cur_bwmode = CHANNEL_WIDTH_80;\r
3386                                 \r
3387                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||\r
3388                                         pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)\r
3389                                 {\r
3390                                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;\r
3391                                 }\r
3392                                 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)\r
3393                                 {\r
3394                                         cur_ch_offset =  rtw_get_offset_by_ch(cur_channel);\r
3395                                 }       \r
3396 \r
3397                                 //modify ht info ie\r
3398                                 if(pht_info)\r
3399                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3400                                 \r
3401                                 switch(cur_ch_offset)\r
3402                                 {\r
3403                                         case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3404                                                 if(pht_info)\r
3405                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            \r
3406                                                 //cur_bwmode = CHANNEL_WIDTH_40;\r
3407                                                 break;\r
3408                                         case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3409                                                 if(pht_info)\r
3410                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            \r
3411                                                 //cur_bwmode = CHANNEL_WIDTH_40;\r
3412                                                 break;\r
3413                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3414                                         default:\r
3415                                                 if(pht_info)\r
3416                                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3417                                                 cur_bwmode = CHANNEL_WIDTH_20;\r
3418                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
3419                                                 break;                                  \r
3420                                 }\r
3421 \r
3422                                 //modify vht op ie\r
3423                                 center_freq = rtw_get_center_ch(cur_channel, cur_bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);\r
3424                                 if( pvht_op_ie && vht_op_ielen)\r
3425                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, center_freq);\r
3426 \r
3427                                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3428                                 \r
3429                         }\r
3430                         \r
3431                 }\r
3432 #endif //CONFIG_80211AC_VHT\r
3433 \r
3434                 if(cur_bwmode == CHANNEL_WIDTH_40)\r
3435                 {\r
3436                         if(pht_info)\r
3437                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3438                         \r
3439                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||\r
3440                                 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)\r
3441                         {\r
3442                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;\r
3443 \r
3444                                 //to update cur_ch_offset value in beacon\r
3445                                 if(pht_info)\r
3446                                 {                               \r
3447                                         switch(cur_ch_offset)\r
3448                                         {\r
3449                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3450                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;\r
3451                                                         break;\r
3452                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3453                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;\r
3454                                                         break;\r
3455                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3456                                                 default:                                                        \r
3457                                                         break;                                  \r
3458                                         }\r
3459                                 }               \r
3460                                 \r
3461                         }\r
3462                         else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)\r
3463                         {\r
3464                                 cur_ch_offset =  rtw_get_offset_by_ch(cur_channel);\r
3465 \r
3466                                 switch(cur_ch_offset)\r
3467                                 {\r
3468                                         case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3469                                                 if(pht_info)\r
3470                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            \r
3471                                                 cur_bwmode = CHANNEL_WIDTH_40;\r
3472                                                 break;\r
3473                                         case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3474                                                 if(pht_info)\r
3475                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            \r
3476                                                 cur_bwmode = CHANNEL_WIDTH_40;\r
3477                                                 break;\r
3478                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3479                                         default:\r
3480                                                 if(pht_info)\r
3481                                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3482                                                 cur_bwmode = CHANNEL_WIDTH_20;\r
3483                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
3484                                                 break;                                  \r
3485                                 }                                               \r
3486                                 \r
3487                         }\r
3488 \r
3489                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3490                         \r
3491                 }\r
3492                 else\r
3493                 {\r
3494                         set_channel_bwmode(padapter, cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);\r
3495                 }               \r
3496 \r
3497                 // to update channel value in beacon\r
3498                 pnetwork->Configuration.DSConfig = cur_channel;         \r
3499                 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3500                 if(p && ie_len>0)\r
3501                         *(p + 2) = cur_channel;\r
3502                 \r
3503                 if(pht_info)\r
3504                         pht_info->primary_channel = cur_channel;\r
3505         }\r
3506 \r
3507         DBG_871X(FUNC_ADPT_FMT" CH=%d, BW=%d, offset=%d\n", FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);\r
3508 \r
3509         pmlmeext->cur_channel = cur_channel;    \r
3510         pmlmeext->cur_bwmode = cur_bwmode;\r
3511         pmlmeext->cur_ch_offset = cur_ch_offset;\r
3512 \r
3513         //buddy interface band is different from current interface, update ERP, support rate, ext support rate IE\r
3514         if(change_band == _TRUE)\r
3515                 change_band_update_ie(padapter, pnetwork);\r
3516 \r
3517 }\r
3518 #endif //CONFIG_CONCURRENT_MODE\r
3519 \r
3520 #endif //CONFIG_AP_MODE\r
3521 \r