[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 ******************************************************************************/
15#define _RTW_STA_MGT_C_
16
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>
22#include <sta_info.h>
23#include <rtl8723a_hal.h>
24
25static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
26
27static void _rtw_init_stainfo(struct sta_info *psta)
28{
29	memset((u8 *)psta, 0, sizeof(struct sta_info));
30	spin_lock_init(&psta->lock);
31	INIT_LIST_HEAD(&psta->list);
32	INIT_LIST_HEAD(&psta->hash_list);
33	_rtw_init_queue23a(&psta->sleep_q);
34	psta->sleepq_len = 0;
35	_rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv);
36	_rtw_init_sta_recv_priv23a(&psta->sta_recvpriv);
37#ifdef CONFIG_8723AU_AP_MODE
38	INIT_LIST_HEAD(&psta->asoc_list);
39	INIT_LIST_HEAD(&psta->auth_list);
40	psta->expire_to = 0;
41	psta->flags = 0;
42	psta->capability = 0;
43	psta->bpairwise_key_installed = false;
44	psta->nonerp_set = 0;
45	psta->no_short_slot_time_set = 0;
46	psta->no_short_preamble_set = 0;
47	psta->no_ht_gf_set = 0;
48	psta->no_ht_set = 0;
49	psta->ht_20mhz_set = 0;
50	psta->keep_alive_trycnt = 0;
51#endif	/*  CONFIG_8723AU_AP_MODE */
52}
53
54int _rtw_init_sta_priv23a(struct sta_priv *pstapriv)
55{
56	int i;
57
58	spin_lock_init(&pstapriv->sta_hash_lock);
59	pstapriv->asoc_sta_count = 0;
60	for (i = 0; i < NUM_STA; i++)
61		INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
62
63#ifdef CONFIG_8723AU_AP_MODE
64	pstapriv->sta_dz_bitmap = 0;
65	pstapriv->tim_bitmap = 0;
66	INIT_LIST_HEAD(&pstapriv->asoc_list);
67	INIT_LIST_HEAD(&pstapriv->auth_list);
68	spin_lock_init(&pstapriv->asoc_list_lock);
69	spin_lock_init(&pstapriv->auth_list_lock);
70	pstapriv->asoc_list_cnt = 0;
71	pstapriv->auth_list_cnt = 0;
72	pstapriv->auth_to = 3; /*  3*2 = 6 sec */
73	pstapriv->assoc_to = 3;
74	/* pstapriv->expire_to = 900;  900*2 = 1800 sec = 30 min,
75	    expire after no any traffic. */
76	/* pstapriv->expire_to = 30;  30*2 = 60 sec = 1 min,
77	    expire after no any traffic. */
78	pstapriv->expire_to = 3; /*  3*2 = 6 sec */
79	pstapriv->max_num_sta = NUM_STA;
80#endif
81	return _SUCCESS;
82}
83
84int _rtw_free_sta_priv23a(struct sta_priv *pstapriv)
85{
86	struct list_head *phead, *plist, *ptmp;
87	struct sta_info *psta;
88	struct recv_reorder_ctrl *preorder_ctrl;
89	int index;
90
91	if (pstapriv) {
92		/*	delete all reordering_ctrl_timer		*/
93		spin_lock_bh(&pstapriv->sta_hash_lock);
94		for (index = 0; index < NUM_STA; index++) {
95			phead = &pstapriv->sta_hash[index];
96
97			list_for_each_safe(plist, ptmp, phead) {
98				int i;
99
100				psta = container_of(plist, struct sta_info,
101						    hash_list);
102				for (i = 0; i < 16 ; i++) {
103					preorder_ctrl = &psta->recvreorder_ctrl[i];
104					del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
105				}
106			}
107		}
108		spin_unlock_bh(&pstapriv->sta_hash_lock);
109		/*===============================*/
110	}
111	return _SUCCESS;
112}
113
114struct sta_info *
115rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp)
116{
117	struct list_head	*phash_list;
118	struct sta_info	*psta;
119	struct recv_reorder_ctrl *preorder_ctrl;
120	s32	index;
121	int i = 0;
122	u16  wRxSeqInitialValue = 0xffff;
123
124	psta = kmalloc(sizeof(struct sta_info), gfp);
125	if (!psta)
126		return NULL;
127
128	spin_lock_bh(&pstapriv->sta_hash_lock);
129
130	_rtw_init_stainfo(psta);
131
132	psta->padapter = pstapriv->padapter;
133
134	ether_addr_copy(psta->hwaddr, hwaddr);
135
136	index = wifi_mac_hash(hwaddr);
137
138	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
139		 ("rtw_alloc_stainfo23a: index  = %x", index));
140	if (index >= NUM_STA) {
141		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
142			 ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
143		psta = NULL;
144		goto exit;
145	}
146	phash_list = &pstapriv->sta_hash[index];
147
148	list_add_tail(&psta->hash_list, phash_list);
149
150	pstapriv->asoc_sta_count++;
151
152/*  For the SMC router, the sequence number of first packet of WPS
153     handshake will be 0. */
154/*  In this case, this packet will be dropped by recv_decache function
155    if we use the 0x00 as the default value for tid_rxseq variable. */
156/*  So, we initialize the tid_rxseq variable as the 0xffff. */
157
158	for (i = 0; i < 16; i++)
159		memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
160			&wRxSeqInitialValue, 2);
161
162	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
163		 ("alloc number_%d stainfo  with hwaddr = %pM\n",
164		 pstapriv->asoc_sta_count, hwaddr));
165
166	init_addba_retry_timer23a(psta);
167
168	/* for A-MPDU Rx reordering buffer control */
169	for (i = 0; i < 16; i++) {
170		preorder_ctrl = &psta->recvreorder_ctrl[i];
171
172		preorder_ctrl->padapter = pstapriv->padapter;
173
174		preorder_ctrl->enable = false;
175
176		preorder_ctrl->indicate_seq = 0xffff;
177		preorder_ctrl->wend_b = 0xffff;
178		/* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
179		preorder_ctrl->wsize_b = 64;/* 64; */
180
181		_rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue);
182
183		rtw_init_recv_timer23a(preorder_ctrl);
184	}
185	/* init for DM */
186	psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
187	psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
188
189	/* init for the sequence number of received management frame */
190	psta->RxMgmtFrameSeqNum = 0xffff;
191exit:
192	spin_unlock_bh(&pstapriv->sta_hash_lock);
193	return psta;
194}
195
196/*  using pstapriv->sta_hash_lock to protect */
197int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
198{
199	struct recv_reorder_ctrl *preorder_ctrl;
200	struct	sta_xmit_priv	*pstaxmitpriv;
201	struct	xmit_priv	*pxmitpriv = &padapter->xmitpriv;
202	struct	sta_priv *pstapriv = &padapter->stapriv;
203	struct hw_xmit *phwxmit;
204	int i;
205
206	if (psta == NULL)
207		goto exit;
208
209	spin_lock_bh(&psta->lock);
210	psta->state &= ~_FW_LINKED;
211	spin_unlock_bh(&psta->lock);
212
213	pstaxmitpriv = &psta->sta_xmitpriv;
214
215	spin_lock_bh(&pxmitpriv->lock);
216
217	rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q);
218	psta->sleepq_len = 0;
219
220	/* vo */
221	rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
222	list_del_init(&pstaxmitpriv->vo_q.tx_pending);
223	phwxmit = pxmitpriv->hwxmits;
224	phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
225	pstaxmitpriv->vo_q.qcnt = 0;
226
227	/* vi */
228	rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
229	list_del_init(&pstaxmitpriv->vi_q.tx_pending);
230	phwxmit = pxmitpriv->hwxmits+1;
231	phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
232	pstaxmitpriv->vi_q.qcnt = 0;
233
234	/* be */
235	rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
236	list_del_init(&pstaxmitpriv->be_q.tx_pending);
237	phwxmit = pxmitpriv->hwxmits+2;
238	phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
239	pstaxmitpriv->be_q.qcnt = 0;
240
241	/* bk */
242	rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
243	list_del_init(&pstaxmitpriv->bk_q.tx_pending);
244	phwxmit = pxmitpriv->hwxmits+3;
245	phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
246	pstaxmitpriv->bk_q.qcnt = 0;
247
248	spin_unlock_bh(&pxmitpriv->lock);
249
250	list_del_init(&psta->hash_list);
251	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
252		("\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
253			pstapriv->asoc_sta_count, psta->hwaddr[0],
254			psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3],
255			psta->hwaddr[4], psta->hwaddr[5]));
256	pstapriv->asoc_sta_count--;
257
258	/*  re-init sta_info; 20061114  will be init in alloc_stainfo */
259	/* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
260	/* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
261
262	del_timer_sync(&psta->addba_retry_timer);
263
264	/* for A-MPDU Rx reordering buffer control,
265	   cancel reordering_ctrl_timer */
266	for (i = 0; i < 16; i++) {
267		struct list_head	*phead, *plist;
268		struct recv_frame *prframe;
269		struct rtw_queue *ppending_recvframe_queue;
270
271		preorder_ctrl = &psta->recvreorder_ctrl[i];
272
273		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
274
275		ppending_recvframe_queue =
276			&preorder_ctrl->pending_recvframe_queue;
277
278		spin_lock_bh(&ppending_recvframe_queue->lock);
279		phead =		get_list_head(ppending_recvframe_queue);
280		plist = phead->next;
281
282		while (!list_empty(phead)) {
283			prframe = container_of(plist, struct recv_frame, list);
284			plist = plist->next;
285			list_del_init(&prframe->list);
286			rtw_free_recvframe23a(prframe);
287		}
288		spin_unlock_bh(&ppending_recvframe_queue->lock);
289	}
290	if (!(psta->state & WIFI_AP_STATE))
291		rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false);
292#ifdef CONFIG_8723AU_AP_MODE
293	spin_lock_bh(&pstapriv->auth_list_lock);
294	if (!list_empty(&psta->auth_list)) {
295		list_del_init(&psta->auth_list);
296		pstapriv->auth_list_cnt--;
297	}
298	spin_unlock_bh(&pstapriv->auth_list_lock);
299
300	psta->expire_to = 0;
301
302	psta->sleepq_ac_len = 0;
303	psta->qos_info = 0;
304
305	psta->max_sp_len = 0;
306	psta->uapsd_bk = 0;
307	psta->uapsd_be = 0;
308	psta->uapsd_vi = 0;
309	psta->uapsd_vo = 0;
310
311	psta->has_legacy_ac = 0;
312
313	pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
314	pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
315
316	if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
317		pstapriv->sta_aid[psta->aid - 1] = NULL;
318		psta->aid = 0;
319	}
320#endif	/*  CONFIG_8723AU_AP_MODE */
321
322	kfree(psta);
323exit:
324	return _SUCCESS;
325}
326
327/*  free all stainfo which in sta_hash[all] */
328void rtw_free_all_stainfo23a(struct rtw_adapter *padapter)
329{
330	struct list_head *plist, *phead, *ptmp;
331	struct sta_info *psta;
332	struct sta_priv *pstapriv = &padapter->stapriv;
333	struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
334	s32 index;
335
336	if (pstapriv->asoc_sta_count == 1)
337		return;
338
339	spin_lock_bh(&pstapriv->sta_hash_lock);
340
341	for (index = 0; index < NUM_STA; index++) {
342		phead = &pstapriv->sta_hash[index];
343
344		list_for_each_safe(plist, ptmp, phead) {
345			psta = container_of(plist, struct sta_info, hash_list);
346
347			if (pbcmc_stainfo != psta)
348				rtw_free_stainfo23a(padapter, psta);
349		}
350	}
351	spin_unlock_bh(&pstapriv->sta_hash_lock);
352}
353
354/* any station allocated can be searched by hash list */
355struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr)
356{
357	struct list_head *plist, *phead;
358	struct sta_info *psta = NULL;
359	u32	index;
360	const u8 *addr;
361
362	if (hwaddr == NULL)
363		return NULL;
364
365	if (is_multicast_ether_addr(hwaddr))
366		addr = bc_addr;
367	else
368		addr = hwaddr;
369
370	index = wifi_mac_hash(addr);
371
372	spin_lock_bh(&pstapriv->sta_hash_lock);
373
374	phead = &pstapriv->sta_hash[index];
375
376	list_for_each(plist, phead) {
377		psta = container_of(plist, struct sta_info, hash_list);
378
379		/*  if found the matched address */
380		if (ether_addr_equal(psta->hwaddr, addr))
381			break;
382
383		psta = NULL;
384	}
385	spin_unlock_bh(&pstapriv->sta_hash_lock);
386	return psta;
387}
388
389int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter)
390{
391	struct	sta_priv *pstapriv = &padapter->stapriv;
392	struct sta_info		*psta;
393	struct tx_servq	*ptxservq;
394	int res = _SUCCESS;
395
396	psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL);
397	if (psta == NULL) {
398		res = _FAIL;
399		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
400			 ("rtw_alloc_stainfo23a fail"));
401		return res;
402	}
403	/*  default broadcast & multicast use macid 1 */
404	psta->mac_id = 1;
405
406	ptxservq = &psta->sta_xmitpriv.be_q;
407	return _SUCCESS;
408}
409
410struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter)
411{
412	struct sta_info		*psta;
413	struct sta_priv		*pstapriv = &padapter->stapriv;
414
415	psta = rtw_get_stainfo23a(pstapriv, bc_addr);
416	return psta;
417}
418
419bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr)
420{
421	bool res = true;
422#ifdef CONFIG_8723AU_AP_MODE
423	struct list_head *plist, *phead;
424	struct rtw_wlan_acl_node *paclnode;
425	bool match = false;
426	struct sta_priv *pstapriv = &padapter->stapriv;
427	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
428	struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
429
430	spin_lock_bh(&pacl_node_q->lock);
431	phead = get_list_head(pacl_node_q);
432
433	list_for_each(plist, phead) {
434		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
435
436		if (ether_addr_equal(paclnode->addr, mac_addr)) {
437			if (paclnode->valid) {
438				match = true;
439				break;
440			}
441		}
442	}
443	spin_unlock_bh(&pacl_node_q->lock);
444
445	if (pacl_list->mode == 1)/* accept unless in deny list */
446		res = (match) ?  false : true;
447	else if (pacl_list->mode == 2)/* deny unless in accept list */
448		res = (match) ?  true : false;
449	else
450		 res = true;
451#endif
452	return res;
453}
454