Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/wireless/realtek/rtw89/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 205 kB image not shown  

Quelle  mac.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2019-2020  Realtek Corporation
 */


#include "cam.h"
#include "chan.h"
#include "debug.h"
#include "efuse.h"
#include "fw.h"
#include "mac.h"
#include "pci.h"
#include "ps.h"
#include "reg.h"
#include "util.h"

static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = {
 [RTW89_MAC_MEM_AXIDMA]         = AXIDMA_BASE_ADDR,
 [RTW89_MAC_MEM_SHARED_BUF] = SHARED_BUF_BASE_ADDR,
 [RTW89_MAC_MEM_DMAC_TBL] = DMAC_TBL_BASE_ADDR,
 [RTW89_MAC_MEM_SHCUT_MACHDR] = SHCUT_MACHDR_BASE_ADDR,
 [RTW89_MAC_MEM_STA_SCHED] = STA_SCHED_BASE_ADDR,
 [RTW89_MAC_MEM_RXPLD_FLTR_CAM] = RXPLD_FLTR_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_SECURITY_CAM] = SECURITY_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_WOW_CAM]  = WOW_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_CMAC_TBL] = CMAC_TBL_BASE_ADDR,
 [RTW89_MAC_MEM_ADDR_CAM] = ADDR_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_BA_CAM]  = BA_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_BCN_IE_CAM0] = BCN_IE_CAM0_BASE_ADDR,
 [RTW89_MAC_MEM_BCN_IE_CAM1] = BCN_IE_CAM1_BASE_ADDR,
 [RTW89_MAC_MEM_TXD_FIFO_0] = TXD_FIFO_0_BASE_ADDR,
 [RTW89_MAC_MEM_TXD_FIFO_1] = TXD_FIFO_1_BASE_ADDR,
 [RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR,
 [RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR,
 [RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR,
 [RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR,
 [RTW89_MAC_MEM_TXD_FIFO_0_V1] = TXD_FIFO_0_BASE_ADDR_V1,
 [RTW89_MAC_MEM_TXD_FIFO_1_V1] = TXD_FIFO_1_BASE_ADDR_V1,
};

static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset,
    u32 val, enum rtw89_mac_mem_sel sel)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 u32 addr = mac->mem_base_addrs[sel] + offset;

 rtw89_write32(rtwdev, mac->filter_model_addr, addr);
 rtw89_write32(rtwdev, mac->indir_access_addr, val);
}

static u32 rtw89_mac_mem_read(struct rtw89_dev *rtwdev, u32 offset,
         enum rtw89_mac_mem_sel sel)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 u32 addr = mac->mem_base_addrs[sel] + offset;

 rtw89_write32(rtwdev, mac->filter_model_addr, addr);
 return rtw89_read32(rtwdev, mac->indir_access_addr);
}

static int rtw89_mac_check_mac_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
         enum rtw89_mac_hwmod_sel sel)
{
 u32 val, r_val;

 if (sel == RTW89_DMAC_SEL) {
  r_val = rtw89_read32(rtwdev, R_AX_DMAC_FUNC_EN);
  val = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN);
 } else if (sel == RTW89_CMAC_SEL && mac_idx == 0) {
  r_val = rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN);
  val = B_AX_CMAC_EN;
 } else if (sel == RTW89_CMAC_SEL && mac_idx == 1) {
  r_val = rtw89_read32(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND);
  val = B_AX_CMAC1_FEN;
 } else {
  return -EINVAL;
 }
 if (r_val == RTW89_R32_EA || r_val == RTW89_R32_DEAD ||
     (val & r_val) != val)
  return -EFAULT;

 return 0;
}

int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
{
 u8 lte_ctrl;
 int ret;

 ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
    50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
 if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
  rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");

 rtw89_write32(rtwdev, R_AX_LTE_WDATA, val);
 rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0xC00F0000 | offset);

 return ret;
}

int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val)
{
 u8 lte_ctrl;
 int ret;

 ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
    50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
 if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
  rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");

 rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0x800F0000 | offset);
 *val = rtw89_read32(rtwdev, R_AX_LTE_RDATA);

 return ret;
}

int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl)
{
 u32 ctrl_reg, data_reg, ctrl_data;
 u32 val;
 int ret;

 switch (ctrl->type) {
 case DLE_CTRL_TYPE_WDE:
  ctrl_reg = R_AX_WDE_DBG_FUN_INTF_CTL;
  data_reg = R_AX_WDE_DBG_FUN_INTF_DATA;
  ctrl_data = FIELD_PREP(B_AX_WDE_DFI_TRGSEL_MASK, ctrl->target) |
       FIELD_PREP(B_AX_WDE_DFI_ADDR_MASK, ctrl->addr) |
       B_AX_WDE_DFI_ACTIVE;
  break;
 case DLE_CTRL_TYPE_PLE:
  ctrl_reg = R_AX_PLE_DBG_FUN_INTF_CTL;
  data_reg = R_AX_PLE_DBG_FUN_INTF_DATA;
  ctrl_data = FIELD_PREP(B_AX_PLE_DFI_TRGSEL_MASK, ctrl->target) |
       FIELD_PREP(B_AX_PLE_DFI_ADDR_MASK, ctrl->addr) |
       B_AX_PLE_DFI_ACTIVE;
  break;
 default:
  rtw89_warn(rtwdev, "[ERR] dfi ctrl type %d\n", ctrl->type);
  return -EINVAL;
 }

 rtw89_write32(rtwdev, ctrl_reg, ctrl_data);

 ret = read_poll_timeout_atomic(rtw89_read32, val, !(val & B_AX_WDE_DFI_ACTIVE),
           1, 1000, false, rtwdev, ctrl_reg);
 if (ret) {
  rtw89_warn(rtwdev, "[ERR] dle dfi ctrl 0x%X set 0x%X timeout\n",
      ctrl_reg, ctrl_data);
  return ret;
 }

 ctrl->out_data = rtw89_read32(rtwdev, data_reg);
 return 0;
}

int rtw89_mac_dle_dfi_quota_cfg(struct rtw89_dev *rtwdev,
    struct rtw89_mac_dle_dfi_quota *quota)
{
 struct rtw89_mac_dle_dfi_ctrl ctrl;
 int ret;

 ctrl.type = quota->dle_type;
 ctrl.target = DLE_DFI_TYPE_QUOTA;
 ctrl.addr = quota->qtaid;
 ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
 if (ret) {
  rtw89_warn(rtwdev, "[ERR] dle dfi quota %d\n", ret);
  return ret;
 }

 quota->rsv_pgnum = FIELD_GET(B_AX_DLE_RSV_PGNUM, ctrl.out_data);
 quota->use_pgnum = FIELD_GET(B_AX_DLE_USE_PGNUM, ctrl.out_data);
 return 0;
}

int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev,
     struct rtw89_mac_dle_dfi_qempty *qempty)
{
 struct rtw89_mac_dle_dfi_ctrl ctrl;
 u32 ret;

 ctrl.type = qempty->dle_type;
 ctrl.target = DLE_DFI_TYPE_QEMPTY;
 ctrl.addr = qempty->grpsel;
 ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
 if (ret) {
  rtw89_warn(rtwdev, "[ERR] dle dfi qempty %d\n", ret);
  return ret;
 }

 qempty->qempty = FIELD_GET(B_AX_DLE_QEMPTY_GRP, ctrl.out_data);
 return 0;
}

static void dump_err_status_dispatcher_ax(struct rtw89_dev *rtwdev)
{
 rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_IMR=0x%08x ",
     rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
 rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_ISR=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
 rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_IMR=0x%08x ",
     rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
 rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_ISR=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
 rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_IMR=0x%08x ",
     rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
 rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_ISR=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
}

