/******************************************************************************
|
*
|
* Copyright(c) 2019 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.
|
*
|
******************************************************************************/
|
|
#include "trx_desc.h"
|
|
#define RXD_RPKT_TYPE_INVALID 0xFF
|
#define TXD_AC_TYPE_MSK 0x3
|
#define TXD_TID_IND_SH 2
|
#define TID_MAX_NUM 8
|
|
#define TID_0_QSEL 0
|
#define TID_1_QSEL 1
|
#define TID_2_QSEL 1
|
#define TID_3_QSEL 0
|
#define TID_4_QSEL 2
|
#define TID_5_QSEL 2
|
#define TID_6_QSEL 3
|
#define TID_7_QSEL 3
|
#define TID_0_IND 0
|
#define TID_1_IND 0
|
#define TID_2_IND 1
|
#define TID_3_IND 1
|
#define TID_4_IND 0
|
#define TID_5_IND 1
|
#define TID_6_IND 0
|
#define TID_7_IND 1
|
|
enum wd_info_pkt_type {
|
WD_INFO_PKT_NORMAL,
|
|
/* keep last */
|
WD_INFO_PKT_LAST,
|
WD_INFO_PKT_MAX = WD_INFO_PKT_LAST,
|
};
|
|
static u8 qsel_l[TID_MAX_NUM] = {
|
TID_0_QSEL, TID_1_QSEL, TID_2_QSEL, TID_3_QSEL,
|
TID_4_QSEL, TID_5_QSEL, TID_6_QSEL, TID_7_QSEL
|
};
|
|
static u8 tid_ind[TID_MAX_NUM] = {
|
TID_0_IND, TID_1_IND, TID_2_IND, TID_3_IND,
|
TID_4_IND, TID_5_IND, TID_6_IND, TID_7_IND
|
};
|
|
u32 mac_txdesc_len(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info)
|
{
|
u32 len;
|
enum rtw_packet_type pkt_type = info->type;
|
|
len = WD_BODY_LEN;
|
|
if (pkt_type != RTW_PHL_PKT_TYPE_H2C &&
|
pkt_type != RTW_PHL_PKT_TYPE_FWDL &&
|
info->wdinfo_en != 0)
|
len += WD_INFO_LEN;
|
|
return len;
|
}
|
|
static u32 txdes_proc_h2c_fwdl(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *buf, u32 len)
|
{
|
struct wd_body_t *wdb;
|
|
if (len != mac_txdesc_len(adapter, info)) {
|
PLTFM_MSG_ERR("[ERR] illegal len %d\n", len);
|
return MACBUFSZ;
|
}
|
|
if (info->pktlen > AX_TXD_TXPKTSIZE_MSK || !info->pktlen) {
|
PLTFM_MSG_ERR("[ERR] illegal txpktsize %d\n", info->pktlen);
|
return MACFUNCINPUT;
|
}
|
|
wdb = (struct wd_body_t *)buf;
|
wdb->dword0 = cpu_to_le32(SET_WORD(MAC_AX_DMA_H2C, AX_TXD_CH_DMA) |
|
(info->type == RTW_PHL_PKT_TYPE_FWDL ? AX_TXD_FWDL_EN : 0));
|
wdb->dword1 = 0;
|
wdb->dword2 = cpu_to_le32(SET_WORD(info->pktlen, AX_TXD_TXPKTSIZE));
|
wdb->dword3 = 0;
|
wdb->dword4 = 0;
|
wdb->dword5 = 0;
|
|
return MACSUCCESS;
|
}
|
|
#if MAC_AX_FEATURE_HV
|
static u32 txdes_proc_hv(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info,
|
struct wd_body_t *wdb,
|
struct wd_info_t *wdi)
|
{
|
struct hv_txpkt_info *hv_info = (struct hv_txpkt_info *)info->mac_priv;
|
|
wdb->dword0 |= cpu_to_le32((hv_info->chk_en ? AX_TXD_CHK_EN : 0));
|
wdi->dword3 |= cpu_to_le32((hv_info->null_1 ? AX_TXD_NULL_1 : 0) |
|
(hv_info->null_0 ? AX_TXD_NULL_0 : 0) |
|
(hv_info->tri_frame ? AX_TXD_TRI_FRAME : 0) |
|
(hv_info->ht_data_snd ? AX_TXD_HT_DATA_SND : 0));
|
wdi->dword5 |= cpu_to_le32(SET_WORD(hv_info->ndpa_dur, AX_TXD_NDPA_DURATION));
|
|
return MACSUCCESS;
|
}
|
#endif
|
|
static u32 txdes_proc_data(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *buf, u32 len)
|
{
|
struct wd_body_t *wdb;
|
struct wd_info_t *wdi;
|
u8 wd_info_tmpl[WD_INFO_PKT_MAX][24] = {{0}};
|
u32 ret;
|
u8 ch, qsel;
|
|
if (len != mac_txdesc_len(adapter, info)) {
|
PLTFM_MSG_ERR("[ERR] illegal len %d\n", len);
|
return MACBUFSZ;
|
}
|
|
if (info->dma_ch > MAC_AX_DATA_HIQ) {
|
PLTFM_MSG_ERR("[ERR] txd ch %d illegal\n", info->dma_ch);
|
return MACTXCHDMA;
|
}
|
|
if (info->pktlen > AX_TXD_TXPKTSIZE_MSK || !info->pktlen) {
|
PLTFM_MSG_ERR("[ERR] illegal txpktsize %d\n", info->pktlen);
|
return MACFUNCINPUT;
|
}
|
|
wdb = (struct wd_body_t *)buf;
|
if (adapter->hw_info->intf == MAC_AX_INTF_SDIO) {
|
wdb->dword0 =
|
cpu_to_le32(AX_TXD_STF_MODE);
|
} else if (adapter->hw_info->intf == MAC_AX_INTF_USB) {
|
wdb->dword0 =
|
cpu_to_le32(AX_TXD_STF_MODE |
|
(info->usb_pkt_ofst ?
|
AX_TXD_PKT_OFFSET : 0));
|
} else if (adapter->hw_info->intf == MAC_AX_INTF_PCIE) {
|
wdb->dword0 =
|
cpu_to_le32((info->wd_page_size ? AX_TXD_WD_PAGE : 0) |
|
(adapter->dle_info.qta_mode ==
|
MAC_AX_QTA_SCC_STF ||
|
adapter->dle_info.qta_mode ==
|
MAC_AX_QTA_DBCC_STF ?
|
AX_TXD_STF_MODE : 0));
|
} else {
|
PLTFM_MSG_ERR("[ERR] unknown intf %d\n",
|
adapter->hw_info->intf);
|
return MACINTF;
|
}
|
|
if (info->dma_ch == MAC_AX_DATA_HIQ &&
|
adapter->hw_info->intf == MAC_AX_INTF_USB)
|
ch = info->band ? MAC_AX_DMA_B1MG : MAC_AX_DMA_B0MG;
|
else if (info->dma_ch == MAC_AX_DATA_HIQ)
|
ch = info->band ? MAC_AX_DMA_B1HI : MAC_AX_DMA_B0HI;
|
else
|
ch = info->dma_ch;
|
|
wdb->dword0 |=
|
cpu_to_le32(SET_WORD(info->hw_seq_mode,
|
AX_TXD_EN_HWSEQ_MODE) |
|
SET_WORD(info->hw_ssn_sel,
|
AX_TXD_HW_SSN_SEL) |
|
SET_WORD(info->hdr_len,
|
AX_TXD_HDR_LLC_LEN) |
|
SET_WORD(ch, AX_TXD_CH_DMA) |
|
(info->hw_amsdu ? AX_TXD_HWAMSDU : 0) |
|
(info->smh_en ? AX_TXD_SMH_EN : 0) |
|
(info->hw_sec_iv ? AX_TXD_HW_AES_IV : 0) |
|
(info->wdinfo_en ? AX_TXD_WDINFO_EN : 0) |
|
SET_WORD(info->wp_offset,
|
AX_TXD_WP_OFFSET));
|
wdb->dword1 =
|
cpu_to_le32(SET_WORD(info->shcut_camid, AX_TXD_SHCUT_CAMID));
|
/* Get bb and qsel from qsel by according MAC ID */
|
if (info->dma_ch == MAC_AX_DATA_HIQ)
|
qsel = info->band ? MAC_AX_HI1_SEL : MAC_AX_HI0_SEL;
|
else
|
qsel = (info->band << 3) | (info->wmm << 2) | qsel_l[info->tid];
|
wdb->dword2 =
|
cpu_to_le32(SET_WORD(info->pktlen, AX_TXD_TXPKTSIZE) |
|
SET_WORD(qsel, AX_TXD_QSEL) |
|
(tid_ind[info->tid] ? AX_TXD_TID_IND : 0) |
|
SET_WORD(info->macid, AX_TXD_MACID));
|
|
wdb->dword3 = cpu_to_le32(SET_WORD(info->sw_seq,
|
AX_TXD_WIFI_SEQ) |
|
(info->ampdu_en ? AX_TXD_AGG_EN : 0) |
|
((info->bk || info->ack_ch_info) ?
|
AX_TXD_BK : 0));
|
wdb->dword4 = 0;
|
wdb->dword5 = 0;
|
|
wdi = (struct wd_info_t *)wd_info_tmpl[WD_INFO_PKT_NORMAL];
|
wdi->dword0 =
|
cpu_to_le32((info->userate_sel ? AX_TXD_USERATE_SEL : 0) |
|
SET_WORD(info->f_rate, AX_TXD_DATARATE) |
|
SET_WORD(info->f_bw, AX_TXD_DATA_BW) |
|
(info->data_bw_er ? AX_TXD_DATA_BW_ER : 0) |
|
SET_WORD(info->f_gi_ltf, AX_TXD_GI_LTF) |
|
(info->f_er ? AX_TXD_DATA_ER : 0) |
|
(info->f_dcm ? AX_TXD_DATA_DCM : 0) |
|
(info->f_stbc ? AX_TXD_DATA_STBC : 0) |
|
(info->f_ldpc ? AX_TXD_DATA_LDPC : 0) |
|
(info->dis_data_rate_fb ? AX_TXD_DISDATAFB : 0) |
|
(info->dis_rts_rate_fb ? AX_TXD_DISRTSFB : 0) |
|
SET_WORD(info->hal_port,
|
AX_TXD_MULTIPORT_ID) |
|
SET_WORD(info->mbssid, AX_TXD_MBSSID) |
|
(info->ack_ch_info ? AX_TXD_ACK_CH_INFO : 0));
|
wdi->dword1 =
|
cpu_to_le32(SET_WORD(info->max_agg_num, AX_TXD_MAX_AGG_NUM) |
|
SET_WORD(info->data_tx_cnt_lmt, AX_TXD_DATA_TXCNT_LMT) |
|
(info->data_tx_cnt_lmt_en ?
|
AX_TXD_DATA_TXCNT_LMT_SEL : 0) |
|
(info->bc || info->mc ? AX_TXD_BMC : 0) |
|
(info->nav_use_hdr ? AX_TXD_NAVUSEHDR : 0) |
|
(info->bc || info->mc ? AX_TXD_BMC : 0) |
|
(info->a_ctrl_uph ? AX_TXD_A_CTRL_UPH : 0) |
|
(info->a_ctrl_bsr ? AX_TXD_A_CTRL_BSR : 0) |
|
(info->a_ctrl_cas ? AX_TXD_A_CTRL_CAS : 0) |
|
SET_WORD(info->data_rty_lowest_rate,
|
AX_TXD_DATA_RTY_LOWEST_RATE));
|
wdi->dword2 =
|
cpu_to_le32(SET_WORD(info->life_time_sel, AX_TXD_LIFETIME_SEL) |
|
SET_WORD(info->sec_type, AX_TXD_SECTYPE) |
|
(info->sec_hw_enc ? AX_TXD_SEC_HW_ENC : 0) |
|
SET_WORD(info->sec_cam_idx, AX_TXD_SEC_CAM_IDX) |
|
SET_WORD(info->ampdu_density,
|
AX_TXD_AMPDU_DENSITY));
|
|
wdi->dword3 =
|
cpu_to_le32((info->sifs_tx ? AX_TXD_SIFS_TX : 0) |
|
SET_WORD(info->ndpa, AX_TXD_NDPA) |
|
SET_WORD(info->snd_pkt_sel, AX_TXD_SND_PKT_SEL) |
|
(info->rtt_en ? AX_TXD_RTT_EN : 0) |
|
(info->spe_rpt ? AX_TXD_SPE_RPT : 0));
|
|
wdi->dword4 =
|
cpu_to_le32((info->rts_en ? AX_TXD_RTS_EN : 0) |
|
(info->cts2self ? AX_TXD_CTS2SELF : 0) |
|
SET_WORD(info->rts_cca_mode, AX_TXD_CCA_RTS) |
|
(info->hw_rts_en ? AX_TXD_HW_RTS_EN : 0) |
|
SET_WORD(info->sw_define, AX_TXD_SW_DEFINE));
|
|
wdi->dword5 = 0;
|
|
#if MAC_AX_FEATURE_HV
|
txdes_proc_hv(adapter, info, wdb, wdi);
|
#endif
|
|
if (info->wdinfo_en)
|
PLTFM_MEMCPY(buf + WD_BODY_LEN, (u8 *)wdi, WD_INFO_LEN);
|
|
if (adapter->hw_info->wd_checksum_en) {
|
ret = mac_wd_checksum(adapter, info, buf);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] mac_wd_checksum %d\n", ret);
|
return ret;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 txdes_proc_mgnt(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *buf, u32 len)
|
{
|
struct wd_body_t *wdb;
|
struct wd_info_t *wdi;
|
u8 wd_info_tmpl[WD_INFO_PKT_MAX][24] = {{0}};
|
u32 ret;
|
|
if (len != mac_txdesc_len(adapter, info)) {
|
PLTFM_MSG_ERR("[ERR] illegal len %d\n", len);
|
return MACBUFSZ;
|
}
|
|
if (info->pktlen > AX_TXD_TXPKTSIZE_MSK || !info->pktlen) {
|
PLTFM_MSG_ERR("[ERR] illegal txpktsize %d\n", info->pktlen);
|
return MACFUNCINPUT;
|
}
|
|
wdb = (struct wd_body_t *)buf;
|
if (adapter->hw_info->intf == MAC_AX_INTF_SDIO) {
|
wdb->dword0 =
|
cpu_to_le32(AX_TXD_STF_MODE);
|
} else if (adapter->hw_info->intf == MAC_AX_INTF_USB) {
|
wdb->dword0 =
|
cpu_to_le32(AX_TXD_STF_MODE |
|
(info->usb_pkt_ofst ?
|
AX_TXD_PKT_OFFSET : 0));
|
} else if (adapter->hw_info->intf == MAC_AX_INTF_PCIE) {
|
wdb->dword0 =
|
cpu_to_le32((info->wd_page_size ? AX_TXD_WD_PAGE : 0) |
|
(adapter->dle_info.qta_mode ==
|
MAC_AX_QTA_SCC_STF ||
|
adapter->dle_info.qta_mode ==
|
MAC_AX_QTA_DBCC_STF ?
|
AX_TXD_STF_MODE : 0));
|
} else {
|
PLTFM_MSG_ERR("[ERR] unknown intf %d\n",
|
adapter->hw_info->intf);
|
return MACINTF;
|
}
|
|
wdb->dword0 |=
|
cpu_to_le32(SET_WORD(info->hw_seq_mode,
|
AX_TXD_EN_HWSEQ_MODE) |
|
SET_WORD(info->hw_ssn_sel,
|
AX_TXD_HW_SSN_SEL) |
|
SET_WORD(info->hdr_len,
|
AX_TXD_HDR_LLC_LEN) |
|
(info->wdinfo_en ? AX_TXD_WDINFO_EN : 0));
|
|
wdb->dword0 |=
|
cpu_to_le32(SET_WORD((info->band ?
|
MAC_AX_DMA_B1MG :
|
MAC_AX_DMA_B0MG),
|
AX_TXD_CH_DMA));
|
|
wdb->dword1 = 0;
|
/* Get bb and qsel from qsel by according MAC ID */
|
wdb->dword2 =
|
cpu_to_le32(SET_WORD(info->pktlen, AX_TXD_TXPKTSIZE) |
|
SET_WORD((info->band ?
|
MAC_AX_MG1_SEL : MAC_AX_MG0_SEL),
|
AX_TXD_QSEL) |
|
SET_WORD(info->macid, AX_TXD_MACID));
|
wdb->dword3 = cpu_to_le32(SET_WORD(info->sw_seq,
|
AX_TXD_WIFI_SEQ) |
|
(info->bk ? AX_TXD_BK : 0));
|
wdb->dword4 = 0;
|
wdb->dword5 = 0;
|
|
wdi = (struct wd_info_t *)wd_info_tmpl[WD_INFO_PKT_NORMAL];
|
wdi->dword0 =
|
cpu_to_le32((info->userate_sel ? AX_TXD_USERATE_SEL : 0) |
|
SET_WORD(info->f_rate, AX_TXD_DATARATE) |
|
SET_WORD(info->f_bw, AX_TXD_DATA_BW) |
|
(info->data_bw_er ? AX_TXD_DATA_BW_ER : 0) |
|
SET_WORD(info->f_gi_ltf, AX_TXD_GI_LTF) |
|
(info->f_er ? AX_TXD_DATA_ER : 0) |
|
(info->f_dcm ? AX_TXD_DATA_DCM : 0) |
|
(info->f_stbc ? AX_TXD_DATA_STBC : 0) |
|
(info->f_ldpc ? AX_TXD_DATA_LDPC : 0) |
|
(info->dis_data_rate_fb ? AX_TXD_DISDATAFB : 0) |
|
(info->dis_rts_rate_fb ? AX_TXD_DISRTSFB : 0) |
|
SET_WORD(info->hal_port, AX_TXD_MULTIPORT_ID) |
|
SET_WORD(info->mbssid, AX_TXD_MBSSID));
|
wdi->dword1 =
|
cpu_to_le32(SET_WORD(info->max_agg_num, AX_TXD_MAX_AGG_NUM) |
|
SET_WORD(info->data_tx_cnt_lmt, AX_TXD_DATA_TXCNT_LMT) |
|
(info->data_tx_cnt_lmt_en ?
|
AX_TXD_DATA_TXCNT_LMT_SEL : 0) |
|
(info->bc || info->mc ? AX_TXD_BMC : 0) |
|
(info->nav_use_hdr ? AX_TXD_NAVUSEHDR : 0));
|
wdi->dword2 =
|
cpu_to_le32(SET_WORD(info->life_time_sel, AX_TXD_LIFETIME_SEL) |
|
SET_WORD(info->sec_type, AX_TXD_SECTYPE) |
|
(info->sec_hw_enc ? AX_TXD_SEC_HW_ENC : 0) |
|
SET_WORD(info->sec_cam_idx, AX_TXD_SEC_CAM_IDX) |
|
SET_WORD(info->ampdu_density,
|
AX_TXD_AMPDU_DENSITY));
|
|
wdi->dword3 =
|
cpu_to_le32((info->sifs_tx ? AX_TXD_SIFS_TX : 0) |
|
SET_WORD(info->ndpa, AX_TXD_NDPA) |
|
SET_WORD(info->snd_pkt_sel, AX_TXD_SND_PKT_SEL) |
|
(info->rtt_en ? AX_TXD_RTT_EN : 0) |
|
(info->spe_rpt ? AX_TXD_SPE_RPT : 0));
|
|
wdi->dword4 =
|
cpu_to_le32((info->rts_en ? AX_TXD_RTS_EN : 0) |
|
(info->cts2self ? AX_TXD_CTS2SELF : 0) |
|
SET_WORD(info->rts_cca_mode, AX_TXD_CCA_RTS) |
|
(info->hw_rts_en ? AX_TXD_HW_RTS_EN : 0) |
|
SET_WORD(info->sw_define, AX_TXD_SW_DEFINE));
|
|
wdi->dword5 = 0;
|
|
#if MAC_AX_FEATURE_HV
|
txdes_proc_hv(adapter, info, wdb, wdi);
|
#endif
|
|
if (info->wdinfo_en)
|
PLTFM_MEMCPY(buf + WD_BODY_LEN, (u8 *)wdi, WD_INFO_LEN);
|
|
if (adapter->hw_info->wd_checksum_en) {
|
ret = mac_wd_checksum(adapter, info, buf);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] mac_wd_checksum %d\n", ret);
|
return ret;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static struct txd_proc_type txdes_proc_mac[] = {
|
{RTW_PHL_PKT_TYPE_H2C, txdes_proc_h2c_fwdl},
|
{RTW_PHL_PKT_TYPE_FWDL, txdes_proc_h2c_fwdl},
|
{RTW_PHL_PKT_TYPE_DATA, txdes_proc_data},
|
{RTW_PHL_PKT_TYPE_MGNT, txdes_proc_mgnt},
|
{RTW_PHL_PKT_TYPE_MAX, NULL},
|
};
|
|
u32 mac_build_txdesc(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *buf, u32 len)
|
{
|
struct txd_proc_type *proc = txdes_proc_mac;
|
enum rtw_packet_type pkt_type = info->type;
|
u32 (*handler)(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *buf, u32 len) = NULL;
|
|
for (; proc->type != RTW_PHL_PKT_TYPE_MAX; proc++) {
|
if (pkt_type == proc->type) {
|
handler = proc->handler;
|
break;
|
}
|
}
|
|
if (!handler) {
|
PLTFM_MSG_ERR("[ERR]null type handler type: %X\n", proc->type);
|
return MACNOITEM;
|
}
|
|
return handler(adapter, info, buf, len);
|
}
|
|
u32 mac_refill_txdesc(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *txpkt_info,
|
struct mac_ax_refill_info *mask,
|
struct mac_ax_refill_info *info)
|
{
|
u32 dw0 = ((struct wd_body_t *)info->pkt)->dword0;
|
u32 dw1 = ((struct wd_body_t *)info->pkt)->dword1;
|
u32 ret;
|
|
if (mask->packet_offset)
|
((struct wd_body_t *)info->pkt)->dword0 =
|
dw0 | (info->packet_offset ? AX_TXD_PKT_OFFSET : 0);
|
|
if (mask->agg_num == AX_TXD_DMA_TXAGG_NUM_MSK)
|
((struct wd_body_t *)info->pkt)->dword1 =
|
SET_CLR_WORD(dw1, info->agg_num, AX_TXD_DMA_TXAGG_NUM);
|
|
if (adapter->hw_info->wd_checksum_en) {
|
ret = mac_wd_checksum(adapter, txpkt_info, info->pkt);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] mac_wd_checksum %d\n", ret);
|
return ret;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_comm(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf)
|
{
|
u32 hdr_val = le32_to_cpu(((struct rxd_short_t *)buf)->dword0);
|
|
info->rxdlen = hdr_val & AX_RXD_LONG_RXD ? RXD_LONG_LEN : RXD_SHORT_LEN;
|
info->pktsize = GET_FIELD(hdr_val, AX_RXD_RPKT_LEN);
|
info->shift = (u8)GET_FIELD(hdr_val, AX_RXD_SHIFT);
|
info->drvsize = (u8)GET_FIELD(hdr_val, AX_RXD_DRV_INFO_SIZE);
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_wifi(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
u32 hdr_val;
|
|
info->type = MAC_AX_PKT_DATA;
|
|
hdr_val = le32_to_cpu(((struct rxd_short_t *)buf)->dword3);
|
info->u.data.crc_err = !!(hdr_val & AX_RXD_CRC32_ERR);
|
info->u.data.icv_err = !!(hdr_val & AX_RXD_ICV_ERR);
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_c2h(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
info->type = MAC_AX_PKT_C2H;
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_ch_info(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
info->type = MAC_AX_PKT_CH_INFO;
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_dfs(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
info->type = MAC_AX_PKT_DFS;
|
|
return MACSUCCESS;
|
}
|
|
static u32 rxdes_parse_ppdu(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
u32 hdr_val = le32_to_cpu(((struct rxd_short_t *)buf)->dword0);
|
|
info->type = MAC_AX_PKT_PPDU;
|
info->u.ppdu.mac_info = !!(hdr_val & AX_RXD_MAC_INFO_VLD);
|
|
return MACSUCCESS;
|
}
|
|
static struct rxd_parse_type rxdes_parse_mac[] = {
|
{RXD_S_RPKT_TYPE_WIFI, rxdes_parse_wifi},
|
{RXD_S_RPKT_TYPE_C2H, rxdes_parse_c2h},
|
{RXD_S_RPKT_TYPE_PPDU, rxdes_parse_ppdu},
|
{RXD_S_RPKT_TYPE_CH_INFO, rxdes_parse_ch_info},
|
{RXD_S_RPKT_TYPE_DFS_RPT, rxdes_parse_dfs},
|
{RXD_RPKT_TYPE_INVALID, NULL},
|
};
|
|
u32 mac_parse_rxdesc(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len)
|
{
|
struct rxd_parse_type *parse = rxdes_parse_mac;
|
u8 rpkt_type;
|
u32 hdr_val;
|
u32 (*handler)(struct mac_ax_adapter *adapter,
|
struct mac_ax_rxpkt_info *info, u8 *buf, u32 len) = NULL;
|
|
hdr_val = le32_to_cpu(((struct rxd_short_t *)buf)->dword0);
|
rpkt_type = (u8)GET_FIELD(hdr_val, AX_RXD_RPKT_TYPE);
|
|
rxdes_parse_comm(adapter, info, buf);
|
|
for (; parse->type != RXD_RPKT_TYPE_INVALID; parse++) {
|
if (rpkt_type == parse->type) {
|
handler = parse->handler;
|
break;
|
}
|
}
|
|
if (!handler) {
|
PLTFM_MSG_ERR("[ERR]null type handler type: %X\n", parse->type);
|
return MACNOITEM;
|
}
|
|
return handler(adapter, info, buf, len);
|
}
|
|
u32 mac_wd_checksum(struct mac_ax_adapter *adapter,
|
struct rtw_t_meta_data *info, u8 *wddesc)
|
{
|
u16 chksum = 0;
|
u32 wddesc_size;
|
u16 *data;
|
u32 i, dw4;
|
|
if (!wddesc) {
|
PLTFM_MSG_ERR("[ERR]null pointer\n");
|
return MACNPTR;
|
}
|
|
if (adapter->hw_info->wd_checksum_en != 1)
|
PLTFM_MSG_TRACE("[TRACE]chksum disable\n");
|
|
dw4 = ((struct wd_body_t *)wddesc)->dword4;
|
|
((struct wd_body_t *)wddesc)->dword4 =
|
SET_CLR_WORD(dw4, 0x0, AX_TXD_TXDESC_CHECKSUM);
|
|
data = (u16 *)(wddesc);
|
/*unit : 4 bytes*/
|
wddesc_size = mac_txdesc_len(adapter, info) >> 2;
|
for (i = 0; i < wddesc_size; i++)
|
chksum ^= (*(data + 2 * i) ^ *(data + (2 * i + 1)));
|
|
/* *(data + 2 * i) & *(data + (2 * i + 1) have endain issue*/
|
/* Process eniadn issue after checksum calculation */
|
((struct wd_body_t *)wddesc)->dword4 =
|
SET_CLR_WORD(dw4, (u16)(chksum), AX_TXD_TXDESC_CHECKSUM);
|
return MACSUCCESS;
|
}
|
|
u32 mac_patch_rx_rate(struct mac_ax_adapter *adapter,
|
struct rtw_r_meta_data *info)
|
{
|
u32 nss;
|
|
if (!is_chip_id(adapter, MAC_AX_CHIP_ID_8852A))
|
return MACSUCCESS;
|
|
if (is_cv(adapter, CBV)) {
|
if (info->rpkt_type != RX_8852A_DESC_PKT_T_WIFI ||
|
info->ppdu_type != RX_8852A_DESC_PPDU_T_HE_SU ||
|
info->rx_gi_ltf != RX_8852A_DESC_RX_GI_LTF_4X_0_8)
|
return MACSUCCESS;
|
|
nss = GET_NSS_FROM_RX_RATE(info->rx_rate);
|
|
if (nss == NSS_1) /* real nss = 2 */
|
info->rx_rate = SET_NSS_TO_RX_RATE(info->rx_rate, NSS_2);
|
else if (nss == NSS_8) /* real nss = 1 */
|
info->rx_rate = SET_NSS_TO_RX_RATE(info->rx_rate, NSS_1);
|
}
|
|
return MACSUCCESS;
|
}
|