blob: dc9d0ddf6b3ae421c234e13ee497f717520350fc [file] [log] [blame]
Larry Finger1b509ca2013-08-21 22:33:48 -05001/******************************************************************************
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
22#include <osdep_service.h>
23#include <drv_types.h>
24#include <recv_osdep.h>
25#include <xmit_osdep.h>
26#include <mlme_osdep.h>
27#include <sta_info.h>
Larry Fingerd249db9e52014-02-07 18:38:50 -060028#include <linux/vmalloc.h>
Larry Finger1b509ca2013-08-21 22:33:48 -050029
30static void _rtw_init_stainfo(struct sta_info *psta)
31{
Jia He7be921a22014-11-04 09:39:58 +080032 memset((u8 *)psta, 0, sizeof(struct sta_info));
Larry Finger1b509ca2013-08-21 22:33:48 -050033
Larry Fingerf214e522013-12-19 22:38:38 -060034 spin_lock_init(&psta->lock);
navin patidaraa3f5cc2014-06-22 13:49:34 +053035 INIT_LIST_HEAD(&psta->list);
36 INIT_LIST_HEAD(&psta->hash_list);
Larry Finger1b509ca2013-08-21 22:33:48 -050037 _rtw_init_queue(&psta->sleep_q);
38 psta->sleepq_len = 0;
39
40 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
41 _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
42
43#ifdef CONFIG_88EU_AP_MODE
44
navin patidaraa3f5cc2014-06-22 13:49:34 +053045 INIT_LIST_HEAD(&psta->asoc_list);
Larry Finger1b509ca2013-08-21 22:33:48 -050046
navin patidaraa3f5cc2014-06-22 13:49:34 +053047 INIT_LIST_HEAD(&psta->auth_list);
Larry Finger1b509ca2013-08-21 22:33:48 -050048
49 psta->expire_to = 0;
50
51 psta->flags = 0;
52
53 psta->capability = 0;
54
55 psta->bpairwise_key_installed = false;
56
57#ifdef CONFIG_88EU_AP_MODE
58 psta->nonerp_set = 0;
59 psta->no_short_slot_time_set = 0;
60 psta->no_short_preamble_set = 0;
61 psta->no_ht_gf_set = 0;
62 psta->no_ht_set = 0;
63 psta->ht_20mhz_set = 0;
64#endif
65
66 psta->under_exist_checking = 0;
67
68 psta->keep_alive_trycnt = 0;
69
70#endif /* CONFIG_88EU_AP_MODE */
71
Larry Finger1b509ca2013-08-21 22:33:48 -050072}
73
74u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
75{
76 struct sta_info *psta;
77 s32 i;
78
Larry Finger1b509ca2013-08-21 22:33:48 -050079
Larry Finger2397c6e2014-02-06 20:45:42 -060080 pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
Larry Finger1b509ca2013-08-21 22:33:48 -050081
82 if (!pstapriv->pallocated_stainfo_buf)
83 return _FAIL;
84
85 pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
86 ((size_t)(pstapriv->pallocated_stainfo_buf) & 3);
87
88 _rtw_init_queue(&pstapriv->free_sta_queue);
89
Larry Fingerf214e522013-12-19 22:38:38 -060090 spin_lock_init(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -050091
92 pstapriv->asoc_sta_count = 0;
93 _rtw_init_queue(&pstapriv->sleep_q);
94 _rtw_init_queue(&pstapriv->wakeup_q);
95
96 psta = (struct sta_info *)(pstapriv->pstainfo_buf);
97
98 for (i = 0; i < NUM_STA; i++) {
99 _rtw_init_stainfo(psta);
100
navin patidaraa3f5cc2014-06-22 13:49:34 +0530101 INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
Larry Finger1b509ca2013-08-21 22:33:48 -0500102
navin patidarae6787a2014-06-22 13:49:31 +0530103 list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
Larry Finger1b509ca2013-08-21 22:33:48 -0500104
105 psta++;
106 }
107
108#ifdef CONFIG_88EU_AP_MODE
109
110 pstapriv->sta_dz_bitmap = 0;
111 pstapriv->tim_bitmap = 0;
112
navin patidaraa3f5cc2014-06-22 13:49:34 +0530113 INIT_LIST_HEAD(&pstapriv->asoc_list);
114 INIT_LIST_HEAD(&pstapriv->auth_list);
Larry Fingerf214e522013-12-19 22:38:38 -0600115 spin_lock_init(&pstapriv->asoc_list_lock);
116 spin_lock_init(&pstapriv->auth_list_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500117 pstapriv->asoc_list_cnt = 0;
118 pstapriv->auth_list_cnt = 0;
119
120 pstapriv->auth_to = 3; /* 3*2 = 6 sec */
121 pstapriv->assoc_to = 3;
122 pstapriv->expire_to = 3; /* 3*2 = 6 sec */
123 pstapriv->max_num_sta = NUM_STA;
124#endif
125
Larry Finger1b509ca2013-08-21 22:33:48 -0500126
127 return _SUCCESS;
128}
129
130inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
131{
132 int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
133
134 if (!stainfo_offset_valid(offset))
135 DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
136
137 return offset;
138}
139
140inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
141{
142 if (!stainfo_offset_valid(offset))
143 DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
144
145 return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
146}
147
Larry Finger1b509ca2013-08-21 22:33:48 -0500148/* this function is used to free the memory of lock || sema for all stainfos */
Larry Finger1f8e6352013-12-22 17:36:58 -0600149static void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
Larry Finger1b509ca2013-08-21 22:33:48 -0500150{
Larry Finger1b509ca2013-08-21 22:33:48 -0500151 struct list_head *plist, *phead;
152 struct sta_info *psta = NULL;
153
Larry Finger1b509ca2013-08-21 22:33:48 -0500154
Larry Finger7057dcb2013-12-19 22:38:34 -0600155 spin_lock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500156
157 phead = get_list_head(&pstapriv->free_sta_queue);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600158 plist = phead->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500159
navin patidar84660702014-06-22 13:49:32 +0530160 while (phead != plist) {
Larry Fingerbea88102014-02-09 15:15:57 -0600161 psta = container_of(plist, struct sta_info , list);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600162 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500163 }
164
Larry Fingere02bcf62013-12-19 22:38:35 -0600165 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500166
Larry Finger1b509ca2013-08-21 22:33:48 -0500167}
168
169static void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
170{
Larry Finger1b509ca2013-08-21 22:33:48 -0500171 rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
Larry Finger1b509ca2013-08-21 22:33:48 -0500172}
173
174u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
175{
Larry Finger1b509ca2013-08-21 22:33:48 -0500176 struct list_head *phead, *plist;
177 struct sta_info *psta = NULL;
178 struct recv_reorder_ctrl *preorder_ctrl;
179 int index;
180
Larry Finger1b509ca2013-08-21 22:33:48 -0500181 if (pstapriv) {
182 /* delete all reordering_ctrl_timer */
Larry Finger7057dcb2013-12-19 22:38:34 -0600183 spin_lock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500184 for (index = 0; index < NUM_STA; index++) {
185 phead = &(pstapriv->sta_hash[index]);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600186 plist = phead->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500187
navin patidar84660702014-06-22 13:49:32 +0530188 while (phead != plist) {
Larry Finger1b509ca2013-08-21 22:33:48 -0500189 int i;
Larry Fingerbea88102014-02-09 15:15:57 -0600190 psta = container_of(plist, struct sta_info , hash_list);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600191 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500192
193 for (i = 0; i < 16; i++) {
194 preorder_ctrl = &psta->recvreorder_ctrl[i];
Larry Fingerf42f52a2014-02-09 15:15:54 -0600195 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
Larry Finger1b509ca2013-08-21 22:33:48 -0500196 }
197 }
198 }
Larry Fingere02bcf62013-12-19 22:38:35 -0600199 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500200 /*===============================*/
201
202 rtw_mfree_sta_priv_lock(pstapriv);
203
Faris de Haanecdca552013-09-09 17:34:44 +0200204 if (pstapriv->pallocated_stainfo_buf)
Larry Finger03bd6ae2014-02-06 20:45:43 -0600205 vfree(pstapriv->pallocated_stainfo_buf);
Larry Finger1b509ca2013-08-21 22:33:48 -0500206 }
207
Larry Finger1b509ca2013-08-21 22:33:48 -0500208 return _SUCCESS;
209}
210
211struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
212{
Larry Finger1b509ca2013-08-21 22:33:48 -0500213 s32 index;
214 struct list_head *phash_list;
215 struct sta_info *psta;
216 struct __queue *pfree_sta_queue;
217 struct recv_reorder_ctrl *preorder_ctrl;
218 int i = 0;
219 u16 wRxSeqInitialValue = 0xffff;
220
Larry Finger1b509ca2013-08-21 22:33:48 -0500221
222 pfree_sta_queue = &pstapriv->free_sta_queue;
223
Larry Finger7057dcb2013-12-19 22:38:34 -0600224 spin_lock_bh(&(pfree_sta_queue->lock));
Larry Finger1b509ca2013-08-21 22:33:48 -0500225
navin patidarf7091bc2014-06-22 14:06:29 +0530226 if (list_empty(&pfree_sta_queue->queue)) {
Larry Fingere02bcf62013-12-19 22:38:35 -0600227 spin_unlock_bh(&pfree_sta_queue->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500228 psta = NULL;
229 } else {
Larry Fingerc44e5e32014-02-09 15:15:58 -0600230 psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
navin patidar8d5bdec2014-06-22 14:06:27 +0530231 list_del_init(&(psta->list));
Larry Fingere02bcf62013-12-19 22:38:35 -0600232 spin_unlock_bh(&pfree_sta_queue->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500233 _rtw_init_stainfo(psta);
234 memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
235 index = wifi_mac_hash(hwaddr);
236 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index=%x", index));
237 if (index >= NUM_STA) {
238 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
239 psta = NULL;
240 goto exit;
241 }
242 phash_list = &(pstapriv->sta_hash[index]);
243
Larry Finger7057dcb2013-12-19 22:38:34 -0600244 spin_lock_bh(&(pstapriv->sta_hash_lock));
Larry Finger1b509ca2013-08-21 22:33:48 -0500245
navin patidarae6787a2014-06-22 13:49:31 +0530246 list_add_tail(&psta->hash_list, phash_list);
Larry Finger1b509ca2013-08-21 22:33:48 -0500247
Faris de Haanecdca552013-09-09 17:34:44 +0200248 pstapriv->asoc_sta_count++;
Larry Finger1b509ca2013-08-21 22:33:48 -0500249
Larry Fingere02bcf62013-12-19 22:38:35 -0600250 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500251
252/* Commented by Albert 2009/08/13 */
253/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
254/* 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. */
255/* So, we initialize the tid_rxseq variable as the 0xffff. */
256
257 for (i = 0; i < 16; i++)
258 memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
259
260 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
261 ("alloc number_%d stainfo with hwaddr = %pM\n",
262 pstapriv->asoc_sta_count , hwaddr));
263
264 init_addba_retry_timer(pstapriv->padapter, psta);
265
266 /* for A-MPDU Rx reordering buffer control */
267 for (i = 0; i < 16; i++) {
268 preorder_ctrl = &psta->recvreorder_ctrl[i];
269
270 preorder_ctrl->padapter = pstapriv->padapter;
271
272 preorder_ctrl->enable = false;
273
274 preorder_ctrl->indicate_seq = 0xffff;
275 preorder_ctrl->wend_b = 0xffff;
276 preorder_ctrl->wsize_b = 64;/* 64; */
277
278 _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
279
280 rtw_init_recv_timer(preorder_ctrl);
281 }
282
283 /* init for DM */
284 psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
285 psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
286
287 /* init for the sequence number of received management frame */
288 psta->RxMgmtFrameSeqNum = 0xffff;
289 }
290
291exit:
Larry Finger1b509ca2013-08-21 22:33:48 -0500292 return psta;
293}
294
295/* using pstapriv->sta_hash_lock to protect */
296u32 rtw_free_stainfo(struct adapter *padapter , struct sta_info *psta)
297{
298 int i;
Larry Finger1b509ca2013-08-21 22:33:48 -0500299 struct __queue *pfree_sta_queue;
300 struct recv_reorder_ctrl *preorder_ctrl;
301 struct sta_xmit_priv *pstaxmitpriv;
302 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
303 struct sta_priv *pstapriv = &padapter->stapriv;
304
Larry Finger1b509ca2013-08-21 22:33:48 -0500305
306 if (psta == NULL)
307 goto exit;
308
309 pfree_sta_queue = &pstapriv->free_sta_queue;
310
311 pstaxmitpriv = &psta->sta_xmitpriv;
312
Larry Finger7057dcb2013-12-19 22:38:34 -0600313 spin_lock_bh(&pxmitpriv->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500314
315 rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
316 psta->sleepq_len = 0;
317
318 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
319
navin patidar8d5bdec2014-06-22 14:06:27 +0530320 list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
Larry Finger1b509ca2013-08-21 22:33:48 -0500321
322 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
323
navin patidar8d5bdec2014-06-22 14:06:27 +0530324 list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
Larry Finger1b509ca2013-08-21 22:33:48 -0500325
326 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
327
navin patidar8d5bdec2014-06-22 14:06:27 +0530328 list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
Larry Finger1b509ca2013-08-21 22:33:48 -0500329
330 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
331
navin patidar8d5bdec2014-06-22 14:06:27 +0530332 list_del_init(&(pstaxmitpriv->be_q.tx_pending));
Larry Finger1b509ca2013-08-21 22:33:48 -0500333
Larry Fingere02bcf62013-12-19 22:38:35 -0600334 spin_unlock_bh(&pxmitpriv->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500335
navin patidar8d5bdec2014-06-22 14:06:27 +0530336 list_del_init(&psta->hash_list);
Larry Finger1b509ca2013-08-21 22:33:48 -0500337 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]));
338 pstapriv->asoc_sta_count--;
339
340 /* re-init sta_info; 20061114 */
341 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
342 _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
343
Larry Fingerf42f52a2014-02-09 15:15:54 -0600344 del_timer_sync(&psta->addba_retry_timer);
Larry Finger1b509ca2013-08-21 22:33:48 -0500345
346 /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
Faris de Haanecdca552013-09-09 17:34:44 +0200347 for (i = 0; i < 16; i++) {
Larry Finger1b509ca2013-08-21 22:33:48 -0500348 struct list_head *phead, *plist;
Larry Fingerf31cca82014-02-14 16:54:07 -0600349 struct recv_frame *prhdr;
350 struct recv_frame *prframe;
Larry Finger1b509ca2013-08-21 22:33:48 -0500351 struct __queue *ppending_recvframe_queue;
352 struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
353
354 preorder_ctrl = &psta->recvreorder_ctrl[i];
355
Larry Fingerf42f52a2014-02-09 15:15:54 -0600356 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
Larry Finger1b509ca2013-08-21 22:33:48 -0500357
358 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
359
Larry Finger7057dcb2013-12-19 22:38:34 -0600360 spin_lock_bh(&ppending_recvframe_queue->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500361
362 phead = get_list_head(ppending_recvframe_queue);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600363 plist = phead->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500364
navin patidar9c4b0e72014-06-22 13:49:33 +0530365 while (!list_empty(phead)) {
Larry Fingerf31cca82014-02-14 16:54:07 -0600366 prhdr = container_of(plist, struct recv_frame, list);
367 prframe = (struct recv_frame *)prhdr;
Larry Finger1b509ca2013-08-21 22:33:48 -0500368
Larry Fingerc44e5e32014-02-09 15:15:58 -0600369 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500370
navin patidar8d5bdec2014-06-22 14:06:27 +0530371 list_del_init(&(prframe->list));
Larry Finger1b509ca2013-08-21 22:33:48 -0500372
373 rtw_free_recvframe(prframe, pfree_recv_queue);
374 }
375
Larry Fingere02bcf62013-12-19 22:38:35 -0600376 spin_unlock_bh(&ppending_recvframe_queue->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500377 }
378
379 if (!(psta->state & WIFI_AP_STATE))
380 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
381
382#ifdef CONFIG_88EU_AP_MODE
383
Larry Finger7057dcb2013-12-19 22:38:34 -0600384 spin_lock_bh(&pstapriv->auth_list_lock);
navin patidar9c4b0e72014-06-22 13:49:33 +0530385 if (!list_empty(&psta->auth_list)) {
navin patidar8d5bdec2014-06-22 14:06:27 +0530386 list_del_init(&psta->auth_list);
Larry Finger1b509ca2013-08-21 22:33:48 -0500387 pstapriv->auth_list_cnt--;
388 }
Larry Fingere02bcf62013-12-19 22:38:35 -0600389 spin_unlock_bh(&pstapriv->auth_list_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500390
391 psta->expire_to = 0;
392
393 psta->sleepq_ac_len = 0;
394 psta->qos_info = 0;
395
396 psta->max_sp_len = 0;
397 psta->uapsd_bk = 0;
398 psta->uapsd_be = 0;
399 psta->uapsd_vi = 0;
400 psta->uapsd_vo = 0;
401 psta->has_legacy_ac = 0;
402
403 pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
404 pstapriv->tim_bitmap &= ~BIT(psta->aid);
405
406 if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
407 pstapriv->sta_aid[psta->aid - 1] = NULL;
408 psta->aid = 0;
409 }
410
411 psta->under_exist_checking = 0;
412
413#endif /* CONFIG_88EU_AP_MODE */
414
Larry Finger7057dcb2013-12-19 22:38:34 -0600415 spin_lock_bh(&(pfree_sta_queue->lock));
navin patidarae6787a2014-06-22 13:49:31 +0530416 list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
Larry Fingere02bcf62013-12-19 22:38:35 -0600417 spin_unlock_bh(&pfree_sta_queue->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500418
419exit:
420
Larry Finger1b509ca2013-08-21 22:33:48 -0500421
422 return _SUCCESS;
423}
424
425/* free all stainfo which in sta_hash[all] */
426void rtw_free_all_stainfo(struct adapter *padapter)
427{
Larry Finger1b509ca2013-08-21 22:33:48 -0500428 struct list_head *plist, *phead;
429 s32 index;
430 struct sta_info *psta = NULL;
431 struct sta_priv *pstapriv = &padapter->stapriv;
432 struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
433
Larry Finger1b509ca2013-08-21 22:33:48 -0500434
435 if (pstapriv->asoc_sta_count == 1)
Larry Fingerf578b5d2014-02-09 15:15:59 -0600436 return;
Larry Finger1b509ca2013-08-21 22:33:48 -0500437
Larry Finger7057dcb2013-12-19 22:38:34 -0600438 spin_lock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500439
440 for (index = 0; index < NUM_STA; index++) {
441 phead = &(pstapriv->sta_hash[index]);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600442 plist = phead->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500443
navin patidar84660702014-06-22 13:49:32 +0530444 while (phead != plist) {
Larry Fingerbea88102014-02-09 15:15:57 -0600445 psta = container_of(plist, struct sta_info , hash_list);
Larry Finger1b509ca2013-08-21 22:33:48 -0500446
Larry Fingerc44e5e32014-02-09 15:15:58 -0600447 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500448
449 if (pbcmc_stainfo != psta)
450 rtw_free_stainfo(padapter , psta);
451 }
452 }
Larry Fingere02bcf62013-12-19 22:38:35 -0600453 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500454}
455
456/* any station allocated can be searched by hash list */
457struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
458{
Larry Finger1b509ca2013-08-21 22:33:48 -0500459 struct list_head *plist, *phead;
460 struct sta_info *psta = NULL;
461 u32 index;
462 u8 *addr;
463 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
464
Larry Finger1b509ca2013-08-21 22:33:48 -0500465
466 if (hwaddr == NULL)
467 return NULL;
468
469 if (IS_MCAST(hwaddr))
470 addr = bc_addr;
471 else
472 addr = hwaddr;
473
474 index = wifi_mac_hash(addr);
475
Larry Finger7057dcb2013-12-19 22:38:34 -0600476 spin_lock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500477
478 phead = &(pstapriv->sta_hash[index]);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600479 plist = phead->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500480
navin patidar84660702014-06-22 13:49:32 +0530481 while (phead != plist) {
Larry Fingerbea88102014-02-09 15:15:57 -0600482 psta = container_of(plist, struct sta_info, hash_list);
Larry Finger1b509ca2013-08-21 22:33:48 -0500483
Larry Fingerf42f52a2014-02-09 15:15:54 -0600484 if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
Larry Finger1b509ca2013-08-21 22:33:48 -0500485 /* if found the matched address */
486 break;
487 }
488 psta = NULL;
Larry Fingerc44e5e32014-02-09 15:15:58 -0600489 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500490 }
491
Larry Fingere02bcf62013-12-19 22:38:35 -0600492 spin_unlock_bh(&pstapriv->sta_hash_lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500493 return psta;
494}
495
496u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
497{
498 struct sta_info *psta;
499 u32 res = _SUCCESS;
500 unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
501 struct sta_priv *pstapriv = &padapter->stapriv;
502
Larry Finger1b509ca2013-08-21 22:33:48 -0500503
504 psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
505
506 if (psta == NULL) {
507 res = _FAIL;
508 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
509 goto exit;
510 }
511
512 /* default broadcast & multicast use macid 1 */
513 psta->mac_id = 1;
514
515exit:
Larry Finger1b509ca2013-08-21 22:33:48 -0500516 return res;
517}
518
519struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
520{
521 struct sta_info *psta;
522 struct sta_priv *pstapriv = &padapter->stapriv;
523 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Larry Finger1b509ca2013-08-21 22:33:48 -0500524 psta = rtw_get_stainfo(pstapriv, bc_addr);
Larry Finger1b509ca2013-08-21 22:33:48 -0500525 return psta;
526}
527
528u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
529{
530 u8 res = true;
531#ifdef CONFIG_88EU_AP_MODE
Larry Finger1b509ca2013-08-21 22:33:48 -0500532 struct list_head *plist, *phead;
533 struct rtw_wlan_acl_node *paclnode;
534 u8 match = false;
535 struct sta_priv *pstapriv = &padapter->stapriv;
536 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
537 struct __queue *pacl_node_q = &pacl_list->acl_node_q;
538
Larry Finger7057dcb2013-12-19 22:38:34 -0600539 spin_lock_bh(&(pacl_node_q->lock));
Larry Finger1b509ca2013-08-21 22:33:48 -0500540 phead = get_list_head(pacl_node_q);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600541 plist = phead->next;
navin patidar84660702014-06-22 13:49:32 +0530542 while (phead != plist) {
Larry Fingerbea88102014-02-09 15:15:57 -0600543 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
Larry Fingerc44e5e32014-02-09 15:15:58 -0600544 plist = plist->next;
Larry Finger1b509ca2013-08-21 22:33:48 -0500545
Larry Fingerf42f52a2014-02-09 15:15:54 -0600546 if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
Larry Finger1b509ca2013-08-21 22:33:48 -0500547 if (paclnode->valid) {
548 match = true;
549 break;
550 }
551 }
552 }
Larry Fingere02bcf62013-12-19 22:38:35 -0600553 spin_unlock_bh(&pacl_node_q->lock);
Larry Finger1b509ca2013-08-21 22:33:48 -0500554
555 if (pacl_list->mode == 1)/* accept unless in deny list */
556 res = (match) ? false : true;
557 else if (pacl_list->mode == 2)/* deny unless in accept list */
558 res = (match) ? true : false;
559 else
560 res = true;
561
562#endif
563
564 return res;
565}