wifi: rtw89: debug: add diagnosis for RF

Add debugfs diag_rf and show RFK (RF calibration) diagnosis things for
now. Record channel related info before triggering RFK, and then record
state of each kind of RFK from C2H event report. Besides, in track work,
monitor TSSI status too. Both support history up to 10, and show records
via debugfs.

The following is an example of output.

RFK (next index: 2)
  PHY-X    =    0     0     0     0     0     0     0     0     0     0
  S0-CH    = 0012a 0012a 00000 00000 00000 00000 00000 00000 00000 00000
  S0-CV    = 0032c 0032c 00000 00000 00000 00000 00000 00000 00000 00000
  S0-C5    = 10000 10000 00000 00000 00000 00000 00000 00000 00000 00000
  S1-CH    = 0012a 0012a 00000 00000 00000 00000 00000 00000 00000 00000
  S1-CV    = 0032d 0032d 00000 00000 00000 00000 00000 00000 00000 00000
  S1-C5    = 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000
  PRE_NTFY =    0     0     0     0     0     0     0     0     0     0
  TSSI     =    1     1     0     0     0     0     0     0     0     0
  IQK      =    1     1     0     0     0     0     0     0     0     0
  DPK      =    1     1     0     0     0     0     0     0     0     0
  TXGAPK   =    1     1     0     0     0     0     0     0     0     0
  DACK     =    0     0     0     0     0     0     0     0     0     0
  RX_DCK   =    1     1     0     0     0     0     0     0     0     0
  TX_IQK   =    1     1     0     0     0     0     0     0     0     0
  CIM3k    =    1     1     0     0     0     0     0     0     0     0
TSSI-track (next index: 6)
  S0       =   00e   00e   00c   00d   00d   00e   00d   00d   00d   00e
  S1       =   00a   00b   009   00a   00a   00a   009   009   009   00a

Debugfs diag_rf can also be used to manually trigger RFK when written by 1.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260712034506.53209-9-pkshih@realtek.com
This commit is contained in:
Zong-Zhe Yang 2026-07-12 11:45:06 +08:00 committed by Ping-Ke Shih
parent b5bf2dc96f
commit 3c15399ef6
6 changed files with 272 additions and 12 deletions

View File

@ -486,6 +486,37 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
__rtw89_core_set_chip_txpwr(rtwdev, conf.chans[1], RTW89_PHY_1);
}
static void rtw89_core_rfk_record(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
bool start)
{
struct rtw89_rfk_wait_info *info = &rtwdev->rfk_wait;
struct rtw89_rfk_record *record = &info->records[info->record_idx];
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 path_num = min(chip->rf_path_num, RTW89_RFK_RECORD_PATH_NR);
int path;
if (!start)
goto end;
info->record_ptr = record;
record->phy_idx = rtwvif_link->phy_idx;
for (path = 0; path < path_num; path++) {
record->ch[path] = rtw89_read_rf(rtwdev, path, RR_CFGCH,
RR_CFGCH_BAND0 | RR_CFGCH_CH);
record->cv[path] = rtw89_read_rf(rtwdev, path, RR_VCO,
RR_VCO_SEL | RR_VCO_STS);
record->c5[path] = rtw89_read_rf(rtwdev, path, RR_SYNFB, RFREG_MASK);
}
return;
end:
info->record_idx = (info->record_idx + 1) % RTW89_RFK_RECORD_HISTORY_NR;
info->record_ptr = NULL;
}
void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
@ -503,9 +534,14 @@ void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
rtw89_set_channel(rtwdev);
}
if (chip->ops->rfk_channel)
if (chip->ops->rfk_channel) {
rtw89_core_rfk_record(rtwdev, rtwvif_link, true);
chip->ops->rfk_channel(rtwdev, rtwvif_link);
rtw89_core_rfk_record(rtwdev, rtwvif_link, false);
}
if (prehdl_link) {
rtw89_entity_force_hw(rtwdev, RTW89_PHY_NUM);
rtw89_set_channel(rtwdev);
@ -5274,6 +5310,37 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev,
}
}
static void rtw89_core_rfk_tssi_record(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 path_num = min(chip->rf_path_num, RTW89_RFK_RECORD_PATH_NR);
struct rtw89_rfk_wait_info *info = &rtwdev->rfk_wait;
int i = info->record_tssi_idx;
u32 base;
u32 mask;
int path;
if (chip->chip_gen == RTW89_CHIP_AX)
return;
info->record_tssi_idx = (info->record_tssi_idx + 1) %
RTW89_RFK_RECORD_HISTORY_NR;
if (chip->chip_id == RTL8922A) {
base = 0x2ee10;
mask = 0x7fc00;
} else {
base = 0x2f918;
mask = 0x000001ff;
}
for (path = 0; path < path_num; path++) {
u32 addr = base + 0x100 * path;
info->tssi_code[i][path] = rtw89_read32_mask(rtwdev, addr, mask);
}
}
static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev)
{
enum rtw89_entity_mode mode;
@ -5283,6 +5350,8 @@ static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev)
return;
rtw89_chip_rfk_track(rtwdev);
rtw89_core_rfk_tssi_record(rtwdev);
}
void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,

