rtw_sta_mgt.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTW_STA_MGT_C_
  21. #include <drv_types.h>
  22. #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
  23. #error "Shall be Linux or Windows, but not both!\n"
  24. #endif
  25. void _rtw_init_stainfo(struct sta_info *psta);
  26. void _rtw_init_stainfo(struct sta_info *psta)
  27. {
  28. _func_enter_;
  29. _rtw_memset((u8 *)psta, 0, sizeof (struct sta_info));
  30. _rtw_spinlock_init(&psta->lock);
  31. _rtw_init_listhead(&psta->list);
  32. _rtw_init_listhead(&psta->hash_list);
  33. //_rtw_init_listhead(&psta->asoc_list);
  34. //_rtw_init_listhead(&psta->sleep_list);
  35. //_rtw_init_listhead(&psta->wakeup_list);
  36. _rtw_init_queue(&psta->sleep_q);
  37. psta->sleepq_len = 0;
  38. _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
  39. _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
  40. #ifdef CONFIG_AP_MODE
  41. _rtw_init_listhead(&psta->asoc_list);
  42. _rtw_init_listhead(&psta->auth_list);
  43. psta->expire_to = 0;
  44. psta->flags = 0;
  45. psta->capability = 0;
  46. psta->bpairwise_key_installed = _FALSE;
  47. #ifdef CONFIG_NATIVEAP_MLME
  48. psta->nonerp_set = 0;
  49. psta->no_short_slot_time_set = 0;
  50. psta->no_short_preamble_set = 0;
  51. psta->no_ht_gf_set = 0;
  52. psta->no_ht_set = 0;
  53. psta->ht_20mhz_set = 0;
  54. #endif
  55. #ifdef CONFIG_TX_MCAST2UNI
  56. psta->under_exist_checking = 0;
  57. #endif // CONFIG_TX_MCAST2UNI
  58. psta->keep_alive_trycnt = 0;
  59. #endif // CONFIG_AP_MODE
  60. _func_exit_;
  61. }
  62. u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
  63. {
  64. struct sta_info *psta;
  65. s32 i;
  66. _func_enter_;
  67. pstapriv->pallocated_stainfo_buf = rtw_zvmalloc (sizeof(struct sta_info) * NUM_STA+ 4);
  68. if(!pstapriv->pallocated_stainfo_buf)
  69. return _FAIL;
  70. pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
  71. ((SIZE_PTR)(pstapriv->pallocated_stainfo_buf ) & 3);
  72. _rtw_init_queue(&pstapriv->free_sta_queue);
  73. _rtw_spinlock_init(&pstapriv->sta_hash_lock);
  74. //_rtw_init_queue(&pstapriv->asoc_q);
  75. pstapriv->asoc_sta_count = 0;
  76. _rtw_init_queue(&pstapriv->sleep_q);
  77. _rtw_init_queue(&pstapriv->wakeup_q);
  78. psta = (struct sta_info *)(pstapriv->pstainfo_buf);
  79. for(i = 0; i < NUM_STA; i++)
  80. {
  81. _rtw_init_stainfo(psta);
  82. _rtw_init_listhead(&(pstapriv->sta_hash[i]));
  83. rtw_list_insert_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
  84. psta++;
  85. }
  86. #ifdef CONFIG_AP_MODE
  87. pstapriv->sta_dz_bitmap = 0;
  88. pstapriv->tim_bitmap = 0;
  89. _rtw_init_listhead(&pstapriv->asoc_list);
  90. _rtw_init_listhead(&pstapriv->auth_list);
  91. _rtw_spinlock_init(&pstapriv->asoc_list_lock);
  92. _rtw_spinlock_init(&pstapriv->auth_list_lock);
  93. pstapriv->asoc_list_cnt = 0;
  94. pstapriv->auth_list_cnt = 0;
  95. pstapriv->auth_to = 3; // 3*2 = 6 sec
  96. pstapriv->assoc_to = 3;
  97. //pstapriv->expire_to = 900;// 900*2 = 1800 sec = 30 min, expire after no any traffic.
  98. //pstapriv->expire_to = 30;// 30*2 = 60 sec = 1 min, expire after no any traffic.
  99. #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
  100. pstapriv->expire_to = 3; // 3*2 = 6 sec
  101. #else
  102. pstapriv->expire_to = 60;// 60*2 = 120 sec = 2 min, expire after no any traffic.
  103. #endif
  104. pstapriv->max_num_sta = NUM_STA;
  105. #endif
  106. _func_exit_;
  107. return _SUCCESS;
  108. }
  109. inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
  110. {
  111. int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
  112. if (!stainfo_offset_valid(offset))
  113. DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
  114. return offset;
  115. }
  116. inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
  117. {
  118. if (!stainfo_offset_valid(offset))
  119. DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
  120. return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
  121. }
  122. void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv);
  123. void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv)
  124. {
  125. _func_enter_;
  126. _rtw_spinlock_free(&psta_xmitpriv->lock);
  127. _rtw_spinlock_free(&(psta_xmitpriv->be_q.sta_pending.lock));
  128. _rtw_spinlock_free(&(psta_xmitpriv->bk_q.sta_pending.lock));
  129. _rtw_spinlock_free(&(psta_xmitpriv->vi_q.sta_pending.lock));
  130. _rtw_spinlock_free(&(psta_xmitpriv->vo_q.sta_pending.lock));
  131. _func_exit_;
  132. }
  133. static void _rtw_free_sta_recv_priv_lock(struct sta_recv_priv *psta_recvpriv)
  134. {
  135. _func_enter_;
  136. _rtw_spinlock_free(&psta_recvpriv->lock);
  137. _rtw_spinlock_free(&(psta_recvpriv->defrag_q.lock));
  138. _func_exit_;
  139. }
  140. void rtw_mfree_stainfo(struct sta_info *psta);
  141. void rtw_mfree_stainfo(struct sta_info *psta)
  142. {
  143. _func_enter_;
  144. if(&psta->lock != NULL)
  145. _rtw_spinlock_free(&psta->lock);
  146. _rtw_free_sta_xmit_priv_lock(&psta->sta_xmitpriv);
  147. _rtw_free_sta_recv_priv_lock(&psta->sta_recvpriv);
  148. _func_exit_;
  149. }
  150. // this function is used to free the memory of lock || sema for all stainfos
  151. void rtw_mfree_all_stainfo(struct sta_priv *pstapriv );
  152. void rtw_mfree_all_stainfo(struct sta_priv *pstapriv )
  153. {
  154. _irqL irqL;
  155. _list *plist, *phead;
  156. struct sta_info *psta = NULL;
  157. _func_enter_;
  158. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  159. phead = get_list_head(&pstapriv->free_sta_queue);
  160. plist = get_next(phead);
  161. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
  162. {
  163. psta = LIST_CONTAINOR(plist, struct sta_info ,list);
  164. plist = get_next(plist);
  165. rtw_mfree_stainfo(psta);
  166. }
  167. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  168. _func_exit_;
  169. }
  170. void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv);
  171. void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
  172. {
  173. #ifdef CONFIG_AP_MODE
  174. struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
  175. #endif
  176. rtw_mfree_all_stainfo(pstapriv); //be done before free sta_hash_lock
  177. _rtw_spinlock_free(&pstapriv->free_sta_queue.lock);
  178. _rtw_spinlock_free(&pstapriv->sta_hash_lock);
  179. _rtw_spinlock_free(&pstapriv->wakeup_q.lock);
  180. _rtw_spinlock_free(&pstapriv->sleep_q.lock);
  181. #ifdef CONFIG_AP_MODE
  182. _rtw_spinlock_free(&pstapriv->asoc_list_lock);
  183. _rtw_spinlock_free(&pstapriv->auth_list_lock);
  184. _rtw_spinlock_free(&pacl_list->acl_node_q.lock);
  185. #endif
  186. }
  187. u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
  188. {
  189. _irqL irqL;
  190. _list *phead, *plist;
  191. struct sta_info *psta = NULL;
  192. struct recv_reorder_ctrl *preorder_ctrl;
  193. int index;
  194. _func_enter_;
  195. if(pstapriv){
  196. /* delete all reordering_ctrl_timer */
  197. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  198. for(index = 0; index < NUM_STA; index++)
  199. {
  200. phead = &(pstapriv->sta_hash[index]);
  201. plist = get_next(phead);
  202. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
  203. {
  204. int i;
  205. psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
  206. plist = get_next(plist);
  207. for(i=0; i < 16 ; i++)
  208. {
  209. preorder_ctrl = &psta->recvreorder_ctrl[i];
  210. _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
  211. }
  212. }
  213. }
  214. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  215. /*===============================*/
  216. rtw_mfree_sta_priv_lock(pstapriv);
  217. if(pstapriv->pallocated_stainfo_buf) {
  218. rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
  219. }
  220. }
  221. _func_exit_;
  222. return _SUCCESS;
  223. }
  224. //struct sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr)
  225. struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
  226. {
  227. _irqL irqL, irqL2;
  228. uint tmp_aid;
  229. s32 index;
  230. _list *phash_list;
  231. struct sta_info *psta;
  232. _queue *pfree_sta_queue;
  233. struct recv_reorder_ctrl *preorder_ctrl;
  234. int i = 0;
  235. u16 wRxSeqInitialValue = 0xffff;
  236. _func_enter_;
  237. pfree_sta_queue = &pstapriv->free_sta_queue;
  238. //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL);
  239. _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  240. if (_rtw_queue_empty(pfree_sta_queue) == _TRUE)
  241. {
  242. //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
  243. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  244. psta = NULL;
  245. }
  246. else
  247. {
  248. psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
  249. rtw_list_delete(&(psta->list));
  250. //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
  251. tmp_aid = psta->aid;
  252. _rtw_init_stainfo(psta);
  253. psta->padapter = pstapriv->padapter;
  254. _rtw_memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
  255. index = wifi_mac_hash(hwaddr);
  256. RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("rtw_alloc_stainfo: index = %x", index));
  257. if(index >= NUM_STA){
  258. RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("ERROR=> rtw_alloc_stainfo: index >= NUM_STA"));
  259. psta= NULL;
  260. goto exit;
  261. }
  262. phash_list = &(pstapriv->sta_hash[index]);
  263. //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  264. rtw_list_insert_tail(&psta->hash_list, phash_list);
  265. pstapriv->asoc_sta_count ++ ;
  266. //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  267. // Commented by Albert 2009/08/13
  268. // For the SMC router, the sequence number of first packet of WPS handshake will be 0.
  269. // In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable.
  270. // So, we initialize the tid_rxseq variable as the 0xffff.
  271. for( i = 0; i < 16; i++ )
  272. {
  273. _rtw_memcpy( &psta->sta_recvpriv.rxcache.tid_rxseq[ i ], &wRxSeqInitialValue, 2 );
  274. }
  275. RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("alloc number_%d stainfo with hwaddr = %x %x %x %x %x %x \n",
  276. pstapriv->asoc_sta_count , hwaddr[0], hwaddr[1], hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]));
  277. init_addba_retry_timer(pstapriv->padapter, psta);
  278. #ifdef CONFIG_TDLS
  279. psta->padapter = pstapriv->padapter;
  280. init_TPK_timer(pstapriv->padapter, psta);
  281. init_ch_switch_timer(pstapriv->padapter, psta);
  282. init_base_ch_timer(pstapriv->padapter, psta);
  283. init_off_ch_timer(pstapriv->padapter, psta);
  284. init_handshake_timer(pstapriv->padapter, psta);
  285. init_tdls_alive_timer(pstapriv->padapter, psta);
  286. #endif //CONFIG_TDLS
  287. //for A-MPDU Rx reordering buffer control
  288. for(i=0; i < 16 ; i++)
  289. {
  290. preorder_ctrl = &psta->recvreorder_ctrl[i];
  291. preorder_ctrl->padapter = pstapriv->padapter;
  292. preorder_ctrl->enable = _FALSE;
  293. preorder_ctrl->indicate_seq = 0xffff;
  294. #ifdef DBG_RX_SEQ
  295. DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __FUNCTION__, __LINE__,
  296. preorder_ctrl->indicate_seq);
  297. #endif
  298. preorder_ctrl->wend_b= 0xffff;
  299. //preorder_ctrl->wsize_b = (NR_RECVBUFF-2);
  300. preorder_ctrl->wsize_b = 64;//64;
  301. _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
  302. rtw_init_recv_timer(preorder_ctrl);
  303. }
  304. //init for DM
  305. psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
  306. psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
  307. /* init for the sequence number of received management frame */
  308. psta->RxMgmtFrameSeqNum = 0xffff;
  309. //alloc mac id for non-bc/mc station,
  310. rtw_alloc_macid(pstapriv->padapter, psta);
  311. }
  312. exit:
  313. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  314. _func_exit_;
  315. return psta;
  316. }
  317. // using pstapriv->sta_hash_lock to protect
  318. u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
  319. {
  320. int i;
  321. _irqL irqL0;
  322. _queue *pfree_sta_queue;
  323. struct recv_reorder_ctrl *preorder_ctrl;
  324. struct sta_xmit_priv *pstaxmitpriv;
  325. struct xmit_priv *pxmitpriv= &padapter->xmitpriv;
  326. struct sta_priv *pstapriv = &padapter->stapriv;
  327. struct hw_xmit *phwxmit;
  328. _func_enter_;
  329. if (psta == NULL)
  330. goto exit;
  331. _enter_critical_bh(&psta->lock, &irqL0);
  332. psta->state &= ~_FW_LINKED;
  333. _exit_critical_bh(&psta->lock, &irqL0);
  334. pfree_sta_queue = &pstapriv->free_sta_queue;
  335. pstaxmitpriv = &psta->sta_xmitpriv;
  336. //rtw_list_delete(&psta->sleep_list);
  337. //rtw_list_delete(&psta->wakeup_list);
  338. _enter_critical_bh(&pxmitpriv->lock, &irqL0);
  339. rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
  340. psta->sleepq_len = 0;
  341. //vo
  342. //_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
  343. rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
  344. rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
  345. phwxmit = pxmitpriv->hwxmits;
  346. phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
  347. pstaxmitpriv->vo_q.qcnt = 0;
  348. //_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
  349. //vi
  350. //_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
  351. rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
  352. rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
  353. phwxmit = pxmitpriv->hwxmits+1;
  354. phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
  355. pstaxmitpriv->vi_q.qcnt = 0;
  356. //_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
  357. //be
  358. //_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
  359. rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
  360. rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
  361. phwxmit = pxmitpriv->hwxmits+2;
  362. phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
  363. pstaxmitpriv->be_q.qcnt = 0;
  364. //_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
  365. //bk
  366. //_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
  367. rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
  368. rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
  369. phwxmit = pxmitpriv->hwxmits+3;
  370. phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
  371. pstaxmitpriv->bk_q.qcnt = 0;
  372. //_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
  373. _exit_critical_bh(&pxmitpriv->lock, &irqL0);
  374. rtw_list_delete(&psta->hash_list);
  375. RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]));
  376. pstapriv->asoc_sta_count --;
  377. // re-init sta_info; 20061114 // will be init in alloc_stainfo
  378. //_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
  379. //_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
  380. _cancel_timer_ex(&psta->addba_retry_timer);
  381. #ifdef CONFIG_TDLS
  382. _cancel_timer_ex(&psta->TPK_timer);
  383. _cancel_timer_ex(&psta->option_timer);
  384. _cancel_timer_ex(&psta->base_ch_timer);
  385. _cancel_timer_ex(&psta->off_ch_timer);
  386. _cancel_timer_ex(&psta->alive_timer1);
  387. _cancel_timer_ex(&psta->alive_timer2);
  388. #endif //CONFIG_TDLS
  389. //for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer
  390. for(i=0; i < 16 ; i++)
  391. {
  392. _irqL irqL;
  393. _list *phead, *plist;
  394. union recv_frame *prframe;
  395. _queue *ppending_recvframe_queue;
  396. _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
  397. preorder_ctrl = &psta->recvreorder_ctrl[i];
  398. _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
  399. ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
  400. _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL);
  401. phead = get_list_head(ppending_recvframe_queue);
  402. plist = get_next(phead);
  403. while(!rtw_is_list_empty(phead))
  404. {
  405. prframe = LIST_CONTAINOR(plist, union recv_frame, u);
  406. plist = get_next(plist);
  407. rtw_list_delete(&(prframe->u.hdr.list));
  408. rtw_free_recvframe(prframe, pfree_recv_queue);
  409. }
  410. _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL);
  411. }
  412. if (!(psta->state & WIFI_AP_STATE))
  413. rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE);
  414. //release mac id for non-bc/mc station,
  415. rtw_release_macid(pstapriv->padapter, psta);
  416. #ifdef CONFIG_AP_MODE
  417. /*
  418. _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
  419. rtw_list_delete(&psta->asoc_list);
  420. _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
  421. */
  422. _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0);
  423. if (!rtw_is_list_empty(&psta->auth_list)) {
  424. rtw_list_delete(&psta->auth_list);
  425. pstapriv->auth_list_cnt--;
  426. }
  427. _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0);
  428. psta->expire_to = 0;
  429. psta->sleepq_ac_len = 0;
  430. psta->qos_info = 0;
  431. psta->max_sp_len = 0;
  432. psta->uapsd_bk = 0;
  433. psta->uapsd_be = 0;
  434. psta->uapsd_vi = 0;
  435. psta->uapsd_vo = 0;
  436. psta->has_legacy_ac = 0;
  437. #ifdef CONFIG_NATIVEAP_MLME
  438. pstapriv->sta_dz_bitmap &=~BIT(psta->aid);
  439. pstapriv->tim_bitmap &=~BIT(psta->aid);
  440. //rtw_indicate_sta_disassoc_event(padapter, psta);
  441. if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta))
  442. {
  443. pstapriv->sta_aid[psta->aid - 1] = NULL;
  444. psta->aid = 0;
  445. }
  446. #endif // CONFIG_NATIVEAP_MLME
  447. #ifdef CONFIG_TX_MCAST2UNI
  448. psta->under_exist_checking = 0;
  449. #endif // CONFIG_TX_MCAST2UNI
  450. #endif // CONFIG_AP_MODE
  451. _rtw_spinlock_free(&psta->lock);
  452. //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL0);
  453. rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
  454. //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL0);
  455. exit:
  456. _func_exit_;
  457. return _SUCCESS;
  458. }
  459. // free all stainfo which in sta_hash[all]
  460. void rtw_free_all_stainfo(_adapter *padapter)
  461. {
  462. _irqL irqL;
  463. _list *plist, *phead;
  464. s32 index;
  465. struct sta_info *psta = NULL;
  466. struct sta_priv *pstapriv = &padapter->stapriv;
  467. struct sta_info* pbcmc_stainfo =rtw_get_bcmc_stainfo( padapter);
  468. _func_enter_;
  469. if(pstapriv->asoc_sta_count==1)
  470. goto exit;
  471. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  472. for(index=0; index< NUM_STA; index++)
  473. {
  474. phead = &(pstapriv->sta_hash[index]);
  475. plist = get_next(phead);
  476. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
  477. {
  478. psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
  479. plist = get_next(plist);
  480. if(pbcmc_stainfo!=psta)
  481. rtw_free_stainfo(padapter , psta);
  482. }
  483. }
  484. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  485. exit:
  486. _func_exit_;
  487. }
  488. /* any station allocated can be searched by hash list */
  489. struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
  490. {
  491. _irqL irqL;
  492. _list *plist, *phead;
  493. struct sta_info *psta = NULL;
  494. u32 index;
  495. u8 *addr;
  496. u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
  497. _func_enter_;
  498. if(hwaddr==NULL)
  499. return NULL;
  500. if(IS_MCAST(hwaddr))
  501. {
  502. addr = bc_addr;
  503. }
  504. else
  505. {
  506. addr = hwaddr;
  507. }
  508. index = wifi_mac_hash(addr);
  509. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  510. phead = &(pstapriv->sta_hash[index]);
  511. plist = get_next(phead);
  512. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
  513. {
  514. psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
  515. if ((_rtw_memcmp(psta->hwaddr, addr, ETH_ALEN))== _TRUE)
  516. { // if found the matched address
  517. break;
  518. }
  519. psta=NULL;
  520. plist = get_next(plist);
  521. }
  522. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  523. _func_exit_;
  524. return psta;
  525. }
  526. u32 rtw_init_bcmc_stainfo(_adapter* padapter)
  527. {
  528. struct sta_info *psta;
  529. struct tx_servq *ptxservq;
  530. u32 res=_SUCCESS;
  531. NDIS_802_11_MAC_ADDRESS bcast_addr= {0xff,0xff,0xff,0xff,0xff,0xff};
  532. struct sta_priv *pstapriv = &padapter->stapriv;
  533. //_queue *pstapending = &padapter->xmitpriv.bm_pending;
  534. _func_enter_;
  535. psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
  536. if(psta==NULL){
  537. res=_FAIL;
  538. RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("rtw_alloc_stainfo fail"));
  539. goto exit;
  540. }
  541. // default broadcast & multicast use macid 1
  542. psta->mac_id = 1;
  543. ptxservq= &(psta->sta_xmitpriv.be_q);
  544. /*
  545. _enter_critical(&pstapending->lock, &irqL0);
  546. if (rtw_is_list_empty(&ptxservq->tx_pending))
  547. rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(pstapending));
  548. _exit_critical(&pstapending->lock, &irqL0);
  549. */
  550. exit:
  551. _func_exit_;
  552. return _SUCCESS;
  553. }
  554. struct sta_info* rtw_get_bcmc_stainfo(_adapter* padapter)
  555. {
  556. struct sta_info *psta;
  557. struct sta_priv *pstapriv = &padapter->stapriv;
  558. u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
  559. _func_enter_;
  560. psta = rtw_get_stainfo(pstapriv, bc_addr);
  561. _func_exit_;
  562. return psta;
  563. }
  564. u8 rtw_access_ctrl(_adapter *padapter, u8 *mac_addr)
  565. {
  566. u8 res = _TRUE;
  567. #ifdef CONFIG_AP_MODE
  568. _irqL irqL;
  569. _list *plist, *phead;
  570. struct rtw_wlan_acl_node *paclnode;
  571. u8 match = _FALSE;
  572. struct sta_priv *pstapriv = &padapter->stapriv;
  573. struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
  574. _queue *pacl_node_q =&pacl_list->acl_node_q;
  575. _enter_critical_bh(&(pacl_node_q->lock), &irqL);
  576. phead = get_list_head(pacl_node_q);
  577. plist = get_next(phead);
  578. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
  579. {
  580. paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
  581. plist = get_next(plist);
  582. if(_rtw_memcmp(paclnode->addr, mac_addr, ETH_ALEN))
  583. {
  584. if(paclnode->valid == _TRUE)
  585. {
  586. match = _TRUE;
  587. break;
  588. }
  589. }
  590. }
  591. _exit_critical_bh(&(pacl_node_q->lock), &irqL);
  592. if(pacl_list->mode == 1)//accept unless in deny list
  593. {
  594. res = (match == _TRUE) ? _FALSE:_TRUE;
  595. }
  596. else if(pacl_list->mode == 2)//deny unless in accept list
  597. {
  598. res = (match == _TRUE) ? _TRUE:_FALSE;
  599. }
  600. else
  601. {
  602. res = _TRUE;
  603. }
  604. #endif
  605. return res;
  606. }