• 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 <linux/vmalloc.h>
24 
_rtw_init_stainfo(struct sta_info * psta)25 static void _rtw_init_stainfo(struct sta_info *psta)
26 {
27 	memset((u8 *)psta, 0, sizeof(struct sta_info));
28 
29 	 spin_lock_init(&psta->lock);
30 	INIT_LIST_HEAD(&psta->list);
31 	INIT_LIST_HEAD(&psta->hash_list);
32 	_rtw_init_queue(&psta->sleep_q);
33 	psta->sleepq_len = 0;
34 
35 	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
36 	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
37 
38 #ifdef CONFIG_88EU_AP_MODE
39 
40 	INIT_LIST_HEAD(&psta->asoc_list);
41 
42 	INIT_LIST_HEAD(&psta->auth_list);
43 
44 	psta->expire_to = 0;
45 
46 	psta->flags = 0;
47 
48 	psta->capability = 0;
49 
50 	psta->bpairwise_key_installed = false;
51 
52 	psta->nonerp_set = 0;
53 	psta->no_short_slot_time_set = 0;
54 	psta->no_short_preamble_set = 0;
55 	psta->no_ht_gf_set = 0;
56 	psta->no_ht_set = 0;
57 	psta->ht_20mhz_set = 0;
58 
59 	psta->under_exist_checking = 0;
60 
61 	psta->keep_alive_trycnt = 0;
62 
63 #endif	/*  CONFIG_88EU_AP_MODE */
64 
65 }
66 
_rtw_init_sta_priv(struct sta_priv * pstapriv)67 u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
68 {
69 	struct sta_info *psta;
70 	s32 i;
71 
72 
73 	pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
74 
75 	if (!pstapriv->pallocated_stainfo_buf)
76 		return _FAIL;
77 
78 	pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
79 		((size_t)(pstapriv->pallocated_stainfo_buf) & 3);
80 
81 	_rtw_init_queue(&pstapriv->free_sta_queue);
82 
83 	spin_lock_init(&pstapriv->sta_hash_lock);
84 
85 	pstapriv->asoc_sta_count = 0;
86 	_rtw_init_queue(&pstapriv->sleep_q);
87 	_rtw_init_queue(&pstapriv->wakeup_q);
88 
89 	psta = (struct sta_info *)(pstapriv->pstainfo_buf);
90 
91 	for (i = 0; i < NUM_STA; i++) {
92 		_rtw_init_stainfo(psta);
93 
94 		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
95 
96 		list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
97 
98 		psta++;
99 	}
100 
101 #ifdef CONFIG_88EU_AP_MODE
102 
103 	pstapriv->sta_dz_bitmap = 0;
104 	pstapriv->tim_bitmap = 0;
105 
106 	INIT_LIST_HEAD(&pstapriv->asoc_list);
107 	INIT_LIST_HEAD(&pstapriv->auth_list);
108 	spin_lock_init(&pstapriv->asoc_list_lock);
109 	spin_lock_init(&pstapriv->auth_list_lock);
110 	pstapriv->asoc_list_cnt = 0;
111 	pstapriv->auth_list_cnt = 0;
112 
113 	pstapriv->auth_to = 3; /*  3*2 = 6 sec */
114 	pstapriv->assoc_to = 3;
115 	pstapriv->expire_to = 3; /*  3*2 = 6 sec */
116 	pstapriv->max_num_sta = NUM_STA;
117 #endif
118 
119 
120 	return _SUCCESS;
121 }
122 
rtw_stainfo_offset(struct sta_priv * stapriv,struct sta_info * sta)123 inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
124 {
125 	int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
126 
127 	if (!stainfo_offset_valid(offset))
128 		DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
129 
130 	return offset;
131 }
132 
rtw_get_stainfo_by_offset(struct sta_priv * stapriv,int offset)133 inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
134 {
135 	if (!stainfo_offset_valid(offset))
136 		DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
137 
138 	return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
139 }
140 
_rtw_free_sta_priv(struct sta_priv * pstapriv)141 u32	_rtw_free_sta_priv(struct	sta_priv *pstapriv)
142 {
143 	struct list_head *phead, *plist;
144 	struct sta_info *psta = NULL;
145 	struct recv_reorder_ctrl *preorder_ctrl;
146 	int	index;
147 
148 	if (pstapriv) {
149 		/*	delete all reordering_ctrl_timer		*/
150 		spin_lock_bh(&pstapriv->sta_hash_lock);
151 		for (index = 0; index < NUM_STA; index++) {
152 			phead = &(pstapriv->sta_hash[index]);
153 			plist = phead->next;
154 
155 			while (phead != plist) {
156 				int i;
157 				psta = container_of(plist, struct sta_info,
158 						    hash_list);
159 				plist = plist->next;
160 
161 				for (i = 0; i < 16; i++) {
162 					preorder_ctrl = &psta->recvreorder_ctrl[i];
163 					del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
164 				}
165 			}
166 		}
167 		spin_unlock_bh(&pstapriv->sta_hash_lock);
168 		/*===============================*/
169 
170 		vfree(pstapriv->pallocated_stainfo_buf);
171 	}
172 
173 	return _SUCCESS;
174 }
175 
rtw_alloc_stainfo(struct sta_priv * pstapriv,u8 * hwaddr)176 struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
177 {
178 	s32 index;
179 	struct list_head *phash_list;
180 	struct sta_info	*psta;
181 	struct __queue *pfree_sta_queue;
182 	struct recv_reorder_ctrl *preorder_ctrl;
183 	int i = 0;
184 	u16  wRxSeqInitialValue = 0xffff;
185 
186 	pfree_sta_queue = &pstapriv->free_sta_queue;
187 
188 	spin_lock_bh(&pfree_sta_queue->lock);
189 	psta = list_first_entry_or_null(&pfree_sta_queue->queue,
190 					struct sta_info, list);
191 	if (!psta) {
192 		spin_unlock_bh(&pfree_sta_queue->lock);
193 	} else {
194 		list_del_init(&psta->list);
195 		spin_unlock_bh(&pfree_sta_queue->lock);
196 		_rtw_init_stainfo(psta);
197 		memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
198 		index = wifi_mac_hash(hwaddr);
199 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index=%x", index));
200 		if (index >= NUM_STA) {
201 			RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
202 			psta = NULL;
203 			goto exit;
204 		}
205 		phash_list = &pstapriv->sta_hash[index];
206 
207 		spin_lock_bh(&pstapriv->sta_hash_lock);
208 		list_add_tail(&psta->hash_list, phash_list);
209 		pstapriv->asoc_sta_count++;
210 		spin_unlock_bh(&pstapriv->sta_hash_lock);
211 
212 /*  Commented by Albert 2009/08/13 */
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. */
216 
217 		for (i = 0; i < 16; i++)
218 			memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
219 
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));
223 
224 		init_addba_retry_timer(pstapriv->padapter, psta);
225 
226 		/* for A-MPDU Rx reordering buffer control */
227 		for (i = 0; i < 16; i++) {
228 			preorder_ctrl = &psta->recvreorder_ctrl[i];
229 
230 			preorder_ctrl->padapter = pstapriv->padapter;
231 
232 			preorder_ctrl->enable = false;
233 
234 			preorder_ctrl->indicate_seq = 0xffff;
235 			preorder_ctrl->wend_b = 0xffff;
236 			preorder_ctrl->wsize_b = 64;/* 64; */
237 
238 			_rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
239 
240 			rtw_init_recv_timer(preorder_ctrl);
241 		}
242 
243 		/* init for DM */
244 		psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
245 		psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
246 
247 		/* init for the sequence number of received management frame */
248 		psta->RxMgmtFrameSeqNum = 0xffff;
249 	}
250 
251 exit:
252 	return psta;
253 }
254 
255 /*  using pstapriv->sta_hash_lock to protect */
rtw_free_stainfo(struct adapter * padapter,struct sta_info * psta)256 u32	rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
257 {
258 	int i;
259 	struct __queue *pfree_sta_queue;
260 	struct recv_reorder_ctrl *preorder_ctrl;
261 	struct	sta_xmit_priv	*pstaxmitpriv;
262 	struct	xmit_priv	*pxmitpriv = &padapter->xmitpriv;
263 	struct	sta_priv *pstapriv = &padapter->stapriv;
264 
265 
266 	if (!psta)
267 		goto exit;
268 
269 	pfree_sta_queue = &pstapriv->free_sta_queue;
270 
271 	pstaxmitpriv = &psta->sta_xmitpriv;
272 
273 	spin_lock_bh(&pxmitpriv->lock);
274 
275 	rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
276 	psta->sleepq_len = 0;
277 
278 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
279 
280 	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
281 
282 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
283 
284 	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
285 
286 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
287 
288 	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
289 
290 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
291 
292 	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
293 
294 	spin_unlock_bh(&pxmitpriv->lock);
295 
296 	list_del_init(&psta->hash_list);
297 	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
298 		 ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
299 		 pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1],
300 		 psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4],
301 		 psta->hwaddr[5]));
302 	pstapriv->asoc_sta_count--;
303 
304 	/*  re-init sta_info; 20061114 */
305 	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
306 	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
307 
308 	del_timer_sync(&psta->addba_retry_timer);
309 
310 	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
311 	for (i = 0; i < 16; i++) {
312 		struct list_head *phead, *plist;
313 		struct recv_frame *prhdr;
314 		struct recv_frame *prframe;
315 		struct __queue *ppending_recvframe_queue;
316 		struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
317 
318 		preorder_ctrl = &psta->recvreorder_ctrl[i];
319 
320 		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
321 
322 		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
323 
324 		spin_lock_bh(&ppending_recvframe_queue->lock);
325 
326 		phead =		get_list_head(ppending_recvframe_queue);
327 		plist = phead->next;
328 
329 		while (!list_empty(phead)) {
330 			prhdr = container_of(plist, struct recv_frame, list);
331 			prframe = (struct recv_frame *)prhdr;
332 
333 			plist = plist->next;
334 
335 			list_del_init(&(prframe->list));
336 
337 			rtw_free_recvframe(prframe, pfree_recv_queue);
338 		}
339 
340 		spin_unlock_bh(&ppending_recvframe_queue->lock);
341 	}
342 
343 	if (!(psta->state & WIFI_AP_STATE))
344 		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
345 
346 #ifdef CONFIG_88EU_AP_MODE
347 
348 	spin_lock_bh(&pstapriv->auth_list_lock);
349 	if (!list_empty(&psta->auth_list)) {
350 		list_del_init(&psta->auth_list);
351 		pstapriv->auth_list_cnt--;
352 	}
353 	spin_unlock_bh(&pstapriv->auth_list_lock);
354 
355 	psta->expire_to = 0;
356 
357 	psta->sleepq_ac_len = 0;
358 	psta->qos_info = 0;
359 
360 	psta->max_sp_len = 0;
361 	psta->uapsd_bk = 0;
362 	psta->uapsd_be = 0;
363 	psta->uapsd_vi = 0;
364 	psta->uapsd_vo = 0;
365 	psta->has_legacy_ac = 0;
366 
367 	pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
368 	pstapriv->tim_bitmap &= ~BIT(psta->aid);
369 
370 	if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
371 		pstapriv->sta_aid[psta->aid - 1] = NULL;
372 		psta->aid = 0;
373 	}
374 
375 	psta->under_exist_checking = 0;
376 
377 #endif	/*  CONFIG_88EU_AP_MODE */
378 
379 	spin_lock_bh(&(pfree_sta_queue->lock));
380 	list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
381 	spin_unlock_bh(&pfree_sta_queue->lock);
382 
383 exit:
384 
385 
386 	return _SUCCESS;
387 }
388 
389 /*  free all stainfo which in sta_hash[all] */
rtw_free_all_stainfo(struct adapter * padapter)390 void rtw_free_all_stainfo(struct adapter *padapter)
391 {
392 	struct list_head *plist, *phead;
393 	s32	index;
394 	struct sta_info *psta = NULL;
395 	struct	sta_priv *pstapriv = &padapter->stapriv;
396 	struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
397 
398 
399 	if (pstapriv->asoc_sta_count == 1)
400 		return;
401 
402 	spin_lock_bh(&pstapriv->sta_hash_lock);
403 
404 	for (index = 0; index < NUM_STA; index++) {
405 		phead = &(pstapriv->sta_hash[index]);
406 		plist = phead->next;
407 
408 		while (phead != plist) {
409 			psta = container_of(plist, struct sta_info, hash_list);
410 
411 			plist = plist->next;
412 
413 			if (pbcmc_stainfo != psta)
414 				rtw_free_stainfo(padapter, psta);
415 		}
416 	}
417 	spin_unlock_bh(&pstapriv->sta_hash_lock);
418 }
419 
420 /* any station allocated can be searched by hash list */
rtw_get_stainfo(struct sta_priv * pstapriv,u8 * hwaddr)421 struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
422 {
423 	struct list_head *plist, *phead;
424 	struct sta_info *psta = NULL;
425 	u32	index;
426 	u8 *addr;
427 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
428 
429 
430 	if (!hwaddr)
431 		return NULL;
432 
433 	if (IS_MCAST(hwaddr))
434 		addr = bc_addr;
435 	else
436 		addr = hwaddr;
437 
438 	index = wifi_mac_hash(addr);
439 
440 	spin_lock_bh(&pstapriv->sta_hash_lock);
441 
442 	phead = &(pstapriv->sta_hash[index]);
443 	plist = phead->next;
444 
445 	while (phead != plist) {
446 		psta = container_of(plist, struct sta_info, hash_list);
447 
448 		if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
449 			/*  if found the matched address */
450 			break;
451 		}
452 		psta = NULL;
453 		plist = plist->next;
454 	}
455 
456 	spin_unlock_bh(&pstapriv->sta_hash_lock);
457 	return psta;
458 }
459 
rtw_init_bcmc_stainfo(struct adapter * padapter)460 u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
461 {
462 	struct sta_info		*psta;
463 	u32 res = _SUCCESS;
464 	unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
465 	struct	sta_priv *pstapriv = &padapter->stapriv;
466 
467 
468 	psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
469 
470 	if (!psta) {
471 		res = _FAIL;
472 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
473 		goto exit;
474 	}
475 
476 	/*  default broadcast & multicast use macid 1 */
477 	psta->mac_id = 1;
478 
479 exit:
480 	return res;
481 }
482 
rtw_get_bcmc_stainfo(struct adapter * padapter)483 struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
484 {
485 	struct sta_priv		*pstapriv = &padapter->stapriv;
486 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
487 	 return rtw_get_stainfo(pstapriv, bc_addr);
488 }
489 
rtw_access_ctrl(struct adapter * padapter,u8 * mac_addr)490 u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
491 {
492 	u8 res = true;
493 #ifdef CONFIG_88EU_AP_MODE
494 	struct list_head *plist, *phead;
495 	struct rtw_wlan_acl_node *paclnode;
496 	u8 match = false;
497 	struct sta_priv *pstapriv = &padapter->stapriv;
498 	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
499 	struct __queue *pacl_node_q = &pacl_list->acl_node_q;
500 
501 	spin_lock_bh(&(pacl_node_q->lock));
502 	phead = get_list_head(pacl_node_q);
503 	plist = phead->next;
504 	while (phead != plist) {
505 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
506 		plist = plist->next;
507 
508 		if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
509 			if (paclnode->valid) {
510 				match = true;
511 				break;
512 			}
513 		}
514 	}
515 	spin_unlock_bh(&pacl_node_q->lock);
516 
517 	if (pacl_list->mode == 1)/* accept unless in deny list */
518 		res = (match) ? false : true;
519 	else if (pacl_list->mode == 2)/* deny unless in accept list */
520 		res = (match) ? true : false;
521 	else
522 		 res = true;
523 
524 #endif
525 
526 	return res;
527 }
528