View File

@ -6134,11 +6134,43 @@ enum rtw89_rfk_report_state {
RTW89_RFK_STATE_H2C_CMD_ERR = 0x4,
};
enum rtw89_rfk_report_types {
RTW89_RFK_REPORT_PRE_NTFY,
RTW89_RFK_REPORT_TSSI,
RTW89_RFK_REPORT_IQK,
RTW89_RFK_REPORT_DPK,
RTW89_RFK_REPORT_TXGAPK,
RTW89_RFK_REPORT_DACK,
RTW89_RFK_REPORT_RX_DCK,
RTW89_RFK_REPORT_TX_IQK,
RTW89_RFK_REPORT_CIM3k,
NUM_OF_RTW89_RFK_REPORT_TYPES,
};
#define RTW89_RFK_RECORD_PATH_NR 2
#define RTW89_RFK_RECORD_HISTORY_NR 10
struct rtw89_rfk_record {
u32 ch[RTW89_RFK_RECORD_PATH_NR];
u32 cv[RTW89_RFK_RECORD_PATH_NR];
u32 c5[RTW89_RFK_RECORD_PATH_NR];
enum rtw89_phy_idx phy_idx;
enum rtw89_rfk_report_state states[NUM_OF_RTW89_RFK_REPORT_TYPES];
};
struct rtw89_rfk_wait_info {
struct completion completion;
ktime_t start_time;
enum rtw89_rfk_report_state state;
u8 version;
int record_idx;
struct rtw89_rfk_record *record_ptr;
struct rtw89_rfk_record records[RTW89_RFK_RECORD_HISTORY_NR];
int record_tssi_idx;
u32 tssi_code[RTW89_RFK_RECORD_HISTORY_NR][RTW89_RFK_RECORD_PATH_NR];
};
#define RTW89_DACK_PATH_NR 2

View File

