rtw_sta_mgt.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  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. bool test_st_match_rule(_adapter *adapter, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
  26. {
  27. if (ntohs(*((u16 *)local_port)) == 5001 || ntohs(*((u16 *)remote_port)) == 5001)
  28. return _TRUE;
  29. return _FALSE;
  30. }
  31. struct st_register test_st_reg = {
  32. .s_proto = 0x06,
  33. .rule = test_st_match_rule,
  34. };
  35. inline void rtw_st_ctl_init(struct st_ctl_t *st_ctl)
  36. {
  37. _rtw_memset(st_ctl->reg, 0 , sizeof(struct st_register) * SESSION_TRACKER_REG_ID_NUM);
  38. _rtw_init_queue(&st_ctl->tracker_q);
  39. }
  40. inline void rtw_st_ctl_clear_tracker_q(struct st_ctl_t *st_ctl)
  41. {
  42. _irqL irqL;
  43. _list *plist, *phead;
  44. struct session_tracker *st;
  45. _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
  46. phead = &st_ctl->tracker_q.queue;
  47. plist = get_next(phead);
  48. while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
  49. st = LIST_CONTAINOR(plist, struct session_tracker, list);
  50. plist = get_next(plist);
  51. rtw_list_delete(&st->list);
  52. rtw_mfree((u8 *)st, sizeof(struct session_tracker));
  53. }
  54. _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
  55. }
  56. inline void rtw_st_ctl_deinit(struct st_ctl_t *st_ctl)
  57. {
  58. rtw_st_ctl_clear_tracker_q(st_ctl);
  59. _rtw_deinit_queue(&st_ctl->tracker_q);
  60. }
  61. inline void rtw_st_ctl_register(struct st_ctl_t *st_ctl, u8 st_reg_id, struct st_register *reg)
  62. {
  63. if (st_reg_id >= SESSION_TRACKER_REG_ID_NUM) {
  64. rtw_warn_on(1);
  65. return;
  66. }
  67. st_ctl->reg[st_reg_id].s_proto = reg->s_proto;
  68. st_ctl->reg[st_reg_id].rule = reg->rule;
  69. }
  70. inline void rtw_st_ctl_unregister(struct st_ctl_t *st_ctl, u8 st_reg_id)
  71. {
  72. int i;
  73. if (st_reg_id >= SESSION_TRACKER_REG_ID_NUM) {
  74. rtw_warn_on(1);
  75. return;
  76. }
  77. st_ctl->reg[st_reg_id].s_proto = 0;
  78. st_ctl->reg[st_reg_id].rule = NULL;
  79. /* clear tracker queue if no session trecker registered */
  80. for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++)
  81. if (st_ctl->reg[i].s_proto != 0)
  82. break;
  83. if (i >= SESSION_TRACKER_REG_ID_NUM)
  84. rtw_st_ctl_clear_tracker_q(st_ctl);
  85. }
  86. inline bool rtw_st_ctl_chk_reg_s_proto(struct st_ctl_t *st_ctl, u8 s_proto)
  87. {
  88. bool ret = _FALSE;
  89. int i;
  90. for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
  91. if (st_ctl->reg[i].s_proto == s_proto) {
  92. ret = _TRUE;
  93. break;
  94. }
  95. }
  96. return ret;
  97. }
  98. inline bool rtw_st_ctl_chk_reg_rule(struct st_ctl_t *st_ctl, _adapter *adapter, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
  99. {
  100. bool ret = _FALSE;
  101. int i;
  102. st_match_rule rule;
  103. for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
  104. rule = st_ctl->reg[i].rule;
  105. if (rule && rule(adapter, local_naddr, local_port, remote_naddr, remote_port) == _TRUE) {
  106. ret = _TRUE;
  107. break;
  108. }
  109. }
  110. return ret;
  111. }
  112. #define SESSION_TRACKER_FMT IP_FMT":"PORT_FMT" "IP_FMT":"PORT_FMT" %u %d"
  113. #define SESSION_TRACKER_ARG(st) IP_ARG(&(st)->local_naddr), PORT_ARG(&(st)->local_port), IP_ARG(&(st)->remote_naddr), PORT_ARG(&(st)->remote_port), (st)->status, rtw_get_passing_time_ms((st)->set_time)
  114. void dump_st_ctl(void *sel, struct st_ctl_t *st_ctl)
  115. {
  116. int i;
  117. _irqL irqL;
  118. _list *plist, *phead;
  119. struct session_tracker *st;
  120. if (!DBG_SESSION_TRACKER)
  121. return;
  122. for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++)
  123. RTW_PRINT_SEL(sel, "reg%d: %u %p\n", i, st_ctl->reg[i].s_proto, st_ctl->reg[i].rule);
  124. _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
  125. phead = &st_ctl->tracker_q.queue;
  126. plist = get_next(phead);
  127. while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
  128. st = LIST_CONTAINOR(plist, struct session_tracker, list);
  129. plist = get_next(plist);
  130. RTW_PRINT_SEL(sel, SESSION_TRACKER_FMT"\n", SESSION_TRACKER_ARG(st));
  131. }
  132. _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
  133. }
  134. void _rtw_init_stainfo(struct sta_info *psta);
  135. void _rtw_init_stainfo(struct sta_info *psta)
  136. {
  137. _rtw_memset((u8 *)psta, 0, sizeof(struct sta_info));
  138. _rtw_spinlock_init(&psta->lock);
  139. _rtw_init_listhead(&psta->list);
  140. _rtw_init_listhead(&psta->hash_list);
  141. /* _rtw_init_listhead(&psta->asoc_list); */
  142. /* _rtw_init_listhead(&psta->sleep_list); */
  143. /* _rtw_init_listhead(&psta->wakeup_list); */
  144. _rtw_init_queue(&psta->sleep_q);
  145. psta->sleepq_len = 0;
  146. _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
  147. _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
  148. #ifdef CONFIG_AP_MODE
  149. _rtw_init_listhead(&psta->asoc_list);
  150. _rtw_init_listhead(&psta->auth_list);
  151. psta->expire_to = 0;
  152. psta->flags = 0;
  153. psta->capability = 0;
  154. psta->bpairwise_key_installed = _FALSE;
  155. #ifdef CONFIG_RTW_80211R
  156. psta->ft_pairwise_key_installed = _FALSE;
  157. #endif
  158. #ifdef CONFIG_NATIVEAP_MLME
  159. psta->nonerp_set = 0;
  160. psta->no_short_slot_time_set = 0;
  161. psta->no_short_preamble_set = 0;
  162. psta->no_ht_gf_set = 0;
  163. psta->no_ht_set = 0;
  164. psta->ht_20mhz_set = 0;
  165. psta->ht_40mhz_intolerant = 0;
  166. #endif
  167. #ifdef CONFIG_TX_MCAST2UNI
  168. psta->under_exist_checking = 0;
  169. #endif /* CONFIG_TX_MCAST2UNI */
  170. psta->keep_alive_trycnt = 0;
  171. #endif /* CONFIG_AP_MODE */
  172. rtw_st_ctl_init(&psta->st_ctl);
  173. }
  174. u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
  175. {
  176. struct sta_info *psta;
  177. s32 i;
  178. pstapriv->pallocated_stainfo_buf = rtw_zvmalloc(sizeof(struct sta_info) * NUM_STA + 4);
  179. if (!pstapriv->pallocated_stainfo_buf)
  180. return _FAIL;
  181. pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
  182. ((SIZE_PTR)(pstapriv->pallocated_stainfo_buf) & 3);
  183. _rtw_init_queue(&pstapriv->free_sta_queue);
  184. _rtw_spinlock_init(&pstapriv->sta_hash_lock);
  185. /* _rtw_init_queue(&pstapriv->asoc_q); */
  186. pstapriv->asoc_sta_count = 0;
  187. _rtw_init_queue(&pstapriv->sleep_q);
  188. _rtw_init_queue(&pstapriv->wakeup_q);
  189. psta = (struct sta_info *)(pstapriv->pstainfo_buf);
  190. for (i = 0; i < NUM_STA; i++) {
  191. _rtw_init_stainfo(psta);
  192. _rtw_init_listhead(&(pstapriv->sta_hash[i]));
  193. rtw_list_insert_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
  194. psta++;
  195. }
  196. pstapriv->adhoc_expire_to = 4; /* 4 * 2 = 8 sec */
  197. #ifdef CONFIG_AP_MODE
  198. pstapriv->sta_dz_bitmap = 0;
  199. pstapriv->tim_bitmap = 0;
  200. _rtw_init_listhead(&pstapriv->asoc_list);
  201. _rtw_init_listhead(&pstapriv->auth_list);
  202. _rtw_spinlock_init(&pstapriv->asoc_list_lock);
  203. _rtw_spinlock_init(&pstapriv->auth_list_lock);
  204. pstapriv->asoc_list_cnt = 0;
  205. pstapriv->auth_list_cnt = 0;
  206. pstapriv->auth_to = 3; /* 3*2 = 6 sec */
  207. pstapriv->assoc_to = 3;
  208. /* pstapriv->expire_to = 900; */ /* 900*2 = 1800 sec = 30 min, expire after no any traffic. */
  209. /* pstapriv->expire_to = 30; */ /* 30*2 = 60 sec = 1 min, expire after no any traffic. */
  210. #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
  211. pstapriv->expire_to = 3; /* 3*2 = 6 sec */
  212. #else
  213. pstapriv->expire_to = 60;/* 60*2 = 120 sec = 2 min, expire after no any traffic. */
  214. #endif
  215. #ifdef CONFIG_ATMEL_RC_PATCH
  216. _rtw_memset(pstapriv->atmel_rc_pattern, 0, ETH_ALEN);
  217. #endif
  218. pstapriv->max_num_sta = NUM_STA;
  219. #endif
  220. #if CONFIG_RTW_MACADDR_ACL
  221. _rtw_init_queue(&(pstapriv->acl_list.acl_node_q));
  222. #endif
  223. #if CONFIG_RTW_PRE_LINK_STA
  224. rtw_pre_link_sta_ctl_init(pstapriv);
  225. #endif
  226. return _SUCCESS;
  227. }
  228. inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
  229. {
  230. int offset = (((u8 *)sta) - stapriv->pstainfo_buf) / sizeof(struct sta_info);
  231. if (!stainfo_offset_valid(offset))
  232. RTW_INFO("%s invalid offset(%d), out of range!!!", __func__, offset);
  233. return offset;
  234. }
  235. inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
  236. {
  237. if (!stainfo_offset_valid(offset))
  238. RTW_INFO("%s invalid offset(%d), out of range!!!", __func__, offset);
  239. return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
  240. }
  241. void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv);
  242. void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv)
  243. {
  244. _rtw_spinlock_free(&psta_xmitpriv->lock);
  245. _rtw_spinlock_free(&(psta_xmitpriv->be_q.sta_pending.lock));
  246. _rtw_spinlock_free(&(psta_xmitpriv->bk_q.sta_pending.lock));
  247. _rtw_spinlock_free(&(psta_xmitpriv->vi_q.sta_pending.lock));
  248. _rtw_spinlock_free(&(psta_xmitpriv->vo_q.sta_pending.lock));
  249. }
  250. static void _rtw_free_sta_recv_priv_lock(struct sta_recv_priv *psta_recvpriv)
  251. {
  252. _rtw_spinlock_free(&psta_recvpriv->lock);
  253. _rtw_spinlock_free(&(psta_recvpriv->defrag_q.lock));
  254. }
  255. void rtw_mfree_stainfo(struct sta_info *psta);
  256. void rtw_mfree_stainfo(struct sta_info *psta)
  257. {
  258. if (&psta->lock != NULL)
  259. _rtw_spinlock_free(&psta->lock);
  260. _rtw_free_sta_xmit_priv_lock(&psta->sta_xmitpriv);
  261. _rtw_free_sta_recv_priv_lock(&psta->sta_recvpriv);
  262. }
  263. /* this function is used to free the memory of lock || sema for all stainfos */
  264. void rtw_mfree_all_stainfo(struct sta_priv *pstapriv);
  265. void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
  266. {
  267. _irqL irqL;
  268. _list *plist, *phead;
  269. struct sta_info *psta = NULL;
  270. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  271. phead = get_list_head(&pstapriv->free_sta_queue);
  272. plist = get_next(phead);
  273. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  274. psta = LIST_CONTAINOR(plist, struct sta_info , list);
  275. plist = get_next(plist);
  276. rtw_mfree_stainfo(psta);
  277. }
  278. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  279. }
  280. void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv);
  281. void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
  282. {
  283. rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
  284. _rtw_spinlock_free(&pstapriv->free_sta_queue.lock);
  285. _rtw_spinlock_free(&pstapriv->sta_hash_lock);
  286. _rtw_spinlock_free(&pstapriv->wakeup_q.lock);
  287. _rtw_spinlock_free(&pstapriv->sleep_q.lock);
  288. #ifdef CONFIG_AP_MODE
  289. _rtw_spinlock_free(&pstapriv->asoc_list_lock);
  290. _rtw_spinlock_free(&pstapriv->auth_list_lock);
  291. #endif
  292. }
  293. u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
  294. {
  295. _irqL irqL;
  296. _list *phead, *plist;
  297. struct sta_info *psta = NULL;
  298. struct recv_reorder_ctrl *preorder_ctrl;
  299. int index;
  300. if (pstapriv) {
  301. /* delete all reordering_ctrl_timer */
  302. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  303. for (index = 0; index < NUM_STA; index++) {
  304. phead = &(pstapriv->sta_hash[index]);
  305. plist = get_next(phead);
  306. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  307. int i;
  308. psta = LIST_CONTAINOR(plist, struct sta_info , hash_list);
  309. plist = get_next(plist);
  310. for (i = 0; i < 16 ; i++) {
  311. preorder_ctrl = &psta->recvreorder_ctrl[i];
  312. _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
  313. }
  314. }
  315. }
  316. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  317. /*===============================*/
  318. rtw_mfree_sta_priv_lock(pstapriv);
  319. #if CONFIG_RTW_MACADDR_ACL
  320. _rtw_deinit_queue(&(pstapriv->acl_list.acl_node_q));
  321. #endif
  322. #if CONFIG_RTW_PRE_LINK_STA
  323. rtw_pre_link_sta_ctl_deinit(pstapriv);
  324. #endif
  325. if (pstapriv->pallocated_stainfo_buf)
  326. rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info) * NUM_STA + 4);
  327. }
  328. return _SUCCESS;
  329. }
  330. static void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
  331. {
  332. _adapter *padapter = preorder_ctrl->padapter;
  333. rtw_init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter, rtw_reordering_ctrl_timeout_handler);
  334. }
  335. /* struct sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr) */
  336. struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
  337. {
  338. _irqL irqL, irqL2;
  339. uint tmp_aid;
  340. s32 index;
  341. _list *phash_list;
  342. struct sta_info *psta;
  343. _queue *pfree_sta_queue;
  344. struct recv_reorder_ctrl *preorder_ctrl;
  345. int i = 0;
  346. u16 wRxSeqInitialValue = 0xffff;
  347. pfree_sta_queue = &pstapriv->free_sta_queue;
  348. /* _enter_critical_bh(&(pfree_sta_queue->lock), &irqL); */
  349. _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  350. if (_rtw_queue_empty(pfree_sta_queue) == _TRUE) {
  351. /* _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); */
  352. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  353. psta = NULL;
  354. } else {
  355. psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
  356. rtw_list_delete(&(psta->list));
  357. /* _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); */
  358. tmp_aid = psta->aid;
  359. _rtw_init_stainfo(psta);
  360. psta->padapter = pstapriv->padapter;
  361. _rtw_memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
  362. index = wifi_mac_hash(hwaddr);
  363. if (index >= NUM_STA) {
  364. psta = NULL;
  365. goto exit;
  366. }
  367. phash_list = &(pstapriv->sta_hash[index]);
  368. /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); */
  369. rtw_list_insert_tail(&psta->hash_list, phash_list);
  370. pstapriv->asoc_sta_count++;
  371. /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); */
  372. /* Commented by Albert 2009/08/13
  373. * For the SMC router, the sequence number of first packet of WPS handshake will be 0.
  374. * 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.
  375. * So, we initialize the tid_rxseq variable as the 0xffff. */
  376. for (i = 0; i < 16; i++)
  377. _rtw_memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
  378. rtw_init_timer(&psta->addba_retry_timer, psta->padapter, addba_timer_hdl);
  379. #ifdef CONFIG_IEEE80211W
  380. rtw_init_timer(&psta->dot11w_expire_timer, psta->padapter, sa_query_timer_hdl, psta);
  381. #endif /* CONFIG_IEEE80211W */
  382. #ifdef CONFIG_TDLS
  383. rtw_init_tdls_timer(pstapriv->padapter, psta);
  384. #endif /* CONFIG_TDLS */
  385. /* for A-MPDU Rx reordering buffer control */
  386. for (i = 0; i < 16 ; i++) {
  387. preorder_ctrl = &psta->recvreorder_ctrl[i];
  388. preorder_ctrl->padapter = pstapriv->padapter;
  389. preorder_ctrl->enable = _FALSE;
  390. preorder_ctrl->indicate_seq = 0xffff;
  391. #ifdef DBG_RX_SEQ
  392. RTW_INFO("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __FUNCTION__, __LINE__,
  393. preorder_ctrl->indicate_seq);
  394. #endif
  395. preorder_ctrl->wend_b = 0xffff;
  396. /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
  397. preorder_ctrl->wsize_b = 64;/* 64; */
  398. preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
  399. _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
  400. rtw_init_recv_timer(preorder_ctrl);
  401. }
  402. /* init for DM */
  403. psta->rssi_stat.undecorated_smoothed_pwdb = (-1);
  404. psta->rssi_stat.undecorated_smoothed_cck = (-1);
  405. #ifdef CONFIG_ATMEL_RC_PATCH
  406. psta->flag_atmel_rc = 0;
  407. #endif
  408. /* init for the sequence number of received management frame */
  409. psta->RxMgmtFrameSeqNum = 0xffff;
  410. psta->ra_rpt_linked = _FALSE;
  411. rtw_alloc_macid(pstapriv->padapter, psta);
  412. }
  413. exit:
  414. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
  415. if (psta)
  416. rtw_mi_update_iface_status(&(pstapriv->padapter->mlmepriv), 0);
  417. return psta;
  418. }
  419. /* using pstapriv->sta_hash_lock to protect */
  420. u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
  421. {
  422. int i;
  423. _irqL irqL0;
  424. _queue *pfree_sta_queue;
  425. struct recv_reorder_ctrl *preorder_ctrl;
  426. struct sta_xmit_priv *pstaxmitpriv;
  427. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  428. struct sta_priv *pstapriv = &padapter->stapriv;
  429. struct hw_xmit *phwxmit;
  430. int pending_qcnt[4];
  431. u8 is_pre_link_sta = _FALSE;
  432. if (psta == NULL)
  433. goto exit;
  434. is_pre_link_sta = rtw_is_pre_link_sta(pstapriv, psta->hwaddr);
  435. if (is_pre_link_sta == _FALSE) {
  436. _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
  437. rtw_list_delete(&psta->hash_list);
  438. pstapriv->asoc_sta_count--;
  439. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
  440. rtw_mi_update_iface_status(&(padapter->mlmepriv), 0);
  441. } else {
  442. _enter_critical_bh(&psta->lock, &irqL0);
  443. psta->state = WIFI_FW_PRE_LINK;
  444. _exit_critical_bh(&psta->lock, &irqL0);
  445. }
  446. _enter_critical_bh(&psta->lock, &irqL0);
  447. psta->state &= ~_FW_LINKED;
  448. _exit_critical_bh(&psta->lock, &irqL0);
  449. pfree_sta_queue = &pstapriv->free_sta_queue;
  450. pstaxmitpriv = &psta->sta_xmitpriv;
  451. /* rtw_list_delete(&psta->sleep_list); */
  452. /* rtw_list_delete(&psta->wakeup_list); */
  453. _enter_critical_bh(&pxmitpriv->lock, &irqL0);
  454. rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
  455. psta->sleepq_len = 0;
  456. /* vo */
  457. /* _enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); */
  458. rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
  459. rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
  460. phwxmit = pxmitpriv->hwxmits;
  461. phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
  462. pending_qcnt[0] = pstaxmitpriv->vo_q.qcnt;
  463. pstaxmitpriv->vo_q.qcnt = 0;
  464. /* _exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); */
  465. /* vi */
  466. /* _enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); */
  467. rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
  468. rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
  469. phwxmit = pxmitpriv->hwxmits + 1;
  470. phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
  471. pending_qcnt[1] = pstaxmitpriv->vi_q.qcnt;
  472. pstaxmitpriv->vi_q.qcnt = 0;
  473. /* _exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0); */
  474. /* be */
  475. /* _enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); */
  476. rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
  477. rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
  478. phwxmit = pxmitpriv->hwxmits + 2;
  479. phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
  480. pending_qcnt[2] = pstaxmitpriv->be_q.qcnt;
  481. pstaxmitpriv->be_q.qcnt = 0;
  482. /* _exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0); */
  483. /* bk */
  484. /* _enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); */
  485. rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
  486. rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
  487. phwxmit = pxmitpriv->hwxmits + 3;
  488. phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
  489. pending_qcnt[3] = pstaxmitpriv->bk_q.qcnt;
  490. pstaxmitpriv->bk_q.qcnt = 0;
  491. /* _exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); */
  492. rtw_os_wake_queue_at_free_stainfo(padapter, pending_qcnt);
  493. _exit_critical_bh(&pxmitpriv->lock, &irqL0);
  494. /* re-init sta_info; 20061114 */ /* will be init in alloc_stainfo */
  495. /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */
  496. /* _rtw_init_sta_recv_priv(&psta->sta_recvpriv); */
  497. #ifdef CONFIG_IEEE80211W
  498. _cancel_timer_ex(&psta->dot11w_expire_timer);
  499. #endif /* CONFIG_IEEE80211W */
  500. _cancel_timer_ex(&psta->addba_retry_timer);
  501. #ifdef CONFIG_TDLS
  502. psta->tdls_sta_state = TDLS_STATE_NONE;
  503. rtw_free_tdls_timer(psta);
  504. #endif /* CONFIG_TDLS */
  505. /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
  506. for (i = 0; i < 16 ; i++) {
  507. _irqL irqL;
  508. _list *phead, *plist;
  509. union recv_frame *prframe;
  510. _queue *ppending_recvframe_queue;
  511. _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
  512. preorder_ctrl = &psta->recvreorder_ctrl[i];
  513. _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
  514. ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
  515. _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL);
  516. phead = get_list_head(ppending_recvframe_queue);
  517. plist = get_next(phead);
  518. while (!rtw_is_list_empty(phead)) {
  519. prframe = LIST_CONTAINOR(plist, union recv_frame, u);
  520. plist = get_next(plist);
  521. rtw_list_delete(&(prframe->u.hdr.list));
  522. rtw_free_recvframe(prframe, pfree_recv_queue);
  523. }
  524. _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL);
  525. }
  526. if (!((psta->state & WIFI_AP_STATE) || MacAddr_isBcst(psta->hwaddr)) && is_pre_link_sta == _FALSE)
  527. rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE);
  528. /* release mac id for non-bc/mc station, */
  529. if (is_pre_link_sta == _FALSE)
  530. rtw_release_macid(pstapriv->padapter, psta);
  531. #ifdef CONFIG_AP_MODE
  532. /*
  533. _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
  534. rtw_list_delete(&psta->asoc_list);
  535. _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
  536. */
  537. _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0);
  538. if (!rtw_is_list_empty(&psta->auth_list)) {
  539. rtw_list_delete(&psta->auth_list);
  540. pstapriv->auth_list_cnt--;
  541. }
  542. _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0);
  543. psta->expire_to = 0;
  544. #ifdef CONFIG_ATMEL_RC_PATCH
  545. psta->flag_atmel_rc = 0;
  546. #endif
  547. psta->sleepq_ac_len = 0;
  548. psta->qos_info = 0;
  549. psta->max_sp_len = 0;
  550. psta->uapsd_bk = 0;
  551. psta->uapsd_be = 0;
  552. psta->uapsd_vi = 0;
  553. psta->uapsd_vo = 0;
  554. psta->has_legacy_ac = 0;
  555. #ifdef CONFIG_NATIVEAP_MLME
  556. pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
  557. pstapriv->tim_bitmap &= ~BIT(psta->aid);
  558. /* rtw_indicate_sta_disassoc_event(padapter, psta); */
  559. if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
  560. pstapriv->sta_aid[psta->aid - 1] = NULL;
  561. psta->aid = 0;
  562. }
  563. #endif /* CONFIG_NATIVEAP_MLME */
  564. #ifdef CONFIG_TX_MCAST2UNI
  565. psta->under_exist_checking = 0;
  566. #endif /* CONFIG_TX_MCAST2UNI */
  567. #endif /* CONFIG_AP_MODE */
  568. rtw_st_ctl_deinit(&psta->st_ctl);
  569. if (is_pre_link_sta == _FALSE) {
  570. _rtw_spinlock_free(&psta->lock);
  571. /* _enter_critical_bh(&(pfree_sta_queue->lock), &irqL0); */
  572. _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
  573. rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
  574. _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
  575. /* _exit_critical_bh(&(pfree_sta_queue->lock), &irqL0); */
  576. }
  577. exit:
  578. return _SUCCESS;
  579. }
  580. /* free all stainfo which in sta_hash[all] */
  581. void rtw_free_all_stainfo(_adapter *padapter)
  582. {
  583. _irqL irqL;
  584. _list *plist, *phead;
  585. s32 index;
  586. struct sta_info *psta = NULL;
  587. struct sta_priv *pstapriv = &padapter->stapriv;
  588. struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
  589. u8 free_sta_num = 0;
  590. char free_sta_list[NUM_STA];
  591. int stainfo_offset;
  592. if (pstapriv->asoc_sta_count == 1)
  593. goto exit;
  594. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  595. for (index = 0; index < NUM_STA; index++) {
  596. phead = &(pstapriv->sta_hash[index]);
  597. plist = get_next(phead);
  598. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  599. psta = LIST_CONTAINOR(plist, struct sta_info , hash_list);
  600. plist = get_next(plist);
  601. if (pbcmc_stainfo != psta) {
  602. if (rtw_is_pre_link_sta(pstapriv, psta->hwaddr) == _FALSE)
  603. rtw_list_delete(&psta->hash_list);
  604. stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
  605. if (stainfo_offset_valid(stainfo_offset))
  606. free_sta_list[free_sta_num++] = stainfo_offset;
  607. }
  608. }
  609. }
  610. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  611. for (index = 0; index < free_sta_num; index++) {
  612. psta = rtw_get_stainfo_by_offset(pstapriv, free_sta_list[index]);
  613. rtw_free_stainfo(padapter , psta);
  614. }
  615. exit:
  616. return;
  617. }
  618. /* any station allocated can be searched by hash list */
  619. struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
  620. {
  621. _irqL irqL;
  622. _list *plist, *phead;
  623. struct sta_info *psta = NULL;
  624. u32 index;
  625. u8 *addr;
  626. u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  627. if (hwaddr == NULL)
  628. return NULL;
  629. if (IS_MCAST(hwaddr))
  630. addr = bc_addr;
  631. else
  632. addr = hwaddr;
  633. index = wifi_mac_hash(addr);
  634. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  635. phead = &(pstapriv->sta_hash[index]);
  636. plist = get_next(phead);
  637. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  638. psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
  639. if ((_rtw_memcmp(psta->hwaddr, addr, ETH_ALEN)) == _TRUE) {
  640. /* if found the matched address */
  641. break;
  642. }
  643. psta = NULL;
  644. plist = get_next(plist);
  645. }
  646. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  647. return psta;
  648. }
  649. u32 rtw_init_bcmc_stainfo(_adapter *padapter)
  650. {
  651. struct sta_info *psta;
  652. struct tx_servq *ptxservq;
  653. u32 res = _SUCCESS;
  654. NDIS_802_11_MAC_ADDRESS bcast_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  655. struct sta_priv *pstapriv = &padapter->stapriv;
  656. /* _queue *pstapending = &padapter->xmitpriv.bm_pending; */
  657. psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
  658. if (psta == NULL) {
  659. res = _FAIL;
  660. goto exit;
  661. }
  662. #ifdef CONFIG_BEAMFORMING
  663. psta->txbf_gid = 63;
  664. psta->txbf_paid = 0;
  665. #endif
  666. ptxservq = &(psta->sta_xmitpriv.be_q);
  667. /*
  668. _enter_critical(&pstapending->lock, &irqL0);
  669. if (rtw_is_list_empty(&ptxservq->tx_pending))
  670. rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(pstapending));
  671. _exit_critical(&pstapending->lock, &irqL0);
  672. */
  673. exit:
  674. return _SUCCESS;
  675. }
  676. struct sta_info *rtw_get_bcmc_stainfo(_adapter *padapter)
  677. {
  678. struct sta_info *psta;
  679. struct sta_priv *pstapriv = &padapter->stapriv;
  680. u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  681. psta = rtw_get_stainfo(pstapriv, bc_addr);
  682. return psta;
  683. }
  684. #if CONFIG_RTW_MACADDR_ACL
  685. const char *const _acl_mode_str[] = {
  686. "DISABLED",
  687. "ACCEPT_UNLESS_LISTED",
  688. "DENY_UNLESS_LISTED",
  689. };
  690. u8 rtw_access_ctrl(_adapter *adapter, u8 *mac_addr)
  691. {
  692. u8 res = _TRUE;
  693. _irqL irqL;
  694. _list *list, *head;
  695. struct rtw_wlan_acl_node *acl_node;
  696. u8 match = _FALSE;
  697. struct sta_priv *stapriv = &adapter->stapriv;
  698. struct wlan_acl_pool *acl = &stapriv->acl_list;
  699. _queue *acl_node_q = &acl->acl_node_q;
  700. _enter_critical_bh(&(acl_node_q->lock), &irqL);
  701. head = get_list_head(acl_node_q);
  702. list = get_next(head);
  703. while (rtw_end_of_queue_search(head, list) == _FALSE) {
  704. acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
  705. list = get_next(list);
  706. if (_rtw_memcmp(acl_node->addr, mac_addr, ETH_ALEN)) {
  707. if (acl_node->valid == _TRUE) {
  708. match = _TRUE;
  709. break;
  710. }
  711. }
  712. }
  713. _exit_critical_bh(&(acl_node_q->lock), &irqL);
  714. if (acl->mode == RTW_ACL_MODE_ACCEPT_UNLESS_LISTED)
  715. res = (match == _TRUE) ? _FALSE : _TRUE;
  716. else if (acl->mode == RTW_ACL_MODE_DENY_UNLESS_LISTED)
  717. res = (match == _TRUE) ? _TRUE : _FALSE;
  718. else
  719. res = _TRUE;
  720. return res;
  721. }
  722. void dump_macaddr_acl(void *sel, _adapter *adapter)
  723. {
  724. struct sta_priv *stapriv = &adapter->stapriv;
  725. struct wlan_acl_pool *acl = &stapriv->acl_list;
  726. int i;
  727. RTW_PRINT_SEL(sel, "mode:%s(%d)\n", acl_mode_str(acl->mode), acl->mode);
  728. RTW_PRINT_SEL(sel, "num:%d/%d\n", acl->num, NUM_ACL);
  729. for (i = 0; i < NUM_ACL; i++) {
  730. if (acl->aclnode[i].valid == _FALSE)
  731. continue;
  732. RTW_PRINT_SEL(sel, MAC_FMT"\n", MAC_ARG(acl->aclnode[i].addr));
  733. }
  734. }
  735. #endif /* CONFIG_RTW_MACADDR_ACL */
  736. bool rtw_is_pre_link_sta(struct sta_priv *stapriv, u8 *addr)
  737. {
  738. #if CONFIG_RTW_PRE_LINK_STA
  739. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  740. struct sta_info *sta = NULL;
  741. u8 exist = _FALSE;
  742. int i;
  743. _irqL irqL;
  744. _enter_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  745. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++) {
  746. if (pre_link_sta_ctl->node[i].valid == _TRUE
  747. && _rtw_memcmp(pre_link_sta_ctl->node[i].addr, addr, ETH_ALEN) == _TRUE
  748. ) {
  749. exist = _TRUE;
  750. break;
  751. }
  752. }
  753. _exit_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  754. return exist;
  755. #else
  756. return _FALSE;
  757. #endif
  758. }
  759. #if CONFIG_RTW_PRE_LINK_STA
  760. struct sta_info *rtw_pre_link_sta_add(struct sta_priv *stapriv, u8 *hwaddr)
  761. {
  762. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  763. struct pre_link_sta_node_t *node = NULL;
  764. struct sta_info *sta = NULL;
  765. u8 exist = _FALSE;
  766. int i;
  767. _irqL irqL;
  768. if (rtw_check_invalid_mac_address(hwaddr, _FALSE) == _TRUE)
  769. goto exit;
  770. _enter_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  771. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++) {
  772. if (pre_link_sta_ctl->node[i].valid == _TRUE
  773. && _rtw_memcmp(pre_link_sta_ctl->node[i].addr, hwaddr, ETH_ALEN) == _TRUE
  774. ) {
  775. node = &pre_link_sta_ctl->node[i];
  776. exist = _TRUE;
  777. break;
  778. }
  779. if (node == NULL && pre_link_sta_ctl->node[i].valid == _FALSE)
  780. node = &pre_link_sta_ctl->node[i];
  781. }
  782. if (exist == _FALSE && node) {
  783. _rtw_memcpy(node->addr, hwaddr, ETH_ALEN);
  784. node->valid = _TRUE;
  785. pre_link_sta_ctl->num++;
  786. }
  787. _exit_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  788. if (node == NULL)
  789. goto exit;
  790. sta = rtw_get_stainfo(stapriv, hwaddr);
  791. if (sta)
  792. goto odm_hook;
  793. sta = rtw_alloc_stainfo(stapriv, hwaddr);
  794. if (!sta)
  795. goto exit;
  796. sta->state = WIFI_FW_PRE_LINK;
  797. odm_hook:
  798. rtw_hal_set_odm_var(stapriv->padapter, HAL_ODM_STA_INFO, sta, _TRUE);
  799. exit:
  800. return sta;
  801. }
  802. void rtw_pre_link_sta_del(struct sta_priv *stapriv, u8 *hwaddr)
  803. {
  804. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  805. struct pre_link_sta_node_t *node = NULL;
  806. struct sta_info *sta = NULL;
  807. u8 exist = _FALSE;
  808. int i;
  809. _irqL irqL;
  810. if (rtw_check_invalid_mac_address(hwaddr, _FALSE) == _TRUE)
  811. goto exit;
  812. _enter_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  813. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++) {
  814. if (pre_link_sta_ctl->node[i].valid == _TRUE
  815. && _rtw_memcmp(pre_link_sta_ctl->node[i].addr, hwaddr, ETH_ALEN) == _TRUE
  816. ) {
  817. node = &pre_link_sta_ctl->node[i];
  818. exist = _TRUE;
  819. break;
  820. }
  821. }
  822. if (exist == _TRUE && node) {
  823. node->valid = _FALSE;
  824. pre_link_sta_ctl->num--;
  825. }
  826. _exit_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  827. if (exist == _FALSE)
  828. goto exit;
  829. sta = rtw_get_stainfo(stapriv, hwaddr);
  830. if (!sta)
  831. goto exit;
  832. if (sta->state == WIFI_FW_PRE_LINK)
  833. rtw_free_stainfo(stapriv->padapter, sta);
  834. exit:
  835. return;
  836. }
  837. void rtw_pre_link_sta_ctl_reset(struct sta_priv *stapriv)
  838. {
  839. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  840. struct pre_link_sta_node_t *node = NULL;
  841. struct sta_info *sta = NULL;
  842. int i, j = 0;
  843. _irqL irqL;
  844. u8 addrs[RTW_PRE_LINK_STA_NUM][ETH_ALEN];
  845. _rtw_memset(addrs, 0, RTW_PRE_LINK_STA_NUM * ETH_ALEN);
  846. _enter_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  847. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++) {
  848. if (pre_link_sta_ctl->node[i].valid == _FALSE)
  849. continue;
  850. _rtw_memcpy(&(addrs[j][0]), pre_link_sta_ctl->node[i].addr, ETH_ALEN);
  851. pre_link_sta_ctl->node[i].valid = _FALSE;
  852. pre_link_sta_ctl->num--;
  853. j++;
  854. }
  855. _exit_critical_bh(&(pre_link_sta_ctl->lock), &irqL);
  856. for (i = 0; i < j; i++) {
  857. sta = rtw_get_stainfo(stapriv, &(addrs[i][0]));
  858. if (!sta)
  859. continue;
  860. if (sta->state == WIFI_FW_PRE_LINK)
  861. rtw_free_stainfo(stapriv->padapter, sta);
  862. }
  863. }
  864. void rtw_pre_link_sta_ctl_init(struct sta_priv *stapriv)
  865. {
  866. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  867. int i;
  868. _rtw_spinlock_init(&pre_link_sta_ctl->lock);
  869. pre_link_sta_ctl->num = 0;
  870. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++)
  871. pre_link_sta_ctl->node[i].valid = _FALSE;
  872. }
  873. void rtw_pre_link_sta_ctl_deinit(struct sta_priv *stapriv)
  874. {
  875. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  876. int i;
  877. rtw_pre_link_sta_ctl_reset(stapriv);
  878. _rtw_spinlock_free(&pre_link_sta_ctl->lock);
  879. }
  880. void dump_pre_link_sta_ctl(void *sel, struct sta_priv *stapriv)
  881. {
  882. struct pre_link_sta_ctl_t *pre_link_sta_ctl = &stapriv->pre_link_sta_ctl;
  883. int i;
  884. RTW_PRINT_SEL(sel, "num:%d/%d\n", pre_link_sta_ctl->num, RTW_PRE_LINK_STA_NUM);
  885. for (i = 0; i < RTW_PRE_LINK_STA_NUM; i++) {
  886. if (pre_link_sta_ctl->node[i].valid == _FALSE)
  887. continue;
  888. RTW_PRINT_SEL(sel, MAC_FMT"\n", MAC_ARG(pre_link_sta_ctl->node[i].addr));
  889. }
  890. }
  891. #endif /* CONFIG_RTW_PRE_LINK_STA */