diff options
Diffstat (limited to 'drivers/staging/rtl8723au/hal/rtl8723au_xmit.c')
-rw-r--r-- | drivers/staging/rtl8723au/hal/rtl8723au_xmit.c | 520 |
1 files changed, 0 insertions, 520 deletions
diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c deleted file mode 100644 index 14746dd8db78..000000000000 --- a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c +++ /dev/null @@ -1,520 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8192C_XMIT_C_ -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> -#include <usb_ops.h> -/* include <rtl8192c_hal.h> */ -#include <rtl8723a_hal.h> - -static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz) -{ - int blnSetTxDescOffset; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - - if (pdvobj->ishighspeed) { - if (((sz + TXDESC_SIZE) % 512) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } else { - if (((sz + TXDESC_SIZE) % 64) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } - return blnSetTxDescOffset; -} - -static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - __le16 *usPtr = (__le16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0 ; index < count ; index++) - checksum = checksum ^ le16_to_cpu(*(usPtr + index)); - - ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum); -} - -static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) -{ - if ((pattrib->encrypt > 0) && !pattrib->bswenc) { - switch (pattrib->encrypt) { - /* SEC_TYPE */ - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_TKIP: - /* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */ - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_CCMP: - ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000); - break; - case 0: - default: - break; - } - } -} - -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) -{ - /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */ - - switch (pattrib->vcs_mode) { - case RTS_CTS: - *pdw |= cpu_to_le32(BIT(12)); - break; - case CTS_TO_SELF: - *pdw |= cpu_to_le32(BIT(11)); - break; - case NONE_VCS: - default: - break; - } - - if (pattrib->vcs_mode) { - *pdw |= cpu_to_le32(BIT(13)); - - /* Set RTS BW */ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<28)&0x30000000); - } - } -} - -static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) -{ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<20)&0x003f0000); - } -} - -static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz) -{ - int pull = 0; - uint qsel; - struct rtw_adapter *padapter = pxmitframe->padapter; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct tx_desc *ptxdesc = (struct tx_desc *)pmem; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (urb_zero_packet_chk(padapter, sz) == 0) { - ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ); - pull = 1; - pxmitframe->pkt_offset--; - } - - memset(ptxdesc, 0, sizeof(struct tx_desc)); - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - fill_txdesc_sectype(pattrib, ptxdesc); - - if (pattrib->ampdu_en) - ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */ - else - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 , offset 20 */ - if (pattrib->qos_en) - ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */ - - if ((pattrib->ether_type != 0x888e) && - (pattrib->ether_type != 0x0806) && - (pattrib->dhcp_pkt != 1)) { - /* Non EAP & ARP & DHCP type data packet */ - - fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); - fill_txdesc_phy(pattrib, &ptxdesc->txdw4); - - ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */ - ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* */ - - /* use REG_INIDATA_RATE_SEL value */ - ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]); - } else { - /* EAP data packet and ARP packet. */ - /* Use the 1M data rate to send the EAP/ARP packet. */ - /* This will maybe make the handshake smooth. */ - - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) - ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel&0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - /* offset 8 */ - /* CCX-TXRPT ack for xmit mgmt frames. */ - if (pxmitframe->ack_report) - ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */ - ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { - DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); - } else { - DBG_8723A("pxmitframe->frame_tag = %d\n", - pxmitframe->frame_tag); - - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */ - - ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - - /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controlled by Hw because Fw will also send null data */ - /* which we cannot control when Fw LPS enable. */ - /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ - /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ - /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ - if (!pattrib->qos_en) { - /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); - /* set bit3 to 1. */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); - } - - /* offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */ - - if (bmcst) - ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "offset0-txdesc = 0x%x\n", ptxdesc->txdw0); - - /* offset 4 */ - /* pkt_offset, unit:8 bytes padding */ - if (pxmitframe->pkt_offset > 0) - ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); - - rtl8192cu_cal_txdesc_chksum(ptxdesc); - return pull; -} - -static int rtw_dump_xframe(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int ret = _SUCCESS; - int inner_ret = _SUCCESS; - int t, sz, w_sz, pull = 0; - u8 *mem_addr; - u32 ff_hwaddr; - struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG && - pxmitframe->attrib.ether_type != ETH_P_ARP && - pxmitframe->attrib.ether_type != ETH_P_PAE && - pxmitframe->attrib.dhcp_pkt != 1) - rtw_issue_addbareq_cmd23a(padapter, pxmitframe); - - mem_addr = pxmitframe->buf_addr; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "rtw_dump_xframe()\n"); - - for (t = 0; t < pattrib->nr_frags; t++) { - if (inner_ret != _SUCCESS && ret == _SUCCESS) - ret = _FAIL; - - if (t != (pattrib->nr_frags - 1)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "pattrib->nr_frags =%d\n", pattrib->nr_frags); - - sz = pxmitpriv->frag_len; - sz = sz - 4 - pattrib->icv_len; - } else { - /* no frag */ - sz = pattrib->last_txcmdsz; - } - - pull = update_txdesc(pxmitframe, mem_addr, sz); - - if (pull) { - mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */ - - pxmitframe->buf_addr = mem_addr; - - w_sz = sz + TXDESC_SIZE; - } else { - w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ; - } - - ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe); - inner_ret = rtl8723au_write_port(padapter, ff_hwaddr, - w_sz, pxmitbuf); - rtw_count_tx_stats23a(padapter, pxmitframe, sz); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_write_port, w_sz =%d\n", w_sz); - - mem_addr += w_sz; - - mem_addr = PTR_ALIGN(mem_addr, 4); - } - - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - if (ret != _SUCCESS) - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); - - return ret; -} - -bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - struct hw_xmit *phwxmits; - struct xmit_frame *pxmitframe; - int hwentry; - int res = _SUCCESS, xcnt = 0; - - phwxmits = pxmitpriv->hwxmits; - hwentry = pxmitpriv->hwxmit_entry; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "xmitframe_complete()\n"); - - if (pxmitbuf == NULL) { - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (!pxmitbuf) - return false; - } - pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry); - - if (pxmitframe) { - pxmitframe->pxmitbuf = pxmitbuf; - - pxmitframe->buf_addr = pxmitbuf->pbuf; - - pxmitbuf->priv_data = pxmitframe; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - if (pxmitframe->attrib.priority <= 15)/* TID0~15 */ - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - - rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */ - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "xmitframe_complete(): rtw_dump_xframe\n"); - - if (res == _SUCCESS) { - rtw_dump_xframe(padapter, pxmitframe); - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - xcnt++; - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - return false; - } - return true; -} - -static int xmitframe_direct(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(padapter, pxmitframe); - return res; -} - -/* - * Return - * true dump packet directly - * false enqueue packet - */ -bool rtl8723au_hal_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - struct xmit_buf *pxmitbuf = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pattrib->qsel = pattrib->priority; - spin_lock_bh(&pxmitpriv->lock); - -#ifdef CONFIG_8723AU_AP_MODE - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_unlock_bh(&pxmitpriv->lock); - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - - if (psta) { - if (psta->sleepq_len > (NR_XMITFRAME>>3)) - wakeup_sta_to_xmit23a(padapter, psta); - } - - return false; - } -#endif - - if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0) - goto enqueue; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) - goto enqueue; - - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (pxmitbuf == NULL) - goto enqueue; - - spin_unlock_bh(&pxmitpriv->lock); - - pxmitframe->pxmitbuf = pxmitbuf; - pxmitframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pxmitframe; - - if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - return true; - -enqueue: - res = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - spin_unlock_bh(&pxmitpriv->lock); - - if (res != _SUCCESS) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "pre_xmitframe: enqueue xmitframe fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - return true; - } - return false; -} - -int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - return rtw_dump_xframe(padapter, pmgntframe); -} - -int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int err; - - err = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - if (err != _SUCCESS) { - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - } else { - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - } - return err; -} |