/******************************************************************************
|
*
|
* 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 "cmac_tx.h"
|
|
#define PTCL_IDLE_POLL_CNT 2200
|
#define SW_CVR_DUR_US 30
|
#define SW_CVR_CNT 8
|
#define TX_DLY_MAX 9
|
|
static u32 stop_macid_ctn(struct mac_ax_adapter *adapter,
|
struct mac_role_tbl *role,
|
struct mac_ax_sch_tx_en_cfg *bak);
|
static u32 tx_idle_ck(struct mac_ax_adapter *adapter, u8 band);
|
static u32 tx_idle_sel_ck(struct mac_ax_adapter *adapter, enum ptcl_tx_sel sel,
|
u8 band);
|
static u32 tx_idle_sel_ck_b(struct mac_ax_adapter *adapter,
|
enum ptcl_tx_sel sel, u8 band);
|
static u32 macid_idle_ck(struct mac_ax_adapter *adapter,
|
struct mac_role_tbl *role);
|
static u32 band_idle_ck(struct mac_ax_adapter *adapter, u8 band);
|
static void tx_on_dly(struct mac_ax_adapter *adapter, u8 band);
|
static void sch_2_u16(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en *tx_en, u16 *val16);
|
static void u16_2_sch(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en *tx_en, u16 val16);
|
static u32 h2c_usr_edca(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_edca_param *param);
|
static u32 h2c_usr_tx_rpt(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_tx_rpt_cfg *cfg);
|
static u32 tx_duty_h2c(struct mac_ax_adapter *adapter,
|
u16 pause_intvl, u16 tx_intvl);
|
|
u32 set_hw_ampdu_cfg(struct mac_ax_adapter *adapter,
|
struct mac_ax_ampdu_cfg *cfg)
|
{
|
u16 max_agg_num;
|
u8 max_agg_time;
|
u8 band;
|
u32 ret;
|
u32 bk_addr, agg_addr;
|
u32 val32;
|
u8 val8;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
band = cfg->band;
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
max_agg_num = cfg->max_agg_num;
|
max_agg_time = cfg->max_agg_time_32us;
|
|
bk_addr = band ? R_AX_AGG_BK_0_C1 : R_AX_AGG_BK_0;
|
agg_addr = band ? R_AX_AMPDU_AGG_LIMIT_C1 : R_AX_AMPDU_AGG_LIMIT;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
switch (cfg->wdbk_mode) {
|
case MAC_AX_WDBK_MODE_SINGLE_BK:
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_WDBK_CFG, 0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case MAC_AX_WDBK_MODE_GRP_BK:
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_WDBK_CFG, 1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
switch (cfg->rty_bk_mode) {
|
case MAC_AX_RTY_BK_MODE_AGG:
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK, 0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK_COD,
|
0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case MAC_AX_RTY_BK_MODE_RATE_FB:
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK, 0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK_COD,
|
1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case MAC_AX_RTY_BK_MODE_BK:
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK, 1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
ret = MAC_REG_W_OFLD((u16)bk_addr, B_AX_EN_RTY_BK_COD,
|
1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
val32 = 0;
|
if (max_agg_num > 0 && max_agg_num <= 0x100) {
|
ret = MAC_REG_W_OFLD((u16)agg_addr,
|
GET_MSK(B_AX_MAX_AGG_NUM),
|
max_agg_num - 1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
} else {
|
return MACSETVALERR;
|
}
|
if (max_agg_time > 0 && max_agg_time <= 0xA5) {
|
ret = MAC_REG_W_OFLD((u16)agg_addr,
|
(u32)GET_MSK(B_AX_AMPDU_MAX_TIME),
|
max_agg_time, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
} else {
|
return MACSETVALERR;
|
}
|
|
return MACSUCCESS;
|
}
|
#endif
|
|
val8 = MAC_REG_R8(bk_addr);
|
switch (cfg->wdbk_mode) {
|
case MAC_AX_WDBK_MODE_SINGLE_BK:
|
val8 &= ~B_AX_WDBK_CFG;
|
break;
|
case MAC_AX_WDBK_MODE_GRP_BK:
|
val8 |= B_AX_WDBK_CFG;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
switch (cfg->rty_bk_mode) {
|
case MAC_AX_RTY_BK_MODE_AGG:
|
val8 &= ~(B_AX_EN_RTY_BK | B_AX_EN_RTY_BK_COD);
|
break;
|
case MAC_AX_RTY_BK_MODE_RATE_FB:
|
val8 &= ~(B_AX_EN_RTY_BK);
|
val8 |= B_AX_EN_RTY_BK_COD;
|
break;
|
case MAC_AX_RTY_BK_MODE_BK:
|
val8 |= B_AX_EN_RTY_BK | B_AX_EN_RTY_BK_COD;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
MAC_REG_W8(bk_addr, val8);
|
|
val32 = MAC_REG_R32(agg_addr);
|
if (max_agg_num > 0 && max_agg_num <= 0x100)
|
val32 = SET_CLR_WORD(val32, max_agg_num - 1, B_AX_MAX_AGG_NUM);
|
else
|
return MACSETVALERR;
|
if (max_agg_time > 0 && max_agg_time <= 0xA5)
|
val32 = SET_CLR_WORD(val32, max_agg_time, B_AX_AMPDU_MAX_TIME);
|
else
|
return MACSETVALERR;
|
MAC_REG_W32(agg_addr, val32);
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_usr_tx_rpt_cfg(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_tx_rpt_cfg *cfg)
|
{
|
u32 ret;
|
|
ret = h2c_usr_tx_rpt(adapter, cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_usr_edca_param(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_edca_param *param)
|
{
|
u32 ret;
|
|
ret = h2c_usr_edca(adapter, param);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_edca_param(struct mac_ax_adapter *adapter,
|
struct mac_ax_edca_param *param)
|
{
|
u32 val32;
|
u32 reg_edca;
|
u32 ret;
|
u16 val16;
|
enum mac_ax_cmac_path_sel path;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, param->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = get_edca_addr(adapter, param, ®_edca);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
path = param->path;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
if (path == MAC_AX_CMAC_PATH_SEL_MG0_1 ||
|
path == MAC_AX_CMAC_PATH_SEL_MG2 ||
|
path == MAC_AX_CMAC_PATH_SEL_BCN) {
|
val16 = SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_BE_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_BE_0_AIFS);
|
ret = MAC_REG_W16_OFLD((u16)reg_edca, val16, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
} else {
|
val32 = SET_WORD(param->txop_32us, B_AX_BE_0_TXOPLMT) |
|
SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_BE_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_BE_0_AIFS);
|
ret = MAC_REG_W32_OFLD((u16)reg_edca, val32, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
return MACSUCCESS;
|
}
|
#endif
|
|
if (path == MAC_AX_CMAC_PATH_SEL_MG0_1 ||
|
path == MAC_AX_CMAC_PATH_SEL_MG2 ||
|
path == MAC_AX_CMAC_PATH_SEL_BCN) {
|
val16 = SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_BE_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_BE_0_AIFS);
|
MAC_REG_W16(reg_edca, val16);
|
} else {
|
val32 = SET_WORD(param->txop_32us, B_AX_BE_0_TXOPLMT) |
|
SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_BE_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_BE_0_AIFS);
|
MAC_REG_W32(reg_edca, val32);
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 get_hw_edca_param(struct mac_ax_adapter *adapter,
|
struct mac_ax_edca_param *param)
|
{
|
u32 val32;
|
u32 reg_edca;
|
u32 ret;
|
u16 val16;
|
enum mac_ax_cmac_path_sel path;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, param->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = get_edca_addr(adapter, param, ®_edca);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
path = param->path;
|
|
if (path == MAC_AX_CMAC_PATH_SEL_MG0_1 ||
|
path == MAC_AX_CMAC_PATH_SEL_MG2 ||
|
path == MAC_AX_CMAC_PATH_SEL_BCN) {
|
val16 = MAC_REG_R16(reg_edca);
|
param->txop_32us = 0;
|
param->aifs_us = GET_FIELD(val16, B_AX_BE_0_AIFS);
|
param->ecw_max = (GET_FIELD(val16, B_AX_BE_0_CW) & 0xF0) >> 4;
|
param->ecw_min = GET_FIELD(val16, B_AX_BE_0_CW) & 0x0F;
|
} else {
|
val32 = MAC_REG_R32(reg_edca);
|
param->txop_32us = GET_FIELD(val32, B_AX_BE_0_TXOPLMT);
|
param->aifs_us = GET_FIELD(val32, B_AX_BE_0_AIFS);
|
param->ecw_max = (GET_FIELD(val32, B_AX_BE_0_CW) & 0xF0) >> 4;
|
param->ecw_min = GET_FIELD(val32, B_AX_BE_0_CW) & 0x0F;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_edcca_param(struct mac_ax_adapter *adapter,
|
struct mac_ax_edcca_param *param)
|
{
|
u32 reg_cca_ctl = 0;
|
u32 ret;
|
enum mac_ax_edcca_sel sel;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, param->band, MAC_AX_CMAC_SEL);
|
if (ret)
|
return ret;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
sel = param->sel;
|
if (sel == MAC_AX_EDCCA_IN_TB_CHK) {
|
if (param->tb_check_en)
|
reg_cca_ctl |= B_AX_TB_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_TB_CHK_EDCCA;
|
}
|
if (sel == MAC_AX_EDCCA_IN_SIFS_CHK) {
|
if (param->sifs_check_en)
|
reg_cca_ctl |= B_AX_SIFS_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_SIFS_CHK_EDCCA;
|
}
|
if (sel == MAC_AX_EDCCA_IN_CTN_CHK) {
|
if (param->ctn_check_en)
|
reg_cca_ctl |= B_AX_CTN_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_CTN_CHK_EDCCA;
|
} else {
|
return MACNOITEM;
|
}
|
if (param->band)
|
ret = MAC_REG_W32_OFLD((u16)R_AX_CCA_CONTROL_C1,
|
reg_cca_ctl, 1);
|
else
|
ret = MAC_REG_W32_OFLD((u16)R_AX_CCA_CONTROL,
|
reg_cca_ctl, 1);
|
return ret;
|
}
|
#endif
|
|
if (param->band)
|
reg_cca_ctl = MAC_REG_R32(R_AX_CCA_CONTROL_C1);
|
else
|
reg_cca_ctl = MAC_REG_R32(R_AX_CCA_CONTROL);
|
|
sel = param->sel;
|
if (sel == MAC_AX_EDCCA_IN_TB_CHK) {
|
if (param->tb_check_en)
|
reg_cca_ctl |= B_AX_TB_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_TB_CHK_EDCCA;
|
}
|
if (sel == MAC_AX_EDCCA_IN_SIFS_CHK) {
|
if (param->sifs_check_en)
|
reg_cca_ctl |= B_AX_SIFS_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_SIFS_CHK_EDCCA;
|
}
|
if (sel == MAC_AX_EDCCA_IN_CTN_CHK) {
|
if (param->ctn_check_en)
|
reg_cca_ctl |= B_AX_CTN_CHK_EDCCA;
|
else
|
reg_cca_ctl &= ~B_AX_CTN_CHK_EDCCA;
|
} else {
|
return MACNOITEM;
|
}
|
|
if (param->band)
|
MAC_REG_W32(R_AX_CCA_CONTROL_C1, reg_cca_ctl);
|
else
|
MAC_REG_W32(R_AX_CCA_CONTROL, reg_cca_ctl);
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_muedca_param(struct mac_ax_adapter *adapter,
|
struct mac_ax_muedca_param *param)
|
{
|
u32 val32;
|
u32 reg_edca;
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, param->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = get_muedca_param_addr(adapter, param, ®_edca);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
val32 = SET_WORD(param->muedca_timer_32us,
|
B_AX_MUEDCA_BE_PARAM_0_TIMER) |
|
SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_MUEDCA_BE_PARAM_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_MUEDCA_BE_PARAM_0_AIFS);
|
ret = MAC_REG_W32_OFLD((u16)reg_edca, val32, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
#endif
|
|
val32 = SET_WORD(param->muedca_timer_32us,
|
B_AX_MUEDCA_BE_PARAM_0_TIMER) |
|
SET_WORD((param->ecw_max << 4) | param->ecw_min,
|
B_AX_MUEDCA_BE_PARAM_0_CW) |
|
SET_WORD(param->aifs_us, B_AX_MUEDCA_BE_PARAM_0_AIFS);
|
MAC_REG_W32(reg_edca, val32);
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_muedca_ctrl(struct mac_ax_adapter *adapter,
|
struct mac_ax_muedca_cfg *cfg)
|
{
|
u32 ret;
|
u8 band;
|
u16 val16;
|
u32 reg_en;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
band = cfg->band;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
reg_en = band ? R_AX_MUEDCA_EN_C1 : R_AX_MUEDCA_EN;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
val16 = 0;
|
if (cfg->wmm_sel == MAC_AX_CMAC_WMM1_SEL) {
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_MUEDCA_WMM_SEL,
|
1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
} else {
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_MUEDCA_WMM_SEL,
|
0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_MUEDCA_EN_0,
|
cfg->countdown_en, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_SET_MUEDCATIMER_TF_0,
|
cfg->tb_update_en, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
#endif
|
|
val16 = MAC_REG_R16(reg_en);
|
|
if (cfg->wmm_sel == MAC_AX_CMAC_WMM1_SEL)
|
val16 |= B_AX_MUEDCA_WMM_SEL;
|
else
|
val16 &= ~B_AX_MUEDCA_WMM_SEL;
|
|
if (cfg->countdown_en)
|
val16 |= B_AX_MUEDCA_EN_0;
|
else
|
val16 &= ~B_AX_MUEDCA_EN_0;
|
|
if (cfg->tb_update_en)
|
val16 |= B_AX_SET_MUEDCATIMER_TF_0;
|
else
|
val16 &= ~B_AX_SET_MUEDCATIMER_TF_0;
|
|
MAC_REG_W16(reg_en, val16);
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_tb_ppdu_ctrl(struct mac_ax_adapter *adapter,
|
struct mac_ax_tb_ppdu_ctrl *ctrl)
|
{
|
u16 val16;
|
u8 pri_ac;
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, ctrl->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
switch (ctrl->pri_ac) {
|
case MAC_AX_CMAC_AC_SEL_BE:
|
pri_ac = 0;
|
break;
|
case MAC_AX_CMAC_AC_SEL_BK:
|
pri_ac = 1;
|
break;
|
case MAC_AX_CMAC_AC_SEL_VI:
|
pri_ac = 2;
|
break;
|
case MAC_AX_CMAC_AC_SEL_VO:
|
pri_ac = 3;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
val16 = MAC_REG_R16(ctrl->band ? R_AX_TB_PPDU_CTRL_C1 :
|
R_AX_TB_PPDU_CTRL);
|
val16 &= ~(B_AX_TB_PPDU_BE_DIS | B_AX_TB_PPDU_BK_DIS |
|
B_AX_TB_PPDU_VI_DIS | B_AX_TB_PPDU_VO_DIS);
|
val16 |= (ctrl->be_dis ? B_AX_TB_PPDU_BE_DIS : 0) |
|
(ctrl->bk_dis ? B_AX_TB_PPDU_BK_DIS : 0) |
|
(ctrl->vi_dis ? B_AX_TB_PPDU_VI_DIS : 0) |
|
(ctrl->vo_dis ? B_AX_TB_PPDU_VO_DIS : 0);
|
val16 = SET_CLR_WORD(val16, pri_ac, B_AX_SW_PREFER_AC);
|
MAC_REG_W16(ctrl->band ? R_AX_TB_PPDU_CTRL_C1 : R_AX_TB_PPDU_CTRL,
|
val16);
|
|
return MACSUCCESS;
|
}
|
|
u32 get_hw_tb_ppdu_ctrl(struct mac_ax_adapter *adapter,
|
struct mac_ax_tb_ppdu_ctrl *ctrl)
|
{
|
u16 val16;
|
u8 pri_ac;
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, ctrl->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
val16 = MAC_REG_R16(ctrl->band ? R_AX_TB_PPDU_CTRL_C1 :
|
R_AX_TB_PPDU_CTRL);
|
ctrl->be_dis = (val16 & B_AX_TB_PPDU_BE_DIS) ? 1 : 0;
|
ctrl->bk_dis = (val16 & B_AX_TB_PPDU_BK_DIS) ? 1 : 0;
|
ctrl->vi_dis = (val16 & B_AX_TB_PPDU_VI_DIS) ? 1 : 0;
|
ctrl->vo_dis = (val16 & B_AX_TB_PPDU_VO_DIS) ? 1 : 0;
|
pri_ac = GET_FIELD(val16, B_AX_SW_PREFER_AC);
|
|
switch (pri_ac) {
|
case 0:
|
ctrl->pri_ac = MAC_AX_CMAC_AC_SEL_BE;
|
break;
|
case 1:
|
ctrl->pri_ac = MAC_AX_CMAC_AC_SEL_BK;
|
break;
|
case 2:
|
ctrl->pri_ac = MAC_AX_CMAC_AC_SEL_VI;
|
break;
|
case 3:
|
ctrl->pri_ac = MAC_AX_CMAC_AC_SEL_VO;
|
break;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_sch_tx_en(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en_cfg *cfg)
|
{
|
u16 val16;
|
u8 band;
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u16 tx_en_u16;
|
u16 mask_u16;
|
struct mac_ax_sch_tx_en tx_en;
|
struct mac_ax_sch_tx_en tx_en_mask;
|
u8 chip_id = adapter->hw_info->chip_id;
|
|
band = cfg->band;
|
tx_en = cfg->tx_en;
|
tx_en_mask = cfg->tx_en_mask;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
sch_2_u16(adapter, &tx_en, &tx_en_u16);
|
sch_2_u16(adapter, &tx_en_mask, &mask_u16);
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY ||
|
chip_id == MAC_AX_CHIP_ID_8852C ||
|
chip_id == MAC_AX_CHIP_ID_8192XB) {
|
val16 = MAC_REG_R16(band ? R_AX_CTN_TXEN_C1 : R_AX_CTN_TXEN);
|
|
val16 = (tx_en_u16 & mask_u16) | (~(~tx_en_u16 & mask_u16) & val16);
|
|
MAC_REG_W16(band ? R_AX_CTN_TXEN_C1 : R_AX_CTN_TXEN, val16);
|
} else {
|
hw_sch_tx_en(adapter, band, tx_en_u16, mask_u16);
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 hw_sch_tx_en(struct mac_ax_adapter *adapter, u8 band,
|
u16 tx_en_u16, u16 mask_u16)
|
{
|
#define RETRY_WAIT_US 1
|
u32 ret;
|
struct mac_ax_h2creg_info h2c = {0};
|
struct mac_ax_c2hreg_poll c2h = {0};
|
|
h2c.id = FWCMD_H2CREG_FUNC_SCH_TX_EN;
|
h2c.content_len = sizeof(struct sch_tx_en_h2creg);
|
|
h2c.h2c_content.dword0 =
|
SET_WORD(tx_en_u16, FWCMD_H2C_H2CREG_SCH_TX_PAUSE_TX_EN);
|
h2c.h2c_content.dword1 =
|
SET_WORD(mask_u16, FWCMD_H2C_H2CREG_SCH_TX_PAUSE_MASK) |
|
(band ? FWCMD_H2C_H2CREG_SCH_TX_PAUSE_BAND : 0);
|
|
c2h.polling_id = FWCMD_C2HREG_FUNC_TX_PAUSE_RPT;
|
c2h.retry_cnt = TX_PAUSE_WAIT_CNT;
|
c2h.retry_wait_us = RETRY_WAIT_US;
|
|
ret = proc_msg_reg(adapter, &h2c, &c2h);
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]hw sch tx_en proc msg reg %d\n", ret);
|
return ret;
|
}
|
return MACSUCCESS;
|
}
|
|
u32 get_hw_sch_tx_en(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en_cfg *cfg)
|
{
|
u8 band;
|
u32 ret;
|
u16 val16;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_ax_sch_tx_en tx_en;
|
|
band = cfg->band;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
val16 = MAC_REG_R16(band ? R_AX_CTN_TXEN_C1 : R_AX_CTN_TXEN);
|
u16_2_sch(adapter, &tx_en, val16);
|
cfg->tx_en = tx_en;
|
|
return MACSUCCESS;
|
}
|
|
u32 set_hw_lifetime_cfg(struct mac_ax_adapter *adapter,
|
struct mac_ax_lifetime_cfg *cfg)
|
{
|
u32 ret;
|
u8 band;
|
u8 val8;
|
u32 val32;
|
u32 reg_time_0, reg_time_1, reg_time_2, reg_en;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
band = cfg->band;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
reg_time_0 = band ? R_AX_LIFETIME_0_C1 : R_AX_LIFETIME_0;
|
reg_time_1 = band ? R_AX_LIFETIME_1_C1 : R_AX_LIFETIME_1;
|
reg_time_2 = band ? R_AX_LIFETIME_2_C1 : R_AX_LIFETIME_2;
|
reg_en = band ? R_AX_PTCL_COMMON_SETTING_0_C1 :
|
R_AX_PTCL_COMMON_SETTING_0;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
if (cfg->en.acq_en || cfg->en.mgq_en) {
|
ret = MAC_REG_W_OFLD(R_AX_TX_PASTE_TIMESTAMP_SETTING,
|
B_AX_HDT_TIMESTAMP_EN, 1, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
val32 = SET_WORD(cfg->val.acq_val_1, B_AX_PKT_LIFETIME_1) |
|
SET_WORD(cfg->val.acq_val_2, B_AX_PKT_LIFETIME_2);
|
ret = MAC_REG_W32_OFLD((u16)reg_time_0, val32, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
val32 = SET_WORD(cfg->val.acq_val_3, B_AX_PKT_LIFETIME_3) |
|
SET_WORD(cfg->val.acq_val_4, B_AX_PKT_LIFETIME_4);
|
ret = MAC_REG_W32_OFLD((u16)reg_time_1, val32, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = MAC_REG_W16_OFLD((u16)reg_time_2, cfg->val.mgq_val, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_LIFETIME_EN,
|
cfg->en.acq_en, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
ret = MAC_REG_W_OFLD((u16)reg_en, B_AX_MGQ_LIFETIME_EN,
|
cfg->en.mgq_en, 1);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
#endif
|
|
if (cfg->en.acq_en || cfg->en.mgq_en)
|
MAC_REG_W8(R_AX_TX_PASTE_TIMESTAMP_SETTING,
|
MAC_REG_R8(R_AX_TX_PASTE_TIMESTAMP_SETTING) |
|
B_AX_HDT_TIMESTAMP_EN);
|
|
val32 = SET_WORD(cfg->val.acq_val_1, B_AX_PKT_LIFETIME_1) |
|
SET_WORD(cfg->val.acq_val_2, B_AX_PKT_LIFETIME_2);
|
MAC_REG_W32(reg_time_0, val32);
|
|
val32 = SET_WORD(cfg->val.acq_val_3, B_AX_PKT_LIFETIME_3) |
|
SET_WORD(cfg->val.acq_val_4, B_AX_PKT_LIFETIME_4);
|
MAC_REG_W32(reg_time_1, val32);
|
|
MAC_REG_W16(reg_time_2, cfg->val.mgq_val);
|
|
val8 = MAC_REG_R8(reg_en);
|
val8 &= ~(B_AX_LIFETIME_EN | B_AX_MGQ_LIFETIME_EN);
|
val8 |= (cfg->en.acq_en ? B_AX_LIFETIME_EN : 0) |
|
(cfg->en.mgq_en ? B_AX_MGQ_LIFETIME_EN : 0);
|
MAC_REG_W8(reg_en, val8);
|
|
return MACSUCCESS;
|
}
|
|
u32 get_hw_lifetime_cfg(struct mac_ax_adapter *adapter,
|
struct mac_ax_lifetime_cfg *cfg)
|
{
|
u32 ret;
|
u8 band;
|
u8 val8;
|
u32 val32;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
band = cfg->band;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
val8 = MAC_REG_R8(band ? R_AX_PTCL_COMMON_SETTING_0_C1 :
|
R_AX_PTCL_COMMON_SETTING_0);
|
cfg->en.acq_en = (val8 & B_AX_LIFETIME_EN) ? 1 : 0;
|
cfg->en.mgq_en = (val8 & B_AX_MGQ_LIFETIME_EN) ? 1 : 0;
|
|
val32 = MAC_REG_R32(band ? R_AX_LIFETIME_0_C1 : R_AX_LIFETIME_0);
|
cfg->val.acq_val_1 = GET_FIELD(val32, B_AX_PKT_LIFETIME_1);
|
cfg->val.acq_val_2 = GET_FIELD(val32, B_AX_PKT_LIFETIME_2);
|
|
val32 = MAC_REG_R32(band ? R_AX_LIFETIME_1_C1 : R_AX_LIFETIME_1);
|
cfg->val.acq_val_3 = GET_FIELD(val32, B_AX_PKT_LIFETIME_3);
|
cfg->val.acq_val_4 = GET_FIELD(val32, B_AX_PKT_LIFETIME_4);
|
|
cfg->val.mgq_val = MAC_REG_R16(band ? R_AX_LIFETIME_2_C1 :
|
R_AX_LIFETIME_2);
|
|
return MACSUCCESS;
|
}
|
|
u32 stop_sch_tx(struct mac_ax_adapter *adapter, enum sch_tx_sel sel,
|
struct mac_ax_sch_tx_en_cfg *bak)
|
{
|
struct mac_ax_sch_tx_en_cfg cfg;
|
u32 ret;
|
|
ret = get_hw_sch_tx_en(adapter, bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
cfg.band = bak->band;
|
u16_2_sch(adapter, &cfg.tx_en_mask, 0);
|
|
switch (sel) {
|
case SCH_TX_SEL_ALL:
|
u16_2_sch(adapter, &cfg.tx_en, 0);
|
u16_2_sch(adapter, &cfg.tx_en_mask, 0xFFFF);
|
ret = set_hw_sch_tx_en(adapter, &cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case SCH_TX_SEL_HIQ:
|
cfg.tx_en.hi = 0;
|
cfg.tx_en_mask.hi = 1;
|
ret = set_hw_sch_tx_en(adapter, &cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case SCH_TX_SEL_MG0:
|
cfg.tx_en.mg0 = 0;
|
cfg.tx_en_mask.mg0 = 1;
|
ret = set_hw_sch_tx_en(adapter, &cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case SCH_TX_SEL_MACID:
|
u16_2_sch(adapter, &cfg.tx_en, 0);
|
u16_2_sch(adapter, &cfg.tx_en_mask, 0xFFFF);
|
cfg.tx_en_mask.mg1 = 0;
|
cfg.tx_en_mask.mg2 = 0;
|
cfg.tx_en_mask.hi = 0;
|
cfg.tx_en_mask.bcn = 0;
|
ret = set_hw_sch_tx_en(adapter, &cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 resume_sch_tx(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en_cfg *bak)
|
{
|
u32 ret;
|
|
u16_2_sch(adapter, &bak->tx_en_mask, 0xFFFF);
|
ret = set_hw_sch_tx_en(adapter, bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 stop_macid_tx(struct mac_ax_adapter *adapter, struct mac_role_tbl *role,
|
enum tb_stop_sel stop_sel, struct macid_tx_bak *bak)
|
{
|
u8 band;
|
u32 ret;
|
struct mac_ax_macid_pause_cfg pause;
|
|
band = role->info.band;
|
|
if (role->info.a_info.tf_trs) {
|
bak->ac_dis_bak.band = band;
|
ret = stop_ac_tb_tx(adapter, stop_sel, &bak->ac_dis_bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
|
pause.macid = role->macid;
|
pause.pause = 1;
|
ret = set_macid_pause(adapter, &pause);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
bak->sch_bak.band = band;
|
ret = stop_macid_ctn(adapter, role, &bak->sch_bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 resume_macid_tx(struct mac_ax_adapter *adapter, struct mac_role_tbl *role,
|
struct macid_tx_bak *bak)
|
{
|
u32 ret;
|
struct mac_ax_macid_pause_cfg pause_cfg;
|
|
if (role->info.band == MAC_AX_BAND_0) {
|
u16_2_sch(adapter, &bak->sch_bak.tx_en_mask, 0xFFFF);
|
ret = set_hw_sch_tx_en(adapter, &bak->sch_bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
|
if (role->info.a_info.tf_trs) {
|
ret = set_hw_tb_ppdu_ctrl(adapter, &bak->ac_dis_bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
|
pause_cfg.macid = role->macid;
|
pause_cfg.pause = 0;
|
ret = set_macid_pause(adapter, &pause_cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 tx_idle_poll_macid(struct mac_ax_adapter *adapter,
|
struct mac_role_tbl *role)
|
{
|
return macid_idle_ck(adapter, role);
|
}
|
|
u32 tx_idle_poll_band(struct mac_ax_adapter *adapter, u8 band, u8 txop_aware)
|
{
|
if (txop_aware)
|
return tx_idle_ck(adapter, band);
|
|
return band_idle_ck(adapter, band);
|
}
|
|
u32 tx_idle_poll_sel(struct mac_ax_adapter *adapter, enum ptcl_tx_sel sel,
|
u8 band)
|
{
|
return tx_idle_sel_ck_b(adapter, sel, band);
|
}
|
|
u32 stop_ac_tb_tx(struct mac_ax_adapter *adapter, enum tb_stop_sel stop_sel,
|
struct mac_ax_tb_ppdu_ctrl *ac_dis_bak)
|
{
|
u32 ret;
|
struct mac_ax_tb_ppdu_ctrl ctrl;
|
|
ret = get_hw_tb_ppdu_ctrl(adapter, ac_dis_bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ctrl.band = ac_dis_bak->band;
|
ctrl.pri_ac = ac_dis_bak->pri_ac;
|
ctrl.be_dis = 0;
|
ctrl.bk_dis = 0;
|
ctrl.vi_dis = 0;
|
ctrl.vo_dis = 0;
|
|
switch (stop_sel) {
|
case TB_STOP_SEL_ALL:
|
ctrl.be_dis = 1;
|
ctrl.bk_dis = 1;
|
ctrl.vi_dis = 1;
|
ctrl.vo_dis = 1;
|
ret = set_hw_tb_ppdu_ctrl(adapter, &ctrl);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case TB_STOP_SEL_BE:
|
ctrl.be_dis = 1;
|
ret = set_hw_tb_ppdu_ctrl(adapter, &ctrl);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case TB_STOP_SEL_BK:
|
ctrl.bk_dis = 1;
|
ret = set_hw_tb_ppdu_ctrl(adapter, &ctrl);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case TB_STOP_SEL_VI:
|
ctrl.vi_dis = 1;
|
ret = set_hw_tb_ppdu_ctrl(adapter, &ctrl);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
case TB_STOP_SEL_VO:
|
ctrl.vo_dis = 1;
|
ret = set_hw_tb_ppdu_ctrl(adapter, &ctrl);
|
if (ret != MACSUCCESS)
|
return ret;
|
break;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 get_edca_addr(struct mac_ax_adapter *adapter,
|
struct mac_ax_edca_param *param, u32 *reg_edca)
|
{
|
u8 band;
|
u32 ret;
|
enum mac_ax_cmac_path_sel path;
|
|
band = param->band;
|
path = param->path;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
switch (path) {
|
case MAC_AX_CMAC_PATH_SEL_BE0:
|
*reg_edca =
|
band ? R_AX_EDCA_BE_PARAM_0_C1 : R_AX_EDCA_BE_PARAM_0;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_BK0:
|
*reg_edca =
|
band ? R_AX_EDCA_BK_PARAM_0_C1 : R_AX_EDCA_BK_PARAM_0;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_VI0:
|
*reg_edca =
|
band ? R_AX_EDCA_VI_PARAM_0_C1 : R_AX_EDCA_VI_PARAM_0;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_VO0:
|
*reg_edca =
|
band ? R_AX_EDCA_VO_PARAM_0_C1 : R_AX_EDCA_VO_PARAM_0;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_BE1:
|
*reg_edca =
|
band ? R_AX_EDCA_BE_PARAM_1_C1 : R_AX_EDCA_BE_PARAM_1;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_BK1:
|
*reg_edca =
|
band ? R_AX_EDCA_BK_PARAM_1_C1 : R_AX_EDCA_BK_PARAM_1;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_VI1:
|
*reg_edca =
|
band ? R_AX_EDCA_VI_PARAM_1_C1 : R_AX_EDCA_VI_PARAM_1;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_VO1:
|
*reg_edca =
|
band ? R_AX_EDCA_VO_PARAM_1_C1 : R_AX_EDCA_VO_PARAM_1;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_MG0_1:
|
*reg_edca =
|
band ? R_AX_EDCA_MGQ_PARAM_C1 : R_AX_EDCA_MGQ_PARAM;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_MG2:
|
*reg_edca =
|
band ? (R_AX_EDCA_MGQ_PARAM_C1 + 2) :
|
(R_AX_EDCA_MGQ_PARAM + 2);
|
break;
|
case MAC_AX_CMAC_PATH_SEL_BCN:
|
*reg_edca =
|
band ? (R_AX_EDCA_BCNQ_PARAM_C1 + 2) :
|
(R_AX_EDCA_BCNQ_PARAM + 2);
|
break;
|
case MAC_AX_CMAC_PATH_SEL_TF:
|
*reg_edca = R_AX_EDCA_ULQ_PARAM;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_TWT0:
|
*reg_edca = R_AX_EDCA_TWT_PARAM_0;
|
break;
|
case MAC_AX_CMAC_PATH_SEL_TWT1:
|
*reg_edca = R_AX_EDCA_TWT_PARAM_1;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 get_muedca_param_addr(struct mac_ax_adapter *adapter,
|
struct mac_ax_muedca_param *param,
|
u32 *reg_edca)
|
{
|
u8 band;
|
u32 ret;
|
enum mac_ax_cmac_ac_sel ac;
|
|
band = param->band;
|
ac = param->ac;
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
switch (ac) {
|
case MAC_AX_CMAC_AC_SEL_BE:
|
*reg_edca =
|
band ? R_AX_MUEDCA_BE_PARAM_0_C1 :
|
R_AX_MUEDCA_BE_PARAM_0;
|
break;
|
case MAC_AX_CMAC_AC_SEL_BK:
|
*reg_edca =
|
band ? R_AX_MUEDCA_BK_PARAM_0_C1 :
|
R_AX_MUEDCA_BK_PARAM_0;
|
break;
|
case MAC_AX_CMAC_AC_SEL_VI:
|
*reg_edca =
|
band ? R_AX_MUEDCA_VI_PARAM_0_C1 :
|
R_AX_MUEDCA_VI_PARAM_0;
|
break;
|
case MAC_AX_CMAC_AC_SEL_VO:
|
*reg_edca =
|
band ? R_AX_MUEDCA_VO_PARAM_0_C1 :
|
R_AX_MUEDCA_VO_PARAM_0;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
return MACSUCCESS;
|
}
|
|
/* for sw mode Tx, need to stop sch */
|
/* (for "F2PCMD.disable_sleep_chk"), soar 20200225*/
|
static u32 stop_macid_ctn(struct mac_ax_adapter *adapter,
|
struct mac_role_tbl *role,
|
struct mac_ax_sch_tx_en_cfg *bak)
|
{
|
struct mac_ax_sch_tx_en_cfg cfg;
|
u32 ret;
|
|
ret = check_mac_en(adapter, role->info.band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = get_hw_sch_tx_en(adapter, bak);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
cfg.band = role->info.band;
|
u16_2_sch(adapter, &cfg.tx_en_mask, 0);
|
|
u16_2_sch(adapter, &cfg.tx_en, 0);
|
u16_2_sch(adapter, &cfg.tx_en_mask, 0xFFFF);
|
cfg.tx_en_mask.mg0 = 0;
|
cfg.tx_en_mask.mg1 = 0;
|
cfg.tx_en_mask.mg2 = 0;
|
cfg.tx_en_mask.hi = 0;
|
cfg.tx_en_mask.bcn = 0;
|
|
ret = set_hw_sch_tx_en(adapter, &cfg);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
static u32 tx_idle_ck(struct mac_ax_adapter *adapter, u8 band)
|
{
|
u32 cnt;
|
u8 val8;
|
u32 ret;
|
u32 poll_addr;
|
u32 i;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
poll_addr = band ? R_AX_PTCL_TX_CTN_SEL_C1 : R_AX_PTCL_TX_CTN_SEL;
|
|
cnt = PTCL_IDLE_POLL_CNT;
|
while (--cnt) {
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT) {
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
} else {
|
for (i = 0; i < SW_CVR_CNT; i++) {
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT)
|
break;
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
}
|
if (i >= SW_CVR_CNT)
|
break;
|
}
|
}
|
if (!cnt)
|
return MACPOLLTXIDLE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 tx_idle_sel_ck(struct mac_ax_adapter *adapter, enum ptcl_tx_sel sel,
|
u8 band)
|
{
|
u32 cnt;
|
u8 val8;
|
u32 ret;
|
u32 poll_addr;
|
u32 i;
|
u8 ptcl_tx_qid;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
poll_addr = band ? R_AX_PTCL_TX_CTN_SEL_C1 : R_AX_PTCL_TX_CTN_SEL;
|
|
switch (sel) {
|
case PTCL_TX_SEL_HIQ:
|
ptcl_tx_qid = PTCL_TXQ_HIQ;
|
break;
|
case PTCL_TX_SEL_MG0:
|
ptcl_tx_qid = PTCL_TXQ_MG0;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
cnt = PTCL_IDLE_POLL_CNT;
|
while (--cnt) {
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT) {
|
if (GET_FIELD(val8, B_AX_PTCL_TX_QUEUE_IDX) ==
|
ptcl_tx_qid)
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
else
|
break;
|
} else {
|
for (i = 0; i < SW_CVR_CNT; i++) {
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT)
|
break;
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
}
|
if ((val8 & B_AX_PTCL_TX_ON_STAT) &&
|
GET_FIELD(val8, B_AX_PTCL_TX_QUEUE_IDX) !=
|
ptcl_tx_qid)
|
break;
|
if (i >= SW_CVR_CNT)
|
break;
|
}
|
}
|
if (!cnt)
|
return MACPOLLTXIDLE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 tx_idle_sel_ck_b(struct mac_ax_adapter *adapter,
|
enum ptcl_tx_sel sel, u8 band)
|
{
|
u32 cnt;
|
u8 val8;
|
u32 ret;
|
u8 ptcl_tx_qid;
|
u32 poll_addr;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
poll_addr = band ? R_AX_PTCL_TX_CTN_SEL_C1 : R_AX_PTCL_TX_CTN_SEL;
|
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT)
|
tx_on_dly(adapter, band);
|
else
|
return MACSUCCESS;
|
|
switch (sel) {
|
case PTCL_TX_SEL_HIQ:
|
ptcl_tx_qid = PTCL_TXQ_HIQ;
|
break;
|
case PTCL_TX_SEL_MG0:
|
ptcl_tx_qid = PTCL_TXQ_MG0;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
cnt = PTCL_IDLE_POLL_CNT;
|
while (--cnt) {
|
val8 = MAC_REG_R8(poll_addr);
|
if ((val8 & B_AX_PTCL_TX_ON_STAT) && (val8 & B_AX_PTCL_DROP))
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
else if ((val8 & B_AX_PTCL_TX_ON_STAT) &&
|
(GET_FIELD(val8, B_AX_PTCL_TX_QUEUE_IDX) ==
|
ptcl_tx_qid))
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
else
|
break;
|
}
|
if (!cnt)
|
return MACPOLLTXIDLE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 macid_idle_ck(struct mac_ax_adapter *adapter,
|
struct mac_role_tbl *role)
|
{
|
u32 cnt;
|
u8 val8;
|
u32 ret;
|
u8 band;
|
u32 val32;
|
u8 macid;
|
u8 txq;
|
u32 poll_addr;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
band = role->info.band;
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
poll_addr = band ? R_AX_PTCL_TX_CTN_SEL_C1 : R_AX_PTCL_TX_CTN_SEL;
|
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT)
|
tx_on_dly(adapter, band);
|
else
|
return MACSUCCESS;
|
|
macid = role->macid;
|
|
cnt = PTCL_IDLE_POLL_CNT;
|
while (--cnt) {
|
val8 = MAC_REG_R8(poll_addr);
|
txq = GET_FIELD(val8, B_AX_PTCL_TX_QUEUE_IDX);
|
if ((val8 & B_AX_PTCL_TX_ON_STAT) && (val8 & B_AX_PTCL_DROP)) {
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
} else if ((val8 & B_AX_PTCL_TX_ON_STAT) &&
|
txq != PTCL_TXQ_HIQ && txq != PTCL_TXQ_BCNQ &&
|
txq != PTCL_TXQ_MG0 && txq != PTCL_TXQ_MG1 &&
|
txq != PTCL_TXQ_MG2 && txq != PTCL_TXQ_TB) {
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
/* need to modify for 8852C, soar */
|
val32 = MAC_REG_R32(band ? R_AX_PTCL_TX_MACID_0_C1 :
|
R_AX_PTCL_TX_MACID_0);
|
if (macid == GET_FIELD(val32, B_AX_TX_MACID_0) ||
|
macid == GET_FIELD(val32, B_AX_TX_MACID_1) ||
|
macid == GET_FIELD(val32, B_AX_TX_MACID_2) ||
|
macid == GET_FIELD(val32, B_AX_TX_MACID_3))
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
else
|
break;
|
} else {
|
break;
|
}
|
}
|
if (!cnt)
|
return MACPOLLTXIDLE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 band_idle_ck(struct mac_ax_adapter *adapter, u8 band)
|
{
|
u32 cnt;
|
u8 val8;
|
u32 ret;
|
u32 poll_addr;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
poll_addr = band ? R_AX_PTCL_TX_CTN_SEL_C1 : R_AX_PTCL_TX_CTN_SEL;
|
|
cnt = PTCL_IDLE_POLL_CNT;
|
while (--cnt) {
|
val8 = MAC_REG_R8(poll_addr);
|
if (val8 & B_AX_PTCL_TX_ON_STAT)
|
PLTFM_DELAY_US(SW_CVR_DUR_US);
|
else
|
break;
|
}
|
if (!cnt)
|
return MACPOLLTXIDLE;
|
|
return MACSUCCESS;
|
}
|
|
static void tx_on_dly(struct mac_ax_adapter *adapter, u8 band)
|
{
|
u32 val32;
|
u32 drop_dly_max;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
val32 = MAC_REG_R32(band ? R_AX_TX_CTRL_C1 : R_AX_TX_CTRL);
|
drop_dly_max = GET_FIELD(val32, B_AX_DROP_CHK_MAX_NUM) >> 2;
|
PLTFM_DELAY_US((drop_dly_max > TX_DLY_MAX) ? drop_dly_max : TX_DLY_MAX);
|
}
|
|
static void sch_2_u16(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en *tx_en, u16 *val16)
|
{
|
*val16 = (tx_en->be0 ? B_AX_CTN_TXEN_BE_0 : 0) |
|
(tx_en->bk0 ? B_AX_CTN_TXEN_BK_0 : 0) |
|
(tx_en->vi0 ? B_AX_CTN_TXEN_VI_0 : 0) |
|
(tx_en->vo0 ? B_AX_CTN_TXEN_VO_0 : 0) |
|
(tx_en->be1 ? B_AX_CTN_TXEN_BE_1 : 0) |
|
(tx_en->bk1 ? B_AX_CTN_TXEN_BK_1 : 0) |
|
(tx_en->vi1 ? B_AX_CTN_TXEN_VI_1 : 0) |
|
(tx_en->vo1 ? B_AX_CTN_TXEN_VO_1 : 0) |
|
(tx_en->mg0 ? B_AX_CTN_TXEN_MGQ : 0) |
|
(tx_en->mg1 ? B_AX_CTN_TXEN_MGQ1 : 0) |
|
(tx_en->mg2 ? B_AX_CTN_TXEN_CPUMGQ : 0) |
|
(tx_en->hi ? B_AX_CTN_TXEN_HGQ : 0) |
|
(tx_en->bcn ? B_AX_CTN_TXEN_BCNQ : 0) |
|
(tx_en->ul ? B_AX_CTN_TXEN_ULQ : 0) |
|
(tx_en->twt0 ? B_AX_CTN_TXEN_TWT_0 : 0) |
|
(tx_en->twt1 ? B_AX_CTN_TXEN_TWT_1 : 0);
|
}
|
|
static void u16_2_sch(struct mac_ax_adapter *adapter,
|
struct mac_ax_sch_tx_en *tx_en, u16 val16)
|
{
|
tx_en->be0 = val16 & B_AX_CTN_TXEN_BE_0 ? 1 : 0;
|
tx_en->bk0 = val16 & B_AX_CTN_TXEN_BK_0 ? 1 : 0;
|
tx_en->vi0 = val16 & B_AX_CTN_TXEN_VI_0 ? 1 : 0;
|
tx_en->vo0 = val16 & B_AX_CTN_TXEN_VO_0 ? 1 : 0;
|
tx_en->be1 = val16 & B_AX_CTN_TXEN_BE_1 ? 1 : 0;
|
tx_en->bk1 = val16 & B_AX_CTN_TXEN_BK_1 ? 1 : 0;
|
tx_en->vi1 = val16 & B_AX_CTN_TXEN_VI_1 ? 1 : 0;
|
tx_en->vo1 = val16 & B_AX_CTN_TXEN_VO_1 ? 1 : 0;
|
tx_en->mg0 = val16 & B_AX_CTN_TXEN_MGQ ? 1 : 0;
|
tx_en->mg1 = val16 & B_AX_CTN_TXEN_MGQ1 ? 1 : 0;
|
tx_en->mg2 = val16 & B_AX_CTN_TXEN_CPUMGQ ? 1 : 0;
|
tx_en->hi = val16 & B_AX_CTN_TXEN_HGQ ? 1 : 0;
|
tx_en->bcn = val16 & B_AX_CTN_TXEN_BCNQ ? 1 : 0;
|
tx_en->ul = val16 & B_AX_CTN_TXEN_ULQ ? 1 : 0;
|
tx_en->twt0 = val16 & B_AX_CTN_TXEN_TWT_0 ? 1 : 0;
|
tx_en->twt1 = val16 & B_AX_CTN_TXEN_TWT_1 ? 1 : 0;
|
}
|
|
static u32 h2c_usr_edca(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_edca_param *param)
|
{
|
u8 *buf;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_usr_edca *fwcmd_tbl;
|
u32 ret;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY) {
|
PLTFM_MSG_WARN("%s fw not ready\n", __func__);
|
return MACFWNONRDY;
|
}
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct fwcmd_usr_edca));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto usr_edca_fail;
|
}
|
|
fwcmd_tbl = (struct fwcmd_usr_edca *)buf;
|
fwcmd_tbl->dword0 =
|
cpu_to_le32(SET_WORD(param->idx, FWCMD_H2C_USR_EDCA_PARAM_SEL) |
|
(param->enable ? FWCMD_H2C_USR_EDCA_ENABLE : 0) |
|
(param->band ? FWCMD_H2C_USR_EDCA_BAND : 0) |
|
(param->wmm ? FWCMD_H2C_USR_EDCA_WMM : 0) |
|
SET_WORD(param->ac, FWCMD_H2C_USR_EDCA_AC));
|
fwcmd_tbl->dword1 =
|
cpu_to_le32(SET_WORD(param->aggressive.txop_32us, B_AX_BE_0_TXOPLMT) |
|
SET_WORD((param->aggressive.ecw_max << 4) |
|
param->aggressive.ecw_min, B_AX_BE_0_CW) |
|
SET_WORD(param->aggressive.aifs_us, B_AX_BE_0_AIFS));
|
fwcmd_tbl->dword2 =
|
cpu_to_le32(SET_WORD(param->moderate.txop_32us, B_AX_BE_0_TXOPLMT) |
|
SET_WORD((param->moderate.ecw_max << 4) |
|
param->moderate.ecw_min, B_AX_BE_0_CW) |
|
SET_WORD(param->moderate.aifs_us, B_AX_BE_0_AIFS));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_USR_EDCA,
|
0,
|
0);
|
|
if (ret != MACSUCCESS)
|
goto usr_edca_fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret != MACSUCCESS)
|
goto usr_edca_fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret)
|
goto usr_edca_fail;
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
|
usr_edca_fail:
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
static u32 h2c_usr_tx_rpt(struct mac_ax_adapter *adapter,
|
struct mac_ax_usr_tx_rpt_cfg *param)
|
{
|
u8 *buf;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_usr_tx_rpt *fwcmd_tbl;
|
u32 ret;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY) {
|
PLTFM_MSG_WARN("%s fw not ready\n", __func__);
|
return MACFWNONRDY;
|
}
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct fwcmd_usr_tx_rpt));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
fwcmd_tbl = (struct fwcmd_usr_tx_rpt *)buf;
|
fwcmd_tbl->dword0 =
|
cpu_to_le32(SET_WORD(param->mode, FWCMD_H2C_USR_TX_RPT_MODE) |
|
(param->rpt_start ? FWCMD_H2C_USR_TX_RPT_RTP_START : 0));
|
fwcmd_tbl->dword1 =
|
cpu_to_le32(SET_WORD(param->macid, FWCMD_H2C_USR_TX_RPT_MACID) |
|
(param->band ? FWCMD_H2C_USR_TX_RPT_BAND : 0) |
|
SET_WORD(param->port, FWCMD_H2C_USR_TX_RPT_PORT));
|
fwcmd_tbl->dword2 = cpu_to_le32(param->rpt_period_us);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_USR_TX_RPT,
|
0,
|
0);
|
|
if (ret != MACSUCCESS)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret != MACSUCCESS)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret)
|
goto fail;
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
|
fail:
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
u32 mac_set_cctl_max_tx_time(struct mac_ax_adapter *adapter,
|
struct mac_ax_max_tx_time *tx_time)
|
{
|
#define MAC_AX_DFLT_TX_TIME 5280
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_ax_cctl_info info, msk = {0};
|
u32 ret = MACSUCCESS;
|
struct mac_role_tbl *role;
|
u8 band;
|
u32 offset, max_tx_time;
|
|
role = mac_role_srch(adapter, tx_time->macid);
|
if (!role) {
|
PLTFM_MSG_ERR("%s: The MACID%d does not exist\n",
|
__func__, tx_time->macid);
|
return MACNOITEM;
|
}
|
|
max_tx_time = tx_time->max_tx_time == 0 ?
|
MAC_AX_DFLT_TX_TIME : tx_time->max_tx_time;
|
|
if (tx_time->is_cctrl) {
|
msk.ampdu_time_sel = 1;
|
info.ampdu_time_sel = 1;
|
msk.ampdu_max_time = FWCMD_H2C_CCTRL_AMPDU_MAX_TIME_MSK;
|
info.ampdu_max_time = (max_tx_time - 512) >> 9;
|
ret = mac_upd_cctl_info(adapter, &info, &msk, tx_time->macid, 1);
|
} else {
|
band = role->info.wmm < 2 ? 0 : 1;
|
offset = band == 0 ? R_AX_AMPDU_AGG_LIMIT + 3 :
|
R_AX_AMPDU_AGG_LIMIT_C1 + 3;
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
ret = MAC_REG_W8_OFLD((u16)offset,
|
max_tx_time >> 5,
|
1);
|
if (ret != MACSUCCESS)
|
PLTFM_MSG_ERR("%s: ofld fail %d\n",
|
__func__, ret);
|
return ret;
|
}
|
#endif
|
MAC_REG_W8(offset, max_tx_time >> 5);
|
}
|
|
return ret;
|
}
|
|
u32 mac_get_max_tx_time(struct mac_ax_adapter *adapter,
|
struct mac_ax_max_tx_time *tx_time)
|
{
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u32 ret = MACSUCCESS;
|
struct mac_role_tbl *role;
|
u32 offset;
|
u8 band;
|
|
role = mac_role_srch(adapter, tx_time->macid);
|
if (!role) {
|
PLTFM_MSG_ERR("%s: The MACID%d does not exist\n",
|
__func__, tx_time->macid);
|
return MACNOITEM;
|
}
|
|
if (role->info.c_info.ampdu_time_sel) {
|
tx_time->max_tx_time = (role->info.c_info.ampdu_max_time + 1) << 9;
|
tx_time->is_cctrl = 1;
|
} else {
|
band = role->info.wmm < 2 ? 0 : 1;
|
offset = band == 0 ? R_AX_AMPDU_AGG_LIMIT + 3 :
|
R_AX_AMPDU_AGG_LIMIT_C1 + 3;
|
ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL);
|
if (ret == MACSUCCESS)
|
tx_time->max_tx_time = MAC_REG_R8(offset) << 5;
|
tx_time->is_cctrl = 0;
|
}
|
|
return ret;
|
}
|
|
u32 mac_set_hw_rts_th(struct mac_ax_adapter *adapter,
|
struct mac_ax_hw_rts_th *th)
|
{
|
#define MAC_AX_MULT32_SH 5
|
#define MAC_AX_MULT16_SH 4
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u32 ret, offset;
|
u16 val;
|
|
ret = check_mac_en(adapter, th->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
offset = th->band ? R_AX_AGG_LEN_HT_0_C1 : R_AX_AGG_LEN_HT_0;
|
|
#if MAC_AX_FW_REG_OFLD
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
ret = MAC_REG_W_OFLD((u16)offset,
|
B_AX_RTS_LEN_TH_MSK << B_AX_RTS_LEN_TH_SH,
|
th->len_th >> MAC_AX_MULT16_SH, 0);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("%s: config fail\n", __func__);
|
return ret;
|
}
|
ret = MAC_REG_W_OFLD((u16)offset,
|
B_AX_RTS_TXTIME_TH_MSK <<
|
B_AX_RTS_TXTIME_TH_SH,
|
th->time_th >> MAC_AX_MULT32_SH, 1);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("%s: config fail\n", __func__);
|
return ret;
|
}
|
return MACSUCCESS;
|
}
|
#endif
|
val = SET_WORD(th->len_th >> MAC_AX_MULT16_SH, B_AX_RTS_LEN_TH) |
|
SET_WORD(th->time_th >> MAC_AX_MULT32_SH, B_AX_RTS_TXTIME_TH);
|
MAC_REG_W16(offset, val);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_get_hw_rts_th(struct mac_ax_adapter *adapter,
|
struct mac_ax_hw_rts_th *th)
|
{
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u32 ret, offset;
|
u16 val;
|
|
ret = check_mac_en(adapter, th->band, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
offset = th->band ? R_AX_AGG_LEN_HT_0_C1 : R_AX_AGG_LEN_HT_0;
|
val = MAC_REG_R16(offset);
|
|
th->len_th = GET_FIELD(val, B_AX_RTS_LEN_TH);
|
th->len_th = th->len_th << MAC_AX_MULT16_SH;
|
th->time_th = GET_FIELD(val, B_AX_RTS_TXTIME_TH);
|
th->time_th = th->time_th << MAC_AX_MULT32_SH;
|
|
return MACSUCCESS;
|
#undef MAC_AX_MULT32_SH
|
#undef MAC_AX_MULT16_SH
|
}
|
|
u32 mac_tx_idle_poll(struct mac_ax_adapter *adapter,
|
struct mac_ax_tx_idle_poll_cfg *poll_cfg)
|
{
|
switch (poll_cfg->sel) {
|
case MAC_AX_TX_IDLE_POLL_SEL_BAND:
|
return tx_idle_poll_band(adapter, poll_cfg->band, 1);
|
default:
|
return MACNOITEM;
|
}
|
}
|
|
u32 mac_set_tx_ru26_tb(struct mac_ax_adapter *adapter,
|
u8 disable)
|
{
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u32 val32;
|
|
#if MAC_AX_FW_REG_OFLD
|
u32 ret;
|
|
if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) {
|
if (disable)
|
ret = MAC_REG_W_OFLD(R_AX_RXTRIG_TEST_USER_2, B_AX_RXTRIG_RU26_DIS, 1, 1);
|
else
|
ret = MAC_REG_W_OFLD(R_AX_RXTRIG_TEST_USER_2, B_AX_RXTRIG_RU26_DIS, 0, 1);
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, R_AX_RXTRIG_TEST_USER_2);
|
return ret;
|
}
|
return MACSUCCESS;
|
}
|
#endif
|
val32 = MAC_REG_R32(R_AX_RXTRIG_TEST_USER_2) & (~B_AX_RXTRIG_RU26_DIS);
|
|
if (disable)
|
MAC_REG_W32(R_AX_RXTRIG_TEST_USER_2, val32 | B_AX_RXTRIG_RU26_DIS);
|
else
|
MAC_REG_W32(R_AX_RXTRIG_TEST_USER_2, val32);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_tx_duty(struct mac_ax_adapter *adapter,
|
u16 pause_intvl, u16 tx_intvl)
|
{
|
u32 ret;
|
|
if (!(pause_intvl) || !(tx_intvl))
|
return MACFUNCINPUT;
|
|
ret = tx_duty_h2c(adapter, pause_intvl, tx_intvl);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_tx_duty_stop(struct mac_ax_adapter *adapter)
|
{
|
u32 ret;
|
|
ret = tx_duty_h2c(adapter, 0, 0);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 tx_duty_h2c(struct mac_ax_adapter *adapter,
|
u16 pause_intvl, u16 tx_intvl)
|
{
|
u32 ret, size;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
u8 *buf;
|
struct fwcmd_tx_duty cfg;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
size = sizeof(struct fwcmd_tx_duty);
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, size);
|
if (!buf) {
|
h2cb_free(adapter, h2cb);
|
return MACNOBUF;
|
}
|
|
cfg.dword0 =
|
cpu_to_le32(SET_WORD(pause_intvl, FWCMD_H2C_TX_DUTY_PAUSE_INTVL) |
|
SET_WORD(tx_intvl, FWCMD_H2C_TX_DUTY_TX_INTVL)
|
);
|
cfg.dword1 = cpu_to_le32(pause_intvl ? 0 : FWCMD_H2C_TX_DUTY_STOP);
|
|
PLTFM_MEMCPY(buf, &cfg, size);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_TX_DUTY,
|
0, 0);
|
if (ret != MACSUCCESS) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret != MACSUCCESS) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]platform tx\n");
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
return MACSUCCESS;
|
}
|