300 lines
8.5 KiB
C
300 lines
8.5 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2007 - 2017 Realtek Corporation.
|
|
*
|
|
* 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 _RTL8188E_XMIT_C_
|
|
|
|
#include <drv_types.h>
|
|
#include <rtl8188e_hal.h>
|
|
|
|
#ifdef CONFIG_XMIT_ACK
|
|
void dump_txrpt_ccx_88e(void *buf)
|
|
{
|
|
struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf;
|
|
|
|
RTW_INFO("%s:\n"
|
|
"tag1:%u, pkt_num:%u, txdma_underflow:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
|
|
"mac_id:%u, pkt_ok:%u, bmc:%u\n"
|
|
"retry_cnt:%u, lifetime_over:%u, retry_over:%u\n"
|
|
"ccx_qtime:%u\n"
|
|
"final_data_rate:0x%02x\n"
|
|
"qsel:%u, sw:0x%03x\n"
|
|
, __func__
|
|
, txrpt_ccx->tag1, txrpt_ccx->pkt_num, txrpt_ccx->txdma_underflow, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx
|
|
, txrpt_ccx->mac_id, txrpt_ccx->pkt_ok, txrpt_ccx->bmc
|
|
, txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over
|
|
, txrpt_ccx_qtime_88e(txrpt_ccx)
|
|
, txrpt_ccx->final_data_rate
|
|
, txrpt_ccx->qsel, txrpt_ccx_sw_88e(txrpt_ccx)
|
|
);
|
|
}
|
|
|
|
void handle_txrpt_ccx_88e(_adapter *adapter, u8 *buf)
|
|
{
|
|
struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf;
|
|
|
|
#ifdef DBG_CCX
|
|
dump_txrpt_ccx_88e(buf);
|
|
#endif
|
|
|
|
if (txrpt_ccx->int_ccx) {
|
|
if (txrpt_ccx->pkt_ok)
|
|
rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
|
|
else
|
|
rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
|
|
}
|
|
}
|
|
#endif /* CONFIG_XMIT_ACK */
|
|
|
|
void _dbg_dump_tx_info(_adapter *padapter, int frame_tag, struct tx_desc *ptxdesc)
|
|
{
|
|
u8 bDumpTxPkt;
|
|
u8 bDumpTxDesc = _FALSE;
|
|
rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(bDumpTxPkt));
|
|
|
|
if (bDumpTxPkt == 1) { /* dump txdesc for data frame */
|
|
RTW_INFO("dump tx_desc for data frame\n");
|
|
if ((frame_tag & 0x0f) == DATA_FRAMETAG)
|
|
bDumpTxDesc = _TRUE;
|
|
} else if (bDumpTxPkt == 2) { /* dump txdesc for mgnt frame */
|
|
RTW_INFO("dump tx_desc for mgnt frame\n");
|
|
if ((frame_tag & 0x0f) == MGNT_FRAMETAG)
|
|
bDumpTxDesc = _TRUE;
|
|
} else if (bDumpTxPkt == 3) { /* dump early info */
|
|
}
|
|
|
|
if (bDumpTxDesc) {
|
|
/* ptxdesc->txdw4 = cpu_to_le32(0x00001006); */ /* RTS Rate=24M */
|
|
/* ptxdesc->txdw6 = 0x6666f800; */
|
|
RTW_INFO("=====================================\n");
|
|
RTW_INFO("txdw0(0x%08x)\n", ptxdesc->txdw0);
|
|
RTW_INFO("txdw1(0x%08x)\n", ptxdesc->txdw1);
|
|
RTW_INFO("txdw2(0x%08x)\n", ptxdesc->txdw2);
|
|
RTW_INFO("txdw3(0x%08x)\n", ptxdesc->txdw3);
|
|
RTW_INFO("txdw4(0x%08x)\n", ptxdesc->txdw4);
|
|
RTW_INFO("txdw5(0x%08x)\n", ptxdesc->txdw5);
|
|
RTW_INFO("txdw6(0x%08x)\n", ptxdesc->txdw6);
|
|
RTW_INFO("txdw7(0x%08x)\n", ptxdesc->txdw7);
|
|
RTW_INFO("=====================================\n");
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Description:
|
|
* Aggregation packets and send to hardware
|
|
*
|
|
* Return:
|
|
* 0 Success
|
|
* -1 Hardware resource(TX FIFO) not ready
|
|
* -2 Software resource(xmitbuf) not ready
|
|
*/
|
|
#ifdef CONFIG_TX_EARLY_MODE
|
|
|
|
/* #define DBG_EMINFO */
|
|
|
|
#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
|
|
#define EARLY_MODE_MAX_PKT_NUM 10
|
|
#else
|
|
#define EARLY_MODE_MAX_PKT_NUM 5
|
|
#endif
|
|
|
|
|
|
struct EMInfo {
|
|
u8 EMPktNum;
|
|
u16 EMPktLen[EARLY_MODE_MAX_PKT_NUM];
|
|
};
|
|
|
|
|
|
void
|
|
InsertEMContent_8188E(
|
|
struct EMInfo *pEMInfo,
|
|
u8 *VirtualAddress)
|
|
{
|
|
|
|
#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
|
|
u8 index = 0;
|
|
u32 dwtmp = 0;
|
|
#endif
|
|
|
|
_rtw_memset(VirtualAddress, 0, EARLY_MODE_INFO_SIZE);
|
|
if (pEMInfo->EMPktNum == 0)
|
|
return;
|
|
|
|
#ifdef DBG_EMINFO
|
|
{
|
|
int i;
|
|
RTW_INFO("\n%s ==> pEMInfo->EMPktNum =%d\n", __FUNCTION__, pEMInfo->EMPktNum);
|
|
for (i = 0; i < EARLY_MODE_MAX_PKT_NUM; i++)
|
|
RTW_INFO("%s ==> pEMInfo->EMPktLen[%d] =%d\n", __FUNCTION__, i, pEMInfo->EMPktLen[i]);
|
|
|
|
}
|
|
#endif
|
|
|
|
#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1
|
|
SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);
|
|
|
|
if (pEMInfo->EMPktNum == 1)
|
|
dwtmp = pEMInfo->EMPktLen[0];
|
|
else {
|
|
dwtmp = pEMInfo->EMPktLen[0];
|
|
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
|
|
dwtmp += pEMInfo->EMPktLen[1];
|
|
}
|
|
SET_EARLYMODE_LEN0(VirtualAddress, dwtmp);
|
|
if (pEMInfo->EMPktNum <= 3)
|
|
dwtmp = pEMInfo->EMPktLen[2];
|
|
else {
|
|
dwtmp = pEMInfo->EMPktLen[2];
|
|
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
|
|
dwtmp += pEMInfo->EMPktLen[3];
|
|
}
|
|
SET_EARLYMODE_LEN1(VirtualAddress, dwtmp);
|
|
if (pEMInfo->EMPktNum <= 5)
|
|
dwtmp = pEMInfo->EMPktLen[4];
|
|
else {
|
|
dwtmp = pEMInfo->EMPktLen[4];
|
|
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
|
|
dwtmp += pEMInfo->EMPktLen[5];
|
|
}
|
|
SET_EARLYMODE_LEN2_1(VirtualAddress, dwtmp & 0xF);
|
|
SET_EARLYMODE_LEN2_2(VirtualAddress, dwtmp >> 4);
|
|
if (pEMInfo->EMPktNum <= 7)
|
|
dwtmp = pEMInfo->EMPktLen[6];
|
|
else {
|
|
dwtmp = pEMInfo->EMPktLen[6];
|
|
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
|
|
dwtmp += pEMInfo->EMPktLen[7];
|
|
}
|
|
SET_EARLYMODE_LEN3(VirtualAddress, dwtmp);
|
|
if (pEMInfo->EMPktNum <= 9)
|
|
dwtmp = pEMInfo->EMPktLen[8];
|
|
else {
|
|
dwtmp = pEMInfo->EMPktLen[8];
|
|
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
|
|
dwtmp += pEMInfo->EMPktLen[9];
|
|
}
|
|
SET_EARLYMODE_LEN4(VirtualAddress, dwtmp);
|
|
#else
|
|
SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum);
|
|
SET_EARLYMODE_LEN0(VirtualAddress, pEMInfo->EMPktLen[0]);
|
|
SET_EARLYMODE_LEN1(VirtualAddress, pEMInfo->EMPktLen[1]);
|
|
SET_EARLYMODE_LEN2_1(VirtualAddress, pEMInfo->EMPktLen[2] & 0xF);
|
|
SET_EARLYMODE_LEN2_2(VirtualAddress, pEMInfo->EMPktLen[2] >> 4);
|
|
SET_EARLYMODE_LEN3(VirtualAddress, pEMInfo->EMPktLen[3]);
|
|
SET_EARLYMODE_LEN4(VirtualAddress, pEMInfo->EMPktLen[4]);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateEarlyModeInfo8188E(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
|
|
{
|
|
/* _adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq */
|
|
int index, j;
|
|
u16 offset, pktlen;
|
|
PTXDESC_8188E ptxdesc;
|
|
|
|
u8 *pmem, *pEMInfo_mem;
|
|
s8 node_num_0 = 0, node_num_1 = 0;
|
|
struct EMInfo eminfo;
|
|
struct agg_pkt_info *paggpkt;
|
|
struct xmit_frame *pframe = (struct xmit_frame *)pxmitbuf->priv_data;
|
|
pmem = pframe->buf_addr;
|
|
|
|
#ifdef DBG_EMINFO
|
|
RTW_INFO("\n%s ==> agg_num:%d\n", __FUNCTION__, pframe->agg_num);
|
|
for (index = 0; index < pframe->agg_num; index++) {
|
|
offset = pxmitpriv->agg_pkt[index].offset;
|
|
pktlen = pxmitpriv->agg_pkt[index].pkt_len;
|
|
RTW_INFO("%s ==> agg_pkt[%d].offset=%d\n", __FUNCTION__, index, offset);
|
|
RTW_INFO("%s ==> agg_pkt[%d].pkt_len=%d\n", __FUNCTION__, index, pktlen);
|
|
}
|
|
#endif
|
|
|
|
if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {
|
|
node_num_0 = pframe->agg_num;
|
|
node_num_1 = EARLY_MODE_MAX_PKT_NUM - 1;
|
|
}
|
|
|
|
for (index = 0; index < pframe->agg_num; index++) {
|
|
|
|
offset = pxmitpriv->agg_pkt[index].offset;
|
|
pktlen = pxmitpriv->agg_pkt[index].pkt_len;
|
|
|
|
_rtw_memset(&eminfo, 0, sizeof(struct EMInfo));
|
|
if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) {
|
|
if (node_num_0 > EARLY_MODE_MAX_PKT_NUM) {
|
|
eminfo.EMPktNum = EARLY_MODE_MAX_PKT_NUM;
|
|
node_num_0--;
|
|
} else {
|
|
eminfo.EMPktNum = node_num_1;
|
|
node_num_1--;
|
|
}
|
|
} else
|
|
eminfo.EMPktNum = pframe->agg_num - (index + 1);
|
|
for (j = 0; j < eminfo.EMPktNum ; j++) {
|
|
eminfo.EMPktLen[j] = pxmitpriv->agg_pkt[index + 1 + j].pkt_len + 4; /* 4 bytes CRC */
|
|
}
|
|
|
|
if (pmem) {
|
|
if (index == 0) {
|
|
ptxdesc = (PTXDESC_8188E)(pmem);
|
|
pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;
|
|
} else {
|
|
pmem = pmem + pxmitpriv->agg_pkt[index - 1].offset;
|
|
ptxdesc = (PTXDESC_8188E)(pmem);
|
|
pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE;
|
|
}
|
|
|
|
#ifdef DBG_EMINFO
|
|
RTW_INFO("%s ==> desc.pkt_len=%d\n", __FUNCTION__, ptxdesc->pktlen);
|
|
#endif
|
|
InsertEMContent_8188E(&eminfo, pEMInfo_mem);
|
|
}
|
|
|
|
|
|
}
|
|
_rtw_memset(pxmitpriv->agg_pkt, 0, sizeof(struct agg_pkt_info) * MAX_AGG_PKT_NUM);
|
|
|
|
}
|
|
#endif
|
|
|
|
void fill_txdesc_force_bmc_camid(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
|
|
{
|
|
if ((pattrib->encrypt > 0) && (!pattrib->bswenc)
|
|
&& (pattrib->bmc_camid != INVALID_SEC_MAC_CAM_ID)) {
|
|
|
|
ptxdesc->txdw1 |= cpu_to_le32((0x01 << 21) & 0x00200000);
|
|
ptxdesc->txdw1 |= cpu_to_le32((pattrib->bmc_camid) & 0x1f);
|
|
}
|
|
}
|
|
|
|
void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc)
|
|
{
|
|
u16 *usPtr = (u16 *)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 ^= le16_to_cpu(*(usPtr + index));
|
|
|
|
ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
|
|
}
|