12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/****************************************************************************** 22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * rtl8712_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 _RTL8712_XMIT_C_ 302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h" 322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h" 332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "wifi.h" 342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_intf.h" 352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "usb_ops.h" 362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void dump_xframe(struct _adapter *padapter, 382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe); 39ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Baharstatic void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz); 402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingersint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag) 422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ac_tag = ac_tag; 442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (ac_tag) { 452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case BE_QUEUE_INX: 462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; 472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case BK_QUEUE_INX: 492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ; 502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case VI_QUEUE_INX: 522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ; 532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case VO_QUEUE_INX: 552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ; 562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case BMC_QUEUE_INX: 582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; 592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _SUCCESS; 622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_txframes_sta_ac_pending(struct _adapter *padapter, 652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib) 662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct sta_info *psta; 682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_servq *ptxservq; 692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int priority = pattrib->priority; 702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger psta = pattrib->psta; 722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (priority) { 732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 1: 742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 2: 752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq = &(psta->sta_xmitpriv.bk_q); 762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 4: 782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 5: 792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq = &(psta->sta_xmitpriv.vi_q); 802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 6: 822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 7: 832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq = &(psta->sta_xmitpriv.vo_q); 842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 3: 872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq = &(psta->sta_xmitpriv.be_q); 892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return ptxservq->qcnt; 922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic u32 get_ff_hwaddr(struct xmit_frame *pxmitframe) 952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 addr = 0; 972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib = &pxmitframe->attrib; 982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = pxmitframe->padapter; 992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv; 1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe->frame_tag == TXAGG_FRAMETAG) 1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_H2CCMD; 1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else if (pxmitframe->frame_tag == MGNT_FRAMETAG) 1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_MGTQ; 1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else if (pdvobj->nr_endpoint == 6) { 1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pattrib->priority) { 1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 3: 1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_BEQ; 1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 1: 1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 2: 1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_BKQ; 1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 4: 1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 5: 1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_VIQ; 1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 6: 1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 7: 1212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_VOQ; 1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x10: 1242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x11: 1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x12: 1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x13: 1272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_H2CCMD; 1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_BEQ; 1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if (pdvobj->nr_endpoint == 4) { 1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pattrib->qsel) { 1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 3: 1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 1: 1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 2: 1392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ 1402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 4: 1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 5: 1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 6: 1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 7: 1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/ 1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x10: 1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x11: 1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x12: 1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0x13: 151859171ca92f2865453b4b2e17bf679c67044a833Joe Perches addr = RTL8712_DMA_H2CCMD; 1522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ 1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return addr; 1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, 1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct hw_xmit *phwxmit, 1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_servq *ptxservq, 1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct __queue *pframe_queue) 1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct list_head *xmitframe_plist, *xmitframe_phead; 1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe = NULL; 1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 169e99a428a1daed550142a08f6acb5265a1d108e65James A Shackleford xmitframe_phead = &pframe_queue->queue; 170849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford xmitframe_plist = xmitframe_phead->next; 1712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false) { 1722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe = LIST_CONTAINOR(xmitframe_plist, 1732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame, list); 17429197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford list_del_init(&pxmitframe->list); 1752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq->qcnt--; 1762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phwxmit->txcmdcnt++; 1772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return pxmitframe; 1792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv, 1822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct hw_xmit *phwxmit_i, sint entry) 1832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned long irqL0; 1852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct list_head *sta_plist, *sta_phead; 1862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct hw_xmit *phwxmit; 1872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_servq *ptxservq = NULL; 1882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct __queue *pframe_queue = NULL; 1892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe = NULL; 1902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int i, inx[4]; 1912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int j, tmp, acirp_cnt[4]; 1922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/ 1942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt; 1952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt; 1962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt; 1972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt; 1982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < 4; i++) { 1992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (j = i + 1; j < 4; j++) { 2002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (acirp_cnt[j] < acirp_cnt[i]) { 2012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmp = acirp_cnt[i]; 2022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger acirp_cnt[i] = acirp_cnt[j]; 2032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger acirp_cnt[j] = tmp; 2042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmp = inx[i]; 2052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[i] = inx[j]; 2062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger inx[j] = tmp; 2072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger spin_lock_irqsave(&pxmitpriv->lock, irqL0); 2112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < entry; i++) { 2122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phwxmit = phwxmit_i + inx[i]; 213e99a428a1daed550142a08f6acb5265a1d108e65James A Shackleford sta_phead = &phwxmit->sta_queue->queue; 214849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford sta_plist = sta_phead->next; 2152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger while ((end_of_queue_search(sta_phead, sta_plist)) == false) { 2162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, 2172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tx_pending); 2182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pframe_queue = &ptxservq->sta_pending; 2192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, 2202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxservq, pframe_queue); 2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe) { 2222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phwxmit->accnt--; 2232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto exit_dequeue_xframe_ex; 2242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 225849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford sta_plist = sta_plist->next; 2262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*Remove sta node when there are no pending packets.*/ 227df353f61afb917ff66b2e784b0ffb85d0ebb29a4James A Shackleford if (list_empty(&pframe_queue->queue)) { 228849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford /* must be done after sta_plist->next 229849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford * and before break 230849fb0a8878336732165eb482d3f0e8a4f71dd03James A Shackleford */ 23129197b7c45a144883d87cb8eaf337026cd886a20James A Shackleford list_del_init(&ptxservq->tx_pending); 2322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerexit_dequeue_xframe_ex: 2362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger spin_unlock_irqrestore(&pxmitpriv->lock, irqL0); 2372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return pxmitframe; 2382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_do_queue_select(struct _adapter *padapter, 2412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib) 2422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 243ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar unsigned int qsel = 0; 2442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv; 2452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pdvobj->nr_endpoint == 6) 247ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = (unsigned int) pattrib->priority; 248ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar else if (pdvobj->nr_endpoint == 4) { 249ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = (unsigned int) pattrib->priority; 250ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar if (qsel == 0 || qsel == 3) 251ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = 3; 252ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar else if (qsel == 1 || qsel == 2) 253ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = 1; 254ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar else if (qsel == 4 || qsel == 5) 255ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = 5; 256ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar else if (qsel == 6 || qsel == 7) 257ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = 7; 258ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar else 259ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar qsel = 3; 260ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar } 2612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pattrib->qsel = qsel; 2622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 26493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 26593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) 26693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 26793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 26893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 26993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/ 27093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* dw0 */ 27193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ&0xffff); 27293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptx_desc->txdw0 |= 27393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); 27493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 27593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 27693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* dw1 */ 27793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptx_desc->txdw1 |= cpu_to_le32((0x13<<QSEL_SHT)&0x00001f00); 27893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 27993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return _SUCCESS; 28093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 28193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 28293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) 28393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 28493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *pxmitframe = (struct xmit_frame *) 28593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->priv_data; 28693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct _adapter *padapter = pxmitframe->padapter; 28793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 28893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 28993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pxmitbuf->pbuf + TXDESC_SIZE); 29093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 29193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* Fill up Cmd Header for USB FW Tx Aggregation.*/ 29293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* dw0 */ 29393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | 29493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pcmdpriv->cmd_seq << 24)); 29593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pcmdpriv->cmd_seq++; 29693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 29793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return _SUCCESS; 29893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 29993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 30093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, 30193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *pxmitframe) 30293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 30393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct _adapter *padapter = pxmitframe->padapter; 30493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 30593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar int last_txcmdsz = 0; 30693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar int padding_sz = 0; 30793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 30893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* 802.3->802.11 convertor */ 30993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); 31093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* free skb struct */ 31193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_xmit_complete(padapter, pxmitframe); 31293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (pxmitframe->attrib.ether_type != 0x0806) { 31393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if ((pxmitframe->attrib.ether_type != 0x888e) && 31493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pxmitframe->attrib.dhcp_pkt != 1)) { 31593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_issue_addbareq_cmd(padapter, 31693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->attrib.priority); 31793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 31893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 31993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->last[0] = 1; 32093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), 32193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->attrib.last_txcmdsz); 32293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /*padding zero */ 32393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar last_txcmdsz = pxmitframe->attrib.last_txcmdsz; 32493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar padding_sz = (8 - (last_txcmdsz % 8)); 32593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if ((last_txcmdsz % 8) != 0) { 32693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar int i; 32702a29d2d9209ad24258432057886a5af5816c388Tapasweni Pathak 32893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar for (i = 0; i < padding_sz; i++) 32993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar *(pxmitframe->buf_addr+TXDESC_SIZE+last_txcmdsz+i) = 0; 33093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 33193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* Add the new mpdu's length */ 33293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0&0xffff0000) | 33393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((ptx_desc->txdw0&0x0000ffff)+ 33493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((TXDESC_SIZE+last_txcmdsz+padding_sz)&0x0000ffff))); 33593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 33693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return _SUCCESS; 33793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 33893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 33993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 34093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, 34193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *pxmitframe) 34293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 34393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* linux complete context doesnt need to protect */ 34493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->pxmitbuf = pxmitbuf; 34593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->priv_data = pxmitframe; 34693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 34793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* buffer addr assoc */ 34893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->buf_addr = pxmitbuf->pbuf+TXDESC_SIZE+CMD_HDR_SZ; 34993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /*RTL8712_DMA_H2CCMD */ 35093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_construct_txaggr_cmd_desc(pxmitbuf); 35193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_construct_txaggr_cmd_hdr(pxmitbuf); 35293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) 35393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->aggr_nr = 1; 35493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 35593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return _SUCCESS; 35693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 35793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 35893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, 35993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *pxmitframe) 36093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 36193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->pxmitbuf = pxmitbuf; 36293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->priv_data = pxmitframe; 36393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 36493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* buffer addr assoc */ 36593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + 36693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 36793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) { 36893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, 36993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe); 37093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->aggr_nr++; 37193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 37293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 37393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return TXDESC_SIZE + 37493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 37593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 37693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 37793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Baharu8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, 37893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *pxmitframe) 37993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar{ 38093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct _adapter *padapter = pxmitframe->padapter; 38193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct dvobj_priv *pdvobj = (struct dvobj_priv *) &padapter->dvobjpriv; 382c06df2334ce9a0072c94ffffcd8977fe726015f1Devendra Naga struct tx_desc *ptxdesc = (struct tx_desc *)pxmitbuf->pbuf; 38393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 38493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pxmitbuf->pbuf + TXDESC_SIZE); 38593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff); 38693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 38793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* use 1st xmitframe as media */ 38893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 38993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length-CMD_HDR_SZ)&0x0000ffff)| 39093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pcmd_hdr->cmd_dw0&0xffff0000)); 39193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 39293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* urb length in cmd_dw1 */ 39393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)| 39493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((total_length+TXDESC_SIZE) << 16)); 39593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->last[0] = 1; 39693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->bpending[0] = false; 39793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitframe->mem_addr = pxmitbuf->pbuf; 39893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 39993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if ((pdvobj->ishighspeed && ((total_length+TXDESC_SIZE)%0x200) == 0) || 40093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((!pdvobj->ishighspeed && 40193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((total_length+TXDESC_SIZE)%0x40) == 0))) { 40293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw0 |= cpu_to_le32 40393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (((TXDESC_SIZE+OFFSET_SZ+8)<<OFFSET_SHT)&0x00ff0000); 40493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /*32 bytes for TX Desc + 8 bytes pending*/ 40593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } else { 40693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw0 |= cpu_to_le32 40793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); 40893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /*default = 32 bytes for TX Desc*/ 40993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 41093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, 41193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar total_length+TXDESC_SIZE, (u8 *)pxmitframe); 41293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 41393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return _SUCCESS; 41493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar} 41593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 41693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 41793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 4182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) 4192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 4202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger uint qsel; 4212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = pxmitframe->padapter; 4222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct qos_priv *pqospriv = &pmlmepriv->qospriv; 4242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct security_priv *psecuritypriv = &padapter->securitypriv; 4252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib = &pxmitframe->attrib; 4262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_desc *ptxdesc = (struct tx_desc *)pmem; 4272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv; 42893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 42993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct cmd_priv *pcmdpriv = (struct cmd_priv *)&padapter->cmdpriv; 43093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 4312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 blnSetTxDescOffset; 4322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sint bmcst = IS_MCAST(pattrib->ra); 4332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct ht_priv *phtpriv = &pmlmepriv->htpriv; 4342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_desc txdesc_mp; 4352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc)); 4372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memset(ptxdesc, 0, sizeof(struct tx_desc)); 4382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 0 */ 4392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); 4402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pdvobj->ishighspeed) { 4412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (((sz + TXDESC_SIZE) % 512) == 0) 4422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnSetTxDescOffset = 1; 4432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 4442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnSetTxDescOffset = 0; 4452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 4462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (((sz + TXDESC_SIZE) % 64) == 0) 4472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnSetTxDescOffset = 1; 4482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 4492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger blnSetTxDescOffset = 0; 4502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (blnSetTxDescOffset) { 4522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* 32 bytes for TX Desc + 8 bytes pending */ 4532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ + 8) << 4542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger OFFSET_SHT) & 0x00ff0000); 4552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 4562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* default = 32 bytes for TX Desc */ 4572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ) << 4582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger OFFSET_SHT) & 0x00ff0000); 4592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 4612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe->frame_tag == DATA_FRAMETAG) { 4622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 4 */ 4632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f); 46493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 46593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 46693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* dirty workaround, need to check if it is aggr cmd. */ 46793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) { 46893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw0 |= cpu_to_le32 46993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((0x3 << TYPE_SHT)&TYPE_MSK); 47093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar qsel = (uint)(pattrib->qsel & 0x0000001f); 47193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (qsel == 2) 47293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar qsel = 0; 47393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw1 |= cpu_to_le32 47493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((qsel << QSEL_SHT) & 0x00001f00); 47593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw2 = cpu_to_le32 47693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((qsel << RTS_RC_SHT)&0x001f0000); 47793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw6 |= cpu_to_le32 47893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((0x5 << RSVD6_SHT)&RSVD6_MSK); 47993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } else { 48093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw0 |= cpu_to_le32 48193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((0x3 << TYPE_SHT)&TYPE_MSK); 48293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw1 |= cpu_to_le32 48393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((0x13 << QSEL_SHT) & 0x00001f00); 48493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar qsel = (uint)(pattrib->qsel & 0x0000001f); 48593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (qsel == 2) 48693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar qsel = 0; 48793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw2 = cpu_to_le32 48893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ((qsel << RTS_RC_SHT)&0x0001f000); 48993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar ptxdesc->txdw7 |= cpu_to_le32 49093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (pcmdpriv->cmd_seq << 24); 49193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pcmdpriv->cmd_seq++; 49293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 49393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pattrib->qsel = 0x13; 49493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#else 4952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger qsel = (uint)(pattrib->qsel & 0x0000001f); 4962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 49793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 4982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!pqospriv->qos_option) 4992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/ 5002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((pattrib->encrypt > 0) && !pattrib->bswenc) { 5012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pattrib->encrypt) { /*SEC_TYPE*/ 5022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _WEP40_: 5032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _WEP104_: 5042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) & 5052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00c00000); 5062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*KEY_ID when WEP is used;*/ 5072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((psecuritypriv-> 5082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger PrivacyKeyIndex << 17) & 5092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00060000); 5102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 5112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _TKIP_: 5122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _TKIP_WTMIC_: 5132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) & 5142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00c00000); 5152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 5162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _AES_: 5172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) & 5182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x00c00000); 5192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 5202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case _NO_PRIVACY_: 5212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 5222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 5232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 8*/ 5262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (bmcst) 5272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 |= cpu_to_le32(BMC); 5282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 5292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 12*/ 5302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* f/w will increase the seqnum by itself, driver pass the 5312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * correct priority to fw 5322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * fw will check the correct priority for increasing the 5332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * seqnum per tid. about usb using 4-endpoint, qsel points out 5342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * the correct mapping between AC&Endpoint, 5352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * the purpose is that correct mapping lets the MAC release 5362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * the AC Queue list correctly. */ 5372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 5382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x0fff0000); 5392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((pattrib->ether_type != 0x888e) && 5402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pattrib->ether_type != 0x0806) && 5412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (pattrib->dhcp_pkt != 1)) { 5422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*Not EAP & ARP type data packet*/ 5432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ 5442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (phtpriv->ampdu_enable != true) 5452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 |= cpu_to_le32(BK); 5462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 5482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* EAP data packet and ARP packet. 5492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Use the 1M data rate to send the EAP/ARP packet. 5502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This will maybe make the handshake smooth. 5512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */ 5522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*driver uses data rate*/ 5532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw4 = cpu_to_le32(0x80000000); 5542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/ 5552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pattrib->pctrl == 1) { /* mp tx packets */ 5572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct tx_desc *ptxdesc_mp; 55802a29d2d9209ad24258432057886a5af5816c388Tapasweni Pathak 5592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc_mp = &txdesc_mp; 5602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 8 */ 5612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 = cpu_to_le32(ptxdesc_mp->txdw2); 5622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (bmcst) 5632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 |= cpu_to_le32(BMC); 5642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 |= cpu_to_le32(BK); 5652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 16 */ 5662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw4 = cpu_to_le32(ptxdesc_mp->txdw4); 5672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 20 */ 5682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw5 = cpu_to_le32(ptxdesc_mp->txdw5); 5692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pattrib->pctrl = 0;/* reset to zero; */ 5702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { 5722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 4 */ 5732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/ 5742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger qsel = (uint)(pattrib->qsel & 0x0000001f); 5752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 5762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */ 5772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 8 */ 5782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (bmcst) 5792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw2 |= cpu_to_le32(BMC); 5802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 12 */ 5812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* f/w will increase the seqnum by itself, driver pass the 5822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * correct priority to fw 5832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * fw will check the correct priority for increasing the seqnum 5842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * per tid. about usb using 4-endpoint, qsel points out the 5852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * correct mapping between AC&Endpoint, 5862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * the purpose is that correct mapping let the MAC releases 5872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * the AC Queue list correctly. */ 5882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 5892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x0fff0000); 5902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 16 */ 5912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ 5922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 20 */ 5932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */ 5942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { 5952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 4 */ 5962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger qsel = 0x13; 5972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 5982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 5992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* offset 4 */ 6002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger qsel = (uint)(pattrib->priority&0x0000001f); 6012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 6022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 8*/ 6032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 12*/ 6042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 6052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0x0fff0000); 6062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 16*/ 6072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ 6082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*offset 20*/ 6092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/ 6102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 6112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 6122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 6132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_xmitframe_complete(struct _adapter *padapter, 6142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_priv *pxmitpriv, 6152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_buf *pxmitbuf) 6162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 6172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct hw_xmit *phwxmits; 6182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sint hwentry; 6192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe = NULL; 62093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 62193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar struct xmit_frame *p2ndxmitframe = NULL; 62293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#else 6232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int res = _SUCCESS, xcnt = 0; 62493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 6252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 6262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger phwxmits = pxmitpriv->hwxmits; 6272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger hwentry = pxmitpriv->hwxmit_entry; 6282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitbuf == NULL) { 6292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); 6302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!pxmitbuf) 6312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return false; 63293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 63393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->aggr_nr = 0; 63493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 6352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 63607a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar /* 1st frame dequeued */ 63707a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); 63807a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar /* need to remember the 1st frame */ 63907a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar if (pxmitframe != NULL) { 64007a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar 64193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 64293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar /* 1. dequeue 2nd frame 64393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar * 2. aggr if 2nd xframe is dequeued, else dump directly 64493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar */ 64593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (AGGR_NR_HIGH_BOUND > 1) 64693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, 64793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar hwentry); 64893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (pxmitframe->frame_tag != DATA_FRAMETAG) { 64993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 65093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return false; 65193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 65293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (p2ndxmitframe != NULL) 65393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) { 65493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 65593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar return false; 65693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 65793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe); 65893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (p2ndxmitframe != NULL) { 65993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar u16 total_length; 66002a29d2d9209ad24258432057886a5af5816c388Tapasweni Pathak 66193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar total_length = r8712_xmitframe_aggr_next( 66293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf, p2ndxmitframe); 66393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar do { 66493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar p2ndxmitframe = dequeue_xframe_ex( 66593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitpriv, phwxmits, hwentry); 66693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (p2ndxmitframe != NULL) 66793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar total_length = 66893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_xmitframe_aggr_next( 66993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf, 67093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar p2ndxmitframe); 67193c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar else 67293c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar break; 67393c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } while (total_length <= 0x1800 && 67493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND); 67593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar } 67693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar if (pxmitbuf->aggr_nr > 0) 67793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_dump_aggr_xframe(pxmitbuf, pxmitframe); 67893c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar 67993c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#else 68007a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar 68107a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 68207a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar if (pxmitframe->frame_tag == DATA_FRAMETAG) { 68307a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar if (pxmitframe->attrib.priority <= 15) 68407a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar res = r8712_xmitframe_coalesce(padapter, 68507a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar pxmitframe->pkt, pxmitframe); 68607a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar /* always return ndis_packet after 68707a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar * r8712_xmitframe_coalesce */ 68807a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar r8712_xmit_complete(padapter, pxmitframe); 6892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 69007a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar if (res == _SUCCESS) 69107a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar dump_xframe(padapter, pxmitframe); 69207a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar else 69307a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); 69407a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar xcnt++; 69593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 69607a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar 69707a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */ 69807a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 69907a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar return false; 70007a6b03707d3e6c5e1de2869a79b0bdca97ee2acAli Bahar } 7012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return true; 7022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 7032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 7042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void dump_xframe(struct _adapter *padapter, 7052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe) 7062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 7072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int t, sz, w_sz; 7082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 *mem_addr; 7092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 ff_hwaddr; 7102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib = &pxmitframe->attrib; 7112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 7122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct security_priv *psecuritypriv = &padapter->securitypriv; 7132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 7142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe->attrib.ether_type != 0x0806) { 7152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe->attrib.ether_type != 0x888e) 7162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_issue_addbareq_cmd(padapter, pattrib->priority); 7172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 7182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger mem_addr = pxmitframe->buf_addr; 7192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (t = 0; t < pattrib->nr_frags; t++) { 7202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (t != (pattrib->nr_frags - 1)) { 7212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sz = pxmitpriv->frag_len; 7222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : 7232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pattrib->icv_len); 7242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->last[t] = 0; 7252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 7262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sz = pattrib->last_txcmdsz; 7272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->last[t] = 1; 7282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 7292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger update_txdesc(pxmitframe, (uint *)mem_addr, sz); 7302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger w_sz = sz + TXDESC_SIZE; 7312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->mem_addr = mem_addr; 7322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->bpending[t] = false; 7332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ff_hwaddr = get_ff_hwaddr(pxmitframe); 73493c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#ifdef CONFIG_R8712_TX_AGGR 73593c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz, 73693c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar (unsigned char *)pxmitframe); 73793c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#else 7382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_write_port(padapter, ff_hwaddr, w_sz, 7392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (unsigned char *)pxmitframe); 74093c55dda092c7ec2a0bc6a93b5ab220ddbdffb95Ali Bahar#endif 7412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger mem_addr += w_sz; 7422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger mem_addr = (u8 *)RND4(((addr_t)(mem_addr))); 7432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 7442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 7452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 7462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) 7472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 7482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int res = _SUCCESS; 7492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 7502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); 7512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->pkt = NULL; 7522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (res == _SUCCESS) 7532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger dump_xframe(padapter, pxmitframe); 7542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return res; 7552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 7562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 7572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) 7582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 7592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (r8712_xmit_classifier(padapter, pxmitframe) == _FAIL) { 7602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->pkt = NULL; 7612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _FAIL; 7622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 7632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _SUCCESS; 7642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 765