From: Chih-Kang Chang The H2C command rtw89_fw_h2c_rf_pre_ntfy_mcc have different format. 8922A after FW 0.35.49.0 use v0, after FW 0.35.84.0 use v1. The coming 8922D will use v2. Signed-off-by: Chih-Kang Chang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.h | 5 ++ drivers/net/wireless/realtek/rtw89/fw.c | 55 ++++++++++++++++--- drivers/net/wireless/realtek/rtw89/fw.h | 12 +++- drivers/net/wireless/realtek/rtw89/phy.c | 23 ++++---- .../net/wireless/realtek/rtw89/rtw8922a_rfk.c | 48 +++++++++++++++- 5 files changed, 122 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 38a64b0bfb5c..661b6a23082a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4688,6 +4688,11 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V2, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V3, ), + RTW89_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V0, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V1, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V2, + ), RTW89_FW_FEATURE_RFK_RXDCK_V0, RTW89_FW_FEATURE_RFK_IQK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index fed9b3db1543..24077a8095c4 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -912,6 +912,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 46, 0, NOTIFY_AP_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_V2), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_MCC_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 71, 0, BEACON_LOSS_COUNT_V1), @@ -919,6 +920,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING), __DIS_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, WITH_RFK_PRE_NOTIFY, G), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, RFK_PRE_NOTIFY_MCC_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0), }; @@ -6529,45 +6531,84 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, 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_rfk_mcc_info *rfk_mcc_v0 = &rtwdev->rfk_mcc; + struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *h2c_v0; + struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *h2c_v1; struct rtw89_fw_h2c_rfk_pre_info_mcc *h2c; struct rtw89_hal *hal = &rtwdev->hal; u32 len = sizeof(*h2c); struct sk_buff *skb; + u8 ver = U8_MAX; u8 tbl, path; + u8 tbl_sel; int ret; + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V2, &rtwdev->fw)) { + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw)) { + len = sizeof(*h2c_v1); + ver = 1; + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V0, &rtwdev->fw)) { + len = sizeof(*h2c_v0); + ver = 0; + } + 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; + + if (ver != 0) + goto v1; + + h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *)skb->data; + for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) { + for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { + h2c_v0->tbl_18[tbl][path] = + cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl]); + tbl_sel = rfk_mcc_v0->data[path].table_idx; + h2c_v0->cur_18[path] = + cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl_sel]); + } + } + + h2c_v0->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + goto done; + +v1: + h2c_v1 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *)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]); + h2c_v1->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]); + h2c_v1->cur_18[path] = cpu_to_le32(rfk_mcc->rf18[tbl]); if (path == phy_idx) - h2c->tbl_idx = tbl; + h2c_v1->tbl_idx = tbl; } - h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + h2c_v1->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + h2c_v1->phy_idx = phy_idx; if (rtw89_is_mlo_1_1(rtwdev)) - h2c->mlo_1_1 = cpu_to_le32(1); + h2c_v1->mlo_1_1 = cpu_to_le32(1); + + if (ver == 1) + goto done; + + h2c = (struct rtw89_fw_h2c_rfk_pre_info_mcc *)skb->data; - h2c->phy_idx = phy_idx; h2c->aid = cpu_to_le32(hal->aid); +done: 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); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 5292b568e2bf..91eaf07f5824 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4586,13 +4586,23 @@ struct rtw89_fw_h2c_rfk_pre_info { __le32 mlo_1_1; } __packed; -struct rtw89_fw_h2c_rfk_pre_info_mcc { +struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 { + __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL][NUM_OF_RTW89_FW_RFK_PATH]; + __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; +} __packed; + +struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 { __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; +} __packed; + +struct rtw89_fw_h2c_rfk_pre_info_mcc { + struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 base; u8 rsvd[2]; __le32 aid; } __packed; diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index f56b433a1674..d29fbc9cb5ac 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -3808,19 +3808,22 @@ int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev, { int ret; - if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) - goto pre_ntfy; - - return rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx); + 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); + if (ret) + return ret; + } -pre_ntfy: - rtw89_phy_rfk_report_prep(rtwdev); + if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, &rtwdev->fw)) { + ret = rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx); + if (ret) + return ret; + } - ret = rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx); - if (ret) - return ret; + return 0; - return rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms); } EXPORT_SYMBOL(rtw89_phy_rfk_pre_ntfy_and_wait); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c index fce094c7ce93..98f14b31cf52 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c @@ -205,11 +205,11 @@ static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx) } } -static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, - const struct rtw89_chan *chan, u8 path) +static u8 rtw8922a_chlk_reload_sel_tbl_v0(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) { - struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {}; + struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; u8 tbl_sel; for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) { @@ -229,11 +229,53 @@ static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, rfk_mcc->data[path].ch[tbl_sel] = chan->channel; rfk_mcc->data[path].band[tbl_sel] = chan->band_type; rfk_mcc->data[path].bw[tbl_sel] = chan->band_width; + rfk_mcc->data[path].rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan); rfk_mcc->data[path].table_idx = tbl_sel; return tbl_sel; } +static u8 rtw8922a_chlk_reload_sel_tbl_v1(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) +{ + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {}; + u8 tbl_sel; + + for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) { + struct rtw89_rfk_chan_desc *p = &desc[tbl_sel]; + + p->ch = rfk_mcc->ch[tbl_sel]; + + p->has_band = true; + p->band = rfk_mcc->band[tbl_sel]; + + p->has_bw = true; + p->bw = rfk_mcc->bw[tbl_sel]; + } + + tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan); + + rfk_mcc->ch[tbl_sel] = chan->channel; + rfk_mcc->band[tbl_sel] = chan->band_type; + rfk_mcc->bw[tbl_sel] = chan->band_width; + rfk_mcc->rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan); + + /* shared table array, but tbl_sel can be independent by path */ + rfk_mcc[path].table_idx = tbl_sel; + + return tbl_sel; +} + +static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) +{ + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw)) + return rtw8922a_chlk_reload_sel_tbl_v1(rtwdev, chan, path); + else + return rtw8922a_chlk_reload_sel_tbl_v0(rtwdev, chan, path); +} + static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev) { const struct rtw89_chan *chan0, *chan1; -- 2.25.1