static void rtw89_mac_dump_qta_lost_ax(struct rtw89_dev *rtwdev)
{
 struct rtw89_mac_dle_dfi_qempty qempty;
 struct rtw89_mac_dle_dfi_quota quota;
 struct rtw89_mac_dle_dfi_ctrl ctrl;
 u32 val, not_empty, i;
 int ret;

 qempty.dle_type = DLE_CTRL_TYPE_PLE;
 qempty.grpsel = 0;
 qempty.qempty = ~(u32)0;
 ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
 if (ret)
  rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
 else
  rtw89_info(rtwdev, "DLE group0 empty: 0x%x\n", qempty.qempty);

 for (not_empty = ~qempty.qempty, i = 0; not_empty != 0; not_empty >>= 1, i++) {
  if (!(not_empty & BIT(0)))
   continue;
  ctrl.type = DLE_CTRL_TYPE_PLE;
  ctrl.target = DLE_DFI_TYPE_QLNKTBL;
  ctrl.addr = (QLNKTBL_ADDR_INFO_SEL_0 ? QLNKTBL_ADDR_INFO_SEL : 0) |
       u32_encode_bits(i, QLNKTBL_ADDR_TBL_IDX_MASK);
  ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
  if (ret)
   rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
  else
   rtw89_info(rtwdev, "qidx%d pktcnt = %d\n", i,
       u32_get_bits(ctrl.out_data,
      QLNKTBL_DATA_SEL1_PKT_CNT_MASK));
 }

 quota.dle_type = DLE_CTRL_TYPE_PLE;
 quota.qtaid = 6;
 ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, "a);
 if (ret)
  rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
 else
  rtw89_info(rtwdev, "quota6 rsv/use: 0x%x/0x%x\n",
      quota.rsv_pgnum, quota.use_pgnum);

 val = rtw89_read32(rtwdev, R_AX_PLE_QTA6_CFG);
 rtw89_info(rtwdev, "[PLE][CMAC0_RX]min_pgnum=0x%x\n",
     u32_get_bits(val, B_AX_PLE_Q6_MIN_SIZE_MASK));
 rtw89_info(rtwdev, "[PLE][CMAC0_RX]max_pgnum=0x%x\n",
     u32_get_bits(val, B_AX_PLE_Q6_MAX_SIZE_MASK));
 val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT);
 rtw89_info(rtwdev, "[PLE][CMAC0_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n",
     u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
 rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG));
 rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0));
 rtw89_info(rtwdev, "R_AX_CCA_CONTROL=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_CCA_CONTROL));

 if (!rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_1, RTW89_CMAC_SEL)) {
  quota.dle_type = DLE_CTRL_TYPE_PLE;
  quota.qtaid = 7;
  ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, "a);
  if (ret)
   rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
  else
   rtw89_info(rtwdev, "quota7 rsv/use: 0x%x/0x%x\n",
       quota.rsv_pgnum, quota.use_pgnum);

  val = rtw89_read32(rtwdev, R_AX_PLE_QTA7_CFG);
  rtw89_info(rtwdev, "[PLE][CMAC1_RX]min_pgnum=0x%x\n",
      u32_get_bits(val, B_AX_PLE_Q7_MIN_SIZE_MASK));
  rtw89_info(rtwdev, "[PLE][CMAC1_RX]max_pgnum=0x%x\n",
      u32_get_bits(val, B_AX_PLE_Q7_MAX_SIZE_MASK));
  val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT_C1);
  rtw89_info(rtwdev, "[PLE][CMAC1_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n",
      u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
  rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG_C1=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG_C1));
  rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0_C1=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0_C1));
  rtw89_info(rtwdev, "R_AX_CCA_CONTROL_C1=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_CCA_CONTROL_C1));
 }

 rtw89_info(rtwdev, "R_AX_DLE_EMPTY0=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_DLE_EMPTY0));
 rtw89_info(rtwdev, "R_AX_DLE_EMPTY1=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_DLE_EMPTY1));

 dump_err_status_dispatcher_ax(rtwdev);
}

void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev,
        enum mac_ax_err_info err)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 u32 dbg, event;

 dbg = rtw89_read32(rtwdev, R_AX_SER_DBG_INFO);
 event = u32_get_bits(dbg, B_AX_L0_TO_L1_EVENT_MASK);

 switch (event) {
 case MAC_AX_L0_TO_L1_RX_QTA_LOST:
  rtw89_info(rtwdev, "quota lost!\n");
  mac->dump_qta_lost(rtwdev);
  break;
 default:
  break;
 }
}

