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 132 kB image not shown  

Quelle  debug.c   Sprache: C

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


#include <linux/vmalloc.h>

#include "coex.h"
#include "debug.h"
#include "fw.h"
#include "mac.h"
#include "pci.h"
#include "phy.h"
#include "ps.h"
#include "reg.h"
#include "sar.h"
#include "util.h"

#ifdef CONFIG_RTW89_DEBUGMSG
unsigned int rtw89_debug_mask;
EXPORT_SYMBOL(rtw89_debug_mask);
module_param_named(debug_mask, rtw89_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
#endif

#ifdef CONFIG_RTW89_DEBUGFS
struct rtw89_debugfs_priv_opt {
 bool rlock:1;
 bool wlock:1;
 size_t rsize;
};

struct rtw89_debugfs_priv {
 struct rtw89_dev *rtwdev;
 ssize_t (*cb_read)(struct rtw89_dev *rtwdev,
      struct rtw89_debugfs_priv *debugfs_priv,
      char *buf, size_t bufsz);
 ssize_t (*cb_write)(struct rtw89_dev *rtwdev,
       struct rtw89_debugfs_priv *debugfs_priv,
       const char *buf, size_t count);
 struct rtw89_debugfs_priv_opt opt;
 union {
  u32 cb_data;
  struct {
   u32 addr;
   u32 len;
  } read_reg;
  struct {
   u32 addr;
   u32 mask;
   u8 path;
  } read_rf;
  struct {
   u8 ss_dbg:1;
   u8 dle_dbg:1;
   u8 dmac_dbg:1;
   u8 cmac_dbg:1;
   u8 dbg_port:1;
  } dbgpkg_en;
  struct {
   u32 start;
   u32 len;
   u8 sel;
  } mac_mem;
 };
 ssize_t rused;
 char *rbuf;
};

struct rtw89_debugfs {
 struct rtw89_debugfs_priv read_reg;
 struct rtw89_debugfs_priv write_reg;
 struct rtw89_debugfs_priv read_rf;
 struct rtw89_debugfs_priv write_rf;
 struct rtw89_debugfs_priv rf_reg_dump;
 struct rtw89_debugfs_priv txpwr_table;
 struct rtw89_debugfs_priv mac_reg_dump;
 struct rtw89_debugfs_priv mac_mem_dump;
 struct rtw89_debugfs_priv mac_dbg_port_dump;
 struct rtw89_debugfs_priv send_h2c;
 struct rtw89_debugfs_priv early_h2c;
 struct rtw89_debugfs_priv fw_crash;
 struct rtw89_debugfs_priv btc_info;
 struct rtw89_debugfs_priv btc_manual;
 struct rtw89_debugfs_priv fw_log_manual;
 struct rtw89_debugfs_priv phy_info;
 struct rtw89_debugfs_priv stations;
 struct rtw89_debugfs_priv disable_dm;
 struct rtw89_debugfs_priv mlo_mode;
};

struct rtw89_debugfs_iter_data {
 char *buf;
 size_t bufsz;
 int written_sz;
};

static void rtw89_debugfs_iter_data_setup(struct rtw89_debugfs_iter_data *iter_data,
       char *buf, size_t bufsz)
{
 iter_data->buf = buf;
 iter_data->bufsz = bufsz;
 iter_data->written_sz = 0;
}

static void rtw89_debugfs_iter_data_next(struct rtw89_debugfs_iter_data *iter_data,
      char *buf, size_t bufsz, int written_sz)
{
 iter_data->buf = buf;
 iter_data->bufsz = bufsz;
 iter_data->written_sz += written_sz;
}

static const u16 rtw89_rate_info_bw_to_mhz_map[] = {
 [RATE_INFO_BW_20] = 20,
 [RATE_INFO_BW_40] = 40,
 [RATE_INFO_BW_80] = 80,
 [RATE_INFO_BW_160] = 160,
 [RATE_INFO_BW_320] = 320,
};

static u16 rtw89_rate_info_bw_to_mhz(enum rate_info_bw bw)
{
 if (bw < ARRAY_SIZE(rtw89_rate_info_bw_to_mhz_map))
  return rtw89_rate_info_bw_to_mhz_map[bw];

 return 0;
}

static ssize_t rtw89_debugfs_file_read_helper(struct wiphy *wiphy, struct file *file,
           char *buf, size_t bufsz, void *data)
{
 struct rtw89_debugfs_priv *debugfs_priv = data;
 struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 ssize_t n;

 n = debugfs_priv->cb_read(rtwdev, debugfs_priv, buf, bufsz);
 rtw89_might_trailing_ellipsis(buf, bufsz, n);

 return n;
}

static ssize_t rtw89_debugfs_file_read(struct file *file, char __user *userbuf,
           size_t count, loff_t *ppos)
{
 struct rtw89_debugfs_priv *debugfs_priv = file->private_data;
 struct rtw89_debugfs_priv_opt *opt = &debugfs_priv->opt;
 struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 size_t bufsz = opt->rsize ? opt->rsize : PAGE_SIZE;
 char *buf;
 ssize_t n;

 if (!debugfs_priv->rbuf)
  debugfs_priv->rbuf = devm_kzalloc(rtwdev->dev, bufsz, GFP_KERNEL);

 buf = debugfs_priv->rbuf;
 if (!buf)
  return -ENOMEM;

 if (*ppos) {
  n = debugfs_priv->rused;
  goto out;
 }

 if (opt->rlock) {
  n = wiphy_locked_debugfs_read(rtwdev->hw->wiphy, file, buf, bufsz,
           userbuf, count, ppos,
           rtw89_debugfs_file_read_helper,
           debugfs_priv);
  debugfs_priv->rused = n;

  return n;
 }

 n = rtw89_debugfs_file_read_helper(rtwdev->hw->wiphy, file, buf, bufsz,
        debugfs_priv);
 debugfs_priv->rused = n;

out:
 return simple_read_from_buffer(userbuf, count, ppos, buf, n);
}

static ssize_t rtw89_debugfs_file_write_helper(struct wiphy *wiphy, struct file *file,
            char *buf, size_t count, void *data)
{
 struct rtw89_debugfs_priv *debugfs_priv = data;
 struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;

 return debugfs_priv->cb_write(rtwdev, debugfs_priv, buf, count);
}

static ssize_t rtw89_debugfs_file_write(struct file *file,
     const char __user *userbuf,
     size_t count, loff_t *loff)
{
 struct rtw89_debugfs_priv *debugfs_priv = file->private_data;
 struct rtw89_debugfs_priv_opt *opt = &debugfs_priv->opt;
 struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 char *buf __free(kfree) = kmalloc(count + 1, GFP_KERNEL);
 ssize_t n;

 if (!buf)
  return -ENOMEM;

 if (opt->wlock) {
  n = wiphy_locked_debugfs_write(rtwdev->hw->wiphy,
            file, buf, count + 1,
            userbuf, count,
            rtw89_debugfs_file_write_helper,
            debugfs_priv);
  return n;
 }

 if (copy_from_user(buf, userbuf, count))
  return -EFAULT;

 buf[count] = '\0';

 return debugfs_priv->cb_write(rtwdev, debugfs_priv, buf, count);
}

static const struct debugfs_short_fops file_ops_single_r = {
 .read = rtw89_debugfs_file_read,
 .llseek = generic_file_llseek,
};

static const struct debugfs_short_fops file_ops_common_rw = {
 .read = rtw89_debugfs_file_read,
 .write = rtw89_debugfs_file_write,
 .llseek = generic_file_llseek,
};

static const struct debugfs_short_fops file_ops_single_w = {
 .write = rtw89_debugfs_file_write,
 .llseek = generic_file_llseek,
};

static ssize_t
rtw89_debug_priv_read_reg_select(struct rtw89_dev *rtwdev,
     struct rtw89_debugfs_priv *debugfs_priv,
     const char *buf, size_t count)
{
 u32 addr, len;
 int num;

 num = sscanf(buf, "%x %x", &addr, &len);
 if (num != 2) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 debugfs_priv->read_reg.addr = addr;
 debugfs_priv->read_reg.len = len;

 rtw89_info(rtwdev, "select read %d bytes from 0x%08x\n", len, addr);

 return count;
}

static
ssize_t rtw89_debug_priv_read_reg_get(struct rtw89_dev *rtwdev,
          struct rtw89_debugfs_priv *debugfs_priv,
          char *buf, size_t bufsz)
{
 char *p = buf, *end = buf + bufsz;
 u32 addr, addr_end, data, k;
 u32 len;

 len = debugfs_priv->read_reg.len;
 addr = debugfs_priv->read_reg.addr;

 if (len > 4)
  goto ndata;

 switch (len) {
 case 1:
  data = rtw89_read8(rtwdev, addr);
  break;
 case 2:
  data = rtw89_read16(rtwdev, addr);
  break;
 case 4:
  data = rtw89_read32(rtwdev, addr);
  break;
 default:
  rtw89_info(rtwdev, "invalid read reg len %d\n", len);
  return -EINVAL;
 }

 p += scnprintf(p, end - p, "get %d bytes at 0x%08x=0x%08x\n", len,
         addr, data);

 return p - buf;

ndata:
 addr_end = addr + len;

 for (; addr < addr_end; addr += 16) {
  p += scnprintf(p, end - p, "%08xh : ", 0x18600000 + addr);
  for (k = 0; k < 16; k += 4) {
   data = rtw89_read32(rtwdev, addr + k);
   p += scnprintf(p, end - p, "%08x ", data);
  }
  p += scnprintf(p, end - p, "\n");
 }

 return p - buf;
}

static
ssize_t rtw89_debug_priv_write_reg_set(struct rtw89_dev *rtwdev,
           struct rtw89_debugfs_priv *debugfs_priv,
           const char *buf, size_t count)
{
 u32 addr, val, len;
 int num;

 num = sscanf(buf, "%x %x %x", &addr, &val, &len);
 if (num !=  3) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 switch (len) {
 case 1:
  rtw89_info(rtwdev, "reg write8 0x%08x: 0x%02x\n", addr, val);
  rtw89_write8(rtwdev, addr, (u8)val);
  break;
 case 2:
  rtw89_info(rtwdev, "reg write16 0x%08x: 0x%04x\n", addr, val);
  rtw89_write16(rtwdev, addr, (u16)val);
  break;
 case 4:
  rtw89_info(rtwdev, "reg write32 0x%08x: 0x%08x\n", addr, val);
  rtw89_write32(rtwdev, addr, (u32)val);
  break;
 default:
  rtw89_info(rtwdev, "invalid read write len %d\n", len);
  break;
 }

 return count;
}

static ssize_t
rtw89_debug_priv_read_rf_select(struct rtw89_dev *rtwdev,
    struct rtw89_debugfs_priv *debugfs_priv,
    const char *buf, size_t count)
{
 u32 addr, mask;
 u8 path;
 int num;

 num = sscanf(buf, "%hhd %x %x", &path, &addr, &mask);
 if (num != 3) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 if (path >= rtwdev->chip->rf_path_num) {
  rtw89_info(rtwdev, "wrong rf path\n");
  return -EINVAL;
 }
 debugfs_priv->read_rf.addr = addr;
 debugfs_priv->read_rf.mask = mask;
 debugfs_priv->read_rf.path = path;

 rtw89_info(rtwdev, "select read rf path %d from 0x%08x\n", path, addr);

 return count;
}

static
ssize_t rtw89_debug_priv_read_rf_get(struct rtw89_dev *rtwdev,
         struct rtw89_debugfs_priv *debugfs_priv,
         char *buf, size_t bufsz)
{
 char *p = buf, *end = buf + bufsz;
 u32 addr, data, mask;
 u8 path;

 addr = debugfs_priv->read_rf.addr;
 mask = debugfs_priv->read_rf.mask;
 path = debugfs_priv->read_rf.path;

 data = rtw89_read_rf(rtwdev, path, addr, mask);

 p += scnprintf(p, end - p, "path %d, rf register 0x%08x=0x%08x\n",
         path, addr, data);

 return p - buf;
}

static
ssize_t rtw89_debug_priv_write_rf_set(struct rtw89_dev *rtwdev,
          struct rtw89_debugfs_priv *debugfs_priv,
          const char *buf, size_t count)
{
 u32 addr, val, mask;
 u8 path;
 int num;

 num = sscanf(buf, "%hhd %x %x %x", &path, &addr, &mask, &val);
 if (num != 4) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 if (path >= rtwdev->chip->rf_path_num) {
  rtw89_info(rtwdev, "wrong rf path\n");
  return -EINVAL;
 }

 rtw89_info(rtwdev, "path %d, rf register write 0x%08x=0x%08x (mask = 0x%08x)\n",
     path, addr, val, mask);
 rtw89_write_rf(rtwdev, path, addr, mask, val);

 return count;
}

static
ssize_t rtw89_debug_priv_rf_reg_dump_get(struct rtw89_dev *rtwdev,
      struct rtw89_debugfs_priv *debugfs_priv,
      char *buf, size_t bufsz)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 char *p = buf, *end = buf + bufsz;
 u32 addr, offset, data;
 u8 path;

 for (path = 0; path < chip->rf_path_num; path++) {
  p += scnprintf(p, end - p, "RF path %d:\n\n", path);
  for (addr = 0; addr < 0x100; addr += 4) {
   p += scnprintf(p, end - p, "0x%08x: ", addr);
   for (offset = 0; offset < 4; offset++) {
    data = rtw89_read_rf(rtwdev, path,
           addr + offset, RFREG_MASK);
    p += scnprintf(p, end - p, "0x%05x ", data);
   }
   p += scnprintf(p, end - p, "\n");
  }
  p += scnprintf(p, end - p, "\n");
 }

 return p - buf;
}

