@@ -2634,6 +2634,13 @@ struct rtw89_dack_info {
#define RTW89_IQK_CHS_NR 2
#define RTW89_IQK_PATH_NR 4
+
+struct rtw89_mcc_info {
+ u8 ch[RTW89_IQK_CHS_NR];
+ u8 band[RTW89_IQK_CHS_NR];
+ u8 table_idx;
+};
+
struct rtw89_iqk_info {
bool lok_cor_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
bool lok_fin_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
@@ -3105,6 +3112,7 @@ struct rtw89_dev {
struct rtw89_dack_info dack;
struct rtw89_iqk_info iqk;
struct rtw89_dpk_info dpk;
+ struct rtw89_mcc_info mcc;
bool is_tssi_mode[RF_PATH_MAX];
bool is_bt_iqk_timeout;
@@ -1785,6 +1785,45 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
return -EBUSY;
}
+int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
+ struct rtw89_fw_h2c_rf_get_mccch *mccch;
+ struct sk_buff *skb;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, sizeof(*mccch));
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, sizeof(*mccch));
+ mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data;
+
+ mccch->ch_0 = cpu_to_le32(mcc_info->ch[0]);
+ mccch->ch_1 = cpu_to_le32(mcc_info->ch[1]);
+ mccch->band_0 = cpu_to_le32(mcc_info->band[0]);
+ mccch->band_1 = cpu_to_le32(mcc_info->band[1]);
+ mccch->current_channel = cpu_to_le32(rtwdev->hal.current_channel);
+ mccch->current_band_type = cpu_to_le32(rtwdev->hal.current_band_type);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
+ H2C_FUNC_OUTSRC_RF_GET_MCCCH, 0, 0,
+ sizeof(*mccch));
+
+ if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return -EBUSY;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc);
+
int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
bool rack, bool dack)
@@ -2538,6 +2538,17 @@ struct rtw89_fw_h2c_rf_reg_info {
#define H2C_CL_OUTSRC_RF_REG_A 0x8
#define H2C_CL_OUTSRC_RF_REG_B 0x9
+#define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa
+#define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2
+
+struct rtw89_fw_h2c_rf_get_mccch {
+ __le32 ch_0;
+ __le32 ch_1;
+ __le32 band_0;
+ __le32 band_1;
+ __le32 current_channel;
+ __le32 current_band_type;
+} __packed;
#define RTW89_FW_RSVD_PLE_SIZE 0x800
@@ -2602,6 +2613,7 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
struct rtw89_fw_h2c_rf_reg_info *info,
u16 len, u8 page);
+int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
bool rack, bool dack);
@@ -1766,6 +1766,18 @@ static void rtw8852c_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
}
}
+static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
+
+ memset(mcc_info, 0, sizeof(*mcc_info));
+}
+
+static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
+{
+ rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
+}
+
static
void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
s8 pw_ofst, enum rtw89_mac_idx mac_idx)
@@ -1955,6 +1967,8 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.set_channel_help = rtw8852c_set_channel_help,
.read_efuse = rtw8852c_read_efuse,
.read_phycap = rtw8852c_read_phycap,
+ .rfk_init = rtw8852c_rfk_init,
+ .rfk_channel = rtw8852c_rfk_channel,
.power_trim = rtw8852c_power_trim,
.read_rf = rtw89_phy_read_rf_v1,
.write_rf = rtw89_phy_write_rf_v1,
IQK results in hardware has two copies that are used by firmware to switch these two to support MCC. This H2C tell firmware the corresponding channel and band of each IQK results, and currrent one. Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> --- drivers/net/wireless/realtek/rtw89/core.h | 8 ++++ drivers/net/wireless/realtek/rtw89/fw.c | 39 +++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 12 ++++++ drivers/net/wireless/realtek/rtw89/rtw8852c.c | 14 +++++++ 4 files changed, 73 insertions(+)