void rtw89_mac_dump_dmac_err_status(struct rtw89_dev *rtwdev)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 u32 dmac_err;
 int i, ret;

 ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
 if (ret) {
  rtw89_warn(rtwdev, "[DMAC] : DMAC not enabled\n");
  return;
 }

 dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
 rtw89_info(rtwdev, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err);
 rtw89_info(rtwdev, "R_AX_DMAC_ERR_IMR=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR));

 if (dmac_err) {
  rtw89_info(rtwdev, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1));
  rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1));
  if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_PLE_ERRFLAG_MSG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG));
   rtw89_info(rtwdev, "R_AX_WDE_ERRFLAG_MSG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG));
   rtw89_info(rtwdev, "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN));
   rtw89_info(rtwdev, "R_AX_PLE_DBGERR_STS=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS));
  }
 }

 if (dmac_err & B_AX_WDRLS_ERR_FLAG) {
  rtw89_info(rtwdev, "R_AX_WDRLS_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_WDRLS_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR));
  if (chip->chip_id == RTL8852C)
   rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1));
  else
   rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX));
 }

 if (dmac_err & B_AX_WSEC_ERR_FLAG) {
  if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR));
   rtw89_info(rtwdev, "R_AX_SEC_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG));
   rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
   rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
   rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
   rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
   rtw89_info(rtwdev, "R_AX_SEC_DEBUG1=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_DEBUG1));
   rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
   rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));

   rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
        B_AX_DBG_SEL0, 0x8B);
   rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
        B_AX_DBG_SEL1, 0x8B);
   rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1,
        B_AX_SEL_0XC0_MASK, 1);
   for (i = 0; i < 0x10; i++) {
    rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
         B_AX_SEC_DBG_PORT_FIELD_MASK, i);
    rtw89_info(rtwdev, "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n",
        i, rtw89_read32(rtwdev, R_AX_SEC_DEBUG2));
   }
  } else if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_SEC_ERROR_FLAG=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_ERROR_FLAG));
   rtw89_info(rtwdev, "R_BE_SEC_ERROR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_ERROR_IMR));
   rtw89_info(rtwdev, "R_BE_SEC_ENG_CTRL=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_ENG_CTRL));
   rtw89_info(rtwdev, "R_BE_SEC_MPDU_PROC=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_MPDU_PROC));
   rtw89_info(rtwdev, "R_BE_SEC_CAM_ACCESS=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_CAM_ACCESS));
   rtw89_info(rtwdev, "R_BE_SEC_CAM_RDATA=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_CAM_RDATA));
   rtw89_info(rtwdev, "R_BE_SEC_DEBUG2=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_SEC_DEBUG2));
  } else {
   rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_DEBUG));
   rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
   rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
   rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
   rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
   rtw89_info(rtwdev, "R_AX_SEC_CAM_WDATA=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA));
   rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
   rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
   rtw89_info(rtwdev, "R_AX_SEC_TRX_PKT_CNT=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT));
   rtw89_info(rtwdev, "R_AX_SEC_TRX_BLK_CNT=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT));
  }
 }

 if (dmac_err & B_AX_MPDU_ERR_FLAG) {
  rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR));
  rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR));
 }

 if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) {
  if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_INTERRUPT_MASK_REG=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_INTERRUPT_MASK_REG));
   rtw89_info(rtwdev, "R_BE_INTERRUPT_STS_REG=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_INTERRUPT_STS_REG));
  } else {
   rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR));
  }
 }

 if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) {
  rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
  rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
 }

 if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) {
  if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR));
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR));
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR));
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR));
  } else {
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR));
   rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1));
  }
 }

 if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) {
  rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
  rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
  rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_0=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0));
  rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_1=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1));
  rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_2=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2));
  rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_0=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0));
  rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_1=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1));
  rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_2=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2));
  if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_3=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_3));
   rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_STATUS=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_STATUS));
   rtw89_info(rtwdev, "R_BE_PLE_CPUQ_OP_3=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_3));
   rtw89_info(rtwdev, "R_BE_PL_CPUQ_OP_STATUS=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_STATUS));
  } else {
   rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS));
   rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS));
   if (chip->chip_id == RTL8852C) {
    rtw89_info(rtwdev, "R_AX_RX_CTRL0=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RX_CTRL0));
    rtw89_info(rtwdev, "R_AX_RX_CTRL1=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RX_CTRL1));
    rtw89_info(rtwdev, "R_AX_RX_CTRL2=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RX_CTRL2));
   } else {
    rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0));
    rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1));
    rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n",
        rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2));
   }
  }
 }

 if (dmac_err & B_AX_PKTIN_ERR_FLAG) {
  rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR));
  rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR));
 }

 if (dmac_err & B_AX_DISPATCH_ERR_FLAG) {
  if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_DISP_HOST_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_HOST_IMR));
   rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR1=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR1));
   rtw89_info(rtwdev, "R_BE_DISP_CPU_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_CPU_IMR));
   rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR2=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR2));
   rtw89_info(rtwdev, "R_BE_DISP_OTHER_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_OTHER_IMR));
   rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR0=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR0));
  } else {
   rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
   rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
   rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
  }
 }

 if (dmac_err & B_AX_BBRPT_ERR_FLAG) {
  if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR));
   rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
   rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
  } else {
   rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR));
   rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
   rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
   rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
  }
  if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_IMR));
   rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_ISR));
  }
 }

 if (dmac_err & B_AX_HAXIDMA_ERR_FLAG) {
  if (chip->chip_id == RTL8922A) {
   rtw89_info(rtwdev, "R_BE_HAXI_IDCT_MSK=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_HAXI_IDCT_MSK));
   rtw89_info(rtwdev, "R_BE_HAXI_IDCT=0x%08x\n",
       rtw89_read32(rtwdev, R_BE_HAXI_IDCT));
  } else if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK));
   rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n",
       rtw89_read32(rtwdev, R_AX_HAXI_IDCT));
  }
 }

 if (dmac_err & B_BE_P_AXIDMA_ERR_INT) {
  rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT_MSK=0x%08x\n",
      rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT_MSK,
           RTW89_MAC_MEM_AXIDMA));
  rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT=0x%08x\n",
      rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT,
           RTW89_MAC_MEM_AXIDMA));
 }

 if (dmac_err & B_BE_MLO_ERR_INT) {
  rtw89_info(rtwdev, "R_BE_MLO_ERR_IDCT_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_IMR));
  rtw89_info(rtwdev, "R_BE_PKTIN_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_ISR));
 }

 if (dmac_err & B_BE_PLRLS_ERR_INT) {
  rtw89_info(rtwdev, "R_BE_PLRLS_ERR_IMR=0x%08x\n",
      rtw89_read32(rtwdev, R_BE_PLRLS_ERR_IMR));
  rtw89_info(rtwdev, "R_BE_PLRLS_ERR_ISR=0x%08x\n",
      rtw89_read32(rtwdev, R_BE_PLRLS_ERR_ISR));
 }
}

static void rtw89_mac_dump_cmac_err_status_ax(struct rtw89_dev *rtwdev,
           u8 band)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 u32 offset = 0;
 u32 cmac_err;
 int ret;

 ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL);
 if (ret) {
  if (band)
   rtw89_warn(rtwdev, "[CMAC] : CMAC1 not enabled\n");
  else
   rtw89_warn(rtwdev, "[CMAC] : CMAC0 not enabled\n");
  return;
 }

 if (band)
  offset = RTW89_MAC_AX_BAND_REG_OFFSET;

 cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset);
 rtw89_info(rtwdev, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band,
     rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset));
 rtw89_info(rtwdev, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band,
     rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset));
 rtw89_info(rtwdev, "R_AX_CK_EN [%d]=0x%08x\n", band,
     rtw89_read32(rtwdev, R_AX_CK_EN + offset));

 if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) {
  rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset));
  rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset));
 }

 if (cmac_err & B_AX_PTCL_TOP_ERR_IND) {
  rtw89_info(rtwdev, "R_AX_PTCL_IMR0 [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset));
  rtw89_info(rtwdev, "R_AX_PTCL_ISR0 [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset));
 }

 if (cmac_err & B_AX_DMA_TOP_ERR_IND) {
  if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset));
   rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset));
  } else {
   rtw89_info(rtwdev, "R_AX_DLE_CTRL [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset));
  }
 }

 if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) {
  if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset));
   rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
  } else {
   rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
  }
 }

 if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) {
  rtw89_info(rtwdev, "R_AX_TXPWR_IMR [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset));
  rtw89_info(rtwdev, "R_AX_TXPWR_ISR [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset));
 }

 if (cmac_err & B_AX_WMAC_TX_ERR_IND) {
  if (chip->chip_id == RTL8852C) {
   rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA + offset));
   rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA_MASK + offset));
  } else {
   rtw89_info(rtwdev, "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n", band,
       rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR + offset));
  }
  rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band,
      rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset));
 }

 rtw89_info(rtwdev, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band,
     rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset));
}

static void rtw89_mac_dump_err_status_ax(struct rtw89_dev *rtwdev,
      enum mac_ax_err_info err)
{
 if (err != MAC_AX_ERR_L1_ERR_DMAC &&
     err != MAC_AX_ERR_L0_PROMOTE_TO_L1 &&
     err != MAC_AX_ERR_L0_ERR_CMAC0 &&
     err != MAC_AX_ERR_L0_ERR_CMAC1 &&
     err != MAC_AX_ERR_RXI300)
  return;

 rtw89_info(rtwdev, "--->\nerr=0x%x\n", err);
 rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n",
     rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
 rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n",
     rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
 rtw89_info(rtwdev, "DBG Counter 1 (R_AX_DRV_FW_HSK_4)=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_4));
 rtw89_info(rtwdev, "DBG Counter 2 (R_AX_DRV_FW_HSK_5)=0x%08x\n",
     rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_5));

 rtw89_mac_dump_dmac_err_status(rtwdev);
 rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_0);
 rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_1);

 rtwdev->hci.ops->dump_err_status(rtwdev);

 if (err == MAC_AX_ERR_L0_PROMOTE_TO_L1)
  rtw89_mac_dump_l0_to_l1(rtwdev, err);

 rtw89_info(rtwdev, "<---\n");
}

static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
{
 struct rtw89_ser *ser = &rtwdev->ser;
 u32 dmac_err, imr, isr;
 int ret;

 if (rtwdev->chip->chip_id == RTL8852C) {
  ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
  if (ret)
   return true;

  if (err == MAC_AX_ERR_L1_ERR_DMAC) {
   dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
   imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR);
   isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR);

   if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) &&
       ((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) {
    set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags);
    return true;
   }
  } else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) {
   if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
    return true;
  } else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) {
   if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
    return true;
  }
 }

 return false;
}

u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 u32 err, err_scnr;
 int ret;

 ret = read_poll_timeout(rtw89_read32, err, (err != 0), 1000, 100000,
    false, rtwdev, R_AX_HALT_C2H_CTRL);
 if (ret) {
  rtw89_warn(rtwdev, "Polling FW err status fail\n");
  return ret;
 }

 err = rtw89_read32(rtwdev, R_AX_HALT_C2H);
 rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);

 err_scnr = RTW89_ERROR_SCENARIO(err);
 if (err_scnr == RTW89_WCPU_CPU_EXCEPTION)
  err = MAC_AX_ERR_CPU_EXCEPTION;
 else if (err_scnr == RTW89_WCPU_ASSERTION)
  err = MAC_AX_ERR_ASSERTION;
 else if (err_scnr == RTW89_RXI300_ERROR)
  err = MAC_AX_ERR_RXI300;

 if (rtw89_mac_suppress_log(rtwdev, err))
  return err;

 rtw89_fw_st_dbg_dump(rtwdev);
 mac->dump_err_status(rtwdev, err);

 return err;
}
EXPORT_SYMBOL(rtw89_mac_get_err_status);

