]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: offload DMAC and CMAC init IO to firmware
authorChia-Yuan Li <leo.li@realtek.com>
Mon, 20 Apr 2026 03:40:44 +0000 (11:40 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 29 Apr 2026 04:50:50 +0000 (12:50 +0800)
During the initialization of DMAC and CMAC, the driver performs a
large number of consecutive register writes. Sending these I/O
requests individually over the host interface introduces significant
latency and delays the device bring-up process.

Optimize the initialization flow by wrapping the register write
sequences in mac.c and mac_be.c with rtw89_io_pack() and
rtw89_io_unpack(). This batches the operations and offloads them
to the firmware via H2C commands, which significantly accelerates
the overall initialization time.
(8852C USB2.0 AMD B450 1379 ms -> 1273 ms)

Signed-off-by: Chia-Yuan Li <leo.li@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260420034051.17666-10-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac_be.c

index 6f76ae2a99ce96e5daad5de7a4f0e958d46180d4..353d7b88fb1ac92d25aaf9c7c5ac48a595b435a8 100644 (file)
@@ -2336,6 +2336,8 @@ static int preload_init_set_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
 {
        u32 reg, max_preld_size, min_rsvd_size;
 
+       rtw89_io_pack(rtwdev);
+
        max_preld_size = (mac_idx == RTW89_MAC_0 ?
                          PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM) * PRELD_AMSDU_SIZE;
        reg = mac_idx == RTW89_MAC_0 ?
@@ -2349,6 +2351,8 @@ static int preload_init_set_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
        rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_TXENDWIN_MASK, PRELD_NEXT_WND);
        rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_RSVMINSZ_MASK, min_rsvd_size);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2428,11 +2432,15 @@ static int sta_sch_init_ax(struct rtw89_dev *rtwdev)
                return ret;
        }
 
+       rtw89_io_pack(rtwdev);
+
        rtw89_write32_set(rtwdev, R_AX_SS_CTRL, B_AX_SS_WARM_INIT_FLG);
        rtw89_write32_clr(rtwdev, R_AX_SS_CTRL, B_AX_SS_NONEMPTY_SS2FINFO_EN);
 
        _patch_ss2f_path(rtwdev);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2444,12 +2452,16 @@ static int mpdu_proc_init_ax(struct rtw89_dev *rtwdev)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD);
        rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD);
        rtw89_write32_set(rtwdev, R_AX_MPDU_PROC,
                          B_AX_APPEND_FCS | B_AX_A_ICV_ERR);
        rtw89_write32(rtwdev, R_AX_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2463,6 +2475,8 @@ static int sec_eng_init_ax(struct rtw89_dev *rtwdev)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        val = rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL);
        /* init clock */
        val |= (B_AX_CLK_EN_CGCMP | B_AX_CLK_EN_WAPI | B_AX_CLK_EN_WEP_TKIP);
@@ -2488,6 +2502,8 @@ static int sec_eng_init_ax(struct rtw89_dev *rtwdev)
                rtw89_write32_mask(rtwdev, R_AX_SEC_DEBUG1,
                                   B_AX_TX_TIMEOUT_SEL_MASK, AX_TX_TO_VAL);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2571,6 +2587,8 @@ static int scheduler_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PREBKF_CFG_1, mac_idx);
        if (rtwdev->chip->chip_id == RTL8852C)
                rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
@@ -2599,6 +2617,8 @@ static int scheduler_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
                                   SCH_PREBKF_24US);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2667,6 +2687,8 @@ static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        for (i = RTW89_MGNT; i <= RTW89_DATA; i++) {
                ret = rtw89_mac_typ_fltr_opt_ax(rtwdev, i, RTW89_FWD_TO_HOST,
                                                mac_idx);
@@ -2683,6 +2705,8 @@ static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        rtw89_write16(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx),
                      plcp_ftlr);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2729,6 +2753,8 @@ static int cca_ctrl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CCA_CONTROL, mac_idx);
        val = rtw89_read32(rtwdev, reg);
        val |= (B_AX_TB_CHK_BASIC_NAV | B_AX_TB_CHK_BTCCA |
@@ -2749,16 +2775,22 @@ static int cca_ctrl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
 
        _patch_dis_resp_chk(rtwdev, mac_idx);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
 static int nav_ctrl_init_ax(struct rtw89_dev *rtwdev)
 {
+       rtw89_io_pack(rtwdev);
+
        rtw89_write32_set(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_PLCP_UP_NAV_EN |
                                                     B_AX_WMAC_TF_UP_NAV_EN |
                                                     B_AX_WMAC_NAV_UPPER_EN);
        rtw89_write32_mask(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_NAV_UPPER_MASK, NAV_25MS);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2770,12 +2802,17 @@ static int spatial_reuse_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
        if (ret)
                return ret;
+
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_SR_CTRL, mac_idx);
        rtw89_write8_clr(rtwdev, reg, B_AX_SR_EN);
 
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BSSID_SRC_CTRL, mac_idx);
        rtw89_write8_set(rtwdev, reg, B_AX_PLCP_SRC_EN);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2788,6 +2825,8 @@ static int tmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MAC_LOOPBACK, mac_idx);
        rtw89_write32_clr(rtwdev, reg, B_AX_MACLBK_EN);
 
