[go: nahoru, domu]

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
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>
28#include <linux/vmalloc.h>
29
30static void _rtw_init_stainfo(struct sta_info *psta)
31{
32	memset((u8 *)psta, 0, sizeof (struct sta_info));
33
34	 spin_lock_init(&psta->lock);
35	INIT_LIST_HEAD(&psta->list);
36	INIT_LIST_HEAD(&psta->hash_list);
37	_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
45	INIT_LIST_HEAD(&psta->asoc_list);
46
47	INIT_LIST_HEAD(&psta->auth_list);
48
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
72}
73
74u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
75{
76	struct sta_info *psta;
77	s32 i;
78
79
80	pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
81
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
90	spin_lock_init(&pstapriv->sta_hash_lock);
91
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
101		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
102
103		list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
104
105		psta++;
106	}
107
108#ifdef CONFIG_88EU_AP_MODE
109
110	pstapriv->sta_dz_bitmap = 0;
111	pstapriv->tim_bitmap = 0;
112
113	INIT_LIST_HEAD(&pstapriv->asoc_list);
114	INIT_LIST_HEAD(&pstapriv->auth_list);
115	spin_lock_init(&pstapriv->asoc_list_lock);
116	spin_lock_init(&pstapriv->auth_list_lock);
117	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
126
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
148/*  this function is used to free the memory of lock || sema for all stainfos */
149static void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
150{
151	struct list_head *plist, *phead;
152	struct sta_info *psta = NULL;
153
154
155	spin_lock_bh(&pstapriv->sta_hash_lock);
156
157	phead = get_list_head(&pstapriv->free_sta_queue);
158	plist = phead->next;
159
160	while (phead != plist) {
161		psta = container_of(plist, struct sta_info , list);
162		plist = plist->next;
163	}
164
165	spin_unlock_bh(&pstapriv->sta_hash_lock);
166
167}
168
169static void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
170{
171	 rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
172}
173
174u32	_rtw_free_sta_priv(struct	sta_priv *pstapriv)
175{
176	struct list_head *phead, *plist;
177	struct sta_info *psta = NULL;
178	struct recv_reorder_ctrl *preorder_ctrl;
179	int	index;
180
181	if (pstapriv) {
182		/*	delete all reordering_ctrl_timer		*/
183		spin_lock_bh(&pstapriv->sta_hash_lock);
184		for (index = 0; index < NUM_STA; index++) {
185			phead = &(pstapriv->sta_hash[index]);
186			plist = phead->next;
187
188			while (phead != plist) {
189				int i;
190				psta = container_of(plist, struct sta_info , hash_list);
191				plist = plist->next;
192
193				for (i = 0; i < 16; i++) {
194					preorder_ctrl = &psta->recvreorder_ctrl[i];
195					del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
196				}
197			}
198		}
199		spin_unlock_bh(&pstapriv->sta_hash_lock);
200		/*===============================*/
201
202		rtw_mfree_sta_priv_lock(pstapriv);
203
204		if (pstapriv->pallocated_stainfo_buf)
205			vfree(pstapriv->pallocated_stainfo_buf);
206	}
207
208	return _SUCCESS;
209}
210
211struct	sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
212{
213	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
221
222	pfree_sta_queue = &pstapriv->free_sta_queue;
223
224	spin_lock_bh(&(pfree_sta_queue->lock));
225
226	if (list_empty(&pfree_sta_queue->queue)) {
227		spin_unlock_bh(&pfree_sta_queue->lock);
228		psta = NULL;
229	} else {
230		psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
231		list_del_init(&(psta->list));
232		spin_unlock_bh(&pfree_sta_queue->lock);
233		_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
244		spin_lock_bh(&(pstapriv->sta_hash_lock));
245
246		list_add_tail(&psta->hash_list, phash_list);
247
248		pstapriv->asoc_sta_count++;
249
250		spin_unlock_bh(&pstapriv->sta_hash_lock);
251
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:
292	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;
299	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
305
306	if (psta == NULL)
307		goto exit;
308
309	pfree_sta_queue = &pstapriv->free_sta_queue;
310
311	pstaxmitpriv = &psta->sta_xmitpriv;
312
313	spin_lock_bh(&pxmitpriv->lock);
314
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
320	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
321
322	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
323
324	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
325
326	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
327
328	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
329
330	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
331
332	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
333
334	spin_unlock_bh(&pxmitpriv->lock);
335
336	list_del_init(&psta->hash_list);
337	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
344	del_timer_sync(&psta->addba_retry_timer);
345
346	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
347	for (i = 0; i < 16; i++) {
348		struct list_head *phead, *plist;
349		struct recv_frame *prhdr;
350		struct recv_frame *prframe;
351		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
356		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
357
358		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
359
360		spin_lock_bh(&ppending_recvframe_queue->lock);
361
362		phead =		get_list_head(ppending_recvframe_queue);
363		plist = phead->next;
364
365		while (!list_empty(phead)) {
366			prhdr = container_of(plist, struct recv_frame, list);
367			prframe = (struct recv_frame *)prhdr;
368
369			plist = plist->next;
370
371			list_del_init(&(prframe->list));
372
373			rtw_free_recvframe(prframe, pfree_recv_queue);
374		}
375
376		spin_unlock_bh(&ppending_recvframe_queue->lock);
377	}
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
384	spin_lock_bh(&pstapriv->auth_list_lock);
385	if (!list_empty(&psta->auth_list)) {
386		list_del_init(&psta->auth_list);
387		pstapriv->auth_list_cnt--;
388	}
389	spin_unlock_bh(&pstapriv->auth_list_lock);
390
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
415	spin_lock_bh(&(pfree_sta_queue->lock));
416	list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
417	spin_unlock_bh(&pfree_sta_queue->lock);
418
419exit:
420
421
422	return _SUCCESS;
423}
424
425/*  free all stainfo which in sta_hash[all] */
426void rtw_free_all_stainfo(struct adapter *padapter)
427{
428	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
434
435	if (pstapriv->asoc_sta_count == 1)
436		return;
437
438	spin_lock_bh(&pstapriv->sta_hash_lock);
439
440	for (index = 0; index < NUM_STA; index++) {
441		phead = &(pstapriv->sta_hash[index]);
442		plist = phead->next;
443
444		while (phead != plist) {
445			psta = container_of(plist, struct sta_info , hash_list);
446
447			plist = plist->next;
448
449			if (pbcmc_stainfo != psta)
450				rtw_free_stainfo(padapter , psta);
451		}
452	}
453	spin_unlock_bh(&pstapriv->sta_hash_lock);
454}
455
456/* any station allocated can be searched by hash list */
457struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
458{
459	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
465
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
476	spin_lock_bh(&pstapriv->sta_hash_lock);
477
478	phead = &(pstapriv->sta_hash[index]);
479	plist = phead->next;
480
481	while (phead != plist) {
482		psta = container_of(plist, struct sta_info, hash_list);
483
484		if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
485			/*  if found the matched address */
486			break;
487		}
488		psta = NULL;
489		plist = plist->next;
490	}
491
492	spin_unlock_bh(&pstapriv->sta_hash_lock);
493	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
503
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:
516	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};
524	 psta = rtw_get_stainfo(pstapriv, bc_addr);
525	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
532	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
539	spin_lock_bh(&(pacl_node_q->lock));
540	phead = get_list_head(pacl_node_q);
541	plist = phead->next;
542	while (phead != plist) {
543		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
544		plist = plist->next;
545
546		if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
547			if (paclnode->valid) {
548				match = true;
549				break;
550			}
551		}
552	}
553	spin_unlock_bh(&pacl_node_q->lock);
554
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}
566