@ -93,6 +93,7 @@ struct rtw89_debugfs {
struct rtw89_debugfs_priv beacon_info;
struct rtw89_debugfs_priv diag_mac;
struct rtw89_debugfs_priv diag_bb;
struct rtw89_debugfs_priv diag_rf;
struct rtw89_debugfs_priv monitor_opts;
};
@ -5393,6 +5394,118 @@ rtw89_debug_priv_diag_bb_get(struct rtw89_dev *rtwdev,
return p - buf;
}
static ssize_t
rtw89_debug_priv_diag_rf_get(struct rtw89_dev *rtwdev,
struct rtw89_debugfs_priv *debugfs_priv,
char *buf, size_t bufsz)
{
struct rtw89_rfk_wait_info *info = &rtwdev->rfk_wait;
char *p = buf, *end = buf + bufsz;
int i, j;
p += scnprintf(p, end - p, "RFK (next index: %d)\n", info->record_idx);
p += scnprintf(p, end - p, " PHY-X =");
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++) {
struct rtw89_rfk_record *record = &info->records[i];
p += scnprintf(p, end - p, " %4d ", record->phy_idx);
}
p += scnprintf(p, end - p, "\n");
for (j = 0; j < RTW89_RFK_RECORD_PATH_NR; j++) {
p += scnprintf(p, end - p, " S%d-CH =", j);
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++) {
struct rtw89_rfk_record *record = &info->records[i];
p += scnprintf(p, end - p, " %05x", record->ch[j]);
}
p += scnprintf(p, end - p, "\n");
p += scnprintf(p, end - p, " S%d-CV =", j);
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++) {
struct rtw89_rfk_record *record = &info->records[i];
p += scnprintf(p, end - p, " %05x", record->cv[j]);
}
p += scnprintf(p, end - p, "\n");
p += scnprintf(p, end - p, " S%d-C5 =", j);
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++) {
struct rtw89_rfk_record *record = &info->records[i];
p += scnprintf(p, end - p, " %05x", record->c5[j]);
}
p += scnprintf(p, end - p, "\n");
}
for (j = 0; j < NUM_OF_RTW89_RFK_REPORT_TYPES; j++) {
p += scnprintf(p, end - p, " %-8s =", rtw89_rfk_report_names[j]);
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++) {
struct rtw89_rfk_record *record = &info->records[i];
p += scnprintf(p, end - p, " %4d ", record->states[j]);
}
p += scnprintf(p, end - p, "\n");
}
p += scnprintf(p, end - p, "TSSI-track (next index: %d)\n", info->record_tssi_idx);
for (j = 0; j < RTW89_RFK_RECORD_PATH_NR; j++) {
p += scnprintf(p, end - p, " S%d =", j);
for (i = 0; i < RTW89_RFK_RECORD_HISTORY_NR; i++)
p += scnprintf(p, end - p, " %03x", info->tssi_code[i][j]);
p += scnprintf(p, end - p, "\n");
}
return p - buf;
}
static void rtw89_dbg_diag_rf_set_rfk(struct rtw89_dev *rtwdev)
{
struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
unsigned int link_id;
list_for_each_entry(rtwvif, &mgnt->active_list, mgnt_entry)
rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
}
enum rtw89_dbg_diag_rf_type {
RTW89_DBG_DIAG_RF_RSVD = 0,
RTW89_DBG_DIAG_RF_RFK = 1,
};
static ssize_t
rtw89_debug_priv_diag_rf_set(struct rtw89_dev *rtwdev,
struct rtw89_debugfs_priv *debugfs_priv,
const char *buf, size_t count)
{
u8 type;
int ret;
ret = kstrtou8(buf, 0, &type);
if (ret)
return -EINVAL;
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
rtw89_leave_ps_mode(rtwdev);
switch (type) {
case RTW89_DBG_DIAG_RF_RFK:
rtw89_dbg_diag_rf_set_rfk(rtwdev);
break;
default:
return -EOPNOTSUPP;
}
return count;
}
static ssize_t
rtw89_debug_priv_monitor_opts_get(struct rtw89_dev *rtwdev,
struct rtw89_debugfs_priv *debugfs_priv,
@ -5505,6 +5618,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = {
.beacon_info = rtw89_debug_priv_get(beacon_info),
.diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK),
.diag_bb = rtw89_debug_priv_get(diag_bb, RSIZE_8K, RLOCK),
.diag_rf = rtw89_debug_priv_set_and_get(diag_rf, RWLOCK),
.monitor_opts = rtw89_debug_priv_set_and_get(monitor_opts, RWLOCK),
};
@ -5562,6 +5676,7 @@ void rtw89_debugfs_add_sec2(struct rtw89_dev *rtwdev, struct dentry *debugfs_top
rtw89_debugfs_add_r(beacon_info);
rtw89_debugfs_add_r(diag_mac);
rtw89_debugfs_add_r(diag_bb);
rtw89_debugfs_add_rw(diag_rf);
rtw89_debugfs_add_rw(monitor_opts);
}

View File

