net: wireless: rockchip_wlan: add rtl8188eu support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8188eu / 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, _TRUE);\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 /*\r
92         //DBG_871X("%s\n", __FUNCTION__);\r
93         \r
94         //update TIM IE\r
95         //if(pstapriv->tim_bitmap)\r
96 */\r
97         if (_TRUE) {\r
98                 u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;\r
99                 u16 tim_bitmap_le;\r
100                 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;        \r
101         \r
102                 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);\r
103 \r
104                 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);\r
105                 if (p != NULL && tim_ielen > 0) {\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                 } else {\r
117                         tim_ielen = 0;\r
118 \r
119                         /*calculate head_len*/\r
120                         offset = _FIXED_IE_LENGTH_;\r
121 \r
122                         /* get ssid_ie len */\r
123                         p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));\r
124                         if (p != NULL)\r
125                                 offset += tmp_len+2;\r
126 \r
127                         /*get supported rates len*/\r
128                         p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));     \r
129                         if (p !=  NULL) \r
130                         {                       \r
131                                 offset += tmp_len+2;\r
132                         }\r
133 \r
134                         /*DS Parameter Set IE, len=3*/\r
135                         offset += 3;\r
136 \r
137                         premainder_ie = pie + offset;\r
138 \r
139                         remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;      \r
140 \r
141                         /*append TIM IE from offset*/\r
142                         dst_ie = pie + offset;\r
143                         \r
144                 }\r
145                 \r
146                 if (remainder_ielen > 0) {\r
147                         pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
148                         if(pbackup_remainder_ie && premainder_ie)\r
149                                 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
150                 }               \r
151                 \r
152                 *dst_ie++=_TIM_IE_;\r
153 \r
154                 if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))                     \r
155                         tim_ielen = 5;\r
156                 else\r
157                         tim_ielen = 4;\r
158 \r
159                 *dst_ie++ = tim_ielen;\r
160                 \r
161                 *dst_ie++ = 0;/*DTIM count*/\r
162                 *dst_ie++ = 1;/*DTIM period*/\r
163                 \r
164                 if (pstapriv->tim_bitmap & BIT(0))/*for bc/mc frames*/\r
165                         *dst_ie++ = BIT(0);/*bitmap ctrl */\r
166                 else\r
167                         *dst_ie++ = 0;\r
168 \r
169                 if (tim_ielen == 4) {\r
170                         u8 pvb = 0;\r
171                         \r
172                         if (pstapriv->tim_bitmap & 0x00fe)\r
173                                 pvb = (u8)tim_bitmap_le;\r
174                         else if (pstapriv->tim_bitmap & 0xff00)                 \r
175                                 pvb = (u8)(tim_bitmap_le >> 8);\r
176                         else\r
177                                 pvb = (u8)tim_bitmap_le;\r
178 \r
179                         *dst_ie++ = pvb;\r
180                         \r
181                 } else if (tim_ielen == 5) {\r
182                         _rtw_memcpy(dst_ie, &tim_bitmap_le, 2);\r
183                         dst_ie += 2;                            \r
184                 }       \r
185                 \r
186                 /*copy remainder IE*/\r
187                 if (pbackup_remainder_ie) {\r
188                         _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
189 \r
190                         rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
191                 }       \r
192 \r
193                 offset =  (uint)(dst_ie - pie);\r
194                 pnetwork_mlmeext->IELength = offset + remainder_ielen;\r
195         \r
196         }\r
197 }\r
198 \r
199 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)\r
200 {\r
201         PNDIS_802_11_VARIABLE_IEs       pIE;\r
202         u8      bmatch = _FALSE;\r
203         u8      *pie = pnetwork->IEs;\r
204         u8      *p=NULL, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
205         u32     i, offset, ielen, ie_offset, remainder_ielen = 0;\r
206 \r
207         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)\r
208         {\r
209                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);\r
210 \r
211                 if (pIE->ElementID > index)\r
212                 {\r
213                         break;\r
214                 }\r
215                 else if(pIE->ElementID == index) // already exist the same IE\r
216                 {\r
217                         p = (u8 *)pIE;\r
218                         ielen = pIE->Length;\r
219                         bmatch = _TRUE;\r
220                         break;\r
221                 }\r
222 \r
223                 p = (u8 *)pIE;\r
224                 ielen = pIE->Length;\r
225                 i += (pIE->Length + 2);\r
226         }\r
227 \r
228         if (p != NULL && ielen>0)\r
229         {\r
230                 ielen += 2;\r
231                 \r
232                 premainder_ie = p+ielen;\r
233 \r
234                 ie_offset = (sint)(p -pie);\r
235                 \r
236                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
237 \r
238                 if(bmatch)\r
239                         dst_ie = p;\r
240                 else\r
241                         dst_ie = (p+ielen);\r
242         }\r
243 \r
244         if(dst_ie == NULL)\r
245                 return;\r
246 \r
247         if(remainder_ielen>0)\r
248         {\r
249                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
250                 if(pbackup_remainder_ie && premainder_ie)\r
251                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
252         }\r
253 \r
254         *dst_ie++=index;\r
255         *dst_ie++=len;\r
256 \r
257         _rtw_memcpy(dst_ie, data, len);\r
258         dst_ie+=len;\r
259 \r
260         //copy remainder IE\r
261         if(pbackup_remainder_ie)\r
262         {\r
263                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
264 \r
265                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
266         }\r
267 \r
268         offset =  (uint)(dst_ie - pie);\r
269         pnetwork->IELength = offset + remainder_ielen;\r
270 }\r
271 \r
272 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)\r
273 {\r
274         u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
275         uint offset, ielen, ie_offset, remainder_ielen = 0;\r
276         u8      *pie = pnetwork->IEs;\r
277 \r
278         p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);\r
279         if (p != NULL && ielen>0)\r
280         {\r
281                 ielen += 2;\r
282                 \r
283                 premainder_ie = p+ielen;\r
284 \r
285                 ie_offset = (sint)(p -pie);\r
286                 \r
287                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
288 \r
289                 dst_ie = p;\r
290         }\r
291         else {\r
292                 return;\r
293         }\r
294 \r
295         if(remainder_ielen>0)\r
296         {\r
297                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
298                 if(pbackup_remainder_ie && premainder_ie)\r
299                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
300         }\r
301 \r
302         //copy remainder IE\r
303         if(pbackup_remainder_ie)\r
304         {\r
305                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
306 \r
307                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
308         }\r
309 \r
310         offset =  (uint)(dst_ie - pie);\r
311         pnetwork->IELength = offset + remainder_ielen;\r
312 }\r
313 \r
314 \r
315 u8 chk_sta_is_alive(struct sta_info *psta);\r
316 u8 chk_sta_is_alive(struct sta_info *psta)\r
317 {\r
318         u8 ret = _FALSE;\r
319         #ifdef DBG_EXPIRATION_CHK\r
320         DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"\r
321                 , MAC_ARG(psta->hwaddr)\r
322                 , psta->rssi_stat.UndecoratedSmoothedPWDB\r
323                 //, STA_RX_PKTS_ARG(psta)\r
324                 , STA_RX_PKTS_DIFF_ARG(psta)\r
325                 , psta->expire_to\r
326                 , psta->state&WIFI_SLEEP_STATE?"PS, ":""\r
327                 , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""\r
328                 , psta->sleepq_len\r
329         );\r
330         #endif\r
331 \r
332         //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))\r
333         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
334         {\r
335                 #if 0\r
336                 if(psta->state&WIFI_SLEEP_STATE)\r
337                         ret = _TRUE;\r
338                 #endif\r
339         }\r
340         else\r
341         {\r
342                 ret = _TRUE;\r
343         }\r
344 \r
345         sta_update_last_rx_pkts(psta);\r
346 \r
347         return ret;\r
348 }\r
349 \r
350 void    expire_timeout_chk(_adapter *padapter)\r
351 {\r
352         _irqL irqL;\r
353         _list   *phead, *plist;\r
354         u8 updated = _FALSE;\r
355         struct sta_info *psta=NULL;     \r
356         struct sta_priv *pstapriv = &padapter->stapriv;\r
357         u8 chk_alive_num = 0;\r
358         char chk_alive_list[NUM_STA];\r
359         int i;\r
360 \r
361 \r
362         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
363         \r
364         phead = &pstapriv->auth_list;\r
365         plist = get_next(phead);\r
366         \r
367         //check auth_queue\r
368         #ifdef DBG_EXPIRATION_CHK\r
369         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
370                 DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"\r
371                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);\r
372         }\r
373         #endif\r
374         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
375         {\r
376                 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);\r
377 \r
378                 plist = get_next(plist);\r
379 \r
380 \r
381 #ifdef CONFIG_ATMEL_RC_PATCH\r
382                 if (_TRUE == _rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->hwaddr), ETH_ALEN))\r
383                         continue;\r
384                 if (psta->flag_atmel_rc)\r
385                         continue;\r
386 #endif\r
387                 if(psta->expire_to>0)\r
388                 {\r
389                         psta->expire_to--;\r
390                         if (psta->expire_to == 0)\r
391                         {\r
392                                 rtw_list_delete(&psta->auth_list);\r
393                                 pstapriv->auth_list_cnt--;\r
394                                 \r
395                                 DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",\r
396                                         psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);\r
397                                 \r
398                                 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
399                                 \r
400                                 //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);        \r
401                                 rtw_free_stainfo(padapter, psta);\r
402                                 //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); \r
403                                 \r
404                                 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
405                         }       \r
406                 }       \r
407                 \r
408         }\r
409 \r
410         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
411         psta = NULL;\r
412         \r
413 \r
414         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
415         \r
416         phead = &pstapriv->asoc_list;\r
417         plist = get_next(phead);\r
418 \r
419         //check asoc_queue\r
420         #ifdef DBG_EXPIRATION_CHK\r
421         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
422                 DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"\r
423                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);\r
424         }\r
425         #endif\r
426         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
427         {\r
428                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
429                 plist = get_next(plist);\r
430 #ifdef CONFIG_ATMEL_RC_PATCH\r
431                 DBG_871X("%s:%d  psta=%p, %02x,%02x||%02x,%02x  \n\n", __func__,  __LINE__,\r
432                         psta,pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->hwaddr[0], psta->hwaddr[5]);\r
433                 if (_TRUE == _rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->hwaddr), ETH_ALEN))\r
434                         continue;               \r
435                 if (psta->flag_atmel_rc)\r
436                         continue;\r
437                 DBG_871X("%s: debug line:%d \n", __func__, __LINE__);\r
438 #endif\r
439 #ifdef CONFIG_AUTO_AP_MODE\r
440                 if(psta->isrc)\r
441                         continue;\r
442 #endif\r
443                 if (chk_sta_is_alive(psta) || !psta->expire_to) {\r
444                         psta->expire_to = pstapriv->expire_to;\r
445                         psta->keep_alive_trycnt = 0;\r
446                         #ifdef CONFIG_TX_MCAST2UNI\r
447                         psta->under_exist_checking = 0;\r
448                         #endif  // CONFIG_TX_MCAST2UNI\r
449                 } else {\r
450                         psta->expire_to--;\r
451                 }\r
452 \r
453 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
454 #ifdef CONFIG_80211N_HT\r
455 #ifdef CONFIG_TX_MCAST2UNI\r
456                 if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {\r
457                         // check sta by delba(addba) for 11n STA \r
458                         // ToDo: use CCX report to check for all STAs\r
459                         //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
460                         \r
461                                 if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {\r
462                                 DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
463                                 psta->under_exist_checking = 0;\r
464                                 psta->expire_to = 0;\r
465                         } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {\r
466                                 DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
467                                 psta->under_exist_checking = 1;\r
468                                 //tear down TX AMPDU\r
469                                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
470                                 psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
471                                 psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
472                         }\r
473                 }\r
474 #endif //CONFIG_TX_MCAST2UNI\r
475 #endif //CONFIG_80211N_HT\r
476 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
477 \r
478                 if (psta->expire_to <= 0)\r
479                 {\r
480                         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
481 \r
482                         if (padapter->registrypriv.wifi_spec == 1)\r
483                         {\r
484                                 psta->expire_to = pstapriv->expire_to;\r
485                                 continue;\r
486                         }\r
487 \r
488 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
489 #ifdef CONFIG_80211N_HT\r
490 \r
491 #define KEEP_ALIVE_TRYCNT (3)\r
492 \r
493                         if(psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT)\r
494                         {                               \r
495                                 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
496                                         psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
497                                 else\r
498                                         psta->keep_alive_trycnt = 0;\r
499                                 \r
500                         }\r
501                         else if((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
502                         {\r
503                                 psta->keep_alive_trycnt = 0;\r
504                         }                       \r
505                         if((psta->htpriv.ht_option==_TRUE) && (psta->htpriv.ampdu_enable==_TRUE)) \r
506                         {\r
507                                 uint priority = 1; //test using BK\r
508                                 u8 issued=0;                            \r
509                 \r
510                                 //issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1;\r
511                                 issued |= (psta->htpriv.candidate_tid_bitmap>>priority)&0x1;\r
512 \r
513                                 if(0==issued)\r
514                                 {\r
515                                         if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
516                                         {\r
517                                                 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);\r
518 \r
519                                                 if (psta->state & WIFI_SLEEP_STATE) \r
520                                                         psta->expire_to = 2; // 2x2=4 sec\r
521                                                 else\r
522                                                         psta->expire_to = 1; // 2 sec\r
523                                         \r
524                                                 psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
525                                         \r
526                                                 //add_ba_hdl(padapter, (u8*)paddbareq_parm);\r
527 \r
528                                                 DBG_871X("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
529 \r
530                                                 issue_addba_req(padapter, psta->hwaddr, (u8)priority);\r
531                 \r
532                                                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);\r
533                                                 \r
534                                                 psta->keep_alive_trycnt++;                                              \r
535 \r
536                                                 continue;\r
537                                         }                       \r
538                                 }                                       \r
539                         }\r
540                         if(psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
541                         {\r
542                                 psta->keep_alive_trycnt = 0;\r
543                                 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
544                                 DBG_871X("change to another methods to check alive if staion is at ps mode\n");\r
545                         }       \r
546                         \r
547 #endif //CONFIG_80211N_HT\r
548 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK \r
549                         if (psta->state & WIFI_SLEEP_STATE) {\r
550                                 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {\r
551                                         //to check if alive by another methods if staion is at ps mode.                                 \r
552                                         psta->expire_to = pstapriv->expire_to;\r
553                                         psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
554 \r
555                                         //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));\r
556 \r
557                                         //to update bcn with tim_bitmap for this station\r
558                                         pstapriv->tim_bitmap |= BIT(psta->aid);\r
559                                         update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
560 \r
561                                         if(!pmlmeext->active_keep_alive_check)\r
562                                                 continue;\r
563                                 }\r
564                         }\r
565                         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
566                         if (pmlmeext->active_keep_alive_check) {\r
567                                 int stainfo_offset;\r
568 \r
569                                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
570                                 if (stainfo_offset_valid(stainfo_offset)) {\r
571                                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
572                                 }\r
573 \r
574                                 continue;\r
575                         }\r
576                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
577                         rtw_list_delete(&psta->asoc_list);\r
578                         pstapriv->asoc_list_cnt--;\r
579                         DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
580                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);\r
581                 }       \r
582                 else\r
583                 {\r
584                         /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */\r
585                         if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)\r
586                                 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)\r
587                         ){\r
588                                 DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__\r
589                                         , MAC_ARG(psta->hwaddr)\r
590                                         , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);\r
591                                 wakeup_sta_to_xmit(padapter, psta);\r
592                         }\r
593                 }\r
594         }\r
595 \r
596         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
597 \r
598 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
599 if (chk_alive_num) {\r
600 \r
601         u8 backup_oper_channel=0;\r
602         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
603         /* switch to correct channel of current network  before issue keep-alive frames */\r
604         if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {\r
605                 backup_oper_channel = rtw_get_oper_ch(padapter);\r
606                 SelectChannel(padapter, pmlmeext->cur_channel);\r
607         }\r
608 \r
609         /* issue null data to check sta alive*/\r
610         for (i = 0; i < chk_alive_num; i++) {\r
611                 int ret = _FAIL;\r
612 \r
613                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
614 #ifdef CONFIG_ATMEL_RC_PATCH\r
615                 if (_TRUE == _rtw_memcmp(  pstapriv->atmel_rc_pattern, psta->hwaddr, ETH_ALEN))\r
616                         continue;\r
617                 if (psta->flag_atmel_rc)\r
618                         continue;\r
619 #endif\r
620                 if(!(psta->state &_FW_LINKED))\r
621                         continue;               \r
622         \r
623                 if (psta->state & WIFI_SLEEP_STATE)\r
624                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);\r
625                 else\r
626                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);\r
627 \r
628                 psta->keep_alive_trycnt++;\r
629                 if (ret == _SUCCESS)\r
630                 {\r
631                         DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));\r
632                         psta->expire_to = pstapriv->expire_to;\r
633                         psta->keep_alive_trycnt = 0;\r
634                         continue;\r
635                 }\r
636                 else if (psta->keep_alive_trycnt <= 3)\r
637                 {\r
638                         DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
639                         psta->expire_to = 1;\r
640                         continue;\r
641                 }\r
642 \r
643                 psta->keep_alive_trycnt = 0;\r
644                 DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
645                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
646                 if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {\r
647                         rtw_list_delete(&psta->asoc_list);\r
648                         pstapriv->asoc_list_cnt--;\r
649                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);\r
650                 }\r
651                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
652 \r
653         }\r
654 \r
655         if (backup_oper_channel>0) /* back to the original operation channel */\r
656                 SelectChannel(padapter, backup_oper_channel);\r
657 }\r
658 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
659 \r
660         associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);\r
661 }\r
662 \r
663 void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)\r
664 {       \r
665         int i;\r
666         u8 rf_type;\r
667         unsigned char sta_band = 0, shortGIrate = _FALSE;\r
668         u64 tx_ra_bitmap = 0;\r
669         struct ht_priv  *psta_ht = NULL;\r
670         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
671         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
672 \r
673 #ifdef CONFIG_80211N_HT\r
674         if(psta)\r
675                 psta_ht = &psta->htpriv;\r
676         else\r
677                 return;\r
678 #endif //CONFIG_80211N_HT\r
679 \r
680         if(!(psta->state & _FW_LINKED))\r
681                 return;\r
682 \r
683 #if 0//gtest\r
684         if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)\r
685         {\r
686                 //is this a 2r STA?\r
687                 if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))\r
688                 {\r
689                         priv->pshare->has_2r_sta |= BIT(pstat->aid);\r
690                         if(rtw_read16(padapter, 0x102501f6) != 0xffff)\r
691                         {\r
692                                 rtw_write16(padapter, 0x102501f6, 0xffff);\r
693                                 reset_1r_sta_RA(priv, 0xffff);\r
694                                 Switch_1SS_Antenna(priv, 3);\r
695                         }\r
696                 }\r
697                 else// bg or 1R STA? \r
698                 { \r
699                         if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)\r
700                         {\r
701                                 if(rtw_read16(padapter, 0x102501f6) != 0x7777)\r
702                                 { // MCS7 SGI\r
703                                         rtw_write16(padapter, 0x102501f6,0x7777);\r
704                                         reset_1r_sta_RA(priv, 0x7777);\r
705                                         Switch_1SS_Antenna(priv, 2);\r
706                                 }\r
707                         }\r
708                 }\r
709                 \r
710         }\r
711 \r
712         if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) \r
713         {\r
714                 if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)\r
715                         pstat->rssi_level = 1;\r
716                 else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||\r
717                         ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&\r
718                         (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&\r
719                         (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))\r
720                         pstat->rssi_level = 2;\r
721                 else\r
722                         pstat->rssi_level = 3;\r
723         }\r
724 \r
725         // rate adaptive by rssi\r
726         if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)\r
727         {\r
728                 if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))\r
729                 {\r
730                         switch (pstat->rssi_level) {\r
731                                 case 1:\r
732                                         pstat->tx_ra_bitmap &= 0x100f0000;\r
733                                         break;\r
734                                 case 2:\r
735                                         pstat->tx_ra_bitmap &= 0x100ff000;\r
736                                         break;\r
737                                 case 3:\r
738                                         if (priv->pshare->is_40m_bw)\r
739                                                 pstat->tx_ra_bitmap &= 0x100ff005;\r
740                                         else\r
741                                                 pstat->tx_ra_bitmap &= 0x100ff001;\r
742 \r
743                                         break;\r
744                         }\r
745                 }\r
746                 else \r
747                 {\r
748                         switch (pstat->rssi_level) {\r
749                                 case 1:\r
750                                         pstat->tx_ra_bitmap &= 0x1f0f0000;\r
751                                         break;\r
752                                 case 2:\r
753                                         pstat->tx_ra_bitmap &= 0x1f0ff000;\r
754                                         break;\r
755                                 case 3:\r
756                                         if (priv->pshare->is_40m_bw)\r
757                                                 pstat->tx_ra_bitmap &= 0x000ff005;\r
758                                         else\r
759                                                 pstat->tx_ra_bitmap &= 0x000ff001;\r
760 \r
761                                         break;\r
762                         }\r
763 \r
764                         // Don't need to mask high rates due to new rate adaptive parameters\r
765                         //if (pstat->is_broadcom_sta)           // use MCS12 as the highest rate vs. Broadcom sta\r
766                         //      pstat->tx_ra_bitmap &= 0x81ffffff;\r
767 \r
768                         // NIC driver will report not supporting MCS15 and MCS14 in asoc req\r
769                         //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)\r
770                         //      pstat->tx_ra_bitmap &= 0x83ffffff;              // if Realtek 1x2 sta, don't use MCS15 and MCS14\r
771                 }\r
772         }\r
773         else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))\r
774         {\r
775                 switch (pstat->rssi_level) {\r
776                         case 1:\r
777                                 pstat->tx_ra_bitmap &= 0x00000f00;\r
778                                 break;\r
779                         case 2:\r
780                                 pstat->tx_ra_bitmap &= 0x00000ff0;\r
781                                 break;\r
782                         case 3:\r
783                                 pstat->tx_ra_bitmap &= 0x00000ff5;\r
784                                 break;\r
785                 }\r
786         }\r
787         else \r
788         {\r
789                 pstat->tx_ra_bitmap &= 0x0000000d;\r
790         }\r
791 \r
792         // disable tx short GI when station cannot rx MCS15(AP is 2T2R)\r
793         // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)\r
794         // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate\r
795         if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||\r
796                  (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))\r
797         {\r
798                 pstat->tx_ra_bitmap &= ~BIT(28);        \r
799         }\r
800 #endif\r
801 \r
802         rtw_hal_update_sta_rate_mask(padapter, psta);\r
803         tx_ra_bitmap = psta->ra_mask;\r
804 \r
805         shortGIrate = query_ra_short_GI(psta);\r
806 \r
807         if ( pcur_network->Configuration.DSConfig > 14 ) {\r
808                 \r
809                 if (tx_ra_bitmap & 0xffff000)\r
810                         sta_band |= WIRELESS_11_5N ;\r
811 \r
812                 if (tx_ra_bitmap & 0xff0)\r
813                         sta_band |= WIRELESS_11A;\r
814 \r
815                 // 5G band\r
816                 #ifdef CONFIG_80211AC_VHT\r
817                 if (psta->vhtpriv.vht_option)  {\r
818                         sta_band = WIRELESS_11_5AC;\r
819                 }               \r
820                 #endif\r
821                 \r
822         } else {\r
823                 if (tx_ra_bitmap & 0xffff000)\r
824                         sta_band |= WIRELESS_11_24N;\r
825 \r
826                 if (tx_ra_bitmap & 0xff0)\r
827                         sta_band |= WIRELESS_11G;\r
828 \r
829                 if (tx_ra_bitmap & 0x0f)\r
830                         sta_band |= WIRELESS_11B;\r
831         }\r
832 \r
833         psta->wireless_mode = sta_band;\r
834         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);\r
835         \r
836         if (psta->aid < NUM_STA)\r
837         {\r
838                 u8      arg[4] = {0};\r
839 \r
840                 arg[0] = psta->mac_id;\r
841                 arg[1] = psta->raid;\r
842                 arg[2] = shortGIrate;\r
843                 arg[3] = psta->init_rate;\r
844 \r
845                 DBG_871X("%s=> mac_id:%d , raid:%d , shortGIrate=%d, tx_ra_bitmap:0x%016llx, networkType:0x%02x\n", \r
846                         __FUNCTION__, psta->mac_id, psta->raid, shortGIrate, tx_ra_bitmap, psta->wireless_mode);\r
847                         \r
848                 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);\r
849         }\r
850         else \r
851         {\r
852                 DBG_871X("station aid %d exceed the max number\n", psta->aid);\r
853         }\r
854 \r
855 }\r
856 \r
857 void update_bmc_sta(_adapter *padapter)\r
858 {\r
859         _irqL   irqL;\r
860         unsigned char   network_type;\r
861         int supportRateNum = 0;\r
862         u64 tx_ra_bitmap = 0;\r
863         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
864         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
865         struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);\r
866 \r
867         if(psta)\r
868         {\r
869                 psta->aid = 0;//default set to 0\r
870                 psta->qos_option = 0;\r
871 #ifdef CONFIG_80211N_HT \r
872                 psta->htpriv.ht_option = _FALSE;\r
873 #endif //CONFIG_80211N_HT\r
874 \r
875                 psta->ieee8021x_blocked = 0;\r
876 \r
877                 _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
878 \r
879                 //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.\r
880 \r
881                 //prepare for add_RATid         \r
882                 supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);\r
883                 network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);\r
884                 if (IsSupportedTxCCK(network_type)) {\r
885                         network_type = WIRELESS_11B;\r
886                 }\r
887                 else if (network_type == WIRELESS_INVALID) { // error handling\r
888                         if ( pcur_network->Configuration.DSConfig > 14 )\r
889                                 network_type = WIRELESS_11A;\r
890                         else\r
891                                 network_type = WIRELESS_11B;\r
892                 }\r
893                 update_sta_basic_rate(psta, network_type);\r
894                 psta->wireless_mode = network_type;\r
895 \r
896                 rtw_hal_update_sta_rate_mask(padapter, psta);\r
897                 tx_ra_bitmap = psta->ra_mask;\r
898 \r
899                 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);\r
900 \r
901                 //if(pHalData->fw_ractrl == _TRUE)\r
902                 {\r
903                         u8      arg[4] = {0};\r
904 \r
905                         arg[0] = psta->mac_id;\r
906                         arg[1] = psta->raid;\r
907                         arg[2] = 0;\r
908                         arg[3] = psta->init_rate;\r
909 \r
910                         DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%016llx\n", \r
911                                 __FUNCTION__ , psta->mac_id, psta->raid , tx_ra_bitmap);\r
912 \r
913                         rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);\r
914                 }\r
915 \r
916                 rtw_sta_media_status_rpt(padapter, psta, 1);\r
917 \r
918                 _enter_critical_bh(&psta->lock, &irqL);\r
919                 psta->state = _FW_LINKED;\r
920                 _exit_critical_bh(&psta->lock, &irqL);\r
921 \r
922         }\r
923         else\r
924         {\r
925                 DBG_871X("add_RATid_bmc_sta error!\n");\r
926         }\r
927                 \r
928 }\r
929 \r
930 //notes:\r
931 //AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode \r
932 //MAC_ID = AID+1 for sta in ap/adhoc mode \r
933 //MAC_ID = 1 for bc/mc for sta/ap/adhoc\r
934 //MAC_ID = 0 for bssid for sta/ap/adhoc\r
935 //CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;\r
936 \r
937 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)\r
938 {       \r
939         _irqL   irqL;\r
940         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
941         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
942         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
943 #ifdef CONFIG_80211N_HT\r
944         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
945         struct ht_priv  *phtpriv_sta = &psta->htpriv;\r
946 #endif //CONFIG_80211N_HT\r
947         u8      cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;\r
948         //set intf_tag to if1\r
949         //psta->intf_tag = 0;\r
950 \r
951         DBG_871X("%s\n",__FUNCTION__);\r
952 \r
953         //psta->mac_id = psta->aid+4;\r
954         //psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(),\r
955                                                        //release macid when call rtw_free_stainfo()\r
956 \r
957         //ap mode\r
958         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);\r
959         \r
960         if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\r
961                 psta->ieee8021x_blocked = _TRUE;\r
962         else\r
963                 psta->ieee8021x_blocked = _FALSE;\r
964         \r
965 \r
966         //update sta's cap\r
967         \r
968         //ERP\r
969         VCS_update(padapter, psta);\r
970 #ifdef CONFIG_80211N_HT \r
971         //HT related cap\r
972         if(phtpriv_sta->ht_option)\r
973         {\r
974                 //check if sta supports rx ampdu\r
975                 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;\r
976 \r
977                 phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;\r
978         \r
979                 // bwmode\r
980                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))\r
981                 {                       \r
982                         psta->bw_mode = CHANNEL_WIDTH_40;\r
983                 }\r
984                 else\r
985                 {                       \r
986                         psta->bw_mode = CHANNEL_WIDTH_20;\r
987                 }\r
988 \r
989                 if (psta->ht_40mhz_intolerant)\r
990                         psta->bw_mode = CHANNEL_WIDTH_20;\r
991                 \r
992                 if(pmlmeext->cur_bwmode < psta->bw_mode)\r
993                 {\r
994                         psta->bw_mode = pmlmeext->cur_bwmode;\r
995                 }\r
996 \r
997                 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;\r
998 \r
999 \r
1000                 //check if sta support s Short GI 20M \r
1001                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
1002                 {\r
1003                         phtpriv_sta->sgi_20m = _TRUE;\r
1004                 }\r
1005                 \r
1006                 //check if sta support s Short GI 40M \r
1007                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
1008                 {\r
1009                         if(psta->bw_mode == CHANNEL_WIDTH_40) //according to psta->bw_mode\r
1010                                 phtpriv_sta->sgi_40m = _TRUE;\r
1011                         else\r
1012                                 phtpriv_sta->sgi_40m = _FALSE;\r
1013                 }\r
1014 \r
1015                 psta->qos_option = _TRUE;\r
1016 \r
1017                 // B0 Config LDPC Coding Capability\r
1018                 if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && \r
1019                         GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1020                 {\r
1021                         SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));\r
1022                         DBG_871X("Enable HT Tx LDPC for STA(%d)\n",psta->aid);\r
1023                 }\r
1024 \r
1025                 // B7 B8 B9 Config STBC setting\r
1026                 if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&\r
1027                         GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)))\r
1028                 {\r
1029                         SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX) );\r
1030                         DBG_871X("Enable HT Tx STBC for STA(%d)\n",psta->aid);\r
1031                 }\r
1032 \r
1033 #ifdef CONFIG_BEAMFORMING\r
1034                 /*Config Tx beamforming setting*/\r
1035                 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && \r
1036                         GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1037                 {\r
1038                         SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);\r
1039                         /*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/\r
1040                         SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6);\r
1041                 }\r
1042 \r
1043                 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&\r
1044                         GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap)))\r
1045                 {\r
1046                         SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);\r
1047                         /*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/\r
1048                         SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4);\r
1049                 }\r
1050                 if (cur_beamform_cap) {\r
1051                         DBG_871X("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->aid, cur_beamform_cap);\r
1052                 }\r
1053 #endif /*CONFIG_BEAMFORMING*/\r
1054         }\r
1055         else\r
1056         {\r
1057                 phtpriv_sta->ampdu_enable = _FALSE;\r
1058                 \r
1059                 phtpriv_sta->sgi_20m = _FALSE;\r
1060                 phtpriv_sta->sgi_40m = _FALSE;\r
1061                 psta->bw_mode = CHANNEL_WIDTH_20;\r
1062                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1063         }\r
1064 \r
1065         phtpriv_sta->ldpc_cap = cur_ldpc_cap;\r
1066         phtpriv_sta->stbc_cap = cur_stbc_cap;\r
1067         phtpriv_sta->beamform_cap = cur_beamform_cap;\r
1068 \r
1069         //Rx AMPDU\r
1070         send_delba(padapter, 0, psta->hwaddr);// recipient\r
1071         \r
1072         //TX AMPDU\r
1073         send_delba(padapter, 1, psta->hwaddr);// // originator\r
1074         phtpriv_sta->agg_enable_bitmap = 0x0;//reset\r
1075         phtpriv_sta->candidate_tid_bitmap = 0x0;//reset\r
1076 #endif //CONFIG_80211N_HT\r
1077 \r
1078 #ifdef CONFIG_80211AC_VHT\r
1079         update_sta_vht_info_apmode(padapter, psta);\r
1080 #endif\r
1081 \r
1082         update_ldpc_stbc_cap(psta);\r
1083 \r
1084         //todo: init other variables\r
1085         \r
1086         _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
1087 \r
1088 \r
1089         //add ratid\r
1090         //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()\r
1091 \r
1092 \r
1093         _enter_critical_bh(&psta->lock, &irqL);\r
1094         psta->state |= _FW_LINKED;\r
1095         _exit_critical_bh(&psta->lock, &irqL);\r
1096         \r
1097 \r
1098 }\r
1099 \r
1100 static void update_ap_info(_adapter *padapter, struct sta_info *psta)\r
1101 {\r
1102         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1103         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
1104         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1105         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1106 #ifdef CONFIG_80211N_HT\r
1107         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
1108 #endif //CONFIG_80211N_HT\r
1109 \r
1110         psta->wireless_mode = pmlmeext->cur_wireless_mode;\r
1111 \r
1112         psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);\r
1113         _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);\r
1114 \r
1115 #ifdef CONFIG_80211N_HT \r
1116         //HT related cap\r
1117         if(phtpriv_ap->ht_option)\r
1118         {\r
1119                 //check if sta supports rx ampdu\r
1120                 //phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable;\r
1121 \r
1122                 //check if sta support s Short GI 20M\r
1123                 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
1124                 {\r
1125                         phtpriv_ap->sgi_20m = _TRUE;\r
1126                 }\r
1127                 //check if sta support s Short GI 40M\r
1128                 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
1129                 {\r
1130                         phtpriv_ap->sgi_40m = _TRUE;\r
1131                 }\r
1132 \r
1133                 psta->qos_option = _TRUE;\r
1134         }\r
1135         else\r
1136         {\r
1137                 phtpriv_ap->ampdu_enable = _FALSE;\r
1138                 \r
1139                 phtpriv_ap->sgi_20m = _FALSE;\r
1140                 phtpriv_ap->sgi_40m = _FALSE;\r
1141         }\r
1142 \r
1143         psta->bw_mode = pmlmeext->cur_bwmode;\r
1144         phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;\r
1145 \r
1146         phtpriv_ap->agg_enable_bitmap = 0x0;//reset\r
1147         phtpriv_ap->candidate_tid_bitmap = 0x0;//reset\r
1148 \r
1149         _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));\r
1150 \r
1151 #ifdef CONFIG_80211AC_VHT\r
1152         _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));\r
1153 #endif //CONFIG_80211AC_VHT\r
1154 \r
1155 #endif //CONFIG_80211N_HT\r
1156 \r
1157         psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */\r
1158 }\r
1159 \r
1160 static void rtw_set_hw_wmm_param(_adapter *padapter)\r
1161 {\r
1162         u8      ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;\r
1163         u8      acm_mask;\r
1164         u16     TXOP;\r
1165         u32     acParm, i;\r
1166         u32     edca[4], inx[4];\r
1167         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
1168         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1169         struct xmit_priv                *pxmitpriv = &padapter->xmitpriv;\r
1170         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1171 \r
1172         acm_mask = 0;\r
1173 \r
1174         if (IsSupported5G(pmlmeext->cur_wireless_mode) || \r
1175                 (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))\r
1176                 aSifsTime = 16;\r
1177         else\r
1178                 aSifsTime = 10;\r
1179 \r
1180         if (pmlmeinfo->WMM_enable == 0) {\r
1181                 padapter->mlmepriv.acm_mask = 0;\r
1182 \r
1183                 AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);\r
1184 \r
1185                 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) {\r
1186                         ECWMin = 4;\r
1187                         ECWMax = 10;\r
1188                 } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {\r
1189                         ECWMin = 5;\r
1190                         ECWMax = 10;\r
1191                 } else {\r
1192                         ECWMin = 4;\r
1193                         ECWMax = 10;\r
1194                 }\r
1195 \r
1196                 TXOP = 0;\r
1197                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1198                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));\r
1199                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));\r
1200                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));\r
1201 \r
1202                 ECWMin = 2;\r
1203                 ECWMax = 3;\r
1204                 TXOP = 0x2f;\r
1205                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1206                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));\r
1207                 \r
1208         } else {\r
1209                 edca[0] = edca[1] = edca[2] = edca[3] = 0;\r
1210 \r
1211                 /*TODO:*/\r
1212                 acm_mask = 0;\r
1213                 padapter->mlmepriv.acm_mask = acm_mask;\r
1214 \r
1215                 /*\r
1216                 //BK\r
1217                 //AIFS = AIFSN * slot time + SIFS - r2t phy delay\r
1218                 */\r
1219                 AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime;\r
1220                 ECWMin = 4;\r
1221                 ECWMax = 10;\r
1222                 TXOP = 0;               \r
1223                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1224                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));\r
1225                 edca[XMIT_BK_QUEUE] = acParm;\r
1226                 DBG_871X("WMM(BK): %x\n", acParm);\r
1227                 \r
1228                 /* BE */\r
1229                 AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime;\r
1230                 ECWMin = 4;\r
1231                 ECWMax = 6;\r
1232                 TXOP = 0;               \r
1233                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1234                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));\r
1235                 edca[XMIT_BE_QUEUE] = acParm;\r
1236                 DBG_871X("WMM(BE): %x\n", acParm);\r
1237 \r
1238                 /* VI */\r
1239                 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;\r
1240                 ECWMin = 3;\r
1241                 ECWMax = 4;\r
1242                 TXOP = 94;              \r
1243                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1244                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));\r
1245                 edca[XMIT_VI_QUEUE] = acParm;\r
1246                 DBG_871X("WMM(VI): %x\n", acParm);\r
1247 \r
1248                 /* VO */\r
1249                 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;\r
1250                 ECWMin = 2;\r
1251                 ECWMax = 3;\r
1252                 TXOP = 47;              \r
1253                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);\r
1254                 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));\r
1255                 edca[XMIT_VO_QUEUE] = acParm;\r
1256                 DBG_871X("WMM(VO): %x\n", acParm);\r
1257 \r
1258                 \r
1259                 if (padapter->registrypriv.acm_method == 1)\r
1260                         rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));\r
1261                 else\r
1262                         padapter->mlmepriv.acm_mask = acm_mask;\r
1263 \r
1264                 inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;\r
1265 \r
1266                 if (pregpriv->wifi_spec == 1) {\r
1267                         u32     j, tmp, change_inx = _FALSE;\r
1268 \r
1269                         /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */\r
1270                         for (i = 0 ; i < 4 ; i++) {\r
1271                                 for (j = i+1 ; j < 4 ; j++) {\r
1272                                         /* compare CW and AIFS */\r
1273                                         if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {\r
1274                                                 change_inx = _TRUE;\r
1275                                         } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {\r
1276                                                 /* compare TXOP */\r
1277                                                 if ((edca[j] >> 16) > (edca[i] >> 16))\r
1278                                                         change_inx = _TRUE;\r
1279                                         }\r
1280                                 \r
1281                                         if (change_inx) {\r
1282                                                 tmp = edca[i];\r
1283                                                 edca[i] = edca[j];\r
1284                                                 edca[j] = tmp;\r
1285 \r
1286                                                 tmp = inx[i];\r
1287                                                 inx[i] = inx[j];\r
1288                                                 inx[j] = tmp;\r
1289 \r
1290                                                 change_inx = _FALSE;\r
1291                                         }\r
1292                                 }\r
1293                         }\r
1294                 }\r
1295 \r
1296                 for (i = 0 ; i < 4 ; i++) {\r
1297                         pxmitpriv->wmm_para_seq[i] = inx[i];\r
1298                         DBG_871X("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);\r
1299                 }\r
1300                 \r
1301         }\r
1302         \r
1303 }\r
1304 \r
1305 static void update_hw_ht_param(_adapter *padapter)\r
1306 {\r
1307         unsigned char           max_AMPDU_len;\r
1308         unsigned char           min_MPDU_spacing;\r
1309         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1310         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
1311         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1312         \r
1313         DBG_871X("%s\n", __FUNCTION__);\r
1314         \r
1315 \r
1316         //handle A-MPDU parameter field\r
1317         /*      \r
1318                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k\r
1319                 AMPDU_para [4:2]:Min MPDU Start Spacing \r
1320         */\r
1321         max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;  \r
1322         \r
1323         min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;        \r
1324 \r
1325         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));\r
1326 \r
1327         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));\r
1328 \r
1329         //\r
1330         // Config SM Power Save setting\r
1331         //\r
1332         pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;\r
1333         if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)\r
1334         {\r
1335                 /*u8 i;\r
1336                 //update the MCS rates\r
1337                 for (i = 0; i < 16; i++)\r
1338                 {\r
1339                         pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];\r
1340                 }*/\r
1341                 DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);\r
1342         }\r
1343 \r
1344         //\r
1345         // Config current HT Protection mode.\r
1346         //\r
1347         //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;\r
1348 \r
1349 }\r
1350 \r
1351 static void rtw_ap_check_scan(_adapter *padapter)\r
1352 {\r
1353         _irqL   irqL;\r
1354         _list           *plist, *phead;\r
1355         u32     delta_time, lifetime;\r
1356         struct  wlan_network    *pnetwork = NULL;\r
1357         WLAN_BSSID_EX *pbss = NULL;     \r
1358         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);     \r
1359         _queue  *queue  = &(pmlmepriv->scanned_queue);\r
1360         u8 do_scan = _FALSE;\r
1361 \r
1362         lifetime = SCANQUEUE_LIFETIME; /* 20 sec */\r
1363 \r
1364         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
1365         phead = get_list_head(queue);\r
1366         if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE)\r
1367                 if (padapter->registrypriv.wifi_spec)\r
1368                         do_scan = _TRUE;\r
1369         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
1370 \r
1371 #ifdef CONFIG_AUTO_CHNL_SEL_NHM\r
1372         if (padapter->registrypriv.acs_auto_scan) {\r
1373                 do_scan = _TRUE;\r
1374                 rtw_acs_start(padapter, _TRUE);\r
1375         }\r
1376 #endif\r
1377                 \r
1378         if (_TRUE == do_scan) {\r
1379                 DBG_871X("%s : drv scans by itself and wait_completed\n", __func__);\r
1380                 rtw_drv_scan_by_self(padapter);\r
1381                 rtw_scan_wait_completed(padapter);\r
1382         }\r
1383         \r
1384 #ifdef CONFIG_AUTO_CHNL_SEL_NHM\r
1385         if (padapter->registrypriv.acs_auto_scan)\r
1386                 rtw_acs_start(padapter, _FALSE);\r
1387 #endif  \r
1388         _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
1389 \r
1390         phead = get_list_head(queue);\r
1391         plist = get_next(phead);\r
1392 \r
1393         while (1) {\r
1394                 \r
1395                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)\r
1396                         break;\r
1397 \r
1398                 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);\r
1399                 \r
1400                 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0\r
1401                         && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE\r
1402                         && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) {             \r
1403                         delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);\r
1404                         \r
1405                         if (delta_time < lifetime) {\r
1406 \r
1407                                 uint ie_len = 0;        \r
1408                                 u8 *pbuf = NULL;\r
1409                                 u8 *ie = NULL;\r
1410                 \r
1411                                 pbss = &pnetwork->network;\r
1412                                 ie = pbss->IEs;\r
1413                 \r
1414                                 /*check if HT CAP INFO IE exists or not*/\r
1415                                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_));\r
1416                                 if (pbuf == NULL) {\r
1417                                         /* HT CAP INFO IE don't exist, it is b/g mode bss.*/\r
1418                                 \r
1419                                         if (pmlmepriv->olbc == _FALSE)\r
1420                                                 pmlmepriv->olbc = _TRUE;\r
1421 \r
1422                                         if (pmlmepriv->olbc_ht == _FALSE)\r
1423                                                 pmlmepriv->olbc_ht = _TRUE;\r
1424                                 }                                               \r
1425                         }                       \r
1426                 }\r
1427 \r
1428                 plist = get_next(plist);        \r
1429                 \r
1430         }\r
1431         \r
1432         _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);\r
1433 \r
1434         pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/\r
1435         \r
1436 }\r
1437 \r
1438 void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter)\r
1439 {\r
1440         WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network);\r
1441         struct sta_info *sta = NULL;\r
1442 \r
1443         /* update cur_wireless_mode */\r
1444         update_wireless_mode(adapter);\r
1445 \r
1446         /* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */\r
1447         UpdateBrateTbl(adapter, pnetwork->SupportedRates);\r
1448         rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);\r
1449 \r
1450         /* update capability after cur_wireless_mode updated */\r
1451         update_capinfo(adapter, rtw_get_capability(pnetwork));\r
1452 \r
1453         /* update bc/mc sta_info */\r
1454         update_bmc_sta(adapter);\r
1455 \r
1456         /* update AP's sta info */\r
1457         sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress);\r
1458         if (!sta) {\r
1459                 DBG_871X(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress));\r
1460                 rtw_warn_on(1);\r
1461                 return;\r
1462         }\r
1463 \r
1464         update_ap_info(adapter, sta);\r
1465 }\r
1466 \r
1467 void start_bss_network(_adapter *padapter, struct createbss_parm *parm)\r
1468 {\r
1469 #define DUMP_ADAPTERS_STATUS 0\r
1470 \r
1471         u8 val8;\r
1472         u16 bcn_interval;\r
1473         u32     acparm;\r
1474         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1475         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1476         struct security_priv* psecuritypriv=&(padapter->securitypriv);  \r
1477         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */\r
1478         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1479         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1480         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);\r
1481         u8 req_ch, req_bw, req_offset;\r
1482         bool ch_setting_changed = _FALSE;\r
1483         u8 ch_to_set = 0, bw_to_set, offset_to_set;\r
1484         u8 doiqk = _FALSE;\r
1485 \r
1486         if (parm->req_ch == 0) {\r
1487                 /* change to unspecificed ch, bw, offset, get from IE */\r
1488                 goto get_cbhw_from_ie;\r
1489         } else if (parm->req_ch > 0) {\r
1490                 /* change ch, bw, offset */\r
1491                 req_ch = parm->req_ch;\r
1492                 req_bw = parm->req_bw;\r
1493                 req_offset = parm->req_offset;\r
1494                 goto change_chbw;\r
1495         }\r
1496 \r
1497         bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;       \r
1498 \r
1499         //check if there is wps ie, \r
1500         //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,\r
1501         //and at first time the security ie ( RSN/WPA IE) will not include in beacon.\r
1502         if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))\r
1503         {\r
1504                 pmlmeext->bstart_bss = _TRUE;\r
1505         }\r
1506 \r
1507         //todo: update wmm, ht cap\r
1508         //pmlmeinfo->WMM_enable;\r
1509         //pmlmeinfo->HT_enable;\r
1510         if(pmlmepriv->qospriv.qos_option)\r
1511                 pmlmeinfo->WMM_enable = _TRUE;\r
1512 #ifdef CONFIG_80211N_HT\r
1513         if(pmlmepriv->htpriv.ht_option)\r
1514         {\r
1515                 pmlmeinfo->WMM_enable = _TRUE;\r
1516                 pmlmeinfo->HT_enable = _TRUE;\r
1517                 //pmlmeinfo->HT_info_enable = _TRUE;\r
1518                 //pmlmeinfo->HT_caps_enable = _TRUE;\r
1519 \r
1520                 update_hw_ht_param(padapter);\r
1521         }\r
1522 #endif //#CONFIG_80211N_HT\r
1523 \r
1524 #ifdef CONFIG_80211AC_VHT\r
1525         if(pmlmepriv->vhtpriv.vht_option) {\r
1526                 pmlmeinfo->VHT_enable = _TRUE;\r
1527                 update_hw_vht_param(padapter);\r
1528         }\r
1529 #endif //CONFIG_80211AC_VHT\r
1530 \r
1531         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1532         {\r
1533                 //WEP Key will be set before this function, do not clear CAM.\r
1534                 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))\r
1535                         flush_all_cam_entry(padapter);  //clear CAM\r
1536         }       \r
1537 \r
1538         //set MSR to AP_Mode            \r
1539         Set_MSR(padapter, _HW_STATE_AP_);       \r
1540                 \r
1541         //Set BSSID REG\r
1542         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);\r
1543 \r
1544         //Set EDCA param reg\r
1545 #ifdef CONFIG_CONCURRENT_MODE\r
1546         acparm = 0x005ea42b;\r
1547 #else\r
1548         acparm = 0x002F3217; // VO\r
1549 #endif\r
1550         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));\r
1551         acparm = 0x005E4317; // VI\r
1552         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));\r
1553         //acparm = 0x00105320; // BE\r
1554         acparm = 0x005ea42b;\r
1555         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));\r
1556         acparm = 0x0000A444; // BK\r
1557         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));\r
1558 \r
1559         //Set Security\r
1560         val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;\r
1561         rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));\r
1562 \r
1563         //Beacon Control related register\r
1564         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));\r
1565 \r
1566 #if 0\r
1567         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1568         {\r
1569                 //u32 initialgain;\r
1570 \r
1571                 //initialgain = 0x1e;\r
1572 \r
1573 \r
1574                 //disable dynamic functions, such as high power, DIG\r
1575                 /*rtw_phydm_ability_backup(padapter);*/\r
1576                 /*rtw_phydm_func_disable_all(padapter);*/\r
1577                 \r
1578                 //turn on all dynamic functions \r
1579                 /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);*/\r
1580 \r
1581                 /*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/\r
1582         \r
1583         }\r
1584 #endif\r
1585 \r
1586 get_cbhw_from_ie:\r
1587         rtw_ies_get_chbw(pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)\r
1588                 , pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)\r
1589                 , &req_ch, &req_bw, &req_offset);\r
1590 \r
1591 change_chbw:\r
1592         rtw_warn_on(req_ch == 0);\r
1593 \r
1594         ch_setting_changed = rtw_ap_chbw_decision(padapter, req_ch, req_bw, req_offset\r
1595                 , &ch_to_set, &bw_to_set, &offset_to_set);\r
1596 \r
1597         //let pnetwork_mlmeext == pnetwork_mlme.\r
1598         _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);\r
1599 \r
1600         rtw_start_bss_hdl_after_chbw_decided(padapter);\r
1601 \r
1602         #if defined(CONFIG_DFS_MASTER)\r
1603         rtw_dfs_master_status_apply(padapter, MLME_AP_STARTED);\r
1604         #endif\r
1605 \r
1606         doiqk = _TRUE;\r
1607         rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);\r
1608         \r
1609         if (ch_to_set != 0)\r
1610                 set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);\r
1611 \r
1612         doiqk = _FALSE;\r
1613         rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);\r
1614         if (DUMP_ADAPTERS_STATUS) {\r
1615                 DBG_871X(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter));\r
1616                 dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter));\r
1617         }\r
1618 \r
1619         if (_TRUE == pmlmeext->bstart_bss\r
1620                 && !check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)\r
1621                 && !check_fwstate(pmlmepriv, WIFI_OP_CH_SWITCHING)\r
1622                 #ifdef CONFIG_CONCURRENT_MODE\r
1623                 && !check_buddy_fwstate(padapter, WIFI_SITE_MONITOR)\r
1624                 #endif\r
1625         ) {\r
1626 \r
1627                if ((pmlmepriv->olbc == _TRUE) || (pmlmepriv->olbc_ht == _TRUE)) {\r
1628 \r
1629                         /* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */\r
1630 \r
1631                         pmlmepriv->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK);\r
1632                         pmlmepriv->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS;\r
1633                         update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);\r
1634                 }\r
1635 \r
1636                 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
1637 \r
1638                 #if !defined(CONFIG_INTERRUPT_BASED_TXBCN)\r
1639                 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
1640                 /* other case will  tx beacon when bcn interrupt coming in. */\r
1641                 if (send_beacon(padapter) == _FAIL)\r
1642                         DBG_871X("issue_beacon, fail!\n");\r
1643                 #endif \r
1644                 #endif /* !defined(CONFIG_INTERRUPT_BASED_TXBCN) */\r
1645         }\r
1646 \r
1647         /*Set EDCA param reg after update cur_wireless_mode & update_capinfo*/\r
1648         if (pregpriv->wifi_spec == 1)\r
1649                 rtw_set_hw_wmm_param(padapter);\r
1650         \r
1651         /*pmlmeext->bstart_bss = _TRUE;*/\r
1652 }\r
1653 \r
1654 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf,  int len)\r
1655 {\r
1656         int ret=_SUCCESS;\r
1657         u8 *p;\r
1658         u8 *pHT_caps_ie=NULL;\r
1659         u8 *pHT_info_ie=NULL;\r
1660         u16 cap, ht_cap=_FALSE;\r
1661         uint ie_len = 0;\r
1662         int group_cipher, pairwise_cipher;      \r
1663         u8      channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];\r
1664         int supportRateNum = 0;\r
1665         u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};\r
1666         u8 wps_oui[4]={0x0,0x50,0xf2,0x04};\r
1667         u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};        \r
1668         struct registry_priv *pregistrypriv = &padapter->registrypriv;  \r
1669         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1670         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1671         WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
1672         struct sta_priv *pstapriv = &padapter->stapriv;\r
1673         u8 *ie = pbss_network->IEs;\r
1674         u8 vht_cap=_FALSE;\r
1675         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1676         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1677         u8 rf_num = 0;\r
1678         \r
1679         /* SSID */\r
1680         /* Supported rates */\r
1681         /* DS Params */\r
1682         /* WLAN_EID_COUNTRY */\r
1683         /* ERP Information element */\r
1684         /* Extended supported rates */\r
1685         /* WPA/WPA2 */\r
1686         /* Wi-Fi Wireless Multimedia Extensions */\r
1687         /* ht_capab, ht_oper */\r
1688         /* WPS IE */\r
1689 \r
1690         DBG_871X("%s, len=%d\n", __FUNCTION__, len);\r
1691 \r
1692         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)\r
1693                 return _FAIL;\r
1694 \r
1695 \r
1696         if(len>MAX_IE_SZ)\r
1697                 return _FAIL;\r
1698         \r
1699         pbss_network->IELength = len;\r
1700 \r
1701         _rtw_memset(ie, 0, MAX_IE_SZ);\r
1702         \r
1703         _rtw_memcpy(ie, pbuf, pbss_network->IELength);\r
1704 \r
1705 \r
1706         if(pbss_network->InfrastructureMode!=Ndis802_11APMode)\r
1707                 return _FAIL;\r
1708 \r
1709 \r
1710         rtw_ap_check_scan(padapter);\r
1711         \r
1712 \r
1713         pbss_network->Rssi = 0;\r
1714 \r
1715         _rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);\r
1716         \r
1717         //beacon interval\r
1718         p = rtw_get_beacon_interval_from_ie(ie);//ie + 8;       // 8: TimeStamp, 2: Beacon Interval 2:Capability\r
1719         //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);\r
1720         pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);\r
1721         \r
1722         //capability\r
1723         //cap = *(unsigned short *)rtw_get_capability_from_ie(ie);\r
1724         //cap = le16_to_cpu(cap);\r
1725         cap = RTW_GET_LE16(ie);\r
1726 \r
1727         //SSID\r
1728         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));\r
1729         if(p && ie_len>0)\r
1730         {\r
1731                 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));\r
1732                 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);\r
1733                 pbss_network->Ssid.SsidLength = ie_len;\r
1734                 #ifdef CONFIG_P2P\r
1735                 _rtw_memcpy(padapter->wdinfo.p2p_group_ssid, pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);\r
1736                 padapter->wdinfo.p2p_group_ssid_len = pbss_network->Ssid.SsidLength;\r
1737                 #endif\r
1738         }\r
1739 \r
1740         //chnnel\r
1741         channel = 0;\r
1742         pbss_network->Configuration.Length = 0;\r
1743         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1744         if(p && ie_len>0)\r
1745                 channel = *(p + 2);\r
1746 \r
1747         pbss_network->Configuration.DSConfig = channel;\r
1748 \r
1749         \r
1750         _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);\r
1751         // get supported rates\r
1752         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));   \r
1753         if (p !=  NULL) \r
1754         {\r
1755                 _rtw_memcpy(supportRate, p+2, ie_len);  \r
1756                 supportRateNum = ie_len;\r
1757         }\r
1758         \r
1759         //get ext_supported rates\r
1760         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); \r
1761         if (p !=  NULL)\r
1762         {\r
1763                 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);\r
1764                 supportRateNum += ie_len;\r
1765         \r
1766         }\r
1767 \r
1768         network_type = rtw_check_network_type(supportRate, supportRateNum, channel);\r
1769 \r
1770         rtw_set_supported_rate(pbss_network->SupportedRates, network_type);\r
1771 \r
1772 \r
1773         //parsing ERP_IE\r
1774         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1775         if(p && ie_len>0)\r
1776         {\r
1777                 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);\r
1778         }\r
1779 \r
1780         //update privacy/security\r
1781         if (cap & BIT(4))\r
1782                 pbss_network->Privacy = 1;\r
1783         else\r
1784                 pbss_network->Privacy = 0;\r
1785 \r
1786         psecuritypriv->wpa_psk = 0;\r
1787 \r
1788         //wpa2\r
1789         group_cipher = 0; pairwise_cipher = 0;\r
1790         psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1791         psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;     \r
1792         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));            \r
1793         if(p && ie_len>0)\r
1794         {\r
1795                 if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1796                 {\r
1797                         psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1798                         \r
1799                         psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1800                         psecuritypriv->wpa_psk |= BIT(1);\r
1801 \r
1802                         psecuritypriv->wpa2_group_cipher = group_cipher;\r
1803                         psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;\r
1804 #if 0\r
1805                         switch(group_cipher)\r
1806                         {\r
1807                                 case WPA_CIPHER_NONE:                           \r
1808                                 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1809                                 break;\r
1810                                 case WPA_CIPHER_WEP40:                          \r
1811                                 psecuritypriv->wpa2_group_cipher = _WEP40_;\r
1812                                 break;\r
1813                                 case WPA_CIPHER_TKIP:                           \r
1814                                 psecuritypriv->wpa2_group_cipher = _TKIP_;\r
1815                                 break;\r
1816                                 case WPA_CIPHER_CCMP:                           \r
1817                                 psecuritypriv->wpa2_group_cipher = _AES_;                               \r
1818                                 break;\r
1819                                 case WPA_CIPHER_WEP104:                                 \r
1820                                 psecuritypriv->wpa2_group_cipher = _WEP104_;\r
1821                                 break;\r
1822                         }\r
1823 \r
1824                         switch(pairwise_cipher)\r
1825                         {\r
1826                                 case WPA_CIPHER_NONE:                   \r
1827                                 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;\r
1828                                 break;\r
1829                                 case WPA_CIPHER_WEP40:                  \r
1830                                 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;\r
1831                                 break;\r
1832                                 case WPA_CIPHER_TKIP:                           \r
1833                                 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;\r
1834                                 break;\r
1835                                 case WPA_CIPHER_CCMP:                   \r
1836                                 psecuritypriv->wpa2_pairwise_cipher = _AES_;\r
1837                                 break;\r
1838                                 case WPA_CIPHER_WEP104:                                 \r
1839                                 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;\r
1840                                 break;\r
1841                         }\r
1842 #endif                  \r
1843                 }\r
1844                 \r
1845         }\r
1846 \r
1847         //wpa\r
1848         ie_len = 0;\r
1849         group_cipher = 0; pairwise_cipher = 0;\r
1850         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1851         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;      \r
1852         for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1853         {\r
1854                 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));           \r
1855                 if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))\r
1856                 {\r
1857                         if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1858                         {\r
1859                                 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1860                                 \r
1861                                 psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1862 \r
1863                                 psecuritypriv->wpa_psk |= BIT(0);\r
1864 \r
1865                                 psecuritypriv->wpa_group_cipher = group_cipher;\r
1866                                 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;\r
1867 \r
1868 #if 0\r
1869                                 switch(group_cipher)\r
1870                                 {\r
1871                                         case WPA_CIPHER_NONE:                                   \r
1872                                         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1873                                         break;\r
1874                                         case WPA_CIPHER_WEP40:                                  \r
1875                                         psecuritypriv->wpa_group_cipher = _WEP40_;\r
1876                                         break;\r
1877                                         case WPA_CIPHER_TKIP:                                   \r
1878                                         psecuritypriv->wpa_group_cipher = _TKIP_;\r
1879                                         break;\r
1880                                         case WPA_CIPHER_CCMP:                                   \r
1881                                         psecuritypriv->wpa_group_cipher = _AES_;                                \r
1882                                         break;\r
1883                                         case WPA_CIPHER_WEP104:                                 \r
1884                                         psecuritypriv->wpa_group_cipher = _WEP104_;\r
1885                                         break;\r
1886                                 }\r
1887 \r
1888                                 switch(pairwise_cipher)\r
1889                                 {\r
1890                                         case WPA_CIPHER_NONE:                                   \r
1891                                         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;\r
1892                                         break;\r
1893                                         case WPA_CIPHER_WEP40:                                  \r
1894                                         psecuritypriv->wpa_pairwise_cipher = _WEP40_;\r
1895                                         break;\r
1896                                         case WPA_CIPHER_TKIP:                                   \r
1897                                         psecuritypriv->wpa_pairwise_cipher = _TKIP_;\r
1898                                         break;\r
1899                                         case WPA_CIPHER_CCMP:                                   \r
1900                                         psecuritypriv->wpa_pairwise_cipher = _AES_;\r
1901                                         break;\r
1902                                         case WPA_CIPHER_WEP104:                                 \r
1903                                         psecuritypriv->wpa_pairwise_cipher = _WEP104_;\r
1904                                         break;\r
1905                                 }\r
1906 #endif                          \r
1907                         }\r
1908 \r
1909                         break;\r
1910                         \r
1911                 }\r
1912                         \r
1913                 if ((p == NULL) || (ie_len == 0))\r
1914                 {\r
1915                                 break;\r
1916                 }\r
1917                 \r
1918         }\r
1919 \r
1920         //wmm\r
1921         ie_len = 0;\r
1922         pmlmepriv->qospriv.qos_option = 0;\r
1923         if(pregistrypriv->wmm_enable)\r
1924         {\r
1925                 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1926                 {                       \r
1927                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); \r
1928                         if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) \r
1929                         {\r
1930                                 pmlmepriv->qospriv.qos_option = 1;      \r
1931 \r
1932                                 *(p+8) |= BIT(7);//QoS Info, support U-APSD\r
1933                                 \r
1934                                 /* disable all ACM bits since the WMM admission control is not supported */\r
1935                                 *(p + 10) &= ~BIT(4); /* BE */\r
1936                                 *(p + 14) &= ~BIT(4); /* BK */\r
1937                                 *(p + 18) &= ~BIT(4); /* VI */\r
1938                                 *(p + 22) &= ~BIT(4); /* VO */\r
1939                                 \r
1940                                 break;                          \r
1941                         }\r
1942                         \r
1943                         if ((p == NULL) || (ie_len == 0))\r
1944                         {\r
1945                                 break;\r
1946                         }                       \r
1947                 }               \r
1948         }\r
1949 #ifdef CONFIG_80211N_HT\r
1950         //parsing HT_CAP_IE\r
1951         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1952         if(p && ie_len>0)\r
1953         {\r
1954                 u8 rf_type=0;\r
1955                 HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor=MAX_AMPDU_FACTOR_64K;\r
1956                 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);\r
1957 \r
1958                 if (0) {\r
1959                         DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));\r
1960                         dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);\r
1961                 }\r
1962 \r
1963                 pHT_caps_ie=p;\r
1964 \r
1965                 ht_cap = _TRUE;\r
1966                 network_type |= WIRELESS_11_24N;\r
1967 \r
1968                 rtw_ht_use_default_setting(padapter);\r
1969 \r
1970                 /* Update HT Capabilities Info field */\r
1971                 if (pmlmepriv->htpriv.sgi_20m == _FALSE)\r
1972                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);\r
1973 \r
1974                 if (pmlmepriv->htpriv.sgi_40m == _FALSE)\r
1975                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);\r
1976 \r
1977                 if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))\r
1978                 {\r
1979                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);\r
1980                 }\r
1981 \r
1982                 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))\r
1983                 {\r
1984                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);\r
1985                 }               \r
1986 \r
1987                 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))\r
1988                 {\r
1989                         pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);\r
1990                 }\r
1991 \r
1992                 /* Update A-MPDU Parameters field */\r
1993                 pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY);\r
1994 \r
1995                 if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||\r
1996                         (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))\r
1997                 {\r
1998                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));\r
1999                 }       \r
2000                 else\r
2001                 {\r
2002                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);    \r
2003                 }       \r
2004 \r
2005                 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);\r
2006                 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); //set  Max Rx AMPDU size  to 64K\r
2007                 \r
2008                 _rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element));\r
2009 \r
2010                 /* Update Supported MCS Set field */\r
2011                 {\r
2012                         int i;\r
2013 \r
2014                         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));\r
2015 \r
2016                         /* RX MCS Bitmask */\r
2017                         switch(rf_type)\r
2018                         {\r
2019                                 case RF_1T1R:\r
2020                                 case RF_1T2R: //?\r
2021                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);\r
2022                                         break;\r
2023                                 case RF_2T2R:\r
2024                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);\r
2025                                         break;\r
2026                                 case RF_3T3R:\r
2027                                         set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);\r
2028                                         break;\r
2029                                 default:\r
2030                                         DBG_871X("[warning] rf_type %d is not expected\n", rf_type);\r
2031                         }\r
2032                         for (i = 0; i < 10; i++)\r
2033                                 *(HT_CAP_ELE_RX_MCS_MAP(pht_cap)+i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];\r
2034                 }\r
2035 \r
2036 #ifdef CONFIG_BEAMFORMING\r
2037                 // Use registry value to enable HT Beamforming.\r
2038                 // ToDo: use configure file to set these capability.\r
2039                 pht_cap->tx_BF_cap_info = 0;\r
2040 \r
2041                 // HT Beamformer\r
2042                 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE))\r
2043                 {\r
2044                         // Transmit NDP Capable\r
2045                         SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);\r
2046                         // Explicit Compressed Steering Capable\r
2047                         SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);\r
2048                         // Compressed Steering Number Antennas\r
2049                         SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);\r
2050                         rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);\r
2051                         SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num);          \r
2052                 }\r
2053 \r
2054                 // HT Beamformee\r
2055                 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))\r
2056                 {\r
2057                         // Receive NDP Capable\r
2058                         SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);\r
2059                         // Explicit Compressed Beamforming Feedback Capable\r
2060                         SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);\r
2061                         rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);\r
2062                         SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num);\r
2063                 }\r
2064 #endif //CONFIG_BEAMFORMING\r
2065 \r
2066                 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);\r
2067 \r
2068                 if (0) {\r
2069                         DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));\r
2070                         dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);\r
2071                 }\r
2072         }\r
2073 \r
2074         //parsing HT_INFO_IE\r
2075         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
2076         if(p && ie_len>0)\r
2077         {\r
2078                 pHT_info_ie=p;\r
2079         }\r
2080 #endif //CONFIG_80211N_HT\r
2081         switch(network_type)\r
2082         {\r
2083                 case WIRELESS_11B:\r
2084                         pbss_network->NetworkTypeInUse = Ndis802_11DS;\r
2085                         break;  \r
2086                 case WIRELESS_11G:\r
2087                 case WIRELESS_11BG:\r
2088              case WIRELESS_11G_24N:\r
2089                 case WIRELESS_11BG_24N:\r
2090                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
2091                         break;\r
2092                 case WIRELESS_11A:\r
2093                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;\r
2094                         break;\r
2095                 default :\r
2096                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
2097                         break;\r
2098         }\r
2099         \r
2100         pmlmepriv->cur_network.network_type = network_type;\r
2101 \r
2102 #ifdef CONFIG_80211N_HT\r
2103         pmlmepriv->htpriv.ht_option = _FALSE;\r
2104 \r
2105         if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||\r
2106                       (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))\r
2107         {       \r
2108                 //todo:\r
2109                 //ht_cap = _FALSE;\r
2110         }\r
2111                       \r
2112         //ht_cap        \r
2113         if(pregistrypriv->ht_enable && ht_cap==_TRUE)\r
2114         {               \r
2115                 pmlmepriv->htpriv.ht_option = _TRUE;\r
2116                 pmlmepriv->qospriv.qos_option = 1;\r
2117 \r
2118                 if(pregistrypriv->ampdu_enable==1)\r
2119                 {\r
2120                         pmlmepriv->htpriv.ampdu_enable = _TRUE;\r
2121                 }\r
2122 \r
2123                 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);\r
2124                 \r
2125                 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);\r
2126         }\r
2127 #endif\r
2128 \r
2129 #ifdef CONFIG_80211AC_VHT\r
2130 \r
2131         //Parsing VHT CAP IE\r
2132         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
2133         if(p && ie_len>0)\r
2134         {       \r
2135                 vht_cap = _TRUE; \r
2136         }\r
2137         //Parsing VHT OPERATION IE\r
2138         \r
2139 \r
2140         pmlmepriv->vhtpriv.vht_option = _FALSE;\r
2141         // if channel in 5G band, then add vht ie .\r
2142         if ((pbss_network->Configuration.DSConfig > 14)\r
2143                 && (pmlmepriv->htpriv.ht_option == _TRUE)\r
2144                 && REGSTY_IS_11AC_ENABLE(pregistrypriv)\r
2145                 && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)\r
2146                 && (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent))\r
2147         ) {\r
2148                 if (vht_cap == _TRUE)\r
2149                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
2150                 else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) {\r
2151                         u8      cap_len, operation_len;\r
2152 \r
2153                         rtw_vht_use_default_setting(padapter);\r
2154 \r
2155                         {\r
2156                                 /* VHT Operation mode notifiy bit in Extended IE (127) */\r
2157                                 uint len = 0;\r
2158                                 \r
2159                                 SET_EXT_CAPABILITY_ELE_OP_MODE_NOTIF(pmlmepriv->ext_capab_ie_data, 1);\r
2160                                 pmlmepriv->ext_capab_ie_len = 10;\r
2161                                 rtw_set_ie(pbss_network->IEs + pbss_network->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len);\r
2162                                 pbss_network->IELength += pmlmepriv->ext_capab_ie_len;\r
2163                         }\r
2164                         \r
2165                         // VHT Capabilities element\r
2166                         cap_len = rtw_build_vht_cap_ie(padapter, pbss_network->IEs + pbss_network->IELength);\r
2167                         pbss_network->IELength += cap_len;\r
2168 \r
2169                         // VHT Operation element\r
2170                         operation_len = rtw_build_vht_operation_ie(padapter, pbss_network->IEs + pbss_network->IELength, pbss_network->Configuration.DSConfig);\r
2171                         pbss_network->IELength += operation_len;\r
2172 \r
2173                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
2174                 }               \r
2175         }\r
2176 #endif //CONFIG_80211AC_VHT\r
2177 \r
2178         pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pbss_network);\r
2179 \r
2180         rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_\r
2181                 , &pmlmepriv->ori_ch, &pmlmepriv->ori_bw, &pmlmepriv->ori_offset);\r
2182         rtw_warn_on(pmlmepriv->ori_ch == 0);\r
2183 \r
2184 {\r
2185         /* alloc sta_info for ap itself */\r
2186 \r
2187         struct sta_info *sta;\r
2188 \r
2189         sta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
2190         if (!sta) {\r
2191                 sta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
2192                 if (sta == NULL) \r
2193                         return _FAIL;\r
2194         }\r
2195 }\r
2196 \r
2197         rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);\r
2198 \r
2199         rtw_indicate_connect( padapter);\r
2200 \r
2201         pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon\r
2202                 \r
2203         //update bc/mc sta_info\r
2204         //update_bmc_sta(padapter);\r
2205 \r
2206         return ret;\r
2207 \r
2208 }\r
2209 \r
2210 void rtw_set_macaddr_acl(_adapter *padapter, int mode)\r
2211 {\r
2212         struct sta_priv *pstapriv = &padapter->stapriv;\r
2213         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
2214 \r
2215         DBG_871X("%s, mode=%d\n", __func__, mode);\r
2216 \r
2217         pacl_list->mode = mode;\r
2218 }\r
2219 \r
2220 int rtw_acl_add_sta(_adapter *padapter, u8 *addr)\r
2221 {\r
2222         _irqL irqL;\r
2223         _list   *plist, *phead;\r
2224         u8 added = _FALSE;\r
2225         int i, ret=0;\r
2226         struct rtw_wlan_acl_node *paclnode;\r
2227         struct sta_priv *pstapriv = &padapter->stapriv;\r
2228         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
2229         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
2230 \r
2231         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
2232 \r
2233         if((NUM_ACL-1) < pacl_list->num)\r
2234                 return (-1);    \r
2235 \r
2236 \r
2237         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2238 \r
2239         phead = get_list_head(pacl_node_q);\r
2240         plist = get_next(phead);\r
2241                 \r
2242         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
2243         {\r
2244                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
2245                 plist = get_next(plist);\r
2246 \r
2247                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))\r
2248                 {\r
2249                         if(paclnode->valid == _TRUE)\r
2250                         {\r
2251                                 added = _TRUE;\r
2252                                 DBG_871X("%s, sta has been added\n", __func__);\r
2253                                 break;\r
2254                         }\r
2255                 }               \r
2256         }\r
2257         \r
2258         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2259 \r
2260 \r
2261         if(added == _TRUE)\r
2262                 return ret;\r
2263         \r
2264 \r
2265         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2266 \r
2267         for(i=0; i< NUM_ACL; i++)\r
2268         {\r
2269                 paclnode = &pacl_list->aclnode[i];\r
2270 \r
2271                 if(paclnode->valid == _FALSE)\r
2272                 {\r
2273                         _rtw_init_listhead(&paclnode->list);\r
2274         \r
2275                         _rtw_memcpy(paclnode->addr, addr, ETH_ALEN);\r
2276                 \r
2277                         paclnode->valid = _TRUE;\r
2278 \r
2279                         rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));\r
2280         \r
2281                         pacl_list->num++;\r
2282 \r
2283                         break;\r
2284                 }\r
2285         }\r
2286 \r
2287         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
2288         \r
2289         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2290 \r
2291         return ret;\r
2292 }\r
2293 \r
2294 int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)\r
2295 {\r
2296         _irqL irqL;\r
2297         _list   *plist, *phead;\r
2298         int i, ret=0;\r
2299         struct rtw_wlan_acl_node *paclnode;\r
2300         struct sta_priv *pstapriv = &padapter->stapriv;\r
2301         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
2302         _queue  *pacl_node_q =&pacl_list->acl_node_q;\r
2303         u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };    //Baddr is used for clearing acl_list\r
2304 \r
2305         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
2306 \r
2307         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
2308 \r
2309         phead = get_list_head(pacl_node_q);\r
2310         plist = get_next(phead);\r
2311                 \r
2312         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
2313         {\r
2314                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
2315                 plist = get_next(plist);\r
2316 \r
2317                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN) || _rtw_memcmp(baddr, addr, ETH_ALEN))\r
2318                 {\r
2319                         if(paclnode->valid == _TRUE)\r
2320                         {\r
2321                                 paclnode->valid = _FALSE;\r
2322 \r
2323                                 rtw_list_delete(&paclnode->list);\r
2324                                 \r
2325                                 pacl_list->num--;\r
2326                         }\r
2327                 }               \r
2328         }\r
2329         \r
2330         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
2331 \r
2332         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
2333         \r
2334         return ret;\r
2335 \r
2336 }\r
2337 \r
2338 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)\r
2339 {\r
2340         struct cmd_obj*                 ph2c;\r
2341         struct set_stakey_parm  *psetstakey_para;\r
2342         struct cmd_priv                         *pcmdpriv=&padapter->cmdpriv;   \r
2343         u8      res=_SUCCESS;\r
2344 \r
2345         ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
2346         if ( ph2c == NULL){\r
2347                 res= _FAIL;\r
2348                 goto exit;\r
2349         }\r
2350 \r
2351         psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));\r
2352         if(psetstakey_para==NULL){\r
2353                 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));\r
2354                 res=_FAIL;\r
2355                 goto exit;\r
2356         }\r
2357 \r
2358         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);\r
2359 \r
2360 \r
2361         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;\r
2362 \r
2363         _rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);     \r
2364         \r
2365         _rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);\r
2366 \r
2367         \r
2368         res = rtw_enqueue_cmd(pcmdpriv, ph2c);  \r
2369 \r
2370 exit:\r
2371 \r
2372         return res;\r
2373         \r
2374 }\r
2375 \r
2376 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)\r
2377 {\r
2378         u8 keylen;\r
2379         struct cmd_obj* pcmd;\r
2380         struct setkey_parm *psetkeyparm;\r
2381         struct cmd_priv *pcmdpriv=&(padapter->cmdpriv); \r
2382         int res=_SUCCESS;\r
2383 \r
2384         //DBG_871X("%s\n", __FUNCTION__);\r
2385         \r
2386         pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
2387         if(pcmd==NULL){\r
2388                 res= _FAIL;\r
2389                 goto exit;\r
2390         }\r
2391         psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));\r
2392         if(psetkeyparm==NULL){\r
2393                 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));\r
2394                 res= _FAIL;\r
2395                 goto exit;\r
2396         }\r
2397 \r
2398         _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));\r
2399                 \r
2400         psetkeyparm->keyid=(u8)keyid;\r
2401         if (is_wep_enc(alg))\r
2402                 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);\r
2403 \r
2404         psetkeyparm->algorithm = alg;\r
2405 \r
2406         psetkeyparm->set_tx = set_tx;\r
2407 \r
2408         switch(alg)\r
2409         {\r
2410                 case _WEP40_:                                   \r
2411                         keylen = 5;\r
2412                         break;\r
2413                 case _WEP104_:\r
2414                         keylen = 13;                    \r
2415                         break;\r
2416                 case _TKIP_:\r
2417                 case _TKIP_WTMIC_:\r
2418                 case _AES_:\r
2419                 default:\r
2420                         keylen = 16;\r
2421         }\r
2422 \r
2423         _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);\r
2424         \r
2425         pcmd->cmdcode = _SetKey_CMD_;\r
2426         pcmd->parmbuf = (u8 *)psetkeyparm;   \r
2427         pcmd->cmdsz =  (sizeof(struct setkey_parm));  \r
2428         pcmd->rsp = NULL;\r
2429         pcmd->rspsz = 0;\r
2430 \r
2431 \r
2432         _rtw_init_listhead(&pcmd->list);\r
2433 \r
2434         res = rtw_enqueue_cmd(pcmdpriv, pcmd);\r
2435 \r
2436 exit:\r
2437 \r
2438         return res;\r
2439 }\r
2440 \r
2441 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)\r
2442 {\r
2443         DBG_871X("%s\n", __FUNCTION__);\r
2444 \r
2445         return rtw_ap_set_key(padapter, key, alg, keyid, 1);\r
2446 }\r
2447 \r
2448 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)\r
2449 {\r
2450         u8 alg;\r
2451 \r
2452         switch(keylen)\r
2453         {\r
2454                 case 5:\r
2455                         alg =_WEP40_;                   \r
2456                         break;\r
2457                 case 13:\r
2458                         alg =_WEP104_;                  \r
2459                         break;\r
2460                 default:\r
2461                         alg =_NO_PRIVACY_;                      \r
2462         }\r
2463 \r
2464         DBG_871X("%s\n", __FUNCTION__);\r
2465 \r
2466         return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);\r
2467 }\r
2468 \r
2469 u8 rtw_ap_bmc_frames_hdl(_adapter *padapter)\r
2470 {\r
2471 #define HIQ_XMIT_COUNTS (6)\r
2472         _irqL irqL;\r
2473         struct sta_info *psta_bmc;\r
2474         _list   *xmitframe_plist, *xmitframe_phead;\r
2475         struct xmit_frame *pxmitframe = NULL;\r
2476         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;\r
2477         struct sta_priv  *pstapriv = &padapter->stapriv;\r
2478         bool update_tim = _FALSE;\r
2479 \r
2480 \r
2481         if (padapter->registrypriv.wifi_spec != 1)\r
2482                 return H2C_SUCCESS;\r
2483 \r
2484         \r
2485         psta_bmc = rtw_get_bcmc_stainfo(padapter);\r
2486         if (!psta_bmc)\r
2487                 return H2C_SUCCESS;\r
2488 \r
2489 \r
2490         _enter_critical_bh(&pxmitpriv->lock, &irqL);\r
2491 \r
2492         if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {\r
2493                 int tx_counts = 0;\r
2494                 \r
2495                 _update_beacon(padapter, _TIM_IE_, NULL, _FALSE, "update TIM with TIB=1");\r
2496 \r
2497                 DBG_871X("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);\r
2498 \r
2499                 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);\r
2500                 xmitframe_plist = get_next(xmitframe_phead);\r
2501 \r
2502                 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {\r
2503                         pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);\r
2504 \r
2505                         xmitframe_plist = get_next(xmitframe_plist);\r
2506 \r
2507                         rtw_list_delete(&pxmitframe->list);\r
2508 \r
2509                         psta_bmc->sleepq_len--;\r
2510                         tx_counts++;\r
2511                         \r
2512                         if (psta_bmc->sleepq_len > 0)\r
2513                                 pxmitframe->attrib.mdata = 1;\r
2514                         else\r
2515                                 pxmitframe->attrib.mdata = 0;\r
2516 \r
2517                         if (tx_counts == HIQ_XMIT_COUNTS)\r
2518                                 pxmitframe->attrib.mdata = 0;\r
2519                         \r
2520                         pxmitframe->attrib.triggered = 1;\r
2521 \r
2522                         if (xmitframe_hiq_filter(pxmitframe) == _TRUE)\r
2523                                 pxmitframe->attrib.qsel = QSLT_HIGH;/*HIQ*/\r
2524 \r
2525                         rtw_hal_xmitframe_enqueue(padapter, pxmitframe);\r
2526 \r
2527                         if (tx_counts == HIQ_XMIT_COUNTS)\r
2528                                 break;\r
2529                         \r
2530                 }\r
2531 \r
2532         } else {\r
2533                 if (psta_bmc->sleepq_len == 0) {\r
2534                         \r
2535                         /*DBG_871X("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/\r
2536                         \r
2537                         if (pstapriv->tim_bitmap & BIT(0))\r
2538                                 update_tim = _TRUE;\r
2539 \r
2540                         pstapriv->tim_bitmap &= ~BIT(0);\r
2541                         pstapriv->sta_dz_bitmap &= ~BIT(0);\r
2542 \r
2543                         if (update_tim == _TRUE) {\r
2544                                 DBG_871X("clear TIB\n");\r
2545                                 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty");\r
2546                         }                       \r
2547                 }\r
2548         }\r
2549 \r
2550         _exit_critical_bh(&pxmitpriv->lock, &irqL);\r
2551 \r
2552 /*\r
2553         //HIQ Check\r
2554         rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);\r
2555 \r
2556         while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000)\r
2557         {\r
2558                 rtw_msleep_os(100);\r
2559                 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);\r
2560         }\r
2561 \r
2562 \r
2563         printk("check if hiq empty=%d\n", empty);\r
2564 */\r
2565 \r
2566         return H2C_SUCCESS;\r
2567 }\r
2568 \r
2569 #ifdef CONFIG_NATIVEAP_MLME\r
2570 \r
2571 static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type)\r
2572 {\r
2573         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2574 \r
2575         DBG_871X("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->hwaddr), sta_info_type);\r
2576         \r
2577         if (sta_info_type & STA_INFO_UPDATE_BW) {\r
2578 \r
2579                 if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) {\r
2580                         if (pmlmepriv->sw_to_20mhz) {\r
2581                                 psta->bw_mode = CHANNEL_WIDTH_20;\r
2582                                 /*psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;*/\r
2583                                 psta->htpriv.sgi_40m = _FALSE;                          \r
2584                         } else {\r
2585                                 /*TODO: Switch back to 40MHZ?80MHZ*/\r
2586                         }\r
2587                 }               \r
2588         }\r
2589 \r
2590 /*\r
2591         if (sta_info_type & STA_INFO_UPDATE_RATE) {\r
2592                 \r
2593         }\r
2594 */      \r
2595 \r
2596         if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE)\r
2597                 VCS_update(padapter, psta);\r
2598         \r
2599 /*\r
2600         if (sta_info_type & STA_INFO_UPDATE_CAP) {\r
2601                 \r
2602         }\r
2603 \r
2604         if (sta_info_type & STA_INFO_UPDATE_HT_CAP) {\r
2605                 \r
2606         }\r
2607 \r
2608         if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) {\r
2609                 \r
2610         }       \r
2611 */\r
2612 \r
2613 }\r
2614 \r
2615 static void update_bcn_ext_capab_ie(_adapter *padapter)\r
2616 {\r
2617         sint ie_len = 0;\r
2618         unsigned char   *pbuf;\r
2619         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2620         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2621         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2622         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2623         u8 *ie = pnetwork->IEs; \r
2624         u8 null_extcap_data[8] = {0};\r
2625         \r
2626         pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));\r
2627         if (pbuf && ie_len > 0)\r
2628                 rtw_remove_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_);\r
2629 \r
2630         if ((pmlmepriv->ext_capab_ie_len > 0) && \r
2631                 (_rtw_memcmp(pmlmepriv->ext_capab_ie_data, null_extcap_data, sizeof(null_extcap_data)) == _FALSE))\r
2632                 rtw_add_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_, pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len);\r
2633         \r
2634 }\r
2635 \r
2636 static void update_bcn_fixed_ie(_adapter *padapter)\r
2637 {\r
2638         DBG_871X("%s\n", __FUNCTION__);\r
2639 \r
2640 }\r
2641 \r
2642 static void update_bcn_erpinfo_ie(_adapter *padapter)\r
2643 {\r
2644         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2645         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2646         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2647         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2648         unsigned char *p, *ie = pnetwork->IEs;\r
2649         u32 len = 0;\r
2650 \r
2651         DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);\r
2652 \r
2653         if(!pmlmeinfo->ERP_enable)\r
2654                 return;\r
2655 \r
2656         //parsing ERP_IE\r
2657         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));\r
2658         if(p && len>0)\r
2659         {\r
2660                 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;\r
2661 \r
2662                 if (pmlmepriv->num_sta_non_erp == 1)\r
2663                         pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;\r
2664                 else\r
2665                         pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);\r
2666 \r
2667                 if(pmlmepriv->num_sta_no_short_preamble > 0)\r
2668                         pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;\r
2669                 else\r
2670                         pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);\r
2671         \r
2672                 ERP_IE_handler(padapter, pIE);\r
2673         }\r
2674         \r
2675 }\r
2676 \r
2677 static void update_bcn_htcap_ie(_adapter *padapter)\r
2678 {\r
2679         DBG_871X("%s\n", __FUNCTION__);\r
2680 \r
2681 }\r
2682 \r
2683 static void update_bcn_htinfo_ie(_adapter *padapter)\r
2684 {       \r
2685         /*\r
2686         u8 beacon_updated = _FALSE;\r
2687         u32 sta_info_update_type = STA_INFO_UPDATE_NONE;        \r
2688         */\r
2689         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2690         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2691         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2692         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2693         unsigned char *p, *ie = pnetwork->IEs;\r
2694         u32 len = 0;    \r
2695 \r
2696         if (pmlmepriv->htpriv.ht_option == _FALSE) \r
2697                 return;\r
2698 \r
2699         if (pmlmeinfo->HT_info_enable != 1)\r
2700                 return;\r
2701 \r
2702 \r
2703         DBG_871X("%s current operation mode=0x%X\n",\r
2704                    __FUNCTION__, pmlmepriv->ht_op_mode);\r
2705 \r
2706         DBG_871X("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n", \r
2707                                         pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, pmlmepriv->olbc);\r
2708 \r
2709         /*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/\r
2710         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));\r
2711         if (p && len > 0) {\r
2712                 struct HT_info_element *pht_info = NULL;\r
2713                 \r
2714                 pht_info = (struct HT_info_element *)(p + 2);           \r
2715 \r
2716                 /* for STA Channel Width/Secondary Channel Offset*/\r
2717                 if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->cur_channel <= 14)) {\r
2718                         if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE) \r
2719                                 || (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (pmlmepriv->olbc == _TRUE)) {\r
2720                                 SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0);\r
2721                                 SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0);\r
2722 \r
2723                                 pmlmepriv->sw_to_20mhz = 1;\r
2724                                 /*\r
2725                                 sta_info_update_type |= STA_INFO_UPDATE_BW;\r
2726                                 beacon_updated = _TRUE;\r
2727                                 */\r
2728         \r
2729                                 DBG_871X("%s:switching to 20Mhz\n", __FUNCTION__);      \r
2730 \r
2731                                 /*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/\r
2732                         }\r
2733                 } else {\r
2734 \r
2735                         if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE) \r
2736                                 && (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (pmlmepriv->olbc == _FALSE)) {\r
2737 \r
2738                                 if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_40) {\r
2739                                         \r
2740                                         SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1);\r
2741 \r
2742                                         SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, \r
2743                                         (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) ? \r
2744                                                 HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW);\r
2745                                         \r
2746                                         pmlmepriv->sw_to_20mhz = 0;\r
2747                                         /*\r
2748                                         sta_info_update_type |= STA_INFO_UPDATE_BW;\r
2749                                         beacon_updated = _TRUE;\r
2750                                         */\r
2751                                         \r
2752                                         DBG_871X("%s:switching back to 40Mhz\n", __FUNCTION__); \r
2753                                 }\r
2754                         }\r
2755                 }\r
2756 \r
2757                 /* to update  ht_op_mode*/\r
2758                 *(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode);\r
2759                 \r
2760         }       \r
2761 \r
2762         /*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/\r
2763 \r
2764 }\r
2765 \r
2766 static void update_bcn_rsn_ie(_adapter *padapter)\r
2767 {\r
2768         DBG_871X("%s\n", __FUNCTION__);\r
2769 \r
2770 }\r
2771 \r
2772 static void update_bcn_wpa_ie(_adapter *padapter)\r
2773 {\r
2774         DBG_871X("%s\n", __FUNCTION__);\r
2775 \r
2776 }\r
2777 \r
2778 static void update_bcn_wmm_ie(_adapter *padapter)\r
2779 {\r
2780         DBG_871X("%s\n", __FUNCTION__);\r
2781         \r
2782 }\r
2783 \r
2784 static void update_bcn_wps_ie(_adapter *padapter)\r
2785 {\r
2786         u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;\r
2787         uint wps_ielen=0, wps_offset, remainder_ielen;\r
2788         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2789         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2790         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2791         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2792         unsigned char *ie = pnetwork->IEs;\r
2793         u32 ielen = pnetwork->IELength;\r
2794 \r
2795 \r
2796         DBG_871X("%s\n", __FUNCTION__);\r
2797 \r
2798         pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);\r
2799         \r
2800         if(pwps_ie==NULL || wps_ielen==0)\r
2801                 return;\r
2802 \r
2803         pwps_ie_src = pmlmepriv->wps_beacon_ie;\r
2804         if(pwps_ie_src == NULL)\r
2805                 return;\r
2806 \r
2807         wps_offset = (uint)(pwps_ie-ie);\r
2808 \r
2809         premainder_ie = pwps_ie + wps_ielen;\r
2810 \r
2811         remainder_ielen = ielen - wps_offset - wps_ielen;\r
2812 \r
2813         if(remainder_ielen>0)\r
2814         {\r
2815                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
2816                 if(pbackup_remainder_ie)\r
2817                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
2818         }\r
2819 \r
2820         wps_ielen = (uint)pwps_ie_src[1];//to get ie data len\r
2821         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)\r
2822         {\r
2823                 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);\r
2824                 pwps_ie += (wps_ielen+2);\r
2825 \r
2826                 if(pbackup_remainder_ie)\r
2827                         _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);\r
2828 \r
2829                 //update IELength\r
2830                 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;\r
2831         }\r
2832 \r
2833         if(pbackup_remainder_ie)\r
2834                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
2835         \r
2836         // deal with the case without set_tx_beacon_cmd() in update_beacon() \r
2837 #if defined( CONFIG_INTERRUPT_BASED_TXBCN ) || defined( CONFIG_PCI_HCI )\r
2838         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)\r
2839         {\r
2840                 u8 sr = 0;\r
2841                 rtw_get_wps_attr_content(pwps_ie_src,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);\r
2842         \r
2843                 if( sr ) {\r
2844                         set_fwstate(pmlmepriv, WIFI_UNDER_WPS);\r
2845                         DBG_871X("%s, set WIFI_UNDER_WPS\n", __func__);\r
2846                 }\r
2847         }\r
2848 #endif\r
2849 }\r
2850 \r
2851 static void update_bcn_p2p_ie(_adapter *padapter)\r
2852 {\r
2853 \r
2854 }\r
2855 \r
2856 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)\r
2857 {\r
2858         DBG_871X("%s\n", __FUNCTION__);\r
2859 \r
2860         if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))\r
2861         {\r
2862                 update_bcn_wpa_ie(padapter);\r
2863         }\r
2864         else if(_rtw_memcmp(WMM_OUI, oui, 4))\r
2865         {\r
2866                 update_bcn_wmm_ie(padapter);\r
2867         }\r
2868         else if(_rtw_memcmp(WPS_OUI, oui, 4))\r
2869         {\r
2870                 update_bcn_wps_ie(padapter);\r
2871         }\r
2872         else if(_rtw_memcmp(P2P_OUI, oui, 4))\r
2873         {\r
2874                 update_bcn_p2p_ie(padapter);\r
2875         }\r
2876         else\r
2877         {\r
2878                 DBG_871X("unknown OUI type!\n");\r
2879         }\r
2880         \r
2881         \r
2882 }\r
2883 \r
2884 void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, const char *tag)\r
2885 {\r
2886         _irqL irqL;\r
2887         struct mlme_priv *pmlmepriv;\r
2888         struct mlme_ext_priv    *pmlmeext;\r
2889         //struct mlme_ext_info  *pmlmeinfo;\r
2890         \r
2891         //DBG_871X("%s\n", __FUNCTION__);\r
2892 \r
2893         if(!padapter)\r
2894                 return;\r
2895 \r
2896         pmlmepriv = &(padapter->mlmepriv);\r
2897         pmlmeext = &(padapter->mlmeextpriv);\r
2898         //pmlmeinfo = &(pmlmeext->mlmext_info);\r
2899 \r
2900         if(_FALSE == pmlmeext->bstart_bss)\r
2901                 return;\r
2902 \r
2903         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);\r
2904 \r
2905         switch(ie_id)\r
2906         {\r
2907                 case 0xFF:\r
2908 \r
2909                         update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability\r
2910                         \r
2911                         break;\r
2912         \r
2913                 case _TIM_IE_:\r
2914                         \r
2915                         update_BCNTIM(padapter);\r
2916                         \r
2917                         break;\r
2918 \r
2919                 case _ERPINFO_IE_:\r
2920 \r
2921                         update_bcn_erpinfo_ie(padapter);\r
2922 \r
2923                         break;\r
2924 \r
2925                 case _HT_CAPABILITY_IE_:\r
2926 \r
2927                         update_bcn_htcap_ie(padapter);\r
2928                         \r
2929                         break;\r
2930 \r
2931                 case _RSN_IE_2_:\r
2932 \r
2933                         update_bcn_rsn_ie(padapter);\r
2934 \r
2935                         break;\r
2936                         \r
2937                 case _HT_ADD_INFO_IE_:\r
2938 \r
2939                         update_bcn_htinfo_ie(padapter);\r
2940                         \r
2941                         break;\r
2942         \r
2943                 case _EXT_CAP_IE_:\r
2944 \r
2945                         update_bcn_ext_capab_ie(padapter);\r
2946 \r
2947                         break;\r
2948         \r
2949                 case _VENDOR_SPECIFIC_IE_:\r
2950 \r
2951                         update_bcn_vendor_spec_ie(padapter, oui);\r
2952                         \r
2953                         break;\r
2954                         \r
2955                 default:\r
2956                         break;\r
2957         }\r
2958 \r
2959         pmlmepriv->update_bcn = _TRUE;\r
2960         \r
2961         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);          \r
2962         \r
2963 #ifndef CONFIG_INTERRUPT_BASED_TXBCN \r
2964 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
2965         if(tx)\r
2966         {\r
2967                 //send_beacon(padapter);//send_beacon must execute on TSR level\r
2968                 if (0)\r
2969                         DBG_871X(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);\r
2970                 set_tx_beacon_cmd(padapter);\r
2971         }\r
2972 #else\r
2973         {       \r
2974                 //PCI will issue beacon when BCN interrupt occurs.              \r
2975         }\r
2976 #endif\r
2977 #endif //!CONFIG_INTERRUPT_BASED_TXBCN\r
2978         \r
2979 }\r
2980 \r
2981 #ifdef CONFIG_80211N_HT\r
2982 \r
2983 void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len)\r
2984 {\r
2985         struct sta_info *psta;\r
2986         struct sta_priv *pstapriv = &padapter->stapriv;\r
2987         u8 beacon_updated = _FALSE;\r
2988         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2989         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);       \r
2990         uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);\r
2991         u8 category, action;\r
2992 \r
2993         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));\r
2994         if (psta == NULL) \r
2995                 return;\r
2996 \r
2997 \r
2998         category = frame_body[0];\r
2999         action = frame_body[1];\r
3000 \r
3001         if (frame_body_len > 0) {\r
3002                 if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) {                     \r
3003                         u8 ie_data = frame_body[4];\r
3004 \r
3005                         if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) {\r
3006                                 if (psta->ht_40mhz_intolerant == 0) {                           \r
3007                                         psta->ht_40mhz_intolerant = 1;\r
3008                                         pmlmepriv->num_sta_40mhz_intolerant++;\r
3009                                         beacon_updated = _TRUE;\r
3010                                 }       \r
3011                         } else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ)   {                               \r
3012                                 if (pmlmepriv->ht_20mhz_width_req == _FALSE) {                          \r
3013                                         pmlmepriv->ht_20mhz_width_req = _TRUE;                  \r
3014                                         beacon_updated = _TRUE;\r
3015                                 }       \r
3016                         } else\r
3017                                 beacon_updated = _FALSE;\r
3018                 }               \r
3019         }\r
3020 \r
3021         if (frame_body_len > 8) {\r
3022                 /* if EID_BSSIntolerantChlReport ie exists */\r
3023                 if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) {\r
3024                         /*todo:*/\r
3025                         if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) {                           \r
3026                                 pmlmepriv->ht_intolerant_ch_reported = _TRUE;                   \r
3027                                 beacon_updated = _TRUE;\r
3028                         }\r
3029                 }                       \r
3030         }\r
3031 \r
3032         if (beacon_updated) {\r
3033                 \r
3034                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
3035         \r
3036                 associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW);\r
3037         }\r
3038 \r
3039         \r
3040         \r
3041 }\r
3042 \r
3043 void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field)\r
3044 {\r
3045         u8 e_field, m_field;\r
3046         struct sta_info *psta;\r
3047         struct sta_priv *pstapriv = &padapter->stapriv;\r
3048 \r
3049         psta = rtw_get_stainfo(pstapriv, ta);\r
3050         if (psta == NULL) \r
3051                 return;\r
3052 \r
3053         e_field = (ctrl_field & BIT(0)) ? 1 : 0;\r
3054         m_field = (ctrl_field & BIT(1)) ? 1 : 0;        \r
3055 \r
3056         if (e_field) {\r
3057 \r
3058                 /* enable */\r
3059                 /* 0:static SMPS, 1:dynamic SMPS, 3:SMPS disabled, 2:reserved*/\r
3060                  \r
3061                 if (m_field) /*mode*/\r
3062                         psta->htpriv.smps_cap = 1;\r
3063                 else\r
3064                         psta->htpriv.smps_cap = 0;\r
3065         } else {\r
3066                 /*disable*/\r
3067                 psta->htpriv.smps_cap = 3;\r
3068         }\r
3069 \r
3070         rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);\r
3071 \r
3072 }\r
3073 \r
3074 /*\r
3075 op_mode\r
3076 Set to 0 (HT pure) under the followign conditions\r
3077         - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or\r
3078         - all STAs in the BSS are 20 MHz HT in 20 MHz BSS\r
3079 Set to 1 (HT non-member protection) if there may be non-HT STAs\r
3080         in both the primary and the secondary channel\r
3081 Set to 2 if only HT STAs are associated in BSS,\r
3082         however and at least one 20 MHz HT STA is associated\r
3083 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated\r
3084         (currently non-GF HT station is considered as non-HT STA also)\r
3085 */\r
3086 static int rtw_ht_operation_update(_adapter *padapter)\r
3087 {\r
3088         u16 cur_op_mode, new_op_mode;\r
3089         int op_mode_changes = 0;\r
3090         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3091         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
3092 \r
3093         if (pmlmepriv->htpriv.ht_option == _FALSE) \r
3094                 return 0;\r
3095         \r
3096         /*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)\r
3097                 return 0;*/\r
3098 \r
3099         DBG_871X("%s current operation mode=0x%X\n",\r
3100                    __FUNCTION__, pmlmepriv->ht_op_mode);\r
3101 \r
3102         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)\r
3103             && pmlmepriv->num_sta_ht_no_gf) {\r
3104                 pmlmepriv->ht_op_mode |=\r
3105                         HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
3106                 op_mode_changes++;\r
3107         } else if ((pmlmepriv->ht_op_mode &\r
3108                     HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&\r
3109                    pmlmepriv->num_sta_ht_no_gf == 0) {\r
3110                 pmlmepriv->ht_op_mode &=\r
3111                         ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
3112                 op_mode_changes++;\r
3113         }\r
3114 \r
3115         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
3116             (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {\r
3117                 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
3118                 op_mode_changes++;\r
3119         } else if ((pmlmepriv->ht_op_mode &\r
3120                     HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
3121                    (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {\r
3122                 pmlmepriv->ht_op_mode &=\r
3123                         ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
3124                 op_mode_changes++;\r
3125         }\r
3126 \r
3127         /* Note: currently we switch to the MIXED op mode if HT non-greenfield\r
3128          * station is associated. Probably it's a theoretical case, since\r
3129          * it looks like all known HT STAs support greenfield.\r
3130          */\r
3131         new_op_mode = 0;\r
3132         if (pmlmepriv->num_sta_no_ht /*||\r
3133             (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/)\r
3134                 new_op_mode = OP_MODE_MIXED;\r
3135         else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)\r
3136                  && pmlmepriv->num_sta_ht_20mhz)\r
3137                 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;\r
3138         else if (pmlmepriv->olbc_ht)\r
3139                 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;\r
3140         else\r
3141                 new_op_mode = OP_MODE_PURE;\r
3142 \r
3143         cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
3144         if (cur_op_mode != new_op_mode) {\r
3145                 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
3146                 pmlmepriv->ht_op_mode |= new_op_mode;\r
3147                 op_mode_changes++;\r
3148         }\r
3149 \r
3150         DBG_871X("%s new operation mode=0x%X changes=%d\n",\r
3151                    __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);\r
3152 \r
3153         return op_mode_changes;\r
3154         \r
3155 }\r
3156 \r
3157 #endif /* CONFIG_80211N_HT */\r
3158 \r
3159 void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type)\r
3160 {\r
3161         //update associcated stations cap.\r
3162         if(updated == _TRUE)\r
3163         {\r
3164                 _irqL irqL;\r
3165                 _list   *phead, *plist;\r
3166                 struct sta_info *psta=NULL;     \r
3167                 struct sta_priv *pstapriv = &padapter->stapriv;\r
3168                         \r
3169                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3170                 \r
3171                 phead = &pstapriv->asoc_list;\r
3172                 plist = get_next(phead);\r
3173                 \r
3174                 //check asoc_queue\r
3175                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
3176                 {\r
3177                         psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3178                 \r
3179                         plist = get_next(plist);\r
3180 \r
3181                         associated_stainfo_update(padapter, psta, sta_info_type);                       \r
3182                 }\r
3183 \r
3184                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3185 \r
3186         }               \r
3187 \r
3188 }\r
3189 \r
3190 /* called > TSR LEVEL for USB or SDIO Interface*/\r
3191 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)\r
3192 {\r
3193         u8 beacon_updated = _FALSE;\r
3194         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3195         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
3196 \r
3197         \r
3198 #if 0\r
3199         if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&\r
3200             !psta->no_short_preamble_set) {\r
3201                 psta->no_short_preamble_set = 1;\r
3202                 pmlmepriv->num_sta_no_short_preamble++;\r
3203                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
3204                      (pmlmepriv->num_sta_no_short_preamble == 1))\r
3205                         ieee802_11_set_beacons(hapd->iface);\r
3206         }\r
3207 #endif\r
3208 \r
3209 \r
3210         if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))    \r
3211         {\r
3212                 if(!psta->no_short_preamble_set)\r
3213                 {\r
3214                         psta->no_short_preamble_set = 1;\r
3215                         \r
3216                         pmlmepriv->num_sta_no_short_preamble++;\r
3217                         \r
3218                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
3219                                 (pmlmepriv->num_sta_no_short_preamble == 1))\r
3220                         {\r
3221                                 beacon_updated = _TRUE;\r
3222                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3223                         }       \r
3224                         \r
3225                 }\r
3226         }\r
3227         else\r
3228         {\r
3229                 if(psta->no_short_preamble_set)\r
3230                 {\r
3231                         psta->no_short_preamble_set = 0;\r
3232                         \r
3233                         pmlmepriv->num_sta_no_short_preamble--;\r
3234                         \r
3235                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
3236                                 (pmlmepriv->num_sta_no_short_preamble == 0))\r
3237                         {\r
3238                                 beacon_updated = _TRUE;\r
3239                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3240                         }       \r
3241                         \r
3242                 }\r
3243         }\r
3244 \r
3245 #if 0\r
3246         if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {\r
3247                 psta->nonerp_set = 1;\r
3248                 pmlmepriv->num_sta_non_erp++;\r
3249                 if (pmlmepriv->num_sta_non_erp == 1)\r
3250                         ieee802_11_set_beacons(hapd->iface);\r
3251         }\r
3252 #endif\r
3253 \r
3254         if(psta->flags & WLAN_STA_NONERP)\r
3255         {\r
3256                 if(!psta->nonerp_set)\r
3257                 {\r
3258                         psta->nonerp_set = 1;\r
3259                         \r
3260                         pmlmepriv->num_sta_non_erp++;\r
3261                         \r
3262                         if (pmlmepriv->num_sta_non_erp == 1)\r
3263                         {\r
3264                                 beacon_updated = _TRUE;\r
3265                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
3266                         }       \r
3267                 }\r
3268                 \r
3269         }\r
3270         else\r
3271         {\r
3272                 if(psta->nonerp_set)\r
3273                 {\r
3274                         psta->nonerp_set = 0;\r
3275                         \r
3276                         pmlmepriv->num_sta_non_erp--;\r
3277                         \r
3278                         if (pmlmepriv->num_sta_non_erp == 0)\r
3279                         {\r
3280                                 beacon_updated = _TRUE;\r
3281                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
3282                         }       \r
3283                 }\r
3284                 \r
3285         }\r
3286 \r
3287 \r
3288 #if 0\r
3289         if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&\r
3290             !psta->no_short_slot_time_set) {\r
3291                 psta->no_short_slot_time_set = 1;\r
3292                 pmlmepriv->num_sta_no_short_slot_time++;\r
3293                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
3294                     (pmlmepriv->num_sta_no_short_slot_time == 1))\r
3295                         ieee802_11_set_beacons(hapd->iface);\r
3296         }\r
3297 #endif\r
3298 \r
3299         if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))\r
3300         {\r
3301                 if(!psta->no_short_slot_time_set)\r
3302                 {\r
3303                         psta->no_short_slot_time_set = 1;\r
3304                         \r
3305                         pmlmepriv->num_sta_no_short_slot_time++;\r
3306                         \r
3307                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
3308                                  (pmlmepriv->num_sta_no_short_slot_time == 1))\r
3309                         {\r
3310                                 beacon_updated = _TRUE;\r
3311                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3312                         }                       \r
3313                         \r
3314                 }\r
3315         }\r
3316         else\r
3317         {\r
3318                 if(psta->no_short_slot_time_set)\r
3319                 {\r
3320                         psta->no_short_slot_time_set = 0;\r
3321                         \r
3322                         pmlmepriv->num_sta_no_short_slot_time--;\r
3323                         \r
3324                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
3325                                  (pmlmepriv->num_sta_no_short_slot_time == 0))\r
3326                         {\r
3327                                 beacon_updated = _TRUE;\r
3328                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3329                         }                       \r
3330                 }\r
3331         }       \r
3332         \r
3333 #ifdef CONFIG_80211N_HT\r
3334 \r
3335         if (psta->flags & WLAN_STA_HT) \r
3336         {\r
3337                 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);\r
3338                         \r
3339                 DBG_871X("HT: STA " MAC_FMT " HT Capabilities "\r
3340                            "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);\r
3341 \r
3342                 if (psta->no_ht_set) {\r
3343                         psta->no_ht_set = 0;\r
3344                         pmlmepriv->num_sta_no_ht--;\r
3345                 }\r
3346                 \r
3347                 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {\r
3348                         if (!psta->no_ht_gf_set) {\r
3349                                 psta->no_ht_gf_set = 1;\r
3350                                 pmlmepriv->num_sta_ht_no_gf++;\r
3351                         }\r
3352                         DBG_871X("%s STA " MAC_FMT " - no "\r
3353                                    "greenfield, num of non-gf stations %d\n",\r
3354                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
3355                                    pmlmepriv->num_sta_ht_no_gf);\r
3356                 }\r
3357                 \r
3358                 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {\r
3359                         if (!psta->ht_20mhz_set) {\r
3360                                 psta->ht_20mhz_set = 1;\r
3361                                 pmlmepriv->num_sta_ht_20mhz++;\r
3362                         }\r
3363                         DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "\r
3364                                    "num of 20MHz HT STAs %d\n",\r
3365                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
3366                                    pmlmepriv->num_sta_ht_20mhz);\r
3367                 }\r
3368                 \r
3369 \r
3370                 if (ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) {\r
3371 \r
3372                         if (!psta->ht_40mhz_intolerant) {\r
3373                                 psta->ht_40mhz_intolerant = 1;\r
3374                                 pmlmepriv->num_sta_40mhz_intolerant++;\r
3375                                 DBG_871X("%s STA " MAC_FMT " - HT_CAP_40MHZ_INTOLERANT is set\n" ,\r
3376                                    __FUNCTION__, MAC_ARG(psta->hwaddr));\r
3377                                 beacon_updated = _TRUE;\r
3378                         }\r
3379                                 \r
3380 /*\r
3381                         if (pmlmepriv->ht_40mhz_intolerant == _FALSE) {\r
3382                                 \r
3383                                 pmlmepriv->ht_40mhz_intolerant = _TRUE;                         \r
3384                         \r
3385                                 DBG_871X("%s STA " MAC_FMT " - HT_CAP_40MHZ_INTOLERANT is set\n" ,\r
3386                                    __FUNCTION__, MAC_ARG(psta->hwaddr));\r
3387 \r
3388                                 beacon_updated = _TRUE;\r
3389                         }\r
3390 */                      \r
3391 \r
3392                         /*update ext_capab_ie_len & ext_capab_ie_data for beacon, probersp, assocrsp.*/\r
3393                         if (pmlmepriv->ext_capab_ie_len == 0)\r
3394                                 pmlmepriv->ext_capab_ie_len = 1;\r
3395                         SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 1);\r
3396 \r
3397                         update_beacon(padapter, _EXT_CAP_IE_, NULL, _FALSE);\r
3398                 }               \r
3399                 \r
3400         } \r
3401         else \r
3402         {\r
3403                 if (!psta->no_ht_set) {\r
3404                         psta->no_ht_set = 1;\r
3405                         pmlmepriv->num_sta_no_ht++;\r
3406                 }\r
3407                 if(pmlmepriv->htpriv.ht_option == _TRUE) {              \r
3408                         DBG_871X("%s STA " MAC_FMT\r
3409                                    " - no HT, num of non-HT stations %d\n",\r
3410                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
3411                                    pmlmepriv->num_sta_no_ht);\r
3412                 }\r
3413         }\r
3414 \r
3415         if (rtw_ht_operation_update(padapter) > 0) {\r
3416                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
3417                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
3418                 /*beacon_updated = _TRUE;*/\r
3419         }       \r
3420         \r
3421 #endif /* CONFIG_80211N_HT */\r
3422 \r
3423         //update associcated stations cap.\r
3424         associated_clients_update(padapter,  beacon_updated, STA_INFO_UPDATE_ALL);\r
3425 \r
3426         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
3427 \r
3428 }\r
3429 \r
3430 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)\r
3431 {\r
3432         u8 beacon_updated = _FALSE;\r
3433         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3434         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
3435 \r
3436         if(!psta)\r
3437                 return beacon_updated;\r
3438 \r
3439         if (psta->no_short_preamble_set) {\r
3440                 psta->no_short_preamble_set = 0;\r
3441                 pmlmepriv->num_sta_no_short_preamble--;\r
3442                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
3443                     && pmlmepriv->num_sta_no_short_preamble == 0)\r
3444                 {\r
3445                         beacon_updated = _TRUE;\r
3446                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3447                 }       \r
3448         }       \r
3449 \r
3450         if (psta->nonerp_set) {\r
3451                 psta->nonerp_set = 0;           \r
3452                 pmlmepriv->num_sta_non_erp--;\r
3453                 if (pmlmepriv->num_sta_non_erp == 0)\r
3454                 {\r
3455                         beacon_updated = _TRUE;\r
3456                         update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
3457                 }       \r
3458         }\r
3459 \r
3460         if (psta->no_short_slot_time_set) {\r
3461                 psta->no_short_slot_time_set = 0;\r
3462                 pmlmepriv->num_sta_no_short_slot_time--;\r
3463                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
3464                     && pmlmepriv->num_sta_no_short_slot_time == 0)\r
3465                 {\r
3466                         beacon_updated = _TRUE;\r
3467                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
3468                 }       \r
3469         }\r
3470         \r
3471 #ifdef CONFIG_80211N_HT\r
3472 \r
3473         if (psta->no_ht_gf_set) {\r
3474                 psta->no_ht_gf_set = 0;\r
3475                 pmlmepriv->num_sta_ht_no_gf--;\r
3476         }\r
3477 \r
3478         if (psta->no_ht_set) {\r
3479                 psta->no_ht_set = 0;\r
3480                 pmlmepriv->num_sta_no_ht--;\r
3481         }\r
3482 \r
3483         if (psta->ht_20mhz_set) {\r
3484                 psta->ht_20mhz_set = 0;\r
3485                 pmlmepriv->num_sta_ht_20mhz--;\r
3486         }\r
3487 \r
3488         if (psta->ht_40mhz_intolerant) {\r
3489                 psta->ht_40mhz_intolerant = 0;\r
3490                 pmlmepriv->num_sta_40mhz_intolerant--;\r
3491 \r
3492                 /*update ext_capab_ie_len & ext_capab_ie_data for beacon, probersp, assocrsp.*/\r
3493                 if ((pmlmepriv->ext_capab_ie_len > 0) && (pmlmepriv->num_sta_40mhz_intolerant == 0)) {\r
3494                         SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 0);\r
3495                         update_beacon(padapter, _EXT_CAP_IE_, NULL, _FALSE);\r
3496                 }\r
3497                 \r
3498                 beacon_updated = _TRUE;\r
3499 \r
3500                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);\r
3501         }\r
3502 \r
3503         if (rtw_ht_operation_update(padapter) > 0) {\r
3504                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
3505                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
3506         }\r
3507         \r
3508 #endif /* CONFIG_80211N_HT */\r
3509 \r
3510         /* update associated stations cap.\r
3511         associated_clients_update(padapter,  beacon_updated, STA_INFO_UPDATE_ALL); //move it to avoid deadlock\r
3512         */\r
3513         \r
3514         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
3515 \r
3516         return beacon_updated;\r
3517 \r
3518 }\r
3519 \r
3520 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue)\r
3521 {\r
3522         _irqL irqL;\r
3523         u8 beacon_updated = _FALSE;\r
3524         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3525         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
3526         struct sta_priv *pstapriv = &padapter->stapriv;\r
3527 \r
3528         if(!psta)\r
3529                 return beacon_updated;\r
3530 \r
3531         if (active == _TRUE)\r
3532         {\r
3533 #ifdef CONFIG_80211N_HT\r
3534                 //tear down Rx AMPDU\r
3535                 send_delba(padapter, 0, psta->hwaddr);// recipient\r
3536         \r
3537                 //tear down TX AMPDU\r
3538                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
3539                 \r
3540 #endif //CONFIG_80211N_HT\r
3541 \r
3542                 issue_deauth(padapter, psta->hwaddr, reason);\r
3543         }\r
3544 \r
3545 #ifdef CONFIG_BEAMFORMING\r
3546         beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->hwaddr, ETH_ALEN, 1);\r
3547 #endif\r
3548 \r
3549         psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
3550         psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
3551 \r
3552         //clear cam entry / key\r
3553         rtw_clearstakey_cmd(padapter, psta, enqueue);\r
3554 \r
3555 \r
3556         _enter_critical_bh(&psta->lock, &irqL);\r
3557         psta->state &= ~_FW_LINKED;\r
3558         _exit_critical_bh(&psta->lock, &irqL);\r
3559 \r
3560         #ifdef CONFIG_IOCTL_CFG80211\r
3561         if (1) {\r
3562                 #ifdef COMPAT_KERNEL_RELEASE\r
3563                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
3564                 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
3565                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
3566                 #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
3567                 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */\r
3568                 #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
3569         } else\r
3570         #endif //CONFIG_IOCTL_CFG80211\r
3571         {\r
3572                 rtw_indicate_sta_disassoc_event(padapter, psta);\r
3573         }\r
3574 \r
3575         report_del_sta_event(padapter, psta->hwaddr, reason, enqueue);\r
3576 \r
3577         beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);\r
3578 \r
3579         //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                                        \r
3580         rtw_free_stainfo(padapter, psta);\r
3581         //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
3582         \r
3583 \r
3584         return beacon_updated;\r
3585 \r
3586 }\r
3587 \r
3588 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)\r
3589 {\r
3590         _irqL irqL;\r
3591         _list   *phead, *plist;\r
3592         int ret=0;      \r
3593         struct sta_info *psta = NULL;   \r
3594         struct sta_priv *pstapriv = &padapter->stapriv;\r
3595         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3596         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3597         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
3598 \r
3599         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
3600                 return ret;\r
3601 \r
3602         DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",\r
3603                 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);\r
3604 \r
3605         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3606         phead = &pstapriv->asoc_list;\r
3607         plist = get_next(phead);\r
3608         \r
3609         /* for each sta in asoc_queue */\r
3610         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
3611         {               \r
3612                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3613                 plist = get_next(plist);\r
3614 \r
3615                 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);\r
3616                 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);\r
3617         }\r
3618         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3619 \r
3620         issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);\r
3621 \r
3622         return ret;\r
3623 }\r
3624 \r
3625 int rtw_sta_flush(_adapter *padapter, bool enqueue)\r
3626 {\r
3627         _irqL irqL;\r
3628         _list   *phead, *plist;\r
3629         int ret = 0;\r
3630         struct sta_info *psta = NULL;   \r
3631         struct sta_priv *pstapriv = &padapter->stapriv;\r
3632         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3633         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3634         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
3635         u8 flush_num = 0;\r
3636         char flush_list[NUM_STA];\r
3637         int i;\r
3638 \r
3639         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
3640                 return ret;\r
3641 \r
3642         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));\r
3643 \r
3644         /* pick sta from sta asoc_queue */\r
3645         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3646         phead = &pstapriv->asoc_list;\r
3647         plist = get_next(phead);\r
3648         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {\r
3649                 int stainfo_offset;\r
3650 \r
3651                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3652                 plist = get_next(plist);\r
3653 \r
3654                 rtw_list_delete(&psta->asoc_list);\r
3655                 pstapriv->asoc_list_cnt--;\r
3656 \r
3657                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
3658                 if (stainfo_offset_valid(stainfo_offset))\r
3659                         flush_list[flush_num++] = stainfo_offset;\r
3660                 else\r
3661                         rtw_warn_on(1);\r
3662         }\r
3663         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3664 \r
3665         /* call ap_free_sta() for each sta picked */\r
3666         for (i = 0; i < flush_num; i++) {\r
3667                 psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);\r
3668                 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue);\r
3669         }\r
3670 \r
3671         issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);\r
3672 \r
3673         associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL);\r
3674 \r
3675         return ret;\r
3676 }\r
3677 \r
3678 /* called > TSR LEVEL for USB or SDIO Interface*/\r
3679 void sta_info_update(_adapter *padapter, struct sta_info *psta)\r
3680 {       \r
3681         int flags = psta->flags;\r
3682         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3683         \r
3684                                 \r
3685         //update wmm cap.\r
3686         if(WLAN_STA_WME&flags)\r
3687                 psta->qos_option = 1;\r
3688         else\r
3689                 psta->qos_option = 0;\r
3690 \r
3691         if(pmlmepriv->qospriv.qos_option == 0)  \r
3692                 psta->qos_option = 0;\r
3693 \r
3694                 \r
3695 #ifdef CONFIG_80211N_HT         \r
3696         //update 802.11n ht cap.\r
3697         if(WLAN_STA_HT&flags)\r
3698         {\r
3699                 psta->htpriv.ht_option = _TRUE;\r
3700                 psta->qos_option = 1;   \r
3701 \r
3702                 psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS)>>2;\r
3703         }\r
3704         else            \r
3705         {\r
3706                 psta->htpriv.ht_option = _FALSE;\r
3707         }\r
3708                 \r
3709         if(pmlmepriv->htpriv.ht_option == _FALSE)       \r
3710                 psta->htpriv.ht_option = _FALSE;\r
3711 #endif\r
3712 \r
3713 #ifdef CONFIG_80211AC_VHT\r
3714         //update 802.11AC vht cap.\r
3715         if(WLAN_STA_VHT&flags)\r
3716         {\r
3717                 psta->vhtpriv.vht_option = _TRUE;\r
3718         }\r
3719         else            \r
3720         {\r
3721                 psta->vhtpriv.vht_option = _FALSE;\r
3722         }\r
3723 \r
3724         if(pmlmepriv->vhtpriv.vht_option == _FALSE)\r
3725                 psta->vhtpriv.vht_option = _FALSE;\r
3726 #endif  \r
3727 \r
3728 \r
3729         update_sta_info_apmode(padapter, psta);\r
3730                 \r
3731 \r
3732 }\r
3733 \r
3734 /* called >= TSR LEVEL for USB or SDIO Interface*/\r
3735 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)\r
3736 {\r
3737         if (psta->state & _FW_LINKED) {\r
3738                 //add ratid\r
3739                 add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT\r
3740         }       \r
3741 }\r
3742 /* restore hw setting from sw data structures */\r
3743 void rtw_ap_restore_network(_adapter *padapter)\r
3744 {\r
3745         struct mlme_priv *mlmepriv = &padapter->mlmepriv;\r
3746         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
3747         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3748         struct sta_priv * pstapriv = &padapter->stapriv;\r
3749         struct sta_info *psta;\r
3750         struct security_priv* psecuritypriv=&(padapter->securitypriv);\r
3751         _irqL irqL;\r
3752         _list   *phead, *plist;\r
3753         u8 chk_alive_num = 0;\r
3754         char chk_alive_list[NUM_STA];\r
3755         int i;\r
3756 \r
3757         rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);\r
3758 \r
3759         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);\r
3760 \r
3761         rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY);\r
3762 \r
3763         if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
3764                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
3765         {\r
3766                 /* restore group key, WEP keys is restored in ips_leave() */\r
3767                 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);\r
3768         }\r
3769 \r
3770         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3771         \r
3772         phead = &pstapriv->asoc_list;\r
3773         plist = get_next(phead);\r
3774 \r
3775         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {\r
3776                 int stainfo_offset;\r
3777 \r
3778                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
3779                 plist = get_next(plist);\r
3780 \r
3781                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
3782                 if (stainfo_offset_valid(stainfo_offset)) {\r
3783                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
3784                 }\r
3785         }\r
3786 \r
3787         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
3788 \r
3789         for (i = 0; i < chk_alive_num; i++) {\r
3790                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
3791 \r
3792                 if (psta == NULL) {\r
3793                         DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));\r
3794                 } else if (psta->state &_FW_LINKED) {\r
3795                         rtw_sta_media_status_rpt(padapter, psta, 1);\r
3796                         Update_RA_Entry(padapter, psta);\r
3797                         //pairwise key\r
3798                         /* per sta pairwise key and settings */\r
3799                         if(     (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
3800                                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
3801                         {\r
3802                                 rtw_setstakey_cmd(padapter, psta, UNICAST_KEY,_FALSE);\r
3803                         }                       \r
3804                 }\r
3805         }\r
3806 \r
3807 }\r
3808 \r
3809 void start_ap_mode(_adapter *padapter)\r
3810 {\r
3811         int i;\r
3812         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3813         struct sta_priv *pstapriv = &padapter->stapriv;\r
3814         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
3815         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
3816         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
3817         \r
3818         pmlmepriv->update_bcn = _FALSE;\r
3819         \r
3820         /*init_mlme_ap_info(padapter);*/\r
3821         \r
3822         pmlmeext->bstart_bss = _FALSE;\r
3823 \r
3824         pmlmepriv->num_sta_non_erp = 0;\r
3825 \r
3826         pmlmepriv->num_sta_no_short_slot_time = 0;\r
3827 \r
3828         pmlmepriv->num_sta_no_short_preamble = 0;\r
3829 \r
3830         pmlmepriv->num_sta_ht_no_gf = 0;\r
3831 #ifdef CONFIG_80211N_HT\r
3832         pmlmepriv->num_sta_no_ht = 0;\r
3833 #endif //CONFIG_80211N_HT\r
3834         pmlmeinfo->HT_info_enable = 0;\r
3835         pmlmeinfo->HT_caps_enable = 0;\r
3836         pmlmeinfo->HT_enable = 0;\r
3837         \r
3838         pmlmepriv->num_sta_ht_20mhz = 0;\r
3839         pmlmepriv->num_sta_40mhz_intolerant = 0;\r
3840         pmlmepriv->olbc = _FALSE;\r
3841         pmlmepriv->olbc_ht = _FALSE;\r
3842         \r
3843 #ifdef CONFIG_80211N_HT\r
3844         pmlmepriv->ht_20mhz_width_req = _FALSE;\r
3845         pmlmepriv->ht_intolerant_ch_reported = _FALSE;\r
3846         pmlmepriv->ht_op_mode = 0;\r
3847         pmlmepriv->sw_to_20mhz = 0;\r
3848 #endif\r
3849 \r
3850         _rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data));\r
3851         pmlmepriv->ext_capab_ie_len = 0;\r
3852 \r
3853         for (i = 0 ;  i < NUM_STA ; i++)\r
3854                 pstapriv->sta_aid[i] = NULL;\r
3855         \r
3856         //for ACL \r
3857         _rtw_init_listhead(&(pacl_list->acl_node_q.queue));\r
3858         pacl_list->num = 0;\r
3859         pacl_list->mode = 0;\r
3860         for(i = 0; i < NUM_ACL; i++)\r
3861         {               \r
3862                 _rtw_init_listhead(&pacl_list->aclnode[i].list);\r
3863                 pacl_list->aclnode[i].valid = _FALSE;\r
3864         }\r
3865 \r
3866 }\r
3867 \r
3868 void stop_ap_mode(_adapter *padapter)\r
3869 {\r
3870         _irqL irqL;\r
3871         _list   *phead, *plist;\r
3872         struct rtw_wlan_acl_node *paclnode;\r
3873         struct sta_info *psta=NULL;\r
3874         struct sta_priv *pstapriv = &padapter->stapriv;\r
3875         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3876         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;        \r
3877         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
3878         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
3879 \r
3880         pmlmepriv->update_bcn = _FALSE;\r
3881         pmlmeext->bstart_bss = _FALSE;\r
3882         padapter->netif_up = _FALSE;\r
3883         //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);\r
3884         \r
3885         //reset and init security priv , this can refine with rtw_reset_securitypriv\r
3886         _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));\r
3887         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;\r
3888         padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;\r
3889 \r
3890         #ifdef CONFIG_DFS_MASTER\r
3891         rtw_dfs_master_status_apply(padapter, MLME_AP_STOPPED);\r
3892         #endif\r
3893 \r
3894         /* free scan queue */\r
3895         rtw_free_network_queue(padapter, _TRUE);\r
3896 \r
3897         //for ACL\r
3898         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
3899         phead = get_list_head(pacl_node_q);\r
3900         plist = get_next(phead);                \r
3901         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
3902         {\r
3903                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
3904                 plist = get_next(plist);\r
3905 \r
3906                 if(paclnode->valid == _TRUE)\r
3907                 {\r
3908                         paclnode->valid = _FALSE;\r
3909 \r
3910                         rtw_list_delete(&paclnode->list);\r
3911                                 \r
3912                         pacl_list->num--;               \r
3913                 }               \r
3914         }       \r
3915         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
3916         \r
3917         DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);\r
3918         \r
3919         rtw_sta_flush(padapter, _TRUE);\r
3920 \r
3921         //free_assoc_sta_resources      \r
3922         rtw_free_all_stainfo(padapter);\r
3923         \r
3924         psta = rtw_get_bcmc_stainfo(padapter);\r
3925         //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                \r
3926         rtw_free_stainfo(padapter, psta);\r
3927         //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
3928         \r
3929         rtw_init_bcmc_stainfo(padapter);        \r
3930 \r
3931         rtw_free_mlme_priv_ie_data(pmlmepriv);\r
3932 \r
3933 #ifdef CONFIG_BT_COEXIST\r
3934         rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect \r
3935 #endif  \r
3936 \r
3937 }\r
3938 \r
3939 #endif //CONFIG_NATIVEAP_MLME\r
3940 \r
3941 void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset)\r
3942 {\r
3943 #define UPDATE_VHT_CAP 1\r
3944 #define UPDATE_HT_CAP 1\r
3945 \r
3946 #ifdef CONFIG_80211AC_VHT\r
3947         {\r
3948                 struct vht_priv *vhtpriv = &adapter->mlmepriv.vhtpriv;\r
3949                 u8 *vht_cap_ie, *vht_op_ie;\r
3950                 int vht_cap_ielen, vht_op_ielen;\r
3951                 u8      center_freq;\r
3952 \r
3953                 vht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3954                 vht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3955                 center_freq = rtw_get_center_ch(ch, bw, offset);\r
3956 \r
3957                 /* update vht cap ie */\r
3958                 if (vht_cap_ie && vht_cap_ielen) {\r
3959                         #if UPDATE_VHT_CAP\r
3960                         /* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m)\r
3961                                 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1);\r
3962                         else */\r
3963                                 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0);\r
3964 \r
3965                         if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m)\r
3966                                 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1);\r
3967                         else\r
3968                                 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0);\r
3969                         #endif\r
3970                 }\r
3971 \r
3972                 /* update vht op ie */\r
3973                 if (vht_op_ie && vht_op_ielen) {\r
3974                         if (bw < CHANNEL_WIDTH_80) {\r
3975                                 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);\r
3976                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);\r
3977                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);\r
3978                         } else if (bw == CHANNEL_WIDTH_80) {\r
3979                                 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1);\r
3980                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq);\r
3981                                 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);\r
3982                         } else {\r
3983                                 DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);\r
3984                                 rtw_warn_on(1);\r
3985                         }\r
3986                 }\r
3987         }\r
3988 #endif /* CONFIG_80211AC_VHT */\r
3989 #ifdef CONFIG_80211N_HT\r
3990         {\r
3991                 struct ht_priv  *htpriv = &adapter->mlmepriv.htpriv;\r
3992                 u8 *ht_cap_ie, *ht_op_ie;\r
3993                 int ht_cap_ielen, ht_op_ielen;\r
3994 \r
3995                 ht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTCapability, &ht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3996                 ht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTInfo, &ht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
3997 \r
3998                 /* update ht cap ie */\r
3999                 if (ht_cap_ie && ht_cap_ielen) {\r
4000                         #if UPDATE_HT_CAP\r
4001                         if (bw >= CHANNEL_WIDTH_40)\r
4002                                 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1);\r
4003                         else\r
4004                                 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0);\r
4005 \r
4006                         if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m)\r
4007                                 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1);\r
4008                         else\r
4009                                 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0);\r
4010 \r
4011                         if (htpriv->sgi_20m)\r
4012                                 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1);\r
4013                         else\r
4014                                 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0);\r
4015                         #endif\r
4016                 }\r
4017 \r
4018                 /* update ht op ie */\r
4019                 if (ht_op_ie && ht_op_ielen) {\r
4020                         SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch);\r
4021                         switch (offset) {\r
4022                         case HAL_PRIME_CHNL_OFFSET_LOWER:\r
4023                                 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCA);\r
4024                                 break;\r
4025                         case HAL_PRIME_CHNL_OFFSET_UPPER:\r
4026                                 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCB);\r
4027                                 break;\r
4028                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:\r
4029                         default:\r
4030                                 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCN);\r
4031                                 break;\r
4032                         }\r
4033 \r
4034                         if (bw >= CHANNEL_WIDTH_40)\r
4035                                 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1);\r
4036                         else\r
4037                                 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0);\r
4038                 }\r
4039         }\r
4040 #endif /* CONFIG_80211N_HT */\r
4041 \r
4042 {\r
4043         u8 *p;\r
4044         int ie_len;\r
4045         u8 old_ch = bss->Configuration.DSConfig;\r
4046         bool change_band = _FALSE;\r
4047 \r
4048         if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14))\r
4049                 change_band = _TRUE;\r
4050 \r
4051         /* update channel in IE */\r
4052         p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));\r
4053         if (p && ie_len > 0)\r
4054                 *(p + 2) = ch;\r
4055 \r
4056         bss->Configuration.DSConfig = ch;\r
4057 \r
4058         /* band is changed, update ERP, support rate, ext support rate IE */\r
4059         if (change_band == _TRUE)\r
4060                 change_band_update_ie(adapter, bss, ch);\r
4061 }\r
4062 \r
4063 }\r
4064 \r
4065 bool rtw_ap_chbw_decision(_adapter *adapter, u8 req_ch, u8 req_bw, u8 req_offset\r
4066         , u8 *ch, u8 *bw, u8 *offset)\r
4067 {\r
4068         u8 dec_ch, dec_bw, dec_offset;\r
4069         u8 u_ch = 0, u_offset, u_bw;\r
4070         bool changed = _FALSE;\r
4071         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);\r
4072         u8 sta_num;\r
4073         u8 ld_sta_num;\r
4074         u8 lg_sta_num;\r
4075         u8 ap_num;\r
4076         u8 ld_ap_num;\r
4077         bool set_u_ch = _FALSE, set_dec_ch = _FALSE;\r
4078 \r
4079         dec_ch = req_ch;\r
4080         dec_bw = req_bw;\r
4081         dec_offset = req_offset;\r
4082         \r
4083         rtw_dev_iface_status_no_self(adapter, &sta_num, &ld_sta_num, &lg_sta_num, &ap_num, &ld_ap_num);\r
4084         DBG_871X(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num%u, ap_num:%u\n"\r
4085                 , FUNC_ADPT_ARG(adapter), ld_sta_num, lg_sta_num, ap_num);\r
4086 \r
4087         if (ld_sta_num || ap_num) {\r
4088                 /* has linked STA or AP mode, follow */\r
4089 \r
4090                 rtw_warn_on(!rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset));\r
4091 \r
4092                 DBG_871X(FUNC_ADPT_FMT" union no self: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);\r
4093                 DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);\r
4094 \r
4095                 rtw_adjust_chbw(adapter, u_ch, &dec_bw, &dec_offset);\r
4096 \r
4097                 rtw_sync_chbw(&dec_ch, &dec_bw, &dec_offset\r
4098                         , &u_ch, &u_bw, &u_offset);\r
4099 \r
4100                 rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)\r
4101                         , dec_ch, dec_bw, dec_offset);\r
4102 \r
4103                 set_u_ch = _TRUE;\r
4104         } else if (lg_sta_num) {\r
4105                 /* has linking STA */\r
4106 \r
4107                 rtw_warn_on(!rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset));\r
4108 \r
4109                 DBG_871X(FUNC_ADPT_FMT" union no self: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);\r
4110                 DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);\r
4111 \r
4112                 rtw_adjust_chbw(adapter, dec_ch, &dec_bw, &dec_offset);\r
4113                 \r
4114                 if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch, dec_bw, dec_offset)) {\r
4115 \r
4116                         rtw_sync_chbw(&dec_ch, &dec_bw, &dec_offset\r
4117                                         , &u_ch, &u_bw, &u_offset);\r
4118 \r
4119                         rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)\r
4120                                 , dec_ch, dec_bw, dec_offset);\r
4121 \r
4122                         set_u_ch = _TRUE;\r
4123                 } else {\r
4124                         /* set this for possible ch change when join down*/\r
4125                         set_fwstate(&adapter->mlmepriv, WIFI_OP_CH_SWITCHING);\r
4126                 }\r
4127         } else {\r
4128                 /* single AP mode */\r
4129 \r
4130                 DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);\r
4131                 rtw_adjust_chbw(adapter, dec_ch, &dec_bw, &dec_offset);\r
4132 \r
4133                 #if defined(CONFIG_DFS_MASTER)\r
4134                 /* check NOL */\r
4135                 if (rtw_chset_is_ch_non_ocp(mlmeext->channel_set, dec_ch, dec_bw, dec_offset)) {\r
4136                         /* choose 5G DFS channel for debug */\r
4137                         if (adapter_to_rfctl(adapter)->dbg_dfs_master_choose_dfs_ch_first\r
4138                                 && rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_NON_DFS) == _TRUE) {\r
4139                                 DBG_871X(FUNC_ADPT_FMT" choose 5G DFS channel for debug\n", FUNC_ADPT_ARG(adapter));\r
4140                         } else \r
4141                         /* choose from 5G no DFS */\r
4142                         if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_DFS) == _FALSE) {\r
4143                                 /* including 5G DFS, not long CAC */\r
4144                                 if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_LONG_CAC) == _FALSE) {\r
4145                                         /* including 5G DFS, long CAC */\r
4146                                         if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G) == _FALSE) {\r
4147                                                 /* including 2.4G channel */\r
4148                                                 if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_5G) == _FALSE) {\r
4149                                                         DBG_871X(FUNC_ADPT_FMT" no available ch\n", FUNC_ADPT_ARG(adapter));\r
4150                                                         rtw_warn_on(1);\r
4151                                                 }\r
4152                                         }\r
4153                                 }\r
4154                         }\r
4155                 }\r
4156                 #endif /* defined(CONFIG_DFS_MASTER) */\r
4157 \r
4158                 rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)\r
4159                                 , dec_ch, dec_bw, dec_offset);\r
4160 \r
4161                 set_dec_ch = _TRUE;\r
4162         }\r
4163 \r
4164         if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)\r
4165                 #ifdef CONFIG_CONCURRENT_MODE\r
4166                 || check_buddy_fwstate(adapter, _FW_UNDER_SURVEY)\r
4167                 #endif\r
4168         ) {\r
4169                 /* scanning, leave ch setting to scan state machine */\r
4170                 set_u_ch = set_dec_ch = _FALSE;\r
4171         }\r
4172 \r
4173         if (mlmeext->cur_channel != dec_ch\r
4174                 || mlmeext->cur_bwmode != dec_bw\r
4175                 || mlmeext->cur_ch_offset != dec_offset)\r
4176                 changed = _TRUE;\r
4177 \r
4178         if (changed == _TRUE && rtw_linked_check(adapter) == _TRUE) {\r
4179                 #ifdef CONFIG_SPCT_CH_SWITCH\r
4180                 if (1)\r
4181                         rtw_ap_inform_ch_switch(adapter, dec_ch, dec_offset);\r
4182                 else\r
4183                 #endif\r
4184                         rtw_sta_flush(adapter, _FALSE);\r
4185         }\r
4186 \r
4187         mlmeext->cur_channel = dec_ch;\r
4188         mlmeext->cur_bwmode = dec_bw;\r
4189         mlmeext->cur_ch_offset = dec_offset;\r
4190 \r
4191         if (u_ch != 0)\r
4192                 DBG_871X(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);\r
4193 \r
4194         DBG_871X(FUNC_ADPT_FMT" dec: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), dec_ch, dec_bw, dec_offset);\r
4195 \r
4196         if (set_u_ch == _TRUE) {\r
4197                 *ch = u_ch;\r
4198                 *bw = u_bw;\r
4199                 *offset = u_offset;\r
4200         } else if (set_dec_ch == _TRUE) {\r
4201                 *ch = dec_ch;\r
4202                 *bw = dec_bw;\r
4203                 *offset = dec_offset;\r
4204         }       \r
4205 \r
4206         return changed;\r
4207 }\r
4208 \r
4209 #endif //CONFIG_AP_MODE\r
4210 \r