Path: blob/master/ALFA-W1F1/RTL8814AU/hal/rtl8814a/usb/rtl8814au_xmit.c
1308 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTL8814AU_XMIT_C_1516/* #include <drv_types.h> */17#include <rtl8814a_hal.h>181920s32 rtl8814au_init_xmit_priv(_adapter *padapter)21{22struct xmit_priv *pxmitpriv = &padapter->xmitpriv;23HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);2425#ifdef PLATFORM_LINUX26tasklet_init(&pxmitpriv->xmit_tasklet,27(void(*))rtl8814au_xmit_tasklet,28(unsigned long)padapter);29#endif30#ifdef CONFIG_TX_EARLY_MODE31pHalData->bEarlyModeEnable = padapter->registrypriv.early_mode;32#endif3334return _SUCCESS;35}3637void rtl8814au_free_xmit_priv(_adapter *padapter)38{39}4041static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz , u8 bagg_pkt)42{43int pull = 0;44uint qsel;45u8 data_rate, pwr_status, offset;46_adapter *padapter = pxmitframe->padapter;47struct mlme_priv *pmlmepriv = &padapter->mlmepriv;48struct pkt_attrib *pattrib = &pxmitframe->attrib;49HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);50u8 *ptxdesc = pmem;51struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;52struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);53sint bmcst = IS_MCAST(pattrib->ra);54u16 SWDefineContent = 0x0;55u8 DriverFixedRate = 0x0;5657#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX58if (padapter->registrypriv.mp_mode == 0) {59if ((PACKET_OFFSET_SZ != 0) && (!bagg_pkt) && (rtw_usb_bulk_size_boundary(padapter, TXDESC_SIZE + sz) == _FALSE)) {60ptxdesc = (pmem + PACKET_OFFSET_SZ);61/* RTW_INFO("==> non-agg-pkt,shift pointer...\n"); */62pull = 1;63}64}65#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */6667_rtw_memset(ptxdesc, 0, TXDESC_SIZE);6869/* 4 offset 0 */70/* SET_TX_DESC_FIRST_SEG_8812(ptxdesc, 1); */71SET_TX_DESC_LAST_SEG_8814A(ptxdesc, 1);72/* SET_TX_DESC_OWN_8812(ptxdesc, 1); */7374/* RTW_INFO("%s==> pkt_len=%d,bagg_pkt=%02x\n",__FUNCTION__,sz,bagg_pkt); */75SET_TX_DESC_PKT_SIZE_8814A(ptxdesc, sz);7677offset = TXDESC_SIZE + OFFSET_SZ;7879#ifdef CONFIG_TX_EARLY_MODE80if (bagg_pkt) {81offset += EARLY_MODE_INFO_SIZE ;/* 0x28 */82}83#endif84/* RTW_INFO("%s==>offset(0x%02x)\n",__FUNCTION__,offset); */85SET_TX_DESC_OFFSET_8814A(ptxdesc, offset);8687if (bmcst)88SET_TX_DESC_BMC_8814A(ptxdesc, 1);8990#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX91if (padapter->registrypriv.mp_mode == 0) {92if ((PACKET_OFFSET_SZ != 0) && (!bagg_pkt)) {93if ((pull) && (pxmitframe->pkt_offset > 0))94pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1;95}96}97#endif9899/* RTW_INFO("%s, pkt_offset=0x%02x\n",__FUNCTION__,pxmitframe->pkt_offset); */100/* pkt_offset, unit:8 bytes padding */101if (pxmitframe->pkt_offset > 0)102SET_TX_DESC_PKT_OFFSET_8814A(ptxdesc, pxmitframe->pkt_offset);103104SET_TX_DESC_MACID_8814A(ptxdesc, pattrib->mac_id);105SET_TX_DESC_RATE_ID_8814A(ptxdesc, pattrib->raid);106107SET_TX_DESC_QUEUE_SEL_8814A(ptxdesc, pattrib->qsel);108109/* offset 12 */110111if (!pattrib->qos_en) {112/* HW sequence, to fix to use 0 queue. todo: 4AC packets to use auto queue select */113SET_TX_DESC_HWSEQ_EN_8814A(ptxdesc, 1); /* Hw set sequence number */114SET_TX_DESC_EN_HWEXSEQ_8814A(ptxdesc, 0);115SET_TX_DESC_DISQSELSEQ_8814A(ptxdesc, 1);116SET_TX_DESC_HW_SSN_SEL_8814A(ptxdesc, 0);117} else {118SET_TX_DESC_SEQ_8814A(ptxdesc, pattrib->seqnum);119}120if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {121/* RTW_INFO("pxmitframe->frame_tag == DATA_FRAMETAG\n"); */122123rtl8814a_fill_txdesc_sectype(pattrib, ptxdesc);124#if defined(CONFIG_CONCURRENT_MODE)125if (bmcst)126fill_txdesc_force_bmc_camid(pattrib, ptxdesc);127#endif128129/* offset 20 */130#ifdef CONFIG_USB_TX_AGGREGATION131if (pxmitframe->agg_num > 1) {132/* RTW_INFO("%s agg_num:%d\n",__FUNCTION__,pxmitframe->agg_num ); */133SET_TX_DESC_USB_TXAGG_NUM_8814A(ptxdesc, pxmitframe->agg_num);134}135#endif /* CONFIG_USB_TX_AGGREGATION */136137rtl8814a_fill_txdesc_vcs(padapter, pattrib, ptxdesc);138139if ((pattrib->ether_type != 0x888e) &&140(pattrib->ether_type != 0x0806) &&141(pattrib->ether_type != 0x88b4) &&142(pattrib->dhcp_pkt != 1)143#ifdef CONFIG_AUTO_AP_MODE144&& (pattrib->pctrl != _TRUE)145#endif146) {147/* Non EAP & ARP & DHCP type data packet */148149if (pattrib->ampdu_en == _TRUE) {150SET_TX_DESC_AGG_ENABLE_8814A(ptxdesc, 1);151SET_TX_DESC_MAX_AGG_NUM_8814A(ptxdesc, 0x1f);152/* Set A-MPDU aggregation. */153SET_TX_DESC_AMPDU_DENSITY_8814A(ptxdesc, pattrib->ampdu_spacing);154} else155SET_TX_DESC_BK_8814A(ptxdesc, 1);156157rtl8814a_fill_txdesc_phy(padapter, pattrib, ptxdesc);158159/* compatibility for MCC consideration, use pmlmeext->cur_channel */160if (pmlmeext->cur_channel > 14)161/* for 5G. OFMD 6M */162SET_TX_DESC_DATA_RATE_FB_LIMIT_8814A(ptxdesc, 4);163else164/* for 2.4G CCK 1M */165SET_TX_DESC_DATA_RATE_FB_LIMIT_8814A(ptxdesc, 0);166167if (pHalData->fw_ractrl == _FALSE) {168SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);169DriverFixedRate = 0x01;170171if (pHalData->INIDATA_RATE[pattrib->mac_id] & BIT(7))172SET_TX_DESC_DATA_SHORT_8814A(ptxdesc, 1);173174SET_TX_DESC_TX_RATE_8814A(ptxdesc, (pHalData->INIDATA_RATE[pattrib->mac_id] & 0x7F));175}176if (bmcst) {177DriverFixedRate = 0x01;178fill_txdesc_bmc_tx_rate(pattrib, ptxdesc);179}180181if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */182SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);183DriverFixedRate = 0x01;184if (padapter->fix_rate & BIT(7))185SET_TX_DESC_DATA_SHORT_8814A(ptxdesc, 1);186187SET_TX_DESC_TX_RATE_8814A(ptxdesc, (padapter->fix_rate & 0x7F));188if (!padapter->data_fb)189SET_TX_DESC_DISABLE_FB_8814A(ptxdesc, 1);190}191192if (pattrib->ldpc)193SET_TX_DESC_DATA_LDPC_8814A(ptxdesc, 1);194if (pattrib->stbc)195SET_TX_DESC_DATA_STBC_8814A(ptxdesc, 1);196197/* work arond before fixing RA */198/* SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1); */199/* SET_TX_DESC_TX_RATE_8814A(ptxdesc, 0x10); */200} else {201/* EAP data packet and ARP packet and DHCP. */202/* Use the 1M data rate to send the EAP/ARP packet. */203/* This will maybe make the handshake smooth. */204205SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);206DriverFixedRate = 0x01;207SET_TX_DESC_BK_8814A(ptxdesc, 1);208209/* HW will ignore this setting if the transmission rate is legacy OFDM. */210if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)211SET_TX_DESC_DATA_SHORT_8814A(ptxdesc, 1);212#ifdef CONFIG_IP_R_MONITOR213if((pattrib->ether_type == ETH_P_ARP) &&214(IsSupportedTxOFDM(padapter->registrypriv.wireless_mode))) {215SET_TX_DESC_TX_RATE_8814A(ptxdesc, MRateToHwRate(IEEE80211_OFDM_RATE_6MB));216#ifdef DBG_IP_R_MONITOR217RTW_INFO(FUNC_ADPT_FMT ": SP Packet(0x%04X) rate=0x%x SeqNum = %d\n",218FUNC_ADPT_ARG(padapter), pattrib->ether_type, MRateToHwRate(pmlmeext->tx_rate), pattrib->seqnum);219#endif/*DBG_IP_R_MONITOR*/220} else221#endif/*CONFIG_IP_R_MONITOR*/222SET_TX_DESC_TX_RATE_8814A(ptxdesc, MRateToHwRate(pmlmeext->tx_rate));223}224225} else if ((pxmitframe->frame_tag & 0x0f) == MGNT_FRAMETAG) {226/* RTW_INFO("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); */227228SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);229DriverFixedRate = 0x01;230231SET_TX_DESC_TX_RATE_8814A(ptxdesc, MRateToHwRate(pattrib->rate));232233/* VHT NDPA or HT NDPA Packet for Beamformer. */234235#ifdef CONFIG_BEAMFORMING236if ((pattrib->subtype == WIFI_NDPA) ||237((pattrib->subtype == WIFI_ACTION_NOACK) && (pattrib->order == 1))) {238SET_TX_DESC_NAV_USE_HDR_8814A(ptxdesc, 1);239240SET_TX_DESC_DATA_BW_8814A(ptxdesc, BWMapping_8814(padapter, pattrib));241SET_TX_DESC_RTS_SC_8814A(ptxdesc, SCMapping_8814(padapter, pattrib));242243SET_TX_DESC_RETRY_LIMIT_ENABLE_8814A(ptxdesc, 1);244SET_TX_DESC_DATA_RETRY_LIMIT_8814A(ptxdesc, 5);245SET_TX_DESC_DISABLE_FB_8814A(ptxdesc, 1);246247/* if(pattrib->rts_cca) */248/* { */249/* SET_TX_DESC_NDPA_8812(ptxdesc, 2); */250/* } */251/* else */252{253SET_TX_DESC_NDPA_8814A(ptxdesc, 1);254}255} else256#endif257{258SET_TX_DESC_RETRY_LIMIT_ENABLE_8814A(ptxdesc, 1);259if (pattrib->retry_ctrl == _TRUE)260SET_TX_DESC_DATA_RETRY_LIMIT_8814A(ptxdesc, 6);261else262SET_TX_DESC_DATA_RETRY_LIMIT_8814A(ptxdesc, 12);263}264265#ifdef CONFIG_XMIT_ACK266/* CCX-TXRPT ack for xmit mgmt frames. */267if (pxmitframe->ack_report) {268SET_TX_DESC_SPE_RPT_8814A(ptxdesc, 1);269#ifdef DBG_CCX270RTW_INFO("%s set tx report\n", __func__);271#endif272}273#endif /* CONFIG_XMIT_ACK */274} else if ((pxmitframe->frame_tag & 0x0f) == TXAGG_FRAMETAG)275RTW_INFO("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");276#ifdef CONFIG_MP_INCLUDED277else if (((pxmitframe->frame_tag & 0x0f) == MP_FRAMETAG) &&278(padapter->registrypriv.mp_mode == 1))279fill_txdesc_for_mp(padapter, ptxdesc);280#endif281else {282RTW_INFO("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);283284SET_TX_DESC_USE_RATE_8814A(ptxdesc, 1);285DriverFixedRate = 0x01;286SET_TX_DESC_TX_RATE_8814A(ptxdesc, MRateToHwRate(pmlmeext->tx_rate));287}288if (DriverFixedRate)289SWDefineContent |= 0x01;290SET_TX_DESC_SW_DEFINE_8814A(ptxdesc, SWDefineContent);291292#ifdef CONFIG_ANTENNA_DIVERSITY293if (!bmcst && pattrib->psta)294odm_set_tx_ant_by_tx_info(adapter_to_phydm(padapter), ptxdesc, pattrib->psta->cmn.mac_id);295#endif296297#ifdef CONFIG_BEAMFORMING298SET_TX_DESC_GID_8814A(ptxdesc, pattrib->txbf_g_id);299SET_TX_DESC_PAID_8814A(ptxdesc, pattrib->txbf_p_aid);300#endif301rtl8814a_cal_txdesc_chksum(ptxdesc);302_dbg_dump_tx_info(padapter, pxmitframe->frame_tag, ptxdesc);303return pull;304}305306307#ifdef CONFIG_XMIT_THREAD_MODE308/*309* Description310* Transmit xmitbuf to hardware tx fifo311*312* Return313* _SUCCESS ok314* _FAIL something error315*/316s32 rtl8814au_xmit_buf_handler(PADAPTER padapter)317{318PHAL_DATA_TYPE phal;319struct xmit_priv *pxmitpriv;320struct xmit_buf *pxmitbuf;321struct xmit_frame *pxmitframe;322s32 ret;323324325phal = GET_HAL_DATA(padapter);326pxmitpriv = &padapter->xmitpriv;327328ret = _rtw_down_sema(&pxmitpriv->xmit_sema);329if (_FAIL == ret) {330return _FAIL;331}332333if (RTW_CANNOT_RUN(padapter)) {334return _FAIL;335}336337if (rtw_mi_check_pending_xmitbuf(padapter) == 0)338return _SUCCESS;339340#ifdef CONFIG_LPS_LCLK341ret = rtw_register_tx_alive(padapter);342if (ret != _SUCCESS) {343return _SUCCESS;344}345#endif /* CONFIG_LPS_LCLK */346347do {348pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);349if (pxmitbuf == NULL)350break;351352pxmitframe = (struct xmit_frame *) pxmitbuf->priv_data;353rtw_write_port(padapter, pxmitbuf->ff_hwaddr, pxmitbuf->len, (unsigned char *)pxmitbuf);354rtw_free_xmitframe(pxmitpriv, pxmitframe);355356} while (1);357358#ifdef CONFIG_LPS_LCLK359rtw_unregister_tx_alive(padapter);360#endif /* CONFIG_LPS_LCLK */361362return _SUCCESS;363}364#endif /* CONFIG_XMIT_THREAD_MODE */365366367/* for non-agg data frame or management frame */368static s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe)369{370s32 ret = _SUCCESS;371s32 inner_ret = _SUCCESS;372int t, sz, w_sz, pull = 0;373u8 *mem_addr;374u32 ff_hwaddr;375struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;376struct pkt_attrib *pattrib = &pxmitframe->attrib;377struct xmit_priv *pxmitpriv = &padapter->xmitpriv;378struct security_priv *psecuritypriv = &padapter->securitypriv;379#ifdef CONFIG_80211N_HT380if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&381(pxmitframe->attrib.ether_type != 0x0806) &&382(pxmitframe->attrib.ether_type != 0x888e) &&383(pxmitframe->attrib.ether_type != 0x88b4) &&384(pxmitframe->attrib.dhcp_pkt != 1))385rtw_issue_addbareq_cmd(padapter, pxmitframe);386#endif /* CONFIG_80211N_HT */387mem_addr = pxmitframe->buf_addr;388389/* RTW_INFO("rtw_dump_xframe()\n"); */390391for (t = 0; t < pattrib->nr_frags; t++) {392if (inner_ret != _SUCCESS && ret == _SUCCESS)393ret = _FAIL;394395if (t != (pattrib->nr_frags - 1)) {396397sz = pxmitpriv->frag_len;398sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);399} else /* no frag */400sz = pattrib->last_txcmdsz;401402pull = update_txdesc(pxmitframe, mem_addr, sz, _FALSE);403404if (pull) {405mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */406407/* pxmitbuf->pbuf = mem_addr; */408pxmitframe->buf_addr = mem_addr;409410w_sz = sz + TXDESC_SIZE;411} else412w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;413414ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);415416#ifdef CONFIG_XMIT_THREAD_MODE417pxmitbuf->len = w_sz;418pxmitbuf->ff_hwaddr = ff_hwaddr;419420if (pxmitframe->attrib.qsel == QSLT_BEACON)421/* download rsvd page*/422rtw_write_port(padapter, ff_hwaddr, w_sz, (u8 *)pxmitbuf);423else424enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);425#else426inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);427#endif428rtw_count_tx_stats(padapter, pxmitframe, sz);429430/* RTW_INFO("rtw_write_port, w_sz=%d\n", w_sz); */431/* RTW_INFO("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority); */432433mem_addr += w_sz;434435mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr)));436437}438439#ifdef CONFIG_XMIT_THREAD_MODE440if (pxmitframe->attrib.qsel == QSLT_BEACON)441#endif442rtw_free_xmitframe(pxmitpriv, pxmitframe);443444if (ret != _SUCCESS)445rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);446447return ret;448}449450#ifdef CONFIG_USB_TX_AGGREGATION451#define IDEA_CONDITION 1 /* check all packets before enqueue */452s32 rtl8814au_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)453{454HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);455struct xmit_frame *pxmitframe = NULL;456struct xmit_frame *pfirstframe = NULL;457458/* aggregate variable */459struct hw_xmit *phwxmit;460struct sta_info *psta = NULL;461struct tx_servq *ptxservq = NULL;462463_irqL irqL;464_list *xmitframe_plist = NULL, *xmitframe_phead = NULL;465466u32 pbuf; /* next pkt address */467u32 pbuf_tail; /* last pkt tail */468u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */469470u32 bulkSize = pHalData->UsbBulkOutSize;471u8 descCount;472u32 bulkPtr;473474/* dump frame variable */475u32 ff_hwaddr;476477_list *sta_plist, *sta_phead;478u8 single_sta_in_queue = _FALSE;479480#ifndef IDEA_CONDITION481int res = _SUCCESS;482#endif483484485486/* check xmitbuffer is ok */487if (pxmitbuf == NULL) {488pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);489if (pxmitbuf == NULL) {490/* RTW_INFO("%s #1, connot alloc xmitbuf!!!!\n",__FUNCTION__); */491return _FALSE;492}493}494495/* RTW_INFO("%s =====================================\n",__FUNCTION__); */496/* 3 1. pick up first frame */497do {498rtw_free_xmitframe(pxmitpriv, pxmitframe);499500pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);501if (pxmitframe == NULL) {502/* no more xmit frame, release xmit buffer */503/* RTW_INFO("no more xmit frame ,return\n"); */504rtw_free_xmitbuf(pxmitpriv, pxmitbuf);505return _FALSE;506}507508#ifndef IDEA_CONDITION509if (pxmitframe->frame_tag != DATA_FRAMETAG) {510/* rtw_free_xmitframe(pxmitpriv, pxmitframe); */511continue;512}513514/* TID 0~15 */515if ((pxmitframe->attrib.priority < 0) ||516(pxmitframe->attrib.priority > 15)) {517/* rtw_free_xmitframe(pxmitpriv, pxmitframe); */518continue;519}520#endif521/* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */522pxmitframe->pxmitbuf = pxmitbuf;523pxmitframe->buf_addr = pxmitbuf->pbuf;524pxmitbuf->priv_data = pxmitframe;525526pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */527#ifdef CONFIG_TX_EARLY_MODE528pxmitframe->pkt_offset = (PACKET_OFFSET_SZ / 8) + 1; /* 2; */ /* first frame of aggregation, reserve one offset for EM info ,another for usb bulk-out block check */529#else530pxmitframe->pkt_offset = (PACKET_OFFSET_SZ / 8); /* 1; */ /* first frame of aggregation, reserve offset */531#endif532533if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) {534RTW_INFO("%s coalesce 1st xmitframe failed\n", __FUNCTION__);535continue;536}537538539/* always return ndis_packet after rtw_xmitframe_coalesce */540rtw_os_xmit_complete(padapter, pxmitframe);541542break;543} while (1);544545/* 3 2. aggregate same priority and same DA(AP or STA) frames */546pfirstframe = pxmitframe;547len = rtw_wlan_pkt_size(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);548pbuf_tail = len;549pbuf = _RND8(pbuf_tail);550551/* check pkt amount in one bulk */552descCount = 0;553bulkPtr = bulkSize;554if (pbuf < bulkPtr)555descCount++;556if (descCount == pHalData->UsbTxAggDescNum)557goto agg_end;558else {559descCount = 0;560bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; /* round to next bulkSize */561}562563/* dequeue same priority packet from station tx queue */564psta = pfirstframe->attrib.psta;565switch (pfirstframe->attrib.priority) {566case 1:567case 2:568ptxservq = &(psta->sta_xmitpriv.bk_q);569phwxmit = pxmitpriv->hwxmits + 3;570break;571572case 4:573case 5:574ptxservq = &(psta->sta_xmitpriv.vi_q);575phwxmit = pxmitpriv->hwxmits + 1;576break;577578case 6:579case 7:580ptxservq = &(psta->sta_xmitpriv.vo_q);581phwxmit = pxmitpriv->hwxmits;582break;583584case 0:585case 3:586default:587ptxservq = &(psta->sta_xmitpriv.be_q);588phwxmit = pxmitpriv->hwxmits + 2;589break;590}591/* RTW_INFO("==> pkt_no=%d,pkt_len=%d,len=%d,RND8_LEN=%d,pkt_offset=0x%02x\n", */592/* pxmitframe->agg_num,pxmitframe->attrib.last_txcmdsz,len,pbuf,pxmitframe->pkt_offset ); */593594595_enter_critical_bh(&pxmitpriv->lock, &irqL);596597sta_phead = get_list_head(phwxmit->sta_queue);598sta_plist = get_next(sta_phead);599single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));600601xmitframe_phead = get_list_head(&ptxservq->sta_pending);602xmitframe_plist = get_next(xmitframe_phead);603604while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) {605pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);606xmitframe_plist = get_next(xmitframe_plist);607608if (_FAIL == rtw_hal_busagg_qsel_check(padapter, pfirstframe->attrib.qsel, pxmitframe->attrib.qsel))609break;610611pxmitframe->agg_num = 0; /* not first frame of aggregation */612#ifdef CONFIG_TX_EARLY_MODE613pxmitframe->pkt_offset = 1;/* not first frame of aggregation,reserve offset for EM Info */614#else615pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */616#endif617618len = rtw_wlan_pkt_size(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);619620if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) {621/* RTW_INFO("%s....len> MAX_XMITBUF_SZ\n",__FUNCTION__); */622pxmitframe->agg_num = 1;623pxmitframe->pkt_offset = 1;624break;625}626rtw_list_delete(&pxmitframe->list);627ptxservq->qcnt--;628phwxmit->accnt--;629630#ifndef IDEA_CONDITION631/* suppose only data frames would be in queue */632if (pxmitframe->frame_tag != DATA_FRAMETAG) {633rtw_free_xmitframe(pxmitpriv, pxmitframe);634continue;635}636637/* TID 0~15 */638if ((pxmitframe->attrib.priority < 0) ||639(pxmitframe->attrib.priority > 15)) {640rtw_free_xmitframe(pxmitpriv, pxmitframe);641continue;642}643#endif644645/* pxmitframe->pxmitbuf = pxmitbuf; */646pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;647648if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) {649RTW_INFO("%s coalesce failed\n", __FUNCTION__);650rtw_free_xmitframe(pxmitpriv, pxmitframe);651continue;652}653654/* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */655/* always return ndis_packet after rtw_xmitframe_coalesce */656rtw_os_xmit_complete(padapter, pxmitframe);657658/* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */659update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, _TRUE);660661/* don't need xmitframe any more */662rtw_free_xmitframe(pxmitpriv, pxmitframe);663664/* handle pointer and stop condition */665pbuf_tail = pbuf + len;666pbuf = _RND8(pbuf_tail);667668669pfirstframe->agg_num++;670#ifdef CONFIG_TX_EARLY_MODE671pxmitpriv->agg_pkt[pfirstframe->agg_num - 1].offset = _RND8(len);672pxmitpriv->agg_pkt[pfirstframe->agg_num - 1].pkt_len = pxmitframe->attrib.last_txcmdsz;673#endif674if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)675break;676677if (pbuf < bulkPtr) {678descCount++;679if (descCount == pHalData->UsbTxAggDescNum)680break;681} else {682descCount = 0;683bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize;684}685} /* end while( aggregate same priority and same DA(AP or STA) frames) */686if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE)687rtw_list_delete(&ptxservq->tx_pending);688else if (single_sta_in_queue == _FALSE) {689/* Re-arrange the order of stations in this ac queue to balance the service for these stations */690rtw_list_delete(&ptxservq->tx_pending);691rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));692}693694_exit_critical_bh(&pxmitpriv->lock, &irqL);695agg_end:696#ifdef CONFIG_80211N_HT697if ((pfirstframe->attrib.ether_type != 0x0806) &&698(pfirstframe->attrib.ether_type != 0x888e) &&699(pfirstframe->attrib.ether_type != 0x88b4) &&700(pfirstframe->attrib.dhcp_pkt != 1))701rtw_issue_addbareq_cmd(padapter, pfirstframe);702#endif /* CONFIG_80211N_HT */703#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX704/* 3 3. update first frame txdesc */705if ((PACKET_OFFSET_SZ != 0) && ((pbuf_tail % bulkSize) == 0)) {706/* remove pkt_offset */707pbuf_tail -= PACKET_OFFSET_SZ;708pfirstframe->buf_addr += PACKET_OFFSET_SZ;709pfirstframe->pkt_offset--;710/* RTW_INFO("$$$$$ buf size equal to USB block size $$$$$$\n"); */711}712#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */713714update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, _TRUE);715716#ifdef CONFIG_TX_EARLY_MODE717/* prepare EM info for first frame, agg_num value start from 1 */718pxmitpriv->agg_pkt[0].offset = _RND8(pfirstframe->attrib.last_txcmdsz + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ));719pxmitpriv->agg_pkt[0].pkt_len = pfirstframe->attrib.last_txcmdsz;/* get from rtw_xmitframe_coalesce */720721UpdateEarlyModeInfo8812(pxmitpriv, pxmitbuf);722#endif723724/* 3 4. write xmit buffer to USB FIFO */725ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);726/* RTW_INFO("%s ===================================== write port,buf_size(%d)\n",__FUNCTION__,pbuf_tail); */727/* xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr */728729#ifdef CONFIG_XMIT_THREAD_MODE730pxmitbuf->len = pbuf_tail;731pxmitbuf->ff_hwaddr = ff_hwaddr;732733if (pfirstframe->attrib.qsel == QSLT_BEACON)734/* download rsvd page*/735rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);736else737enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);738#else739rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);740#endif741742743/* 3 5. update statisitc */744pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);745pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);746747748rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail);749750#ifdef CONFIG_XMIT_THREAD_MODE751if (pfirstframe->attrib.qsel == QSLT_BEACON)752#endif753rtw_free_xmitframe(pxmitpriv, pfirstframe);754755return _TRUE;756}757758#else /* CONFIG_USB_TX_AGGREGATION */759760s32 rtl8814au_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)761{762763struct hw_xmit *phwxmits;764sint hwentry;765struct xmit_frame *pxmitframe = NULL;766int res = _SUCCESS, xcnt = 0;767768phwxmits = pxmitpriv->hwxmits;769hwentry = pxmitpriv->hwxmit_entry;770771772if (pxmitbuf == NULL) {773pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);774if (!pxmitbuf)775return _FALSE;776}777778779do {780pxmitframe = rtw_dequeue_xframe(pxmitpriv, phwxmits, hwentry);781782if (pxmitframe) {783pxmitframe->pxmitbuf = pxmitbuf;784785pxmitframe->buf_addr = pxmitbuf->pbuf;786787pxmitbuf->priv_data = pxmitframe;788789if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {790if (pxmitframe->attrib.priority <= 15) /* TID0~15 */791res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);792/* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */793rtw_os_xmit_complete(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce */794}795796797798799if (res == _SUCCESS)800rtw_dump_xframe(padapter, pxmitframe);801else {802rtw_free_xmitbuf(pxmitpriv, pxmitbuf);803rtw_free_xmitframe(pxmitpriv, pxmitframe);804}805806xcnt++;807808} else {809rtw_free_xmitbuf(pxmitpriv, pxmitbuf);810return _FALSE;811}812813break;814815} while (0/*xcnt < (NR_XMITFRAME >> 3)*/);816817return _TRUE;818819}820#endif821822823824static s32 xmitframe_direct(_adapter *padapter, struct xmit_frame *pxmitframe)825{826s32 res = _SUCCESS;827/* RTW_INFO("==> %s\n",__FUNCTION__); */828829res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);830if (res == _SUCCESS)831rtw_dump_xframe(padapter, pxmitframe);832else833RTW_INFO("==> %s xmitframe_coalsece failed\n", __FUNCTION__);834835return res;836}837838/*839* Return840* _TRUE dump packet directly841* _FALSE enqueue packet842*/843static s32 pre_xmitframe(_adapter *padapter, struct xmit_frame *pxmitframe)844{845_irqL irqL;846s32 res;847struct xmit_buf *pxmitbuf = NULL;848struct xmit_priv *pxmitpriv = &padapter->xmitpriv;849struct pkt_attrib *pattrib = &pxmitframe->attrib;850struct mlme_priv *pmlmepriv = &padapter->mlmepriv;851852_enter_critical_bh(&pxmitpriv->lock, &irqL);853854if (rtw_txframes_sta_ac_pending(padapter, pattrib) > 0) {855/* RTW_INFO("enqueue AC(%d)\n",pattrib->priority); */856goto enqueue;857}858859if (rtw_xmit_ac_blocked(padapter) == _TRUE)860goto enqueue;861862if (DEV_STA_LG_NUM(padapter->dvobj))863goto enqueue;864865pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);866if (pxmitbuf == NULL)867goto enqueue;868869_exit_critical_bh(&pxmitpriv->lock, &irqL);870871pxmitframe->pxmitbuf = pxmitbuf;872pxmitframe->buf_addr = pxmitbuf->pbuf;873pxmitbuf->priv_data = pxmitframe;874875if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {876rtw_free_xmitbuf(pxmitpriv, pxmitbuf);877rtw_free_xmitframe(pxmitpriv, pxmitframe);878}879880return _TRUE;881882enqueue:883res = rtw_xmitframe_enqueue(padapter, pxmitframe);884_exit_critical_bh(&pxmitpriv->lock, &irqL);885886if (res != _SUCCESS) {887rtw_free_xmitframe(pxmitpriv, pxmitframe);888889pxmitpriv->tx_drop++;890return _TRUE;891}892893return _FALSE;894}895896s32 rtl8814au_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe)897{898return rtw_dump_xframe(padapter, pmgntframe);899}900901/*902* Return903* _TRUE dump packet directly ok904* _FALSE temporary can't transmit packets to hardware905*/906s32 rtl8814au_hal_xmit(_adapter *padapter, struct xmit_frame *pxmitframe)907{908return pre_xmitframe(padapter, pxmitframe);909}910911s32 rtl8814au_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)912{913struct xmit_priv *pxmitpriv = &padapter->xmitpriv;914s32 err;915916err = rtw_xmitframe_enqueue(padapter, pxmitframe);917if (err != _SUCCESS) {918rtw_free_xmitframe(pxmitpriv, pxmitframe);919920pxmitpriv->tx_drop++;921} else {922#ifdef PLATFORM_LINUX923tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);924#endif925}926927return err;928929}930931932#ifdef CONFIG_HOSTAPD_MLME933934static void rtl8814au_hostap_mgnt_xmit_cb(struct urb *urb)935{936#ifdef PLATFORM_LINUX937struct sk_buff *skb = (struct sk_buff *)urb->context;938939/* RTW_INFO("%s\n", __FUNCTION__); */940941rtw_skb_free(skb);942#endif943}944945s32 rtl8814au_hostap_mgnt_xmit_entry(_adapter *padapter, _pkt *pkt)946{947#ifdef PLATFORM_LINUX948u16 fc;949int rc, len, pipe;950unsigned int bmcst, tid, qsel;951struct sk_buff *skb, *pxmit_skb;952struct urb *urb;953unsigned char *pxmitbuf;954struct tx_desc *ptxdesc;955struct rtw_ieee80211_hdr *tx_hdr;956struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;957struct net_device *pnetdev = padapter->pnetdev;958HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);959struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);960961962/* RTW_INFO("%s\n", __FUNCTION__); */963964skb = pkt;965966len = skb->len;967tx_hdr = (struct rtw_ieee80211_hdr *)(skb->data);968fc = le16_to_cpu(tx_hdr->frame_ctl);969bmcst = IS_MCAST(tx_hdr->addr1);970971if ((fc & RTW_IEEE80211_FCTL_FTYPE) != RTW_IEEE80211_FTYPE_MGMT)972goto _exit;973974pxmit_skb = rtw_skb_alloc(len + TXDESC_SIZE);975976if (!pxmit_skb)977goto _exit;978979pxmitbuf = pxmit_skb->data;980981urb = usb_alloc_urb(0, GFP_ATOMIC);982if (!urb)983goto _exit;984985/* ----- fill tx desc ----- */986ptxdesc = (struct tx_desc *)pxmitbuf;987_rtw_memset(ptxdesc, 0, sizeof(*ptxdesc));988989/* offset 0 */990ptxdesc->txdw0 |= cpu_to_le32(len & 0x0000ffff);991ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00ff0000); /* default = 32 bytes for TX Desc */992ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);993994if (bmcst)995ptxdesc->txdw0 |= cpu_to_le32(BIT(24));996997/* offset 4 */998ptxdesc->txdw1 |= cpu_to_le32(0x00);/* MAC_ID */9991000ptxdesc->txdw1 |= cpu_to_le32((0x12 << QSEL_SHT) & 0x00001f00);10011002ptxdesc->txdw1 |= cpu_to_le32((0x06 << 16) & 0x000f0000); /* b mode */10031004/* offset 8 */10051006/* offset 12 */1007ptxdesc->txdw3 |= cpu_to_le32((le16_to_cpu(tx_hdr->seq_ctl) << 16) & 0xffff0000);10081009/* offset 16 */1010ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */10111012/* offset 20 */101310141015/* HW append seq */1016ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */1017ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */101810191020rtl8188eu_cal_txdesc_chksum(ptxdesc);1021/* ----- end of fill tx desc ----- */10221023/* */1024skb_put(pxmit_skb, len + TXDESC_SIZE);1025pxmitbuf = pxmitbuf + TXDESC_SIZE;1026_rtw_memcpy(pxmitbuf, skb->data, len);10271028/* RTW_INFO("mgnt_xmit, len=%x\n", pxmit_skb->len); */102910301031/* ----- prepare urb for submit ----- */10321033/* translate DMA FIFO addr to pipehandle */1034/* pipe = ffaddr2pipehdl(pdvobj, MGT_QUEUE_INX); */1035pipe = usb_sndbulkpipe(pdvobj->pusbdev, pHalData->Queue2EPNum[(u8)MGT_QUEUE_INX] & 0x0f);10361037usb_fill_bulk_urb(urb, pdvobj->pusbdev, pipe,1038pxmit_skb->data, pxmit_skb->len, rtl8192cu_hostap_mgnt_xmit_cb, pxmit_skb);10391040urb->transfer_flags |= URB_ZERO_PACKET;1041usb_anchor_urb(urb, &phostapdpriv->anchored);1042rc = usb_submit_urb(urb, GFP_ATOMIC);1043if (rc < 0) {1044usb_unanchor_urb(urb);1045kfree_skb(skb);1046}1047usb_free_urb(urb);104810491050_exit:10511052rtw_skb_free(skb);10531054#endif10551056return 0;10571058}1059#endif106010611062