• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
26 
_rtw_init_stainfo(struct sta_info * psta)27 static 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 
_rtw_init_sta_priv23a(struct sta_priv * pstapriv)54 int _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 
_rtw_free_sta_priv23a(struct sta_priv * pstapriv)84 int _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 
114 struct sta_info *
rtw_alloc_stainfo23a(struct sta_priv * pstapriv,const u8 * hwaddr,gfp_t gfp)115 rtw_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;
191 exit:
192 	spin_unlock_bh(&pstapriv->sta_hash_lock);
193 	return psta;
194 }
195 
196 /*  using pstapriv->sta_hash_lock to protect */
rtw_free_stainfo23a(struct rtw_adapter * padapter,struct sta_info * psta)197 int 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);
323 exit:
324 	return _SUCCESS;
325 }
326 
327 /*  free all stainfo which in sta_hash[all] */
rtw_free_all_stainfo23a(struct rtw_adapter * padapter)328 void 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 */
rtw_get_stainfo23a(struct sta_priv * pstapriv,const u8 * hwaddr)355 struct 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 
rtw_init_bcmc_stainfo23a(struct rtw_adapter * padapter)389 int 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 
rtw_get_bcmc_stainfo23a(struct rtw_adapter * padapter)410 struct 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 
rtw_access_ctrl23a(struct rtw_adapter * padapter,u8 * mac_addr)419 bool 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