/******************************************************************************
|
*
|
* 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 "dbcc.h"
|
#include "cpuio.h"
|
|
static u32 band1_enable(struct mac_ax_adapter *adapter,
|
struct mac_ax_trx_info *info)
|
{
|
u32 ret;
|
u32 sleep_bak[4] = {0};
|
u32 pause_bak[4] = {0};
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_ax_sch_tx_en_cfg txen_bak;
|
|
txen_bak.band = 0;
|
ret = stop_sch_tx(adapter, SCH_TX_SEL_ALL, &txen_bak);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]stop sch tx %d\n", ret);
|
return ret;
|
}
|
|
sleep_bak[0] = MAC_REG_R32(R_AX_MACID_SLEEP_0);
|
sleep_bak[1] = MAC_REG_R32(R_AX_MACID_SLEEP_1);
|
sleep_bak[2] = MAC_REG_R32(R_AX_MACID_SLEEP_2);
|
sleep_bak[3] = MAC_REG_R32(R_AX_MACID_SLEEP_3);
|
pause_bak[0] = MAC_REG_R32(R_AX_SS_MACID_PAUSE_0);
|
pause_bak[1] = MAC_REG_R32(R_AX_SS_MACID_PAUSE_1);
|
pause_bak[2] = MAC_REG_R32(R_AX_SS_MACID_PAUSE_2);
|
pause_bak[3] = MAC_REG_R32(R_AX_SS_MACID_PAUSE_3);
|
|
MAC_REG_W32(R_AX_MACID_SLEEP_0, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_MACID_SLEEP_1, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_MACID_SLEEP_2, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_MACID_SLEEP_3, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_0, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_1, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_2, 0xFFFFFFFF);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_3, 0xFFFFFFFF);
|
|
ret = tx_idle_poll_band(adapter, 0, 0);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]tx idle poll %d\n", ret);
|
return ret;
|
}
|
|
ret = dle_quota_change(adapter, info->qta_mode);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DLE quota change %d\n", ret);
|
return ret;
|
}
|
|
MAC_REG_W32(R_AX_MACID_SLEEP_0, sleep_bak[0]);
|
MAC_REG_W32(R_AX_MACID_SLEEP_1, sleep_bak[1]);
|
MAC_REG_W32(R_AX_MACID_SLEEP_2, sleep_bak[2]);
|
MAC_REG_W32(R_AX_MACID_SLEEP_3, sleep_bak[3]);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_0, pause_bak[0]);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_1, pause_bak[1]);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_2, pause_bak[2]);
|
MAC_REG_W32(R_AX_SS_MACID_PAUSE_3, pause_bak[3]);
|
|
ret = resume_sch_tx(adapter, &txen_bak);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]CMAC%d resume sch tx %d\n",
|
txen_bak.band, ret);
|
return ret;
|
}
|
|
ret = cmac_func_en(adapter, MAC_AX_BAND_1, MAC_AX_FUNC_EN);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]CMAC%d func en %d\n", MAC_AX_BAND_1, ret);
|
return ret;
|
}
|
|
ret = cmac_init(adapter, info, MAC_AX_BAND_1);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]CMAC%d init %d\n", MAC_AX_BAND_1, ret);
|
return ret;
|
}
|
|
MAC_REG_W32(R_AX_SYS_ISO_CTRL_EXTEND,
|
MAC_REG_R32(R_AX_SYS_ISO_CTRL_EXTEND) |
|
(B_AX_R_SYM_FEN_WLBBFUN_1 | B_AX_R_SYM_FEN_WLBBGLB_1));
|
|
adapter->sm.bb1_func = MAC_AX_FUNC_ON;
|
|
ret = mac_enable_imr(adapter, MAC_AX_BAND_1, MAC_AX_CMAC_SEL);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] enable CMAC1 IMR %d\n", ret);
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 band1_disable(struct mac_ax_adapter *adapter,
|
struct mac_ax_trx_info *info)
|
{
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_ax_pkt_drop_info drop_info;
|
|
MAC_REG_W32(R_AX_SYS_ISO_CTRL_EXTEND,
|
MAC_REG_R32(R_AX_SYS_ISO_CTRL_EXTEND) &
|
~B_AX_R_SYM_FEN_WLBBFUN_1);
|
|
drop_info.band = MAC_AX_BAND_1;
|
drop_info.sel = MAC_AX_PKT_DROP_SEL_BAND;
|
ret = adapter->ops->pkt_drop(adapter, &drop_info);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]CMAC%d pkt drop %d\n", drop_info.band, ret);
|
return ret;
|
}
|
|
ret = mac_remove_role_by_band(adapter, MAC_AX_BAND_1, 0);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]Remove Address CAM %d\n", ret);
|
return ret;
|
}
|
|
ret = cmac_func_en(adapter, MAC_AX_BAND_1, MAC_AX_FUNC_DIS);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]CMAC%d func dis %d\n", MAC_AX_BAND_1, ret);
|
return ret;
|
}
|
|
ret = dle_quota_change(adapter, info->qta_mode);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DLE quota change %d\n", ret);
|
return ret;
|
}
|
|
return 0;
|
}
|
|
u32 mac_dbcc_enable(struct mac_ax_adapter *adapter,
|
struct mac_ax_trx_info *info, u8 dbcc_en)
|
{
|
u32 ret;
|
|
if (dbcc_en) {
|
ret = band1_enable(adapter, info);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] band1_enable %d\n", ret);
|
return ret;
|
}
|
ret = mac_notify_fw_dbcc(adapter, 1);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("%s: [ERR] notfify dbcc fail %d\n",
|
__func__, ret);
|
return ret;
|
}
|
} else {
|
ret = mac_notify_fw_dbcc(adapter, 0);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("%s: [ERR] notfify dbcc fail %d\n",
|
__func__, ret);
|
return ret;
|
}
|
ret = band1_disable(adapter, info);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR] band1_disable %d\n", ret);
|
return ret;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dbcc_move_macid(struct mac_ax_adapter *adapter, u8 macid, u8 dbcc_en)
|
{
|
struct mac_role_tbl *role;
|
struct deq_enq_info q_info;
|
u32 ret;
|
|
role = mac_role_srch(adapter, macid);
|
if (!role) {
|
PLTFM_MSG_ERR("dbcc%d move macid%d srch role fail\n",
|
dbcc_en, macid);
|
return MACNOITEM;
|
}
|
|
if (dbcc_en) {
|
ret = mac_ss_wmm_sta_move(adapter,
|
(enum mac_ax_ss_wmm)role->wmm,
|
MAC_AX_SS_WMM_TBL_C1_WMM0);
|
} else {
|
ret = mac_ss_wmm_sta_move(adapter,
|
(enum mac_ax_ss_wmm)role->wmm,
|
MAC_AX_SS_WMM_TBL_C0_WMM0);
|
}
|
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("dbcc%d move macid%d wmm%d move %d\n",
|
dbcc_en, macid, role->wmm, ret);
|
return ret;
|
}
|
|
PLTFM_MEMSET(&q_info, 0, sizeof(struct deq_enq_info));
|
|
if (dbcc_en) {
|
q_info.src_pid = WDE_DLE_PID_C0;
|
q_info.src_qid = WDE_DLE_QID_MG0_C0;
|
q_info.dst_pid = WDE_DLE_PID_C1;
|
q_info.dst_qid = WDE_DLE_QID_MG0_C1;
|
} else {
|
q_info.src_pid = WDE_DLE_PID_C1;
|
q_info.src_qid = WDE_DLE_QID_MG0_C1;
|
q_info.dst_pid = WDE_DLE_PID_C0;
|
q_info.dst_qid = WDE_DLE_QID_MG0_C0;
|
}
|
|
ret = deq_enq_all(adapter, &q_info);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("dbcc%d move mgq %d\n", dbcc_en, ret);
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|