diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index b42d3a4df4bf..b7d5eb25ef74 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4685,6 +4685,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V2, + RTW89_FW_FEATURE_WITH_RFK_PRE_NOTIFY, RTW89_FW_FEATURE_RFK_RXDCK_V0, RTW89_FW_FEATURE_RFK_IQK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, @@ -5239,6 +5240,7 @@ struct rtw89_rfk_mcc_info_data { u8 ch[RTW89_RFK_CHS_NR]; u8 band[RTW89_RFK_CHS_NR]; u8 bw[RTW89_RFK_CHS_NR]; + u32 rf18[RTW89_RFK_CHS_NR]; u8 table_idx; }; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d05b15ea022a..d13c93fafb34 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -892,6 +892,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING), + __CFG_FW_FEAT(RTL8922A, le, 0, 35, 80, 0, WITH_RFK_PRE_NOTIFY), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0), }; @@ -6490,6 +6491,65 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, return ret; } +int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_fw_h2c_rfk_pre_info_mcc *h2c; + struct rtw89_hal *hal = &rtwdev->hal; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 tbl, path; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c rfk_pre_ntfy_mcc\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_fw_h2c_rfk_pre_info_mcc *)skb->data; + + BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR); + + for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) + h2c->tbl_18[tbl] = cpu_to_le32(rfk_mcc->rf18[tbl]); + + BUILD_BUG_ON(ARRAY_SIZE(rtwdev->rfk_mcc.data) < NUM_OF_RTW89_FW_RFK_PATH); + + /* shared table array, but tbl_sel can be independent by path */ + for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { + tbl = rfk_mcc[path].table_idx; + h2c->cur_18[path] = cpu_to_le32(rfk_mcc->rf18[tbl]); + + if (path == phy_idx) + h2c->tbl_idx = tbl; + } + + h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + + if (rtw89_is_mlo_1_1(rtwdev)) + h2c->mlo_1_1 = cpu_to_le32(1); + + h2c->phy_idx = phy_idx; + h2c->aid = cpu_to_le32(hal->aid); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, + H2C_FUNC_OUTSRC_RF_MCC_INFO, 0, 0, len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode) { diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index f12728ccb31f..5292b568e2bf 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4471,6 +4471,7 @@ enum rtw89_mrc_h2c_func { #define H2C_CL_OUTSRC_RF_REG_B 0x9 #define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa #define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2 +#define H2C_FUNC_OUTSRC_RF_MCC_INFO 0xf #define H2C_FUNC_OUTSRC_RF_PS_INFO 0x10 #define H2C_CL_OUTSRC_RF_FW_RFK 0xb @@ -4585,6 +4586,17 @@ struct rtw89_fw_h2c_rfk_pre_info { __le32 mlo_1_1; } __packed; +struct rtw89_fw_h2c_rfk_pre_info_mcc { + __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL]; + __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; + __le32 mlo_1_1; + u8 phy_idx; + u8 tbl_idx; + u8 rsvd[2]; + __le32 aid; +} __packed; + struct rtw89_h2c_rf_tssi { __le16 len; u8 phy; @@ -4942,6 +4954,7 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); int rtw89_fw_h2c_mcc_dig(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx chanctx_idx, u8 mcc_role_idx, u8 pd_val, bool en); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 9f418b1fb7ed..d0e5d52964de 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -3808,6 +3808,12 @@ int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev, { int ret; + if (RTW89_CHK_FW_FEATURE(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) + goto pre_ntfy; + + return rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx); + +pre_ntfy: rtw89_phy_rfk_report_prep(rtwdev); ret = rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);