int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
{
 struct rtw89_ser *ser = &rtwdev->ser;
 u32 halt;
 int ret = 0;

 if (err > MAC_AX_SET_ERR_MAX) {
  rtw89_err(rtwdev, "Bad set-err-status value 0x%08x\n", err);
  return -EINVAL;
 }

 ret = read_poll_timeout(rtw89_read32, halt, (halt == 0x0), 1000,
    100000, false, rtwdev, R_AX_HALT_H2C_CTRL);
 if (ret) {
  rtw89_err(rtwdev, "FW doesn't receive previous msg\n");
  return -EFAULT;
 }

 rtw89_write32(rtwdev, R_AX_HALT_H2C, err);

 if (ser->prehandle_l1 &&
     (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
  return 0;

 rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);

 return 0;
}
EXPORT_SYMBOL(rtw89_mac_set_err_status);

static int hfc_reset_param(struct rtw89_dev *rtwdev)
{
 const struct rtw89_hfc_param_ini *param_ini, *param_inis;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 u8 qta_mode = rtwdev->mac.dle_info.qta_mode;

 param_inis = rtwdev->chip->hfc_param_ini[rtwdev->hci.type];
 if (!param_inis)
  return -EINVAL;

 param_ini = ¶m_inis[qta_mode];

 param->en = 0;

 if (param_ini->pub_cfg)
  param->pub_cfg = *param_ini->pub_cfg;

 if (param_ini->prec_cfg)
  param->prec_cfg = *param_ini->prec_cfg;

 if (param_ini->ch_cfg)
  param->ch_cfg = param_ini->ch_cfg;

 memset(¶m->ch_info, 0, sizeof(param->ch_info));
 memset(¶m->pub_info, 0, sizeof(param->pub_info));
 param->mode = param_ini->mode;

 return 0;
}

static int hfc_ch_cfg_chk(struct rtw89_dev *rtwdev, u8 ch)
{
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_ch_cfg *ch_cfg = param->ch_cfg;
 const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
 const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;

 if (ch >= RTW89_DMA_CH_NUM)
  return -EINVAL;

 if ((ch_cfg[ch].min && ch_cfg[ch].min < prec_cfg->ch011_prec) ||
     ch_cfg[ch].max > pub_cfg->pub_max)
  return -EINVAL;
 if (ch_cfg[ch].grp >= grp_num)
  return -EINVAL;

 return 0;
}

static int hfc_pub_info_chk(struct rtw89_dev *rtwdev)
{
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_pub_cfg *cfg = ¶m->pub_cfg;
 struct rtw89_hfc_pub_info *info = ¶m->pub_info;

 if (info->g0_used + info->g1_used + info->pub_aval != cfg->pub_max) {
  if (rtwdev->chip->chip_id == RTL8852A)
   return 0;
  else
   return -EFAULT;
 }

 return 0;
}

static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev)
{
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;

 if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max)
  return -EFAULT;

 return 0;
}

static int hfc_ch_ctrl(struct rtw89_dev *rtwdev, u8 ch)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
 int ret = 0;
 u32 val = 0;

 ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
 if (ret)
  return ret;

 ret = hfc_ch_cfg_chk(rtwdev, ch);
 if (ret)
  return ret;

 if (ch > RTW89_DMA_B1HI)
  return -EINVAL;

 val = u32_encode_bits(cfg[ch].min, B_AX_MIN_PG_MASK) |
       u32_encode_bits(cfg[ch].max, B_AX_MAX_PG_MASK) |
       (cfg[ch].grp ? B_AX_GRP : 0);
 rtw89_write32(rtwdev, regs->ach_page_ctrl + ch * 4, val);

 return 0;
}

static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 struct rtw89_hfc_ch_info *info = param->ch_info;
 const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
 u32 val;
 u32 ret;

 ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
 if (ret)
  return ret;

 if (ch > RTW89_DMA_H2C)
  return -EINVAL;

 val = rtw89_read32(rtwdev, regs->ach_page_info + ch * 4);
 info[ch].aval = u32_get_bits(val, B_AX_AVAL_PG_MASK);
 if (ch < RTW89_DMA_H2C)
  info[ch].used = u32_get_bits(val, B_AX_USE_PG_MASK);
 else
  info[ch].used = cfg[ch].min - info[ch].aval;

 return 0;
}

static int hfc_pub_ctrl(struct rtw89_dev *rtwdev)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 const struct rtw89_hfc_pub_cfg *cfg = &rtwdev->mac.hfc_param.pub_cfg;
 u32 val;
 int ret;

 ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
 if (ret)
  return ret;

 ret = hfc_pub_cfg_chk(rtwdev);
 if (ret)
  return ret;

 val = u32_encode_bits(cfg->grp0, B_AX_PUBPG_G0_MASK) |
       u32_encode_bits(cfg->grp1, B_AX_PUBPG_G1_MASK);
 rtw89_write32(rtwdev, regs->pub_page_ctrl1, val);

 val = u32_encode_bits(cfg->wp_thrd, B_AX_WP_THRD_MASK);
 rtw89_write32(rtwdev, regs->wp_page_ctrl2, val);

 return 0;
}

static void hfc_get_mix_info_ax(struct rtw89_dev *rtwdev)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
 struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
 struct rtw89_hfc_pub_info *info = ¶m->pub_info;
 u32 val;

 val = rtw89_read32(rtwdev, regs->pub_page_info1);
 info->g0_used = u32_get_bits(val, B_AX_G0_USE_PG_MASK);
 info->g1_used = u32_get_bits(val, B_AX_G1_USE_PG_MASK);
 val = rtw89_read32(rtwdev, regs->pub_page_info3);
 info->g0_aval = u32_get_bits(val, B_AX_G0_AVAL_PG_MASK);
 info->g1_aval = u32_get_bits(val, B_AX_G1_AVAL_PG_MASK);
 info->pub_aval =
  u32_get_bits(rtw89_read32(rtwdev, regs->pub_page_info2),
        B_AX_PUB_AVAL_PG_MASK);
 info->wp_aval =
  u32_get_bits(rtw89_read32(rtwdev, regs->wp_page_info1),
        B_AX_WP_AVAL_PG_MASK);

 val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
 param->en = val & B_AX_HCI_FC_EN ? 1 : 0;
 param->h2c_en = val & B_AX_HCI_FC_CH12_EN ? 1 : 0;
 param->mode = u32_get_bits(val, B_AX_HCI_FC_MODE_MASK);
 prec_cfg->ch011_full_cond =
  u32_get_bits(val, B_AX_HCI_FC_WD_FULL_COND_MASK);
 prec_cfg->h2c_full_cond =
  u32_get_bits(val, B_AX_HCI_FC_CH12_FULL_COND_MASK);
 prec_cfg->wp_ch07_full_cond =
  u32_get_bits(val, B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
 prec_cfg->wp_ch811_full_cond =
  u32_get_bits(val, B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);

 val = rtw89_read32(rtwdev, regs->ch_page_ctrl);
 prec_cfg->ch011_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH011_MASK);
 prec_cfg->h2c_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH12_MASK);

 val = rtw89_read32(rtwdev, regs->pub_page_ctrl2);
 pub_cfg->pub_max = u32_get_bits(val, B_AX_PUBPG_ALL_MASK);

 val = rtw89_read32(rtwdev, regs->wp_page_ctrl1);
 prec_cfg->wp_ch07_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH07_MASK);
 prec_cfg->wp_ch811_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH811_MASK);

 val = rtw89_read32(rtwdev, regs->wp_page_ctrl2);
 pub_cfg->wp_thrd = u32_get_bits(val, B_AX_WP_THRD_MASK);

 val = rtw89_read32(rtwdev, regs->pub_page_ctrl1);
 pub_cfg->grp0 = u32_get_bits(val, B_AX_PUBPG_G0_MASK);
 pub_cfg->grp1 = u32_get_bits(val, B_AX_PUBPG_G1_MASK);
}

static int hfc_upd_mix_info(struct rtw89_dev *rtwdev)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 int ret;

 ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
 if (ret)
  return ret;

 mac->hfc_get_mix_info(rtwdev);

 ret = hfc_pub_info_chk(rtwdev);
 if (param->en && ret)
  return ret;

 return 0;
}

static void hfc_h2c_cfg_ax(struct rtw89_dev *rtwdev)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
 u32 val;

 val = u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
 rtw89_write32(rtwdev, regs->ch_page_ctrl, val);

 rtw89_write32_mask(rtwdev, regs->hci_fc_ctrl,
      B_AX_HCI_FC_CH12_FULL_COND_MASK,
      prec_cfg->h2c_full_cond);
}

