1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _RTW_STA_MGT_C_
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <xmit_osdep.h>
21 #include <mlme_osdep.h>
24 void _rtw_init_stainfo(struct sta_info
*psta
)
26 memset((u8
*)psta
, 0, sizeof (struct sta_info
));
27 spin_lock_init(&psta
->lock
);
28 INIT_LIST_HEAD(&psta
->list
);
29 INIT_LIST_HEAD(&psta
->hash_list
);
30 _rtw_init_queue23a(&psta
->sleep_q
);
32 _rtw_init_sta_xmit_priv23a(&psta
->sta_xmitpriv
);
33 _rtw_init_sta_recv_priv23a(&psta
->sta_recvpriv
);
34 #ifdef CONFIG_8723AU_AP_MODE
35 INIT_LIST_HEAD(&psta
->asoc_list
);
36 INIT_LIST_HEAD(&psta
->auth_list
);
40 psta
->bpairwise_key_installed
= false;
42 psta
->no_short_slot_time_set
= 0;
43 psta
->no_short_preamble_set
= 0;
44 psta
->no_ht_gf_set
= 0;
46 psta
->ht_20mhz_set
= 0;
47 psta
->keep_alive_trycnt
= 0;
48 #endif /* CONFIG_8723AU_AP_MODE */
51 u32
_rtw_init_sta_priv23a(struct sta_priv
*pstapriv
)
53 struct sta_info
*psta
;
56 pstapriv
->pallocated_stainfo_buf
= rtw_zvmalloc(sizeof(struct sta_info
) * NUM_STA
+ 4);
58 if (!pstapriv
->pallocated_stainfo_buf
)
61 pstapriv
->pstainfo_buf
= pstapriv
->pallocated_stainfo_buf
+ 4 -
62 ((unsigned long)(pstapriv
->pallocated_stainfo_buf
) & 3);
63 _rtw_init_queue23a(&pstapriv
->free_sta_queue
);
64 spin_lock_init(&pstapriv
->sta_hash_lock
);
65 pstapriv
->asoc_sta_count
= 0;
66 _rtw_init_queue23a(&pstapriv
->sleep_q
);
67 _rtw_init_queue23a(&pstapriv
->wakeup_q
);
68 psta
= (struct sta_info
*)(pstapriv
->pstainfo_buf
);
70 for (i
= 0; i
< NUM_STA
; i
++) {
71 _rtw_init_stainfo(psta
);
72 INIT_LIST_HEAD(&pstapriv
->sta_hash
[i
]);
73 list_add_tail(&psta
->list
, get_list_head(&pstapriv
->free_sta_queue
));
76 #ifdef CONFIG_8723AU_AP_MODE
77 pstapriv
->sta_dz_bitmap
= 0;
78 pstapriv
->tim_bitmap
= 0;
79 INIT_LIST_HEAD(&pstapriv
->asoc_list
);
80 INIT_LIST_HEAD(&pstapriv
->auth_list
);
81 spin_lock_init(&pstapriv
->asoc_list_lock
);
82 spin_lock_init(&pstapriv
->auth_list_lock
);
83 pstapriv
->asoc_list_cnt
= 0;
84 pstapriv
->auth_list_cnt
= 0;
85 pstapriv
->auth_to
= 3; /* 3*2 = 6 sec */
86 pstapriv
->assoc_to
= 3;
87 /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, expire after no any traffic. */
88 /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, expire after no any traffic. */
89 pstapriv
->expire_to
= 3; /* 3*2 = 6 sec */
90 pstapriv
->max_num_sta
= NUM_STA
;
95 inline int rtw_stainfo_offset23a(struct sta_priv
*stapriv
, struct sta_info
*sta
)
97 int offset
= (((u8
*)sta
) - stapriv
->pstainfo_buf
)/sizeof(struct sta_info
);
99 if (!stainfo_offset_valid(offset
))
100 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__
, offset
);
104 inline struct sta_info
*rtw_get_stainfo23a_by_offset23a(struct sta_priv
*stapriv
, int offset
)
106 if (!stainfo_offset_valid(offset
))
107 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__
, offset
);
108 return (struct sta_info
*)(stapriv
->pstainfo_buf
+ offset
* sizeof(struct sta_info
));
111 /* this function is used to free the memory of lock || sema for all stainfos */
112 void rtw_mfree_all_stainfo(struct sta_priv
*pstapriv
)
114 struct list_head
*plist
, *phead
;
115 struct sta_info
*psta
;
117 spin_lock_bh(&pstapriv
->sta_hash_lock
);
119 phead
= get_list_head(&pstapriv
->free_sta_queue
);
121 /* we really achieve a lot in this loop .... */
122 list_for_each(plist
, phead
)
123 psta
= container_of(plist
, struct sta_info
, list
);
124 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
127 void rtw_mfree_sta_priv_lock(struct sta_priv
*pstapriv
)
129 rtw_mfree_all_stainfo(pstapriv
); /* be done before free sta_hash_lock */
132 u32
_rtw_free_sta_priv23a(struct sta_priv
*pstapriv
)
134 struct list_head
*phead
, *plist
, *ptmp
;
135 struct sta_info
*psta
;
136 struct recv_reorder_ctrl
*preorder_ctrl
;
140 /* delete all reordering_ctrl_timer */
141 spin_lock_bh(&pstapriv
->sta_hash_lock
);
142 for (index
= 0; index
< NUM_STA
; index
++) {
143 phead
= &pstapriv
->sta_hash
[index
];
145 list_for_each_safe(plist
, ptmp
, phead
) {
147 psta
= container_of(plist
, struct sta_info
,
149 for (i
= 0; i
< 16 ; i
++) {
150 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
151 del_timer_sync(&preorder_ctrl
->reordering_ctrl_timer
);
155 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
156 /*===============================*/
158 rtw_mfree_sta_priv_lock(pstapriv
);
160 if (pstapriv
->pallocated_stainfo_buf
)
161 rtw_vmfree(pstapriv
->pallocated_stainfo_buf
, sizeof(struct sta_info
)*NUM_STA
+4);
166 struct sta_info
*rtw_alloc_stainfo23a(struct sta_priv
*pstapriv
, u8
*hwaddr
)
168 struct list_head
*phash_list
;
169 struct sta_info
*psta
;
170 struct rtw_queue
*pfree_sta_queue
;
171 struct recv_reorder_ctrl
*preorder_ctrl
;
175 u16 wRxSeqInitialValue
= 0xffff;
177 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
179 spin_lock_bh(&pstapriv
->sta_hash_lock
);
181 if (_rtw_queue_empty23a(pfree_sta_queue
)) {
182 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
185 psta
= container_of((&pfree_sta_queue
->queue
)->next
, struct sta_info
, list
);
187 list_del_init(&psta
->list
);
191 _rtw_init_stainfo(psta
);
193 psta
->padapter
= pstapriv
->padapter
;
195 memcpy(psta
->hwaddr
, hwaddr
, ETH_ALEN
);
197 index
= wifi_mac_hash(hwaddr
);
199 RT_TRACE(_module_rtl871x_sta_mgt_c_
, _drv_info_
,
200 ("rtw_alloc_stainfo23a: index = %x", index
));
201 if (index
>= NUM_STA
) {
202 RT_TRACE(_module_rtl871x_sta_mgt_c_
, _drv_err_
,
203 ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
207 phash_list
= &pstapriv
->sta_hash
[index
];
209 list_add_tail(&psta
->hash_list
, phash_list
);
211 pstapriv
->asoc_sta_count
++ ;
213 /* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
214 /* 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. */
215 /* So, we initialize the tid_rxseq variable as the 0xffff. */
217 for (i
= 0; i
< 16; i
++)
218 memcpy(&psta
->sta_recvpriv
.rxcache
.tid_rxseq
[i
], &wRxSeqInitialValue
, 2);
220 RT_TRACE(_module_rtl871x_sta_mgt_c_
, _drv_info_
,
221 ("alloc number_%d stainfo with hwaddr = %pM\n",
222 pstapriv
->asoc_sta_count
, hwaddr
));
224 init_addba_retry_timer23a(psta
);
226 /* for A-MPDU Rx reordering buffer control */
227 for (i
= 0; i
< 16; i
++) {
228 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
230 preorder_ctrl
->padapter
= pstapriv
->padapter
;
232 preorder_ctrl
->enable
= false;
234 preorder_ctrl
->indicate_seq
= 0xffff;
235 preorder_ctrl
->wend_b
= 0xffff;
236 /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
237 preorder_ctrl
->wsize_b
= 64;/* 64; */
239 _rtw_init_queue23a(&preorder_ctrl
->pending_recvframe_queue
);
241 rtw_init_recv_timer23a(preorder_ctrl
);
244 psta
->rssi_stat
.UndecoratedSmoothedPWDB
= (-1);
245 psta
->rssi_stat
.UndecoratedSmoothedCCK
= (-1);
247 /* init for the sequence number of received management frame */
248 psta
->RxMgmtFrameSeqNum
= 0xffff;
250 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
254 /* using pstapriv->sta_hash_lock to protect */
255 u32
rtw_free_stainfo23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
257 struct rtw_queue
*pfree_sta_queue
;
258 struct recv_reorder_ctrl
*preorder_ctrl
;
259 struct sta_xmit_priv
*pstaxmitpriv
;
260 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
261 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
262 struct hw_xmit
*phwxmit
;
268 spin_lock_bh(&psta
->lock
);
269 psta
->state
&= ~_FW_LINKED
;
270 spin_unlock_bh(&psta
->lock
);
272 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
274 pstaxmitpriv
= &psta
->sta_xmitpriv
;
276 spin_lock_bh(&pxmitpriv
->lock
);
278 rtw_free_xmitframe_queue23a(pxmitpriv
, &psta
->sleep_q
);
279 psta
->sleepq_len
= 0;
282 rtw_free_xmitframe_queue23a(pxmitpriv
, &pstaxmitpriv
->vo_q
.sta_pending
);
283 list_del_init(&pstaxmitpriv
->vo_q
.tx_pending
);
284 phwxmit
= pxmitpriv
->hwxmits
;
285 phwxmit
->accnt
-= pstaxmitpriv
->vo_q
.qcnt
;
286 pstaxmitpriv
->vo_q
.qcnt
= 0;
289 rtw_free_xmitframe_queue23a(pxmitpriv
, &pstaxmitpriv
->vi_q
.sta_pending
);
290 list_del_init(&pstaxmitpriv
->vi_q
.tx_pending
);
291 phwxmit
= pxmitpriv
->hwxmits
+1;
292 phwxmit
->accnt
-= pstaxmitpriv
->vi_q
.qcnt
;
293 pstaxmitpriv
->vi_q
.qcnt
= 0;
296 rtw_free_xmitframe_queue23a(pxmitpriv
, &pstaxmitpriv
->be_q
.sta_pending
);
297 list_del_init(&pstaxmitpriv
->be_q
.tx_pending
);
298 phwxmit
= pxmitpriv
->hwxmits
+2;
299 phwxmit
->accnt
-= pstaxmitpriv
->be_q
.qcnt
;
300 pstaxmitpriv
->be_q
.qcnt
= 0;
303 rtw_free_xmitframe_queue23a(pxmitpriv
, &pstaxmitpriv
->bk_q
.sta_pending
);
304 list_del_init(&pstaxmitpriv
->bk_q
.tx_pending
);
305 phwxmit
= pxmitpriv
->hwxmits
+3;
306 phwxmit
->accnt
-= pstaxmitpriv
->bk_q
.qcnt
;
307 pstaxmitpriv
->bk_q
.qcnt
= 0;
309 spin_unlock_bh(&pxmitpriv
->lock
);
311 list_del_init(&psta
->hash_list
);
312 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]));
313 pstapriv
->asoc_sta_count
--;
315 /* re-init sta_info; 20061114 will be init in alloc_stainfo */
316 /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
317 /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
319 del_timer_sync(&psta
->addba_retry_timer
);
321 /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
322 for (i
= 0; i
< 16; i
++) {
323 struct list_head
*phead
, *plist
;
324 struct recv_frame
*prframe
;
325 struct rtw_queue
*ppending_recvframe_queue
;
326 struct rtw_queue
*pfree_recv_queue
= &padapter
->recvpriv
.free_recv_queue
;
328 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
330 del_timer_sync(&preorder_ctrl
->reordering_ctrl_timer
);
332 ppending_recvframe_queue
= &preorder_ctrl
->pending_recvframe_queue
;
334 spin_lock_bh(&ppending_recvframe_queue
->lock
);
335 phead
= get_list_head(ppending_recvframe_queue
);
338 while (!list_empty(phead
)) {
339 prframe
= container_of(plist
, struct recv_frame
, list
);
341 list_del_init(&prframe
->list
);
342 rtw_free_recvframe23a(prframe
, pfree_recv_queue
);
344 spin_unlock_bh(&ppending_recvframe_queue
->lock
);
346 if (!(psta
->state
& WIFI_AP_STATE
))
347 rtw_hal_set_odm_var23a(padapter
, HAL_ODM_STA_INFO
, psta
, false);
348 #ifdef CONFIG_8723AU_AP_MODE
349 spin_lock_bh(&pstapriv
->auth_list_lock
);
350 if (!list_empty(&psta
->auth_list
)) {
351 list_del_init(&psta
->auth_list
);
352 pstapriv
->auth_list_cnt
--;
354 spin_unlock_bh(&pstapriv
->auth_list_lock
);
358 psta
->sleepq_ac_len
= 0;
361 psta
->max_sp_len
= 0;
367 psta
->has_legacy_ac
= 0;
369 pstapriv
->sta_dz_bitmap
&= ~CHKBIT(psta
->aid
);
370 pstapriv
->tim_bitmap
&= ~CHKBIT(psta
->aid
);
372 if ((psta
->aid
>0) && (pstapriv
->sta_aid
[psta
->aid
- 1] == psta
)) {
373 pstapriv
->sta_aid
[psta
->aid
- 1] = NULL
;
376 #endif /* CONFIG_8723AU_AP_MODE */
377 list_add_tail(&psta
->list
, get_list_head(pfree_sta_queue
));
382 /* free all stainfo which in sta_hash[all] */
383 void rtw_free_all_stainfo23a(struct rtw_adapter
*padapter
)
385 struct list_head
*plist
, *phead
, *ptmp
;
386 struct sta_info
*psta
;
387 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
388 struct sta_info
* pbcmc_stainfo
= rtw_get_bcmc_stainfo23a(padapter
);
389 s32 index
; if (pstapriv
->asoc_sta_count
== 1)
392 spin_lock_bh(&pstapriv
->sta_hash_lock
);
394 for (index
= 0; index
< NUM_STA
; index
++) {
395 phead
= &pstapriv
->sta_hash
[index
];
397 list_for_each_safe(plist
, ptmp
, phead
) {
398 psta
= container_of(plist
, struct sta_info
, hash_list
);
400 if (pbcmc_stainfo
!= psta
)
401 rtw_free_stainfo23a(padapter
, psta
);
404 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
407 /* any station allocated can be searched by hash list */
408 struct sta_info
*rtw_get_stainfo23a(struct sta_priv
*pstapriv
, u8
*hwaddr
)
410 struct list_head
*plist
, *phead
;
411 struct sta_info
*psta
= NULL
;
414 u8 bc_addr
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
419 if (is_multicast_ether_addr(hwaddr
))
424 index
= wifi_mac_hash(addr
);
426 spin_lock_bh(&pstapriv
->sta_hash_lock
);
428 phead
= &pstapriv
->sta_hash
[index
];
430 list_for_each(plist
, phead
) {
431 psta
= container_of(plist
, struct sta_info
, hash_list
);
433 if (!memcmp(psta
->hwaddr
, addr
, ETH_ALEN
)) {
434 /* if found the matched address */
439 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
443 u32
rtw_init_bcmc_stainfo23a(struct rtw_adapter
* padapter
)
445 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
446 struct sta_info
*psta
;
447 struct tx_servq
*ptxservq
;
449 unsigned char bcast_addr
[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
451 psta
= rtw_alloc_stainfo23a(pstapriv
, bcast_addr
);
454 RT_TRACE(_module_rtl871x_sta_mgt_c_
, _drv_err_
,
455 ("rtw_alloc_stainfo23a fail"));
458 /* default broadcast & multicast use macid 1 */
461 ptxservq
= &psta
->sta_xmitpriv
.be_q
;
465 struct sta_info
*rtw_get_bcmc_stainfo23a(struct rtw_adapter
*padapter
)
467 struct sta_info
*psta
;
468 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
469 u8 bc_addr
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
471 psta
= rtw_get_stainfo23a(pstapriv
, bc_addr
);
475 u8
rtw_access_ctrl23a(struct rtw_adapter
*padapter
, u8
*mac_addr
)
478 #ifdef CONFIG_8723AU_AP_MODE
479 struct list_head
*plist
, *phead
;
480 struct rtw_wlan_acl_node
*paclnode
;
482 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
483 struct wlan_acl_pool
*pacl_list
= &pstapriv
->acl_list
;
484 struct rtw_queue
*pacl_node_q
= &pacl_list
->acl_node_q
;
486 spin_lock_bh(&pacl_node_q
->lock
);
487 phead
= get_list_head(pacl_node_q
);
489 list_for_each(plist
, phead
) {
490 paclnode
= container_of(plist
, struct rtw_wlan_acl_node
, list
);
492 if (!memcmp(paclnode
->addr
, mac_addr
, ETH_ALEN
)) {
493 if (paclnode
->valid
) {
499 spin_unlock_bh(&pacl_node_q
->lock
);
501 if (pacl_list
->mode
== 1)/* accept unless in deny list */
502 res
= (match
) ? false : true;
503 else if (pacl_list
->mode
== 2)/* deny unless in accept list */
504 res
= (match
) ? true : false;