12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/******************************************************************************
22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * rtl871x_xmit.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_XMIT_C_
302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h"
322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h"
332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "rtl871x_byteorder.h"
342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "wifi.h"
352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_intf.h"
362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "usb_ops.h"
372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic const u8 RFC1042_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0x00};
412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void init_hwxmits(struct hw_xmit *phwxmit, sint entry);
422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void alloc_hwxmits(struct _adapter *padapter);
432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void free_hwxmits(struct _adapter *padapter);
442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void _init_txservq(struct tx_servq *ptxservq)
462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_listhead(&ptxservq->tx_pending);
482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&ptxservq->sta_pending);
492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	ptxservq->qcnt = 0;
502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memset((unsigned char *)psta_xmitpriv, 0,
552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		 sizeof(struct sta_xmit_priv));
562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_init(&psta_xmitpriv->lock);
572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_txservq(&psta_xmitpriv->be_q);
582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_txservq(&psta_xmitpriv->bk_q);
592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_txservq(&psta_xmitpriv->vi_q);
602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_txservq(&psta_xmitpriv->vo_q);
612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_listhead(&psta_xmitpriv->legacy_dz);
622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_listhead(&psta_xmitpriv->apsd);
632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingersint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			   struct _adapter *padapter)
672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint i;
692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_buf *pxmitbuf;
702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_frame *pxframe;
712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_init(&pxmitpriv->lock);
742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*
752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	Please insert all the queue initializaiton using _init_queue below
762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	*/
772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->adapter = padapter;
782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->be_pending);
792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->bk_pending);
802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->vi_pending);
812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->vo_pending);
822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->bm_pending);
832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->legacy_dz_queue);
842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->apsd_queue);
852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->free_xmit_queue);
862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*
872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	and initialize free_xmit_frame below.
892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	Please also apply  free_txobj to link_up all the xmit_frames...
902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	*/
912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->pallocated_frame_buf = _malloc(NR_XMITFRAME *
922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					  sizeof(struct xmit_frame) + 4);
932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitpriv->pallocated_frame_buf == NULL) {
942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->pxmit_frame_buf = NULL;
952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 -
982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			((addr_t) (pxmitpriv->pallocated_frame_buf) & 3);
992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < NR_XMITFRAME; i++) {
1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_init_listhead(&(pxframe->list));
1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->padapter = padapter;
1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->frame_tag = DATA_FRAMETAG;
1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->pkt = NULL;
1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->buf_addr = NULL;
1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->pxmitbuf = NULL;
1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		list_insert_tail(&(pxframe->list),
1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 &(pxmitpriv->free_xmit_queue.queue));
1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe++;
1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*
1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		init xmit hw_txqueue
1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	*/
1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_hw_txqueue(&pxmitpriv->be_txqueue, BE_QUEUE_INX);
1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_hw_txqueue(&pxmitpriv->bk_txqueue, BK_QUEUE_INX);
1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_hw_txqueue(&pxmitpriv->vi_txqueue, VI_QUEUE_INX);
1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_hw_txqueue(&pxmitpriv->vo_txqueue, VO_QUEUE_INX);
1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX);
1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
1212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->txirp_cnt = 1;
1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*per AC pending irp*/
1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->beq_cnt = 0;
1242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->bkq_cnt = 0;
1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->viq_cnt = 0;
1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->voq_cnt = 0;
1272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*init xmit_buf*/
1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->free_xmitbuf_queue);
1292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_init_queue(&pxmitpriv->pending_xmitbuf_queue);
1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->pallocated_xmitbuf = _malloc(NR_XMITBUFF *
1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					sizeof(struct xmit_buf) + 4);
1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitpriv->pallocated_xmitbuf  == NULL)
1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			      ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < NR_XMITBUFF; i++) {
1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_init_listhead(&pxmitbuf->list);
1392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf->pallocated_buf = _malloc(MAX_XMITBUF_SZ +
1402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					   XMITBUF_ALIGN_SZ);
1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pxmitbuf->pallocated_buf == NULL)
1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			return _FAIL;
1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 ((addr_t) (pxmitbuf->pallocated_buf) &
1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 (XMITBUF_ALIGN_SZ - 1));
1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_resource_alloc(padapter, pxmitbuf);
1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		list_insert_tail(&pxmitbuf->list,
1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 &(pxmitpriv->free_xmitbuf_queue.queue));
1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf++;
1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
152f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar	_init_workitem(&padapter->wkFilterRxFF0, r8712_SetFilter, padapter);
1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	alloc_hwxmits(padapter);
1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	tasklet_init(&pxmitpriv->xmit_tasklet,
156f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar		(void(*)(unsigned long))r8712_xmit_bh,
157f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar		(unsigned long)padapter);
1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid _free_xmit_priv(struct xmit_priv *pxmitpriv)
1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	int i;
1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct _adapter *padapter = pxmitpriv->adapter;
1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_frame *pxmitframe = (struct xmit_frame *)
1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					pxmitpriv->pxmit_frame_buf;
1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitpriv->pxmit_frame_buf == NULL)
1702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
1712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < NR_XMITFRAME; i++) {
1722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_complete(padapter, pxmitframe);
1732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitframe++;
1742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < NR_XMITBUFF; i++) {
1762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_resource_free(padapter, pxmitbuf);
1772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		kfree(pxmitbuf->pallocated_buf);
1782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf++;
1792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
1802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	kfree(pxmitpriv->pallocated_frame_buf);
1812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	kfree(pxmitpriv->pallocated_xmitbuf);
1822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	free_hwxmits(padapter);
1832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingersint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
1862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		   struct pkt_attrib *pattrib)
1872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
1882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	uint i;
1892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_file pktfile;
1902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info *psta = NULL;
1912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct ethhdr etherhdr;
1922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct tx_cmd txdesc;
1942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint bmcast;
1962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_priv		*pstapriv = &padapter->stapriv;
1972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct security_priv	*psecuritypriv = &padapter->securitypriv;
1982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
1992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
2002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_open_pktfile(pkt, &pktfile);
2022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	i = _r8712_pktfile_read(&pktfile, (unsigned char *)&etherhdr, ETH_HLEN);
2042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->ether_type = ntohs(etherhdr.h_proto);
2062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
2082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8 bool;
2092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*If driver xmit ARP packet, driver can set ps mode to initial
2102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	 * setting. It stands for getting DHCP or fix IP.*/
2112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->ether_type == 0x0806) {
2122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (padapter->pwrctrlpriv.pwr_mode !=
2132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		    padapter->registrypriv.power_mgnt) {
2142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			_cancel_timer(&(pmlmepriv->dhcp_timer), &bool);
2152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_set_ps_mode(padapter, padapter->registrypriv.
2162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				power_mgnt, padapter->registrypriv.smart_ps);
2172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
2182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
2202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
2222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->pctrl = 0;
2232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
2242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
2252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
2262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
2272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
2282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
2292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
2302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
2322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
2332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
2342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/*firstly, filter packet not belongs to mp*/
2352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pattrib->ether_type != 0x8712)
2362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			return _FAIL;
2372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* for mp storing the txcmd per packet,
2382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		 * according to the info of txcmd to update pattrib */
2392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/*get MP_TXDESC_SIZE bytes txcmd per packet*/
2402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		i = _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE);
2412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
2422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
2432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->pctrl = 1;
2442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* r8712_xmitframe_coalesce() overwrite this!*/
2462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->pktlen = pktfile.pkt_len;
2472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (ETH_P_IP == pattrib->ether_type) {
2482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* The following is for DHCP and ARP packet, we use cck1M to
2492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		 * tx these packets and let LPS awake some time
2502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		 * to prevent DHCP protocol fail */
2512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		u8 tmp[24];
2522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_r8712_pktfile_read(&pktfile, &tmp[0], 24);
2532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->dhcp_pkt = 0;
2542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
2552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (ETH_P_IP == pattrib->ether_type) {/* IP header*/
2562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (((tmp[21] == 68) && (tmp[23] == 67)) ||
2572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					((tmp[21] == 67) && (tmp[23] == 68))) {
2582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					/* 68 : UDP BOOTP client
2592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 * 67 : UDP BOOTP server
2602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 * Use low rate to send DHCP packet.*/
2612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					pattrib->dhcp_pkt = 1;
2622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				}
2632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
2642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
2652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	bmcast = IS_MCAST(pattrib->ra);
2672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* get sta_info*/
2682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (bmcast) {
2692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = r8712_get_bcmc_stainfo(padapter);
2702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->mac_id = 4;
2712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else {
2722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
2732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			psta = r8712_get_stainfo(pstapriv,
2742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						 get_bssid(pmlmepriv));
2752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pattrib->mac_id = 5;
2762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		} else {
2772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			psta = r8712_get_stainfo(pstapriv, pattrib->ra);
2782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (psta == NULL)  /* drop the pkt */
2792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				return _FAIL;
2802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
2812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				pattrib->mac_id = 5;
2822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			else
2832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				pattrib->mac_id = psta->mac_id;
2842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
2852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (psta) {
2882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->psta = psta;
2892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else {
2902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* if we cannot get psta => drrp the pkt */
2912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
2922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
2932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->ack_policy = 0;
2952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* get ether_hdr_len */
2962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->pkt_hdrlen = ETH_HLEN;
2972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
2982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pqospriv->qos_option)
2992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_set_qos(&pktfile, pattrib);
3002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else {
3012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->hdrlen = WLAN_HDR_A3_LEN;
3022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->subtype = WIFI_DATA_TYPE;
3032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->priority = 0;
3042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
3052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (psta->ieee8021x_blocked == true) {
3062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->encrypt = 0;
3072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if ((pattrib->ether_type != 0x888e) &&
3082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		    (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false))
3092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			return _FAIL;
3102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else
3112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
3122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	switch (pattrib->encrypt) {
3132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case _WEP40_:
3142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case _WEP104_:
3152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->iv_len = 4;
3162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->icv_len = 4;
3172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
3182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case _TKIP_:
3192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->iv_len = 8;
3202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->icv_len = 4;
3212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (padapter->securitypriv.busetkipkey == _FAIL)
3222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			return _FAIL;
3232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
3242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case _AES_:
3252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->iv_len = 8;
3262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->icv_len = 8;
3272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
3282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	default:
3292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->iv_len = 0;
3302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->icv_len = 0;
3312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
3322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
3332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
3342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->encrypt &&
3352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	    ((padapter->securitypriv.sw_encrypt == true) ||
3362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	     (psecuritypriv->hw_decrypted == false)))
3372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->bswenc = true;
3382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else
3392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->bswenc = false;
3402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
3412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	 * some settings above.*/
3422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
3432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pattrib->priority = (txdesc.txdw1 >> QSEL_SHT) & 0x1f;
3442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
3452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
3462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
3472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic sint xmitframe_addmic(struct _adapter *padapter,
3482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			     struct xmit_frame *pxmitframe)
3492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
3502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u32	curfragnum, length, datalen;
3512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8	*pframe, *payload, mic[8];
3522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	mic_data micdata;
3532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	sta_info *stainfo;
3542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	qos_priv *pqospriv = &(padapter->mlmepriv.qospriv);
3552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	pkt_attrib  *pattrib = &pxmitframe->attrib;
3562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	security_priv *psecuritypriv = &padapter->securitypriv;
3572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
3582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
3592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint bmcst = IS_MCAST(pattrib->ra);
3602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
3612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->psta)
3622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		stainfo = pattrib->psta;
3632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else
3642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		stainfo = r8712_get_stainfo(&padapter->stapriv,
3652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					    &pattrib->ra[0]);
3662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->encrypt == _TKIP_) {
3672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/*encode mic code*/
3682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (stainfo != NULL) {
3692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					   0x0, 0x0};
3722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			datalen = pattrib->pktlen - pattrib->hdrlen;
373859171ca92f2865453b4b2e17bf679c67044a833Joe Perches			pframe = pxmitframe->buf_addr + TXDESC_OFFSET;
3742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (bmcst) {
3752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (!memcmp(psecuritypriv->XGrptxmickey
3762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				   [psecuritypriv->XGrpKeyid].skey,
3772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				   null_key, 16))
3782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					return _FAIL;
3792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				/*start to calculate the mic code*/
3802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				r8712_secmicsetkey(&micdata,
3812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 psecuritypriv->
3822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 XGrptxmickey[psecuritypriv->
3832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					XGrpKeyid].skey);
3842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			} else {
3852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (!memcmp(&stainfo->tkiptxmickey.skey[0],
3862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					    null_key, 16))
3872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					return _FAIL;
3882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				/* start to calculate the mic code */
3892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				r8712_secmicsetkey(&micdata,
3902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					     &stainfo->tkiptxmickey.skey[0]);
3912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
3922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (pframe[1] & 1) {   /* ToDS==1 */
3932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				r8712_secmicappend(&micdata,
3942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						   &pframe[16], 6); /*DA*/
3952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (pframe[1]&2)  /* From Ds==1 */
3962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata,
3972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   &pframe[24], 6);
3982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				else
3992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata,
4002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   &pframe[10], 6);
4012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			} else {	/* ToDS==0 */
4022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				r8712_secmicappend(&micdata,
4032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						   &pframe[4], 6); /* DA */
4042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (pframe[1]&2)  /* From Ds==1 */
4052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata,
4062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   &pframe[16], 6);
4072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				else
4082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata,
4092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   &pframe[10], 6);
4102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
4112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (pqospriv->qos_option == 1)
4122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					priority[0] = (u8)pxmitframe->
4132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						      attrib.priority;
4142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_secmicappend(&micdata, &priority[0], 4);
4152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			payload = pframe;
4162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			for (curfragnum = 0; curfragnum < pattrib->nr_frags;
4172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			     curfragnum++) {
4182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				payload = (u8 *)RND4((addr_t)(payload));
4192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				payload = payload+pattrib->
4202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					  hdrlen+pattrib->iv_len;
4212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if ((curfragnum + 1) == pattrib->nr_frags) {
4222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					length = pattrib->last_txcmdsz -
4232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  pattrib->hdrlen -
4242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  pattrib->iv_len -
4252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  ((psecuritypriv->sw_encrypt)
4262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  ? pattrib->icv_len : 0);
4272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata, payload,
4282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   length);
4292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					payload = payload+length;
4302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				} else{
4312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					length = pxmitpriv->frag_len -
4322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					    pattrib->hdrlen-pattrib->iv_len -
4332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					    ((psecuritypriv->sw_encrypt) ?
4342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					    pattrib->icv_len : 0);
4352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					r8712_secmicappend(&micdata, payload,
4362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							   length);
4372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					payload = payload + length +
4382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  pattrib->icv_len;
4392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				}
4402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
4412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_secgetmic(&micdata, &(mic[0]));
4422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			/* add mic code  and add the mic code length in
4432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			 * last_txcmdsz */
4442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(payload, &(mic[0]), 8);
4452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pattrib->last_txcmdsz += 8;
4462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			payload = payload-pattrib->last_txcmdsz + 8;
4472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
4482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
4492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
4502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
4512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
4522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic sint xmitframe_swencrypt(struct _adapter *padapter,
4532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				struct xmit_frame *pxmitframe)
4542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
4552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
4562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
4572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->bswenc) {
4582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		switch (pattrib->encrypt) {
4592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		case _WEP40_:
4602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		case _WEP104_:
4612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_wep_encrypt(padapter, (u8 *)pxmitframe);
4622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			break;
4632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		case _TKIP_:
4642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_tkip_encrypt(padapter, (u8 *)pxmitframe);
4652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			break;
4662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		case _AES_:
4672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			r8712_aes_encrypt(padapter, (u8 *)pxmitframe);
4682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			break;
4692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		default:
4702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				break;
4712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
4722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
4732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
4742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
4752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
4762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic sint make_wlanhdr(struct _adapter *padapter , u8 *hdr,
4772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			 struct pkt_attrib *pattrib)
4782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
4792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u16 *qc;
4802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
4812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
4822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct qos_priv *pqospriv = &pmlmepriv->qospriv;
4842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u16 *fctrl = &pwlanhdr->frame_ctl;
4852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	memset(hdr, 0, WLANHDR_OFFSET);
4862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	SetFrameSubType(fctrl, pattrib->subtype);
4872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->subtype & WIFI_DATA_TYPE) {
4882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if ((check_fwstate(pmlmepriv,  WIFI_STATION_STATE) == true)) {
4892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			/* to_ds = 1, fr_ds = 0; */
4902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			SetToDs(fctrl);
4912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv),
4922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				ETH_ALEN);
4932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
4942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
4952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		} else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) {
4962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			/* to_ds = 0, fr_ds = 1; */
4972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			SetFrDs(fctrl);
4982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
4992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv),
5002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				ETH_ALEN);
5012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
5022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		} else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
5032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			   || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)
5042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			   == true)) {
5052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
5062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
5072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
5082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				ETH_ALEN);
5092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		} else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
5102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
5112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
5122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
5132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				ETH_ALEN);
5142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		} else
5152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			return _FAIL;
5162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pattrib->encrypt)
5182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			SetPrivacy(fctrl);
5192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pqospriv->qos_option) {
5202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
5212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (pattrib->priority)
5222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				SetPriority(qc, pattrib->priority);
5232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			SetAckpolicy(qc, pattrib->ack_policy);
5242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
5252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* TODO: fill HT Control Field */
5262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* Update Seq Num will be handled by f/w */
5272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		{
5282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			struct sta_info *psta;
5292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			sint bmcst = IS_MCAST(pattrib->ra);
5312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (pattrib->psta)
5322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				psta = pattrib->psta;
5332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			else {
5342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (bmcst)
5352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					psta = r8712_get_bcmc_stainfo(padapter);
5362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				else
5372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					psta =
5382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 r8712_get_stainfo(&padapter->stapriv,
5392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					 pattrib->ra);
5402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
5412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (psta) {
5422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				psta->sta_xmitpriv.txseq_tid
5432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  [pattrib->priority]++;
5442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				psta->sta_xmitpriv.txseq_tid[pattrib->priority]
5452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						   &= 0xFFF;
5462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				pattrib->seqnum = psta->sta_xmitpriv.
5472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						  txseq_tid[pattrib->priority];
5482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				SetSeqNum(hdr, pattrib->seqnum);
5492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
5502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
5512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
5522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
5532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
5542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic sint r8712_put_snap(u8 *data, u16 h_proto)
5562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
5572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct ieee80211_snap_hdr *snap;
5582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	const u8 *oui;
5592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap = (struct ieee80211_snap_hdr *)data;
5612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->dsap = 0xaa;
5622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->ssap = 0xaa;
5632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->ctrl = 0x03;
5642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (h_proto == 0x8137 || h_proto == 0x80f3)
5652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		oui = P802_1H_OUI;
5662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else
5672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		oui = RFC1042_OUI;
5682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->oui[0] = oui[0];
5692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->oui[1] = oui[1];
5702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	snap->oui[2] = oui[2];
5712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
5722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return SNAP_SIZE + sizeof(u16);
5732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
5742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*
5762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This sub-routine will perform all the following:
5772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 1. remove 802.3 header.
5782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 2. create wlan_header, based on the info in pxmitframe
5792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 3. append sta's iv/ext-iv
5802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 4. append LLC
5812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 5. move frag chunk from pframe to pxmitframe->mem
5822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 6. apply sw-encrypt, if necessary.
5832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */
5842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingersint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
5852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			struct xmit_frame *pxmitframe)
5862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
5872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_file pktfile;
5882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
5892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint	frg_len, mpdu_len, llc_sz;
5902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u32	mem_sz;
5912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8	frg_inx;
5922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	addr_t addr;
5932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8 *pframe, *mem_start, *ptxdesc;
5942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info		*psta;
5952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct security_priv	*psecuritypriv = &padapter->securitypriv;
5962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
5972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
5982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
5992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8 *pbuf_start;
6002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint bmcst = IS_MCAST(pattrib->ra);
6012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
6022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->psta == NULL)
6032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
6042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	psta = pattrib->psta;
6052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitframe->buf_addr == NULL)
6062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
6072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pbuf_start = pxmitframe->buf_addr;
6082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	ptxdesc = pbuf_start;
6092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	mem_start = pbuf_start + TXDESC_OFFSET;
6102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL)
6112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
6122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	_r8712_open_pktfile(pkt, &pktfile);
613f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar	_r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
6142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
6152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
6162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pattrib->ether_type == 0x8712) {
6172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			/* take care -  update_txdesc overwrite this */
6182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			_r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE);
6192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
6202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
6212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pattrib->pktlen = pktfile.pkt_len;
6222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	frg_inx = 0;
6232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	frg_len = pxmitpriv->frag_len - 4;
6242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	while (1) {
6252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		llc_sz = 0;
6262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		mpdu_len = frg_len;
6272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pframe = mem_start;
6282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		SetMFrag(mem_start);
6292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pframe += pattrib->hdrlen;
6302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		mpdu_len -= pattrib->hdrlen;
6312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		/* adding icv, if necessary...*/
6322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (pattrib->iv_len) {
6332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (psta != NULL) {
6342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				switch (pattrib->encrypt) {
6352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				case _WEP40_:
6362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				case _WEP104_:
6372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					WEP_IV(pattrib->iv, psta->txpn,
6382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					       (u8)psecuritypriv->
6392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					       PrivacyKeyIndex);
6402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					break;
6412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				case _TKIP_:
6422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					if (bmcst)
6432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						TKIP_IV(pattrib->iv,
6442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						    psta->txpn,
6452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						    (u8)psecuritypriv->
6462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						    XGrpKeyid);
6472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					else
6482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						TKIP_IV(pattrib->iv, psta->txpn,
6492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger							0);
6502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					break;
6512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				case _AES_:
6522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					if (bmcst)
6532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						AES_IV(pattrib->iv, psta->txpn,
6542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						    (u8)psecuritypriv->
6552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						    XGrpKeyid);
6562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					else
6572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						AES_IV(pattrib->iv, psta->txpn,
6582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						       0);
6592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					break;
6602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				}
6612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			}
6622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pframe, pattrib->iv, pattrib->iv_len);
6632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pframe += pattrib->iv_len;
6642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			mpdu_len -= pattrib->iv_len;
6652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
6662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (frg_inx == 0) {
6672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			llc_sz = r8712_put_snap(pframe, pattrib->ether_type);
6682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pframe += llc_sz;
6692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			mpdu_len -= llc_sz;
6702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
6712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if ((pattrib->icv_len > 0) && (pattrib->bswenc))
6722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			mpdu_len -= pattrib->icv_len;
6732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (bmcst)
6742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			mem_sz = _r8712_pktfile_read(&pktfile, pframe,
6752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 pattrib->pktlen);
6762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		else
6772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			mem_sz = _r8712_pktfile_read(&pktfile, pframe,
6782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 mpdu_len);
6792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pframe += mem_sz;
6802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
6812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			memcpy(pframe, pattrib->icv, pattrib->icv_len);
6822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pframe += pattrib->icv_len;
6832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
6842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		frg_inx++;
6852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (bmcst || (r8712_endofpktfile(&pktfile) == true)) {
6862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pattrib->nr_frags = frg_inx;
6872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pattrib->last_txcmdsz = pattrib->hdrlen +
6882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						pattrib->iv_len +
6892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						((pattrib->nr_frags == 1) ?
6902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						llc_sz : 0) +
6912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						((pattrib->bswenc) ?
6922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger						pattrib->icv_len : 0) + mem_sz;
6932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			ClearMFrag(mem_start);
6942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			break;
6952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
6962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		addr = (addr_t)(pframe);
6972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET;
6982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen);
6992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
7002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (xmitframe_addmic(padapter, pxmitframe) == _FAIL)
7022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
7032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	xmitframe_swencrypt(padapter, pxmitframe);
7042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
7052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
7062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len)
7082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
7092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	uint	protection;
7102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	u8	*perp;
7112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint	 erp_len;
7122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
7132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	registry_priv *pregistrypriv = &padapter->registrypriv;
7142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	switch (pxmitpriv->vcs_setting) {
7162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case DISABLE_VCS:
7172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->vcs = NONE_VCS;
7182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
7192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case ENABLE_VCS:
7202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
7212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case AUTO_VCS:
7222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	default:
7232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		perp = r8712_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
7242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (perp == NULL)
7252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			pxmitpriv->vcs = NONE_VCS;
7262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		else {
7272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			protection = (*(perp + 2)) & BIT(1);
7282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (protection) {
7292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				if (pregistrypriv->vcs_type == RTS_CTS)
7302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					pxmitpriv->vcs = RTS_CTS;
7312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				else
7322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					pxmitpriv->vcs = CTS_TO_SELF;
7332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			} else
7342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				pxmitpriv->vcs = NONE_VCS;
7352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
7362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
7372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
7382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
7392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
7412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
7422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
7432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_buf *pxmitbuf =  NULL;
7442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
7452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
7462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
7482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (_queue_empty(pfree_xmitbuf_queue) == true)
7492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf = NULL;
7502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else {
7512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phead = get_list_head(pfree_xmitbuf_queue);
7522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		plist = get_next(phead);
7532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
7542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		list_delete(&(pxmitbuf->list));
7552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
7562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitbuf !=  NULL)
7572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->free_xmitbuf_cnt--;
7582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
7592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return pxmitbuf;
7602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
7612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
7632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
7642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
7652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
7662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitbuf == NULL)
7682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
7692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
7702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	list_delete(&pxmitbuf->list);
7712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
7722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->free_xmitbuf_cnt++;
7732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
7742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
7752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
7762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*
7782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry FingerCalling context:
7792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger1. OS_TXENTRY
7802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
7812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry FingerIf we turn on USE_RXTHREAD, then, no need for critical section.
7832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry FingerOtherwise, we must use _enter/_exit critical to protect free_xmit_queue...
7842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry FingerMust be very very cautious...
7862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger*/
7882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
7892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv)
7902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
7912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	/*
7922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		Please remember to use all the osdep_service api,
7932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		and lock/unlock or _enter/_exit critical to protect
7942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pfree_xmit_queue
7952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	*/
7962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
7972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_frame *pxframe = NULL;
7982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
7992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
8002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
8022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (_queue_empty(pfree_xmit_queue) == true)
8032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe =  NULL;
8042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else {
8052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phead = get_list_head(pfree_xmit_queue);
8062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		plist = get_next(phead);
8072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
8082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		list_delete(&(pxframe->list));
8092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
8102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxframe !=  NULL) {
8112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->free_xmitframe_cnt--;
8122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->buf_addr = NULL;
8132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->pxmitbuf = NULL;
8142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->attrib.psta = NULL;
8152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxframe->pkt = NULL;
8162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
8172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
8182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return pxframe;
8192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
8202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
8222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			  struct xmit_frame *pxmitframe)
8232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
8242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
8252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
8262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct _adapter *padapter = pxmitpriv->adapter;
827f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar	struct sk_buff *pndis_pkt = NULL;
8282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitframe == NULL)
8302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
8312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
8322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	list_delete(&pxmitframe->list);
833f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar	if (pxmitframe->pkt) {
834f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar		pndis_pkt = pxmitframe->pkt;
835f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar		pxmitframe->pkt = NULL;
836f95302eed91061d1d9440d572166e46d58d35b7cAli Bahar	}
8372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	list_insert_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
8382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->free_xmitframe_cnt++;
8392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
8402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (netif_queue_stopped(padapter->pnetdev))
8412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		netif_wake_queue(padapter->pnetdev);
8422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
8432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
8452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		      struct xmit_frame *pxmitframe)
8462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
8472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitframe == NULL)
8482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
8492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitframe->frame_tag == DATA_FRAMETAG)
8502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_free_xmitframe(pxmitpriv, pxmitframe);
8512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
8522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
8542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				struct  __queue *pframequeue)
8552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
8562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
8572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct list_head *plist, *phead;
8582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct	xmit_frame	*pxmitframe;
8592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&(pframequeue->lock), irqL);
8612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	phead = get_list_head(pframequeue);
8622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	plist = get_next(phead);
8632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	while (end_of_queue_search(phead, plist) == false) {
8642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
8652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		plist = get_next(plist);
8662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_free_xmitframe(pxmitpriv, pxmitframe);
8672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
8682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&(pframequeue->lock), irqL);
8692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
8702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic inline struct tx_servq *get_sta_pending(struct _adapter *padapter,
8722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					       struct  __queue **ppstapending,
8732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger					       struct sta_info *psta, sint up)
8742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
8752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct tx_servq *ptxservq;
8772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct hw_xmit *phwxmits =  padapter->xmitpriv.hwxmits;
8782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
8792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	switch (up) {
8802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 1:
8812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 2:
8822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ptxservq = &(psta->sta_xmitpriv.bk_q);
8832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		*ppstapending = &padapter->xmitpriv.bk_pending;
8842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		(phwxmits+3)->accnt++;
8852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
8862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 4:
8872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 5:
8882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ptxservq = &(psta->sta_xmitpriv.vi_q);
8892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		*ppstapending = &padapter->xmitpriv.vi_pending;
8902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		(phwxmits+1)->accnt++;
8912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
8922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 6:
8932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 7:
8942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ptxservq = &(psta->sta_xmitpriv.vo_q);
8952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		*ppstapending = &padapter->xmitpriv.vo_pending;
8962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		(phwxmits+0)->accnt++;
8972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
8982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 0:
8992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	case 3:
9002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	default:
9012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ptxservq = &(psta->sta_xmitpriv.be_q);
9022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		*ppstapending = &padapter->xmitpriv.be_pending;
9032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		(phwxmits + 2)->accnt++;
9042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		break;
9052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
9062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return ptxservq;
9072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
9082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
9092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*
9102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Will enqueue pxmitframe to the proper queue, and indicate it
9112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * to xx_pending list.....
9122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */
9132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingersint r8712_xmit_classifier(struct _adapter *padapter,
9142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			   struct xmit_frame *pxmitframe)
9152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
9162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL0;
9172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct  __queue *pstapending;
9182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_info	*psta;
9192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct tx_servq	*ptxservq;
9202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_attrib *pattrib = &pxmitframe->attrib;
9212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
9222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
9232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint bmcst = IS_MCAST(pattrib->ra);
9242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
9252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pattrib->psta)
9262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		psta = pattrib->psta;
9272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	else {
9282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		if (bmcst)
9292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			psta = r8712_get_bcmc_stainfo(padapter);
9302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		else {
9312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
9322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				psta = r8712_get_stainfo(pstapriv,
9332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				       get_bssid(pmlmepriv));
9342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			else
9352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				psta = r8712_get_stainfo(pstapriv, pattrib->ra);
9362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		}
9372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
9382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (psta == NULL)
9392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return _FAIL;
9402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	ptxservq = get_sta_pending(padapter, &pstapending,
9412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		   psta, pattrib->priority);
9422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pstapending->lock, irqL0);
9432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (is_list_empty(&ptxservq->tx_pending))
9442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		list_insert_tail(&ptxservq->tx_pending,
9452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger				 get_list_head(pstapending));
9462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	list_insert_tail(&pxmitframe->list,
9472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			 get_list_head(&ptxservq->sta_pending));
9482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	ptxservq->qcnt++;
9492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_unlock_irqrestore(&pstapending->lock, irqL0);
9502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return _SUCCESS;
9512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
9522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
9532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void alloc_hwxmits(struct _adapter *padapter)
9542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
9552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct hw_xmit *hwxmits;
9562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
9572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
9582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
9592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->hwxmits = (struct hw_xmit *)_malloc(sizeof(struct hw_xmit) *
9602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger			     pxmitpriv->hwxmit_entry);
9612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitpriv->hwxmits == NULL)
9622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return;
9632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	hwxmits = pxmitpriv->hwxmits;
9642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitpriv->hwxmit_entry == 5) {
9652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->bmc_txqueue.head = 0;
9662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue;
9672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
9682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->vo_txqueue.head = 0;
9692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
9702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
9712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitpriv->vi_txqueue.head = 0;
9722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
9732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
9742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->bk_txqueue.head = 0;
9752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
9762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
9772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->be_txqueue.head = 0;
9782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue;
9792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
9802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else if (pxmitpriv->hwxmit_entry == 4) {
9812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->vo_txqueue.head = 0;
9822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue;
9832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
9842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->vi_txqueue.head = 0;
9852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue;
9862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
9872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->be_txqueue.head = 0;
9882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue;
9892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
9902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		pxmitpriv->bk_txqueue.head = 0;
9912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
9922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
9932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
9942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
9952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
9962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void free_hwxmits(struct _adapter *padapter)
9972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
9982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
9992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
1000400838659314cc67032f35962eee5a8639981b61Alexander Beregalov	kfree(pxmitpriv->hwxmits);
10012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
10022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
10032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void init_hwxmits(struct hw_xmit *phwxmit, sint entry)
10042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
10052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	sint i;
10062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
10072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	for (i = 0; i < entry; i++, phwxmit++) {
10082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		spin_lock_init(&phwxmit->xmit_lock);
10092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		_init_listhead(&phwxmit->pending);
10102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phwxmit->txcmdcnt = 0;
10112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		phwxmit->accnt = 0;
10122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
10132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
10142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
101507a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Baharvoid xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
101607a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar			struct xmit_buf *pxmitbuf)
101707a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar{
101807a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	/* pxmitbuf attach to pxmitframe */
101907a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	pxmitframe->pxmitbuf = pxmitbuf;
102007a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	/* urb and irp connection */
102107a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
102207a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	/* buffer addr assoc */
102307a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	pxmitframe->buf_addr = pxmitbuf->pbuf;
102407a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	/* pxmitframe attach to pxmitbuf */
102507a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar	pxmitbuf->priv_data = pxmitframe;
102607a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar}
102707a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar
10282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*
10292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * tx_action == 0 == no frames to transmit
10302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * tx_action > 0 ==> we have frames to transmit
10312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
10322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger *						 to transmit 1 frame.
10332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */
10342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
10352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe)
10362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{
10372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	unsigned long irqL;
10382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	int ret;
10392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_buf *pxmitbuf = NULL;
10402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
10412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	struct pkt_attrib *pattrib = &pxmitframe->attrib;
10422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger
10432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	r8712_do_queue_select(padapter, pattrib);
10442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	spin_lock_irqsave(&pxmitpriv->lock, irqL);
10452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (r8712_txframes_sta_ac_pending(padapter, pattrib) > 0) {
10462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ret = false;
10472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_enqueue(padapter, pxmitframe);
10482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
10492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		return ret;
10502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
10512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
10522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	if (pxmitbuf == NULL) { /*enqueue packet*/
10532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ret = false;
10542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_enqueue(padapter, pxmitframe);
10552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
10562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	} else { /*dump packet directly*/
10572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
10582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		ret = true;
105907a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar		xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
10602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger		r8712_xmit_direct(padapter, pxmitframe);
10612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	}
10622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger	return ret;
10632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}
1064