@ -3968,6 +3968,23 @@ void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev,
[RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K] = rtw89_phy_c2h_rfk_log_cim3k,
};
#define NAME_RTW89_RFK_REPORT(type) \
[RTW89_RFK_REPORT_ ## type] = #type
const char * const rtw89_rfk_report_names[] = {
NAME_RTW89_RFK_REPORT(PRE_NTFY),
NAME_RTW89_RFK_REPORT(TSSI),
NAME_RTW89_RFK_REPORT(IQK),
NAME_RTW89_RFK_REPORT(DPK),
NAME_RTW89_RFK_REPORT(TXGAPK),
NAME_RTW89_RFK_REPORT(DACK),
NAME_RTW89_RFK_REPORT(RX_DCK),
NAME_RTW89_RFK_REPORT(TX_IQK),
NAME_RTW89_RFK_REPORT(CIM3k),
};
static_assert(ARRAY_SIZE(rtw89_rfk_report_names) == NUM_OF_RTW89_RFK_REPORT_TYPES);
static
void rtw89_phy_rfk_report_prep(struct rtw89_dev *rtwdev)
{
@ -3979,8 +3996,8 @@ void rtw89_phy_rfk_report_prep(struct rtw89_dev *rtwdev)
}
static
int rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev, const char *rfk_name,
unsigned int ms)
int ____rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev, const char *rfk_name,
unsigned int ms)
{
struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
unsigned long time_left;
@ -4017,6 +4034,29 @@ int rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev, const char *rfk_name,
return 0;
}
static
int __rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev,
enum rtw89_rfk_report_types rfk_type,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan,
unsigned int ms)
{
const char *rfk_name = rtw89_rfk_report_names[rfk_type];
struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
struct rtw89_rfk_record *record = wait->record_ptr;
int ret;
ret = ____rtw89_phy_rfk_report_wait(rtwdev, rfk_name, ms);
if (record)
record->states[rfk_type] = wait->state;
return ret;
}
#define rtw89_phy_rfk_report_wait(rtwdev, type, phy_idx, chan, ms) \
__rtw89_phy_rfk_report_wait(rtwdev, RTW89_RFK_REPORT_ ## type, phy_idx, chan, ms)
static void
rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
@ -4122,7 +4162,7 @@ int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) {
rtw89_phy_rfk_report_prep(rtwdev);
rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);
ret = rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms);
ret = rtw89_phy_rfk_report_wait(rtwdev, PRE_NTFY, phy_idx, NULL, ms);
if (ret)
return ret;
}
@ -4152,7 +4192,7 @@ int rtw89_phy_rfk_tssi_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "TSSI", ms);
return rtw89_phy_rfk_report_wait(rtwdev, TSSI, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_tssi_and_wait);
@ -4169,7 +4209,7 @@ int rtw89_phy_rfk_iqk_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "IQK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, IQK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_iqk_and_wait);
@ -4186,7 +4226,7 @@ int rtw89_phy_rfk_dpk_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "DPK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, DPK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_dpk_and_wait);
@ -4203,7 +4243,7 @@ int rtw89_phy_rfk_txgapk_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "TXGAPK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, TXGAPK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_txgapk_and_wait);
@ -4220,7 +4260,7 @@ int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "DACK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, DACK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait);
@ -4237,7 +4277,7 @@ int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "RX_DCK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, RX_DCK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_rxdck_and_wait);
@ -4254,7 +4294,7 @@ int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "TX_IQK", ms);
return rtw89_phy_rfk_report_wait(rtwdev, TX_IQK, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_txiqk_and_wait);
@ -4271,7 +4311,7 @@ int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev,
if (ret)
return ret;
return rtw89_phy_rfk_report_wait(rtwdev, "CIM3k", ms);
return rtw89_phy_rfk_report_wait(rtwdev, CIM3k, phy_idx, chan, ms);
}
EXPORT_SYMBOL(rtw89_phy_rfk_cim3k_and_wait);

View File

@ -1150,6 +1150,9 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func);
void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u32 len, u8 class, u8 func);
extern const char * const rtw89_rfk_report_names[];
int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
unsigned int ms);

View File

@ -8763,6 +8763,7 @@
#define RR_VCO 0xb2
#define RR_VCO_VAL GENMASK(18, 14)
#define RR_VCO_SEL GENMASK(9, 8)
#define RR_VCO_STS GENMASK(7, 0)
#define RR_VCI 0xb3
#define RR_VCI_ON BIT(7)
#define RR_LPF 0xb7