static void hfc_mix_cfg_ax(struct rtw89_dev *rtwdev)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
 const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
 u32 val;

 val = u32_encode_bits(prec_cfg->ch011_prec, B_AX_PREC_PAGE_CH011_MASK) |
       u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
 rtw89_write32(rtwdev, regs->ch_page_ctrl, val);

 val = u32_encode_bits(pub_cfg->pub_max, B_AX_PUBPG_ALL_MASK);
 rtw89_write32(rtwdev, regs->pub_page_ctrl2, val);

 val = u32_encode_bits(prec_cfg->wp_ch07_prec,
         B_AX_PREC_PAGE_WP_CH07_MASK) |
       u32_encode_bits(prec_cfg->wp_ch811_prec,
         B_AX_PREC_PAGE_WP_CH811_MASK);
 rtw89_write32(rtwdev, regs->wp_page_ctrl1, val);

 val = u32_replace_bits(rtw89_read32(rtwdev, regs->hci_fc_ctrl),
          param->mode, B_AX_HCI_FC_MODE_MASK);
 val = u32_replace_bits(val, prec_cfg->ch011_full_cond,
          B_AX_HCI_FC_WD_FULL_COND_MASK);
 val = u32_replace_bits(val, prec_cfg->h2c_full_cond,
          B_AX_HCI_FC_CH12_FULL_COND_MASK);
 val = u32_replace_bits(val, prec_cfg->wp_ch07_full_cond,
          B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
 val = u32_replace_bits(val, prec_cfg->wp_ch811_full_cond,
          B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);
 rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
}

static void hfc_func_en_ax(struct rtw89_dev *rtwdev, bool en, bool h2c_en)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_page_regs *regs = chip->page_regs;
 struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
 u32 val;

 val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
 param->en = en;
 param->h2c_en = h2c_en;
 val = en ? (val | B_AX_HCI_FC_EN) : (val & ~B_AX_HCI_FC_EN);
 val = h2c_en ? (val | B_AX_HCI_FC_CH12_EN) :
    (val & ~B_AX_HCI_FC_CH12_EN);
 rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
}

int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_en)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 const struct rtw89_chip_info *chip = rtwdev->chip;
 u32 dma_ch_mask = chip->dma_ch_mask;
 u8 ch;
 u32 ret = 0;

 if (reset)
  ret = hfc_reset_param(rtwdev);
 if (ret)
  return ret;

 ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
 if (ret)
  return ret;

 mac->hfc_func_en(rtwdev, falsefalse);

 if (!en && h2c_en) {
  mac->hfc_h2c_cfg(rtwdev);
  mac->hfc_func_en(rtwdev, en, h2c_en);
  return ret;
 }

 for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
  if (dma_ch_mask & BIT(ch))
   continue;
  ret = hfc_ch_ctrl(rtwdev, ch);
  if (ret)
   return ret;
 }

 ret = hfc_pub_ctrl(rtwdev);
 if (ret)
  return ret;

 mac->hfc_mix_cfg(rtwdev);
 if (en || h2c_en) {
  mac->hfc_func_en(rtwdev, en, h2c_en);
  udelay(10);
 }
 for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
  if (dma_ch_mask & BIT(ch))
   continue;
  ret = hfc_upd_ch_info(rtwdev, ch);
  if (ret)
   return ret;
 }
 ret = hfc_upd_mix_info(rtwdev);

 return ret;
}

#define PWR_POLL_CNT 2000
static int pwr_cmd_poll(struct rtw89_dev *rtwdev,
   const struct rtw89_pwr_cfg *cfg)
{
 u8 val = 0;
 int ret;
 u32 addr = cfg->base == PWR_INTF_MSK_SDIO ?
     cfg->addr | SDIO_LOCAL_BASE_ADDR : cfg->addr;

 ret = read_poll_timeout(rtw89_read8, val, !((val ^ cfg->val) & cfg->msk),
    1000, 1000 * PWR_POLL_CNT, false, rtwdev, addr);

 if (!ret)
  return 0;

 rtw89_warn(rtwdev, "[ERR] Polling timeout\n");
 rtw89_warn(rtwdev, "[ERR] addr: %X, %X\n", addr, cfg->addr);
 rtw89_warn(rtwdev, "[ERR] val: %X, %X\n", val, cfg->val);

 return -EBUSY;
}

static int rtw89_mac_sub_pwr_seq(struct rtw89_dev *rtwdev, u8 cv_msk,
     u8 intf_msk, const struct rtw89_pwr_cfg *cfg)
{
 const struct rtw89_pwr_cfg *cur_cfg;
 u32 addr;
 u8 val;

 for (cur_cfg = cfg; cur_cfg->cmd != PWR_CMD_END; cur_cfg++) {
  if (!(cur_cfg->intf_msk & intf_msk) ||
      !(cur_cfg->cv_msk & cv_msk))
   continue;

  switch (cur_cfg->cmd) {
  case PWR_CMD_WRITE:
   addr = cur_cfg->addr;

   if (cur_cfg->base == PWR_BASE_SDIO)
    addr |= SDIO_LOCAL_BASE_ADDR;

   val = rtw89_read8(rtwdev, addr);
   val &= ~(cur_cfg->msk);
   val |= (cur_cfg->val & cur_cfg->msk);

   rtw89_write8(rtwdev, addr, val);
   break;
  case PWR_CMD_POLL:
   if (pwr_cmd_poll(rtwdev, cur_cfg))
    return -EBUSY;
   break;
  case PWR_CMD_DELAY:
   if (cur_cfg->val == PWR_DELAY_US)
    udelay(cur_cfg->addr);
   else
    fsleep(cur_cfg->addr * 1000);
   break;
  default:
   return -EINVAL;
  }
 }

 return 0;
}

static int rtw89_mac_pwr_seq(struct rtw89_dev *rtwdev,
        const struct rtw89_pwr_cfg * const *cfg_seq)
{
 int ret;

 for (; *cfg_seq; cfg_seq++) {
  ret = rtw89_mac_sub_pwr_seq(rtwdev, BIT(rtwdev->hal.cv),
         PWR_INTF_MSK_PCIE, *cfg_seq);
  if (ret)
   return -EBUSY;
 }

 return 0;
}

static enum rtw89_rpwm_req_pwr_state
rtw89_mac_get_req_pwr_state(struct rtw89_dev *rtwdev)
{
 enum rtw89_rpwm_req_pwr_state state;

 switch (rtwdev->ps_mode) {
 case RTW89_PS_MODE_RFOFF:
  state = RTW89_MAC_RPWM_REQ_PWR_STATE_BAND0_RFOFF;
  break;
 case RTW89_PS_MODE_CLK_GATED:
  state = RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED;
  break;
 case RTW89_PS_MODE_PWR_GATED:
  state = RTW89_MAC_RPWM_REQ_PWR_STATE_PWR_GATED;
  break;
 default:
  state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
  break;
 }
 return state;
}

static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
    enum rtw89_rpwm_req_pwr_state req_pwr_state,
    bool notify_wake)
{
 u16 request;

 spin_lock_bh(&rtwdev->rpwm_lock);

 request = rtw89_read16(rtwdev, R_AX_RPWM);
 request ^= request | PS_RPWM_TOGGLE;
 request |= req_pwr_state;

 if (notify_wake) {
  request |= PS_RPWM_NOTIFY_WAKE;
 } else {
  rtwdev->mac.rpwm_seq_num = (rtwdev->mac.rpwm_seq_num + 1) &
         RPWM_SEQ_NUM_MAX;
  request |= FIELD_PREP(PS_RPWM_SEQ_NUM,
          rtwdev->mac.rpwm_seq_num);

  if (req_pwr_state < RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
   request |= PS_RPWM_ACK;
 }
 rtw89_write16(rtwdev, rtwdev->hci.rpwm_addr, request);

 spin_unlock_bh(&rtwdev->rpwm_lock);
}

static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
          enum rtw89_rpwm_req_pwr_state req_pwr_state)
{
 bool request_deep_mode;
 bool in_deep_mode;
 u8 rpwm_req_num;
 u8 cpwm_rsp_seq;
 u8 cpwm_seq;
 u8 cpwm_status;

