12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/******************************************************************************
22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * rtl871x_sta_mgt.c
32865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
42865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
52865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Linux device driver for RTL8192SU
62865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
72865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is free software; you can redistribute it and/or modify it
82865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * under the terms of version 2 of the GNU General Public License as
92865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * published by the Free Software Foundation.
102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT
122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * more details.
152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * You should have received a copy of the GNU General Public License along with
172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * this program; if not, write to the Free Software Foundation, Inc.,
182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Modifications for inclusion into the Linux staging tree are
212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2010 Larry Finger. All rights reserved.
222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Contact information:
242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * WLAN FAE <wlanfae@realtek.com>
252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Larry Finger <Larry.Finger@lwfinger.net>
262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *
272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ******************************************************************************/
282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define _RTL871X_STA_MGT_C_
302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h"
322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h"
332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "recv_osdep.h"
342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "xmit_osdep.h"
352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "sta_info.h"
362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void _init_stainfo(struct sta_info *psta)
382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memset((u8 *)psta, 0, sizeof(struct sta_info));
402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	 spin_lock_init(&psta->lock);
41534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&psta->list);
42534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&psta->hash_list);
432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
45534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&psta->asoc_list);
46534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&psta->auth_list);
472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru32 _r8712_init_sta_priv(struct	sta_priv *pstapriv)
502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta;
522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	s32 i;
532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5491d435fe368ab30702d7bcd50f680e7185899295Vitaly Osipov	pstapriv->pallocated_stainfo_buf = kmalloc(sizeof(struct sta_info) *
5591d435fe368ab30702d7bcd50f680e7185899295Vitaly Osipov						   NUM_STA + 4, GFP_ATOMIC);
562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pstapriv->pallocated_stainfo_buf == NULL)
572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		((addr_t)(pstapriv->pallocated_stainfo_buf) & 3);
602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pstapriv->free_sta_queue);
612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_init(&pstapriv->sta_hash_lock);
622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pstapriv->asoc_sta_count = 0;
632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pstapriv->sleep_q);
642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pstapriv->wakeup_q);
652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	psta = (struct sta_info *)(pstapriv->pstainfo_buf);
662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < NUM_STA; i++) {
672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_init_stainfo(psta);
68534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
69e99a428a1daed550142a08f6acb5265a1d108e65James A Shackleford		list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue);
702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta++;
712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
72534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&pstapriv->asoc_list);
73534c4acd1d45942eaae0db5858c82a33fac47468James A Shackleford	INIT_LIST_HEAD(&pstapriv->auth_list);
742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* this function is used to free the memory of lock || sema for all stainfos */
782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void mfree_all_stainfo(struct sta_priv *pstapriv)
792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta = NULL;
832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
85e99a428a1daed550142a08f6acb5265a1d108e65James A Shackleford	phead = &pstapriv->free_sta_queue.queue;
86849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford	plist = phead->next;
872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	while ((end_of_queue_search(phead, plist)) == false) {
882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = LIST_CONTAINOR(plist, struct sta_info, list);
89849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford		plist = plist->next;
902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void mfree_sta_priv_lock(struct	sta_priv *pstapriv)
972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	 mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru32 _r8712_free_sta_priv(struct sta_priv *pstapriv)
1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pstapriv) {
1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		mfree_sta_priv_lock(pstapriv);
1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		kfree(pstapriv->pallocated_stainfo_buf);
1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	uint tmp_aid;
1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	s32	index;
1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *phash_list;
1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info	*psta;
1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_sta_queue;
1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct recv_reorder_ctrl *preorder_ctrl;
1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	int i = 0;
1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u16  wRxSeqInitialValue = 0xffff;
1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long flags;
1212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pfree_sta_queue = &pstapriv->free_sta_queue;
1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pfree_sta_queue->lock), flags);
124df353f61afb917ff66b2e784b0ffb85d0ebb29a4James A Shackleford	if (list_empty(&pfree_sta_queue->queue))
1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = NULL;
1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else {
127849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford		psta = LIST_CONTAINOR(pfree_sta_queue->queue.next,
1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				      struct sta_info, list);
12929197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford		list_del_init(&(psta->list));
1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		tmp_aid = psta->aid;
1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_init_stainfo(psta);
1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		index = wifi_mac_hash(hwaddr);
1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (index >= NUM_STA) {
1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			psta = NULL;
1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			goto exit;
1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phash_list = &(pstapriv->sta_hash[index]);
139fdfbf7890dcac98d698ce889720e90c1f26cf30fJames A Shackleford		list_add_tail(&psta->hash_list, phash_list);
14077e73e8c90aded3215ecb4d05b9c91ec94349b61Thomas Cort		pstapriv->asoc_sta_count++;
1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* For the SMC router, the sequence number of first packet of WPS handshake
1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * will be 0. In this case, this packet will be dropped by recv_decache function
1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * if we use the 0x00 as the default value for tid_rxseq variable. So, we
1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * initialize the tid_rxseq variable as the 0xffff.
1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */
1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		for (i = 0; i < 16; i++)
1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				&wRxSeqInitialValue, 2);
1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* for A-MPDU Rx reordering buffer control */
15177e73e8c90aded3215ecb4d05b9c91ec94349b61Thomas Cort		for (i = 0; i < 16; i++) {
1522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			preorder_ctrl = &psta->recvreorder_ctrl[i];
1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			preorder_ctrl->padapter = pstapriv->padapter;
1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			preorder_ctrl->indicate_seq = 0xffff;
1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			preorder_ctrl->wend_b = 0xffff;
1562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			preorder_ctrl->wsize_b = 64;
1572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			_init_queue(&preorder_ctrl->pending_recvframe_queue);
1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_init_recv_timer(preorder_ctrl);
1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerexit:
1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pfree_sta_queue->lock), flags);
1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return psta;
1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* using pstapriv->sta_hash_lock to protect */
1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
1692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	int i;
1702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL0;
1712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_sta_queue;
1722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct recv_reorder_ctrl *preorder_ctrl;
1732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	sta_xmit_priv *pstaxmitpriv;
1742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
1752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	sta_priv *pstapriv = &padapter->stapriv;
1762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (psta == NULL)
1782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
1792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pfree_sta_queue = &pstapriv->free_sta_queue;
1802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pstaxmitpriv = &psta->sta_xmitpriv;
1812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0);
1822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
18329197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
1842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0);
1852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0);
1862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
18729197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
1882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0);
1892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0);
1902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
19129197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
1922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0);
1932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0);
1942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
19529197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
1962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0);
19729197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford	list_del_init(&psta->hash_list);
1982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pstapriv->asoc_sta_count--;
1992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* re-init sta_info; 20061114 */
2002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
2012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
2022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* for A-MPDU Rx reordering buffer control,
2032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	 * cancel reordering_ctrl_timer */
2042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < 16; i++) {
2052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		preorder_ctrl = &psta->recvreorder_ctrl[i];
2062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
2072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock(&(pfree_sta_queue->lock));
2092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* insert into free_sta_queue; 20061114 */
210e99a428a1daed550142a08f6acb5265a1d108e65James A Shackleford	list_add_tail(&psta->list, &pfree_sta_queue->queue);
2112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock(&(pfree_sta_queue->lock));
2122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* free all stainfo which in sta_hash[all] */
2152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_free_all_stainfo(struct _adapter *padapter)
2162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
2182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
2192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	s32 index;
2202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta = NULL;
2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	sta_priv *pstapriv = &padapter->stapriv;
2222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *pbcmc_stainfo = r8712_get_bcmc_stainfo(padapter);
2232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pstapriv->asoc_sta_count == 1)
2252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
2262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
2272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (index = 0; index < NUM_STA; index++) {
2282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phead = &(pstapriv->sta_hash[index]);
229849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford		plist = phead->next;
2302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		while ((end_of_queue_search(phead, plist)) == false) {
2312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			psta = LIST_CONTAINOR(plist,
2322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					      struct sta_info, hash_list);
233849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford			plist = plist->next;
2342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (pbcmc_stainfo != psta)
2352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				r8712_free_stainfo(padapter , psta);
2362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
2372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
2392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/* any station allocated can be searched by hash list */
2422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
2432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long	 irqL;
2452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
2462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta = NULL;
2472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u32	index;
2482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (hwaddr == NULL)
2502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return NULL;
2512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	index = wifi_mac_hash(hwaddr);
2522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
2532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	phead = &(pstapriv->sta_hash[index]);
254849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford	plist = phead->next;
2552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	while ((end_of_queue_search(phead, plist)) == false) {
2562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
2572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
2582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			/* if found the matched address */
2592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			break;
2602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
2612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = NULL;
262849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford		plist = plist->next;
2632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
2652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return psta;
2662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_init_bcmc_stainfo(struct _adapter *padapter)
2692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info	*psta;
2712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct tx_servq	*ptxservq;
2722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	sta_priv *pstapriv = &padapter->stapriv;
2742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	psta = r8712_alloc_stainfo(pstapriv, bcast_addr);
2762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (psta == NULL)
2772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
2782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	ptxservq = &(psta->sta_xmitpriv.be_q);
2792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter)
2822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta;
2842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
2852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	psta = r8712_get_stainfo(pstapriv, bc_addr);
2882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return psta;
2892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr)
2932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return true;
2952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
296