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 *)ðerhdr, 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, ðerhdr.h_dest, ETH_ALEN); 2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(pattrib->src, ðerhdr.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