]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: phy: support static PD level setting
authorEric Huang <echuang@realtek.com>
Mon, 20 Apr 2026 03:40:40 +0000 (11:40 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 29 Apr 2026 04:47:02 +0000 (12:47 +0800)
PD (Packet Detection) threshold is a key parameter in the DIG
(Dynamic Initial Gain) algorithm that determines the sensitivity
of packet detection. Current implementation only supports dynamic
PD adjustment based on environment. This patch adds support for
static PD threshold via debugfs allowing users to set a fixed PD
value for testing or specific scenarios.

Signed-off-by: Eric Huang <echuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260420034051.17666-6-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/debug.c
drivers/net/wireless/realtek/rtw89/phy.c

index ac399ecaea6b3253cef82d42525f58c79added3d..0b212f6edc8bfdf2eab20dda584174e0e3dd1a52 100644 (file)
@@ -5180,6 +5180,7 @@ enum rtw89_dm_type {
        RTW89_DM_MLO,
        RTW89_DM_HW_SCAN,
        RTW89_DM_INACTIVE_PS,
+       RTW89_DM_DIG_PD,
 };
 
 #define RTW89_THERMAL_PROT_LV_MAX 5
@@ -5221,6 +5222,9 @@ struct rtw89_hal {
 
        u8 thermal_prot_th;
        u8 thermal_prot_lv; /* 0 ~ RTW89_THERMAL_PROT_LV_MAX */
+
+       u8 fixed_dig_pd_th; /* v = (X(dBm) + 102)/2 */
+       s8 fixed_dig_cck_pd_th; /* dBm */
 };
 
 #define RTW89_MAX_MAC_ID_NUM 128
index ebe3b1f9c39d2655e4d5593be87dc5c3173b7103..2cb6e441b2f832374be17b64b285fbf08b279ecd 100644 (file)
@@ -87,6 +87,7 @@ struct rtw89_debugfs {
        struct rtw89_debugfs_priv phy_info;
        struct rtw89_debugfs_priv stations;
        struct rtw89_debugfs_priv disable_dm;
+       struct rtw89_debugfs_priv static_pd_th;
        struct rtw89_debugfs_priv mlo_mode;
        struct rtw89_debugfs_priv beacon_info;
        struct rtw89_debugfs_priv diag_mac;
@@ -4349,6 +4350,7 @@ static const struct rtw89_disabled_dm_info {
        DM_INFO(MLO),
        DM_INFO(HW_SCAN),
        DM_INFO(INACTIVE_PS),
+       DM_INFO(DIG_PD),
 };
 
 static ssize_t
@@ -4394,6 +4396,96 @@ rtw89_debug_priv_disable_dm_set(struct rtw89_dev *rtwdev,
        return count;
 }
 
+#define RTW89_DIG_PD_TH_MIN_DBM                -102
+#define RTW89_DIG_PD_TH_MAX_DBM                -40
+#define RTW89_DIG_PD_TH_STEP           2
+
+static s8 rtw89_dig_pd_th_to_dbm(u8 reg_val)
+{
+       return RTW89_DIG_PD_TH_MIN_DBM + RTW89_DIG_PD_TH_STEP * reg_val;
+}
+
+static u8 rtw89_dig_pd_th_dbm_to_reg(s8 dbm)
+{
+       return (dbm - RTW89_DIG_PD_TH_MIN_DBM) / RTW89_DIG_PD_TH_STEP;
+}
+
+static ssize_t
+rtw89_debug_priv_static_pd_th_get(struct rtw89_dev *rtwdev,
+                                 struct rtw89_debugfs_priv *debugfs_priv,
+                                 char *buf, size_t bufsz)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       char *p = buf, *end = buf + bufsz;
+       bool disabled;
+       s8 pd_th_dbm;
+       s8 cck_pd_th;
+
+       disabled = hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD);
+
+       if (disabled) {
+               pd_th_dbm = rtw89_dig_pd_th_to_dbm(hal->fixed_dig_pd_th);
+               cck_pd_th = hal->fixed_dig_cck_pd_th;
+
+               p += scnprintf(p, end - p, "DIG: static\n");
+               p += scnprintf(p, end - p, "OFDM PD threshold: %d dBm\n", pd_th_dbm);
+               p += scnprintf(p, end - p, "CCK PD threshold: %d dBm\n", cck_pd_th);
+       } else {
+               p += scnprintf(p, end - p, "DIG: dynamic\n");
+       }
+
+       p += scnprintf(p, end - p, "\nUsage: echo <mode> [pd_th] > static_pd_th\n");
+       p += scnprintf(p, end - p, "  mode: 0 = dynamic, 1 = static\n");
+       p += scnprintf(p, end - p, "  pd_th: PD threshold in dBm (-102 ~ -40)\n");
+
+       return p - buf;
+}
+
+static ssize_t
+rtw89_debug_priv_static_pd_th_set(struct rtw89_dev *rtwdev,
+                                 struct rtw89_debugfs_priv *debugfs_priv,
+                                 const char *buf, size_t count)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       int ret;
+       u32 mode;
+       s32 pd_th_dbm;
+
+       ret = sscanf(buf, "%u %d", &mode, &pd_th_dbm);
+       if (ret < 1)
+               return -EINVAL;
+
+       if (mode > 1)
+               return -EINVAL;
+
+       if (mode == 0) {
+               rtw89_core_dm_disable_clr(rtwdev, RTW89_DM_DIG_PD);
+               hal->fixed_dig_pd_th = 0;
+               hal->fixed_dig_cck_pd_th = 0;
+
+               rtw89_debug(rtwdev, RTW89_DBG_DIG,
+                           "DIG static mode disabled\n");
+       } else {
+               if (ret < 2 || pd_th_dbm < RTW89_DIG_PD_TH_MIN_DBM ||
+                   pd_th_dbm > RTW89_DIG_PD_TH_MAX_DBM)
+                       return -EINVAL;
+
+               rtw89_core_dm_disable_set(rtwdev, RTW89_DM_DIG_PD);
+               hal->fixed_dig_pd_th = clamp(rtw89_dig_pd_th_dbm_to_reg(pd_th_dbm),
+                                            0, 0x1f);
+               /* CCK uses dBm directly */
+               hal->fixed_dig_cck_pd_th = pd_th_dbm;
+
+               rtw89_debug(rtwdev, RTW89_DBG_DIG,
+                           "DIG static mode: PD=0x%02x (%d dBm), CCK=%d dBm\n",
+                           hal->fixed_dig_pd_th,
+                           rtw89_dig_pd_th_to_dbm(hal->fixed_dig_pd_th),
+                           hal->fixed_dig_cck_pd_th);
+       }
+
+       return count;
+}
+
 static void rtw89_debug_mlo_mode_set_mlsr(struct rtw89_dev *rtwdev,
                                          unsigned int link_id)
 {
@@ -4882,6 +4974,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = {
        .phy_info = rtw89_debug_priv_get(phy_info),
        .stations = rtw89_debug_priv_get(stations, RLOCK),
        .disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK),
+       .static_pd_th = rtw89_debug_priv_set_and_get(static_pd_th, RWLOCK),
        .mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK),
        .beacon_info = rtw89_debug_priv_get(beacon_info),
        .diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK),