@@ -2798,6 +2837,8 @@ static int tmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_HIGH_MCS_THRE_MASK, TXDFIFO_HIGH_MCS_THRE);
        rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_LOW_MCS_THRE_MASK, TXDFIFO_LOW_MCS_THRE);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2812,6 +2853,8 @@ static int trxptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx);
        val = rtw89_read32(rtwdev, reg);
        val &= ~B_AX_WMAC_SPEC_SIFS_CCK_MASK;
@@ -2842,6 +2885,8 @@ static int trxptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        reg = rtw89_mac_reg_by_idx(rtwdev, rrsr->rsc.addr, mac_idx);
        rtw89_write32_mask(rtwdev, reg, rrsr->rsc.mask, rrsr->rsc.data);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -2876,6 +2921,8 @@ static int rmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        if (mac_idx == RTW89_MAC_0)
                rst_bacam(rtwdev);
 
@@ -2917,6 +2964,8 @@ static int rmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx);
        rtw89_write8_clr(rtwdev, reg, B_AX_VHT_SU_SIGB_CRC_CHK);
 
+       rtw89_io_unpack(rtwdev);
+
        return ret;
 }
 
@@ -2968,6 +3017,8 @@ static int ptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) {
                reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SIFS_SETTING, mac_idx);
                val = rtw89_read32(rtwdev, reg);
@@ -3005,6 +3056,8 @@ static int ptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
                                   B_AX_AMPDU_MAX_LEN_VHT_MASK, 0x3FF80);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
index 39a28fd27412bd462981f268b5014cfa0b445da3..a0fa8e0597398730707306779efbce8f365a041e 100644 (file)
@@ -1000,6 +1000,8 @@ static int mpdu_proc_init_be(struct rtw89_dev *rtwdev)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        rtw89_write32_set(rtwdev, R_BE_MPDU_PROC, B_BE_APPEND_FCS);
        rtw89_write32(rtwdev, R_BE_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL |
                                                   B_BE_CA_CHK_ADDRCAM_EN);
@@ -1019,6 +1021,8 @@ static int mpdu_proc_init_be(struct rtw89_dev *rtwdev)
        val32 = u32_replace_bits(val32, 1, B_BE_FWD_WLAN_CPU_TYPE_1_MASK);
        rtw89_write32(rtwdev, R_BE_DISP_FWD_WLAN_0, val32);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1031,6 +1035,8 @@ static int sec_eng_init_be(struct rtw89_dev *rtwdev)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        val32 = rtw89_read32(rtwdev, R_BE_SEC_ENG_CTRL);
        val32 |= B_BE_CLK_EN_CGCMP | B_BE_CLK_EN_WAPI | B_BE_CLK_EN_WEP_TKIP |
                 B_BE_SEC_TX_ENC | B_BE_SEC_RX_DEC |
@@ -1041,6 +1047,8 @@ static int sec_eng_init_be(struct rtw89_dev *rtwdev)
 
        rtw89_write32_set(rtwdev, R_BE_SEC_MPDU_PROC, B_BE_APPEND_ICV | B_BE_APPEND_MIC);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1083,13 +1091,16 @@ static int mlo_init_be(struct rtw89_dev *rtwdev)
        u32 reg;
        int ret;
 
-       val32 = rtw89_read32(rtwdev, R_BE_MLO_INIT_CTL);
+       rtw89_io_pack(rtwdev);
 
+       val32 = rtw89_read32(rtwdev, R_BE_MLO_INIT_CTL);
        val32 |= B_BE_MLO_TABLE_REINIT;
        rtw89_write32(rtwdev, R_BE_MLO_INIT_CTL, val32);
        val32 &= ~B_BE_MLO_TABLE_REINIT;
        rtw89_write32(rtwdev, R_BE_MLO_INIT_CTL, val32);
 
+       rtw89_io_unpack(rtwdev);
+
        ret = read_poll_timeout_atomic(rtw89_read32, val32,
                                       val32 & B_BE_MLO_TABLE_INIT_DONE,
                                       1, 1000, false, rtwdev, R_BE_MLO_INIT_CTL);
@@ -1101,9 +1112,13 @@ static int mlo_init_be(struct rtw89_dev *rtwdev)
        else
                reg = R_BE_SS_CTRL_V1;
 
+       rtw89_io_pack(rtwdev);
+
        rtw89_write32_set(rtwdev, reg, B_BE_MLO_HW_CHGLINK_EN);
        rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_ACQCHK_CFG_0, B_BE_R_MACID_ACQ_CHK_EN);
 
