File Index
Files and directories
Sign in
FILE

debug.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/realtek/rtw89/debug.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/* Copyright(c) 2019-2020  Realtek Corporation
   3 */
   4
   5#include <linux/vmalloc.h>
   6
   7#include "coex.h"
   8#include "debug.h"
   9#include "fw.h"
  10#include "mac.h"
  11#include "pci.h"
  12#include "phy.h"
  13#include "ps.h"
  14#include "reg.h"
  15#include "sar.h"
  16#include "util.h"
  17
  18#ifdef CONFIG_RTW89_DEBUGMSG
  19unsigned int rtw89_debug_mask;
  20EXPORT_SYMBOL(rtw89_debug_mask);
  21module_param_named(debug_mask, rtw89_debug_mask, uint, 0644);
  22MODULE_PARM_DESC(debug_mask, "Debugging mask");
  23#endif
  24
  25#ifdef CONFIG_RTW89_DEBUGFS
  26struct rtw89_debugfs_priv_opt {
  27	bool rlock:1;
  28	bool wlock:1;
  29	size_t rsize;
  30};
  31
  32struct rtw89_debugfs_priv {
  33	struct rtw89_dev *rtwdev;
  34	ssize_t (*cb_read)(struct rtw89_dev *rtwdev,
  35			   struct rtw89_debugfs_priv *debugfs_priv,
  36			   char *buf, size_t bufsz);
  37	ssize_t (*cb_write)(struct rtw89_dev *rtwdev,
  38			    struct rtw89_debugfs_priv *debugfs_priv,
  39			    const char *buf, size_t count);
  40	struct rtw89_debugfs_priv_opt opt;
  41	union {
  42		u32 cb_data;
  43		struct {
  44			u32 addr;
  45			u32 len;
  46		} read_reg;
  47		struct {
  48			u32 addr;
  49			u32 mask;
  50			u8 path;
  51		} read_rf;
  52		struct {
  53			u8 ss_dbg:1;
  54			u8 dle_dbg:1;
  55			u8 dmac_dbg:1;
  56			u8 cmac_dbg:1;
  57			u8 dbg_port:1;
  58		} dbgpkg_en;
  59		struct {
  60			u32 start;
  61			u32 len;
  62			u8 sel;
  63		} mac_mem;
  64	};
  65	ssize_t rused;
  66	char *rbuf;
  67};
  68
  69struct rtw89_debugfs {
  70	struct rtw89_debugfs_priv read_reg;
  71	struct rtw89_debugfs_priv write_reg;
  72	struct rtw89_debugfs_priv read_rf;
  73	struct rtw89_debugfs_priv write_rf;
  74	struct rtw89_debugfs_priv rf_reg_dump;
  75	struct rtw89_debugfs_priv txpwr_table;
  76	struct rtw89_debugfs_priv mac_reg_dump;
  77	struct rtw89_debugfs_priv mac_mem_dump;
  78	struct rtw89_debugfs_priv mac_dbg_port_dump;
  79	struct rtw89_debugfs_priv send_h2c;
  80	struct rtw89_debugfs_priv early_h2c;
  81	struct rtw89_debugfs_priv fw_crash;
  82	struct rtw89_debugfs_priv btc_info;
  83	struct rtw89_debugfs_priv btc_manual;
  84	struct rtw89_debugfs_priv fw_log_manual;
  85	struct rtw89_debugfs_priv phy_info;
  86	struct rtw89_debugfs_priv stations;
  87	struct rtw89_debugfs_priv disable_dm;
  88	struct rtw89_debugfs_priv mlo_mode;
  89	struct rtw89_debugfs_priv beacon_info;
  90	struct rtw89_debugfs_priv diag_mac;
  91};
  92
  93struct rtw89_debugfs_iter_data {
  94	char *buf;
  95	size_t bufsz;
  96	int written_sz;
  97};
  98
  99static void rtw89_debugfs_iter_data_setup(struct rtw89_debugfs_iter_data *iter_data,
 100					  char *buf, size_t bufsz)
 101{
 102	iter_data->buf = buf;
 103	iter_data->bufsz = bufsz;
 104	iter_data->written_sz = 0;
 105}
 106
 107static void rtw89_debugfs_iter_data_next(struct rtw89_debugfs_iter_data *iter_data,
 108					 char *buf, size_t bufsz, int written_sz)
 109{
 110	iter_data->buf = buf;
 111	iter_data->bufsz = bufsz;
 112	iter_data->written_sz += written_sz;
 113}
 114
 115static const u16 rtw89_rate_info_bw_to_mhz_map[] = {
 116	[RATE_INFO_BW_20] = 20,
 117	[RATE_INFO_BW_40] = 40,
 118	[RATE_INFO_BW_80] = 80,
 119	[RATE_INFO_BW_160] = 160,
 120	[RATE_INFO_BW_320] = 320,
 121};
 122
 123static u16 rtw89_rate_info_bw_to_mhz(enum rate_info_bw bw)
 124{
 125	if (bw < ARRAY_SIZE(rtw89_rate_info_bw_to_mhz_map))
 126		return rtw89_rate_info_bw_to_mhz_map[bw];
 127
 128	return 0;
 129}
 130
 131static ssize_t rtw89_debugfs_file_read_helper(struct wiphy *wiphy, struct file *file,
 132					      char *buf, size_t bufsz, void *data)
 133{
 134	struct rtw89_debugfs_priv *debugfs_priv = data;
 135	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 136	ssize_t n;
 137
 138	n = debugfs_priv->cb_read(rtwdev, debugfs_priv, buf, bufsz);
 139	rtw89_might_trailing_ellipsis(buf, bufsz, n);
 140
 141	return n;
 142}
 143
 144static ssize_t rtw89_debugfs_file_read(struct file *file, char __user *userbuf,
 145				       size_t count, loff_t *ppos)
 146{
 147	struct rtw89_debugfs_priv *debugfs_priv = file->private_data;
 148	struct rtw89_debugfs_priv_opt *opt = &debugfs_priv->opt;
 149	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 150	size_t bufsz = opt->rsize ? opt->rsize : PAGE_SIZE;
 151	char *buf;
 152	ssize_t n;
 153
 154	if (!debugfs_priv->rbuf)
 155		debugfs_priv->rbuf = devm_kzalloc(rtwdev->dev, bufsz, GFP_KERNEL);
 156
 157	buf = debugfs_priv->rbuf;
 158	if (!buf)
 159		return -ENOMEM;
 160
 161	if (*ppos) {
 162		n = debugfs_priv->rused;
 163		goto out;
 164	}
 165
 166	if (opt->rlock) {
 167		n = wiphy_locked_debugfs_read(rtwdev->hw->wiphy, file, buf, bufsz,
 168					      userbuf, count, ppos,
 169					      rtw89_debugfs_file_read_helper,
 170					      debugfs_priv);
 171		debugfs_priv->rused = n;
 172
 173		return n;
 174	}
 175
 176	n = rtw89_debugfs_file_read_helper(rtwdev->hw->wiphy, file, buf, bufsz,
 177					   debugfs_priv);
 178	debugfs_priv->rused = n;
 179
 180out:
 181	return simple_read_from_buffer(userbuf, count, ppos, buf, n);
 182}
 183
 184static ssize_t rtw89_debugfs_file_write_helper(struct wiphy *wiphy, struct file *file,
 185					       char *buf, size_t count, void *data)
 186{
 187	struct rtw89_debugfs_priv *debugfs_priv = data;
 188	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 189
 190	return debugfs_priv->cb_write(rtwdev, debugfs_priv, buf, count);
 191}
 192
 193static ssize_t rtw89_debugfs_file_write(struct file *file,
 194					const char __user *userbuf,
 195					size_t count, loff_t *loff)
 196{
 197	struct rtw89_debugfs_priv *debugfs_priv = file->private_data;
 198	struct rtw89_debugfs_priv_opt *opt = &debugfs_priv->opt;
 199	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
 200	char *buf __free(kfree) = kmalloc(count + 1, GFP_KERNEL);
 201	ssize_t n;
 202
 203	if (!buf)
 204		return -ENOMEM;
 205
 206	if (opt->wlock) {
 207		n = wiphy_locked_debugfs_write(rtwdev->hw->wiphy,
 208					       file, buf, count + 1,
 209					       userbuf, count,
 210					       rtw89_debugfs_file_write_helper,
 211					       debugfs_priv);
 212		return n;
 213	}
 214
 215	if (copy_from_user(buf, userbuf, count))
 216		return -EFAULT;
 217
 218	buf[count] = '\0';
 219
 220	return debugfs_priv->cb_write(rtwdev, debugfs_priv, buf, count);
 221}
 222
 223static const struct debugfs_short_fops file_ops_single_r = {
 224	.read = rtw89_debugfs_file_read,
 225	.llseek = generic_file_llseek,
 226};
 227
 228static const struct debugfs_short_fops file_ops_common_rw = {
 229	.read = rtw89_debugfs_file_read,
 230	.write = rtw89_debugfs_file_write,
 231	.llseek = generic_file_llseek,
 232};
 233
 234static const struct debugfs_short_fops file_ops_single_w = {
 235	.write = rtw89_debugfs_file_write,
 236	.llseek = generic_file_llseek,
 237};
 238
 239static ssize_t
 240rtw89_debug_priv_read_reg_select(struct rtw89_dev *rtwdev,
 241				 struct rtw89_debugfs_priv *debugfs_priv,
 242				 const char *buf, size_t count)
 243{
 244	u32 addr, len;
 245	int num;
 246
 247	num = sscanf(buf, "%x %x", &addr, &len);
 248	if (num != 2) {
 249		rtw89_info(rtwdev, "invalid format: <addr> <len>\n");
 250		return -EINVAL;
 251	}
 252
 253	debugfs_priv->read_reg.addr = addr;
 254	debugfs_priv->read_reg.len = len;
 255
 256	rtw89_info(rtwdev, "select read %d bytes from 0x%08x\n", len, addr);
 257
 258	return count;
 259}
 260
 261static
 262ssize_t rtw89_debug_priv_read_reg_get(struct rtw89_dev *rtwdev,
 263				      struct rtw89_debugfs_priv *debugfs_priv,
 264				      char *buf, size_t bufsz)
 265{
 266	char *p = buf, *end = buf + bufsz;
 267	u32 addr, addr_end, data, k;
 268	u32 len;
 269
 270	len = debugfs_priv->read_reg.len;
 271	addr = debugfs_priv->read_reg.addr;
 272
 273	if (len > 4)
 274		goto ndata;
 275
 276	switch (len) {
 277	case 1:
 278		data = rtw89_read8(rtwdev, addr);
 279		break;
 280	case 2:
 281		data = rtw89_read16(rtwdev, addr);
 282		break;
 283	case 4:
 284		data = rtw89_read32(rtwdev, addr);
 285		break;
 286	default:
 287		rtw89_info(rtwdev, "invalid read reg len %d\n", len);
 288		return -EINVAL;
 289	}
 290
 291	p += scnprintf(p, end - p, "get %d bytes at 0x%08x=0x%08x\n", len,
 292		       addr, data);
 293
 294	return p - buf;
 295
 296ndata:
 297	addr_end = addr + len;
 298
 299	for (; addr < addr_end; addr += 16) {
 300		p += scnprintf(p, end - p, "%08xh : ", 0x18600000 + addr);
 301		for (k = 0; k < 16; k += 4) {
 302			data = rtw89_read32(rtwdev, addr + k);
 303			p += scnprintf(p, end - p, "%08x ", data);
 304		}
 305		p += scnprintf(p, end - p, "\n");
 306	}
 307
 308	return p - buf;
 309}
 310
 311static
 312ssize_t rtw89_debug_priv_write_reg_set(struct rtw89_dev *rtwdev,
 313				       struct rtw89_debugfs_priv *debugfs_priv,
 314				       const char *buf, size_t count)
 315{
 316	u32 addr, val, len;
 317	int num;
 318
 319	num = sscanf(buf, "%x %x %x", &addr, &val, &len);
 320	if (num !=  3) {
 321		rtw89_info(rtwdev, "invalid format: <addr> <val> <len>\n");
 322		return -EINVAL;
 323	}
 324
 325	switch (len) {
 326	case 1:
 327		rtw89_info(rtwdev, "reg write8 0x%08x: 0x%02x\n", addr, val);
 328		rtw89_write8(rtwdev, addr, (u8)val);
 329		break;
 330	case 2:
 331		rtw89_info(rtwdev, "reg write16 0x%08x: 0x%04x\n", addr, val);
 332		rtw89_write16(rtwdev, addr, (u16)val);
 333		break;
 334	case 4:
 335		rtw89_info(rtwdev, "reg write32 0x%08x: 0x%08x\n", addr, val);
 336		rtw89_write32(rtwdev, addr, (u32)val);
 337		break;
 338	default:
 339		rtw89_info(rtwdev, "invalid read write len %d\n", len);
 340		break;
 341	}
 342
 343	return count;
 344}
 345
 346static ssize_t
 347rtw89_debug_priv_read_rf_select(struct rtw89_dev *rtwdev,
 348				struct rtw89_debugfs_priv *debugfs_priv,
 349				const char *buf, size_t count)
 350{
 351	u32 addr, mask;
 352	u8 path;
 353	int num;
 354
 355	num = sscanf(buf, "%hhd %x %x", &path, &addr, &mask);
 356	if (num != 3) {
 357		rtw89_info(rtwdev, "invalid format: <path> <addr> <mask>\n");
 358		return -EINVAL;
 359	}
 360
 361	if (path >= rtwdev->chip->rf_path_num) {
 362		rtw89_info(rtwdev, "wrong rf path\n");
 363		return -EINVAL;
 364	}
 365	debugfs_priv->read_rf.addr = addr;
 366	debugfs_priv->read_rf.mask = mask;
 367	debugfs_priv->read_rf.path = path;
 368
 369	rtw89_info(rtwdev, "select read rf path %d from 0x%08x\n", path, addr);
 370
 371	return count;
 372}
 373
 374static
 375ssize_t rtw89_debug_priv_read_rf_get(struct rtw89_dev *rtwdev,
 376				     struct rtw89_debugfs_priv *debugfs_priv,
 377				     char *buf, size_t bufsz)
 378{
 379	char *p = buf, *end = buf + bufsz;
 380	u32 addr, data, mask;
 381	u8 path;
 382
 383	addr = debugfs_priv->read_rf.addr;
 384	mask = debugfs_priv->read_rf.mask;
 385	path = debugfs_priv->read_rf.path;
 386
 387	data = rtw89_read_rf(rtwdev, path, addr, mask);
 388
 389	p += scnprintf(p, end - p, "path %d, rf register 0x%08x=0x%08x\n",
 390		       path, addr, data);
 391
 392	return p - buf;
 393}
 394
 395static
 396ssize_t rtw89_debug_priv_write_rf_set(struct rtw89_dev *rtwdev,
 397				      struct rtw89_debugfs_priv *debugfs_priv,
 398				      const char *buf, size_t count)
 399{
 400	u32 addr, val, mask;
 401	u8 path;
 402	int num;
 403
 404	num = sscanf(buf, "%hhd %x %x %x", &path, &addr, &mask, &val);
 405	if (num != 4) {
 406		rtw89_info(rtwdev, "invalid format: <path> <addr> <mask> <val>\n");
 407		return -EINVAL;
 408	}
 409
 410	if (path >= rtwdev->chip->rf_path_num) {
 411		rtw89_info(rtwdev, "wrong rf path\n");
 412		return -EINVAL;
 413	}
 414
 415	rtw89_info(rtwdev, "path %d, rf register write 0x%08x=0x%08x (mask = 0x%08x)\n",
 416		   path, addr, val, mask);
 417	rtw89_write_rf(rtwdev, path, addr, mask, val);
 418
 419	return count;
 420}
 421
 422static
 423ssize_t rtw89_debug_priv_rf_reg_dump_get(struct rtw89_dev *rtwdev,
 424					 struct rtw89_debugfs_priv *debugfs_priv,
 425					 char *buf, size_t bufsz)
 426{
 427	const struct rtw89_chip_info *chip = rtwdev->chip;
 428	char *p = buf, *end = buf + bufsz;
 429	u32 addr, offset, data;
 430	u8 path;
 431
 432	for (path = 0; path < chip->rf_path_num; path++) {
 433		p += scnprintf(p, end - p, "RF path %d:\n\n", path);
 434		for (addr = 0; addr < 0x100; addr += 4) {
 435			p += scnprintf(p, end - p, "0x%08x: ", addr);
 436			for (offset = 0; offset < 4; offset++) {
 437				data = rtw89_read_rf(rtwdev, path,
 438						     addr + offset, RFREG_MASK);
 439				p += scnprintf(p, end - p, "0x%05x  ", data);
 440			}
 441			p += scnprintf(p, end - p, "\n");
 442		}
 443		p += scnprintf(p, end - p, "\n");
 444	}
 445
 446	return p - buf;
 447}
 448
 449struct txpwr_ent {
 450	bool nested;
 451	union {
 452		const char *txt;
 453		const struct txpwr_ent *ptr;
 454	};
 455	u8 len;
 456};
 457
 458struct txpwr_map {
 459	const struct txpwr_ent *ent;
 460	u8 size;
 461	u32 addr_from;
 462	u32 addr_to;
 463	u32 addr_to_1ss;
 464};
 465
 466#define __GEN_TXPWR_ENT_NESTED(_e) \
 467	{ .nested = true, .ptr = __txpwr_ent_##_e, \
 468	  .len = ARRAY_SIZE(__txpwr_ent_##_e) }
 469
 470#define __GEN_TXPWR_ENT0(_t) { .len = 0, .txt = _t }
 471
 472#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
 473	{ .len = 2, .txt = _t "\t-  " _e0 "  " _e1 }
 474
 475#define __GEN_TXPWR_ENT4(_t, _e0, _e1, _e2, _e3) \
 476	{ .len = 4, .txt = _t "\t-  " _e0 "  " _e1 "  " _e2 "  " _e3 }
 477
 478#define __GEN_TXPWR_ENT8(_t, _e0, _e1, _e2, _e3, _e4, _e5, _e6, _e7) \
 479	{ .len = 8, .txt = _t "\t-  " \
 480	  _e0 "  " _e1 "  " _e2 "  " _e3 "  " \
 481	  _e4 "  " _e5 "  " _e6 "  " _e7 }
 482
 483static const struct txpwr_ent __txpwr_ent_byr_ax[] = {
 484	__GEN_TXPWR_ENT4("CCK       ", "1M   ", "2M   ", "5.5M ", "11M  "),
 485	__GEN_TXPWR_ENT4("LEGACY    ", "6M   ", "9M   ", "12M  ", "18M  "),
 486	__GEN_TXPWR_ENT4("LEGACY    ", "24M  ", "36M  ", "48M  ", "54M  "),
 487	/* 1NSS */
 488	__GEN_TXPWR_ENT4("MCS_1NSS  ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
 489	__GEN_TXPWR_ENT4("MCS_1NSS  ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
 490	__GEN_TXPWR_ENT4("MCS_1NSS  ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
 491	__GEN_TXPWR_ENT4("HEDCM_1NSS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
 492	/* 2NSS */
 493	__GEN_TXPWR_ENT4("MCS_2NSS  ", "MCS0 ", "MCS1 ", "MCS2 ", "MCS3 "),
 494	__GEN_TXPWR_ENT4("MCS_2NSS  ", "MCS4 ", "MCS5 ", "MCS6 ", "MCS7 "),
 495	__GEN_TXPWR_ENT4("MCS_2NSS  ", "MCS8 ", "MCS9 ", "MCS10", "MCS11"),
 496	__GEN_TXPWR_ENT4("HEDCM_2NSS", "MCS0 ", "MCS1 ", "MCS3 ", "MCS4 "),
 497};
 498
 499static_assert((ARRAY_SIZE(__txpwr_ent_byr_ax) * 4) ==
 500	(R_AX_PWR_BY_RATE_MAX - R_AX_PWR_BY_RATE + 4));
 501
 502static const struct txpwr_map __txpwr_map_byr_ax = {
 503	.ent = __txpwr_ent_byr_ax,
 504	.size = ARRAY_SIZE(__txpwr_ent_byr_ax),
 505	.addr_from = R_AX_PWR_BY_RATE,
 506	.addr_to = R_AX_PWR_BY_RATE_MAX,
 507	.addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
 508};
 509
 510static const struct txpwr_ent __txpwr_ent_lmt_ax[] = {
 511	/* 1TX */
 512	__GEN_TXPWR_ENT2("CCK_1TX_20M    ", "NON_BF", "BF"),
 513	__GEN_TXPWR_ENT2("CCK_1TX_40M    ", "NON_BF", "BF"),
 514	__GEN_TXPWR_ENT2("OFDM_1TX       ", "NON_BF", "BF"),
 515	__GEN_TXPWR_ENT2("MCS_1TX_20M_0  ", "NON_BF", "BF"),
 516	__GEN_TXPWR_ENT2("MCS_1TX_20M_1  ", "NON_BF", "BF"),
 517	__GEN_TXPWR_ENT2("MCS_1TX_20M_2  ", "NON_BF", "BF"),
 518	__GEN_TXPWR_ENT2("MCS_1TX_20M_3  ", "NON_BF", "BF"),
 519	__GEN_TXPWR_ENT2("MCS_1TX_20M_4  ", "NON_BF", "BF"),
 520	__GEN_TXPWR_ENT2("MCS_1TX_20M_5  ", "NON_BF", "BF"),
 521	__GEN_TXPWR_ENT2("MCS_1TX_20M_6  ", "NON_BF", "BF"),
 522	__GEN_TXPWR_ENT2("MCS_1TX_20M_7  ", "NON_BF", "BF"),
 523	__GEN_TXPWR_ENT2("MCS_1TX_40M_0  ", "NON_BF", "BF"),
 524	__GEN_TXPWR_ENT2("MCS_1TX_40M_1  ", "NON_BF", "BF"),
 525	__GEN_TXPWR_ENT2("MCS_1TX_40M_2  ", "NON_BF", "BF"),
 526	__GEN_TXPWR_ENT2("MCS_1TX_40M_3  ", "NON_BF", "BF"),
 527	__GEN_TXPWR_ENT2("MCS_1TX_80M_0  ", "NON_BF", "BF"),
 528	__GEN_TXPWR_ENT2("MCS_1TX_80M_1  ", "NON_BF", "BF"),
 529	__GEN_TXPWR_ENT2("MCS_1TX_160M   ", "NON_BF", "BF"),
 530	__GEN_TXPWR_ENT2("MCS_1TX_40M_0p5", "NON_BF", "BF"),
 531	__GEN_TXPWR_ENT2("MCS_1TX_40M_2p5", "NON_BF", "BF"),
 532	/* 2TX */
 533	__GEN_TXPWR_ENT2("CCK_2TX_20M    ", "NON_BF", "BF"),
 534	__GEN_TXPWR_ENT2("CCK_2TX_40M    ", "NON_BF", "BF"),
 535	__GEN_TXPWR_ENT2("OFDM_2TX       ", "NON_BF", "BF"),
 536	__GEN_TXPWR_ENT2("MCS_2TX_20M_0  ", "NON_BF", "BF"),
 537	__GEN_TXPWR_ENT2("MCS_2TX_20M_1  ", "NON_BF", "BF"),
 538	__GEN_TXPWR_ENT2("MCS_2TX_20M_2  ", "NON_BF", "BF"),
 539	__GEN_TXPWR_ENT2("MCS_2TX_20M_3  ", "NON_BF", "BF"),
 540	__GEN_TXPWR_ENT2("MCS_2TX_20M_4  ", "NON_BF", "BF"),
 541	__GEN_TXPWR_ENT2("MCS_2TX_20M_5  ", "NON_BF", "BF"),
 542	__GEN_TXPWR_ENT2("MCS_2TX_20M_6  ", "NON_BF", "BF"),
 543	__GEN_TXPWR_ENT2("MCS_2TX_20M_7  ", "NON_BF", "BF"),
 544	__GEN_TXPWR_ENT2("MCS_2TX_40M_0  ", "NON_BF", "BF"),
 545	__GEN_TXPWR_ENT2("MCS_2TX_40M_1  ", "NON_BF", "BF"),
 546	__GEN_TXPWR_ENT2("MCS_2TX_40M_2  ", "NON_BF", "BF"),
 547	__GEN_TXPWR_ENT2("MCS_2TX_40M_3  ", "NON_BF", "BF"),
 548	__GEN_TXPWR_ENT2("MCS_2TX_80M_0  ", "NON_BF", "BF"),
 549	__GEN_TXPWR_ENT2("MCS_2TX_80M_1  ", "NON_BF", "BF"),
 550	__GEN_TXPWR_ENT2("MCS_2TX_160M   ", "NON_BF", "BF"),
 551	__GEN_TXPWR_ENT2("MCS_2TX_40M_0p5", "NON_BF", "BF"),
 552	__GEN_TXPWR_ENT2("MCS_2TX_40M_2p5", "NON_BF", "BF"),
 553};
 554
 555static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ax) * 2) ==
 556	(R_AX_PWR_LMT_MAX - R_AX_PWR_LMT + 4));
 557
 558static const struct txpwr_map __txpwr_map_lmt_ax = {
 559	.ent = __txpwr_ent_lmt_ax,
 560	.size = ARRAY_SIZE(__txpwr_ent_lmt_ax),
 561	.addr_from = R_AX_PWR_LMT,
 562	.addr_to = R_AX_PWR_LMT_MAX,
 563	.addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
 564};
 565
 566static const struct txpwr_ent __txpwr_ent_lmt_ru_ax[] = {
 567	/* 1TX */
 568	__GEN_TXPWR_ENT8("1TX", "RU26__0", "RU26__1", "RU26__2", "RU26__3",
 569			 "RU26__4", "RU26__5", "RU26__6", "RU26__7"),
 570	__GEN_TXPWR_ENT8("1TX", "RU52__0", "RU52__1", "RU52__2", "RU52__3",
 571			 "RU52__4", "RU52__5", "RU52__6", "RU52__7"),
 572	__GEN_TXPWR_ENT8("1TX", "RU106_0", "RU106_1", "RU106_2", "RU106_3",
 573			 "RU106_4", "RU106_5", "RU106_6", "RU106_7"),
 574	/* 2TX */
 575	__GEN_TXPWR_ENT8("2TX", "RU26__0", "RU26__1", "RU26__2", "RU26__3",
 576			 "RU26__4", "RU26__5", "RU26__6", "RU26__7"),
 577	__GEN_TXPWR_ENT8("2TX", "RU52__0", "RU52__1", "RU52__2", "RU52__3",
 578			 "RU52__4", "RU52__5", "RU52__6", "RU52__7"),
 579	__GEN_TXPWR_ENT8("2TX", "RU106_0", "RU106_1", "RU106_2", "RU106_3",
 580			 "RU106_4", "RU106_5", "RU106_6", "RU106_7"),
 581};
 582
 583static_assert((ARRAY_SIZE(__txpwr_ent_lmt_ru_ax) * 8) ==
 584	(R_AX_PWR_RU_LMT_MAX - R_AX_PWR_RU_LMT + 4));
 585
 586static const struct txpwr_map __txpwr_map_lmt_ru_ax = {
 587	.ent = __txpwr_ent_lmt_ru_ax,
 588	.size = ARRAY_SIZE(__txpwr_ent_lmt_ru_ax),
 589	.addr_from = R_AX_PWR_RU_LMT,
 590	.addr_to = R_AX_PWR_RU_LMT_MAX,
 591	.addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
 592};
 593
 594static const struct txpwr_ent __txpwr_ent_byr_mcs_be[] = {
 595	__GEN_TXPWR_ENT4("MCS_1SS       ", "MCS0  ", "MCS1  ", "MCS2 ", "MCS3 "),
 596	__GEN_TXPWR_ENT4("MCS_1SS       ", "MCS4  ", "MCS5  ", "MCS6 ", "MCS7 "),
 597	__GEN_TXPWR_ENT4("MCS_1SS       ", "MCS8  ", "MCS9  ", "MCS10", "MCS11"),
 598	__GEN_TXPWR_ENT2("MCS_1SS       ", "MCS12 ", "MCS13 \t"),
 599	__GEN_TXPWR_ENT4("HEDCM_1SS     ", "MCS0  ", "MCS1  ", "MCS3 ", "MCS4 "),
 600	__GEN_TXPWR_ENT4("DLRU_MCS_1SS  ", "MCS0  ", "MCS1  ", "MCS2 ", "MCS3 "),
 601	__GEN_TXPWR_ENT4("DLRU_MCS_1SS  ", "MCS4  ", "MCS5  ", "MCS6 ", "MCS7 "),
 602	__GEN_TXPWR_ENT4("DLRU_MCS_1SS  ", "MCS8  ", "MCS9  ", "MCS10", "MCS11"),
 603	__GEN_TXPWR_ENT2("DLRU_MCS_1SS  ", "MCS12 ", "MCS13 \t"),
 604	__GEN_TXPWR_ENT4("DLRU_HEDCM_1SS", "MCS0  ", "MCS1  ", "MCS3 ", "MCS4 "),
 605	__GEN_TXPWR_ENT4("MCS_2SS       ", "MCS0  ", "MCS1  ", "MCS2 ", "MCS3 "),
 606	__GEN_TXPWR_ENT4("MCS_2SS       ", "MCS4  ", "MCS5  ", "MCS6 ", "MCS7 "),
 607	__GEN_TXPWR_ENT4("MCS_2SS       ", "MCS8  ", "MCS9  ", "MCS10", "MCS11"),
 608	__GEN_TXPWR_ENT2("MCS_2SS       ", "MCS12 ", "MCS13 \t"),
 609	__GEN_TXPWR_ENT4("HEDCM_2SS     ", "MCS0  ", "MCS1  ", "MCS3 ", "MCS4 "),
 610	__GEN_TXPWR_ENT4("DLRU_MCS_2SS  ", "MCS0  ", "MCS1  ", "MCS2 ", "MCS3 "),
 611	__GEN_TXPWR_ENT4("DLRU_MCS_2SS  ", "MCS4  ", "MCS5  ", "MCS6 ", "MCS7 "),
 612	__GEN_TXPWR_ENT4("DLRU_MCS_2SS  ", "MCS8  ", "MCS9  ", "MCS10", "MCS11"),
 613	__GEN_TXPWR_ENT2("DLRU_MCS_2SS  ", "MCS12 ", "MCS13 \t"),
 614	__GEN_TXPWR_ENT4("DLRU_HEDCM_2SS", "MCS0  ", "MCS1  ", "MCS3 ", "MCS4 "),
 615};
 616
 617static const struct txpwr_ent __txpwr_ent_byr_be[] = {
 618	__GEN_TXPWR_ENT0("BW20"),
 619	__GEN_TXPWR_ENT4("CCK       ", "1M    ", "2M    ", "5.5M ", "11M  "),
 620	__GEN_TXPWR_ENT4("LEGACY    ", "6M    ", "9M    ", "12M  ", "18M  "),
 621	__GEN_TXPWR_ENT4("LEGACY    ", "24M   ", "36M   ", "48M  ", "54M  "),
 622	__GEN_TXPWR_ENT2("EHT       ", "MCS14 ", "MCS15 \t"),
 623	__GEN_TXPWR_ENT2("DLRU_EHT  ", "MCS14 ", "MCS15 \t"),
 624	__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
 625
 626	__GEN_TXPWR_ENT0("BW40"),
 627	__GEN_TXPWR_ENT4("CCK       ", "1M    ", "2M    ", "5.5M ", "11M  "),
 628	__GEN_TXPWR_ENT4("LEGACY    ", "6M    ", "9M    ", "12M  ", "18M  "),
 629	__GEN_TXPWR_ENT4("LEGACY    ", "24M   ", "36M   ", "48M  ", "54M  "),
 630	__GEN_TXPWR_ENT2("EHT       ", "MCS14 ", "MCS15 \t"),
 631	__GEN_TXPWR_ENT2("DLRU_EHT  ", "MCS14 ", "MCS15 \t"),
 632	__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
 633
 634	/* there is no CCK section after BW80 */
 635	__GEN_TXPWR_ENT0("BW80"),
 636	__GEN_TXPWR_ENT4("LEGACY    ", "6M    ", "9M    ", "12M  ", "18M  "),
 637	__GEN_TXPWR_ENT4("LEGACY    ", "24M   ", "36M   ", "48M  ", "54M  "),
 638	__GEN_TXPWR_ENT2("EHT       ", "MCS14 ", "MCS15 \t"),
 639	__GEN_TXPWR_ENT2("DLRU_EHT  ", "MCS14 ", "MCS15 \t"),
 640	__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
 641
 642	__GEN_TXPWR_ENT0("BW160"),
 643	__GEN_TXPWR_ENT4("LEGACY    ", "6M    ", "9M    ", "12M  ", "18M  "),
 644	__GEN_TXPWR_ENT4("LEGACY    ", "24M   ", "36M   ", "48M  ", "54M  "),
 645	__GEN_TXPWR_ENT2("EHT       ", "MCS14 ", "MCS15 \t"),
 646	__GEN_TXPWR_ENT2("DLRU_EHT  ", "MCS14 ", "MCS15 \t"),
 647	__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
 648
 649	__GEN_TXPWR_ENT0("BW320"),
 650	__GEN_TXPWR_ENT4("LEGACY    ", "6M    ", "9M    ", "12M  ", "18M  "),
 651	__GEN_TXPWR_ENT4("LEGACY    ", "24M   ", "36M   ", "48M  ", "54M  "),
 652	__GEN_TXPWR_ENT2("EHT       ", "MCS14 ", "MCS15 \t"),
 653	__GEN_TXPWR_ENT2("DLRU_EHT  ", "MCS14 ", "MCS15 \t"),
 654	__GEN_TXPWR_ENT_NESTED(byr_mcs_be),
 655};
 656
 657static const struct txpwr_map __txpwr_map_byr_be = {
 658	.ent = __txpwr_ent_byr_be,
 659	.size = ARRAY_SIZE(__txpwr_ent_byr_be),
 660	.addr_from = R_BE_PWR_BY_RATE,
 661	.addr_to = R_BE_PWR_BY_RATE_MAX,
 662	.addr_to_1ss = 0, /* not support */
 663};
 664
 665static const struct txpwr_ent __txpwr_ent_lmt_mcs_be[] = {
 666	__GEN_TXPWR_ENT2("MCS_20M_0  ", "NON_BF", "BF"),
 667	__GEN_TXPWR_ENT2("MCS_20M_1  ", "NON_BF", "BF"),
 668	__GEN_TXPWR_ENT2("MCS_20M_2  ", "NON_BF", "BF"),
 669	__GEN_TXPWR_ENT2("MCS_20M_3  ", "NON_BF", "BF"),
 670	__GEN_TXPWR_ENT2("MCS_20M_4  ", "NON_BF", "BF"),
 671	__GEN_TXPWR_ENT2("MCS_20M_5  ", "NON_BF", "BF"),
 672	__GEN_TXPWR_ENT2("MCS_20M_6  ", "NON_BF", "BF"),
 673	__GEN_TXPWR_ENT2("MCS_20M_7  ", "NON_BF", "BF"),
 674	__GEN_TXPWR_ENT2("MCS_20M_8  ", "NON_BF", "BF"),
 675	__GEN_TXPWR_ENT2("MCS_20M_9  ", "NON_BF", "BF"),
 676	__GEN_TXPWR_ENT2("MCS_20M_10 ", "NON_BF", "BF"),
 677	__GEN_TXPWR_ENT2("MCS_20M_11 ", "NON_BF", "BF"),
 678	__GEN_TXPWR_ENT2("MCS_20M_12 ", "NON_BF", "BF"),
 679	__GEN_TXPWR_ENT2("MCS_20M_13 ", "NON_BF", "BF"),
 680	__GEN_TXPWR_ENT2("MCS_20M_14 ", "NON_BF", "BF"),
 681	__GEN_TXPWR_ENT2("MCS_20M_15 ", "NON_BF", "BF"),
 682	__GEN_TXPWR_ENT2("MCS_40M_0  ", "NON_BF", "BF"),
 683	__GEN_TXPWR_ENT2("MCS_40M_1  ", "NON_BF", "BF"),
 684	__GEN_TXPWR_ENT2("MCS_40M_2  ", "NON_BF", "BF"),
 685	__GEN_TXPWR_ENT2("MCS_40M_3  ", "NON_BF", "BF"),
 686	__GEN_TXPWR_ENT2("MCS_40M_4  ", "NON_BF", "BF"),
 687	__GEN_TXPWR_ENT2("MCS_40M_5  ", "NON_BF", "BF"),
 688	__GEN_TXPWR_ENT2("MCS_40M_6  ", "NON_BF", "BF"),
 689	__GEN_TXPWR_ENT2("MCS_40M_7  ", "NON_BF", "BF"),
 690	__GEN_TXPWR_ENT2("MCS_80M_0  ", "NON_BF", "BF"),
 691	__GEN_TXPWR_ENT2("MCS_80M_1  ", "NON_BF", "BF"),
 692	__GEN_TXPWR_ENT2("MCS_80M_2  ", "NON_BF", "BF"),
 693	__GEN_TXPWR_ENT2("MCS_80M_3  ", "NON_BF", "BF"),
 694	__GEN_TXPWR_ENT2("MCS_160M_0 ", "NON_BF", "BF"),
 695	__GEN_TXPWR_ENT2("MCS_160M_1 ", "NON_BF", "BF"),
 696	__GEN_TXPWR_ENT2("MCS_320M   ", "NON_BF", "BF"),
 697	__GEN_TXPWR_ENT2("MCS_40M_0p5", "NON_BF", "BF"),
 698	__GEN_TXPWR_ENT2("MCS_40M_2p5", "NON_BF", "BF"),
 699	__GEN_TXPWR_ENT2("MCS_40M_4p5", "NON_BF", "BF"),
 700	__GEN_TXPWR_ENT2("MCS_40M_6p5", "NON_BF", "BF"),
 701};
 702
 703static const struct txpwr_ent __txpwr_ent_lmt_be[] = {
 704	__GEN_TXPWR_ENT0("1TX"),
 705	__GEN_TXPWR_ENT2("CCK_20M    ", "NON_BF", "BF"),
 706	__GEN_TXPWR_ENT2("CCK_40M    ", "NON_BF", "BF"),
 707	__GEN_TXPWR_ENT2("OFDM       ", "NON_BF", "BF"),
 708	__GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
 709
 710	__GEN_TXPWR_ENT0("2TX"),
 711	__GEN_TXPWR_ENT2("CCK_20M    ", "NON_BF", "BF"),
 712	__GEN_TXPWR_ENT2("CCK_40M    ", "NON_BF", "BF"),
 713	__GEN_TXPWR_ENT2("OFDM       ", "NON_BF", "BF"),
 714	__GEN_TXPWR_ENT_NESTED(lmt_mcs_be),
 715};
 716
 717static const struct txpwr_map __txpwr_map_lmt_be = {
 718	.ent = __txpwr_ent_lmt_be,
 719	.size = ARRAY_SIZE(__txpwr_ent_lmt_be),
 720	.addr_from = R_BE_PWR_LMT,
 721	.addr_to = R_BE_PWR_LMT_MAX,
 722	.addr_to_1ss = 0, /* not support */
 723};
 724
 725static const struct txpwr_ent __txpwr_ent_lmt_ru_indexes_be[] = {
 726	__GEN_TXPWR_ENT8("RU26    ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
 727			 "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
 728	__GEN_TXPWR_ENT8("RU26    ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
 729			 "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
 730	__GEN_TXPWR_ENT8("RU52    ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
 731			 "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
 732	__GEN_TXPWR_ENT8("RU52    ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
 733			 "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
 734	__GEN_TXPWR_ENT8("RU106   ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
 735			 "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
 736	__GEN_TXPWR_ENT8("RU106   ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
 737			 "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
 738	__GEN_TXPWR_ENT8("RU52_26 ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
 739			 "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
 740	__GEN_TXPWR_ENT8("RU52_26 ", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
 741			 "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
 742	__GEN_TXPWR_ENT8("RU106_26", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 ",
 743			 "IDX_4 ", "IDX_5 ", "IDX_6 ", "IDX_7 "),
 744	__GEN_TXPWR_ENT8("RU106_26", "IDX_8 ", "IDX_9 ", "IDX_10", "IDX_11",
 745			 "IDX_12", "IDX_13", "IDX_14", "IDX_15"),
 746};
 747
 748static const struct txpwr_ent __txpwr_ent_lmt_ru_be[] = {
 749	__GEN_TXPWR_ENT0("1TX"),
 750	__GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
 751
 752	__GEN_TXPWR_ENT0("2TX"),
 753	__GEN_TXPWR_ENT_NESTED(lmt_ru_indexes_be),
 754};
 755
 756static const struct txpwr_map __txpwr_map_lmt_ru_be = {
 757	.ent = __txpwr_ent_lmt_ru_be,
 758	.size = ARRAY_SIZE(__txpwr_ent_lmt_ru_be),
 759	.addr_from = R_BE_PWR_RU_LMT,
 760	.addr_to = R_BE_PWR_RU_LMT_MAX,
 761	.addr_to_1ss = 0, /* not support */
 762};
 763
 764static unsigned int
 765__print_txpwr_ent(char *buf, size_t bufsz, const struct txpwr_ent *ent,
 766		  const s8 *bufp, const unsigned int cur, unsigned int *ate)
 767{
 768	char *p = buf, *end = buf + bufsz;
 769	unsigned int cnt, i;
 770	unsigned int eaten;
 771	char *fmt;
 772
 773	if (ent->nested) {
 774		for (cnt = 0, i = 0; i < ent->len; i++, cnt += eaten)
 775			p += __print_txpwr_ent(p, end - p, ent->ptr + i, bufp,
 776					       cur + cnt, &eaten);
 777		*ate = cnt;
 778		goto out;
 779	}
 780
 781	switch (ent->len) {
 782	case 0:
 783		p += scnprintf(p, end - p, "\t<< %s >>\n", ent->txt);
 784		*ate = 0;
 785		goto out;
 786	case 2:
 787		fmt = "%s\t| %3d, %3d,\t\tdBm\n";
 788		p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
 789			       bufp[cur + 1]);
 790		*ate = 2;
 791		goto out;
 792	case 4:
 793		fmt = "%s\t| %3d, %3d, %3d, %3d,\tdBm\n";
 794		p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
 795			       bufp[cur + 1],
 796			       bufp[cur + 2], bufp[cur + 3]);
 797		*ate = 4;
 798		goto out;
 799	case 8:
 800		fmt = "%s\t| %3d, %3d, %3d, %3d, %3d, %3d, %3d, %3d,\tdBm\n";
 801		p += scnprintf(p, end - p, fmt, ent->txt, bufp[cur],
 802			       bufp[cur + 1],
 803			       bufp[cur + 2], bufp[cur + 3], bufp[cur + 4],
 804			       bufp[cur + 5], bufp[cur + 6], bufp[cur + 7]);
 805		*ate = 8;
 806		goto out;
 807	default:
 808		return 0;
 809	}
 810
 811out:
 812	return p - buf;
 813}
 814
 815static ssize_t __print_txpwr_map(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
 816				 const struct txpwr_map *map)
 817{
 818	u8 fct = rtwdev->chip->txpwr_factor_mac;
 819	u8 path_num = rtwdev->chip->rf_path_num;
 820	char *p = buf, *end = buf + bufsz;
 821	unsigned int cur, i;
 822	unsigned int eaten;
 823	u32 max_valid_addr;
 824	u32 val, addr;
 825	s8 *bufp, tmp;
 826	int ret;
 827
 828	if (path_num == 1)
 829		max_valid_addr = map->addr_to_1ss;
 830	else
 831		max_valid_addr = map->addr_to;
 832
 833	if (max_valid_addr == 0)
 834		return -EOPNOTSUPP;
 835
 836	bufp = vzalloc(map->addr_to - map->addr_from + 4);
 837	if (!bufp)
 838		return -ENOMEM;
 839
 840	for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
 841		ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
 842		if (ret)
 843			val = MASKDWORD;
 844
 845		cur = addr - map->addr_from;
 846		for (i = 0; i < 4; i++, val >>= 8) {
 847			/* signed 7 bits, and reserved BIT(7) */
 848			tmp = sign_extend32(val, 6);
 849			bufp[cur + i] = tmp >> fct;
 850		}
 851	}
 852
 853	for (cur = 0, i = 0; i < map->size; i++, cur += eaten)
 854		p += __print_txpwr_ent(p, end - p, &map->ent[i], bufp, cur, &eaten);
 855
 856	vfree(bufp);
 857	return p - buf;
 858}
 859
 860static int __print_regd(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
 861			const struct rtw89_chan *chan)
 862{
 863	const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 864	char *p = buf, *end = buf + bufsz;
 865	u8 band = chan->band_type;
 866	u8 regd = rtw89_regd_get(rtwdev, band);
 867
 868	p += scnprintf(p, end - p, "%s\n", rtw89_regd_get_string(regd));
 869	p += scnprintf(p, end - p, "\t(txpwr UK follow ETSI: %s)\n",
 870		       str_yes_no(regulatory->txpwr_uk_follow_etsi));
 871
 872	return p - buf;
 873}
 874
 875struct dbgfs_txpwr_table {
 876	const struct txpwr_map *byr;
 877	const struct txpwr_map *lmt;
 878	const struct txpwr_map *lmt_ru;
 879};
 880
 881static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
 882	.byr = &__txpwr_map_byr_ax,
 883	.lmt = &__txpwr_map_lmt_ax,
 884	.lmt_ru = &__txpwr_map_lmt_ru_ax,
 885};
 886
 887static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
 888	.byr = &__txpwr_map_byr_be,
 889	.lmt = &__txpwr_map_lmt_be,
 890	.lmt_ru = &__txpwr_map_lmt_ru_be,
 891};
 892
 893static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
 894	[RTW89_CHIP_AX] = &dbgfs_txpwr_table_ax,
 895	[RTW89_CHIP_BE] = &dbgfs_txpwr_table_be,
 896};
 897
 898static
 899int rtw89_debug_priv_txpwr_table_get_regd(struct rtw89_dev *rtwdev,
 900					  char *buf, size_t bufsz,
 901					  const struct rtw89_chan *chan)
 902{
 903	const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 904	const struct rtw89_reg_6ghz_tpe *tpe6 = &regulatory->reg_6ghz_tpe;
 905	char *p = buf, *end = buf + bufsz;
 906
 907	p += scnprintf(p, end - p, "[Chanctx] band %u, ch %u, bw %u\n",
 908		       chan->band_type, chan->channel, chan->band_width);
 909
 910	p += scnprintf(p, end - p, "[Regulatory] ");
 911	p += __print_regd(rtwdev, p, end - p, chan);
 912
 913	if (chan->band_type == RTW89_BAND_6G) {
 914		p += scnprintf(p, end - p, "[reg6_pwr_type] %u\n",
 915			       regulatory->reg_6ghz_power);
 916
 917		if (tpe6->valid)
 918			p += scnprintf(p, end - p, "[TPE] %d dBm\n",
 919				       tpe6->constraint);
 920	}
 921
 922	return p - buf;
 923}
 924
 925static
 926ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
 927					 struct rtw89_debugfs_priv *debugfs_priv,
 928					 char *buf, size_t bufsz)
 929{
 930	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
 931	struct rtw89_sar_parm sar_parm = {};
 932	const struct dbgfs_txpwr_table *tbl;
 933	const struct rtw89_chan *chan;
 934	char *p = buf, *end = buf + bufsz;
 935	ssize_t n;
 936
 937	lockdep_assert_wiphy(rtwdev->hw->wiphy);
 938
 939	rtw89_leave_ps_mode(rtwdev);
 940	chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
 941	sar_parm.center_freq = chan->freq;
 942
 943	p += rtw89_debug_priv_txpwr_table_get_regd(rtwdev, p, end - p, chan);
 944
 945	p += scnprintf(p, end - p, "[SAR]\n");
 946	p += rtw89_print_sar(rtwdev, p, end - p, &sar_parm);
 947
 948	p += scnprintf(p, end - p, "[TAS]\n");
 949	p += rtw89_print_tas(rtwdev, p, end - p);
 950
 951	p += scnprintf(p, end - p, "[DAG]\n");
 952	p += rtw89_print_ant_gain(rtwdev, p, end - p, chan);
 953
 954	tbl = dbgfs_txpwr_tables[chip_gen];
 955	if (!tbl)
 956		return -EOPNOTSUPP;
 957
 958	p += scnprintf(p, end - p, "\n[TX power byrate]\n");
 959	n = __print_txpwr_map(rtwdev, p, end - p, tbl->byr);
 960	if (n < 0)
 961		return n;
 962	p += n;
 963
 964	p += scnprintf(p, end - p, "\n[TX power limit]\n");
 965	n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt);
 966	if (n < 0)
 967		return n;
 968	p += n;
 969
 970	p += scnprintf(p, end - p, "\n[TX power limit_ru]\n");
 971	n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru);
 972	if (n < 0)
 973		return n;
 974	p += n;
 975
 976	return p - buf;
 977}
 978
 979static ssize_t
 980rtw89_debug_priv_mac_reg_dump_select(struct rtw89_dev *rtwdev,
 981				     struct rtw89_debugfs_priv *debugfs_priv,
 982				     const char *buf, size_t count)
 983{
 984	const struct rtw89_chip_info *chip = rtwdev->chip;
 985	int sel;
 986	int ret;
 987
 988	ret = kstrtoint(buf, 0, &sel);
 989	if (ret)
 990		return ret;
 991
 992	if (sel < RTW89_DBG_SEL_MAC_00 || sel > RTW89_DBG_SEL_RFC) {
 993		rtw89_info(rtwdev, "invalid args: %d\n", sel);
 994		return -EINVAL;
 995	}
 996
 997	if (sel == RTW89_DBG_SEL_MAC_30 && chip->chip_id != RTL8852C) {
 998		rtw89_info(rtwdev, "sel %d is address hole on chip %d\n", sel,
 999			   chip->chip_id);
1000		return -EINVAL;
1001	}
1002
1003	debugfs_priv->cb_data = sel;
1004	rtw89_info(rtwdev, "select mac page dump %d\n", debugfs_priv->cb_data);
1005
1006	return count;
1007}
1008
1009#define RTW89_MAC_PAGE_SIZE		0x100
1010
1011static
1012ssize_t rtw89_debug_priv_mac_reg_dump_get(struct rtw89_dev *rtwdev,
1013					  struct rtw89_debugfs_priv *debugfs_priv,
1014					  char *buf, size_t bufsz)
1015{
1016	enum rtw89_debug_mac_reg_sel reg_sel = debugfs_priv->cb_data;
1017	char *p = buf, *end = buf + bufsz;
1018	u32 start, end_addr;
1019	u32 i, j, k, page;
1020	u32 val;
1021
1022	switch (reg_sel) {
1023	case RTW89_DBG_SEL_MAC_00:
1024		p += scnprintf(p, end - p, "Debug selected MAC page 0x00\n");
1025		start = 0x000;
1026		end_addr = 0x014;
1027		break;
1028	case RTW89_DBG_SEL_MAC_30:
1029		p += scnprintf(p, end - p, "Debug selected MAC page 0x30\n");
1030		start = 0x030;
1031		end_addr = 0x033;
1032		break;
1033	case RTW89_DBG_SEL_MAC_40:
1034		p += scnprintf(p, end - p, "Debug selected MAC page 0x40\n");
1035		start = 0x040;
1036		end_addr = 0x07f;
1037		break;
1038	case RTW89_DBG_SEL_MAC_80:
1039		p += scnprintf(p, end - p, "Debug selected MAC page 0x80\n");
1040		start = 0x080;
1041		end_addr = 0x09f;
1042		break;
1043	case RTW89_DBG_SEL_MAC_C0:
1044		p += scnprintf(p, end - p, "Debug selected MAC page 0xc0\n");
1045		start = 0x0c0;
1046		end_addr = 0x0df;
1047		break;
1048	case RTW89_DBG_SEL_MAC_E0:
1049		p += scnprintf(p, end - p, "Debug selected MAC page 0xe0\n");
1050		start = 0x0e0;
1051		end_addr = 0x0ff;
1052		break;
1053	case RTW89_DBG_SEL_BB:
1054		p += scnprintf(p, end - p, "Debug selected BB register\n");
1055		start = 0x100;
1056		end_addr = 0x17f;
1057		break;
1058	case RTW89_DBG_SEL_IQK:
1059		p += scnprintf(p, end - p, "Debug selected IQK register\n");
1060		start = 0x180;
1061		end_addr = 0x1bf;
1062		break;
1063	case RTW89_DBG_SEL_RFC:
1064		p += scnprintf(p, end - p, "Debug selected RFC register\n");
1065		start = 0x1c0;
1066		end_addr = 0x1ff;
1067		break;
1068	default:
1069		p += scnprintf(p, end - p, "Selected invalid register page\n");
1070		return -EINVAL;
1071	}
1072
1073	for (i = start; i <= end_addr; i++) {
1074		page = i << 8;
1075		for (j = page; j < page + RTW89_MAC_PAGE_SIZE; j += 16) {
1076			p += scnprintf(p, end - p, "%08xh : ", 0x18600000 + j);
1077			for (k = 0; k < 4; k++) {
1078				val = rtw89_read32(rtwdev, j + (k << 2));
1079				p += scnprintf(p, end - p, "%08x ", val);
1080			}
1081			p += scnprintf(p, end - p, "\n");
1082		}
1083	}
1084
1085	return p - buf;
1086}
1087
1088static ssize_t
1089rtw89_debug_priv_mac_mem_dump_select(struct rtw89_dev *rtwdev,
1090				     struct rtw89_debugfs_priv *debugfs_priv,
1091				     const char *buf, size_t count)
1092{
1093	u32 sel, start_addr, len;
1094	int num;
1095
1096	num = sscanf(buf, "%x %x %x", &sel, &start_addr, &len);
1097	if (num != 3) {
1098		rtw89_info(rtwdev, "invalid format: <sel> <start> <len>\n");
1099		return -EINVAL;
1100	}
1101
1102	debugfs_priv->mac_mem.sel = sel;
1103	debugfs_priv->mac_mem.start = start_addr;
1104	debugfs_priv->mac_mem.len = len;
1105
1106	rtw89_info(rtwdev, "select mem %d start %d len %d\n",
1107		   sel, start_addr, len);
1108
1109	return count;
1110}
1111
1112static int rtw89_debug_dump_mac_mem(struct rtw89_dev *rtwdev,
1113				    char *buf, size_t bufsz,
1114				    u8 sel, u32 start_addr, u32 len)
1115{
1116	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1117	u32 filter_model_addr = mac->filter_model_addr;
1118	u32 indir_access_addr = mac->indir_access_addr;
1119	u32 mem_page_size = mac->mem_page_size;
1120	u32 base_addr, start_page, residue;
1121	char *p = buf, *end = buf + bufsz;
1122	u32 i, j, pp, pages;
1123	u32 dump_len, remain;
1124	u32 val;
1125
1126	remain = len;
1127	pages = len / mem_page_size + 1;
1128	start_page = start_addr / mem_page_size;
1129	residue = start_addr % mem_page_size;
1130	base_addr = mac->mem_base_addrs[sel];
1131	base_addr += start_page * mem_page_size;
1132
1133	for (pp = 0; pp < pages; pp++) {
1134		dump_len = min_t(u32, remain, mem_page_size);
1135		rtw89_write32(rtwdev, filter_model_addr, base_addr);
1136		for (i = indir_access_addr + residue;
1137		     i < indir_access_addr + dump_len;) {
1138			p += scnprintf(p, end - p, "%08xh:", i);
1139			for (j = 0;
1140			     j < 4 && i < indir_access_addr + dump_len;
1141			     j++, i += 4) {
1142				val = rtw89_read32(rtwdev, i);
1143				p += scnprintf(p, end - p, "  %08x", val);
1144				remain -= 4;
1145			}
1146			p += scnprintf(p, end - p, "\n");
1147		}
1148		base_addr += mem_page_size;
1149	}
1150
1151	return p - buf;
1152}
1153
1154static ssize_t
1155rtw89_debug_priv_mac_mem_dump_get(struct rtw89_dev *rtwdev,
1156				  struct rtw89_debugfs_priv *debugfs_priv,
1157				  char *buf, size_t bufsz)
1158{
1159	char *p = buf, *end = buf + bufsz;
1160	bool grant_read = false;
1161
1162	lockdep_assert_wiphy(rtwdev->hw->wiphy);
1163
1164	if (debugfs_priv->mac_mem.sel >= RTW89_MAC_MEM_NUM)
1165		return -ENOENT;
1166
1167	if (rtwdev->chip->chip_id == RTL8852C) {
1168		switch (debugfs_priv->mac_mem.sel) {
1169		case RTW89_MAC_MEM_TXD_FIFO_0_V1:
1170		case RTW89_MAC_MEM_TXD_FIFO_1_V1:
1171		case RTW89_MAC_MEM_TXDATA_FIFO_0:
1172		case RTW89_MAC_MEM_TXDATA_FIFO_1:
1173			grant_read = true;
1174			break;
1175		default:
1176			break;
1177		}
1178	}
1179
1180	rtw89_leave_ps_mode(rtwdev);
1181	if (grant_read)
1182		rtw89_write32_set(rtwdev, R_AX_TCR1, B_AX_TCR_FORCE_READ_TXDFIFO);
1183	p += rtw89_debug_dump_mac_mem(rtwdev, p, end - p,
1184				      debugfs_priv->mac_mem.sel,
1185				      debugfs_priv->mac_mem.start,
1186				      debugfs_priv->mac_mem.len);
1187	if (grant_read)
1188		rtw89_write32_clr(rtwdev, R_AX_TCR1, B_AX_TCR_FORCE_READ_TXDFIFO);
1189
1190	return p - buf;
1191}
1192
1193static ssize_t
1194rtw89_debug_priv_mac_dbg_port_dump_select(struct rtw89_dev *rtwdev,
1195					  struct rtw89_debugfs_priv *debugfs_priv,
1196					  const char *buf, size_t count)
1197{
1198	int sel, set;
1199	int num;
1200	bool enable;
1201
1202	num = sscanf(buf, "%d %d", &sel, &set);
1203	if (num != 2) {
1204		rtw89_info(rtwdev, "invalid format: <sel> <set>\n");
1205		return -EINVAL;
1206	}
1207
1208	enable = set != 0;
1209	switch (sel) {
1210	case 0:
1211		debugfs_priv->dbgpkg_en.ss_dbg = enable;
1212		break;
1213	case 1:
1214		debugfs_priv->dbgpkg_en.dle_dbg = enable;
1215		break;
1216	case 2:
1217		debugfs_priv->dbgpkg_en.dmac_dbg = enable;
1218		break;
1219	case 3:
1220		debugfs_priv->dbgpkg_en.cmac_dbg = enable;
1221		break;
1222	case 4:
1223		debugfs_priv->dbgpkg_en.dbg_port = enable;
1224		break;
1225	default:
1226		rtw89_info(rtwdev, "invalid args: sel %d set %d\n", sel, set);
1227		return -EINVAL;
1228	}
1229
1230	rtw89_info(rtwdev, "%s debug port dump %d\n",
1231		   enable ? "Enable" : "Disable", sel);
1232
1233	return count;
1234}
1235
1236static int rtw89_debug_mac_dump_ss_dbg(struct rtw89_dev *rtwdev,
1237				       char *buf, size_t bufsz)
1238{
1239	return 0;
1240}
1241
1242static int rtw89_debug_mac_dump_dle_dbg(struct rtw89_dev *rtwdev,
1243				       char *buf, size_t bufsz)
1244{
1245#define DLE_DFI_DUMP(__type, __target, __sel)				\
1246({									\
1247	u32 __ctrl;							\
1248	u32 __reg_ctrl = R_AX_##__type##_DBG_FUN_INTF_CTL;		\
1249	u32 __reg_data = R_AX_##__type##_DBG_FUN_INTF_DATA;		\
1250	u32 __data, __val32;						\
1251	int __ret;							\
1252									\
1253	__ctrl = FIELD_PREP(B_AX_##__type##_DFI_TRGSEL_MASK,		\
1254			    DLE_DFI_TYPE_##__target) |			\
1255		 FIELD_PREP(B_AX_##__type##_DFI_ADDR_MASK, __sel) |	\
1256		 B_AX_WDE_DFI_ACTIVE;					\
1257	rtw89_write32(rtwdev, __reg_ctrl, __ctrl);			\
1258	__ret = read_poll_timeout(rtw89_read32, __val32,		\
1259			!(__val32 & B_AX_##__type##_DFI_ACTIVE),	\
1260			1000, 50000, false,				\
1261			rtwdev, __reg_ctrl);				\
1262	if (__ret) {							\
1263		rtw89_err(rtwdev, "failed to dump DLE %s %s %d\n",	\
1264			  #__type, #__target, __sel);			\
1265		return __ret;						\
1266	}								\
1267									\
1268	__data = rtw89_read32(rtwdev, __reg_data);			\
1269	__data;								\
1270})
1271
1272#define DLE_DFI_FREE_PAGE_DUMP(__p, __end, __type)			\
1273({									\
1274	u32 __freepg, __pubpg;						\
1275	u32 __freepg_head, __freepg_tail, __pubpg_num;			\
1276									\
1277	__freepg = DLE_DFI_DUMP(__type, FREEPG, 0);			\
1278	__pubpg = DLE_DFI_DUMP(__type, FREEPG, 1);			\
1279	__freepg_head = FIELD_GET(B_AX_DLE_FREE_HEADPG, __freepg);	\
1280	__freepg_tail = FIELD_GET(B_AX_DLE_FREE_TAILPG, __freepg);	\
1281	__pubpg_num = FIELD_GET(B_AX_DLE_PUB_PGNUM, __pubpg);		\
1282	__p += scnprintf(__p, __end - __p, "[%s] freepg head: %d\n",	\
1283			 #__type, __freepg_head);			\
1284	__p += scnprintf(__p, __end - __p, "[%s] freepg tail: %d\n",	\
1285			 #__type, __freepg_tail);			\
1286	__p += scnprintf(__p, __end - __p, "[%s] pubpg num  : %d\n",	\
1287			 #__type, __pubpg_num);				\
1288})
1289
1290#define case_QUOTA(__p, __end, __type, __id)				\
1291	case __type##_QTAID_##__id:					\
1292		val32 = DLE_DFI_DUMP(__type, QUOTA, __type##_QTAID_##__id); \
1293		rsv_pgnum = FIELD_GET(B_AX_DLE_RSV_PGNUM, val32);	\
1294		use_pgnum = FIELD_GET(B_AX_DLE_USE_PGNUM, val32);	\
1295		__p += scnprintf(__p, __end - __p, "[%s][%s] rsv_pgnum: %d\n", \
1296				 #__type, #__id, rsv_pgnum);		\
1297		__p += scnprintf(__p, __end - __p, "[%s][%s] use_pgnum: %d\n", \
1298				 #__type, #__id, use_pgnum);		\
1299		break
1300	char *p = buf, *end = buf + bufsz;
1301	u32 quota_id;
1302	u32 val32;
1303	u16 rsv_pgnum, use_pgnum;
1304	int ret;
1305
1306	ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
1307	if (ret) {
1308		p += scnprintf(p, end - p, "[DLE]  : DMAC not enabled\n");
1309		goto out;
1310	}
1311
1312	DLE_DFI_FREE_PAGE_DUMP(p, end, WDE);
1313	DLE_DFI_FREE_PAGE_DUMP(p, end, PLE);
1314	for (quota_id = 0; quota_id <= WDE_QTAID_CPUIO; quota_id++) {
1315		switch (quota_id) {
1316		case_QUOTA(p, end, WDE, HOST_IF);
1317		case_QUOTA(p, end, WDE, WLAN_CPU);
1318		case_QUOTA(p, end, WDE, DATA_CPU);
1319		case_QUOTA(p, end, WDE, PKTIN);
1320		case_QUOTA(p, end, WDE, CPUIO);
1321		}
1322	}
1323	for (quota_id = 0; quota_id <= PLE_QTAID_CPUIO; quota_id++) {
1324		switch (quota_id) {
1325		case_QUOTA(p, end, PLE, B0_TXPL);
1326		case_QUOTA(p, end, PLE, B1_TXPL);
1327		case_QUOTA(p, end, PLE, C2H);
1328		case_QUOTA(p, end, PLE, H2C);
1329		case_QUOTA(p, end, PLE, WLAN_CPU);
1330		case_QUOTA(p, end, PLE, MPDU);
1331		case_QUOTA(p, end, PLE, CMAC0_RX);
1332		case_QUOTA(p, end, PLE, CMAC1_RX);
1333		case_QUOTA(p, end, PLE, CMAC1_BBRPT);
1334		case_QUOTA(p, end, PLE, WDRLS);
1335		case_QUOTA(p, end, PLE, CPUIO);
1336		}
1337	}
1338
1339out:
1340	return p - buf;
1341
1342#undef case_QUOTA
1343#undef DLE_DFI_DUMP
1344#undef DLE_DFI_FREE_PAGE_DUMP
1345}
1346
1347static int rtw89_debug_mac_dump_dmac_dbg(struct rtw89_dev *rtwdev,
1348					 char *buf, size_t bufsz)
1349{
1350	const struct rtw89_chip_info *chip = rtwdev->chip;
1351	char *p = buf, *end = buf + bufsz;
1352	u32 dmac_err;
1353	int i, ret;
1354
1355	ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
1356	if (ret) {
1357		p += scnprintf(p, end - p, "[DMAC] : DMAC not enabled\n");
1358		goto out;
1359	}
1360
1361	dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
1362	p += scnprintf(p, end - p, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err);
1363	p += scnprintf(p, end - p, "R_AX_DMAC_ERR_IMR=0x%08x\n",
1364		       rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR));
1365
1366	if (dmac_err) {
1367		p += scnprintf(p, end - p, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n",
1368			       rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1));
1369		p += scnprintf(p, end - p, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n",
1370			       rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1));
1371		if (chip->chip_id == RTL8852C) {
1372			p += scnprintf(p, end - p,
1373				       "R_AX_PLE_ERRFLAG_MSG=0x%08x\n",
1374				       rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG));
1375			p += scnprintf(p, end - p,
1376				       "R_AX_WDE_ERRFLAG_MSG=0x%08x\n",
1377				       rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG));
1378			p += scnprintf(p, end - p,
1379				       "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n",
1380				       rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN));
1381			p += scnprintf(p, end - p,
1382				       "R_AX_PLE_DBGERR_STS=0x%08x\n",
1383				       rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS));
1384		}
1385	}
1386
1387	if (dmac_err & B_AX_WDRLS_ERR_FLAG) {
1388		p += scnprintf(p, end - p, "R_AX_WDRLS_ERR_IMR=0x%08x\n",
1389			       rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR));
1390		p += scnprintf(p, end - p, "R_AX_WDRLS_ERR_ISR=0x%08x\n",
1391			       rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR));
1392		if (chip->chip_id == RTL8852C)
1393			p += scnprintf(p, end - p,
1394				       "R_AX_RPQ_RXBD_IDX=0x%08x\n",
1395				       rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1));
1396		else
1397			p += scnprintf(p, end - p,
1398				       "R_AX_RPQ_RXBD_IDX=0x%08x\n",
1399				       rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX));
1400	}
1401
1402	if (dmac_err & B_AX_WSEC_ERR_FLAG) {
1403		if (chip->chip_id == RTL8852C) {
1404			p += scnprintf(p, end - p,
1405				       "R_AX_SEC_ERR_IMR=0x%08x\n",
1406				       rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR));
1407			p += scnprintf(p, end - p,
1408				       "R_AX_SEC_ERR_ISR=0x%08x\n",
1409				       rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG));
1410			p += scnprintf(p, end - p,
1411				       "R_AX_SEC_ENG_CTRL=0x%08x\n",
1412				       rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
1413			p += scnprintf(p, end - p,
1414				       "R_AX_SEC_MPDU_PROC=0x%08x\n",
1415				       rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
1416			p += scnprintf(p, end - p,
1417				       "R_AX_SEC_CAM_ACCESS=0x%08x\n",
1418				       rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
1419			p += scnprintf(p, end - p,
1420				       "R_AX_SEC_CAM_RDATA=0x%08x\n",
1421				       rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
1422			p += scnprintf(p, end - p, "R_AX_SEC_DEBUG1=0x%08x\n",
1423				       rtw89_read32(rtwdev, R_AX_SEC_DEBUG1));
1424			p += scnprintf(p, end - p,
1425				       "R_AX_SEC_TX_DEBUG=0x%08x\n",
1426				       rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
1427			p += scnprintf(p, end - p,
1428				       "R_AX_SEC_RX_DEBUG=0x%08x\n",
1429				       rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
1430
1431			rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
1432					   B_AX_DBG_SEL0, 0x8B);
1433			rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
1434					   B_AX_DBG_SEL1, 0x8B);
1435			rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1,
1436					   B_AX_SEL_0XC0_MASK, 1);
1437			for (i = 0; i < 0x10; i++) {
1438				rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
1439						   B_AX_SEC_DBG_PORT_FIELD_MASK, i);
1440				p += scnprintf(p, end - p,
1441					       "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n",
1442					       i,
1443					       rtw89_read32(rtwdev, R_AX_SEC_DEBUG2));
1444			}
1445		} else {
1446			p += scnprintf(p, end - p,
1447				       "R_AX_SEC_ERR_IMR_ISR=0x%08x\n",
1448				       rtw89_read32(rtwdev, R_AX_SEC_DEBUG));
1449			p += scnprintf(p, end - p,
1450				       "R_AX_SEC_ENG_CTRL=0x%08x\n",
1451				       rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
1452			p += scnprintf(p, end - p,
1453				       "R_AX_SEC_MPDU_PROC=0x%08x\n",
1454				       rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
1455			p += scnprintf(p, end - p,
1456				       "R_AX_SEC_CAM_ACCESS=0x%08x\n",
1457				       rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
1458			p += scnprintf(p, end - p,
1459				       "R_AX_SEC_CAM_RDATA=0x%08x\n",
1460				       rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
1461			p += scnprintf(p, end - p,
1462				       "R_AX_SEC_CAM_WDATA=0x%08x\n",
1463				       rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA));
1464			p += scnprintf(p, end - p,
1465				       "R_AX_SEC_TX_DEBUG=0x%08x\n",
1466				       rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
1467			p += scnprintf(p, end - p,
1468				       "R_AX_SEC_RX_DEBUG=0x%08x\n",
1469				       rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
1470			p += scnprintf(p, end - p,
1471				       "R_AX_SEC_TRX_PKT_CNT=0x%08x\n",
1472				       rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT));
1473			p += scnprintf(p, end - p,
1474				       "R_AX_SEC_TRX_BLK_CNT=0x%08x\n",
1475				       rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT));
1476		}
1477	}
1478
1479	if (dmac_err & B_AX_MPDU_ERR_FLAG) {
1480		p += scnprintf(p, end - p, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n",
1481			       rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR));
1482		p += scnprintf(p, end - p, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n",
1483			       rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR));
1484		p += scnprintf(p, end - p, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n",
1485			       rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR));
1486		p += scnprintf(p, end - p, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n",
1487			       rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR));
1488	}
1489
1490	if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) {
1491		p += scnprintf(p, end - p,
1492			       "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n",
1493			       rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR));
1494		p += scnprintf(p, end - p,
1495			       "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n",
1496			       rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR));
1497	}
1498
1499	if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) {
1500		p += scnprintf(p, end - p, "R_AX_WDE_ERR_IMR=0x%08x\n",
1501			       rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
1502		p += scnprintf(p, end - p, "R_AX_WDE_ERR_ISR=0x%08x\n",
1503			       rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
1504		p += scnprintf(p, end - p, "R_AX_PLE_ERR_IMR=0x%08x\n",
1505			       rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
1506		p += scnprintf(p, end - p, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
1507			       rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
1508	}
1509
1510	if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) {
1511		if (chip->chip_id == RTL8852C) {
1512			p += scnprintf(p, end - p,
1513				       "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n",
1514				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR));
1515			p += scnprintf(p, end - p,
1516				       "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n",
1517				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR));
1518			p += scnprintf(p, end - p,
1519				       "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n",
1520				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR));
1521			p += scnprintf(p, end - p,
1522				       "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n",
1523				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR));
1524		} else {
1525			p += scnprintf(p, end - p,
1526				       "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n",
1527				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR));
1528			p += scnprintf(p, end - p,
1529				       "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n",
1530				       rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1));
1531		}
1532	}
1533
1534	if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) {
1535		p += scnprintf(p, end - p, "R_AX_WDE_ERR_IMR=0x%08x\n",
1536			       rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
1537		p += scnprintf(p, end - p, "R_AX_WDE_ERR_ISR=0x%08x\n",
1538			       rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
1539		p += scnprintf(p, end - p, "R_AX_PLE_ERR_IMR=0x%08x\n",
1540			       rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
1541		p += scnprintf(p, end - p, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
1542			       rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
1543		p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_0=0x%08x\n",
1544			       rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0));
1545		p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_1=0x%08x\n",
1546			       rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1));
1547		p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_2=0x%08x\n",
1548			       rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2));
1549		p += scnprintf(p, end - p, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n",
1550			       rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS));
1551		p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_0=0x%08x\n",
1552			       rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0));
1553		p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_1=0x%08x\n",
1554			       rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1));
1555		p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_2=0x%08x\n",
1556			       rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2));
1557		p += scnprintf(p, end - p, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n",
1558			       rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS));
1559		if (chip->chip_id == RTL8852C) {
1560			p += scnprintf(p, end - p, "R_AX_RX_CTRL0=0x%08x\n",
1561				       rtw89_read32(rtwdev, R_AX_RX_CTRL0));
1562			p += scnprintf(p, end - p, "R_AX_RX_CTRL1=0x%08x\n",
1563				       rtw89_read32(rtwdev, R_AX_RX_CTRL1));
1564			p += scnprintf(p, end - p, "R_AX_RX_CTRL2=0x%08x\n",
1565				       rtw89_read32(rtwdev, R_AX_RX_CTRL2));
1566		} else {
1567			p += scnprintf(p, end - p,
1568				       "R_AX_RXDMA_PKT_INFO_0=0x%08x\n",
1569				       rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0));
1570			p += scnprintf(p, end - p,
1571				       "R_AX_RXDMA_PKT_INFO_1=0x%08x\n",
1572				       rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1));
1573			p += scnprintf(p, end - p,
1574				       "R_AX_RXDMA_PKT_INFO_2=0x%08x\n",
1575				       rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2));
1576		}
1577	}
1578
1579	if (dmac_err & B_AX_PKTIN_ERR_FLAG) {
1580		p += scnprintf(p, end - p, "R_AX_PKTIN_ERR_IMR=0x%08x\n",
1581			       rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR));
1582		p += scnprintf(p, end - p, "R_AX_PKTIN_ERR_ISR=0x%08x\n",
1583			       rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR));
1584	}
1585
1586	if (dmac_err & B_AX_DISPATCH_ERR_FLAG) {
1587		p += scnprintf(p, end - p,
1588			       "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n",
1589			       rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
1590		p += scnprintf(p, end - p,
1591			       "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n",
1592			       rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
1593		p += scnprintf(p, end - p,
1594			       "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n",
1595			       rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
1596		p += scnprintf(p, end - p,
1597			       "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n",
1598			       rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
1599		p += scnprintf(p, end - p,
1600			       "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n",
1601			       rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
1602		p += scnprintf(p, end - p,
1603			       "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n",
1604			       rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
1605	}
1606
1607	if (dmac_err & B_AX_BBRPT_ERR_FLAG) {
1608		if (chip->chip_id == RTL8852C) {
1609			p += scnprintf(p, end - p,
1610				       "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n",
1611				       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR));
1612			p += scnprintf(p, end - p,
1613				       "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n",
1614				       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR));
1615			p += scnprintf(p, end - p,
1616				       "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
1617				       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
1618			p += scnprintf(p, end - p,
1619				       "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
1620				       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
1621			p += scnprintf(p, end - p,
1622				       "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
1623				       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
1624			p += scnprintf(p, end - p,
1625				       "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
1626				       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
1627		} else {
1628			p += scnprintf(p, end - p,
1629				       "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n",
1630				       rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR));
1631			p += scnprintf(p, end - p,
1632				       "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
1633				       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
1634			p += scnprintf(p, end - p,
1635				       "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
1636				       rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
1637			p += scnprintf(p, end - p,
1638				       "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
1639				       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
1640			p += scnprintf(p, end - p,
1641				       "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
1642				       rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
1643		}
1644	}
1645
1646	if (dmac_err & B_AX_HAXIDMA_ERR_FLAG && chip->chip_id == RTL8852C) {
1647		p += scnprintf(p, end - p, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n",
1648			       rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK));
1649		p += scnprintf(p, end - p, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n",
1650			       rtw89_read32(rtwdev, R_AX_HAXI_IDCT));
1651	}
1652
1653out:
1654	return p - buf;
1655}
1656
1657static int rtw89_debug_mac_dump_cmac_err(struct rtw89_dev *rtwdev,
1658					 char *buf, size_t bufsz,
1659					 enum rtw89_mac_idx band)
1660{
1661	const struct rtw89_chip_info *chip = rtwdev->chip;
1662	char *p = buf, *end = buf + bufsz;
1663	u32 offset = 0;
1664	u32 cmac_err;
1665	int ret;
1666
1667	ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL);
1668	if (ret) {
1669		if (band)
1670			p += scnprintf(p, end - p,
1671				       "[CMAC] : CMAC1 not enabled\n");
1672		else
1673			p += scnprintf(p, end - p,
1674				       "[CMAC] : CMAC0 not enabled\n");
1675		goto out;
1676	}
1677
1678	if (band)
1679		offset = RTW89_MAC_AX_BAND_REG_OFFSET;
1680
1681	cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset);
1682	p += scnprintf(p, end - p, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band,
1683		       rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset));
1684	p += scnprintf(p, end - p, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band,
1685		       rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset));
1686	p += scnprintf(p, end - p, "R_AX_CK_EN [%d]=0x%08x\n", band,
1687		       rtw89_read32(rtwdev, R_AX_CK_EN + offset));
1688
1689	if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) {
1690		p += scnprintf(p, end - p,
1691			       "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band,
1692			       rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset));
1693		p += scnprintf(p, end - p,
1694			       "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n", band,
1695			       rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset));
1696	}
1697
1698	if (cmac_err & B_AX_PTCL_TOP_ERR_IND) {
1699		p += scnprintf(p, end - p, "R_AX_PTCL_IMR0 [%d]=0x%08x\n",
1700			       band,
1701			       rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset));
1702		p += scnprintf(p, end - p, "R_AX_PTCL_ISR0 [%d]=0x%08x\n",
1703			       band,
1704			       rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset));
1705	}
1706
1707	if (cmac_err & B_AX_DMA_TOP_ERR_IND) {
1708		if (chip->chip_id == RTL8852C) {
1709			p += scnprintf(p, end - p,
1710				       "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band,
1711				       rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset));
1712			p += scnprintf(p, end - p,
1713				       "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n",
1714				       band,
1715				       rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset));
1716		} else {
1717			p += scnprintf(p, end - p,
1718				       "R_AX_DLE_CTRL [%d]=0x%08x\n", band,
1719				       rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset));
1720		}
1721	}
1722
1723	if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) {
1724		if (chip->chip_id == RTL8852C) {
1725			p += scnprintf(p, end - p,
1726				       "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n",
1727				       band,
1728				       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset));
1729			p += scnprintf(p, end - p,
1730				       "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n",
1731				       band,
1732				       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
1733		} else {
1734			p += scnprintf(p, end - p,
1735				       "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n",
1736				       band,
1737				       rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
1738		}
1739	}
1740
1741	if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) {
1742		p += scnprintf(p, end - p, "R_AX_TXPWR_IMR [%d]=0x%08x\n",
1743			       band,
1744			       rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset));
1745		p += scnprintf(p, end - p, "R_AX_TXPWR_ISR [%d]=0x%08x\n",
1746			       band,
1747			       rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset));
1748	}
1749
1750	if (cmac_err & B_AX_WMAC_TX_ERR_IND) {
1751		if (chip->chip_id == RTL8852C) {
1752			p += scnprintf(p, end - p,
1753				       "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n",
1754				       band,
1755				       rtw89_read32(rtwdev,
1756						    R_AX_TRXPTCL_ERROR_INDICA + offset));
1757			p += scnprintf(p, end - p,
1758				       "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n",
1759				       band,
1760				       rtw89_read32(rtwdev,
1761						    R_AX_TRXPTCL_ERROR_INDICA_MASK + offset));
1762		} else {
1763			p += scnprintf(p, end - p,
1764				       "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n",
1765				       band,
1766				       rtw89_read32(rtwdev,
1767						    R_AX_TMAC_ERR_IMR_ISR + offset));
1768		}
1769		p += scnprintf(p, end - p,
1770			       "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band,
1771			       rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset));
1772	}
1773
1774	p += scnprintf(p, end - p, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band,
1775		       rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset));
1776
1777out:
1778	return p - buf;
1779}
1780
1781static int rtw89_debug_mac_dump_cmac_dbg(struct rtw89_dev *rtwdev,
1782					 char *buf, size_t bufsz)
1783{
1784	char *p = buf, *end = buf + bufsz;
1785
1786	p += rtw89_debug_mac_dump_cmac_err(rtwdev, p, end - p, RTW89_MAC_0);
1787	if (rtwdev->dbcc_en)
1788		p += rtw89_debug_mac_dump_cmac_err(rtwdev, p, end - p, RTW89_MAC_1);
1789
1790	return p - buf;
1791}
1792
1793static const struct rtw89_mac_dbg_port_info dbg_port_ptcl_c0 = {
1794	.sel_addr = R_AX_PTCL_DBG,
1795	.sel_byte = 1,
1796	.sel_msk = B_AX_PTCL_DBG_SEL_MASK,
1797	.srt = 0x00,
1798	.end = 0x3F,
1799	.rd_addr = R_AX_PTCL_DBG_INFO,
1800	.rd_byte = 4,
1801	.rd_msk = B_AX_PTCL_DBG_INFO_MASK
1802};
1803
1804static const struct rtw89_mac_dbg_port_info dbg_port_ptcl_c1 = {
1805	.sel_addr = R_AX_PTCL_DBG_C1,
1806	.sel_byte = 1,
1807	.sel_msk = B_AX_PTCL_DBG_SEL_MASK,
1808	.srt = 0x00,
1809	.end = 0x3F,
1810	.rd_addr = R_AX_PTCL_DBG_INFO_C1,
1811	.rd_byte = 4,
1812	.rd_msk = B_AX_PTCL_DBG_INFO_MASK
1813};
1814
1815static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx0_5 = {
1816	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1817	.sel_byte = 2,
1818	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1819	.srt = 0x0,
1820	.end = 0xD,
1821	.rd_addr = R_AX_DBG_PORT_SEL,
1822	.rd_byte = 4,
1823	.rd_msk = B_AX_DEBUG_ST_MASK
1824};
1825
1826static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx6 = {
1827	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1828	.sel_byte = 2,
1829	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1830	.srt = 0x0,
1831	.end = 0x5,
1832	.rd_addr = R_AX_DBG_PORT_SEL,
1833	.rd_byte = 4,
1834	.rd_msk = B_AX_DEBUG_ST_MASK
1835};
1836
1837static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx7 = {
1838	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1839	.sel_byte = 2,
1840	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1841	.srt = 0x0,
1842	.end = 0x9,
1843	.rd_addr = R_AX_DBG_PORT_SEL,
1844	.rd_byte = 4,
1845	.rd_msk = B_AX_DEBUG_ST_MASK
1846};
1847
1848static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx8 = {
1849	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1850	.sel_byte = 2,
1851	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1852	.srt = 0x0,
1853	.end = 0x3,
1854	.rd_addr = R_AX_DBG_PORT_SEL,
1855	.rd_byte = 4,
1856	.rd_msk = B_AX_DEBUG_ST_MASK
1857};
1858
1859static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx9_C = {
1860	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1861	.sel_byte = 2,
1862	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1863	.srt = 0x0,
1864	.end = 0x1,
1865	.rd_addr = R_AX_DBG_PORT_SEL,
1866	.rd_byte = 4,
1867	.rd_msk = B_AX_DEBUG_ST_MASK
1868};
1869
1870static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_txD = {
1871	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1872	.sel_byte = 2,
1873	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1874	.srt = 0x0,
1875	.end = 0x0,
1876	.rd_addr = R_AX_DBG_PORT_SEL,
1877	.rd_byte = 4,
1878	.rd_msk = B_AX_DEBUG_ST_MASK
1879};
1880
1881static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx0 = {
1882	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1883	.sel_byte = 2,
1884	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1885	.srt = 0x0,
1886	.end = 0xB,
1887	.rd_addr = R_AX_DBG_PORT_SEL,
1888	.rd_byte = 4,
1889	.rd_msk = B_AX_DEBUG_ST_MASK
1890};
1891
1892static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx1 = {
1893	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1894	.sel_byte = 2,
1895	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1896	.srt = 0x0,
1897	.end = 0x4,
1898	.rd_addr = R_AX_DBG_PORT_SEL,
1899	.rd_byte = 4,
1900	.rd_msk = B_AX_DEBUG_ST_MASK
1901};
1902
1903static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx3 = {
1904	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1905	.sel_byte = 2,
1906	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1907	.srt = 0x0,
1908	.end = 0x8,
1909	.rd_addr = R_AX_DBG_PORT_SEL,
1910	.rd_byte = 4,
1911	.rd_msk = B_AX_DEBUG_ST_MASK
1912};
1913
1914static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx4 = {
1915	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1916	.sel_byte = 2,
1917	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1918	.srt = 0x0,
1919	.end = 0x7,
1920	.rd_addr = R_AX_DBG_PORT_SEL,
1921	.rd_byte = 4,
1922	.rd_msk = B_AX_DEBUG_ST_MASK
1923};
1924
1925static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx5_8 = {
1926	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1927	.sel_byte = 2,
1928	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1929	.srt = 0x0,
1930	.end = 0x1,
1931	.rd_addr = R_AX_DBG_PORT_SEL,
1932	.rd_byte = 4,
1933	.rd_msk = B_AX_DEBUG_ST_MASK
1934};
1935
1936static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx9 = {
1937	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1938	.sel_byte = 2,
1939	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1940	.srt = 0x0,
1941	.end = 0x3,
1942	.rd_addr = R_AX_DBG_PORT_SEL,
1943	.rd_byte = 4,
1944	.rd_msk = B_AX_DEBUG_ST_MASK
1945};
1946
1947static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_txA_C = {
1948	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1949	.sel_byte = 2,
1950	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1951	.srt = 0x0,
1952	.end = 0x0,
1953	.rd_addr = R_AX_DBG_PORT_SEL,
1954	.rd_byte = 4,
1955	.rd_msk = B_AX_DEBUG_ST_MASK
1956};
1957
1958static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx0 = {
1959	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1960	.sel_byte = 2,
1961	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1962	.srt = 0x0,
1963	.end = 0x8,
1964	.rd_addr = R_AX_DBG_PORT_SEL,
1965	.rd_byte = 4,
1966	.rd_msk = B_AX_DEBUG_ST_MASK
1967};
1968
1969static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx1_2 = {
1970	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1971	.sel_byte = 2,
1972	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1973	.srt = 0x0,
1974	.end = 0x0,
1975	.rd_addr = R_AX_DBG_PORT_SEL,
1976	.rd_byte = 4,
1977	.rd_msk = B_AX_DEBUG_ST_MASK
1978};
1979
1980static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx3 = {
1981	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1982	.sel_byte = 2,
1983	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1984	.srt = 0x0,
1985	.end = 0x6,
1986	.rd_addr = R_AX_DBG_PORT_SEL,
1987	.rd_byte = 4,
1988	.rd_msk = B_AX_DEBUG_ST_MASK
1989};
1990
1991static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx4 = {
1992	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
1993	.sel_byte = 2,
1994	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
1995	.srt = 0x0,
1996	.end = 0x0,
1997	.rd_addr = R_AX_DBG_PORT_SEL,
1998	.rd_byte = 4,
1999	.rd_msk = B_AX_DEBUG_ST_MASK
2000};
2001
2002static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx5 = {
2003	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2004	.sel_byte = 2,
2005	.sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK,
2006	.srt = 0x0,
2007	.end = 0x0,
2008	.rd_addr = R_AX_DBG_PORT_SEL,
2009	.rd_byte = 4,
2010	.rd_msk = B_AX_DEBUG_ST_MASK
2011};
2012
2013static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_0 = {
2014	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2015	.sel_byte = 1,
2016	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2017	.srt = 0x0,
2018	.end = 0x3,
2019	.rd_addr = R_AX_DBG_PORT_SEL,
2020	.rd_byte = 4,
2021	.rd_msk = B_AX_DEBUG_ST_MASK
2022};
2023
2024static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_1 = {
2025	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2026	.sel_byte = 1,
2027	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2028	.srt = 0x0,
2029	.end = 0x6,
2030	.rd_addr = R_AX_DBG_PORT_SEL,
2031	.rd_byte = 4,
2032	.rd_msk = B_AX_DEBUG_ST_MASK
2033};
2034
2035static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_2 = {
2036	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2037	.sel_byte = 1,
2038	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2039	.srt = 0x0,
2040	.end = 0x0,
2041	.rd_addr = R_AX_DBG_PORT_SEL,
2042	.rd_byte = 4,
2043	.rd_msk = B_AX_DEBUG_ST_MASK
2044};
2045
2046static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p1 = {
2047	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2048	.sel_byte = 1,
2049	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2050	.srt = 0x8,
2051	.end = 0xE,
2052	.rd_addr = R_AX_DBG_PORT_SEL,
2053	.rd_byte = 4,
2054	.rd_msk = B_AX_DEBUG_ST_MASK
2055};
2056
2057static const struct rtw89_mac_dbg_port_info dbg_port_dspt_stf_ctrl = {
2058	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2059	.sel_byte = 1,
2060	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2061	.srt = 0x0,
2062	.end = 0x5,
2063	.rd_addr = R_AX_DBG_PORT_SEL,
2064	.rd_byte = 4,
2065	.rd_msk = B_AX_DEBUG_ST_MASK
2066};
2067
2068static const struct rtw89_mac_dbg_port_info dbg_port_dspt_addr_ctrl = {
2069	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2070	.sel_byte = 1,
2071	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2072	.srt = 0x0,
2073	.end = 0x6,
2074	.rd_addr = R_AX_DBG_PORT_SEL,
2075	.rd_byte = 4,
2076	.rd_msk = B_AX_DEBUG_ST_MASK
2077};
2078
2079static const struct rtw89_mac_dbg_port_info dbg_port_dspt_wde_intf = {
2080	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2081	.sel_byte = 1,
2082	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2083	.srt = 0x0,
2084	.end = 0xF,
2085	.rd_addr = R_AX_DBG_PORT_SEL,
2086	.rd_byte = 4,
2087	.rd_msk = B_AX_DEBUG_ST_MASK
2088};
2089
2090static const struct rtw89_mac_dbg_port_info dbg_port_dspt_ple_intf = {
2091	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2092	.sel_byte = 1,
2093	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2094	.srt = 0x0,
2095	.end = 0x9,
2096	.rd_addr = R_AX_DBG_PORT_SEL,
2097	.rd_byte = 4,
2098	.rd_msk = B_AX_DEBUG_ST_MASK
2099};
2100
2101static const struct rtw89_mac_dbg_port_info dbg_port_dspt_flow_ctrl = {
2102	.sel_addr = R_AX_DISPATCHER_DBG_PORT,
2103	.sel_byte = 1,
2104	.sel_msk = B_AX_DISPATCHER_CH_SEL_MASK,
2105	.srt = 0x0,
2106	.end = 0x3,
2107	.rd_addr = R_AX_DBG_PORT_SEL,
2108	.rd_byte = 4,
2109	.rd_msk = B_AX_DEBUG_ST_MASK
2110};
2111
2112static const struct rtw89_mac_dbg_port_info dbg_port_sch_c0 = {
2113	.sel_addr = R_AX_SCH_DBG_SEL,
2114	.sel_byte = 1,
2115	.sel_msk = B_AX_SCH_DBG_SEL_MASK,
2116	.srt = 0x00,
2117	.end = 0x2F,
2118	.rd_addr = R_AX_SCH_DBG,
2119	.rd_byte = 4,
2120	.rd_msk = B_AX_SCHEDULER_DBG_MASK
2121};
2122
2123static const struct rtw89_mac_dbg_port_info dbg_port_sch_c1 = {
2124	.sel_addr = R_AX_SCH_DBG_SEL_C1,
2125	.sel_byte = 1,
2126	.sel_msk = B_AX_SCH_DBG_SEL_MASK,
2127	.srt = 0x00,
2128	.end = 0x2F,
2129	.rd_addr = R_AX_SCH_DBG_C1,
2130	.rd_byte = 4,
2131	.rd_msk = B_AX_SCHEDULER_DBG_MASK
2132};
2133
2134static const struct rtw89_mac_dbg_port_info dbg_port_tmac_c0 = {
2135	.sel_addr = R_AX_MACTX_DBG_SEL_CNT,
2136	.sel_byte = 1,
2137	.sel_msk = B_AX_DBGSEL_MACTX_MASK,
2138	.srt = 0x00,
2139	.end = 0x19,
2140	.rd_addr = R_AX_DBG_PORT_SEL,
2141	.rd_byte = 4,
2142	.rd_msk = B_AX_DEBUG_ST_MASK
2143};
2144
2145static const struct rtw89_mac_dbg_port_info dbg_port_tmac_c1 = {
2146	.sel_addr = R_AX_MACTX_DBG_SEL_CNT_C1,
2147	.sel_byte = 1,
2148	.sel_msk = B_AX_DBGSEL_MACTX_MASK,
2149	.srt = 0x00,
2150	.end = 0x19,
2151	.rd_addr = R_AX_DBG_PORT_SEL,
2152	.rd_byte = 4,
2153	.rd_msk = B_AX_DEBUG_ST_MASK
2154};
2155
2156static const struct rtw89_mac_dbg_port_info dbg_port_rmac_c0 = {
2157	.sel_addr = R_AX_RX_DEBUG_SELECT,
2158	.sel_byte = 1,
2159	.sel_msk = B_AX_DEBUG_SEL_MASK,
2160	.srt = 0x00,
2161	.end = 0x58,
2162	.rd_addr = R_AX_DBG_PORT_SEL,
2163	.rd_byte = 4,
2164	.rd_msk = B_AX_DEBUG_ST_MASK
2165};
2166
2167static const struct rtw89_mac_dbg_port_info dbg_port_rmac_c1 = {
2168	.sel_addr = R_AX_RX_DEBUG_SELECT_C1,
2169	.sel_byte = 1,
2170	.sel_msk = B_AX_DEBUG_SEL_MASK,
2171	.srt = 0x00,
2172	.end = 0x58,
2173	.rd_addr = R_AX_DBG_PORT_SEL,
2174	.rd_byte = 4,
2175	.rd_msk = B_AX_DEBUG_ST_MASK
2176};
2177
2178static const struct rtw89_mac_dbg_port_info dbg_port_rmacst_c0 = {
2179	.sel_addr = R_AX_RX_STATE_MONITOR,
2180	.sel_byte = 1,
2181	.sel_msk = B_AX_STATE_SEL_MASK,
2182	.srt = 0x00,
2183	.end = 0x17,
2184	.rd_addr = R_AX_RX_STATE_MONITOR,
2185	.rd_byte = 4,
2186	.rd_msk = B_AX_RX_STATE_MONITOR_MASK
2187};
2188
2189static const struct rtw89_mac_dbg_port_info dbg_port_rmacst_c1 = {
2190	.sel_addr = R_AX_RX_STATE_MONITOR_C1,
2191	.sel_byte = 1,
2192	.sel_msk = B_AX_STATE_SEL_MASK,
2193	.srt = 0x00,
2194	.end = 0x17,
2195	.rd_addr = R_AX_RX_STATE_MONITOR_C1,
2196	.rd_byte = 4,
2197	.rd_msk = B_AX_RX_STATE_MONITOR_MASK
2198};
2199
2200static const struct rtw89_mac_dbg_port_info dbg_port_rmac_plcp_c0 = {
2201	.sel_addr = R_AX_RMAC_PLCP_MON,
2202	.sel_byte = 4,
2203	.sel_msk = B_AX_PCLP_MON_SEL_MASK,
2204	.srt = 0x0,
2205	.end = 0xF,
2206	.rd_addr = R_AX_RMAC_PLCP_MON,
2207	.rd_byte = 4,
2208	.rd_msk = B_AX_RMAC_PLCP_MON_MASK
2209};
2210
2211static const struct rtw89_mac_dbg_port_info dbg_port_rmac_plcp_c1 = {
2212	.sel_addr = R_AX_RMAC_PLCP_MON_C1,
2213	.sel_byte = 4,
2214	.sel_msk = B_AX_PCLP_MON_SEL_MASK,
2215	.srt = 0x0,
2216	.end = 0xF,
2217	.rd_addr = R_AX_RMAC_PLCP_MON_C1,
2218	.rd_byte = 4,
2219	.rd_msk = B_AX_RMAC_PLCP_MON_MASK
2220};
2221
2222static const struct rtw89_mac_dbg_port_info dbg_port_trxptcl_c0 = {
2223	.sel_addr = R_AX_DBGSEL_TRXPTCL,
2224	.sel_byte = 1,
2225	.sel_msk = B_AX_DBGSEL_TRXPTCL_MASK,
2226	.srt = 0x08,
2227	.end = 0x10,
2228	.rd_addr = R_AX_DBG_PORT_SEL,
2229	.rd_byte = 4,
2230	.rd_msk = B_AX_DEBUG_ST_MASK
2231};
2232
2233static const struct rtw89_mac_dbg_port_info dbg_port_trxptcl_c1 = {
2234	.sel_addr = R_AX_DBGSEL_TRXPTCL_C1,
2235	.sel_byte = 1,
2236	.sel_msk = B_AX_DBGSEL_TRXPTCL_MASK,
2237	.srt = 0x08,
2238	.end = 0x10,
2239	.rd_addr = R_AX_DBG_PORT_SEL,
2240	.rd_byte = 4,
2241	.rd_msk = B_AX_DEBUG_ST_MASK
2242};
2243
2244static const struct rtw89_mac_dbg_port_info dbg_port_tx_infol_c0 = {
2245	.sel_addr = R_AX_WMAC_TX_CTRL_DEBUG,
2246	.sel_byte = 1,
2247	.sel_msk = B_AX_TX_CTRL_DEBUG_SEL_MASK,
2248	.srt = 0x00,
2249	.end = 0x07,
2250	.rd_addr = R_AX_WMAC_TX_INFO0_DEBUG,
2251	.rd_byte = 4,
2252	.rd_msk = B_AX_TX_CTRL_INFO_P0_MASK
2253};
2254
2255static const struct rtw89_mac_dbg_port_info dbg_port_tx_infoh_c0 = {
2256	.sel_addr = R_AX_WMAC_TX_CTRL_DEBUG,
2257	.sel_byte = 1,
2258	.sel_msk = B_AX_TX_CTRL_DEBUG_SEL_MASK,
2259	.srt = 0x00,
2260	.end = 0x07,
2261	.rd_addr = R_AX_WMAC_TX_INFO1_DEBUG,
2262	.rd_byte = 4,
2263	.rd_msk = B_AX_TX_CTRL_INFO_P1_MASK
2264};
2265
2266static const struct rtw89_mac_dbg_port_info dbg_port_tx_infol_c1 = {
2267	.sel_addr = R_AX_WMAC_TX_CTRL_DEBUG_C1,
2268	.sel_byte = 1,
2269	.sel_msk = B_AX_TX_CTRL_DEBUG_SEL_MASK,
2270	.srt = 0x00,
2271	.end = 0x07,
2272	.rd_addr = R_AX_WMAC_TX_INFO0_DEBUG_C1,
2273	.rd_byte = 4,
2274	.rd_msk = B_AX_TX_CTRL_INFO_P0_MASK
2275};
2276
2277static const struct rtw89_mac_dbg_port_info dbg_port_tx_infoh_c1 = {
2278	.sel_addr = R_AX_WMAC_TX_CTRL_DEBUG_C1,
2279	.sel_byte = 1,
2280	.sel_msk = B_AX_TX_CTRL_DEBUG_SEL_MASK,
2281	.srt = 0x00,
2282	.end = 0x07,
2283	.rd_addr = R_AX_WMAC_TX_INFO1_DEBUG_C1,
2284	.rd_byte = 4,
2285	.rd_msk = B_AX_TX_CTRL_INFO_P1_MASK
2286};
2287
2288static const struct rtw89_mac_dbg_port_info dbg_port_txtf_infol_c0 = {
2289	.sel_addr = R_AX_WMAC_TX_TF_INFO_0,
2290	.sel_byte = 1,
2291	.sel_msk = B_AX_WMAC_TX_TF_INFO_SEL_MASK,
2292	.srt = 0x00,
2293	.end = 0x04,
2294	.rd_addr = R_AX_WMAC_TX_TF_INFO_1,
2295	.rd_byte = 4,
2296	.rd_msk = B_AX_WMAC_TX_TF_INFO_P0_MASK
2297};
2298
2299static const struct rtw89_mac_dbg_port_info dbg_port_txtf_infoh_c0 = {
2300	.sel_addr = R_AX_WMAC_TX_TF_INFO_0,
2301	.sel_byte = 1,
2302	.sel_msk = B_AX_WMAC_TX_TF_INFO_SEL_MASK,
2303	.srt = 0x00,
2304	.end = 0x04,
2305	.rd_addr = R_AX_WMAC_TX_TF_INFO_2,
2306	.rd_byte = 4,
2307	.rd_msk = B_AX_WMAC_TX_TF_INFO_P1_MASK
2308};
2309
2310static const struct rtw89_mac_dbg_port_info dbg_port_txtf_infol_c1 = {
2311	.sel_addr = R_AX_WMAC_TX_TF_INFO_0_C1,
2312	.sel_byte = 1,
2313	.sel_msk = B_AX_WMAC_TX_TF_INFO_SEL_MASK,
2314	.srt = 0x00,
2315	.end = 0x04,
2316	.rd_addr = R_AX_WMAC_TX_TF_INFO_1_C1,
2317	.rd_byte = 4,
2318	.rd_msk = B_AX_WMAC_TX_TF_INFO_P0_MASK
2319};
2320
2321static const struct rtw89_mac_dbg_port_info dbg_port_txtf_infoh_c1 = {
2322	.sel_addr = R_AX_WMAC_TX_TF_INFO_0_C1,
2323	.sel_byte = 1,
2324	.sel_msk = B_AX_WMAC_TX_TF_INFO_SEL_MASK,
2325	.srt = 0x00,
2326	.end = 0x04,
2327	.rd_addr = R_AX_WMAC_TX_TF_INFO_2_C1,
2328	.rd_byte = 4,
2329	.rd_msk = B_AX_WMAC_TX_TF_INFO_P1_MASK
2330};
2331
2332static const struct rtw89_mac_dbg_port_info dbg_port_wde_bufmgn_freepg = {
2333	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2334	.sel_byte = 4,
2335	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2336	.srt = 0x80000000,
2337	.end = 0x80000001,
2338	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2339	.rd_byte = 4,
2340	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2341};
2342
2343static const struct rtw89_mac_dbg_port_info dbg_port_wde_bufmgn_quota = {
2344	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2345	.sel_byte = 4,
2346	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2347	.srt = 0x80010000,
2348	.end = 0x80010004,
2349	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2350	.rd_byte = 4,
2351	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2352};
2353
2354static const struct rtw89_mac_dbg_port_info dbg_port_wde_bufmgn_pagellt = {
2355	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2356	.sel_byte = 4,
2357	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2358	.srt = 0x80020000,
2359	.end = 0x80020FFF,
2360	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2361	.rd_byte = 4,
2362	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2363};
2364
2365static const struct rtw89_mac_dbg_port_info dbg_port_wde_bufmgn_pktinfo = {
2366	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2367	.sel_byte = 4,
2368	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2369	.srt = 0x80030000,
2370	.end = 0x80030FFF,
2371	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2372	.rd_byte = 4,
2373	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2374};
2375
2376static const struct rtw89_mac_dbg_port_info dbg_port_wde_quemgn_prepkt = {
2377	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2378	.sel_byte = 4,
2379	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2380	.srt = 0x80040000,
2381	.end = 0x80040FFF,
2382	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2383	.rd_byte = 4,
2384	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2385};
2386
2387static const struct rtw89_mac_dbg_port_info dbg_port_wde_quemgn_nxtpkt = {
2388	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2389	.sel_byte = 4,
2390	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2391	.srt = 0x80050000,
2392	.end = 0x80050FFF,
2393	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2394	.rd_byte = 4,
2395	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2396};
2397
2398static const struct rtw89_mac_dbg_port_info dbg_port_wde_quemgn_qlnktbl = {
2399	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2400	.sel_byte = 4,
2401	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2402	.srt = 0x80060000,
2403	.end = 0x80060453,
2404	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2405	.rd_byte = 4,
2406	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2407};
2408
2409static const struct rtw89_mac_dbg_port_info dbg_port_wde_quemgn_qempty = {
2410	.sel_addr = R_AX_WDE_DBG_FUN_INTF_CTL,
2411	.sel_byte = 4,
2412	.sel_msk = B_AX_WDE_DFI_DATA_MASK,
2413	.srt = 0x80070000,
2414	.end = 0x80070011,
2415	.rd_addr = R_AX_WDE_DBG_FUN_INTF_DATA,
2416	.rd_byte = 4,
2417	.rd_msk = B_AX_WDE_DFI_DATA_MASK
2418};
2419
2420static const struct rtw89_mac_dbg_port_info dbg_port_ple_bufmgn_freepg = {
2421	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2422	.sel_byte = 4,
2423	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2424	.srt = 0x80000000,
2425	.end = 0x80000001,
2426	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2427	.rd_byte = 4,
2428	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2429};
2430
2431static const struct rtw89_mac_dbg_port_info dbg_port_ple_bufmgn_quota = {
2432	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2433	.sel_byte = 4,
2434	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2435	.srt = 0x80010000,
2436	.end = 0x8001000A,
2437	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2438	.rd_byte = 4,
2439	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2440};
2441
2442static const struct rtw89_mac_dbg_port_info dbg_port_ple_bufmgn_pagellt = {
2443	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2444	.sel_byte = 4,
2445	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2446	.srt = 0x80020000,
2447	.end = 0x80020DBF,
2448	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2449	.rd_byte = 4,
2450	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2451};
2452
2453static const struct rtw89_mac_dbg_port_info dbg_port_ple_bufmgn_pktinfo = {
2454	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2455	.sel_byte = 4,
2456	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2457	.srt = 0x80030000,
2458	.end = 0x80030DBF,
2459	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2460	.rd_byte = 4,
2461	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2462};
2463
2464static const struct rtw89_mac_dbg_port_info dbg_port_ple_quemgn_prepkt = {
2465	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2466	.sel_byte = 4,
2467	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2468	.srt = 0x80040000,
2469	.end = 0x80040DBF,
2470	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2471	.rd_byte = 4,
2472	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2473};
2474
2475static const struct rtw89_mac_dbg_port_info dbg_port_ple_quemgn_nxtpkt = {
2476	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2477	.sel_byte = 4,
2478	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2479	.srt = 0x80050000,
2480	.end = 0x80050DBF,
2481	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2482	.rd_byte = 4,
2483	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2484};
2485
2486static const struct rtw89_mac_dbg_port_info dbg_port_ple_quemgn_qlnktbl = {
2487	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2488	.sel_byte = 4,
2489	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2490	.srt = 0x80060000,
2491	.end = 0x80060041,
2492	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2493	.rd_byte = 4,
2494	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2495};
2496
2497static const struct rtw89_mac_dbg_port_info dbg_port_ple_quemgn_qempty = {
2498	.sel_addr = R_AX_PLE_DBG_FUN_INTF_CTL,
2499	.sel_byte = 4,
2500	.sel_msk = B_AX_PLE_DFI_DATA_MASK,
2501	.srt = 0x80070000,
2502	.end = 0x80070001,
2503	.rd_addr = R_AX_PLE_DBG_FUN_INTF_DATA,
2504	.rd_byte = 4,
2505	.rd_msk = B_AX_PLE_DFI_DATA_MASK
2506};
2507
2508static const struct rtw89_mac_dbg_port_info dbg_port_pktinfo = {
2509	.sel_addr = R_AX_DBG_FUN_INTF_CTL,
2510	.sel_byte = 4,
2511	.sel_msk = B_AX_DFI_DATA_MASK,
2512	.srt = 0x80000000,
2513	.end = 0x8000017f,
2514	.rd_addr = R_AX_DBG_FUN_INTF_DATA,
2515	.rd_byte = 4,
2516	.rd_msk = B_AX_DFI_DATA_MASK
2517};
2518
2519static const struct rtw89_mac_dbg_port_info dbg_port_pcie_txdma = {
2520	.sel_addr = R_AX_PCIE_DBG_CTRL,
2521	.sel_byte = 2,
2522	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2523	.srt = 0x00,
2524	.end = 0x03,
2525	.rd_addr = R_AX_DBG_PORT_SEL,
2526	.rd_byte = 4,
2527	.rd_msk = B_AX_DEBUG_ST_MASK
2528};
2529
2530static const struct rtw89_mac_dbg_port_info dbg_port_pcie_rxdma = {
2531	.sel_addr = R_AX_PCIE_DBG_CTRL,
2532	.sel_byte = 2,
2533	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2534	.srt = 0x00,
2535	.end = 0x04,
2536	.rd_addr = R_AX_DBG_PORT_SEL,
2537	.rd_byte = 4,
2538	.rd_msk = B_AX_DEBUG_ST_MASK
2539};
2540
2541static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cvt = {
2542	.sel_addr = R_AX_PCIE_DBG_CTRL,
2543	.sel_byte = 2,
2544	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2545	.srt = 0x00,
2546	.end = 0x01,
2547	.rd_addr = R_AX_DBG_PORT_SEL,
2548	.rd_byte = 4,
2549	.rd_msk = B_AX_DEBUG_ST_MASK
2550};
2551
2552static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cxpl = {
2553	.sel_addr = R_AX_PCIE_DBG_CTRL,
2554	.sel_byte = 2,
2555	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2556	.srt = 0x00,
2557	.end = 0x05,
2558	.rd_addr = R_AX_DBG_PORT_SEL,
2559	.rd_byte = 4,
2560	.rd_msk = B_AX_DEBUG_ST_MASK
2561};
2562
2563static const struct rtw89_mac_dbg_port_info dbg_port_pcie_io = {
2564	.sel_addr = R_AX_PCIE_DBG_CTRL,
2565	.sel_byte = 2,
2566	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2567	.srt = 0x00,
2568	.end = 0x05,
2569	.rd_addr = R_AX_DBG_PORT_SEL,
2570	.rd_byte = 4,
2571	.rd_msk = B_AX_DEBUG_ST_MASK
2572};
2573
2574static const struct rtw89_mac_dbg_port_info dbg_port_pcie_misc = {
2575	.sel_addr = R_AX_PCIE_DBG_CTRL,
2576	.sel_byte = 2,
2577	.sel_msk = B_AX_PCIE_DBG_SEL_MASK,
2578	.srt = 0x00,
2579	.end = 0x06,
2580	.rd_addr = R_AX_DBG_PORT_SEL,
2581	.rd_byte = 4,
2582	.rd_msk = B_AX_DEBUG_ST_MASK
2583};
2584
2585static const struct rtw89_mac_dbg_port_info dbg_port_pcie_misc2 = {
2586	.sel_addr = R_AX_DBG_CTRL,
2587	.sel_byte = 1,
2588	.sel_msk = B_AX_DBG_SEL0,
2589	.srt = 0x34,
2590	.end = 0x3C,
2591	.rd_addr = R_AX_DBG_PORT_SEL,
2592	.rd_byte = 4,
2593	.rd_msk = B_AX_DEBUG_ST_MASK
2594};
2595
2596static int
2597rtw89_debug_mac_dbg_port_sel(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
2598			     u32 sel, const struct rtw89_mac_dbg_port_info **ppinfo)
2599{
2600	const struct rtw89_mac_dbg_port_info *info = NULL;
2601	char *p = buf, *end = buf + bufsz;
2602	u32 index;
2603	u32 val32;
2604	u16 val16;
2605	u8 val8;
2606
2607	switch (sel) {
2608	case RTW89_DBG_PORT_SEL_PTCL_C0:
2609		info = &dbg_port_ptcl_c0;
2610		val16 = rtw89_read16(rtwdev, R_AX_PTCL_DBG);
2611		val16 |= B_AX_PTCL_DBG_EN;
2612		rtw89_write16(rtwdev, R_AX_PTCL_DBG, val16);
2613		p += scnprintf(p, end - p, "Enable PTCL C0 dbgport.\n");
2614		break;
2615	case RTW89_DBG_PORT_SEL_PTCL_C1:
2616		info = &dbg_port_ptcl_c1;
2617		val16 = rtw89_read16(rtwdev, R_AX_PTCL_DBG_C1);
2618		val16 |= B_AX_PTCL_DBG_EN;
2619		rtw89_write16(rtwdev, R_AX_PTCL_DBG_C1, val16);
2620		p += scnprintf(p, end - p, "Enable PTCL C1 dbgport.\n");
2621		break;
2622	case RTW89_DBG_PORT_SEL_SCH_C0:
2623		info = &dbg_port_sch_c0;
2624		val32 = rtw89_read32(rtwdev, R_AX_SCH_DBG_SEL);
2625		val32 |= B_AX_SCH_DBG_EN;
2626		rtw89_write32(rtwdev, R_AX_SCH_DBG_SEL, val32);
2627		p += scnprintf(p, end - p, "Enable SCH C0 dbgport.\n");
2628		break;
2629	case RTW89_DBG_PORT_SEL_SCH_C1:
2630		info = &dbg_port_sch_c1;
2631		val32 = rtw89_read32(rtwdev, R_AX_SCH_DBG_SEL_C1);
2632		val32 |= B_AX_SCH_DBG_EN;
2633		rtw89_write32(rtwdev, R_AX_SCH_DBG_SEL_C1, val32);
2634		p += scnprintf(p, end - p, "Enable SCH C1 dbgport.\n");
2635		break;
2636	case RTW89_DBG_PORT_SEL_TMAC_C0:
2637		info = &dbg_port_tmac_c0;
2638		val32 = rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL);
2639		val32 = u32_replace_bits(val32, TRXPTRL_DBG_SEL_TMAC,
2640					 B_AX_DBGSEL_TRXPTCL_MASK);
2641		rtw89_write32(rtwdev, R_AX_DBGSEL_TRXPTCL, val32);
2642
2643		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2644		val32 = u32_replace_bits(val32, TMAC_DBG_SEL_C0, B_AX_DBG_SEL0);
2645		val32 = u32_replace_bits(val32, TMAC_DBG_SEL_C0, B_AX_DBG_SEL1);
2646		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2647
2648		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2649		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2650		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2651		p += scnprintf(p, end - p, "Enable TMAC C0 dbgport.\n");
2652		break;
2653	case RTW89_DBG_PORT_SEL_TMAC_C1:
2654		info = &dbg_port_tmac_c1;
2655		val32 = rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL_C1);
2656		val32 = u32_replace_bits(val32, TRXPTRL_DBG_SEL_TMAC,
2657					 B_AX_DBGSEL_TRXPTCL_MASK);
2658		rtw89_write32(rtwdev, R_AX_DBGSEL_TRXPTCL_C1, val32);
2659
2660		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2661		val32 = u32_replace_bits(val32, TMAC_DBG_SEL_C1, B_AX_DBG_SEL0);
2662		val32 = u32_replace_bits(val32, TMAC_DBG_SEL_C1, B_AX_DBG_SEL1);
2663		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2664
2665		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2666		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2667		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2668		p += scnprintf(p, end - p, "Enable TMAC C1 dbgport.\n");
2669		break;
2670	case RTW89_DBG_PORT_SEL_RMAC_C0:
2671		info = &dbg_port_rmac_c0;
2672		val32 = rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL);
2673		val32 = u32_replace_bits(val32, TRXPTRL_DBG_SEL_RMAC,
2674					 B_AX_DBGSEL_TRXPTCL_MASK);
2675		rtw89_write32(rtwdev, R_AX_DBGSEL_TRXPTCL, val32);
2676
2677		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2678		val32 = u32_replace_bits(val32, RMAC_DBG_SEL_C0, B_AX_DBG_SEL0);
2679		val32 = u32_replace_bits(val32, RMAC_DBG_SEL_C0, B_AX_DBG_SEL1);
2680		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2681
2682		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2683		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2684		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2685
2686		val8 = rtw89_read8(rtwdev, R_AX_DBGSEL_TRXPTCL);
2687		val8 = u8_replace_bits(val8, RMAC_CMAC_DBG_SEL,
2688				       B_AX_DBGSEL_TRXPTCL_MASK);
2689		rtw89_write8(rtwdev, R_AX_DBGSEL_TRXPTCL, val8);
2690		p += scnprintf(p, end - p, "Enable RMAC C0 dbgport.\n");
2691		break;
2692	case RTW89_DBG_PORT_SEL_RMAC_C1:
2693		info = &dbg_port_rmac_c1;
2694		val32 = rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL_C1);
2695		val32 = u32_replace_bits(val32, TRXPTRL_DBG_SEL_RMAC,
2696					 B_AX_DBGSEL_TRXPTCL_MASK);
2697		rtw89_write32(rtwdev, R_AX_DBGSEL_TRXPTCL_C1, val32);
2698
2699		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2700		val32 = u32_replace_bits(val32, RMAC_DBG_SEL_C1, B_AX_DBG_SEL0);
2701		val32 = u32_replace_bits(val32, RMAC_DBG_SEL_C1, B_AX_DBG_SEL1);
2702		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2703
2704		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2705		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2706		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2707
2708		val8 = rtw89_read8(rtwdev, R_AX_DBGSEL_TRXPTCL_C1);
2709		val8 = u8_replace_bits(val8, RMAC_CMAC_DBG_SEL,
2710				       B_AX_DBGSEL_TRXPTCL_MASK);
2711		rtw89_write8(rtwdev, R_AX_DBGSEL_TRXPTCL_C1, val8);
2712		p += scnprintf(p, end - p, "Enable RMAC C1 dbgport.\n");
2713		break;
2714	case RTW89_DBG_PORT_SEL_RMACST_C0:
2715		info = &dbg_port_rmacst_c0;
2716		p += scnprintf(p, end - p, "Enable RMAC state C0 dbgport.\n");
2717		break;
2718	case RTW89_DBG_PORT_SEL_RMACST_C1:
2719		info = &dbg_port_rmacst_c1;
2720		p += scnprintf(p, end - p, "Enable RMAC state C1 dbgport.\n");
2721		break;
2722	case RTW89_DBG_PORT_SEL_RMAC_PLCP_C0:
2723		info = &dbg_port_rmac_plcp_c0;
2724		p += scnprintf(p, end - p, "Enable RMAC PLCP C0 dbgport.\n");
2725		break;
2726	case RTW89_DBG_PORT_SEL_RMAC_PLCP_C1:
2727		info = &dbg_port_rmac_plcp_c1;
2728		p += scnprintf(p, end - p, "Enable RMAC PLCP C1 dbgport.\n");
2729		break;
2730	case RTW89_DBG_PORT_SEL_TRXPTCL_C0:
2731		info = &dbg_port_trxptcl_c0;
2732		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2733		val32 = u32_replace_bits(val32, TRXPTCL_DBG_SEL_C0, B_AX_DBG_SEL0);
2734		val32 = u32_replace_bits(val32, TRXPTCL_DBG_SEL_C0, B_AX_DBG_SEL1);
2735		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2736
2737		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2738		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2739		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2740		p += scnprintf(p, end - p, "Enable TRXPTCL C0 dbgport.\n");
2741		break;
2742	case RTW89_DBG_PORT_SEL_TRXPTCL_C1:
2743		info = &dbg_port_trxptcl_c1;
2744		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
2745		val32 = u32_replace_bits(val32, TRXPTCL_DBG_SEL_C1, B_AX_DBG_SEL0);
2746		val32 = u32_replace_bits(val32, TRXPTCL_DBG_SEL_C1, B_AX_DBG_SEL1);
2747		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
2748
2749		val32 = rtw89_read32(rtwdev, R_AX_SYS_STATUS1);
2750		val32 = u32_replace_bits(val32, MAC_DBG_SEL, B_AX_SEL_0XC0_MASK);
2751		rtw89_write32(rtwdev, R_AX_SYS_STATUS1, val32);
2752		p += scnprintf(p, end - p, "Enable TRXPTCL C1 dbgport.\n");
2753		break;
2754	case RTW89_DBG_PORT_SEL_TX_INFOL_C0:
2755		info = &dbg_port_tx_infol_c0;
2756		val32 = rtw89_read32(rtwdev, R_AX_TCR1);
2757		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2758		rtw89_write32(rtwdev, R_AX_TCR1, val32);
2759		p += scnprintf(p, end - p, "Enable tx infol dump.\n");
2760		break;
2761	case RTW89_DBG_PORT_SEL_TX_INFOH_C0:
2762		info = &dbg_port_tx_infoh_c0;
2763		val32 = rtw89_read32(rtwdev, R_AX_TCR1);
2764		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2765		rtw89_write32(rtwdev, R_AX_TCR1, val32);
2766		p += scnprintf(p, end - p, "Enable tx infoh dump.\n");
2767		break;
2768	case RTW89_DBG_PORT_SEL_TX_INFOL_C1:
2769		info = &dbg_port_tx_infol_c1;
2770		val32 = rtw89_read32(rtwdev, R_AX_TCR1_C1);
2771		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2772		rtw89_write32(rtwdev, R_AX_TCR1_C1, val32);
2773		p += scnprintf(p, end - p, "Enable tx infol dump.\n");
2774		break;
2775	case RTW89_DBG_PORT_SEL_TX_INFOH_C1:
2776		info = &dbg_port_tx_infoh_c1;
2777		val32 = rtw89_read32(rtwdev, R_AX_TCR1_C1);
2778		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2779		rtw89_write32(rtwdev, R_AX_TCR1_C1, val32);
2780		p += scnprintf(p, end - p, "Enable tx infoh dump.\n");
2781		break;
2782	case RTW89_DBG_PORT_SEL_TXTF_INFOL_C0:
2783		info = &dbg_port_txtf_infol_c0;
2784		val32 = rtw89_read32(rtwdev, R_AX_TCR1);
2785		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2786		rtw89_write32(rtwdev, R_AX_TCR1, val32);
2787		p += scnprintf(p, end - p, "Enable tx tf infol dump.\n");
2788		break;
2789	case RTW89_DBG_PORT_SEL_TXTF_INFOH_C0:
2790		info = &dbg_port_txtf_infoh_c0;
2791		val32 = rtw89_read32(rtwdev, R_AX_TCR1);
2792		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2793		rtw89_write32(rtwdev, R_AX_TCR1, val32);
2794		p += scnprintf(p, end - p, "Enable tx tf infoh dump.\n");
2795		break;
2796	case RTW89_DBG_PORT_SEL_TXTF_INFOL_C1:
2797		info = &dbg_port_txtf_infol_c1;
2798		val32 = rtw89_read32(rtwdev, R_AX_TCR1_C1);
2799		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2800		rtw89_write32(rtwdev, R_AX_TCR1_C1, val32);
2801		p += scnprintf(p, end - p, "Enable tx tf infol dump.\n");
2802		break;
2803	case RTW89_DBG_PORT_SEL_TXTF_INFOH_C1:
2804		info = &dbg_port_txtf_infoh_c1;
2805		val32 = rtw89_read32(rtwdev, R_AX_TCR1_C1);
2806		val32 |= B_AX_TCR_FORCE_READ_TXDFIFO;
2807		rtw89_write32(rtwdev, R_AX_TCR1_C1, val32);
2808		p += scnprintf(p, end - p, "Enable tx tf infoh dump.\n");
2809		break;
2810	case RTW89_DBG_PORT_SEL_WDE_BUFMGN_FREEPG:
2811		info = &dbg_port_wde_bufmgn_freepg;
2812		p += scnprintf(p, end - p, "Enable wde bufmgn freepg dump.\n");
2813		break;
2814	case RTW89_DBG_PORT_SEL_WDE_BUFMGN_QUOTA:
2815		info = &dbg_port_wde_bufmgn_quota;
2816		p += scnprintf(p, end - p, "Enable wde bufmgn quota dump.\n");
2817		break;
2818	case RTW89_DBG_PORT_SEL_WDE_BUFMGN_PAGELLT:
2819		info = &dbg_port_wde_bufmgn_pagellt;
2820		p += scnprintf(p, end - p,
2821			       "Enable wde bufmgn pagellt dump.\n");
2822		break;
2823	case RTW89_DBG_PORT_SEL_WDE_BUFMGN_PKTINFO:
2824		info = &dbg_port_wde_bufmgn_pktinfo;
2825		p += scnprintf(p, end - p,
2826			       "Enable wde bufmgn pktinfo dump.\n");
2827		break;
2828	case RTW89_DBG_PORT_SEL_WDE_QUEMGN_PREPKT:
2829		info = &dbg_port_wde_quemgn_prepkt;
2830		p += scnprintf(p, end - p, "Enable wde quemgn prepkt dump.\n");
2831		break;
2832	case RTW89_DBG_PORT_SEL_WDE_QUEMGN_NXTPKT:
2833		info = &dbg_port_wde_quemgn_nxtpkt;
2834		p += scnprintf(p, end - p, "Enable wde quemgn nxtpkt dump.\n");
2835		break;
2836	case RTW89_DBG_PORT_SEL_WDE_QUEMGN_QLNKTBL:
2837		info = &dbg_port_wde_quemgn_qlnktbl;
2838		p += scnprintf(p, end - p,
2839			       "Enable wde quemgn qlnktbl dump.\n");
2840		break;
2841	case RTW89_DBG_PORT_SEL_WDE_QUEMGN_QEMPTY:
2842		info = &dbg_port_wde_quemgn_qempty;
2843		p += scnprintf(p, end - p, "Enable wde quemgn qempty dump.\n");
2844		break;
2845	case RTW89_DBG_PORT_SEL_PLE_BUFMGN_FREEPG:
2846		info = &dbg_port_ple_bufmgn_freepg;
2847		p += scnprintf(p, end - p, "Enable ple bufmgn freepg dump.\n");
2848		break;
2849	case RTW89_DBG_PORT_SEL_PLE_BUFMGN_QUOTA:
2850		info = &dbg_port_ple_bufmgn_quota;
2851		p += scnprintf(p, end - p, "Enable ple bufmgn quota dump.\n");
2852		break;
2853	case RTW89_DBG_PORT_SEL_PLE_BUFMGN_PAGELLT:
2854		info = &dbg_port_ple_bufmgn_pagellt;
2855		p += scnprintf(p, end - p,
2856			       "Enable ple bufmgn pagellt dump.\n");
2857		break;
2858	case RTW89_DBG_PORT_SEL_PLE_BUFMGN_PKTINFO:
2859		info = &dbg_port_ple_bufmgn_pktinfo;
2860		p += scnprintf(p, end - p,
2861			       "Enable ple bufmgn pktinfo dump.\n");
2862		break;
2863	case RTW89_DBG_PORT_SEL_PLE_QUEMGN_PREPKT:
2864		info = &dbg_port_ple_quemgn_prepkt;
2865		p += scnprintf(p, end - p, "Enable ple quemgn prepkt dump.\n");
2866		break;
2867	case RTW89_DBG_PORT_SEL_PLE_QUEMGN_NXTPKT:
2868		info = &dbg_port_ple_quemgn_nxtpkt;
2869		p += scnprintf(p, end - p, "Enable ple quemgn nxtpkt dump.\n");
2870		break;
2871	case RTW89_DBG_PORT_SEL_PLE_QUEMGN_QLNKTBL:
2872		info = &dbg_port_ple_quemgn_qlnktbl;
2873		p += scnprintf(p, end - p,
2874			       "Enable ple quemgn qlnktbl dump.\n");
2875		break;
2876	case RTW89_DBG_PORT_SEL_PLE_QUEMGN_QEMPTY:
2877		info = &dbg_port_ple_quemgn_qempty;
2878		p += scnprintf(p, end - p, "Enable ple quemgn qempty dump.\n");
2879		break;
2880	case RTW89_DBG_PORT_SEL_PKTINFO:
2881		info = &dbg_port_pktinfo;
2882		p += scnprintf(p, end - p, "Enable pktinfo dump.\n");
2883		break;
2884	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX0:
2885		rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
2886				   B_AX_DBG_SEL0, 0x80);
2887		rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1,
2888				   B_AX_SEL_0XC0_MASK, 1);
2889		fallthrough;
2890	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX1:
2891	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX2:
2892	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX3:
2893	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX4:
2894	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX5:
2895		info = &dbg_port_dspt_hdt_tx0_5;
2896		index = sel - RTW89_DBG_PORT_SEL_DSPT_HDT_TX0;
2897		rtw89_write16_mask(rtwdev, info->sel_addr,
2898				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2899		rtw89_write16_mask(rtwdev, info->sel_addr,
2900				   B_AX_DISPATCHER_CH_SEL_MASK, index);
2901		p += scnprintf(p, end - p,
2902			       "Enable Dispatcher hdt tx%x dump.\n", index);
2903		break;
2904	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX6:
2905		info = &dbg_port_dspt_hdt_tx6;
2906		rtw89_write16_mask(rtwdev, info->sel_addr,
2907				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2908		rtw89_write16_mask(rtwdev, info->sel_addr,
2909				   B_AX_DISPATCHER_CH_SEL_MASK, 6);
2910		p += scnprintf(p, end - p,
2911			       "Enable Dispatcher hdt tx6 dump.\n");
2912		break;
2913	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX7:
2914		info = &dbg_port_dspt_hdt_tx7;
2915		rtw89_write16_mask(rtwdev, info->sel_addr,
2916				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2917		rtw89_write16_mask(rtwdev, info->sel_addr,
2918				   B_AX_DISPATCHER_CH_SEL_MASK, 7);
2919		p += scnprintf(p, end - p,
2920			       "Enable Dispatcher hdt tx7 dump.\n");
2921		break;
2922	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX8:
2923		info = &dbg_port_dspt_hdt_tx8;
2924		rtw89_write16_mask(rtwdev, info->sel_addr,
2925				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2926		rtw89_write16_mask(rtwdev, info->sel_addr,
2927				   B_AX_DISPATCHER_CH_SEL_MASK, 8);
2928		p += scnprintf(p, end - p,
2929			       "Enable Dispatcher hdt tx8 dump.\n");
2930		break;
2931	case RTW89_DBG_PORT_SEL_DSPT_HDT_TX9:
2932	case RTW89_DBG_PORT_SEL_DSPT_HDT_TXA:
2933	case RTW89_DBG_PORT_SEL_DSPT_HDT_TXB:
2934	case RTW89_DBG_PORT_SEL_DSPT_HDT_TXC:
2935		info = &dbg_port_dspt_hdt_tx9_C;
2936		index = sel + 9 - RTW89_DBG_PORT_SEL_DSPT_HDT_TX9;
2937		rtw89_write16_mask(rtwdev, info->sel_addr,
2938				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2939		rtw89_write16_mask(rtwdev, info->sel_addr,
2940				   B_AX_DISPATCHER_CH_SEL_MASK, index);
2941		p += scnprintf(p, end - p,
2942			       "Enable Dispatcher hdt tx%x dump.\n", index);
2943		break;
2944	case RTW89_DBG_PORT_SEL_DSPT_HDT_TXD:
2945		info = &dbg_port_dspt_hdt_txD;
2946		rtw89_write16_mask(rtwdev, info->sel_addr,
2947				   B_AX_DISPATCHER_INTN_SEL_MASK, 0);
2948		rtw89_write16_mask(rtwdev, info->sel_addr,
2949				   B_AX_DISPATCHER_CH_SEL_MASK, 0xD);
2950		p += scnprintf(p, end - p,
2951			       "Enable Dispatcher hdt txD dump.\n");
2952		break;
2953	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX0:
2954		info = &dbg_port_dspt_cdt_tx0;
2955		rtw89_write16_mask(rtwdev, info->sel_addr,
2956				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
2957		rtw89_write16_mask(rtwdev, info->sel_addr,
2958				   B_AX_DISPATCHER_CH_SEL_MASK, 0);
2959		p += scnprintf(p, end - p,
2960			       "Enable Dispatcher cdt tx0 dump.\n");
2961		break;
2962	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX1:
2963		info = &dbg_port_dspt_cdt_tx1;
2964		rtw89_write16_mask(rtwdev, info->sel_addr,
2965				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
2966		rtw89_write16_mask(rtwdev, info->sel_addr,
2967				   B_AX_DISPATCHER_CH_SEL_MASK, 1);
2968		p += scnprintf(p, end - p,
2969			       "Enable Dispatcher cdt tx1 dump.\n");
2970		break;
2971	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX3:
2972		info = &dbg_port_dspt_cdt_tx3;
2973		rtw89_write16_mask(rtwdev, info->sel_addr,
2974				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
2975		rtw89_write16_mask(rtwdev, info->sel_addr,
2976				   B_AX_DISPATCHER_CH_SEL_MASK, 3);
2977		p += scnprintf(p, end - p,
2978			       "Enable Dispatcher cdt tx3 dump.\n");
2979		break;
2980	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX4:
2981		info = &dbg_port_dspt_cdt_tx4;
2982		rtw89_write16_mask(rtwdev, info->sel_addr,
2983				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
2984		rtw89_write16_mask(rtwdev, info->sel_addr,
2985				   B_AX_DISPATCHER_CH_SEL_MASK, 4);
2986		p += scnprintf(p, end - p,
2987			       "Enable Dispatcher cdt tx4 dump.\n");
2988		break;
2989	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX5:
2990	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX6:
2991	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX7:
2992	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX8:
2993		info = &dbg_port_dspt_cdt_tx5_8;
2994		index = sel + 5 - RTW89_DBG_PORT_SEL_DSPT_CDT_TX5;
2995		rtw89_write16_mask(rtwdev, info->sel_addr,
2996				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
2997		rtw89_write16_mask(rtwdev, info->sel_addr,
2998				   B_AX_DISPATCHER_CH_SEL_MASK, index);
2999		p += scnprintf(p, end - p,
3000			       "Enable Dispatcher cdt tx%x dump.\n", index);
3001		break;
3002	case RTW89_DBG_PORT_SEL_DSPT_CDT_TX9:
3003		info = &dbg_port_dspt_cdt_tx9;
3004		rtw89_write16_mask(rtwdev, info->sel_addr,
3005				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
3006		rtw89_write16_mask(rtwdev, info->sel_addr,
3007				   B_AX_DISPATCHER_CH_SEL_MASK, 9);
3008		p += scnprintf(p, end - p,
3009			       "Enable Dispatcher cdt tx9 dump.\n");
3010		break;
3011	case RTW89_DBG_PORT_SEL_DSPT_CDT_TXA:
3012	case RTW89_DBG_PORT_SEL_DSPT_CDT_TXB:
3013	case RTW89_DBG_PORT_SEL_DSPT_CDT_TXC:
3014		info = &dbg_port_dspt_cdt_txA_C;
3015		index = sel + 0xA - RTW89_DBG_PORT_SEL_DSPT_CDT_TXA;
3016		rtw89_write16_mask(rtwdev, info->sel_addr,
3017				   B_AX_DISPATCHER_INTN_SEL_MASK, 1);
3018		rtw89_write16_mask(rtwdev, info->sel_addr,
3019				   B_AX_DISPATCHER_CH_SEL_MASK, index);
3020		p += scnprintf(p, end - p,
3021			       "Enable Dispatcher cdt tx%x dump.\n", index);
3022		break;
3023	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX0:
3024		info = &dbg_port_dspt_hdt_rx0;
3025		rtw89_write16_mask(rtwdev, info->sel_addr,
3026				   B_AX_DISPATCHER_INTN_SEL_MASK, 2);
3027		rtw89_write16_mask(rtwdev, info->sel_addr,
3028				   B_AX_DISPATCHER_CH_SEL_MASK, 0);
3029		p += scnprintf(p, end - p,
3030			       "Enable Dispatcher hdt rx0 dump.\n");
3031		break;
3032	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX1:
3033	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX2:
3034		info = &dbg_port_dspt_hdt_rx1_2;
3035		index = sel + 1 - RTW89_DBG_PORT_SEL_DSPT_HDT_RX1;
3036		rtw89_write16_mask(rtwdev, info->sel_addr,
3037				   B_AX_DISPATCHER_INTN_SEL_MASK, 2);
3038		rtw89_write16_mask(rtwdev, info->sel_addr,
3039				   B_AX_DISPATCHER_CH_SEL_MASK, index);
3040		p += scnprintf(p, end - p,
3041			       "Enable Dispatcher hdt rx%x dump.\n", index);
3042		break;
3043	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX3:
3044		info = &dbg_port_dspt_hdt_rx3;
3045		rtw89_write16_mask(rtwdev, info->sel_addr,
3046				   B_AX_DISPATCHER_INTN_SEL_MASK, 2);
3047		rtw89_write16_mask(rtwdev, info->sel_addr,
3048				   B_AX_DISPATCHER_CH_SEL_MASK, 3);
3049		p += scnprintf(p, end - p,
3050			       "Enable Dispatcher hdt rx3 dump.\n");
3051		break;
3052	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX4:
3053		info = &dbg_port_dspt_hdt_rx4;
3054		rtw89_write16_mask(rtwdev, info->sel_addr,
3055				   B_AX_DISPATCHER_INTN_SEL_MASK, 2);
3056		rtw89_write16_mask(rtwdev, info->sel_addr,
3057				   B_AX_DISPATCHER_CH_SEL_MASK, 4);
3058		p += scnprintf(p, end - p,
3059			       "Enable Dispatcher hdt rx4 dump.\n");
3060		break;
3061	case RTW89_DBG_PORT_SEL_DSPT_HDT_RX5:
3062		info = &dbg_port_dspt_hdt_rx5;
3063		rtw89_write16_mask(rtwdev, info->sel_addr,
3064				   B_AX_DISPATCHER_INTN_SEL_MASK, 2);
3065		rtw89_write16_mask(rtwdev, info->sel_addr,
3066				   B_AX_DISPATCHER_CH_SEL_MASK, 5);
3067		p += scnprintf(p, end - p,
3068			       "Enable Dispatcher hdt rx5 dump.\n");
3069		break;
3070	case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_0:
3071		info = &dbg_port_dspt_cdt_rx_p0_0;
3072		rtw89_write16_mask(rtwdev, info->sel_addr,
3073				   B_AX_DISPATCHER_INTN_SEL_MASK, 3);
3074		rtw89_write16_mask(rtwdev, info->sel_addr,
3075				   B_AX_DISPATCHER_CH_SEL_MASK, 0);
3076		p += scnprintf(p, end - p,
3077			       "Enable Dispatcher cdt rx part0 0 dump.\n");
3078		break;
3079	case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0:
3080	case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_1:
3081		info = &dbg_port_dspt_cdt_rx_p0_1;
3082		rtw89_write16_mask(rtwdev, info->sel_addr,
3083				   B_AX_DISPATCHER_INTN_SEL_MASK, 3);
3084		rtw89_write16_mask(rtwdev, info->sel_addr,
3085				   B_AX_DISPATCHER_CH_SEL_MASK, 1);
3086		p += scnprintf(p, end - p,
3087			       "Enable Dispatcher cdt rx part0 1 dump.\n");
3088		break;
3089	case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_2:
3090		info = &dbg_port_dspt_cdt_rx_p0_2;
3091		rtw89_write16_mask(rtwdev, info->sel_addr,
3092				   B_AX_DISPATCHER_INTN_SEL_MASK, 3);
3093		rtw89_write16_mask(rtwdev, info->sel_addr,
3094				   B_AX_DISPATCHER_CH_SEL_MASK, 2);
3095		p += scnprintf(p, end - p,
3096			       "Enable Dispatcher cdt rx part0 2 dump.\n");
3097		break;
3098	case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P1:
3099		info = &dbg_port_dspt_cdt_rx_p1;
3100		rtw89_write8_mask(rtwdev, info->sel_addr,
3101				  B_AX_DISPATCHER_INTN_SEL_MASK, 3);
3102		p += scnprintf(p, end - p,
3103			       "Enable Dispatcher cdt rx part1 dump.\n");
3104		break;
3105	case RTW89_DBG_PORT_SEL_DSPT_STF_CTRL:
3106		info = &dbg_port_dspt_stf_ctrl;
3107		rtw89_write8_mask(rtwdev, info->sel_addr,
3108				  B_AX_DISPATCHER_INTN_SEL_MASK, 4);
3109		p += scnprintf(p, end - p,
3110			       "Enable Dispatcher stf control dump.\n");
3111		break;
3112	case RTW89_DBG_PORT_SEL_DSPT_ADDR_CTRL:
3113		info = &dbg_port_dspt_addr_ctrl;
3114		rtw89_write8_mask(rtwdev, info->sel_addr,
3115				  B_AX_DISPATCHER_INTN_SEL_MASK, 5);
3116		p += scnprintf(p, end - p,
3117			       "Enable Dispatcher addr control dump.\n");
3118		break;
3119	case RTW89_DBG_PORT_SEL_DSPT_WDE_INTF:
3120		info = &dbg_port_dspt_wde_intf;
3121		rtw89_write8_mask(rtwdev, info->sel_addr,
3122				  B_AX_DISPATCHER_INTN_SEL_MASK, 6);
3123		p += scnprintf(p, end - p,
3124			       "Enable Dispatcher wde interface dump.\n");
3125		break;
3126	case RTW89_DBG_PORT_SEL_DSPT_PLE_INTF:
3127		info = &dbg_port_dspt_ple_intf;
3128		rtw89_write8_mask(rtwdev, info->sel_addr,
3129				  B_AX_DISPATCHER_INTN_SEL_MASK, 7);
3130		p += scnprintf(p, end - p,
3131			       "Enable Dispatcher ple interface dump.\n");
3132		break;
3133	case RTW89_DBG_PORT_SEL_DSPT_FLOW_CTRL:
3134		info = &dbg_port_dspt_flow_ctrl;
3135		rtw89_write8_mask(rtwdev, info->sel_addr,
3136				  B_AX_DISPATCHER_INTN_SEL_MASK, 8);
3137		p += scnprintf(p, end - p,
3138			       "Enable Dispatcher flow control dump.\n");
3139		break;
3140	case RTW89_DBG_PORT_SEL_PCIE_TXDMA:
3141		info = &dbg_port_pcie_txdma;
3142		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3143		val32 = u32_replace_bits(val32, PCIE_TXDMA_DBG_SEL, B_AX_DBG_SEL0);
3144		val32 = u32_replace_bits(val32, PCIE_TXDMA_DBG_SEL, B_AX_DBG_SEL1);
3145		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3146		p += scnprintf(p, end - p, "Enable pcie txdma dump.\n");
3147		break;
3148	case RTW89_DBG_PORT_SEL_PCIE_RXDMA:
3149		info = &dbg_port_pcie_rxdma;
3150		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3151		val32 = u32_replace_bits(val32, PCIE_RXDMA_DBG_SEL, B_AX_DBG_SEL0);
3152		val32 = u32_replace_bits(val32, PCIE_RXDMA_DBG_SEL, B_AX_DBG_SEL1);
3153		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3154		p += scnprintf(p, end - p, "Enable pcie rxdma dump.\n");
3155		break;
3156	case RTW89_DBG_PORT_SEL_PCIE_CVT:
3157		info = &dbg_port_pcie_cvt;
3158		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3159		val32 = u32_replace_bits(val32, PCIE_CVT_DBG_SEL, B_AX_DBG_SEL0);
3160		val32 = u32_replace_bits(val32, PCIE_CVT_DBG_SEL, B_AX_DBG_SEL1);
3161		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3162		p += scnprintf(p, end - p, "Enable pcie cvt dump.\n");
3163		break;
3164	case RTW89_DBG_PORT_SEL_PCIE_CXPL:
3165		info = &dbg_port_pcie_cxpl;
3166		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3167		val32 = u32_replace_bits(val32, PCIE_CXPL_DBG_SEL, B_AX_DBG_SEL0);
3168		val32 = u32_replace_bits(val32, PCIE_CXPL_DBG_SEL, B_AX_DBG_SEL1);
3169		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3170		p += scnprintf(p, end - p, "Enable pcie cxpl dump.\n");
3171		break;
3172	case RTW89_DBG_PORT_SEL_PCIE_IO:
3173		info = &dbg_port_pcie_io;
3174		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3175		val32 = u32_replace_bits(val32, PCIE_IO_DBG_SEL, B_AX_DBG_SEL0);
3176		val32 = u32_replace_bits(val32, PCIE_IO_DBG_SEL, B_AX_DBG_SEL1);
3177		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3178		p += scnprintf(p, end - p, "Enable pcie io dump.\n");
3179		break;
3180	case RTW89_DBG_PORT_SEL_PCIE_MISC:
3181		info = &dbg_port_pcie_misc;
3182		val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL);
3183		val32 = u32_replace_bits(val32, PCIE_MISC_DBG_SEL, B_AX_DBG_SEL0);
3184		val32 = u32_replace_bits(val32, PCIE_MISC_DBG_SEL, B_AX_DBG_SEL1);
3185		rtw89_write32(rtwdev, R_AX_DBG_CTRL, val32);
3186		p += scnprintf(p, end - p, "Enable pcie misc dump.\n");
3187		break;
3188	case RTW89_DBG_PORT_SEL_PCIE_MISC2:
3189		info = &dbg_port_pcie_misc2;
3190		val16 = rtw89_read16(rtwdev, R_AX_PCIE_DBG_CTRL);
3191		val16 = u16_replace_bits(val16, PCIE_MISC2_DBG_SEL,
3192					 B_AX_PCIE_DBG_SEL_MASK);
3193		rtw89_write16(rtwdev, R_AX_PCIE_DBG_CTRL, val16);
3194		p += scnprintf(p, end - p, "Enable pcie misc2 dump.\n");
3195		break;
3196	default:
3197		p += scnprintf(p, end - p, "Dbg port select err\n");
3198		break;
3199	}
3200
3201	*ppinfo = info;
3202
3203	return p - buf;
3204}
3205
3206static bool is_dbg_port_valid(struct rtw89_dev *rtwdev, u32 sel)
3207{
3208	if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE &&
3209	    sel >= RTW89_DBG_PORT_SEL_PCIE_TXDMA &&
3210	    sel <= RTW89_DBG_PORT_SEL_PCIE_MISC2)
3211		return false;
3212	if (rtw89_is_rtl885xb(rtwdev) &&
3213	    sel >= RTW89_DBG_PORT_SEL_PTCL_C1 &&
3214	    sel <= RTW89_DBG_PORT_SEL_TXTF_INFOH_C1)
3215		return false;
3216	if (rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL) &&
3217	    sel >= RTW89_DBG_PORT_SEL_WDE_BUFMGN_FREEPG &&
3218	    sel <= RTW89_DBG_PORT_SEL_PKTINFO)
3219		return false;
3220	if (rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL) &&
3221	    sel >= RTW89_DBG_PORT_SEL_DSPT_HDT_TX0 &&
3222	    sel <= RTW89_DBG_PORT_SEL_DSPT_FLOW_CTRL)
3223		return false;
3224	if (rtw89_mac_check_mac_en(rtwdev, 0, RTW89_CMAC_SEL) &&
3225	    sel >= RTW89_DBG_PORT_SEL_PTCL_C0 &&
3226	    sel <= RTW89_DBG_PORT_SEL_TXTF_INFOH_C0)
3227		return false;
3228	if (rtw89_mac_check_mac_en(rtwdev, 1, RTW89_CMAC_SEL) &&
3229	    sel >= RTW89_DBG_PORT_SEL_PTCL_C1 &&
3230	    sel <= RTW89_DBG_PORT_SEL_TXTF_INFOH_C1)
3231		return false;
3232
3233	return true;
3234}
3235
3236static int rtw89_debug_mac_dbg_port_dump(struct rtw89_dev *rtwdev,
3237					 char *buf, size_t bufsz, u32 sel)
3238{
3239	const struct rtw89_mac_dbg_port_info *info = NULL;
3240	char *p = buf, *end = buf + bufsz;
3241	u32 val32;
3242	u16 val16;
3243	u8 val8;
3244	u32 i;
3245
3246	p += rtw89_debug_mac_dbg_port_sel(rtwdev, p, end - p, sel, &info);
3247
3248	if (!info) {
3249		rtw89_err(rtwdev, "failed to select debug port %d\n", sel);
3250		goto out;
3251	}
3252
3253#define case_DBG_SEL(__sel) \
3254	case RTW89_DBG_PORT_SEL_##__sel: \
3255		p += scnprintf(p, end - p, "Dump debug port " #__sel ":\n"); \
3256		break
3257
3258	switch (sel) {
3259	case_DBG_SEL(PTCL_C0);
3260	case_DBG_SEL(PTCL_C1);
3261	case_DBG_SEL(SCH_C0);
3262	case_DBG_SEL(SCH_C1);
3263	case_DBG_SEL(TMAC_C0);
3264	case_DBG_SEL(TMAC_C1);
3265	case_DBG_SEL(RMAC_C0);
3266	case_DBG_SEL(RMAC_C1);
3267	case_DBG_SEL(RMACST_C0);
3268	case_DBG_SEL(RMACST_C1);
3269	case_DBG_SEL(TRXPTCL_C0);
3270	case_DBG_SEL(TRXPTCL_C1);
3271	case_DBG_SEL(TX_INFOL_C0);
3272	case_DBG_SEL(TX_INFOH_C0);
3273	case_DBG_SEL(TX_INFOL_C1);
3274	case_DBG_SEL(TX_INFOH_C1);
3275	case_DBG_SEL(TXTF_INFOL_C0);
3276	case_DBG_SEL(TXTF_INFOH_C0);
3277	case_DBG_SEL(TXTF_INFOL_C1);
3278	case_DBG_SEL(TXTF_INFOH_C1);
3279	case_DBG_SEL(WDE_BUFMGN_FREEPG);
3280	case_DBG_SEL(WDE_BUFMGN_QUOTA);
3281	case_DBG_SEL(WDE_BUFMGN_PAGELLT);
3282	case_DBG_SEL(WDE_BUFMGN_PKTINFO);
3283	case_DBG_SEL(WDE_QUEMGN_PREPKT);
3284	case_DBG_SEL(WDE_QUEMGN_NXTPKT);
3285	case_DBG_SEL(WDE_QUEMGN_QLNKTBL);
3286	case_DBG_SEL(WDE_QUEMGN_QEMPTY);
3287	case_DBG_SEL(PLE_BUFMGN_FREEPG);
3288	case_DBG_SEL(PLE_BUFMGN_QUOTA);
3289	case_DBG_SEL(PLE_BUFMGN_PAGELLT);
3290	case_DBG_SEL(PLE_BUFMGN_PKTINFO);
3291	case_DBG_SEL(PLE_QUEMGN_PREPKT);
3292	case_DBG_SEL(PLE_QUEMGN_NXTPKT);
3293	case_DBG_SEL(PLE_QUEMGN_QLNKTBL);
3294	case_DBG_SEL(PLE_QUEMGN_QEMPTY);
3295	case_DBG_SEL(PKTINFO);
3296	case_DBG_SEL(DSPT_HDT_TX0);
3297	case_DBG_SEL(DSPT_HDT_TX1);
3298	case_DBG_SEL(DSPT_HDT_TX2);
3299	case_DBG_SEL(DSPT_HDT_TX3);
3300	case_DBG_SEL(DSPT_HDT_TX4);
3301	case_DBG_SEL(DSPT_HDT_TX5);
3302	case_DBG_SEL(DSPT_HDT_TX6);
3303	case_DBG_SEL(DSPT_HDT_TX7);
3304	case_DBG_SEL(DSPT_HDT_TX8);
3305	case_DBG_SEL(DSPT_HDT_TX9);
3306	case_DBG_SEL(DSPT_HDT_TXA);
3307	case_DBG_SEL(DSPT_HDT_TXB);
3308	case_DBG_SEL(DSPT_HDT_TXC);
3309	case_DBG_SEL(DSPT_HDT_TXD);
3310	case_DBG_SEL(DSPT_HDT_TXE);
3311	case_DBG_SEL(DSPT_HDT_TXF);
3312	case_DBG_SEL(DSPT_CDT_TX0);
3313	case_DBG_SEL(DSPT_CDT_TX1);
3314	case_DBG_SEL(DSPT_CDT_TX3);
3315	case_DBG_SEL(DSPT_CDT_TX4);
3316	case_DBG_SEL(DSPT_CDT_TX5);
3317	case_DBG_SEL(DSPT_CDT_TX6);
3318	case_DBG_SEL(DSPT_CDT_TX7);
3319	case_DBG_SEL(DSPT_CDT_TX8);
3320	case_DBG_SEL(DSPT_CDT_TX9);
3321	case_DBG_SEL(DSPT_CDT_TXA);
3322	case_DBG_SEL(DSPT_CDT_TXB);
3323	case_DBG_SEL(DSPT_CDT_TXC);
3324	case_DBG_SEL(DSPT_HDT_RX0);
3325	case_DBG_SEL(DSPT_HDT_RX1);
3326	case_DBG_SEL(DSPT_HDT_RX2);
3327	case_DBG_SEL(DSPT_HDT_RX3);
3328	case_DBG_SEL(DSPT_HDT_RX4);
3329	case_DBG_SEL(DSPT_HDT_RX5);
3330	case_DBG_SEL(DSPT_CDT_RX_P0);
3331	case_DBG_SEL(DSPT_CDT_RX_P0_0);
3332	case_DBG_SEL(DSPT_CDT_RX_P0_1);
3333	case_DBG_SEL(DSPT_CDT_RX_P0_2);
3334	case_DBG_SEL(DSPT_CDT_RX_P1);
3335	case_DBG_SEL(DSPT_STF_CTRL);
3336	case_DBG_SEL(DSPT_ADDR_CTRL);
3337	case_DBG_SEL(DSPT_WDE_INTF);
3338	case_DBG_SEL(DSPT_PLE_INTF);
3339	case_DBG_SEL(DSPT_FLOW_CTRL);
3340	case_DBG_SEL(PCIE_TXDMA);
3341	case_DBG_SEL(PCIE_RXDMA);
3342	case_DBG_SEL(PCIE_CVT);
3343	case_DBG_SEL(PCIE_CXPL);
3344	case_DBG_SEL(PCIE_IO);
3345	case_DBG_SEL(PCIE_MISC);
3346	case_DBG_SEL(PCIE_MISC2);
3347	}
3348
3349#undef case_DBG_SEL
3350
3351	p += scnprintf(p, end - p, "Sel addr = 0x%X\n", info->sel_addr);
3352	p += scnprintf(p, end - p, "Read addr = 0x%X\n", info->rd_addr);
3353
3354	for (i = info->srt; i <= info->end; i++) {
3355		switch (info->sel_byte) {
3356		case 1:
3357		default:
3358			rtw89_write8_mask(rtwdev, info->sel_addr,
3359					  info->sel_msk, i);
3360			p += scnprintf(p, end - p, "0x%02X: ", i);
3361			break;
3362		case 2:
3363			rtw89_write16_mask(rtwdev, info->sel_addr,
3364					   info->sel_msk, i);
3365			p += scnprintf(p, end - p, "0x%04X: ", i);
3366			break;
3367		case 4:
3368			rtw89_write32_mask(rtwdev, info->sel_addr,
3369					   info->sel_msk, i);
3370			p += scnprintf(p, end - p, "0x%04X: ", i);
3371			break;
3372		}
3373
3374		udelay(10);
3375
3376		switch (info->rd_byte) {
3377		case 1:
3378		default:
3379			val8 = rtw89_read8_mask(rtwdev,
3380						info->rd_addr, info->rd_msk);
3381			p += scnprintf(p, end - p, "0x%02X\n", val8);
3382			break;
3383		case 2:
3384			val16 = rtw89_read16_mask(rtwdev,
3385						  info->rd_addr, info->rd_msk);
3386			p += scnprintf(p, end - p, "0x%04X\n", val16);
3387			break;
3388		case 4:
3389			val32 = rtw89_read32_mask(rtwdev,
3390						  info->rd_addr, info->rd_msk);
3391			p += scnprintf(p, end - p, "0x%08X\n", val32);
3392			break;
3393		}
3394	}
3395
3396out:
3397	return p - buf;
3398}
3399
3400static int rtw89_debug_mac_dump_dbg_port(struct rtw89_dev *rtwdev,
3401					 char *buf, size_t bufsz)
3402{
3403	char *p = buf, *end = buf + bufsz;
3404	ssize_t n;
3405	u32 sel;
3406
3407	for (sel = RTW89_DBG_PORT_SEL_PTCL_C0;
3408	     sel < RTW89_DBG_PORT_SEL_LAST; sel++) {
3409		if (!is_dbg_port_valid(rtwdev, sel))
3410			continue;
3411		n = rtw89_debug_mac_dbg_port_dump(rtwdev, p, end - p, sel);
3412		if (n < 0) {
3413			rtw89_err(rtwdev,
3414				  "failed to dump debug port %d\n", sel);
3415			break;
3416		}
3417		p += n;
3418	}
3419
3420	return p - buf;
3421}
3422
3423static ssize_t
3424rtw89_debug_priv_mac_dbg_port_dump_get(struct rtw89_dev *rtwdev,
3425				       struct rtw89_debugfs_priv *debugfs_priv,
3426				       char *buf, size_t bufsz)
3427{
3428	char *p = buf, *end = buf + bufsz;
3429
3430	if (debugfs_priv->dbgpkg_en.ss_dbg)
3431		p += rtw89_debug_mac_dump_ss_dbg(rtwdev, p, end - p);
3432	if (debugfs_priv->dbgpkg_en.dle_dbg)
3433		p += rtw89_debug_mac_dump_dle_dbg(rtwdev, p, end - p);
3434	if (debugfs_priv->dbgpkg_en.dmac_dbg)
3435		p += rtw89_debug_mac_dump_dmac_dbg(rtwdev, p, end - p);
3436	if (debugfs_priv->dbgpkg_en.cmac_dbg)
3437		p += rtw89_debug_mac_dump_cmac_dbg(rtwdev, p, end - p);
3438	if (debugfs_priv->dbgpkg_en.dbg_port)
3439		p += rtw89_debug_mac_dump_dbg_port(rtwdev, p, end - p);
3440
3441	return p - buf;
3442};
3443
3444static u8 *rtw89_hex2bin(struct rtw89_dev *rtwdev, const char *buf, size_t count)
3445{
3446	u8 *bin;
3447	int num;
3448	int err = 0;
3449
3450	num = count / 2;
3451	bin = kmalloc(num, GFP_KERNEL);
3452	if (!bin) {
3453		err = -EFAULT;
3454		goto out;
3455	}
3456
3457	if (hex2bin(bin, buf, num)) {
3458		rtw89_info(rtwdev, "valid format: H1H2H3...\n");
3459		kfree(bin);
3460		err = -EINVAL;
3461	}
3462
3463out:
3464	return err ? ERR_PTR(err) : bin;
3465}
3466
3467static ssize_t rtw89_debug_priv_send_h2c_set(struct rtw89_dev *rtwdev,
3468					     struct rtw89_debugfs_priv *debugfs_priv,
3469					     const char *buf, size_t count)
3470{
3471	u8 *h2c;
3472	int ret;
3473	u16 h2c_len = count / 2;
3474
3475	h2c = rtw89_hex2bin(rtwdev, buf, count);
3476	if (IS_ERR(h2c))
3477		return -EFAULT;
3478
3479	ret = rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
3480
3481	kfree(h2c);
3482
3483	return ret ? ret : count;
3484}
3485
3486static ssize_t
3487rtw89_debug_priv_early_h2c_get(struct rtw89_dev *rtwdev,
3488			       struct rtw89_debugfs_priv *debugfs_priv,
3489			       char *buf, size_t bufsz)
3490{
3491	struct rtw89_early_h2c *early_h2c;
3492	char *p = buf, *end = buf + bufsz;
3493	int seq = 0;
3494
3495	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3496
3497	list_for_each_entry(early_h2c, &rtwdev->early_h2c_list, list)
3498		p += scnprintf(p, end - p, "%d: %*ph\n", ++seq,
3499			       early_h2c->h2c_len, early_h2c->h2c);
3500
3501	return p - buf;
3502}
3503
3504static ssize_t
3505rtw89_debug_priv_early_h2c_set(struct rtw89_dev *rtwdev,
3506			       struct rtw89_debugfs_priv *debugfs_priv,
3507			       const char *buf, size_t count)
3508{
3509	struct rtw89_early_h2c *early_h2c;
3510	u8 *h2c;
3511	u16 h2c_len = count / 2;
3512
3513	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3514
3515	h2c = rtw89_hex2bin(rtwdev, buf, count);
3516	if (IS_ERR(h2c))
3517		return -EFAULT;
3518
3519	if (h2c_len >= 2 && h2c[0] == 0x00 && h2c[1] == 0x00) {
3520		kfree(h2c);
3521		rtw89_fw_free_all_early_h2c(rtwdev);
3522		goto out;
3523	}
3524
3525	early_h2c = kmalloc(sizeof(*early_h2c), GFP_KERNEL);
3526	if (!early_h2c) {
3527		kfree(h2c);
3528		return -EFAULT;
3529	}
3530
3531	early_h2c->h2c = h2c;
3532	early_h2c->h2c_len = h2c_len;
3533
3534	list_add_tail(&early_h2c->list, &rtwdev->early_h2c_list);
3535
3536out:
3537	return count;
3538}
3539
3540static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
3541{
3542	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
3543	struct rtw89_cpuio_ctrl ctrl_para = {0};
3544	u16 pkt_id;
3545	int ret;
3546
3547	rtw89_leave_ps_mode(rtwdev);
3548
3549	ret = mac->dle_buf_req(rtwdev, 0x20, true, &pkt_id);
3550	if (ret)
3551		return ret;
3552
3553	/* intentionally, enqueue two pkt, but has only one pkt id */
3554	ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
3555	ctrl_para.start_pktid = pkt_id;
3556	ctrl_para.end_pktid = pkt_id;
3557	ctrl_para.pkt_num = 1; /* start from 0 */
3558	ctrl_para.dst_pid = WDE_DLE_PORT_ID_WDRLS;
3559	ctrl_para.dst_qid = WDE_DLE_QUEID_NO_REPORT;
3560
3561	if (mac->set_cpuio(rtwdev, &ctrl_para, true))
3562		return -EFAULT;
3563
3564	return 0;
3565}
3566
3567static int rtw89_dbg_trigger_mac_error_ax(struct rtw89_dev *rtwdev)
3568{
3569	u16 val16;
3570	u8 val8;
3571	int ret;
3572
3573	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL);
3574	if (ret)
3575		return ret;
3576
3577	val8 = rtw89_read8(rtwdev, R_AX_CMAC_FUNC_EN);
3578	rtw89_write8(rtwdev, R_AX_CMAC_FUNC_EN, val8 & ~B_AX_TMAC_EN);
3579	mdelay(1);
3580	rtw89_write8(rtwdev, R_AX_CMAC_FUNC_EN, val8);
3581
3582	val16 = rtw89_read16(rtwdev, R_AX_PTCL_IMR0);
3583	rtw89_write16(rtwdev, R_AX_PTCL_IMR0, val16 | B_AX_F2PCMD_EMPTY_ERR_INT_EN);
3584	rtw89_write16(rtwdev, R_AX_PTCL_IMR0, val16);
3585
3586	return 0;
3587}
3588
3589static int rtw89_dbg_trigger_mac_error_be(struct rtw89_dev *rtwdev)
3590{
3591	int ret;
3592
3593	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL);
3594	if (ret)
3595		return ret;
3596
3597	rtw89_write32_set(rtwdev, R_BE_CMAC_FW_TRIGGER_IDCT_ISR,
3598			  B_BE_CMAC_FW_TRIG_IDCT | B_BE_CMAC_FW_ERR_IDCT_IMR);
3599
3600	return 0;
3601}
3602
3603static int rtw89_dbg_trigger_mac_error(struct rtw89_dev *rtwdev)
3604{
3605	const struct rtw89_chip_info *chip = rtwdev->chip;
3606
3607	rtw89_leave_ps_mode(rtwdev);
3608
3609	switch (chip->chip_gen) {
3610	case RTW89_CHIP_AX:
3611		return rtw89_dbg_trigger_mac_error_ax(rtwdev);
3612	case RTW89_CHIP_BE:
3613		return rtw89_dbg_trigger_mac_error_be(rtwdev);
3614	default:
3615		return -EOPNOTSUPP;
3616	}
3617}
3618
3619static ssize_t
3620rtw89_debug_priv_fw_crash_get(struct rtw89_dev *rtwdev,
3621			      struct rtw89_debugfs_priv *debugfs_priv,
3622			      char *buf, size_t bufsz)
3623{
3624	char *p = buf, *end = buf + bufsz;
3625
3626	p += scnprintf(p, end - p, "%d\n",
3627		       test_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags));
3628	return p - buf;
3629}
3630
3631enum rtw89_dbg_crash_simulation_type {
3632	RTW89_DBG_SIM_CPU_EXCEPTION = 1,
3633	RTW89_DBG_SIM_CTRL_ERROR = 2,
3634	RTW89_DBG_SIM_MAC_ERROR = 3,
3635};
3636
3637static ssize_t
3638rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev,
3639			      struct rtw89_debugfs_priv *debugfs_priv,
3640			      const char *buf, size_t count)
3641{
3642	int (*sim)(struct rtw89_dev *rtwdev);
3643	bool announce = true;
3644	u8 crash_type;
3645	int ret;
3646
3647	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3648
3649	ret = kstrtou8(buf, 0, &crash_type);
3650	if (ret)
3651		return -EINVAL;
3652
3653	switch (crash_type) {
3654	case RTW89_DBG_SIM_CPU_EXCEPTION:
3655		if (!RTW89_CHK_FW_FEATURE_GROUP(CRASH_TRIGGER, &rtwdev->fw))
3656			return -EOPNOTSUPP;
3657		sim = rtw89_fw_h2c_trigger_cpu_exception;
3658		break;
3659	case RTW89_DBG_SIM_CTRL_ERROR:
3660		sim = rtw89_dbg_trigger_ctrl_error;
3661		break;
3662	case RTW89_DBG_SIM_MAC_ERROR:
3663		sim = rtw89_dbg_trigger_mac_error;
3664
3665		/* Driver SER flow won't get involved; only FW will. */
3666		announce = false;
3667		break;
3668	default:
3669		return -EINVAL;
3670	}
3671
3672	if (announce)
3673		set_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
3674
3675	ret = sim(rtwdev);
3676
3677	if (ret)
3678		return ret;
3679
3680	return count;
3681}
3682
3683static ssize_t rtw89_debug_priv_btc_info_get(struct rtw89_dev *rtwdev,
3684					     struct rtw89_debugfs_priv *debugfs_priv,
3685					     char *buf, size_t bufsz)
3686{
3687	return rtw89_btc_dump_info(rtwdev, buf, bufsz);
3688}
3689
3690static ssize_t rtw89_debug_priv_btc_manual_set(struct rtw89_dev *rtwdev,
3691					       struct rtw89_debugfs_priv *debugfs_priv,
3692					       const char *buf, size_t count)
3693{
3694	struct rtw89_btc *btc = &rtwdev->btc;
3695	const struct rtw89_btc_ver *ver = btc->ver;
3696	int ret;
3697
3698	ret = kstrtobool(buf, &btc->manual_ctrl);
3699	if (ret)
3700		return ret;
3701
3702	if (ver->fcxctrl == 7)
3703		btc->ctrl.ctrl_v7.manual = btc->manual_ctrl;
3704	else
3705		btc->ctrl.ctrl.manual = btc->manual_ctrl;
3706
3707	return count;
3708}
3709
3710static ssize_t rtw89_debug_priv_fw_log_manual_set(struct rtw89_dev *rtwdev,
3711						  struct rtw89_debugfs_priv *debugfs_priv,
3712						  const char *buf, size_t count)
3713{
3714	struct rtw89_fw_log *log = &rtwdev->fw.log;
3715	bool fw_log_manual;
3716
3717	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3718
3719	if (kstrtobool(buf, &fw_log_manual))
3720		goto out;
3721
3722	log->enable = fw_log_manual;
3723	if (log->enable)
3724		rtw89_fw_log_prepare(rtwdev);
3725	rtw89_fw_h2c_fw_log(rtwdev, fw_log_manual);
3726out:
3727	return count;
3728}
3729
3730static int rtw89_sta_link_info_get_iter(struct rtw89_dev *rtwdev,
3731					char *buf, size_t bufsz,
3732					struct rtw89_sta_link *rtwsta_link)
3733{
3734	static const char * const he_gi_str[] = {
3735		[NL80211_RATE_INFO_HE_GI_0_8] = "0.8",
3736		[NL80211_RATE_INFO_HE_GI_1_6] = "1.6",
3737		[NL80211_RATE_INFO_HE_GI_3_2] = "3.2",
3738	};
3739	static const char * const eht_gi_str[] = {
3740		[NL80211_RATE_INFO_EHT_GI_0_8] = "0.8",
3741		[NL80211_RATE_INFO_EHT_GI_1_6] = "1.6",
3742		[NL80211_RATE_INFO_EHT_GI_3_2] = "3.2",
3743	};
3744	struct rate_info *rate = &rtwsta_link->ra_report.txrate;
3745	struct ieee80211_rx_status *status = &rtwsta_link->rx_status;
3746	struct rtw89_hal *hal = &rtwdev->hal;
3747	u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
3748	bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity;
3749	struct ieee80211_link_sta *link_sta;
3750	char *p = buf, *end = buf + bufsz;
3751	u8 evm_min, evm_max, evm_1ss;
3752	u16 max_rc_amsdu_len;
3753	u8 rssi;
3754	u8 snr;
3755	int i;
3756
3757	rcu_read_lock();
3758
3759	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
3760	max_rc_amsdu_len = link_sta->agg.max_rc_amsdu_len;
3761
3762	rcu_read_unlock();
3763
3764	p += scnprintf(p, end - p, "TX rate [%u, %u]: ", rtwsta_link->mac_id,
3765		       rtwsta_link->link_id);
3766
3767	if (rate->flags & RATE_INFO_FLAGS_MCS)
3768		p += scnprintf(p, end - p, "HT MCS-%d%s", rate->mcs,
3769			       rate->flags & RATE_INFO_FLAGS_SHORT_GI ? " SGI" : "");
3770	else if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
3771		p += scnprintf(p, end - p, "VHT %dSS MCS-%d%s", rate->nss,
3772			       rate->mcs,
3773			       rate->flags & RATE_INFO_FLAGS_SHORT_GI ? " SGI" : "");
3774	else if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
3775		p += scnprintf(p, end - p, "HE %dSS MCS-%d GI:%s", rate->nss,
3776			       rate->mcs,
3777			       rate->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ?
3778			       he_gi_str[rate->he_gi] : "N/A");
3779	else if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
3780		p += scnprintf(p, end - p, "EHT %dSS MCS-%d GI:%s", rate->nss,
3781			       rate->mcs,
3782			       rate->eht_gi < ARRAY_SIZE(eht_gi_str) ?
3783			       eht_gi_str[rate->eht_gi] : "N/A");
3784	else
3785		p += scnprintf(p, end - p, "Legacy %d", rate->legacy);
3786	p += scnprintf(p, end - p, "%s",
3787		       rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : "");
3788	p += scnprintf(p, end - p, " BW:%u",
3789		       rtw89_rate_info_bw_to_mhz(rate->bw));
3790	p += scnprintf(p, end - p, " (hw_rate=0x%x)",
3791		       rtwsta_link->ra_report.hw_rate);
3792	p += scnprintf(p, end - p, " ==> agg_wait=%d (%d)\n",
3793		       rtwsta_link->max_agg_wait,
3794		       max_rc_amsdu_len);
3795
3796	p += scnprintf(p, end - p, "RX rate [%u, %u]: ", rtwsta_link->mac_id,
3797		       rtwsta_link->link_id);
3798
3799	switch (status->encoding) {
3800	case RX_ENC_LEGACY:
3801		p += scnprintf(p, end - p, "Legacy %d", status->rate_idx +
3802			       (status->band != NL80211_BAND_2GHZ ? 4 : 0));
3803		break;
3804	case RX_ENC_HT:
3805		p += scnprintf(p, end - p, "HT MCS-%d%s", status->rate_idx,
3806			       status->enc_flags & RX_ENC_FLAG_SHORT_GI ? " SGI" : "");
3807		break;
3808	case RX_ENC_VHT:
3809		p += scnprintf(p, end - p, "VHT %dSS MCS-%d%s", status->nss,
3810			       status->rate_idx,
3811			       status->enc_flags & RX_ENC_FLAG_SHORT_GI ? " SGI" : "");
3812		break;
3813	case RX_ENC_HE:
3814		p += scnprintf(p, end - p, "HE %dSS MCS-%d GI:%s",
3815			       status->nss, status->rate_idx,
3816			       status->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ?
3817			       he_gi_str[status->he_gi] : "N/A");
3818		break;
3819	case RX_ENC_EHT:
3820		p += scnprintf(p, end - p, "EHT %dSS MCS-%d GI:%s",
3821			       status->nss, status->rate_idx,
3822			       status->eht.gi < ARRAY_SIZE(eht_gi_str) ?
3823			       eht_gi_str[status->eht.gi] : "N/A");
3824		break;
3825	}
3826	p += scnprintf(p, end - p, " BW:%u",
3827		       rtw89_rate_info_bw_to_mhz(status->bw));
3828	p += scnprintf(p, end - p, " (hw_rate=0x%x)\n",
3829		       rtwsta_link->rx_hw_rate);
3830
3831	rssi = ewma_rssi_read(&rtwsta_link->avg_rssi);
3832	p += scnprintf(p, end - p, "RSSI: %d dBm (raw=%d, prev=%d) [",
3833		       RTW89_RSSI_RAW_TO_DBM(rssi), rssi,
3834		       rtwsta_link->prev_rssi);
3835	for (i = 0; i < ant_num; i++) {
3836		rssi = ewma_rssi_read(&rtwsta_link->rssi[i]);
3837		p += scnprintf(p, end - p, "%d%s%s",
3838			       RTW89_RSSI_RAW_TO_DBM(rssi),
3839			       ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "",
3840			       i + 1 == ant_num ? "" : ", ");
3841	}
3842	p += scnprintf(p, end - p, "]\n");
3843
3844	evm_1ss = ewma_evm_read(&rtwsta_link->evm_1ss);
3845	p += scnprintf(p, end - p, "EVM: [%2u.%02u, ", evm_1ss >> 2,
3846		       (evm_1ss & 0x3) * 25);
3847	for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) {
3848		evm_min = ewma_evm_read(&rtwsta_link->evm_min[i]);
3849		evm_max = ewma_evm_read(&rtwsta_link->evm_max[i]);
3850
3851		p += scnprintf(p, end - p, "%s(%2u.%02u, %2u.%02u)",
3852			       i == 0 ? "" : " ",
3853			       evm_min >> 2, (evm_min & 0x3) * 25,
3854			       evm_max >> 2, (evm_max & 0x3) * 25);
3855	}
3856	p += scnprintf(p, end - p, "]\t");
3857
3858	snr = ewma_snr_read(&rtwsta_link->avg_snr);
3859	p += scnprintf(p, end - p, "SNR: %u\n", snr);
3860
3861	return p - buf;
3862}
3863
3864static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
3865{
3866	struct rtw89_debugfs_iter_data *iter_data =
3867		(struct rtw89_debugfs_iter_data *)data;
3868	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
3869	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
3870	struct rtw89_sta_link *rtwsta_link;
3871	size_t bufsz = iter_data->bufsz;
3872	char *buf = iter_data->buf;
3873	char *p = buf, *end = buf + bufsz;
3874	unsigned int link_id;
3875
3876	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
3877		p += rtw89_sta_link_info_get_iter(rtwdev, p, end - p, rtwsta_link);
3878
3879	rtw89_debugfs_iter_data_next(iter_data, p, end - p, p - buf);
3880}
3881
3882static int
3883rtw89_debug_append_rx_rate(char *buf, size_t bufsz, struct rtw89_pkt_stat *pkt_stat,
3884			   enum rtw89_hw_rate first_rate, int len)
3885{
3886	char *p = buf, *end = buf + bufsz;
3887	int i;
3888
3889	for (i = 0; i < len; i++)
3890		p += scnprintf(p, end - p, "%s%u", i == 0 ? "" : ", ",
3891			       pkt_stat->rx_rate_cnt[first_rate + i]);
3892
3893	return p - buf;
3894}
3895
3896#define FIRST_RATE_SAME(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_ ## rate}
3897#define FIRST_RATE_ENUM(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_V1_ ## rate}
3898#define FIRST_RATE_GEV1(rate) {RTW89_HW_RATE_INVAL, RTW89_HW_RATE_V1_ ## rate}
3899
3900static const struct rtw89_rx_rate_cnt_info {
3901	enum rtw89_hw_rate first_rate[RTW89_CHIP_GEN_NUM];
3902	int len;
3903	int ext;
3904	const char *rate_mode;
3905} rtw89_rx_rate_cnt_infos[] = {
3906	{FIRST_RATE_SAME(CCK1), 4, 0, "Legacy:"},
3907	{FIRST_RATE_SAME(OFDM6), 8, 0, "OFDM:"},
3908	{FIRST_RATE_ENUM(MCS0), 8, 0, "HT 0:"},
3909	{FIRST_RATE_ENUM(MCS8), 8, 0, "HT 1:"},
3910	{FIRST_RATE_ENUM(VHT_NSS1_MCS0), 10, 2, "VHT 1SS:"},
3911	{FIRST_RATE_ENUM(VHT_NSS2_MCS0), 10, 2, "VHT 2SS:"},
3912	{FIRST_RATE_ENUM(HE_NSS1_MCS0), 12, 0, "HE 1SS:"},
3913	{FIRST_RATE_ENUM(HE_NSS2_MCS0), 12, 0, "HE 2SS:"},
3914	{FIRST_RATE_GEV1(EHT_NSS1_MCS0), 14, 2, "EHT 1SS:"},
3915	{FIRST_RATE_GEV1(EHT_NSS2_MCS0), 14, 0, "EHT 2SS:"},
3916};
3917
3918static ssize_t rtw89_debug_priv_phy_info_get(struct rtw89_dev *rtwdev,
3919					     struct rtw89_debugfs_priv *debugfs_priv,
3920					     char *buf, size_t bufsz)
3921{
3922	struct rtw89_traffic_stats *stats = &rtwdev->stats;
3923	struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat;
3924	const struct rtw89_chip_info *chip = rtwdev->chip;
3925	struct rtw89_debugfs_iter_data iter_data;
3926	const struct rtw89_rx_rate_cnt_info *info;
3927	struct rtw89_hal *hal = &rtwdev->hal;
3928	char *p = buf, *end = buf + bufsz;
3929	enum rtw89_hw_rate first_rate;
3930	u8 rssi;
3931	int i;
3932
3933	rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi);
3934
3935	p += scnprintf(p, end - p, "TP TX: %u [%u] Mbps (lv: %d",
3936		       stats->tx_throughput, stats->tx_throughput_raw,
3937		       stats->tx_tfc_lv);
3938	if (hal->thermal_prot_lv)
3939		p += scnprintf(p, end - p, ", duty: %d%%",
3940			       100 - hal->thermal_prot_lv * RTW89_THERMAL_PROT_STEP);
3941	p += scnprintf(p, end - p, "), RX: %u [%u] Mbps (lv: %d)\n",
3942		       stats->rx_throughput, stats->rx_throughput_raw,
3943		       stats->rx_tfc_lv);
3944	p += scnprintf(p, end - p, "Beacon: %u (%d dBm), TF: %u\n",
3945		       pkt_stat->beacon_nr,
3946		       RTW89_RSSI_RAW_TO_DBM(rssi), stats->rx_tf_periodic);
3947	p += scnprintf(p, end - p, "Avg packet length: TX=%u, RX=%u\n",
3948		       stats->tx_avg_len,
3949		       stats->rx_avg_len);
3950
3951	p += scnprintf(p, end - p, "RX count:\n");
3952
3953	for (i = 0; i < ARRAY_SIZE(rtw89_rx_rate_cnt_infos); i++) {
3954		info = &rtw89_rx_rate_cnt_infos[i];
3955		first_rate = info->first_rate[chip->chip_gen];
3956		if (first_rate >= RTW89_HW_RATE_NR)
3957			continue;
3958
3959		p += scnprintf(p, end - p, "%10s [", info->rate_mode);
3960		p += rtw89_debug_append_rx_rate(p, end - p, pkt_stat,
3961						first_rate, info->len);
3962		if (info->ext) {
3963			p += scnprintf(p, end - p, "][");
3964			p += rtw89_debug_append_rx_rate(p, end - p, pkt_stat,
3965							first_rate + info->len, info->ext);
3966		}
3967		p += scnprintf(p, end - p, "]\n");
3968	}
3969
3970	rtw89_debugfs_iter_data_setup(&iter_data, p, end - p);
3971	ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_info_get_iter, &iter_data);
3972	p += iter_data.written_sz;
3973
3974	return p - buf;
3975}
3976
3977static int rtw89_dump_addr_cam(struct rtw89_dev *rtwdev,
3978			       char *buf, size_t bufsz,
3979			       struct rtw89_addr_cam_entry *addr_cam)
3980{
3981	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
3982	const struct rtw89_sec_cam_entry *sec_entry;
3983	char *p = buf, *end = buf + bufsz;
3984	u8 sec_cam_idx;
3985	int i;
3986
3987	p += scnprintf(p, end - p, "\taddr_cam_idx=%u\n",
3988		       addr_cam->addr_cam_idx);
3989	p += scnprintf(p, end - p, "\t-> bssid_cam_idx=%u\n",
3990		       addr_cam->bssid_cam_idx);
3991	p += scnprintf(p, end - p, "\tsec_cam_bitmap=%*ph\n",
3992		       (int)sizeof(addr_cam->sec_cam_map),
3993		       addr_cam->sec_cam_map);
3994	for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) {
3995		sec_cam_idx = addr_cam->sec_ent[i];
3996		sec_entry = cam_info->sec_entries[sec_cam_idx];
3997		if (!sec_entry)
3998			continue;
3999		p += scnprintf(p, end - p, "\tsec[%d]: sec_cam_idx %u", i,
4000			       sec_entry->sec_cam_idx);
4001		if (sec_entry->ext_key)
4002			p += scnprintf(p, end - p, ", %u",
4003				       sec_entry->sec_cam_idx + 1);
4004		p += scnprintf(p, end - p, "\n");
4005	}
4006
4007	return p - buf;
4008}
4009
4010__printf(4, 5)
4011static int rtw89_dump_pkt_offload(char *buf, size_t bufsz, struct list_head *pkt_list,
4012				  const char *fmt, ...)
4013{
4014	char *p = buf, *end = buf + bufsz;
4015	struct rtw89_pktofld_info *info;
4016	struct va_format vaf;
4017	va_list args;
4018
4019	if (list_empty(pkt_list))
4020		return 0;
4021
4022	va_start(args, fmt);
4023	vaf.va = &args;
4024	vaf.fmt = fmt;
4025
4026	p += scnprintf(p, end - p, "%pV", &vaf);
4027
4028	va_end(args);
4029
4030	list_for_each_entry(info, pkt_list, list)
4031		p += scnprintf(p, end - p, "%d ", info->id);
4032
4033	p += scnprintf(p, end - p, "\n");
4034
4035	return p - buf;
4036}
4037
4038static int rtw89_vif_link_ids_get(struct rtw89_dev *rtwdev,
4039				  char *buf, size_t bufsz, u8 *mac,
4040				  struct rtw89_vif_link *rtwvif_link,
4041				  bool designated)
4042{
4043	struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
4044	char *p = buf, *end = buf + bufsz;
4045
4046	p += scnprintf(p, end - p, "    [%u] %pM\n", rtwvif_link->mac_id,
4047		       rtwvif_link->mac_addr);
4048	p += scnprintf(p, end - p, "\tlink_id=%u%s\n", rtwvif_link->link_id,
4049		       designated ? " (*)" : "");
4050	p += scnprintf(p, end - p, "\tbssid_cam_idx=%u\n",
4051		       bssid_cam->bssid_cam_idx);
4052	p += rtw89_dump_addr_cam(rtwdev, p, end - p, &rtwvif_link->addr_cam);
4053	p += rtw89_dump_pkt_offload(p, end - p, &rtwvif_link->general_pkt_list,
4054				    "\tpkt_ofld[GENERAL]: ");
4055
4056	return p - buf;
4057}
4058
4059static
4060void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
4061{
4062	struct rtw89_debugfs_iter_data *iter_data =
4063		(struct rtw89_debugfs_iter_data *)data;
4064	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
4065	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
4066	struct rtw89_vif_link *designated_link;
4067	struct rtw89_vif_link *rtwvif_link;
4068	size_t bufsz = iter_data->bufsz;
4069	char *buf = iter_data->buf;
4070	char *p = buf, *end = buf + bufsz;
4071	unsigned int link_id;
4072
4073	designated_link = rtw89_get_designated_link(rtwvif);
4074
4075	p += scnprintf(p, end - p, "VIF %pM\n", rtwvif->mac_addr);
4076	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
4077		p += rtw89_vif_link_ids_get(rtwdev, p, end - p, mac, rtwvif_link,
4078					    rtwvif_link == designated_link);
4079
4080	rtw89_debugfs_iter_data_next(iter_data, p, end - p, p - buf);
4081}
4082
4083static int rtw89_dump_ba_cam(struct rtw89_dev *rtwdev,
4084			     char *buf, size_t bufsz,
4085			     struct rtw89_sta_link *rtwsta_link)
4086{
4087	struct rtw89_ba_cam_entry *entry;
4088	char *p = buf, *end = buf + bufsz;
4089	bool first = true;
4090
4091	list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) {
4092		if (first) {
4093			p += scnprintf(p, end - p, "\tba_cam ");
4094			first = false;
4095		} else {
4096			p += scnprintf(p, end - p, ", ");
4097		}
4098		p += scnprintf(p, end - p, "tid[%u]=%d", entry->tid,
4099			       (int)(entry - rtwdev->cam_info.ba_cam_entry));
4100	}
4101	p += scnprintf(p, end - p, "\n");
4102
4103	return p - buf;
4104}
4105
4106static int rtw89_sta_link_ids_get(struct rtw89_dev *rtwdev,
4107				  char *buf, size_t bufsz,
4108				  struct rtw89_sta_link *rtwsta_link,
4109				  bool designated)
4110{
4111	struct ieee80211_link_sta *link_sta;
4112	char *p = buf, *end = buf + bufsz;
4113
4114	rcu_read_lock();
4115
4116	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
4117
4118	p += scnprintf(p, end - p, "    [%u] %pM\n", rtwsta_link->mac_id,
4119		       link_sta->addr);
4120
4121	rcu_read_unlock();
4122
4123	p += scnprintf(p, end - p, "\tlink_id=%u%s\n", rtwsta_link->link_id,
4124		       designated ? " (*)" : "");
4125	p += rtw89_dump_addr_cam(rtwdev, p, end - p, &rtwsta_link->addr_cam);
4126	p += rtw89_dump_ba_cam(rtwdev, p, end - p, rtwsta_link);
4127
4128	return p - buf;
4129}
4130
4131static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
4132{
4133	struct rtw89_debugfs_iter_data *iter_data =
4134		(struct rtw89_debugfs_iter_data *)data;
4135	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
4136	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
4137	struct rtw89_sta_link *designated_link;
4138	struct rtw89_sta_link *rtwsta_link;
4139	size_t bufsz = iter_data->bufsz;
4140	char *buf = iter_data->buf;
4141	char *p = buf, *end = buf + bufsz;
4142	unsigned int link_id;
4143
4144	designated_link = rtw89_get_designated_link(rtwsta);
4145
4146	p += scnprintf(p, end - p, "STA %pM %s\n", sta->addr,
4147		       sta->tdls ? "(TDLS)" : "");
4148	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
4149		p += rtw89_sta_link_ids_get(rtwdev, p, end - p, rtwsta_link,
4150					    rtwsta_link == designated_link);
4151
4152	rtw89_debugfs_iter_data_next(iter_data, p, end - p, p - buf);
4153}
4154
4155static ssize_t rtw89_debug_priv_stations_get(struct rtw89_dev *rtwdev,
4156					     struct rtw89_debugfs_priv *debugfs_priv,
4157					     char *buf, size_t bufsz)
4158{
4159	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
4160	struct rtw89_debugfs_iter_data iter_data;
4161	char *p = buf, *end = buf + bufsz;
4162	u8 idx;
4163
4164	lockdep_assert_wiphy(rtwdev->hw->wiphy);
4165
4166	p += scnprintf(p, end - p, "map:\n");
4167	p += scnprintf(p, end - p, "\tmac_id:    %*ph\n",
4168		       (int)sizeof(rtwdev->mac_id_map),
4169		       rtwdev->mac_id_map);
4170	p += scnprintf(p, end - p, "\taddr_cam:  %*ph\n",
4171		       (int)sizeof(cam_info->addr_cam_map),
4172		       cam_info->addr_cam_map);
4173	p += scnprintf(p, end - p, "\tbssid_cam: %*ph\n",
4174		       (int)sizeof(cam_info->bssid_cam_map),
4175		       cam_info->bssid_cam_map);
4176	p += scnprintf(p, end - p, "\tsec_cam:   %*ph\n",
4177		       (int)sizeof(cam_info->sec_cam_map),
4178		       cam_info->sec_cam_map);
4179	p += scnprintf(p, end - p, "\tba_cam:    %*ph\n",
4180		       (int)sizeof(cam_info->ba_cam_map),
4181		       cam_info->ba_cam_map);
4182	p += scnprintf(p, end - p, "\tpkt_ofld:  %*ph\n",
4183		       (int)sizeof(rtwdev->pkt_offload),
4184		       rtwdev->pkt_offload);
4185
4186	for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) {
4187		if (!(rtwdev->chip->support_bands & BIT(idx)))
4188			continue;
4189		p += rtw89_dump_pkt_offload(p, end - p, &rtwdev->scan_info.pkt_list[idx],
4190					    "\t\t[SCAN %u]: ", idx);
4191	}
4192
4193	rtw89_debugfs_iter_data_setup(&iter_data, p, end - p);
4194	ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
4195		IEEE80211_IFACE_ITER_NORMAL, rtw89_vif_ids_get_iter, &iter_data);
4196	p += iter_data.written_sz;
4197
4198	rtw89_debugfs_iter_data_setup(&iter_data, p, end - p);
4199	ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_ids_get_iter, &iter_data);
4200	p += iter_data.written_sz;
4201
4202	return p - buf;
4203}
4204
4205static void rtw89_debug_disable_dm_cfg_bmap(struct rtw89_dev *rtwdev, u32 new)
4206{
4207	struct rtw89_hal *hal = &rtwdev->hal;
4208	u32 old = hal->disabled_dm_bitmap;
4209
4210	if (new == old)
4211		return;
4212
4213	hal->disabled_dm_bitmap = new;
4214
4215	rtw89_debug(rtwdev, RTW89_DBG_STATE, "Disable DM: 0x%x -> 0x%x\n", old, new);
4216}
4217
4218static void rtw89_debug_disable_dm_set_flag(struct rtw89_dev *rtwdev, u8 flag)
4219{
4220	struct rtw89_hal *hal = &rtwdev->hal;
4221	u32 cur = hal->disabled_dm_bitmap;
4222
4223	rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur | BIT(flag));
4224}
4225
4226static void rtw89_debug_disable_dm_clr_flag(struct rtw89_dev *rtwdev, u8 flag)
4227{
4228	struct rtw89_hal *hal = &rtwdev->hal;
4229	u32 cur = hal->disabled_dm_bitmap;
4230
4231	rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur & ~BIT(flag));
4232}
4233
4234#define DM_INFO(type) {RTW89_DM_ ## type, #type}
4235
4236static const struct rtw89_disabled_dm_info {
4237	enum rtw89_dm_type type;
4238	const char *name;
4239} rtw89_disabled_dm_infos[] = {
4240	DM_INFO(DYNAMIC_EDCCA),
4241	DM_INFO(THERMAL_PROTECT),
4242	DM_INFO(TAS),
4243	DM_INFO(MLO),
4244};
4245
4246static ssize_t
4247rtw89_debug_priv_disable_dm_get(struct rtw89_dev *rtwdev,
4248				struct rtw89_debugfs_priv *debugfs_priv,
4249				char *buf, size_t bufsz)
4250{
4251	const struct rtw89_disabled_dm_info *info;
4252	struct rtw89_hal *hal = &rtwdev->hal;
4253	char *p = buf, *end = buf + bufsz;
4254	u32 disabled;
4255	int i;
4256
4257	p += scnprintf(p, end - p, "Disabled DM: 0x%x\n",
4258		       hal->disabled_dm_bitmap);
4259
4260	for (i = 0; i < ARRAY_SIZE(rtw89_disabled_dm_infos); i++) {
4261		info = &rtw89_disabled_dm_infos[i];
4262		disabled = BIT(info->type) & hal->disabled_dm_bitmap;
4263
4264		p += scnprintf(p, end - p, "[%d] %s: %c\n", info->type,
4265			       info->name,
4266			       disabled ? 'X' : 'O');
4267	}
4268
4269	return p - buf;
4270}
4271
4272static ssize_t
4273rtw89_debug_priv_disable_dm_set(struct rtw89_dev *rtwdev,
4274				struct rtw89_debugfs_priv *debugfs_priv,
4275				const char *buf, size_t count)
4276{
4277	u32 conf;
4278	int ret;
4279
4280	ret = kstrtou32(buf, 0, &conf);
4281	if (ret)
4282		return -EINVAL;
4283
4284	rtw89_debug_disable_dm_cfg_bmap(rtwdev, conf);
4285
4286	return count;
4287}
4288
4289static void rtw89_debug_mlo_mode_set_mlsr(struct rtw89_dev *rtwdev,
4290					  unsigned int link_id)
4291{
4292	struct ieee80211_vif *vif;
4293	struct rtw89_vif *rtwvif;
4294
4295	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
4296		vif = rtwvif_to_vif(rtwvif);
4297		if (!ieee80211_vif_is_mld(vif))
4298			continue;
4299
4300		rtw89_core_mlsr_switch(rtwdev, rtwvif, link_id);
4301	}
4302}
4303
4304static ssize_t
4305rtw89_debug_priv_mlo_mode_get(struct rtw89_dev *rtwdev,
4306			      struct rtw89_debugfs_priv *debugfs_priv,
4307			      char *buf, size_t bufsz)
4308{
4309	bool mlo_dm_dis = rtwdev->hal.disabled_dm_bitmap & BIT(RTW89_DM_MLO);
4310	char *p = buf, *end = buf + bufsz;
4311	struct ieee80211_vif *vif;
4312	struct rtw89_vif *rtwvif;
4313	int count = 0;
4314
4315	p += scnprintf(p, end - p, "MLD(s) status: (MLO DM: %s)\n",
4316		       str_disable_enable(mlo_dm_dis));
4317
4318	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
4319		vif = rtwvif_to_vif(rtwvif);
4320		if (!ieee80211_vif_is_mld(vif))
4321			continue;
4322
4323		p += scnprintf(p, end - p,
4324			       "\t#%u: MLO mode %x, valid 0x%x, active 0x%x\n",
4325			       count++, rtwvif->mlo_mode, vif->valid_links,
4326			       vif->active_links);
4327	}
4328
4329	if (count == 0)
4330		p += scnprintf(p, end - p, "\t(None)\n");
4331
4332	return p - buf;
4333}
4334
4335static ssize_t
4336rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev,
4337			      struct rtw89_debugfs_priv *debugfs_priv,
4338			      const char *buf, size_t count)
4339{
4340	u8 num, mlo_mode;
4341	u32 argv;
4342
4343	num = sscanf(buf, "%hhx %u", &mlo_mode, &argv);
4344	if (num != 2)
4345		return -EINVAL;
4346
4347	rtw89_debug_disable_dm_set_flag(rtwdev, RTW89_DM_MLO);
4348
4349	rtw89_debug(rtwdev, RTW89_DBG_STATE, "Set MLO mode to %x\n", mlo_mode);
4350
4351	switch (mlo_mode) {
4352	case RTW89_MLO_MODE_MLSR:
4353		rtw89_debug_mlo_mode_set_mlsr(rtwdev, argv);
4354		break;
4355	default:
4356		rtw89_debug(rtwdev, RTW89_DBG_STATE, "Unsupported MLO mode\n");
4357		rtw89_debug_disable_dm_clr_flag(rtwdev, RTW89_DM_MLO);
4358
4359		return -EOPNOTSUPP;
4360	}
4361
4362	return count;
4363}
4364
4365enum __diag_mac_cmd {
4366	__CMD_EQUALV,
4367	__CMD_EQUALO,
4368	__CMD_NEQUALV,
4369	__CMD_NEQUALO,
4370	__CMD_SETEQUALV,
4371	__CMD_SETEQUALO,
4372	__CMD_CMPWCR,
4373	__CMD_CMPWWD,
4374	__CMD_NEQ_CMPWCR,
4375	__CMD_NEQ_CMPWWD,
4376	__CMD_INCREMENT,
4377	__CMD_MESSAGE,
4378};
4379
4380enum __diag_mac_io {
4381	__IO_NORMAL,
4382	__IO_NORMAL_PCIE,
4383	__IO_NORMAL_USB,
4384	__IO_NORMAL_SDIO,
4385	__IO_PCIE_CFG,
4386	__IO_SDIO_CCCR,
4387};
4388
4389struct __diag_mac_rule_header {
4390	u8 sheet;
4391	u8 cmd;
4392	u8 seq_major;
4393	u8 seq_minor;
4394	u8 io_band;
4395	#define __DIAG_MAC_IO GENMASK(3, 0)
4396	#define __DIAG_MAC_N_BAND BIT(4)
4397	#define __DIAG_MAC_HAS_BAND BIT(5)
4398	u8 len; /* include header. Unit: 4 bytes */
4399	u8 rsvd[2];
4400} __packed;
4401
4402struct __diag_mac_rule_equal {
4403	struct __diag_mac_rule_header header;
4404	__le32 addr;
4405	__le32 addr_name_offset;
4406	__le32 mask;
4407	__le32 val;
4408	__le32 msg_offset;
4409	u8 rsvd[4];
4410} __packed;
4411
4412struct __diag_mac_rule_increment {
4413	struct __diag_mac_rule_header header;
4414	__le32 addr;
4415	__le32 addr_name_offset;
4416	__le32 mask;
4417	__le16 sel;
4418	__le16 delay;
4419	__le32 msg_offset;
4420	u8 rsvd[4];
4421} __packed;
4422
4423struct __diag_mac_msg_buf {
4424	__le16 len;
4425	char string[];
4426} __packed;
4427
4428static ssize_t rtw89_mac_diag_do_equalv(struct rtw89_dev *rtwdev,
4429					char *buf, size_t bufsz,
4430					const struct __diag_mac_rule_equal *r,
4431					const void *msg_start,
4432					u64 *positive_bmp)
4433{
4434	const struct __diag_mac_msg_buf *name = msg_start +
4435						le32_to_cpu(r->addr_name_offset);
4436	const struct __diag_mac_msg_buf *msg = msg_start +
4437					       le32_to_cpu(r->msg_offset);
4438	bool want_eq = r->header.cmd == __CMD_EQUALV;
4439	char *p = buf, *end = buf + bufsz;
4440	bool equal = false;
4441	u32 val;
4442
4443	*positive_bmp <<= 1;
4444
4445	if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
4446		val = rtw89_read32_pci_cfg(rtwdev, le32_to_cpu(r->addr));
4447	else
4448		val = rtw89_read32(rtwdev, le32_to_cpu(r->addr));
4449
4450	if ((val & le32_to_cpu(r->mask)) == le32_to_cpu(r->val))
4451		equal = true;
4452
4453	if (want_eq == equal) {
4454		*positive_bmp |= BIT(0);
4455		return p - buf;
4456	}
4457
4458	p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s => %x, %.*s\n",
4459		       r->header.sheet, r->header.cmd, le16_to_cpu(name->len),
4460		       name->string, val, le16_to_cpu(msg->len), msg->string);
4461
4462	return p - buf;
4463}
4464
4465static ssize_t rtw89_mac_diag_do_increment(struct rtw89_dev *rtwdev,
4466					   char *buf, size_t bufsz,
4467					   const struct __diag_mac_rule_increment *r,
4468					   const void *msg_start,
4469					   u64 *positive_bmp)
4470{
4471	const struct __diag_mac_msg_buf *name = msg_start +
4472						le32_to_cpu(r->addr_name_offset);
4473	const struct __diag_mac_msg_buf *msg = msg_start +
4474					       le32_to_cpu(r->msg_offset);
4475	char *p = buf, *end = buf + bufsz;
4476	u32 addr = le32_to_cpu(r->addr);
4477	u32 mask = le32_to_cpu(r->mask);
4478	u16 sel = le16_to_cpu(r->sel);
4479	u32 val1, val2;
4480
4481	*positive_bmp <<= 1;
4482
4483	rtw89_write32(rtwdev, addr, sel);
4484
4485	if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
4486		val1 = rtw89_read32_pci_cfg(rtwdev, addr);
4487	else
4488		val1 = rtw89_read32(rtwdev, addr);
4489
4490	mdelay(le16_to_cpu(r->delay));
4491
4492	if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
4493		val2 = rtw89_read32_pci_cfg(rtwdev, addr);
4494	else
4495		val2 = rtw89_read32(rtwdev, addr);
4496
4497	if ((val2 & mask) > (val1 & mask)) {
4498		*positive_bmp |= BIT(0);
4499		return p - buf;
4500	}
4501
4502	p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s [%d]=> %x, %.*s\n",
4503		       r->header.sheet, r->header.cmd, le16_to_cpu(name->len),
4504		       name->string, le16_to_cpu(r->sel), val1,
4505		       le16_to_cpu(msg->len), msg->string);
4506
4507	return p - buf;
4508}
4509
4510static bool rtw89_mac_diag_match_hci(struct rtw89_dev *rtwdev,
4511				     const struct __diag_mac_rule_header *rh)
4512{
4513	switch (u8_get_bits(rh->io_band, __DIAG_MAC_IO)) {
4514	case __IO_NORMAL:
4515	default:
4516		return true;
4517	case __IO_NORMAL_PCIE:
4518	case __IO_PCIE_CFG:
4519		if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE)
4520			return true;
4521		break;
4522	case __IO_NORMAL_USB:
4523		if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
4524			return true;
4525		break;
4526	case __IO_NORMAL_SDIO:
4527	case __IO_SDIO_CCCR:
4528		if (rtwdev->hci.type == RTW89_HCI_TYPE_SDIO)
4529			return true;
4530		break;
4531	}
4532
4533	return false;
4534}
4535
4536static bool rtw89_mac_diag_match_band(struct rtw89_dev *rtwdev,
4537				      const struct __diag_mac_rule_header *rh)
4538{
4539	u8 active_bands;
4540	bool has_band;
4541	u8 band;
4542
4543	has_band = u8_get_bits(rh->io_band, __DIAG_MAC_HAS_BAND);
4544	if (!has_band)
4545		return true;
4546
4547	band = u8_get_bits(rh->io_band, __DIAG_MAC_N_BAND);
4548	active_bands = rtw89_get_active_phy_bitmap(rtwdev);
4549
4550	if (active_bands & BIT(band))
4551		return true;
4552
4553	return false;
4554}
4555
4556static ssize_t rtw89_mac_diag_iter_all(struct rtw89_dev *rtwdev,
4557				       char *buf, size_t bufsz)
4558{
4559	const struct rtw89_fw_element_hdr *elm = rtwdev->fw.elm_info.diag_mac;
4560	u32 n_plains = 0, n_rules = 0, n_positive = 0, n_ignore = 0;
4561	char *p = buf, *end = buf + bufsz, *p_rewind;
4562	const void *rule, *rule_end;
4563	u32 elm_size, rule_size;
4564	const void *msg_start;
4565	u64 positive_bmp = 0;
4566	u8 prev_sheet = 0;
4567	u8 prev_seq = 0;
4568	int limit;
4569
4570	if (!elm) {
4571		p += scnprintf(p, end - p, "No diag_mac entry\n");
4572		goto out;
4573	}
4574
4575	rule_size = le32_to_cpu(elm->u.diag_mac.rule_size);
4576	elm_size = le32_to_cpu(elm->size);
4577
4578	if (ALIGN(rule_size, 16) > elm_size) {
4579		p += scnprintf(p, end - p, "rule size (%u) exceed elm_size (%u)\n",
4580			       ALIGN(rule_size, 16), elm_size);
4581		goto out;
4582	}
4583
4584	rule = &elm->u.diag_mac.rules_and_msgs[0];
4585	rule_end = &elm->u.diag_mac.rules_and_msgs[rule_size];
4586	msg_start = &elm->u.diag_mac.rules_and_msgs[ALIGN(rule_size, 16)];
4587
4588	for (limit = 0; limit < 5000 && rule < rule_end; limit++) {
4589		const struct __diag_mac_rule_header *rh = rule;
4590		u8 sheet = rh->sheet;
4591		u8 seq = rh->seq_major;
4592
4593		if (!rtw89_mac_diag_match_hci(rtwdev, rh) ||
4594		    !rtw89_mac_diag_match_band(rtwdev, rh)) {
4595			n_ignore++;
4596			goto next;
4597		}
4598
4599		if (!seq || prev_sheet != sheet || prev_seq != seq) {
4600			if (positive_bmp) {
4601				n_positive++;
4602				/*
4603				 * discard output for negative results if one in
4604				 * a sequence set is positive.
4605				 */
4606				if (p_rewind)
4607					p = p_rewind;
4608			}
4609			p_rewind = seq ? p : NULL;
4610			positive_bmp = 0;
4611			n_rules++;
4612		}
4613
4614		switch (rh->cmd) {
4615		case __CMD_EQUALV:
4616		case __CMD_NEQUALV:
4617			p += rtw89_mac_diag_do_equalv(rtwdev, p, end - p, rule,
4618						      msg_start, &positive_bmp);
4619			break;
4620		case __CMD_INCREMENT:
4621			p += rtw89_mac_diag_do_increment(rtwdev, p, end - p, rule,
4622							 msg_start, &positive_bmp);
4623			break;
4624		default:
4625			p += scnprintf(p, end - p, "unknown rule cmd %u\n", rh->cmd);
4626			break;
4627		}
4628
4629next:
4630		n_plains++;
4631		rule += rh->len * 4;
4632		prev_seq = seq;
4633		prev_sheet = sheet;
4634	}
4635
4636	if (positive_bmp) {
4637		n_positive++;
4638		if (p_rewind)
4639			p = p_rewind;
4640	}
4641
4642	p += scnprintf(p, end - p, "\nPlain(Ignore)/Rules/Positive: %u(%u)/%u/%u\n",
4643		       n_plains, n_ignore, n_rules, n_positive);
4644
4645out:
4646	return p - buf;
4647}
4648
4649static ssize_t
4650rtw89_debug_priv_diag_mac_get(struct rtw89_dev *rtwdev,
4651			      struct rtw89_debugfs_priv *debugfs_priv,
4652			      char *buf, size_t bufsz)
4653{
4654	lockdep_assert_wiphy(rtwdev->hw->wiphy);
4655
4656	rtw89_leave_lps(rtwdev);
4657
4658	return rtw89_mac_diag_iter_all(rtwdev, buf, bufsz);
4659}
4660
4661static ssize_t
4662rtw89_debug_priv_beacon_info_get(struct rtw89_dev *rtwdev,
4663				 struct rtw89_debugfs_priv *debugfs_priv,
4664				 char *buf, size_t bufsz)
4665{
4666	struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat;
4667	struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track;
4668	struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat;
4669	struct rtw89_beacon_dist *bcn_dist = &bcn_stat->bcn_dist;
4670	u16 upper, lower = bcn_stat->tbtt_tu_min;
4671	char *p = buf, *end = buf + bufsz;
4672	u16 *drift = bcn_stat->drift;
4673	u8 bcn_num = bcn_stat->num;
4674	u8 count;
4675	u8 i;
4676
4677	p += scnprintf(p, end - p, "[Beacon info]\n");
4678	p += scnprintf(p, end - p, "count: %u\n", pkt_stat->beacon_nr);
4679	p += scnprintf(p, end - p, "interval: %u\n", bcn_track->beacon_int);
4680	p += scnprintf(p, end - p, "dtim: %u\n", bcn_track->dtim);
4681	p += scnprintf(p, end - p, "raw rssi: %lu\n",
4682		       ewma_rssi_read(&rtwdev->phystat.bcn_rssi));
4683	p += scnprintf(p, end - p, "hw rate: %u\n", pkt_stat->beacon_rate);
4684	p += scnprintf(p, end - p, "length: %u\n", pkt_stat->beacon_len);
4685
4686	p += scnprintf(p, end - p, "\n[Distribution]\n");
4687	p += scnprintf(p, end - p, "tbtt\n");
4688	for (i = 0; i < RTW89_BCN_TRACK_MAX_BIN_NUM; i++) {
4689		upper = lower + RTW89_BCN_TRACK_BIN_WIDTH - 1;
4690		if (i == RTW89_BCN_TRACK_MAX_BIN_NUM - 1)
4691			upper = max(upper, bcn_stat->tbtt_tu_max);
4692
4693		p += scnprintf(p, end - p, "%02u - %02u: %u\n",
4694			       lower, upper, bcn_dist->bins[i]);
4695
4696		lower = upper + 1;
4697	}
4698
4699	p += scnprintf(p, end - p, "\ndrift\n");
4700
4701	for (i = 0; i < bcn_num; i += count) {
4702		count = 1;
4703		while (i + count < bcn_num && drift[i] == drift[i + count])
4704			count++;
4705
4706		p += scnprintf(p, end - p, "%u: %u\n", drift[i], count);
4707	}
4708	p += scnprintf(p, end - p, "\nlower bound: %u\n", bcn_dist->lower_bound);
4709	p += scnprintf(p, end - p, "upper bound: %u\n", bcn_dist->upper_bound);
4710	p += scnprintf(p, end - p, "outlier count: %u\n", bcn_dist->outlier_count);
4711
4712	p += scnprintf(p, end - p, "\n[Tracking]\n");
4713	p += scnprintf(p, end - p, "tbtt offset: %u\n", bcn_track->tbtt_offset);
4714	p += scnprintf(p, end - p, "bcn timeout: %u\n", bcn_track->bcn_timeout);
4715
4716	return p - buf;
4717}
4718
4719#define rtw89_debug_priv_get(name, opts...)			\
4720{								\
4721	.cb_read = rtw89_debug_priv_ ##name## _get,		\
4722	.opt = { opts },					\
4723}
4724
4725#define rtw89_debug_priv_set(name, opts...)			\
4726{								\
4727	.cb_write = rtw89_debug_priv_ ##name## _set,		\
4728	.opt = { opts },					\
4729}
4730
4731#define rtw89_debug_priv_select_and_get(name, opts...)		\
4732{								\
4733	.cb_write = rtw89_debug_priv_ ##name## _select,		\
4734	.cb_read = rtw89_debug_priv_ ##name## _get,		\
4735	.opt = { opts },					\
4736}
4737
4738#define rtw89_debug_priv_set_and_get(name, opts...)		\
4739{								\
4740	.cb_write = rtw89_debug_priv_ ##name## _set,		\
4741	.cb_read = rtw89_debug_priv_ ##name## _get,		\
4742	.opt = { opts },					\
4743}
4744
4745#define RSIZE_8K .rsize = 0x2000
4746#define RSIZE_12K .rsize = 0x3000
4747#define RSIZE_16K .rsize = 0x4000
4748#define RSIZE_20K .rsize = 0x5000
4749#define RSIZE_32K .rsize = 0x8000
4750#define RSIZE_64K .rsize = 0x10000
4751#define RSIZE_128K .rsize = 0x20000
4752#define RSIZE_1M .rsize = 0x100000
4753#define RLOCK .rlock = 1
4754#define WLOCK .wlock = 1
4755#define RWLOCK RLOCK, WLOCK
4756
4757static const struct rtw89_debugfs rtw89_debugfs_templ = {
4758	.read_reg = rtw89_debug_priv_select_and_get(read_reg),
4759	.write_reg = rtw89_debug_priv_set(write_reg),
4760	.read_rf = rtw89_debug_priv_select_and_get(read_rf),
4761	.write_rf = rtw89_debug_priv_set(write_rf),
4762	.rf_reg_dump = rtw89_debug_priv_get(rf_reg_dump, RSIZE_8K),
4763	.txpwr_table = rtw89_debug_priv_get(txpwr_table, RSIZE_20K, RLOCK),
4764	.mac_reg_dump = rtw89_debug_priv_select_and_get(mac_reg_dump, RSIZE_128K),
4765	.mac_mem_dump = rtw89_debug_priv_select_and_get(mac_mem_dump, RSIZE_16K, RLOCK),
4766	.mac_dbg_port_dump = rtw89_debug_priv_select_and_get(mac_dbg_port_dump, RSIZE_1M),
4767	.send_h2c = rtw89_debug_priv_set(send_h2c),
4768	.early_h2c = rtw89_debug_priv_set_and_get(early_h2c, RWLOCK),
4769	.fw_crash = rtw89_debug_priv_set_and_get(fw_crash, WLOCK),
4770	.btc_info = rtw89_debug_priv_get(btc_info, RSIZE_12K),
4771	.btc_manual = rtw89_debug_priv_set(btc_manual),
4772	.fw_log_manual = rtw89_debug_priv_set(fw_log_manual, WLOCK),
4773	.phy_info = rtw89_debug_priv_get(phy_info),
4774	.stations = rtw89_debug_priv_get(stations, RLOCK),
4775	.disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK),
4776	.mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK),
4777	.beacon_info = rtw89_debug_priv_get(beacon_info),
4778	.diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK),
4779};
4780
4781#define rtw89_debugfs_add(name, mode, fopname, parent)				\
4782	do {									\
4783		struct rtw89_debugfs_priv *priv = &rtwdev->debugfs->name;	\
4784		priv->rtwdev = rtwdev;						\
4785		if (IS_ERR(debugfs_create_file(#name, mode, parent, priv,	\
4786					       &file_ops_ ##fopname)))		\
4787			pr_debug("Unable to initialize debugfs:%s\n", #name);	\
4788	} while (0)
4789
4790#define rtw89_debugfs_add_w(name)						\
4791	rtw89_debugfs_add(name, S_IFREG | 0222, single_w, debugfs_topdir)
4792#define rtw89_debugfs_add_rw(name)						\
4793	rtw89_debugfs_add(name, S_IFREG | 0666, common_rw, debugfs_topdir)
4794#define rtw89_debugfs_add_r(name)						\
4795	rtw89_debugfs_add(name, S_IFREG | 0444, single_r, debugfs_topdir)
4796
4797static
4798void rtw89_debugfs_add_sec0(struct rtw89_dev *rtwdev, struct dentry *debugfs_topdir)
4799{
4800	rtw89_debugfs_add_rw(read_reg);
4801	rtw89_debugfs_add_w(write_reg);
4802	rtw89_debugfs_add_rw(read_rf);
4803	rtw89_debugfs_add_w(write_rf);
4804	rtw89_debugfs_add_r(rf_reg_dump);
4805	rtw89_debugfs_add_r(txpwr_table);
4806	rtw89_debugfs_add_rw(mac_reg_dump);
4807	rtw89_debugfs_add_rw(mac_mem_dump);
4808	rtw89_debugfs_add_rw(mac_dbg_port_dump);
4809}
4810
4811static
4812void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_topdir)
4813{
4814	rtw89_debugfs_add_w(send_h2c);
4815	rtw89_debugfs_add_rw(early_h2c);
4816	rtw89_debugfs_add_rw(fw_crash);
4817	rtw89_debugfs_add_r(btc_info);
4818	rtw89_debugfs_add_w(btc_manual);
4819	rtw89_debugfs_add_w(fw_log_manual);
4820	rtw89_debugfs_add_r(phy_info);
4821	rtw89_debugfs_add_r(stations);
4822	rtw89_debugfs_add_rw(disable_dm);
4823	rtw89_debugfs_add_rw(mlo_mode);
4824	rtw89_debugfs_add_r(beacon_info);
4825	rtw89_debugfs_add_r(diag_mac);
4826}
4827
4828void rtw89_debugfs_init(struct rtw89_dev *rtwdev)
4829{
4830	struct dentry *debugfs_topdir;
4831
4832	rtwdev->debugfs = kmemdup(&rtw89_debugfs_templ,
4833				  sizeof(rtw89_debugfs_templ), GFP_KERNEL);
4834	if (!rtwdev->debugfs)
4835		return;
4836
4837	debugfs_topdir = debugfs_create_dir("rtw89",
4838					    rtwdev->hw->wiphy->debugfsdir);
4839
4840	rtw89_debugfs_add_sec0(rtwdev, debugfs_topdir);
4841	rtw89_debugfs_add_sec1(rtwdev, debugfs_topdir);
4842}
4843
4844void rtw89_debugfs_deinit(struct rtw89_dev *rtwdev)
4845{
4846	kfree(rtwdev->debugfs);
4847}
4848#endif
4849
4850#ifdef CONFIG_RTW89_DEBUGMSG
4851void rtw89_debug(struct rtw89_dev *rtwdev, enum rtw89_debug_mask mask,
4852		 const char *fmt, ...)
4853{
4854	struct va_format vaf = {
4855	.fmt = fmt,
4856	};
4857
4858	va_list args;
4859
4860	va_start(args, fmt);
4861	vaf.va = &args;
4862
4863	if (rtw89_debug_mask & mask)
4864		dev_printk(KERN_DEBUG, rtwdev->dev, "%pV", &vaf);
4865
4866	va_end(args);
4867}
4868EXPORT_SYMBOL(rtw89_debug);
4869#endif
~/ Read-only file preview.