struct txpwr_ent {
 bool nested;
 union {
  const char *txt;
  const struct txpwr_ent *ptr;
 };
 u8 len;
};

struct txpwr_map {
 const struct txpwr_ent *ent;
 u8 size;
 u32 addr_from;
 u32 addr_to;
 u32 addr_to_1ss;
};

#define __GEN_TXPWR_ENT_NESTED(_e) \
 { .nested = true, .ptr = __txpwr_ent_##_e, \
   .len = ARRAY_SIZE(__txpwr_ent_##_e) }

#define __GEN_TXPWR_ENT0(_t) { .len = 0, .txt = _t }

#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
 { .len = 2, .txt = _t "\t- " _e0 " " _e1 }

#define __GEN_TXPWR_ENT4(_t, _e0, _e1, _e2, _e3) \
 { .len = 4, .txt = _t "\t- " _e0 " " _e1 " " _e2 " " _e3 }

#define __GEN_TXPWR_ENT8(_t, _e0, _e1, _e2, _e3, _e4, _e5, _e6, _e7) \
 { .len = 8, .txt = _t "\t- " \
   _e0 " " _e1 " " _e2 " " _e3 " " \
   _e4 " " _e5 " " _e6 " " _e7 }

static const struct txpwr_ent __txpwr_ent_byr_ax[] = {
 __GEN_TXPWR_ENT4("CCK ""1M ""2M ""5.5M ""11M "),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 /* 1NSS */
 __GEN_TXPWR_ENT4("MCS_1NSS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("MCS_1NSS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("MCS_1NSS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT4("HEDCM_1NSS""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
 /* 2NSS */
 __GEN_TXPWR_ENT4("MCS_2NSS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("MCS_2NSS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("MCS_2NSS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT4("HEDCM_2NSS""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
};

static_assert((ARRAY_SIZE(__txpwr_ent_byr_ax) * 4) ==
 (R_AX_PWR_BY_RATE_MAX - R_AX_PWR_BY_RATE + 4));

static const struct txpwr_map __txpwr_map_byr_ax = {
 .ent = __txpwr_ent_byr_ax,
 .size = ARRAY_SIZE(__txpwr_ent_byr_ax),
 .addr_from = R_AX_PWR_BY_RATE,
 .addr_to = R_AX_PWR_BY_RATE_MAX,
 .addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
};

static const struct txpwr_ent __txpwr_ent_lmt_ax[] = {
 /* 1TX */
 __GEN_TXPWR_ENT2("CCK_1TX_20M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("CCK_1TX_40M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("OFDM_1TX ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_4 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_5 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_6 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_20M_7 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_80M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_80M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_160M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_0p5""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_1TX_40M_2p5""NON_BF""BF"),
 /* 2TX */
 __GEN_TXPWR_ENT2("CCK_2TX_20M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("CCK_2TX_40M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("OFDM_2TX ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_4 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_5 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_6 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_20M_7 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_80M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_80M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_160M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_0p5""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_2TX_40M_2p5""NON_BF""BF"),
};

static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ax) * 2) ==
 (R_AX_PWR_LMT_MAX - R_AX_PWR_LMT + 4));

static const struct txpwr_map __txpwr_map_lmt_ax = {
 .ent = __txpwr_ent_lmt_ax,
 .size = ARRAY_SIZE(__txpwr_ent_lmt_ax),
 .addr_from = R_AX_PWR_LMT,
 .addr_to = R_AX_PWR_LMT_MAX,
 .addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
};

static const struct txpwr_ent __txpwr_ent_lmt_ru_ax[] = {
 /* 1TX */
 __GEN_TXPWR_ENT8("1TX""RU26__0""RU26__1""RU26__2""RU26__3",
    "RU26__4""RU26__5""RU26__6""RU26__7"),
 __GEN_TXPWR_ENT8("1TX""RU52__0""RU52__1""RU52__2""RU52__3",
    "RU52__4""RU52__5""RU52__6""RU52__7"),
 __GEN_TXPWR_ENT8("1TX""RU106_0""RU106_1""RU106_2""RU106_3",
    "RU106_4""RU106_5""RU106_6""RU106_7"),
 /* 2TX */
 __GEN_TXPWR_ENT8("2TX""RU26__0""RU26__1""RU26__2""RU26__3",
    "RU26__4""RU26__5""RU26__6""RU26__7"),
 __GEN_TXPWR_ENT8("2TX""RU52__0""RU52__1""RU52__2""RU52__3",
    "RU52__4""RU52__5""RU52__6""RU52__7"),
 __GEN_TXPWR_ENT8("2TX""RU106_0""RU106_1""RU106_2""RU106_3",
    "RU106_4""RU106_5""RU106_6""RU106_7"),
};

static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru_ax) * 8) ==
 (R_AX_PWR_RU_LMT_MAX - R_AX_PWR_RU_LMT + 4));

static const struct txpwr_map __txpwr_map_lmt_ru_ax = {
 .ent = __txpwr_ent_lmt_ru_ax,
 .size = ARRAY_SIZE(__txpwr_ent_lmt_ru_ax),
 .addr_from = R_AX_PWR_RU_LMT,
 .addr_to = R_AX_PWR_RU_LMT_MAX,
 .addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
};

static const struct txpwr_ent __txpwr_ent_byr_mcs_be[] = {
 __GEN_TXPWR_ENT4("MCS_1SS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("MCS_1SS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("MCS_1SS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT2("MCS_1SS ""MCS12 ""MCS13 \t"),
 __GEN_TXPWR_ENT4("HEDCM_1SS ""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_1SS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_1SS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_1SS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT2("DLRU_MCS_1SS ""MCS12 ""MCS13 \t"),
 __GEN_TXPWR_ENT4("DLRU_HEDCM_1SS""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
 __GEN_TXPWR_ENT4("MCS_2SS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("MCS_2SS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("MCS_2SS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT2("MCS_2SS ""MCS12 ""MCS13 \t"),
 __GEN_TXPWR_ENT4("HEDCM_2SS ""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_2SS ""MCS0 ""MCS1 ""MCS2 ""MCS3 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_2SS ""MCS4 ""MCS5 ""MCS6 ""MCS7 "),
 __GEN_TXPWR_ENT4("DLRU_MCS_2SS ""MCS8 ""MCS9 ""MCS10""MCS11"),
 __GEN_TXPWR_ENT2("DLRU_MCS_2SS ""MCS12 ""MCS13 \t"),
 __GEN_TXPWR_ENT4("DLRU_HEDCM_2SS""MCS0 ""MCS1 ""MCS3 ""MCS4 "),
};

static const struct txpwr_ent __txpwr_ent_byr_be[] = {
 __GEN_TXPWR_ENT0("BW20"),
 __GEN_TXPWR_ENT4("CCK ""1M ""2M ""5.5M ""11M "),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 __GEN_TXPWR_ENT2("EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT2("DLRU_EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT_NESTED(byr_mcs_be),

 __GEN_TXPWR_ENT0("BW40"),
 __GEN_TXPWR_ENT4("CCK ""1M ""2M ""5.5M ""11M "),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 __GEN_TXPWR_ENT2("EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT2("DLRU_EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT_NESTED(byr_mcs_be),

 /* there is no CCK section after BW80 */
 __GEN_TXPWR_ENT0("BW80"),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 __GEN_TXPWR_ENT2("EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT2("DLRU_EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT_NESTED(byr_mcs_be),

 __GEN_TXPWR_ENT0("BW160"),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 __GEN_TXPWR_ENT2("EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT2("DLRU_EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT_NESTED(byr_mcs_be),

 __GEN_TXPWR_ENT0("BW320"),
 __GEN_TXPWR_ENT4("LEGACY ""6M ""9M ""12M ""18M "),
 __GEN_TXPWR_ENT4("LEGACY ""24M ""36M ""48M ""54M "),
 __GEN_TXPWR_ENT2("EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT2("DLRU_EHT ""MCS14 ""MCS15 \t"),
 __GEN_TXPWR_ENT_NESTED(byr_mcs_be),
};

static const struct txpwr_map __txpwr_map_byr_be = {
 .ent = __txpwr_ent_byr_be,
 .size = ARRAY_SIZE(__txpwr_ent_byr_be),
 .addr_from = R_BE_PWR_BY_RATE,
 .addr_to = R_BE_PWR_BY_RATE_MAX,
 .addr_to_1ss = 0, /* not support */
};

static const struct txpwr_ent __txpwr_ent_lmt_mcs_be[] = {
 __GEN_TXPWR_ENT2("MCS_20M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_4 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_5 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_6 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_7 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_8 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_9 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_10 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_11 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_12 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_13 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_14 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_20M_15 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_4 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_5 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_6 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_7 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_80M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_80M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_80M_2 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_80M_3 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_160M_0 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_160M_1 ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_320M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_0p5""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_2p5""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_4p5""NON_BF""BF"),
 __GEN_TXPWR_ENT2("MCS_40M_6p5""NON_BF""BF"),
};

static const struct txpwr_ent __txpwr_ent_lmt_be[] = {
 __GEN_TXPWR_ENT0("1TX"),
 __GEN_TXPWR_ENT2("CCK_20M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("CCK_40M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("OFDM ""NON_BF""BF"),
 __GEN_TXPWR_ENT_NESTED(lmt_mcs_be),

 __GEN_TXPWR_ENT0("2TX"),
 __GEN_TXPWR_ENT2("CCK_20M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("CCK_40M ""NON_BF""BF"),
 __GEN_TXPWR_ENT2("OFDM ""NON_BF""BF"),
 __GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
};

static const struct txpwr_map __txpwr_map_lmt_be = {
 .ent = __txpwr_ent_lmt_be,
 .size = ARRAY_SIZE(__txpwr_ent_lmt_be),
 .addr_from = R_BE_PWR_LMT,
 .addr_to = R_BE_PWR_LMT_MAX,
 .addr_to_1ss = 0, /* not support */
};

static const struct txpwr_ent __txpwr_ent_lmt_ru_indexes_be[] = {
 __GEN_TXPWR_ENT8("RU26 ""IDX_0 ""IDX_1 ""IDX_2 ""IDX_3 ",
    "IDX_4 ""IDX_5 ""IDX_6 ""IDX_7 "),
 __GEN_TXPWR_ENT8("RU26 ""IDX_8 ""IDX_9 ""IDX_10""IDX_11",
    "IDX_12""IDX_13""IDX_14""IDX_15"),
 __GEN_TXPWR_ENT8("RU52 ""IDX_0 ""IDX_1 ""IDX_2 ""IDX_3 ",
    "IDX_4 ""IDX_5 ""IDX_6 ""IDX_7 "),
 __GEN_TXPWR_ENT8("RU52 ""IDX_8 ""IDX_9 ""IDX_10""IDX_11",
    "IDX_12""IDX_13""IDX_14""IDX_15"),
 __GEN_TXPWR_ENT8("RU106 ""IDX_0 ""IDX_1 ""IDX_2 ""IDX_3 ",
    "IDX_4 ""IDX_5 ""IDX_6 ""IDX_7 "),
 __GEN_TXPWR_ENT8("RU106 ""IDX_8 ""IDX_9 ""IDX_10""IDX_11",
    "IDX_12""IDX_13""IDX_14""IDX_15"),
 __GEN_TXPWR_ENT8("RU52_26 ""IDX_0 ""IDX_1 ""IDX_2 ""IDX_3 ",
    "IDX_4 ""IDX_5 ""IDX_6 ""IDX_7 "),
 __GEN_TXPWR_ENT8("RU52_26 ""IDX_8 ""IDX_9 ""IDX_10""IDX_11",
    "IDX_12""IDX_13""IDX_14""IDX_15"),
 __GEN_TXPWR_ENT8("RU106_26""IDX_0 ""IDX_1 ""IDX_2 ""IDX_3 ",
    "IDX_4 ""IDX_5 ""IDX_6 ""IDX_7 "),
 __GEN_TXPWR_ENT8("RU106_26""IDX_8 ""IDX_9 ""IDX_10""IDX_11",
    "IDX_12""IDX_13""IDX_14""IDX_15"),
};

static const struct txpwr_ent __txpwr_ent_lmt_ru_be[] = {
 __GEN_TXPWR_ENT0("1TX"),
 __GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),

 __GEN_TXPWR_ENT0("2TX"),
 __GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
};

static const struct txpwr_map __txpwr_map_lmt_ru_be = {
 .ent = __txpwr_ent_lmt_ru_be,
 .size = ARRAY_SIZE(__txpwr_ent_lmt_ru_be),
 .addr_from = R_BE_PWR_RU_LMT,
 .addr_to = R_BE_PWR_RU_LMT_MAX,
 .addr_to_1ss = 0, /* not support */
};

static unsigned int
__print_txpwr_ent(char *buf, size_t bufsz, const struct txpwr_ent *ent,
    const s8 *bufp, const unsigned int cur, unsigned int *ate)
{
 char *p = buf, *end = buf + bufsz;
 unsigned int cnt, i;
 unsigned int eaten;
 char *fmt;

 if (ent->nested) {
  for (cnt = 0, i = 0; i < ent->len; i++, cnt += eaten)
   p += __print_txpwr_ent(p, end - p, ent->ptr + i, bufp,
            cur + cnt, &eaten);
  *ate = cnt;
  goto out;
 }

 switch (ent->len) {
 case 0:
  p += scnprintf(p, end - p, "\t<< %s >>\n", ent->txt);
  *ate = 0;
  goto out;
 case 2:
  fmt = "%s\t| %3d, %3d,\t\tdBm\n";
  p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
          bufp[cur + 1]);
  *ate = 2;
  goto out;
 case 4:
  fmt = "%s\t| %3d, %3d, %3d, %3d,\tdBm\n";
  p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
          bufp[cur + 1],
          bufp[cur + 2], bufp[cur + 3]);
  *ate = 4;
  goto out;
 case 8:
  fmt = "%s\t| %3d, %3d, %3d, %3d, %3d, %3d, %3d, %3d,\tdBm\n";
  p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
          bufp[cur + 1],
          bufp[cur + 2], bufp[cur + 3], bufp[cur + 4],
          bufp[cur + 5], bufp[cur + 6], bufp[cur + 7]);
  *ate = 8;
  goto out;
 default:
  return 0;
 }

out:
 return p - buf;
}

static ssize_t __print_txpwr_map(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
     const struct txpwr_map *map)
{
 u8 fct = rtwdev->chip->txpwr_factor_mac;
 u8 path_num = rtwdev->chip->rf_path_num;
 char *p = buf, *end = buf + bufsz;
 unsigned int cur, i;
 unsigned int eaten;
 u32 max_valid_addr;
 u32 val, addr;
 s8 *bufp, tmp;
 int ret;

 bufp = vzalloc(map->addr_to - map->addr_from + 4);
 if (!bufp)
  return -ENOMEM;

 if (path_num == 1)
  max_valid_addr = map->addr_to_1ss;
 else
  max_valid_addr = map->addr_to;

 if (max_valid_addr == 0)
  return -EOPNOTSUPP;

 for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
  ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
  if (ret)
   val = MASKDWORD;

  cur = addr - map->addr_from;
  for (i = 0; i < 4; i++, val >>= 8) {
   /* signed 7 bits, and reserved BIT(7) */
   tmp = sign_extend32(val, 6);
   bufp[cur + i] = tmp >> fct;
  }
 }

 for (cur = 0, i = 0; i < map->size; i++, cur += eaten)
  p += __print_txpwr_ent(p, end - p, &map->ent[i], bufp, cur, &eaten);

 vfree(bufp);
 return p - buf;
}

static int __print_regd(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
   const struct rtw89_chan *chan)
{
 const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 char *p = buf, *end = buf + bufsz;
 u8 band = chan->band_type;
 u8 regd = rtw89_regd_get(rtwdev, band);

 p += scnprintf(p, end - p, "%s\n", rtw89_regd_get_string(regd));
 p += scnprintf(p, end - p, "\t(txpwr UK follow ETSI: %s)\n",
         str_yes_no(regulatory->txpwr_uk_follow_etsi));

 return p - buf;
}

struct dbgfs_txpwr_table {
 const struct txpwr_map *byr;
 const struct txpwr_map *lmt;
 const struct txpwr_map *lmt_ru;
};

static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
 .byr = &__txpwr_map_byr_ax,
 .lmt = &__txpwr_map_lmt_ax,
 .lmt_ru = &__txpwr_map_lmt_ru_ax,
};

static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
 .byr = &__txpwr_map_byr_be,
 .lmt = &__txpwr_map_lmt_be,
 .lmt_ru = &__txpwr_map_lmt_ru_be,
};

static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
 [RTW89_CHIP_AX] = &dbgfs_txpwr_table_ax,
 [RTW89_CHIP_BE] = &dbgfs_txpwr_table_be,
};

static
int rtw89_debug_priv_txpwr_table_get_regd(struct rtw89_dev *rtwdev,
       char *buf, size_t bufsz,
       const struct rtw89_chan *chan)
{
 const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 const struct rtw89_reg_6ghz_tpe *tpe6 = ®ulatory->reg_6ghz_tpe;
 char *p = buf, *end = buf + bufsz;

 p += scnprintf(p, end - p, "[Chanctx] band %u, ch %u, bw %u\n",
         chan->band_type, chan->channel, chan->band_width);

 p += scnprintf(p, end - p, "[Regulatory] ");
 p += __print_regd(rtwdev, p, end - p, chan);

 if (chan->band_type == RTW89_BAND_6G) {
  p += scnprintf(p, end - p, "[reg6_pwr_type] %u\n",
          regulatory->reg_6ghz_power);

  if (tpe6->valid)
   p += scnprintf(p, end - p, "[TPE] %d dBm\n",
           tpe6->constraint);
 }

 return p - buf;
}

static
ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
      struct rtw89_debugfs_priv *debugfs_priv,
      char *buf, size_t bufsz)
{
 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
 struct rtw89_sar_parm sar_parm = {};
 const struct dbgfs_txpwr_table *tbl;
 const struct rtw89_chan *chan;
 char *p = buf, *end = buf + bufsz;
 ssize_t n;

 lockdep_assert_wiphy(rtwdev->hw->wiphy);

 rtw89_leave_ps_mode(rtwdev);
 chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
 sar_parm.center_freq = chan->freq;

 p += rtw89_debug_priv_txpwr_table_get_regd(rtwdev, p, end - p, chan);

 p += scnprintf(p, end - p, "[SAR]\n");
 p += rtw89_print_sar(rtwdev, p, end - p, &sar_parm);

 p += scnprintf(p, end - p, "[TAS]\n");
 p += rtw89_print_tas(rtwdev, p, end - p);

 p += scnprintf(p, end - p, "[DAG]\n");
 p += rtw89_print_ant_gain(rtwdev, p, end - p, chan);

 tbl = dbgfs_txpwr_tables[chip_gen];
 if (!tbl)
  return -EOPNOTSUPP;

 p += scnprintf(p, end - p, "\n[TX power byrate]\n");
 n = __print_txpwr_map(rtwdev, p, end - p, tbl->byr);
 if (n < 0)
  return n;
 p += n;

 p += scnprintf(p, end - p, "\n[TX power limit]\n");
 n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt);
 if (n < 0)
  return n;
 p += n;

 p += scnprintf(p, end - p, "\n[TX power limit_ru]\n");
 n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru);
 if (n < 0)
  return n;
 p += n;

 return p - buf;
}

static ssize_t
rtw89_debug_priv_mac_reg_dump_select(struct rtw89_dev *rtwdev,
         struct rtw89_debugfs_priv *debugfs_priv,
         const char *buf, size_t count)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 int sel;
 int ret;

 ret = kstrtoint(buf, 0, &sel);
 if (ret)
  return ret;

 if (sel < RTW89_DBG_SEL_MAC_00 || sel > RTW89_DBG_SEL_RFC) {
  rtw89_info(rtwdev, "invalid args: %d\n", sel);
  return -EINVAL;
 }

 if (sel == RTW89_DBG_SEL_MAC_30 && chip->chip_id != RTL8852C) {
  rtw89_info(rtwdev, "sel %d is address hole on chip %d\n", sel,
      chip->chip_id);
  return -EINVAL;
 }

 debugfs_priv->cb_data = sel;
 rtw89_info(rtwdev, "select mac page dump %d\n", debugfs_priv->cb_data);

 return count;
}

#define RTW89_MAC_PAGE_SIZE  0x100

static
ssize_t rtw89_debug_priv_mac_reg_dump_get(struct rtw89_dev *rtwdev,
       struct rtw89_debugfs_priv *debugfs_priv,
       char *buf, size_t bufsz)
{
 enum rtw89_debug_mac_reg_sel reg_sel = debugfs_priv->cb_data;
 char *p = buf, *end = buf + bufsz;
 u32 start, end_addr;
 u32 i, j, k, page;
 u32 val;

 switch (reg_sel) {
 case RTW89_DBG_SEL_MAC_00:
  p += scnprintf(p, end - p, "Debug selected MAC page 0x00\n");
  start = 0x000;
  end_addr = 0x014;
  break;
 case RTW89_DBG_SEL_MAC_30:
  p += scnprintf(p, end - p, "Debug selected MAC page 0x30\n");
  start = 0x030;
  end_addr = 0x033;
  break;
 case RTW89_DBG_SEL_MAC_40:
  p += scnprintf(p, end - p, "Debug selected MAC page 0x40\n");
  start = 0x040;
  end_addr = 0x07f;
  break;
 case RTW89_DBG_SEL_MAC_80:
  p += scnprintf(p, end - p, "Debug selected MAC page 0x80\n");
  start = 0x080;
  end_addr = 0x09f;
  break;
 case RTW89_DBG_SEL_MAC_C0:
  p += scnprintf(p, end - p, "Debug selected MAC page 0xc0\n");
  start = 0x0c0;
  end_addr = 0x0df;
  break;
 case RTW89_DBG_SEL_MAC_E0:
  p += scnprintf(p, end - p, "Debug selected MAC page 0xe0\n");
  start = 0x0e0;
  end_addr = 0x0ff;
  break;
 case RTW89_DBG_SEL_BB:
  p += scnprintf(p, end - p, "Debug selected BB register\n");
  start = 0x100;
  end_addr = 0x17f;
  break;
 case RTW89_DBG_SEL_IQK:
  p += scnprintf(p, end - p, "Debug selected IQK register\n");
  start = 0x180;
  end_addr = 0x1bf;
  break;
 case RTW89_DBG_SEL_RFC:
  p += scnprintf(p, end - p, "Debug selected RFC register\n");
  start = 0x1c0;
  end_addr = 0x1ff;
  break;
 default:
  p += scnprintf(p, end - p, "Selected invalid register page\n");
  return -EINVAL;
 }

 for (i = start; i <= end_addr; i++) {
  page = i << 8;
  for (j = page; j < page + RTW89_MAC_PAGE_SIZE; j += 16) {
   p += scnprintf(p, end - p, "%08xh : ", 0x18600000 + j);
   for (k = 0; k < 4; k++) {
    val = rtw89_read32(rtwdev, j + (k << 2));
    p += scnprintf(p, end - p, "%08x ", val);
   }
   p += scnprintf(p, end - p, "\n");
  }
 }

 return p - buf;
}

static ssize_t
rtw89_debug_priv_mac_mem_dump_select(struct rtw89_dev *rtwdev,
         struct rtw89_debugfs_priv *debugfs_priv,
         const char *buf, size_t count)
{
 u32 sel, start_addr, len;
 int num;

 num = sscanf(buf, "%x %x %x", &sel, &start_addr, &len);
 if (num != 3) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 debugfs_priv->mac_mem.sel = sel;
 debugfs_priv->mac_mem.start = start_addr;
 debugfs_priv->mac_mem.len = len;

 rtw89_info(rtwdev, "select mem %d start %d len %d\n",
     sel, start_addr, len);

 return count;
}

static int rtw89_debug_dump_mac_mem(struct rtw89_dev *rtwdev,
        char *buf, size_t bufsz,
        u8 sel, u32 start_addr, u32 len)
{
 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 u32 filter_model_addr = mac->filter_model_addr;
 u32 indir_access_addr = mac->indir_access_addr;
 u32 mem_page_size = mac->mem_page_size;
 u32 base_addr, start_page, residue;
 char *p = buf, *end = buf + bufsz;
 u32 i, j, pp, pages;
 u32 dump_len, remain;
 u32 val;

 remain = len;
 pages = len / mem_page_size + 1;
 start_page = start_addr / mem_page_size;
 residue = start_addr % mem_page_size;
 base_addr = mac->mem_base_addrs[sel];
 base_addr += start_page * mem_page_size;

 for (pp = 0; pp < pages; pp++) {
  dump_len = min_t(u32, remain, mem_page_size);
  rtw89_write32(rtwdev, filter_model_addr, base_addr);
  for (i = indir_access_addr + residue;
       i < indir_access_addr + dump_len;) {
   p += scnprintf(p, end - p, "%08xh:", i);
   for (j = 0;
        j < 4 && i < indir_access_addr + dump_len;
        j++, i += 4) {
    val = rtw89_read32(rtwdev, i);
    p += scnprintf(p, end - p, " %08x", val);
    remain -= 4;
   }
   p += scnprintf(p, end - p, "\n");
  }
  base_addr += mem_page_size;
 }

 return p - buf;
}

static ssize_t
rtw89_debug_priv_mac_mem_dump_get(struct rtw89_dev *rtwdev,
      struct rtw89_debugfs_priv *debugfs_priv,
      char *buf, size_t bufsz)
{
 char *p = buf, *end = buf + bufsz;
 bool grant_read = false;

 lockdep_assert_wiphy(rtwdev->hw->wiphy);

 if (debugfs_priv->mac_mem.sel >= RTW89_MAC_MEM_NUM)
  return -ENOENT;

 if (rtwdev->chip->chip_id == RTL8852C) {
  switch (debugfs_priv->mac_mem.sel) {
  case RTW89_MAC_MEM_TXD_FIFO_0_V1:
  case RTW89_MAC_MEM_TXD_FIFO_1_V1:
  case RTW89_MAC_MEM_TXDATA_FIFO_0:
  case RTW89_MAC_MEM_TXDATA_FIFO_1:
   grant_read = true;
   break;
  default:
   break;
  }
 }

 rtw89_leave_ps_mode(rtwdev);
 if (grant_read)
  rtw89_write32_set(rtwdev, R_AX_TCR1, B_AX_TCR_FORCE_READ_TXDFIFO);
 p += rtw89_debug_dump_mac_mem(rtwdev, p, end - p,
          debugfs_priv->mac_mem.sel,
          debugfs_priv->mac_mem.start,
          debugfs_priv->mac_mem.len);
 if (grant_read)
  rtw89_write32_clr(rtwdev, R_AX_TCR1, B_AX_TCR_FORCE_READ_TXDFIFO);

 return p - buf;
}

static ssize_t
rtw89_debug_priv_mac_dbg_port_dump_select(struct rtw89_dev *rtwdev,
       struct rtw89_debugfs_priv *debugfs_priv,
       const char *buf, size_t count)
{
 int sel, set;
 int num;
 bool enable;

 num = sscanf(buf, "%d %d", &sel, &set);
 if (num != 2) {
  rtw89_info(rtwdev, "invalid format: \n");
  return -EINVAL;
 }

 enable = set != 0;
 switch (sel) {
 case 0:
  debugfs_priv->dbgpkg_en.ss_dbg = enable;
  break;
 case 1:
  debugfs_priv->dbgpkg_en.dle_dbg = enable;
  break;
 case 2:
  debugfs_priv->dbgpkg_en.dmac_dbg = enable;
  break;
 case 3:
  debugfs_priv->dbgpkg_en.cmac_dbg = enable;
  break;
 case 4:
  debugfs_priv->dbgpkg_en.dbg_port = enable;
  break;
 default:
  rtw89_info(rtwdev, "invalid args: sel %d set %d\n", sel, set);
  return -EINVAL;
 }

 rtw89_info(rtwdev, "%s debug port dump %d\n",
     enable ? "Enable" : "Disable", sel);

 return count;
}

static int rtw89_debug_mac_dump_ss_dbg(struct rtw89_dev *rtwdev,
           char *buf, size_t bufsz)
{
 return 0;
}

static int rtw89_debug_mac_dump_dle_dbg(struct rtw89_dev *rtwdev,
           char *buf, size_t bufsz)
{
#define DLE_DFI_DUMP(__type, __target, __sel)    \
({         \
 u32 __ctrl;       \
 u32 __reg_ctrl = R_AX_##__type##_DBG_FUN_INTF_CTL;  \
 u32 __reg_data = R_AX_##__type##_DBG_FUN_INTF_DATA;  \
 u32 __data, __val32;      \
 int __ret;       \
         \
 __ctrl = FIELD_PREP(B_AX_##__type##_DFI_TRGSEL_MASK,  \
       DLE_DFI_TYPE_##__target) |   \
   FIELD_PREP(B_AX_##__type##_DFI_ADDR_MASK, __sel) | \
   B_AX_WDE_DFI_ACTIVE;     \
 rtw89_write32(rtwdev, __reg_ctrl, __ctrl);   \
 __ret = read_poll_timeout(rtw89_read32, __val32,  \
   !(__val32 & B_AX_##__type##_DFI_ACTIVE), \
   1000, 50000, false,    \
   rtwdev, __reg_ctrl);    \
 if (__ret) {       \
  rtw89_err(rtwdev, "failed to dump DLE %s %s %d\n", \
     #__type, #__target, __sel);   \
  return __ret;      \
 }        \
         \
 __data = rtw89_read32(rtwdev, __reg_data);   \
 __data;        \
})

#define DLE_DFI_FREE_PAGE_DUMP(__p, __end, __type)   \
({         \
 u32 __freepg, __pubpg;      \
 u32 __freepg_head, __freepg_tail, __pubpg_num;   \
         \
 __freepg = DLE_DFI_DUMP(__type, FREEPG, 0);   \
 __pubpg = DLE_DFI_DUMP(__type, FREEPG, 1);   \
 __freepg_head = FIELD_GET(B_AX_DLE_FREE_HEADPG, __freepg); \
 __freepg_tail = FIELD_GET(B_AX_DLE_FREE_TAILPG, __freepg); \
 __pubpg_num = FIELD_GET(B_AX_DLE_PUB_PGNUM, __pubpg);  \
 __p += scnprintf(__p, __end - __p, "[%s] freepg head: %d\n", \
    #__type, __freepg_head);   \
 __p += scnprintf(__p, __end - __p, "[%s] freepg tail: %d\n", \
    #__type, __freepg_tail);   \
 __p += scnprintf(__p, __end - __p, "[%s] pubpg num : %d\n", \
    #__type, __pubpg_num);    \
})

#define case_QUOTA(__p, __end, __type, __id)    \
 case __type##_QTAID_##__id:     \
  val32 = DLE_DFI_DUMP(__type, QUOTA, __type##_QTAID_##__id); \
  rsv_pgnum = FIELD_GET(B_AX_DLE_RSV_PGNUM, val32); \
  use_pgnum = FIELD_GET(B_AX_DLE_USE_PGNUM, val32); \
  __p += scnprintf(__p, __end - __p, "[%s][%s] rsv_pgnum: %d\n", \
     #__type, #__id, rsv_pgnum);  \
  __p += scnprintf(__p, __end - __p, "[%s][%s] use_pgnum: %d\n", \
     #__type, #__id, use_pgnum);  \
  break
 char *p = buf, *end = buf + bufsz;
 u32 quota_id;
 u32 val32;
 u16 rsv_pgnum, use_pgnum;
 int ret;

 ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
 if (ret) {
  p += scnprintf(p, end - p, "[DLE] : DMAC not enabled\n");
  goto out;
 }

 DLE_DFI_FREE_PAGE_DUMP(p, end, WDE);
 DLE_DFI_FREE_PAGE_DUMP(p, end, PLE);
 for (quota_id = 0; quota_id <= WDE_QTAID_CPUIO; quota_id++) {
  switch (quota_id) {
  case_QUOTA(p, end, WDE, HOST_IF);
  case_QUOTA(p, end, WDE, WLAN_CPU);
  case_QUOTA(p, end, WDE, DATA_CPU);
  case_QUOTA(p, end, WDE, PKTIN);
  case_QUOTA(p, end, WDE, CPUIO);
  }
 }
 for (quota_id = 0; quota_id <= PLE_QTAID_CPUIO; quota_id++) {
  switch (quota_id) {
  case_QUOTA(p, end, PLE, B0_TXPL);
  case_QUOTA(p, end, PLE, B1_TXPL);
  case_QUOTA(p, end, PLE, C2H);
  case_QUOTA(p, end, PLE, H2C);
  case_QUOTA(p, end, PLE, WLAN_CPU);
  case_QUOTA(p, end, PLE, MPDU);
  case_QUOTA(p, end, PLE, CMAC0_RX);
  case_QUOTA(p, end, PLE, CMAC1_RX);
  case_QUOTA(p, end, PLE, CMAC1_BBRPT);
  case_QUOTA(p, end, PLE, WDRLS);
  case_QUOTA(p, end, PLE, CPUIO);
  }
 }

out:
 return p - buf;

#undef case_QUOTA
#undef DLE_DFI_DUMP
#undef DLE_DFI_FREE_PAGE_DUMP
}

static int rtw89_debug_mac_dump_dmac_dbg(struct rtw89_dev *rtwdev,
      char *buf, size_t bufsz)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 char *p = buf, *end = buf + bufsz;
 u32 dmac_err;
 int i, ret;

 ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
 if (ret) {
  p += scnprintf(p, end - p, "[DMAC] : DMAC not enabled\n");
  goto out;
 }

 dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
 p += scnprintf(p, end - p, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err);
 p += scnprintf(p, end - p, "R_AX_DMAC_ERR_IMR=0x%08x\n",
         rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR));

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

 if (dmac_err & B_AX_WDRLS_ERR_FLAG) {
  p += scnprintf(p, end - p, "R_AX_WDRLS_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_WDRLS_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR));
  if (chip->chip_id == RTL8852C)
   p += scnprintf(p, end - p,
           "R_AX_RPQ_RXBD_IDX=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1));
  else
   p += scnprintf(p, end - p,
           "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) {
   p += scnprintf(p, end - p,
           "R_AX_SEC_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR));
   p += scnprintf(p, end - p,
           "R_AX_SEC_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG));
   p += scnprintf(p, end - p,
           "R_AX_SEC_ENG_CTRL=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
   p += scnprintf(p, end - p,
           "R_AX_SEC_MPDU_PROC=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
   p += scnprintf(p, end - p,
           "R_AX_SEC_CAM_ACCESS=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
   p += scnprintf(p, end - p,
           "R_AX_SEC_CAM_RDATA=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
   p += scnprintf(p, end - p, "R_AX_SEC_DEBUG1=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_DEBUG1));
   p += scnprintf(p, end - p,
           "R_AX_SEC_TX_DEBUG=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
   p += scnprintf(p, end - p,
           "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);
    p += scnprintf(p, end - p,
            "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n",
            i,
            rtw89_read32(rtwdev, R_AX_SEC_DEBUG2));
   }
  } else {
   p += scnprintf(p, end - p,
           "R_AX_SEC_ERR_IMR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_DEBUG));
   p += scnprintf(p, end - p,
           "R_AX_SEC_ENG_CTRL=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
   p += scnprintf(p, end - p,
           "R_AX_SEC_MPDU_PROC=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
   p += scnprintf(p, end - p,
           "R_AX_SEC_CAM_ACCESS=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
   p += scnprintf(p, end - p,
           "R_AX_SEC_CAM_RDATA=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
   p += scnprintf(p, end - p,
           "R_AX_SEC_CAM_WDATA=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA));
   p += scnprintf(p, end - p,
           "R_AX_SEC_TX_DEBUG=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
   p += scnprintf(p, end - p,
           "R_AX_SEC_RX_DEBUG=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
   p += scnprintf(p, end - p,
           "R_AX_SEC_TRX_PKT_CNT=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT));
   p += scnprintf(p, end - p,
           "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) {
  p += scnprintf(p, end - p, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR));
  p += scnprintf(p, end - p, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR));
  p += scnprintf(p, end - p, "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) {
  p += scnprintf(p, end - p,
          "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR));
  p += scnprintf(p, end - p,
          "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) {
  p += scnprintf(p, end - p, "R_AX_WDE_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_WDE_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
  p += scnprintf(p, end - p, "R_AX_PLE_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
  p += scnprintf(p, end - p, "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) {
   p += scnprintf(p, end - p,
           "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR));
   p += scnprintf(p, end - p,
           "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR));
   p += scnprintf(p, end - p,
           "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR));
   p += scnprintf(p, end - p,
           "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR));
  } else {
   p += scnprintf(p, end - p,
           "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR));
   p += scnprintf(p, end - p,
           "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) {
  p += scnprintf(p, end - p, "R_AX_WDE_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_WDE_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
  p += scnprintf(p, end - p, "R_AX_PLE_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
  p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_0=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0));
  p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_1=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1));
  p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_2=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2));
  p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS));
  p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_0=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0));
  p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_1=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1));
  p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_2=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2));
  p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS));
  if (chip->chip_id == RTL8852C) {
   p += scnprintf(p, end - p, "R_AX_RX_CTRL0=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RX_CTRL0));
   p += scnprintf(p, end - p, "R_AX_RX_CTRL1=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RX_CTRL1));
   p += scnprintf(p, end - p, "R_AX_RX_CTRL2=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RX_CTRL2));
  } else {
   p += scnprintf(p, end - p,
           "R_AX_RXDMA_PKT_INFO_0=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0));
   p += scnprintf(p, end - p,
           "R_AX_RXDMA_PKT_INFO_1=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1));
   p += scnprintf(p, end - p,
           "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) {
  p += scnprintf(p, end - p, "R_AX_PKTIN_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR));
  p += scnprintf(p, end - p, "R_AX_PKTIN_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR));
 }

 if (dmac_err & B_AX_DISPATCH_ERR_FLAG) {
  p += scnprintf(p, end - p,
          "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
  p += scnprintf(p, end - p,
          "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
  p += scnprintf(p, end - p,
          "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
  p += scnprintf(p, end - p,
          "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
  p += scnprintf(p, end - p,
          "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
  p += scnprintf(p, end - p,
          "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) {
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
  } else {
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
   p += scnprintf(p, end - p,
           "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
           rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
  }
 }

 if (dmac_err & B_AX_HAXIDMA_ERR_FLAG && chip->chip_id == RTL8852C) {
  p += scnprintf(p, end - p, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK));
  p += scnprintf(p, end - p, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n",
          rtw89_read32(rtwdev, R_AX_HAXI_IDCT));
 }

out:
 return p - buf;
}

static int rtw89_debug_mac_dump_cmac_err(struct rtw89_dev *rtwdev,
      char *buf, size_t bufsz,
      enum rtw89_mac_idx band)
{
 const struct rtw89_chip_info *chip = rtwdev->chip;
 char *p = buf, *end = buf + bufsz;
 u32 offset = 0;
 u32 cmac_err;
 int ret;

 ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL);
 if (ret) {
  if (band)
   p += scnprintf(p, end - p,
           "[CMAC] : CMAC1 not enabled\n");
  else
   p += scnprintf(p, end - p,
           "[CMAC] : CMAC0 not enabled\n");
  goto out;
 }

 if (band)
  offset = RTW89_MAC_AX_BAND_REG_OFFSET;

 cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset);
 p += scnprintf(p, end - p, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band,
         rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset));
 p += scnprintf(p, end - p, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band,
         rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset));
 p += scnprintf(p, end - p, "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) {
  p += scnprintf(p, end - p,
          "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band,
          rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset));
  p += scnprintf(p, end - p,
          "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) {
  p += scnprintf(p, end - p, "R_AX_PTCL_IMR0 [%d]=0x%08x\n",
          band,
          rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset));
  p += scnprintf(p, end - p, "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) {
   p += scnprintf(p, end - p,
           "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band,
           rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset));
   p += scnprintf(p, end - p,
           "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset));
  } else {
   p += scnprintf(p, end - p,
           "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) {
   p += scnprintf(p, end - p,
           "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset));
   p += scnprintf(p, end - p,
           "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
  } else {
   p += scnprintf(p, end - p,
           "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) {
  p += scnprintf(p, end - p, "R_AX_TXPWR_IMR [%d]=0x%08x\n",
          band,
          rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset));
  p += scnprintf(p, end - p, "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) {
   p += scnprintf(p, end - p,
           "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev,
          R_AX_TRXPTCL_ERROR_INDICA + offset));
   p += scnprintf(p, end - p,
           "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev,
          R_AX_TRXPTCL_ERROR_INDICA_MASK + offset));
  } else {
   p += scnprintf(p, end - p,
           "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n",
           band,
           rtw89_read32(rtwdev,
          R_AX_TMAC_ERR_IMR_ISR + offset));
  }
  p += scnprintf(p, end - p,
          "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band,
          rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset));
 }

 p += scnprintf(p, end - p, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band,
         rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset));

out:
 return p - buf;
}

static int rtw89_debug_mac_dump_cmac_dbg(struct rtw89_dev *rtwdev,
      char *buf, size_t bufsz)
{
 char *p = buf, *end = buf + bufsz;

 p += rtw89_debug_mac_dump_cmac_err(rtwdev, p, end - p, RTW89_MAC_0);
 if (rtwdev->dbcc_en)
  p += rtw89_debug_mac_dump_cmac_err(rtwdev, p, end - p, RTW89_MAC_1);

 return p - buf;
}

static const struct rtw89_mac_dbg_port_info dbg_port_ptcl_c0 = {
 .sel_addr = R_AX_PTCL_DBG,
 .sel_byte = 1,
 .sel_msk = B_AX_PTCL_DBG_SEL_MASK,
 .srt = 0x00,
 .end = 0x3F,
 .rd_addr = R_AX_PTCL_DBG_INFO,
 .rd_byte = 4,
 .rd_msk = B_AX_PTCL_DBG_INFO_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_ptcl_c1 = {
 .sel_addr = R_AX_PTCL_DBG_C1,
 .sel_byte = 1,
 .sel_msk = B_AX_PTCL_DBG_SEL_MASK,
 .srt = 0x00,
 .end = 0x3F,
 .rd_addr = R_AX_PTCL_DBG_INFO_C1,
 .rd_byte = 4,
 .rd_msk = B_AX_PTCL_DBG_INFO_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx0_5 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0xD,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx6 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x5,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx7 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x9,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx8 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x3,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx9_C = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x1,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_txD = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx0 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0xB,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx1 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x4,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx3 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x8,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx4 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x7,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx5_8 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x1,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx9 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x3,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_txA_C = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx0 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x8,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx1_2 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx3 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x6,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx4 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx5 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 2,
 .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_0 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x3,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_1 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x6,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_2 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x0,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p1 = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x8,
 .end = 0xE,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_stf_ctrl = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x5,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_addr_ctrl = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x6,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_wde_intf = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0xF,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_ple_intf = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x9,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_dspt_flow_ctrl = {
 .sel_addr = R_AX_DISPATCHER_DBG_PORT,
 .sel_byte = 1,
 .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
 .srt = 0x0,
 .end = 0x3,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_sch_c0 = {
 .sel_addr = R_AX_SCH_DBG_SEL,
 .sel_byte = 1,
 .sel_msk = B_AX_SCH_DBG_SEL_MASK,
 .srt = 0x00,
 .end = 0x2F,
 .rd_addr = R_AX_SCH_DBG,
 .rd_byte = 4,
 .rd_msk = B_AX_SCHEDULER_DBG_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_sch_c1 = {
 .sel_addr = R_AX_SCH_DBG_SEL_C1,
 .sel_byte = 1,
 .sel_msk = B_AX_SCH_DBG_SEL_MASK,
 .srt = 0x00,
 .end = 0x2F,
 .rd_addr = R_AX_SCH_DBG_C1,
 .rd_byte = 4,
 .rd_msk = B_AX_SCHEDULER_DBG_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_tmac_c0 = {
 .sel_addr = R_AX_MACTX_DBG_SEL_CNT,
 .sel_byte = 1,
 .sel_msk = B_AX_DBGSEL_MACTX_MASK,
 .srt = 0x00,
 .end = 0x19,
 .rd_addr = R_AX_DBG_PORT_SEL,
 .rd_byte = 4,
 .rd_msk = B_AX_DEBUG_ST_MASK
};

static const struct rtw89_mac_dbg_port_info dbg_port_tmac_c1 = {
 .sel_addr = R_AX_MACTX_DBG_SEL_CNT_C1,
 .sel_byte = 1,
 .sel_msk = B_AX_DBGSEL_MACTX_MASK,
 .srt = 0x00,
--> --------------------

--> maximum size reached

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

Messung V0.5
C=100 H=93 G=96

¤ Dauer der Verarbeitung: 0.11 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.