+       rtw89_io_unpack(rtwdev);
+
        return ret;
 }
 
@@ -1173,6 +1188,8 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        if (chip->chip_id == RTL8922D) {
                reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EXT_CTRL, mac_idx);
                rtw89_write32_set(rtwdev, reg, B_BE_CWCNT_PLUS_MODE);
@@ -1216,6 +1233,8 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                rtw89_write32_set(rtwdev, reg, B_BE_TX_NAV_RST_EDCA_EN);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1292,6 +1311,8 @@ static int rx_fltr_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        u32 reg;
        u32 val;
 
+       rtw89_io_pack(rtwdev);
+
        rtw89_mac_typ_fltr_opt_be(rtwdev, RTW89_MGNT, RTW89_FWD_TO_HOST, mac_idx);
        rtw89_mac_typ_fltr_opt_be(rtwdev, RTW89_CTRL, RTW89_FWD_TO_HOST, mac_idx);
        rtw89_mac_typ_fltr_opt_be(rtwdev, RTW89_DATA, RTW89_FWD_TO_HOST, mac_idx);
@@ -1309,6 +1330,8 @@ static int rx_fltr_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
              B_BE_LSIG_PARITY_CHK_EN | B_BE_CCK_SIG_CHK | B_BE_CCK_CRC_CHK;
        rtw89_write16(rtwdev, reg, val);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1322,6 +1345,8 @@ static int nav_ctrl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        u32 val32;
        u32 reg;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMAC_NAV_CTL, mac_idx);
 
        val32 = rtw89_read32(rtwdev, reg);
@@ -1337,6 +1362,8 @@ static int nav_ctrl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_0, mac_idx);
        rtw89_write32_set(rtwdev, reg, B_BE_WMAC_MBA_DUR_FORCE);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1349,12 +1376,16 @@ static int spatial_reuse_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_SR_CTRL, mac_idx);
        rtw89_write8_clr(rtwdev, reg, B_BE_SR_EN | B_BE_SR_CTRL_PLCP_EN);
 
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_BSSID_SRC_CTRL, mac_idx);
        rtw89_write8_set(rtwdev, reg, B_BE_PLCP_SRC_EN);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1364,6 +1395,8 @@ static int tmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        struct rtw89_hal *hal = &rtwdev->hal;
        u32 reg;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TB_PPDU_CTRL, mac_idx);
        rtw89_write32_clr(rtwdev, reg, B_BE_QOSNULL_UPD_MUEDCA_EN);
 
@@ -1378,6 +1411,8 @@ static int tmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                rtw89_write32_clr(rtwdev, reg, CLEAR_DTOP_DIS);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1394,6 +1429,8 @@ static int trxptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_MAC_LOOPBACK, mac_idx);
        val32 = rtw89_read32(rtwdev, reg);
        val32 = u32_replace_bits(val32, S_BE_MACLBK_PLCP_DLY_DEF,
@@ -1453,6 +1490,8 @@ static int trxptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                rtw89_write32_mask(rtwdev, reg, B_BE_RSC_MASK, 1);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1495,6 +1534,8 @@ static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                        return ret;
        }
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_DLK_PROTECT_CTL, mac_idx);
        val16 = rtw89_read16(rtwdev, reg);
        val16 = u16_replace_bits(val16, TRXCFG_RMAC_DATA_TO, B_BE_RX_DLK_DATA_TIME_MASK);
@@ -1534,6 +1575,8 @@ static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                rtw89_write32_set(rtwdev, reg, B_BE_DIS_CHK_MIN_LEN);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1555,10 +1598,14 @@ static int resp_pktctl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                return ret;
        }
 
+       rtw89_io_pack(rtwdev);
+
        reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RESP_CSI_RESERVED_PAGE, mac_idx);
        rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_START_PAGE_MASK, qt_cfg.pktid);
        rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_PAGE_NUM_MASK, qt_cfg.pg_num + 1);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1602,6 +1649,8 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
        if (ret)
                return ret;
 
+       rtw89_io_pack(rtwdev);
+
        if (is_qta_poh(rtwdev)) {
                reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SIFS_SETTING, mac_idx);
                val32 = rtw89_read32(rtwdev, reg);
@@ -1671,6 +1720,8 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
                                               B_BE_PRELD_HIQ_P0_EN);
        }
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }
 
@@ -1965,6 +2016,8 @@ static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx,
        if (!(chip->chip_id == RTL8922A || rtw89_mac_chk_preload_allow(rtwdev)))
                return 0;
 
+       rtw89_io_pack(rtwdev);
+
        max_preld_size = mac_idx == RTW89_MAC_0 ?
                         PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM;
        if (chip->chip_id == RTL8922D)
@@ -1997,6 +2050,8 @@ static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx,
        val32 |= B_BE_B0_PRELD_FEN;
        rtw89_write32(rtwdev, reg, val32);
 
+       rtw89_io_unpack(rtwdev);
+
        return 0;
 }