wifi: rtw89: load RFK log format string from firmware file
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 13 Dec 2023 00:50:51 +0000 (08:50 +0800)
committerKalle Valo <kvalo@kernel.org>
Fri, 15 Dec 2023 13:38:25 +0000 (15:38 +0200)
To debug RFK (RF calibration) in firmware, it sends log via firmware C2H
events to driver with string format ID and four arguments. Load formatted
string from firmware file, and the string ID can get back its string. Then,
use regular print format to show the message.

This firmware element layout looks like

    +============================================+
    |  elm ID  | elm size | version  |           |
    +----------+----------+----------+-----------+
    |                     | nr |rsvd |rfk_id|rsvd|
    +--------------------------------------------+
    | offset[] (__le16 * nr)                     |
    | ...                                        |
    +--------------------------------------------+
    | formatted string with null termintor (*nr) |
    | ...                                        |
    +============================================+

 * a firmware file can contains more than one elements with this element ID
   named RTW89_FW_ELEMENT_ID_RFKLOG_FMT (19), because many RFK needs its
   own formatted strings, so add 'rfk_id' to know it belongs to which RFK.
 * the 'formatted string' just follow 'offset[]' without padding to align
   32bits.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20231213005054.10568-4-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/phy.h

index e5dd51f79a6f4fa8a3f7727f2a07880c0f65b876..5c266f349d373e1d5b1926344bdd667b5702b2b0 100644 (file)
@@ -18,6 +18,7 @@ struct rtw89_mac_gen_def;
 struct rtw89_phy_gen_def;
 struct rtw89_efuse_block_cfg;
 struct rtw89_fw_txpwr_track_cfg;
+struct rtw89_phy_rfk_log_fmt;
 
 extern const struct ieee80211_ops rtw89_ops;
 
@@ -3952,6 +3953,7 @@ struct rtw89_fw_elm_info {
        struct rtw89_phy_table *rf_radio[RF_PATH_MAX];
        struct rtw89_phy_table *rf_nctl;
        struct rtw89_fw_txpwr_track_cfg *txpwr_trk;
+       struct rtw89_phy_rfk_log_fmt *rfk_log_fmt;
 };
 
 struct rtw89_fw_info {
index 76c948da669ec6574adc5640864c197dc04e654b..c1ebf1b13c0f40e2f23718ff0d27fa3166b09113 100644 (file)
@@ -729,6 +729,31 @@ err:
        return -EFAULT;
 }
 
+static
+int rtw89_build_rfk_log_fmt_from_elm(struct rtw89_dev *rtwdev,
+                                    const struct rtw89_fw_element_hdr *elm,
+                                    const union rtw89_fw_element_arg arg)
+{
+       struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+       u8 rfk_id;
+
+       if (elm_info->rfk_log_fmt)
+               goto allocated;
+
+       elm_info->rfk_log_fmt = kzalloc(sizeof(*elm_info->rfk_log_fmt), GFP_KERNEL);
+       if (!elm_info->rfk_log_fmt)
+               return 1; /* this is an optional element, so just ignore this */
+
+allocated:
+       rfk_id = elm->u.rfk_log_fmt.rfk_id;
+       if (rfk_id >= RTW89_PHY_C2H_RFK_LOG_FUNC_NUM)
+               return 1;
+
+       elm_info->rfk_log_fmt->elm[rfk_id] = elm;
+
+       return 0;
+}
+
 static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
        [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
                                        { .fw_type = RTW89_FW_BBMCU0 }, NULL},
@@ -784,6 +809,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
        [RTW89_FW_ELEMENT_ID_TXPWR_TRK] = {
                rtw89_build_txpwr_trk_tbl_from_elm, {}, "PWR_TRK",
        },
+       [RTW89_FW_ELEMENT_ID_RFKLOG_FMT] = {
+               rtw89_build_rfk_log_fmt_from_elm, {}, NULL,
+       },
 };
 
 int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
@@ -1221,6 +1249,7 @@ static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev)
        rtw89_free_phy_tbl_from_elm(elm_info->rf_nctl);
 
        kfree(elm_info->txpwr_trk);
+       kfree(elm_info->rfk_log_fmt);
 }
 
 void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
index f2b61e9ad8a71c2c8a522eea4a58068add5f5745..55ccc07580dfcddbaf03b0eb65f3ac6b751f7226 100644 (file)
@@ -3427,6 +3427,7 @@ enum rtw89_fw_element_id {
        RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT = 16,
        RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU = 17,
        RTW89_FW_ELEMENT_ID_TXPWR_TRK = 18,
+       RTW89_FW_ELEMENT_ID_RFKLOG_FMT = 19,
 
        RTW89_FW_ELEMENT_ID_NUM,
 };
@@ -3542,6 +3543,13 @@ struct rtw89_fw_element_hdr {
                        __le32 rsvd;
                        s8 contents[][DELTA_SWINGIDX_SIZE];
                } __packed txpwr_trk;
+               struct {
+                       u8 nr;
+                       u8 rsvd[3];
+                       u8 rfk_id; /* enum rtw89_phy_c2h_rfk_log_func */
+                       u8 rsvd1[3];
+                       __le16 offset[];
+               } __packed rfk_log_fmt;
                struct __rtw89_fw_txpwr_element txpwr;
        } __packed u;
 } __packed;
index 6792b73e9ca34e5185665e6caacc1c16b92ab1ad..b60bc563d86f8137fe2c648436310495999380cf 100644 (file)
@@ -136,6 +136,17 @@ enum rtw89_phy_c2h_ra_func {
        RTW89_PHY_C2H_FUNC_RA_MAX,
 };
 
+enum rtw89_phy_c2h_rfk_log_func {
+       RTW89_PHY_C2H_RFK_LOG_FUNC_IQK = 0,
+       RTW89_PHY_C2H_RFK_LOG_FUNC_DPK = 1,
+       RTW89_PHY_C2H_RFK_LOG_FUNC_DACK = 2,
+       RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK = 3,
+       RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI = 4,
+       RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK = 5,
+
+       RTW89_PHY_C2H_RFK_LOG_FUNC_NUM,
+};
+
 enum rtw89_phy_c2h_dm_func {
        RTW89_PHY_C2H_DM_FUNC_FW_TEST,
        RTW89_PHY_C2H_DM_FUNC_FW_TRIG_TX_RPT,
@@ -483,6 +494,10 @@ struct rtw89_txpwr_limit_ru_be {
        s8 ru106_26[RTW89_RU_SEC_NUM_BE];
 };
 
+struct rtw89_phy_rfk_log_fmt {
+       const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
+};
+
 struct rtw89_phy_gen_def {
        u32 cr_base;
        const struct rtw89_ccx_regs *ccx;