 if (req_pwr_state >= RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
  request_deep_mode = true;
 else
  request_deep_mode = false;

 if (rtw89_read32_mask(rtwdev, R_AX_LDM, B_AX_EN_32K))
  in_deep_mode = true;
 else
  in_deep_mode = false;

 if (request_deep_mode != in_deep_mode)
  return -EPERM;

 if (request_deep_mode)
  return 0;

 rpwm_req_num = rtwdev->mac.rpwm_seq_num;
 cpwm_rsp_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr,
      PS_CPWM_RSP_SEQ_NUM);

 if (rpwm_req_num != cpwm_rsp_seq)
  return -EPERM;

 rtwdev->mac.cpwm_seq_num = (rtwdev->mac.cpwm_seq_num + 1) &
        CPWM_SEQ_NUM_MAX;

 cpwm_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_SEQ_NUM);
 if (cpwm_seq != rtwdev->mac.cpwm_seq_num)
  return -EPERM;

 cpwm_status = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_STATE);
 if (cpwm_status != req_pwr_state)
  return -EPERM;

 return 0;
}

void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
{
 enum rtw89_rpwm_req_pwr_state state;
 unsigned long delay = enter ? 10 : 150;
 int ret;
 int i;

 if (enter)
  state = rtw89_mac_get_req_pwr_state(rtwdev);
 else
  state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;

 for (i = 0; i < RPWM_TRY_CNT; i++) {
  rtw89_mac_send_rpwm(rtwdev, state, false);
  ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret,
            !ret, delay, 15000, false,
            rtwdev, state);
  if (!ret)
   break;

  if (i == RPWM_TRY_CNT - 1)
   rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
      enter ? "entering" : "leaving");
  else
   rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
        "%d time firmware failed to ack for %s ps mode\n",
        i + 1, enter ? "entering" : "leaving");
 }
}

void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
{
 enum rtw89_rpwm_req_pwr_state state;

 state = rtw89_mac_get_req_pwr_state(rtwdev);
 rtw89_mac_send_rpwm(rtwdev, state, true);
}

static void rtw89_mac_power_switch_boot_mode(struct rtw89_dev *rtwdev)
{
 u32 boot_mode;

 if (rtwdev->hci.type != RTW89_HCI_TYPE_USB)
  return;

 boot_mode = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
 if (!boot_mode)
  return;

 rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
 rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
 rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
 rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
}

static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
{
#define PWR_ACT 1
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 const struct rtw89_chip_info *chip = rtwdev->chip;
 const struct rtw89_pwr_cfg * const *cfg_seq;
 int (*cfg_func)(struct rtw89_dev *rtwdev);
 int ret;
 u8 val;

 rtw89_mac_power_switch_boot_mode(rtwdev);

 if (on) {
  cfg_seq = chip->pwr_on_seq;
  cfg_func = chip->ops->pwr_on_func;
 } else {
  cfg_seq = chip->pwr_off_seq;
  cfg_func = chip->ops->pwr_off_func;
 }

 if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
  __rtw89_leave_ps_mode(rtwdev);

 val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK);
 if (on && val == PWR_ACT) {
  rtw89_err(rtwdev, "MAC has already powered on\n");
  return -EBUSY;
 }

 ret = cfg_func ? cfg_func(rtwdev) : rtw89_mac_pwr_seq(rtwdev, cfg_seq);
 if (ret)
  return ret;

 if (on) {
  if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
   mac->efuse_read_fw_secure(rtwdev);

  set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
  set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
  set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
  rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_TP_MAJOR);
 } else {
  clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
  clear_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
  clear_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
  clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
  clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
  rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
  rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false);
  rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false);
 }

 return 0;
#undef PWR_ACT
}

int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev)
{
 int ret;

 ret = rtw89_mac_power_switch(rtwdev, true);
 if (ret) {
  rtw89_mac_power_switch(rtwdev, false);
  ret = rtw89_mac_power_switch(rtwdev, true);
  if (ret)
   return ret;
 }

 return 0;
}

void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev)
{
 rtw89_mac_power_switch(rtwdev, false);
}

static int cmac_func_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
{
 u32 func_en = 0;
 u32 ck_en = 0;
 u32 c1pc_en = 0;
 u32 addrl_func_en[] = {R_AX_CMAC_FUNC_EN, R_AX_CMAC_FUNC_EN_C1};
 u32 addrl_ck_en[] = {R_AX_CK_EN, R_AX_CK_EN_C1};

 func_en = B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN |
   B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN | B_AX_PTCLTOP_EN |
   B_AX_SCHEDULER_EN | B_AX_TMAC_EN | B_AX_RMAC_EN |
   B_AX_CMAC_CRPRT;
 ck_en = B_AX_CMAC_CKEN | B_AX_PHYINTF_CKEN | B_AX_CMAC_DMA_CKEN |
        B_AX_PTCLTOP_CKEN | B_AX_SCHEDULER_CKEN | B_AX_TMAC_CKEN |
        B_AX_RMAC_CKEN;
 c1pc_en = B_AX_R_SYM_WLCMAC1_PC_EN |
   B_AX_R_SYM_WLCMAC1_P1_PC_EN |
   B_AX_R_SYM_WLCMAC1_P2_PC_EN |
   B_AX_R_SYM_WLCMAC1_P3_PC_EN |
   B_AX_R_SYM_WLCMAC1_P4_PC_EN;

 if (en) {
  if (mac_idx == RTW89_MAC_1) {
   rtw89_write32_set(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
   rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
       B_AX_R_SYM_ISO_CMAC12PP);
   rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
       B_AX_CMAC1_FEN);
  }
  rtw89_write32_set(rtwdev, addrl_ck_en[mac_idx], ck_en);
  rtw89_write32_set(rtwdev, addrl_func_en[mac_idx], func_en);
 } else {
  rtw89_write32_clr(rtwdev, addrl_func_en[mac_idx], func_en);
  rtw89_write32_clr(rtwdev, addrl_ck_en[mac_idx], ck_en);
  if (mac_idx == RTW89_MAC_1) {
   rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
       B_AX_CMAC1_FEN);
   rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
       B_AX_R_SYM_ISO_CMAC12PP);
   rtw89_write32_clr(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
  }
 }

 return 0;
}

static int dmac_func_en_ax(struct rtw89_dev *rtwdev)
{
 enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
 u32 val32;

 if (chip_id == RTL8852C)
  val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
    B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
    B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
    B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
    B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
    B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
    B_AX_DMAC_CRPRT | B_AX_H_AXIDMA_EN);
 else
  val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
    B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
    B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
    B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
    B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
    B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
    B_AX_DMAC_CRPRT);
 rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val32);

 val32 = (B_AX_MAC_SEC_CLK_EN | B_AX_DISPATCHER_CLK_EN |
   B_AX_DLE_CPUIO_CLK_EN | B_AX_PKT_IN_CLK_EN |
   B_AX_STA_SCH_CLK_EN | B_AX_TXPKT_CTRL_CLK_EN |
   B_AX_WD_RLS_CLK_EN | B_AX_BBRPT_CLK_EN);
 if (chip_id == RTL8852BT)
  val32 |= B_AX_AXIDMA_CLK_EN;
 rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val32);

 return 0;
}

static int chip_func_en_ax(struct rtw89_dev *rtwdev)
{
 enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;

 if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
  rtw89_write32_set(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
      B_AX_OCP_L1_MASK);

 return 0;
}

static int sys_init_ax(struct rtw89_dev *rtwdev)
{
 int ret;

 ret = dmac_func_en_ax(rtwdev);
 if (ret)
  return ret;

 ret = cmac_func_en_ax(rtwdev, 0, true);
 if (ret)
  return ret;

 ret = chip_func_en_ax(rtwdev);
 if (ret)
  return ret;

 return ret;
}

