Path: blob/master/drivers/net/wireless/realtek/rtw88/debug.c
25924 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/* Copyright(c) 2018-2019 Realtek Corporation2*/34#include <linux/debugfs.h>5#include <linux/seq_file.h>6#include "main.h"7#include "coex.h"8#include "sec.h"9#include "fw.h"10#include "debug.h"11#include "phy.h"12#include "reg.h"13#include "ps.h"14#include "regd.h"1516#ifdef CONFIG_RTW88_DEBUGFS1718struct rtw_debugfs_priv {19struct rtw_dev *rtwdev;20int (*cb_read)(struct seq_file *m, void *v);21ssize_t (*cb_write)(struct file *filp, const char __user *buffer,22size_t count, loff_t *loff);23union {24u32 cb_data;25u8 *buf;26struct {27u32 page_offset;28u32 page_num;29} rsvd_page;30struct {31u8 rf_path;32u32 rf_addr;33u32 rf_mask;34};35struct {36u32 addr;37u32 len;38} read_reg;39struct {40u8 bit;41} dm_cap;42};43};4445struct rtw_debugfs {46struct rtw_debugfs_priv mac_0;47struct rtw_debugfs_priv mac_1;48struct rtw_debugfs_priv mac_2;49struct rtw_debugfs_priv mac_3;50struct rtw_debugfs_priv mac_4;51struct rtw_debugfs_priv mac_5;52struct rtw_debugfs_priv mac_6;53struct rtw_debugfs_priv mac_7;54struct rtw_debugfs_priv mac_10;55struct rtw_debugfs_priv mac_11;56struct rtw_debugfs_priv mac_12;57struct rtw_debugfs_priv mac_13;58struct rtw_debugfs_priv mac_14;59struct rtw_debugfs_priv mac_15;60struct rtw_debugfs_priv mac_16;61struct rtw_debugfs_priv mac_17;62struct rtw_debugfs_priv bb_8;63struct rtw_debugfs_priv bb_9;64struct rtw_debugfs_priv bb_a;65struct rtw_debugfs_priv bb_b;66struct rtw_debugfs_priv bb_c;67struct rtw_debugfs_priv bb_d;68struct rtw_debugfs_priv bb_e;69struct rtw_debugfs_priv bb_f;70struct rtw_debugfs_priv bb_18;71struct rtw_debugfs_priv bb_19;72struct rtw_debugfs_priv bb_1a;73struct rtw_debugfs_priv bb_1b;74struct rtw_debugfs_priv bb_1c;75struct rtw_debugfs_priv bb_1d;76struct rtw_debugfs_priv bb_1e;77struct rtw_debugfs_priv bb_1f;78struct rtw_debugfs_priv bb_2c;79struct rtw_debugfs_priv bb_2d;80struct rtw_debugfs_priv bb_40;81struct rtw_debugfs_priv bb_41;82struct rtw_debugfs_priv rf_dump;83struct rtw_debugfs_priv tx_pwr_tbl;84struct rtw_debugfs_priv write_reg;85struct rtw_debugfs_priv h2c;86struct rtw_debugfs_priv rf_write;87struct rtw_debugfs_priv rf_read;88struct rtw_debugfs_priv read_reg;89struct rtw_debugfs_priv fix_rate;90struct rtw_debugfs_priv dump_cam;91struct rtw_debugfs_priv rsvd_page;92struct rtw_debugfs_priv phy_info;93struct rtw_debugfs_priv coex_enable;94struct rtw_debugfs_priv coex_info;95struct rtw_debugfs_priv edcca_enable;96struct rtw_debugfs_priv fw_crash;97struct rtw_debugfs_priv force_lowest_basic_rate;98struct rtw_debugfs_priv dm_cap;99};100101static const char * const rtw_dm_cap_strs[] = {102[RTW_DM_CAP_NA] = "NA",103[RTW_DM_CAP_TXGAPK] = "TXGAPK",104};105106static int rtw_debugfs_single_show(struct seq_file *m, void *v)107{108struct rtw_debugfs_priv *debugfs_priv = m->private;109110return debugfs_priv->cb_read(m, v);111}112113static ssize_t rtw_debugfs_common_write(struct file *filp,114const char __user *buffer,115size_t count, loff_t *loff)116{117struct rtw_debugfs_priv *debugfs_priv = filp->private_data;118119return debugfs_priv->cb_write(filp, buffer, count, loff);120}121122static ssize_t rtw_debugfs_single_write(struct file *filp,123const char __user *buffer,124size_t count, loff_t *loff)125{126struct seq_file *seqpriv = (struct seq_file *)filp->private_data;127struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;128129return debugfs_priv->cb_write(filp, buffer, count, loff);130}131132static int rtw_debugfs_single_open_rw(struct inode *inode, struct file *filp)133{134return single_open(filp, rtw_debugfs_single_show, inode->i_private);135}136137static int rtw_debugfs_close(struct inode *inode, struct file *filp)138{139return 0;140}141142static const struct file_operations file_ops_single_r = {143.owner = THIS_MODULE,144.open = rtw_debugfs_single_open_rw,145.read = seq_read,146.llseek = seq_lseek,147.release = single_release,148};149150static const struct file_operations file_ops_single_rw = {151.owner = THIS_MODULE,152.open = rtw_debugfs_single_open_rw,153.release = single_release,154.read = seq_read,155.llseek = seq_lseek,156.write = rtw_debugfs_single_write,157};158159static const struct file_operations file_ops_common_write = {160.owner = THIS_MODULE,161.write = rtw_debugfs_common_write,162.open = simple_open,163.release = rtw_debugfs_close,164};165166static int rtw_debugfs_get_read_reg(struct seq_file *m, void *v)167{168struct rtw_debugfs_priv *debugfs_priv = m->private;169struct rtw_dev *rtwdev = debugfs_priv->rtwdev;170u32 val, len, addr;171172len = debugfs_priv->read_reg.len;173addr = debugfs_priv->read_reg.addr;174switch (len) {175case 1:176val = rtw_read8(rtwdev, addr);177seq_printf(m, "reg 0x%03x: 0x%02x\n", addr, val);178break;179case 2:180val = rtw_read16(rtwdev, addr);181seq_printf(m, "reg 0x%03x: 0x%04x\n", addr, val);182break;183case 4:184val = rtw_read32(rtwdev, addr);185seq_printf(m, "reg 0x%03x: 0x%08x\n", addr, val);186break;187}188return 0;189}190191static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v)192{193struct rtw_debugfs_priv *debugfs_priv = m->private;194struct rtw_dev *rtwdev = debugfs_priv->rtwdev;195u32 val, addr, mask;196u8 path;197198path = debugfs_priv->rf_path;199addr = debugfs_priv->rf_addr;200mask = debugfs_priv->rf_mask;201202mutex_lock(&rtwdev->mutex);203val = rtw_read_rf(rtwdev, path, addr, mask);204mutex_unlock(&rtwdev->mutex);205206seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n",207path, addr, mask, val);208209return 0;210}211212static int rtw_debugfs_get_fix_rate(struct seq_file *m, void *v)213{214struct rtw_debugfs_priv *debugfs_priv = m->private;215struct rtw_dev *rtwdev = debugfs_priv->rtwdev;216struct rtw_dm_info *dm_info = &rtwdev->dm_info;217u8 fix_rate = dm_info->fix_rate;218219if (fix_rate >= DESC_RATE_MAX) {220seq_printf(m, "Fix rate disabled, fix_rate = %u\n", fix_rate);221return 0;222}223224seq_printf(m, "Data frames fixed at desc rate %u\n", fix_rate);225return 0;226}227228static int rtw_debugfs_copy_from_user(char tmp[], int size,229const char __user *buffer, size_t count,230int num)231{232int tmp_len;233234memset(tmp, 0, size);235236if (count < num)237return -EFAULT;238239tmp_len = (count > size - 1 ? size - 1 : count);240241if (copy_from_user(tmp, buffer, tmp_len))242return -EFAULT;243244tmp[tmp_len] = '\0';245246return 0;247}248249static ssize_t rtw_debugfs_set_read_reg(struct file *filp,250const char __user *buffer,251size_t count, loff_t *loff)252{253struct seq_file *seqpriv = (struct seq_file *)filp->private_data;254struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;255struct rtw_dev *rtwdev = debugfs_priv->rtwdev;256char tmp[32 + 1];257u32 addr, len;258int num;259int ret;260261ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);262if (ret)263return ret;264265num = sscanf(tmp, "%x %x", &addr, &len);266267if (num != 2)268return -EINVAL;269270if (len != 1 && len != 2 && len != 4) {271rtw_warn(rtwdev, "read reg setting wrong len\n");272return -EINVAL;273}274debugfs_priv->read_reg.addr = addr;275debugfs_priv->read_reg.len = len;276277return count;278}279280static int rtw_debugfs_get_dump_cam(struct seq_file *m, void *v)281{282struct rtw_debugfs_priv *debugfs_priv = m->private;283struct rtw_dev *rtwdev = debugfs_priv->rtwdev;284u32 val, command;285u32 hw_key_idx = debugfs_priv->cb_data << RTW_SEC_CAM_ENTRY_SHIFT;286u32 read_cmd = RTW_SEC_CMD_POLLING;287int i;288289seq_printf(m, "cam entry%d\n", debugfs_priv->cb_data);290seq_puts(m, "0x0 0x1 0x2 0x3 ");291seq_puts(m, "0x4 0x5\n");292mutex_lock(&rtwdev->mutex);293for (i = 0; i <= 5; i++) {294command = read_cmd | (hw_key_idx + i);295rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);296val = rtw_read32(rtwdev, RTW_SEC_READ_REG);297seq_printf(m, "%8.8x", val);298if (i < 2)299seq_puts(m, " ");300}301seq_puts(m, "\n");302mutex_unlock(&rtwdev->mutex);303return 0;304}305306static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)307{308struct rtw_debugfs_priv *debugfs_priv = m->private;309struct rtw_dev *rtwdev = debugfs_priv->rtwdev;310u16 page_size = rtwdev->chip->page_size;311u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size;312u32 offset = debugfs_priv->rsvd_page.page_offset * page_size;313u8 *buf;314int i;315int ret;316317buf = vzalloc(buf_size);318if (!buf)319return -ENOMEM;320321ret = rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RSVD_PAGE, offset,322buf_size, (u32 *)buf);323if (ret) {324rtw_err(rtwdev, "failed to dump rsvd page\n");325vfree(buf);326return ret;327}328329for (i = 0 ; i < buf_size ; i += 8) {330if (i % page_size == 0)331seq_printf(m, "PAGE %d\n", (i + offset) / page_size);332seq_printf(m, "%8ph\n", buf + i);333}334vfree(buf);335336return 0;337}338339static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp,340const char __user *buffer,341size_t count, loff_t *loff)342{343struct seq_file *seqpriv = (struct seq_file *)filp->private_data;344struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;345struct rtw_dev *rtwdev = debugfs_priv->rtwdev;346char tmp[32 + 1];347u32 offset, page_num;348int num;349int ret;350351ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);352if (ret)353return ret;354355num = sscanf(tmp, "%d %d", &offset, &page_num);356357if (num != 2) {358rtw_warn(rtwdev, "invalid arguments\n");359return -EINVAL;360}361362debugfs_priv->rsvd_page.page_offset = offset;363debugfs_priv->rsvd_page.page_num = page_num;364365return count;366}367368static ssize_t rtw_debugfs_set_single_input(struct file *filp,369const char __user *buffer,370size_t count, loff_t *loff)371{372struct seq_file *seqpriv = (struct seq_file *)filp->private_data;373struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;374u32 input;375int ret;376377ret = kstrtou32_from_user(buffer, count, 0, &input);378if (ret)379return ret;380381debugfs_priv->cb_data = input;382383return count;384}385386static ssize_t rtw_debugfs_set_write_reg(struct file *filp,387const char __user *buffer,388size_t count, loff_t *loff)389{390struct rtw_debugfs_priv *debugfs_priv = filp->private_data;391struct rtw_dev *rtwdev = debugfs_priv->rtwdev;392char tmp[32 + 1];393u32 addr, val, len;394int num;395int ret;396397ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);398if (ret)399return ret;400401/* write BB/MAC register */402num = sscanf(tmp, "%x %x %x", &addr, &val, &len);403404if (num != 3)405return -EINVAL;406407switch (len) {408case 1:409rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,410"reg write8 0x%03x: 0x%08x\n", addr, val);411rtw_write8(rtwdev, addr, (u8)val);412break;413case 2:414rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,415"reg write16 0x%03x: 0x%08x\n", addr, val);416rtw_write16(rtwdev, addr, (u16)val);417break;418case 4:419rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,420"reg write32 0x%03x: 0x%08x\n", addr, val);421rtw_write32(rtwdev, addr, (u32)val);422break;423default:424rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,425"error write length = %d\n", len);426break;427}428429return count;430}431432static ssize_t rtw_debugfs_set_h2c(struct file *filp,433const char __user *buffer,434size_t count, loff_t *loff)435{436struct rtw_debugfs_priv *debugfs_priv = filp->private_data;437struct rtw_dev *rtwdev = debugfs_priv->rtwdev;438char tmp[32 + 1];439u8 param[8];440int num;441int ret;442443ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);444if (ret)445return ret;446447num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx",448¶m[0], ¶m[1], ¶m[2], ¶m[3],449¶m[4], ¶m[5], ¶m[6], ¶m[7]);450if (num != 8) {451rtw_warn(rtwdev, "invalid H2C command format for debug\n");452return -EINVAL;453}454455mutex_lock(&rtwdev->mutex);456rtw_fw_h2c_cmd_dbg(rtwdev, param);457mutex_unlock(&rtwdev->mutex);458459return count;460}461462static ssize_t rtw_debugfs_set_rf_write(struct file *filp,463const char __user *buffer,464size_t count, loff_t *loff)465{466struct rtw_debugfs_priv *debugfs_priv = filp->private_data;467struct rtw_dev *rtwdev = debugfs_priv->rtwdev;468char tmp[32 + 1];469u32 path, addr, mask, val;470int num;471int ret;472473ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);474if (ret)475return ret;476477num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val);478479if (num != 4) {480rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");481return -EINVAL;482}483484mutex_lock(&rtwdev->mutex);485rtw_write_rf(rtwdev, path, addr, mask, val);486mutex_unlock(&rtwdev->mutex);487rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,488"write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n",489path, addr, mask, val);490491return count;492}493494static ssize_t rtw_debugfs_set_rf_read(struct file *filp,495const char __user *buffer,496size_t count, loff_t *loff)497{498struct seq_file *seqpriv = (struct seq_file *)filp->private_data;499struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;500struct rtw_dev *rtwdev = debugfs_priv->rtwdev;501char tmp[32 + 1];502u32 path, addr, mask;503int num;504int ret;505506ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);507if (ret)508return ret;509510num = sscanf(tmp, "%x %x %x", &path, &addr, &mask);511512if (num != 3) {513rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");514return -EINVAL;515}516517debugfs_priv->rf_path = path;518debugfs_priv->rf_addr = addr;519debugfs_priv->rf_mask = mask;520521return count;522}523524static ssize_t rtw_debugfs_set_fix_rate(struct file *filp,525const char __user *buffer,526size_t count, loff_t *loff)527{528struct seq_file *seqpriv = (struct seq_file *)filp->private_data;529struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;530struct rtw_dev *rtwdev = debugfs_priv->rtwdev;531struct rtw_dm_info *dm_info = &rtwdev->dm_info;532u8 fix_rate;533int ret;534535ret = kstrtou8_from_user(buffer, count, 0, &fix_rate);536if (ret)537return ret;538539dm_info->fix_rate = fix_rate;540541return count;542}543544static int rtw_debug_get_mac_page(struct seq_file *m, void *v)545{546struct rtw_debugfs_priv *debugfs_priv = m->private;547struct rtw_dev *rtwdev = debugfs_priv->rtwdev;548u32 page = debugfs_priv->cb_data;549int i, n;550int max = 0xff;551552rtw_read32(rtwdev, debugfs_priv->cb_data);553for (n = 0; n <= max; ) {554seq_printf(m, "\n%8.8x ", n + page);555for (i = 0; i < 4 && n <= max; i++, n += 4)556seq_printf(m, "%8.8x ",557rtw_read32(rtwdev, (page | n)));558}559seq_puts(m, "\n");560return 0;561}562563static int rtw_debug_get_bb_page(struct seq_file *m, void *v)564{565struct rtw_debugfs_priv *debugfs_priv = m->private;566struct rtw_dev *rtwdev = debugfs_priv->rtwdev;567u32 page = debugfs_priv->cb_data;568int i, n;569int max = 0xff;570571rtw_read32(rtwdev, debugfs_priv->cb_data);572for (n = 0; n <= max; ) {573seq_printf(m, "\n%8.8x ", n + page);574for (i = 0; i < 4 && n <= max; i++, n += 4)575seq_printf(m, "%8.8x ",576rtw_read32(rtwdev, (page | n)));577}578seq_puts(m, "\n");579return 0;580}581582static int rtw_debugfs_get_rf_dump(struct seq_file *m, void *v)583{584struct rtw_debugfs_priv *debugfs_priv = m->private;585struct rtw_dev *rtwdev = debugfs_priv->rtwdev;586u32 addr, offset, data;587u8 path;588589mutex_lock(&rtwdev->mutex);590591for (path = 0; path < rtwdev->hal.rf_path_num; path++) {592seq_printf(m, "RF path:%d\n", path);593for (addr = 0; addr < 0x100; addr += 4) {594seq_printf(m, "%8.8x ", addr);595for (offset = 0; offset < 4; offset++) {596data = rtw_read_rf(rtwdev, path, addr + offset,5970xffffffff);598seq_printf(m, "%8.8x ", data);599}600seq_puts(m, "\n");601}602seq_puts(m, "\n");603}604605mutex_unlock(&rtwdev->mutex);606607return 0;608}609610static void rtw_print_cck_rate_txt(struct seq_file *m, u8 rate)611{612static const char * const613cck_rate[] = {"1M", "2M", "5.5M", "11M"};614u8 idx = rate - DESC_RATE1M;615616seq_printf(m, " CCK_%-5s", cck_rate[idx]);617}618619static void rtw_print_ofdm_rate_txt(struct seq_file *m, u8 rate)620{621static const char * const622ofdm_rate[] = {"6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M"};623u8 idx = rate - DESC_RATE6M;624625seq_printf(m, " OFDM_%-4s", ofdm_rate[idx]);626}627628static void rtw_print_ht_rate_txt(struct seq_file *m, u8 rate)629{630u8 mcs_n = rate - DESC_RATEMCS0;631632seq_printf(m, " MCS%-6u", mcs_n);633}634635static void rtw_print_vht_rate_txt(struct seq_file *m, u8 rate)636{637u8 idx = rate - DESC_RATEVHT1SS_MCS0;638u8 n_ss, mcs_n;639640/* n spatial stream */641n_ss = 1 + idx / 10;642/* MCS n */643mcs_n = idx % 10;644seq_printf(m, " VHT%uSMCS%u", n_ss, mcs_n);645}646647static void rtw_print_rate(struct seq_file *m, u8 rate)648{649switch (rate) {650case DESC_RATE1M...DESC_RATE11M:651rtw_print_cck_rate_txt(m, rate);652break;653case DESC_RATE6M...DESC_RATE54M:654rtw_print_ofdm_rate_txt(m, rate);655break;656case DESC_RATEMCS0...DESC_RATEMCS31:657rtw_print_ht_rate_txt(m, rate);658break;659case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT4SS_MCS9:660rtw_print_vht_rate_txt(m, rate);661break;662default:663seq_printf(m, " Unknown rate=0x%x\n", rate);664break;665}666}667668#define case_REGD(src) \669case RTW_REGD_##src: return #src670671static const char *rtw_get_regd_string(u8 regd)672{673switch (regd) {674case_REGD(FCC);675case_REGD(MKK);676case_REGD(ETSI);677case_REGD(IC);678case_REGD(KCC);679case_REGD(ACMA);680case_REGD(CHILE);681case_REGD(UKRAINE);682case_REGD(MEXICO);683case_REGD(CN);684case_REGD(WW);685default:686return "Unknown";687}688}689690static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)691{692struct rtw_debugfs_priv *debugfs_priv = m->private;693struct rtw_dev *rtwdev = debugfs_priv->rtwdev;694struct rtw_power_params pwr_param = {0};695struct rtw_hal *hal = &rtwdev->hal;696u8 nss = rtwdev->efuse.hw_cap.nss;697u8 path, rate, bw, ch, regd;698u8 max_ht_rate, max_rate;699700mutex_lock(&rtwdev->mutex);701bw = hal->current_band_width;702ch = hal->current_channel;703regd = rtw_regd_get(rtwdev);704705seq_printf(m, "channel: %u\n", ch);706seq_printf(m, "bandwidth: %u\n", bw);707seq_printf(m, "regulatory: %s\n", rtw_get_regd_string(regd));708seq_printf(m, "%-4s %-10s %-9s %-9s (%-4s %-4s %-4s) %-4s\n",709"path", "rate", "pwr", "base", "byr", "lmt", "sar", "rem");710711max_ht_rate = DESC_RATEMCS0 + nss * 8 - 1;712713if (rtwdev->chip->vht_supported)714max_rate = DESC_RATEVHT1SS_MCS0 + nss * 10 - 1;715else716max_rate = max_ht_rate;717718mutex_lock(&hal->tx_power_mutex);719for (path = RF_PATH_A; path < hal->rf_path_num; path++) {720/* there is no CCK rates used in 5G */721if (hal->current_band_type == RTW_BAND_5G)722rate = DESC_RATE6M;723else724rate = DESC_RATE1M;725726for (; rate <= max_rate; rate++) {727if (rate > max_ht_rate && rate <= DESC_RATEMCS31)728continue;729730rtw_get_tx_power_params(rtwdev, path, rate, bw,731ch, regd, &pwr_param);732733seq_printf(m, "%4c ", path + 'A');734rtw_print_rate(m, rate);735seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d %4d) %4d\n",736hal->tx_pwr_tbl[path][rate],737hal->tx_pwr_tbl[path][rate],738pwr_param.pwr_base,739min3(pwr_param.pwr_offset,740pwr_param.pwr_limit,741pwr_param.pwr_sar),742pwr_param.pwr_offset, pwr_param.pwr_limit,743pwr_param.pwr_sar,744pwr_param.pwr_remnant);745}746}747748mutex_unlock(&hal->tx_power_mutex);749mutex_unlock(&rtwdev->mutex);750751return 0;752}753754void rtw_debugfs_get_simple_phy_info(struct seq_file *m)755{756struct rtw_debugfs_priv *debugfs_priv = m->private;757struct rtw_dev *rtwdev = debugfs_priv->rtwdev;758struct rtw_hal *hal = &rtwdev->hal;759struct rtw_dm_info *dm_info = &rtwdev->dm_info;760struct rtw_traffic_stats *stats = &rtwdev->stats;761762seq_printf(m, "%-40s = %ddBm/ %d\n", "RSSI/ STA Channel",763dm_info->rssi[RF_PATH_A] - 100, hal->current_channel);764765seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n",766stats->tx_throughput, stats->rx_throughput);767768seq_puts(m, "[Tx Rate] = ");769rtw_print_rate(m, dm_info->tx_rate);770seq_printf(m, "(0x%x)\n", dm_info->tx_rate);771772seq_puts(m, "[Rx Rate] = ");773rtw_print_rate(m, dm_info->curr_rx_rate);774seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate);775}776777static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)778{779struct rtw_debugfs_priv *debugfs_priv = m->private;780struct rtw_dev *rtwdev = debugfs_priv->rtwdev;781struct rtw_dm_info *dm_info = &rtwdev->dm_info;782struct rtw_traffic_stats *stats = &rtwdev->stats;783struct rtw_pkt_count *last_cnt = &dm_info->last_pkt_count;784struct rtw_efuse *efuse = &rtwdev->efuse;785struct ewma_evm *ewma_evm = dm_info->ewma_evm;786struct ewma_snr *ewma_snr = dm_info->ewma_snr;787u8 ss, rate_id;788789seq_puts(m, "==========[Common Info]========\n");790seq_printf(m, "Is link = %c\n", rtw_is_assoc(rtwdev) ? 'Y' : 'N');791seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel);792seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width);793seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]);794seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n",795stats->tx_throughput, stats->rx_throughput);796seq_printf(m, "1SS for TX and RX = %c\n\n", rtwdev->hal.txrx_1ss ?797'Y' : 'N');798799seq_puts(m, "==========[Tx Phy Info]========\n");800seq_puts(m, "[Tx Rate] = ");801rtw_print_rate(m, dm_info->tx_rate);802seq_printf(m, "(0x%x)\n\n", dm_info->tx_rate);803804seq_puts(m, "==========[Rx Phy Info]========\n");805seq_printf(m, "[Rx Beacon Count] = %u\n", last_cnt->num_bcn_pkt);806seq_puts(m, "[Rx Rate] = ");807rtw_print_rate(m, dm_info->curr_rx_rate);808seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate);809810seq_puts(m, "[Rx Rate Count]:\n");811seq_printf(m, " * CCK = {%u, %u, %u, %u}\n",812last_cnt->num_qry_pkt[DESC_RATE1M],813last_cnt->num_qry_pkt[DESC_RATE2M],814last_cnt->num_qry_pkt[DESC_RATE5_5M],815last_cnt->num_qry_pkt[DESC_RATE11M]);816817seq_printf(m, " * OFDM = {%u, %u, %u, %u, %u, %u, %u, %u}\n",818last_cnt->num_qry_pkt[DESC_RATE6M],819last_cnt->num_qry_pkt[DESC_RATE9M],820last_cnt->num_qry_pkt[DESC_RATE12M],821last_cnt->num_qry_pkt[DESC_RATE18M],822last_cnt->num_qry_pkt[DESC_RATE24M],823last_cnt->num_qry_pkt[DESC_RATE36M],824last_cnt->num_qry_pkt[DESC_RATE48M],825last_cnt->num_qry_pkt[DESC_RATE54M]);826827for (ss = 0; ss < efuse->hw_cap.nss; ss++) {828rate_id = DESC_RATEMCS0 + ss * 8;829seq_printf(m, " * HT_MCS[%u:%u] = {%u, %u, %u, %u, %u, %u, %u, %u}\n",830ss * 8, ss * 8 + 7,831last_cnt->num_qry_pkt[rate_id],832last_cnt->num_qry_pkt[rate_id + 1],833last_cnt->num_qry_pkt[rate_id + 2],834last_cnt->num_qry_pkt[rate_id + 3],835last_cnt->num_qry_pkt[rate_id + 4],836last_cnt->num_qry_pkt[rate_id + 5],837last_cnt->num_qry_pkt[rate_id + 6],838last_cnt->num_qry_pkt[rate_id + 7]);839}840841for (ss = 0; ss < efuse->hw_cap.nss; ss++) {842rate_id = DESC_RATEVHT1SS_MCS0 + ss * 10;843seq_printf(m, " * VHT_MCS-%uss MCS[0:9] = {%u, %u, %u, %u, %u, %u, %u, %u, %u, %u}\n",844ss + 1,845last_cnt->num_qry_pkt[rate_id],846last_cnt->num_qry_pkt[rate_id + 1],847last_cnt->num_qry_pkt[rate_id + 2],848last_cnt->num_qry_pkt[rate_id + 3],849last_cnt->num_qry_pkt[rate_id + 4],850last_cnt->num_qry_pkt[rate_id + 5],851last_cnt->num_qry_pkt[rate_id + 6],852last_cnt->num_qry_pkt[rate_id + 7],853last_cnt->num_qry_pkt[rate_id + 8],854last_cnt->num_qry_pkt[rate_id + 9]);855}856857seq_printf(m, "[RSSI(dBm)] = {%d, %d, %d, %d}\n",858dm_info->rssi[RF_PATH_A] - 100,859dm_info->rssi[RF_PATH_B] - 100,860dm_info->rssi[RF_PATH_C] - 100,861dm_info->rssi[RF_PATH_D] - 100);862seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d, -%d, -%d}\n",863dm_info->rx_evm_dbm[RF_PATH_A],864dm_info->rx_evm_dbm[RF_PATH_B],865dm_info->rx_evm_dbm[RF_PATH_C],866dm_info->rx_evm_dbm[RF_PATH_D]);867seq_printf(m, "[Rx SNR] = {%d, %d, %d, %d}\n",868dm_info->rx_snr[RF_PATH_A],869dm_info->rx_snr[RF_PATH_B],870dm_info->rx_snr[RF_PATH_C],871dm_info->rx_snr[RF_PATH_D]);872seq_printf(m, "[CFO_tail(KHz)] = {%d, %d, %d, %d}\n",873dm_info->cfo_tail[RF_PATH_A],874dm_info->cfo_tail[RF_PATH_B],875dm_info->cfo_tail[RF_PATH_C],876dm_info->cfo_tail[RF_PATH_D]);877878if (dm_info->curr_rx_rate >= DESC_RATE6M) {879seq_puts(m, "[Rx Average Status]:\n");880seq_printf(m, " * OFDM, EVM: {-%d}, SNR: {%d}\n",881(u8)ewma_evm_read(&ewma_evm[RTW_EVM_OFDM]),882(u8)ewma_snr_read(&ewma_snr[RTW_SNR_OFDM_A]));883seq_printf(m, " * 1SS, EVM: {-%d}, SNR: {%d}\n",884(u8)ewma_evm_read(&ewma_evm[RTW_EVM_1SS]),885(u8)ewma_snr_read(&ewma_snr[RTW_SNR_1SS_A]));886seq_printf(m, " * 2SS, EVM: {-%d, -%d}, SNR: {%d, %d}\n",887(u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_A]),888(u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_B]),889(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_A]),890(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_B]));891seq_printf(m, " * 3SS, EVM: {-%d, -%d, -%d}, SNR: {%d, %d, %d}\n",892(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_A]),893(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_B]),894(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_C]),895(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_A]),896(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_B]),897(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_C]));898}899900seq_puts(m, "[Rx Counter]:\n");901seq_printf(m, " * CCA (CCK, OFDM, Total) = (%u, %u, %u)\n",902dm_info->cck_cca_cnt,903dm_info->ofdm_cca_cnt,904dm_info->total_cca_cnt);905seq_printf(m, " * False Alarm (CCK, OFDM, Total) = (%u, %u, %u)\n",906dm_info->cck_fa_cnt,907dm_info->ofdm_fa_cnt,908dm_info->total_fa_cnt);909seq_printf(m, " * CCK cnt (ok, err) = (%u, %u)\n",910dm_info->cck_ok_cnt, dm_info->cck_err_cnt);911seq_printf(m, " * OFDM cnt (ok, err) = (%u, %u)\n",912dm_info->ofdm_ok_cnt, dm_info->ofdm_err_cnt);913seq_printf(m, " * HT cnt (ok, err) = (%u, %u)\n",914dm_info->ht_ok_cnt, dm_info->ht_err_cnt);915seq_printf(m, " * VHT cnt (ok, err) = (%u, %u)\n",916dm_info->vht_ok_cnt, dm_info->vht_err_cnt);917918return 0;919}920921static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v)922{923struct rtw_debugfs_priv *debugfs_priv = m->private;924struct rtw_dev *rtwdev = debugfs_priv->rtwdev;925926mutex_lock(&rtwdev->mutex);927rtw_coex_display_coex_info(rtwdev, m);928mutex_unlock(&rtwdev->mutex);929930return 0;931}932933static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,934const char __user *buffer,935size_t count, loff_t *loff)936{937struct seq_file *seqpriv = (struct seq_file *)filp->private_data;938struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;939struct rtw_dev *rtwdev = debugfs_priv->rtwdev;940struct rtw_coex *coex = &rtwdev->coex;941bool enable;942int ret;943944ret = kstrtobool_from_user(buffer, count, &enable);945if (ret)946return ret;947948mutex_lock(&rtwdev->mutex);949coex->manual_control = !enable;950mutex_unlock(&rtwdev->mutex);951952return count;953}954955static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v)956{957struct rtw_debugfs_priv *debugfs_priv = m->private;958struct rtw_dev *rtwdev = debugfs_priv->rtwdev;959struct rtw_coex *coex = &rtwdev->coex;960961seq_printf(m, "coex mechanism %s\n",962coex->manual_control ? "disabled" : "enabled");963964return 0;965}966967static ssize_t rtw_debugfs_set_edcca_enable(struct file *filp,968const char __user *buffer,969size_t count, loff_t *loff)970{971struct seq_file *seqpriv = (struct seq_file *)filp->private_data;972struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;973struct rtw_dev *rtwdev = debugfs_priv->rtwdev;974bool input;975int err;976977err = kstrtobool_from_user(buffer, count, &input);978if (err)979return err;980981rtw_edcca_enabled = input;982rtw_phy_adaptivity_set_mode(rtwdev);983984return count;985}986987static int rtw_debugfs_get_edcca_enable(struct seq_file *m, void *v)988{989struct rtw_debugfs_priv *debugfs_priv = m->private;990struct rtw_dev *rtwdev = debugfs_priv->rtwdev;991struct rtw_dm_info *dm_info = &rtwdev->dm_info;992993seq_printf(m, "EDCCA %s: EDCCA mode %d\n",994rtw_edcca_enabled ? "enabled" : "disabled",995dm_info->edcca_mode);996return 0;997}998999static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,1000const char __user *buffer,1001size_t count, loff_t *loff)1002{1003struct seq_file *seqpriv = (struct seq_file *)filp->private_data;1004struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;1005struct rtw_dev *rtwdev = debugfs_priv->rtwdev;1006bool input;1007int ret;10081009ret = kstrtobool_from_user(buffer, count, &input);1010if (ret)1011return ret;10121013if (!input)1014return -EINVAL;10151016if (test_bit(RTW_FLAG_RESTARTING, rtwdev->flags))1017return -EINPROGRESS;10181019mutex_lock(&rtwdev->mutex);1020rtw_leave_lps_deep(rtwdev);1021set_bit(RTW_FLAG_RESTART_TRIGGERING, rtwdev->flags);1022rtw_write8(rtwdev, REG_HRCV_MSG, 1);1023mutex_unlock(&rtwdev->mutex);10241025return count;1026}10271028static int rtw_debugfs_get_fw_crash(struct seq_file *m, void *v)1029{1030struct rtw_debugfs_priv *debugfs_priv = m->private;1031struct rtw_dev *rtwdev = debugfs_priv->rtwdev;10321033seq_printf(m, "%d\n",1034test_bit(RTW_FLAG_RESTART_TRIGGERING, rtwdev->flags) ||1035test_bit(RTW_FLAG_RESTARTING, rtwdev->flags));1036return 0;1037}10381039static ssize_t rtw_debugfs_set_force_lowest_basic_rate(struct file *filp,1040const char __user *buffer,1041size_t count, loff_t *loff)1042{1043struct seq_file *seqpriv = (struct seq_file *)filp->private_data;1044struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;1045struct rtw_dev *rtwdev = debugfs_priv->rtwdev;1046bool input;1047int err;10481049err = kstrtobool_from_user(buffer, count, &input);1050if (err)1051return err;10521053if (input)1054set_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags);1055else1056clear_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags);10571058return count;1059}10601061static int rtw_debugfs_get_force_lowest_basic_rate(struct seq_file *m, void *v)1062{1063struct rtw_debugfs_priv *debugfs_priv = m->private;1064struct rtw_dev *rtwdev = debugfs_priv->rtwdev;10651066seq_printf(m, "force lowest basic rate: %d\n",1067test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags));10681069return 0;1070}10711072static ssize_t rtw_debugfs_set_dm_cap(struct file *filp,1073const char __user *buffer,1074size_t count, loff_t *loff)1075{1076struct seq_file *seqpriv = (struct seq_file *)filp->private_data;1077struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;1078struct rtw_dev *rtwdev = debugfs_priv->rtwdev;1079struct rtw_dm_info *dm_info = &rtwdev->dm_info;1080int ret, bit;1081bool en;10821083ret = kstrtoint_from_user(buffer, count, 10, &bit);1084if (ret)1085return ret;10861087en = bit > 0;1088bit = abs(bit);10891090if (bit >= RTW_DM_CAP_NUM) {1091rtw_warn(rtwdev, "unknown DM CAP %d\n", bit);1092return -EINVAL;1093}10941095if (en)1096dm_info->dm_flags &= ~BIT(bit);1097else1098dm_info->dm_flags |= BIT(bit);10991100debugfs_priv->dm_cap.bit = bit;11011102return count;1103}11041105static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m)1106{1107struct rtw_dm_info *dm_info = &rtwdev->dm_info;1108struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk;1109int i, path;1110u32 val;11111112seq_printf(m, "\n(%2d) %c%s\n\n", RTW_DM_CAP_TXGAPK,1113dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+',1114rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]);11151116mutex_lock(&rtwdev->mutex);11171118for (path = 0; path < rtwdev->hal.rf_path_num; path++) {1119val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK);1120seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val);11211122for (i = 0; i < RF_HW_OFFSET_NUM; i++)1123seq_printf(m, "[TXGAPK] offset %d %d\n",1124txgapk->rf3f_fs[path][i], i);1125seq_puts(m, "\n");1126}1127mutex_unlock(&rtwdev->mutex);1128}11291130static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v)1131{1132struct rtw_debugfs_priv *debugfs_priv = m->private;1133struct rtw_dev *rtwdev = debugfs_priv->rtwdev;1134struct rtw_dm_info *dm_info = &rtwdev->dm_info;1135int i;11361137switch (debugfs_priv->dm_cap.bit) {1138case RTW_DM_CAP_TXGAPK:1139dump_gapk_status(rtwdev, m);1140break;1141default:1142for (i = 1; i < RTW_DM_CAP_NUM; i++) {1143seq_printf(m, "(%2d) %c%s\n", i,1144dm_info->dm_flags & BIT(i) ? '-' : '+',1145rtw_dm_cap_strs[i]);1146}1147break;1148}1149debugfs_priv->dm_cap.bit = RTW_DM_CAP_NA;1150return 0;1151}11521153#define rtw_debug_priv_mac(addr) \1154{ \1155.cb_read = rtw_debug_get_mac_page, \1156.cb_data = addr, \1157}11581159#define rtw_debug_priv_bb(addr) \1160{ \1161.cb_read = rtw_debug_get_bb_page, \1162.cb_data = addr, \1163}11641165#define rtw_debug_priv_get(name) \1166{ \1167.cb_read = rtw_debugfs_get_ ##name, \1168}11691170#define rtw_debug_priv_set(name) \1171{ \1172.cb_write = rtw_debugfs_set_ ##name, \1173}11741175#define rtw_debug_priv_set_and_get(name) \1176{ \1177.cb_write = rtw_debugfs_set_ ##name, \1178.cb_read = rtw_debugfs_get_ ##name, \1179}11801181#define rtw_debug_priv_set_single_and_get(name) \1182{ \1183.cb_write = rtw_debugfs_set_single_input, \1184.cb_read = rtw_debugfs_get_ ##name, \1185}11861187static const struct rtw_debugfs rtw_debugfs_templ = {1188.mac_0 = rtw_debug_priv_mac(0x0000),1189.mac_1 = rtw_debug_priv_mac(0x0100),1190.mac_2 = rtw_debug_priv_mac(0x0200),1191.mac_3 = rtw_debug_priv_mac(0x0300),1192.mac_4 = rtw_debug_priv_mac(0x0400),1193.mac_5 = rtw_debug_priv_mac(0x0500),1194.mac_6 = rtw_debug_priv_mac(0x0600),1195.mac_7 = rtw_debug_priv_mac(0x0700),1196.mac_10 = rtw_debug_priv_mac(0x1000),1197.mac_11 = rtw_debug_priv_mac(0x1100),1198.mac_12 = rtw_debug_priv_mac(0x1200),1199.mac_13 = rtw_debug_priv_mac(0x1300),1200.mac_14 = rtw_debug_priv_mac(0x1400),1201.mac_15 = rtw_debug_priv_mac(0x1500),1202.mac_16 = rtw_debug_priv_mac(0x1600),1203.mac_17 = rtw_debug_priv_mac(0x1700),1204.bb_8 = rtw_debug_priv_bb(0x0800),1205.bb_9 = rtw_debug_priv_bb(0x0900),1206.bb_a = rtw_debug_priv_bb(0x0a00),1207.bb_b = rtw_debug_priv_bb(0x0b00),1208.bb_c = rtw_debug_priv_bb(0x0c00),1209.bb_d = rtw_debug_priv_bb(0x0d00),1210.bb_e = rtw_debug_priv_bb(0x0e00),1211.bb_f = rtw_debug_priv_bb(0x0f00),1212.bb_18 = rtw_debug_priv_bb(0x1800),1213.bb_19 = rtw_debug_priv_bb(0x1900),1214.bb_1a = rtw_debug_priv_bb(0x1a00),1215.bb_1b = rtw_debug_priv_bb(0x1b00),1216.bb_1c = rtw_debug_priv_bb(0x1c00),1217.bb_1d = rtw_debug_priv_bb(0x1d00),1218.bb_1e = rtw_debug_priv_bb(0x1e00),1219.bb_1f = rtw_debug_priv_bb(0x1f00),1220.bb_2c = rtw_debug_priv_bb(0x2c00),1221.bb_2d = rtw_debug_priv_bb(0x2d00),1222.bb_40 = rtw_debug_priv_bb(0x4000),1223.bb_41 = rtw_debug_priv_bb(0x4100),1224.rf_dump = rtw_debug_priv_get(rf_dump),1225.tx_pwr_tbl = rtw_debug_priv_get(tx_pwr_tbl),1226.write_reg = rtw_debug_priv_set(write_reg),1227.h2c = rtw_debug_priv_set(h2c),1228.rf_write = rtw_debug_priv_set(rf_write),1229.rf_read = rtw_debug_priv_set_and_get(rf_read),1230.read_reg = rtw_debug_priv_set_and_get(read_reg),1231.fix_rate = rtw_debug_priv_set_and_get(fix_rate),1232.dump_cam = rtw_debug_priv_set_single_and_get(dump_cam),1233.rsvd_page = rtw_debug_priv_set_and_get(rsvd_page),1234.phy_info = rtw_debug_priv_get(phy_info),1235.coex_enable = rtw_debug_priv_set_and_get(coex_enable),1236.coex_info = rtw_debug_priv_get(coex_info),1237.edcca_enable = rtw_debug_priv_set_and_get(edcca_enable),1238.fw_crash = rtw_debug_priv_set_and_get(fw_crash),1239.force_lowest_basic_rate = rtw_debug_priv_set_and_get(force_lowest_basic_rate),1240.dm_cap = rtw_debug_priv_set_and_get(dm_cap),1241};12421243#define rtw_debugfs_add_core(name, mode, fopname, parent) \1244do { \1245struct rtw_debugfs_priv *priv = &rtwdev->debugfs->name; \1246priv->rtwdev = rtwdev; \1247if (IS_ERR(debugfs_create_file(#name, mode, \1248parent, priv, \1249&file_ops_ ##fopname))) \1250pr_debug("Unable to initialize debugfs:%s\n", \1251#name); \1252} while (0)12531254#define rtw_debugfs_add_w(name) \1255rtw_debugfs_add_core(name, S_IFREG | 0222, common_write, debugfs_topdir)1256#define rtw_debugfs_add_rw(name) \1257rtw_debugfs_add_core(name, S_IFREG | 0666, single_rw, debugfs_topdir)1258#define rtw_debugfs_add_r(name) \1259rtw_debugfs_add_core(name, S_IFREG | 0444, single_r, debugfs_topdir)12601261static1262void rtw_debugfs_add_basic(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)1263{1264rtw_debugfs_add_w(write_reg);1265rtw_debugfs_add_rw(read_reg);1266rtw_debugfs_add_w(rf_write);1267rtw_debugfs_add_rw(rf_read);1268rtw_debugfs_add_rw(fix_rate);1269rtw_debugfs_add_rw(dump_cam);1270rtw_debugfs_add_rw(rsvd_page);1271rtw_debugfs_add_r(phy_info);1272rtw_debugfs_add_r(coex_info);1273rtw_debugfs_add_rw(coex_enable);1274rtw_debugfs_add_w(h2c);1275rtw_debugfs_add_r(rf_dump);1276rtw_debugfs_add_r(tx_pwr_tbl);1277rtw_debugfs_add_rw(edcca_enable);1278rtw_debugfs_add_rw(fw_crash);1279rtw_debugfs_add_rw(force_lowest_basic_rate);1280rtw_debugfs_add_rw(dm_cap);1281}12821283static1284void rtw_debugfs_add_sec0(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)1285{1286rtw_debugfs_add_r(mac_0);1287rtw_debugfs_add_r(mac_1);1288rtw_debugfs_add_r(mac_2);1289rtw_debugfs_add_r(mac_3);1290rtw_debugfs_add_r(mac_4);1291rtw_debugfs_add_r(mac_5);1292rtw_debugfs_add_r(mac_6);1293rtw_debugfs_add_r(mac_7);1294rtw_debugfs_add_r(bb_8);1295rtw_debugfs_add_r(bb_9);1296rtw_debugfs_add_r(bb_a);1297rtw_debugfs_add_r(bb_b);1298rtw_debugfs_add_r(bb_c);1299rtw_debugfs_add_r(bb_d);1300rtw_debugfs_add_r(bb_e);1301rtw_debugfs_add_r(bb_f);1302}13031304static1305void rtw_debugfs_add_sec1(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)1306{1307rtw_debugfs_add_r(mac_10);1308rtw_debugfs_add_r(mac_11);1309rtw_debugfs_add_r(mac_12);1310rtw_debugfs_add_r(mac_13);1311rtw_debugfs_add_r(mac_14);1312rtw_debugfs_add_r(mac_15);1313rtw_debugfs_add_r(mac_16);1314rtw_debugfs_add_r(mac_17);1315rtw_debugfs_add_r(bb_18);1316rtw_debugfs_add_r(bb_19);1317rtw_debugfs_add_r(bb_1a);1318rtw_debugfs_add_r(bb_1b);1319rtw_debugfs_add_r(bb_1c);1320rtw_debugfs_add_r(bb_1d);1321rtw_debugfs_add_r(bb_1e);1322rtw_debugfs_add_r(bb_1f);1323if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) {1324rtw_debugfs_add_r(bb_2c);1325rtw_debugfs_add_r(bb_2d);1326rtw_debugfs_add_r(bb_40);1327rtw_debugfs_add_r(bb_41);1328}1329}13301331void rtw_debugfs_init(struct rtw_dev *rtwdev)1332{1333struct dentry *debugfs_topdir;13341335rtwdev->debugfs = kmemdup(&rtw_debugfs_templ, sizeof(rtw_debugfs_templ),1336GFP_KERNEL);1337if (!rtwdev->debugfs)1338return;13391340debugfs_topdir = debugfs_create_dir("rtw88",1341rtwdev->hw->wiphy->debugfsdir);13421343rtw_debugfs_add_basic(rtwdev, debugfs_topdir);1344rtw_debugfs_add_sec0(rtwdev, debugfs_topdir);1345rtw_debugfs_add_sec1(rtwdev, debugfs_topdir);1346}13471348void rtw_debugfs_deinit(struct rtw_dev *rtwdev)1349{1350kfree(rtwdev->debugfs);1351}1352#endif /* CONFIG_RTW88_DEBUGFS */13531354#ifdef CONFIG_RTW88_DEBUG13551356void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,1357const char *fmt, ...)1358{1359struct va_format vaf = {1360.fmt = fmt,1361};1362va_list args;13631364va_start(args, fmt);1365vaf.va = &args;13661367if (rtw_debug_mask & mask)1368dev_printk(KERN_DEBUG, rtwdev->dev, "%pV", &vaf);13691370va_end(args);1371}1372EXPORT_SYMBOL(rtw_dbg);13731374#endif /* CONFIG_RTW88_DEBUG */137513761377