@@ -4930,6 +5023,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top
        rtw89_debugfs_add_r(phy_info);
        rtw89_debugfs_add_r(stations);
        rtw89_debugfs_add_rw(disable_dm);
+       rtw89_debugfs_add_rw(static_pd_th);
        rtw89_debugfs_add_rw(mlo_mode);
        rtw89_debugfs_add_r(beacon_info);
        rtw89_debugfs_add_r(diag_mac);
index 1f249c2970060847bf86121bc90645c608c49133..2663fc102e7742893355b136381c203c27ee1f5a 100644 (file)
@@ -7170,11 +7170,19 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev,
        const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, bb->phy_idx);
        const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
        struct rtw89_dig_info *dig = &bb->dig;
+       struct rtw89_hal *hal = &rtwdev->hal;
        u8 final_rssi, under_region = dig->pd_low_th_ofst;
        s8 cck_cca_th;
        u32 pd_val;
 
-       pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi, enable, chan);
+       if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD)) {
+               pd_val = hal->fixed_dig_pd_th;
+
+               rtw89_debug(rtwdev, RTW89_DBG_DIG,
+                           "Fixed DIG: PD_low=%d\n", pd_val);
+       } else {
+               pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi, enable, chan);
+       }
        dig->bak_dig = pd_val;
 
        rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
@@ -7182,17 +7190,24 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev,
        rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
                              dig_regs->pd_spatial_reuse_en, enable, bb->phy_idx);
 
-       if (!rtwdev->hal.support_cckpd)
+       if (!hal->support_cckpd)
                return;
 
-       final_rssi = min_t(u8, rssi, dig->igi_rssi);
-       under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan);
-       cck_cca_th = max_t(s8, final_rssi - under_region, CCKPD_TH_MIN_RSSI);
-       pd_val = (u32)(cck_cca_th - IGI_RSSI_MAX);
+       if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD)) {
+               pd_val = hal->fixed_dig_cck_pd_th;
 
-       rtw89_debug(rtwdev, RTW89_DBG_DIG,
-                   "igi=%d, cck_ccaTH=%d, backoff=%d, cck_PD_low=((%d))dB\n",
-                   final_rssi, cck_cca_th, under_region, pd_val);
+               rtw89_debug(rtwdev, RTW89_DBG_DIG,
+                           "Fixed DIG: cck_PD_low=((%d))dB\n", pd_val);
+       } else {
+               final_rssi = min_t(u8, rssi, dig->igi_rssi);
+               under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan);
+               cck_cca_th = max_t(s8, final_rssi - under_region, CCKPD_TH_MIN_RSSI);
+               pd_val = (u32)(cck_cca_th - IGI_RSSI_MAX);
+
+               rtw89_debug(rtwdev, RTW89_DBG_DIG,
+                           "igi=%d, cck_ccaTH=%d, backoff=%d, cck_PD_low=((%d))dB\n",
+                           final_rssi, cck_cca_th, under_region, pd_val);
+       }
 
        rtw89_phy_write32_idx(rtwdev, dig_regs->bmode_pd_reg,
                              dig_regs->bmode_cca_rssi_limit_en, enable, bb->phy_idx);
@@ -7323,6 +7338,7 @@ static void rtw89_phy_dig_ctrl(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb
 {
        const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
        struct rtw89_dig_info *dig = &bb->dig;
+       struct rtw89_hal *hal = &rtwdev->hal;
        bool en_dig;
        u32 pd_val;
 
@@ -7331,10 +7347,16 @@ static void rtw89_phy_dig_ctrl(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb
 
        if (pause_dig) {
                en_dig = false;
-               pd_val = 0;
+               if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD))
+                       pd_val = hal->fixed_dig_pd_th;
+               else
+                       pd_val = 0;
        } else {
                en_dig = rtwdev->total_sta_assoc > 0;
-               pd_val = restore ? dig->bak_dig : 0;
+               if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD))
+                       pd_val = hal->fixed_dig_pd_th;
+               else
+                       pd_val = restore ? dig->bak_dig : 0;
        }
 
        rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s <%s> PD_low=%d", __func__,