const struct rtw89_mac_size_set rtw89_mac_size = {
 .hfc_preccfg_pcie = {2, 40, 0, 0, 1, 0, 0, 0},
 .hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0},
 .hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0},
 /* PCIE 64 */
 .wde_size0 = {RTW89_WDE_PG_64, 4095, 1,},
 .wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,},
 /* DLFW */
 .wde_size4 = {RTW89_WDE_PG_64, 0, 4096,},
 .wde_size4_v1 = {RTW89_WDE_PG_64, 0, 3328, 0,},
 /* PCIE 64 */
 .wde_size6 = {RTW89_WDE_PG_64, 512, 0,},
 /* 8852B PCIE SCC */
 .wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
 /* DLFW */
 .wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
 /* 8852C DLFW */
 .wde_size18 = {RTW89_WDE_PG_64, 0, 2048,},
 /* 8852C PCIE SCC */
 .wde_size19 = {RTW89_WDE_PG_64, 3328, 0,},
 .wde_size23 = {RTW89_WDE_PG_64, 1022, 2,},
 /* 8852B USB2.0/USB3.0 SCC */
 .wde_size25 = {RTW89_WDE_PG_64, 162, 94,},
 /* PCIE */
 .ple_size0 = {RTW89_PLE_PG_128, 1520, 16,},
 .ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,},
 .ple_size3_v1 = {RTW89_PLE_PG_128, 2928, 0, 212992,},
 /* DLFW */
 .ple_size4 = {RTW89_PLE_PG_128, 64, 1472,},
 /* PCIE 64 */
 .ple_size6 = {RTW89_PLE_PG_128, 496, 16,},
 /* DLFW */
 .ple_size8 = {RTW89_PLE_PG_128, 64, 960,},
 .ple_size9 = {RTW89_PLE_PG_128, 2288, 16,},
 /* 8852C DLFW */
 .ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
 /* 8852C PCIE SCC */
 .ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
 /* 8852B USB2.0 SCC */
 .ple_size32 = {RTW89_PLE_PG_128, 620, 20,},
 /* 8852B USB3.0 SCC */
 .ple_size33 = {RTW89_PLE_PG_128, 632, 8,},
 /* PCIE 64 */
 .wde_qt0 = {3792, 196, 0, 107,},
 .wde_qt0_v1 = {3302, 6, 0, 20,},
 /* DLFW */
 .wde_qt4 = {0, 0, 0, 0,},
 /* PCIE 64 */
 .wde_qt6 = {448, 48, 0, 16,},
 /* 8852B PCIE SCC */
 .wde_qt7 = {446, 48, 0, 16,},
 /* 8852C DLFW */
 .wde_qt17 = {0, 0, 0,  0,},
 /* 8852C PCIE SCC */
 .wde_qt18 = {3228, 60, 0, 40,},
 .wde_qt23 = {958, 48, 0, 16,},
 /* 8852B USB2.0/USB3.0 SCC */
 .wde_qt25 = {152, 2, 0, 8,},
 .ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,},
 .ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,},
 /* PCIE SCC */
 .ple_qt4 = {264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8,},
 /* PCIE SCC */
 .ple_qt5 = {264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120,},
 .ple_qt9 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0,},
 /* DLFW */
 .ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,},
 /* PCIE 64 */
 .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,},
 /* DLFW 52C */
 .ple_qt44 = {0, 0, 16, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
 /* DLFW 52C */
 .ple_qt45 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
 /* 8852C PCIE SCC */
 .ple_qt46 = {525, 0, 16, 20, 13, 13, 178, 0, 32, 62, 8, 16,},
 /* 8852C PCIE SCC */
 .ple_qt47 = {525, 0, 32, 20, 1034, 13, 1199, 0, 1053, 62, 160, 1037,},
 .ple_qt57 = {147, 0, 16, 20, 13, 13, 178, 0, 32, 14, 8, 0,},
 /* PCIE 64 */
 .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,},
 .ple_qt59 = {147, 0, 32, 20, 1860, 13, 2025, 0, 1879, 14, 24, 0,},
 /* USB2.0 52B SCC */
 .ple_qt72 = {130, 0, 16, 48, 4, 13, 322, 0, 32, 14, 8, 0, 0,},
 /* USB2.0 52B 92K */
 .ple_qt73 = {130, 0, 32, 48, 37, 13, 355, 0, 65, 14, 24, 0, 0,},
 /* USB3.0 52B 92K */
 .ple_qt74 = {286, 0, 16, 48, 4, 13, 178, 0, 32, 14, 8, 0, 0,},
 .ple_qt75 = {286, 0, 32, 48, 37, 13, 211, 0, 65, 14, 24, 0, 0,},
 /* 8852A PCIE WOW */
 .ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
 /* 8852B PCIE WOW */
 .ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
 /* 8852BT PCIE WOW */
 .ple_qt_52bt_wow = {147, 0, 32, 20, 1860, 13, 1929, 0, 1879, 14, 24, 0,},
 /* 8851B PCIE WOW */
 .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
 .ple_rsvd_qt0 = {2, 107, 107, 6, 6, 6, 6, 0, 0, 0,},
 .ple_rsvd_qt1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
 .rsvd0_size0 = {212992, 0,},
 .rsvd1_size0 = {587776, 2048,},
};
EXPORT_SYMBOL(rtw89_mac_size);

static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
         enum rtw89_qta_mode mode)
{
 struct rtw89_mac_info *mac = &rtwdev->mac;
 const struct rtw89_dle_mem *cfg, *cfgs;

 cfgs = rtwdev->chip->dle_mem[rtwdev->hci.dle_type];
 if (!cfgs)
  return NULL;

 cfg = &cfgs[mode];
 if (cfg->mode != mode) {
  rtw89_warn(rtwdev, "qta mode unmatch!\n");
  return NULL;
 }

 mac->dle_info.rsvd_qt = cfg->rsvd_qt;
 mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
 mac->dle_info.ple_free_pg = cfg->ple_size->lnk_pge_num;
 mac->dle_info.qta_mode = mode;
 mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma;
 mac->dle_info.c1_rx_qta = cfg->ple_min_qt->cma1_dma;

 return cfg;
}

int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
      enum rtw89_mac_dle_rsvd_qt_type type,
      struct rtw89_mac_dle_rsvd_qt_cfg *cfg)
{
 struct rtw89_dle_info *dle_info = &rtwdev->mac.dle_info;
 const struct rtw89_rsvd_quota *rsvd_qt = dle_info->rsvd_qt;

 switch (type) {
 case DLE_RSVD_QT_MPDU_INFO:
  cfg->pktid = dle_info->ple_free_pg;
  cfg->pg_num = rsvd_qt->mpdu_info_tbl;
  break;
 case DLE_RSVD_QT_B0_CSI:
  cfg->pktid = dle_info->ple_free_pg + rsvd_qt->mpdu_info_tbl;
  cfg->pg_num = rsvd_qt->b0_csi;
  break;
 case DLE_RSVD_QT_B1_CSI:
  cfg->pktid = dle_info->ple_free_pg +
        rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi;
  cfg->pg_num = rsvd_qt->b1_csi;
  break;
 case DLE_RSVD_QT_B0_LMR:
  cfg->pktid = dle_info->ple_free_pg +
        rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi;
  cfg->pg_num = rsvd_qt->b0_lmr;
  break;
 case DLE_RSVD_QT_B1_LMR:
  cfg->pktid = dle_info->ple_free_pg +
        rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
        rsvd_qt->b0_lmr;
  cfg->pg_num = rsvd_qt->b1_lmr;
  break;
 case DLE_RSVD_QT_B0_FTM:
  cfg->pktid = dle_info->ple_free_pg +
        rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
        rsvd_qt->b0_lmr + rsvd_qt->b1_lmr;
  cfg->pg_num = rsvd_qt->b0_ftm;
  break;
 case DLE_RSVD_QT_B1_FTM:
  cfg->pktid = dle_info->ple_free_pg +
        rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
        rsvd_qt->b0_lmr + rsvd_qt->b1_lmr + rsvd_qt->b0_ftm;
  cfg->pg_num = rsvd_qt->b1_ftm;
  break;
 default:
  return -EINVAL;
 }

 cfg->size = (u32)cfg->pg_num * dle_info->ple_pg_size;

 return 0;
}

static bool mac_is_txq_empty_ax(struct rtw89_dev *rtwdev)
{
 struct rtw89_mac_dle_dfi_qempty qempty;
 u32 grpnum, qtmp, val32, msk32;
 int i, j, ret;

 grpnum = rtwdev->chip->wde_qempty_acq_grpnum;
 qempty.dle_type = DLE_CTRL_TYPE_WDE;

 for (i = 0; i < grpnum; i++) {
  qempty.grpsel = i;
  ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
  if (ret) {
   rtw89_warn(rtwdev, "dle dfi acq empty %d\n", ret);
   return false;
  }
  qtmp = qempty.qempty;
  for (j = 0 ; j < QEMP_ACQ_GRP_MACID_NUM; j++) {
   val32 = u32_get_bits(qtmp, QEMP_ACQ_GRP_QSEL_MASK);
   if (val32 != QEMP_ACQ_GRP_QSEL_MASK)
    return false;
   qtmp >>= QEMP_ACQ_GRP_QSEL_SH;
  }
 }

 qempty.grpsel = rtwdev->chip->wde_qempty_mgq_grpsel;
 ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
 if (ret) {
  rtw89_warn(rtwdev, "dle dfi mgq empty %d\n", ret);
  return false;
 }
 msk32 = B_CMAC0_MGQ_NORMAL | B_CMAC0_MGQ_NO_PWRSAV | B_CMAC0_CPUMGQ;
 if ((qempty.qempty & msk32) != msk32)
  return false;

 if (rtwdev->dbcc_en) {
  msk32 |= B_CMAC1_MGQ_NORMAL | B_CMAC1_MGQ_NO_PWRSAV | B_CMAC1_CPUMGQ;
  if ((qempty.qempty & msk32) != msk32)
   return false;
 }

 msk32 = B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU |
  B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_PLE_EMPTY_QTA_DMAC_H2C |
  B_AX_WDE_EMPTY_QUE_OTHERS | B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX |
  B_AX_WDE_EMPTY_QTA_DMAC_CPUIO | B_AX_PLE_EMPTY_QTA_DMAC_CPUIO |
  B_AX_WDE_EMPTY_QUE_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_HIF |
  B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QTA_DMAC_PKTIN |
  B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL | B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL |
  B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX;
 val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0);

 return (val32 & msk32) == msk32;
}

static inline u32 dle_used_size(const struct rtw89_dle_mem *cfg)
{
 const struct rtw89_dle_size *wde = cfg->wde_size;
 const struct rtw89_dle_size *ple = cfg->ple_size;
 u32 used;

 used = wde->pge_size * (wde->lnk_pge_num + wde->unlnk_pge_num) +
        ple->pge_size * (ple->lnk_pge_num + ple->unlnk_pge_num);

 if (cfg->rsvd0_size && cfg->rsvd1_size) {
  used += cfg->rsvd0_size->size;
  used += cfg->rsvd1_size->size;
 }

 return used;
}

static u32 dle_expected_used_size(struct rtw89_dev *rtwdev,
      enum rtw89_qta_mode mode)
{
 u32 size = rtwdev->chip->fifo_size;

 if (mode == RTW89_QTA_SCC)
  size -= rtwdev->chip->dle_scc_rsvd_size;

 return size;
}

static void dle_func_en_ax(struct rtw89_dev *rtwdev, bool enable)
{
 if (enable)
  rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN,
      B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
 else
  rtw89_write32_clr(rtwdev, R_AX_DMAC_FUNC_EN,
      B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
}

static void dle_clk_en_ax(struct rtw89_dev *rtwdev, bool enable)
{
 u32 val = B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN;

 if (enable) {
  if (rtwdev->chip->chip_id == RTL8851B)
   val |= B_AX_AXIDMA_CLK_EN;
  rtw89_write32_set(rtwdev, R_AX_DMAC_CLK_EN, val);
 } else {
  rtw89_write32_clr(rtwdev, R_AX_DMAC_CLK_EN, val);
 }
}

static int dle_mix_cfg_ax(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg)
{
 const struct rtw89_dle_size *size_cfg;
 u32 val;
 u8 bound = 0;

 val = rtw89_read32(rtwdev, R_AX_WDE_PKTBUF_CFG);
 size_cfg = cfg->wde_size;

 switch (size_cfg->pge_size) {
 default:
 case RTW89_WDE_PG_64:
  val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_64,
           B_AX_WDE_PAGE_SEL_MASK);
  break;
 case RTW89_WDE_PG_128:
  val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_128,
           B_AX_WDE_PAGE_SEL_MASK);
  break;
 case RTW89_WDE_PG_256:
  rtw89_err(rtwdev, "[ERR]WDE DLE doesn't support 256 byte!\n");
  return -EINVAL;
 }

 val = u32_replace_bits(val, bound, B_AX_WDE_START_BOUND_MASK);
 val = u32_replace_bits(val, size_cfg->lnk_pge_num,
          B_AX_WDE_FREE_PAGE_NUM_MASK);
 rtw89_write32(rtwdev, R_AX_WDE_PKTBUF_CFG, val);

 val = rtw89_read32(rtwdev, R_AX_PLE_PKTBUF_CFG);
 bound = (size_cfg->lnk_pge_num + size_cfg->unlnk_pge_num)
    * size_cfg->pge_size / DLE_BOUND_UNIT;
 size_cfg = cfg->ple_size;

 switch (size_cfg->pge_size) {
 default:
 case RTW89_PLE_PG_64:
  rtw89_err(rtwdev, "[ERR]PLE DLE doesn't support 64 byte!\n");
  return -EINVAL;
 case RTW89_PLE_PG_128:
  val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_128,
           B_AX_PLE_PAGE_SEL_MASK);
  break;
 case RTW89_PLE_PG_256:
  val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_256,
           B_AX_PLE_PAGE_SEL_MASK);
  break;
 }

 val = u32_replace_bits(val, bound, B_AX_PLE_START_BOUND_MASK);
 val = u32_replace_bits(val, size_cfg->lnk_pge_num,
          B_AX_PLE_FREE_PAGE_NUM_MASK);
 rtw89_write32(rtwdev, R_AX_PLE_PKTBUF_CFG, val);

 return 0;
}

static int chk_dle_rdy_ax(struct rtw89_dev *rtwdev, bool wde_or_ple)
{
 u32 reg, mask;
 u32 ini;

 if (wde_or_ple) {
  reg = R_AX_WDE_INI_STATUS;
  mask = WDE_MGN_INI_RDY;
 } else {
  reg = R_AX_PLE_INI_STATUS;
  mask = PLE_MGN_INI_RDY;
 }

 return read_poll_timeout(rtw89_read32, ini, (ini & mask) == mask, 1,
    2000, false, rtwdev, reg);
}

#define INVALID_QT_WCPU U16_MAX
#define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx)   \
 do {        \
  val = u32_encode_bits(_min_x, B_AX_ ## _module ## _MIN_SIZE_MASK) | \
        u32_encode_bits(_max_x, B_AX_ ## _module ## _MAX_SIZE_MASK);  \
  rtw89_write32(rtwdev,     \
         R_AX_ ## _module ## _QTA ## _idx ## _CFG, \
         val);     \
 } while (0)
#define SET_QUOTA(_x, _module, _idx)     \
 SET_QUOTA_VAL(min_cfg->_x, max_cfg->_x, _module, _idx)

static void wde_quota_cfg_ax(struct rtw89_dev *rtwdev,
        const struct rtw89_wde_quota *min_cfg,
        const struct rtw89_wde_quota *max_cfg,
        u16 ext_wde_min_qt_wcpu)
{
 u16 min_qt_wcpu = ext_wde_min_qt_wcpu != INVALID_QT_WCPU ?
     ext_wde_min_qt_wcpu : min_cfg->wcpu;
 u32 val;

 SET_QUOTA(hif, WDE, 0);
 SET_QUOTA_VAL(min_qt_wcpu, max_cfg->wcpu, WDE, 1);
 SET_QUOTA(pkt_in, WDE, 3);
 SET_QUOTA(cpu_io, WDE, 4);
}

static void ple_quota_cfg_ax(struct rtw89_dev *rtwdev,
        const struct rtw89_ple_quota *min_cfg,
        const struct rtw89_ple_quota *max_cfg)
{
 u32 val;

 SET_QUOTA(cma0_tx, PLE, 0);
 SET_QUOTA(cma1_tx, PLE, 1);
 SET_QUOTA(c2h, PLE, 2);
 SET_QUOTA(h2c, PLE, 3);
 SET_QUOTA(wcpu, PLE, 4);
 SET_QUOTA(mpdu_proc, PLE, 5);
 SET_QUOTA(cma0_dma, PLE, 6);
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=99 H=96 G=97

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.