From: Ching-Te Ku The version 11 init info add current RF path control information. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 2 + drivers/net/wireless/realtek/rtw89/coex.h | 19 ++++ drivers/net/wireless/realtek/rtw89/core.h | 47 ++++++++++ drivers/net/wireless/realtek/rtw89/fw.c | 75 ++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 6 ++ drivers/net/wireless/realtek/rtw89/rtw8922a.c | 88 ++++++++++++++++--- drivers/net/wireless/realtek/rtw89/rtw8922d.c | 40 ++++++--- 7 files changed, 251 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 6a1888d8c476..f94866e1f43a 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -3199,6 +3199,8 @@ static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) rtw89_fw_h2c_cxdrv_init_v7(rtwdev, index); else if (ver->fcxinit == 10) rtw89_fw_h2c_cxdrv_init_v10(rtwdev, index); + else if (ver->fcxinit == 11) + rtw89_fw_h2c_cxdrv_init_v11(rtwdev, index); else rtw89_fw_h2c_cxdrv_init(rtwdev, index); break; diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index 3238c44429a9..41a68ab21d80 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -127,6 +127,11 @@ enum btc_fddt_en { ((__rssi == BTC_RSSI_ST_LOW || \ __rssi == BTC_RSSI_ST_HIGH) ? 1 : 0); }) +/* Antenna TX/RX path position masks and helpers */ +#define BTC_ANT_TX_MASK 0xf0 +#define BTC_ANT_RX_MASK 0x0f +#define BTC_ANT_SHIFT 4 + enum btc_ant { BTC_ANT_SHARED = 0, BTC_ANT_DEDICATED, @@ -473,4 +478,18 @@ void btc_dw2b(u8 *buf, size_t idx, u32 val) buf[idx + 3] = u32_get_bits(val, MASKBYTE3); } +static inline +u8 _btc_get_rf_path_from_ant_num(struct rtw89_btc *btc, u8 antnum) +{ + switch (antnum) { + default: + case 1: + return btc->mdinfo.ant.single_pos; + case 2: + return RF_PATH_AB; + case 3: + return RF_PATH_ABC; + } +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 7573f1965c98..7147e186b4a5 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1537,6 +1537,21 @@ struct rtw89_btc_ant_info_v10 { u8 ant_xmap[2][4]; } __packed; +struct rtw89_btc_ant_info_v11 { + u8 type; + u8 num; + u8 isolation; + u8 single_pos; + + u8 stream_cnt; + u8 path_pos; /* WL path position: Tx[7:4], Rx[3:0] */ + u8 btg_pos; + u8 btg1_pos; + u8 func[5]; + u8 ant_xmap[2][4]; + u8 rsvd0[3]; +} __packed; + struct rtw89_btc_ant_info { u8 type; /* shared, dedicated(non-shared) */ u8 num; /* antenna count */ @@ -1546,6 +1561,7 @@ struct rtw89_btc_ant_info { u8 stream_cnt; /* spatial_stream count: Tx[7:4], Rx[3:0] */ u8 btg_pos; /* BT0 btg-circuit at 0:WL-S0/1:WL-S1 */ u8 btg1_pos; /* BT1 btg-circuit at 0:WL-S0/1:WL-S1 */ + u8 path_pos; /* WL path position: Tx[7:4], Rx[3:0] */ u8 func[5]; /* function at 1~5 Ant refer to enum btc_bt_func_type */ u8 ant_xmap[2][4]; @@ -2387,10 +2403,25 @@ struct rtw89_btc_module_v10 { struct rtw89_btc_ant_info_v10 ant; } __packed; +struct rtw89_btc_module_v11 { + u8 rfe_type; + u8 wa_type; + u8 kt_ver; + u8 kt_ver_adie; + + u8 bt0_pos; + u8 bt0_sw_type; + u8 bt1_pos; + u8 bt1_sw_type; + + struct rtw89_btc_ant_info_v11 ant; +} __packed; + union rtw89_btc_module_info { struct rtw89_btc_module_v0 md_v0; struct rtw89_btc_module_v7 md_v7; struct rtw89_btc_module_v10 md_v10; + struct rtw89_btc_module_v11 md_v11; }; struct rtw89_btc_module { @@ -2473,11 +2504,26 @@ struct rtw89_btc_init_info_v10 { struct rtw89_btc_module_v10 module; } __packed; +struct rtw89_btc_init_info_v11 { + u8 endian_type; /* 0: little-endian, 1:big-endian */ + u8 init_mode; /* refer to enum BTC_MODE_xxx */ + u8 wl_init_ok; + u8 bt0_function; + + u8 bt1_function; + u8 bt2_function; + u8 pta_mode; + u8 pta_direction; + + struct rtw89_btc_module_v11 module; +}; + union rtw89_btc_init_info_u { struct rtw89_btc_init_info_v0 init_v0; struct rtw89_btc_init_info_v7 init_v7; struct rtw89_btc_init_info_v10 init_v10; struct rtw89_btc_init_info_v107 init_v107; + struct rtw89_btc_init_info_v11 init_v11; }; struct rtw89_btc_init_info { @@ -2547,6 +2593,7 @@ enum rtw89_btc_bt_func_type { #define RTW89_BTC_BT_DEF_BR_TX_PWR 4 #define RTW89_BTC_BT_DEF_LE_TX_PWR 4 #define RTW89_BTC_DEFAULT_ANISO 10 +#define RTW89_BTC_BT_DEF_LE_TX_PWR_1 10 struct rtw89_btc_bt_scan_info_v1 { __le16 win; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 3b8c144e0e98..a3a04697e2e6 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -5973,6 +5973,81 @@ int rtw89_fw_h2c_cxdrv_init_v10(struct rtw89_dev *rtwdev, u8 type) return ret; } +int rtw89_fw_h2c_cxdrv_init_v11(struct rtw89_dev *rtwdev, u8 type) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_dm *dm = &btc->dm; + struct rtw89_btc_init_info *init = &dm->init_info; + struct rtw89_h2c_cxinit_v11 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_init_v11\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cxinit_v11 *)skb->data; + + h2c->hdr.type = type; + h2c->hdr.ver = 11; + h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7; + + h2c->init.endian_type = init->endian_type; + h2c->init.init_mode = init->init_mode; + h2c->init.wl_init_ok = init->wl_init_ok; + h2c->init.bt0_function = init->bt0_function; + + h2c->init.bt1_function = init->bt1_function; + h2c->init.bt2_function = init->bt2_function; + h2c->init.pta_mode = init->pta_mode; + h2c->init.pta_direction = init->pta_direction; + + h2c->init.module.rfe_type = init->module.rfe_type; + h2c->init.module.wa_type = init->module.wa_type; + h2c->init.module.kt_ver = init->module.kt_ver; + h2c->init.module.kt_ver_adie = init->module.kt_ver_adie; + + h2c->init.module.bt0_pos = init->module.bt0_pos; + h2c->init.module.bt0_sw_type = init->module.bt0_sw_type; + h2c->init.module.bt1_pos = init->module.bt1_pos; + h2c->init.module.bt1_sw_type = init->module.bt1_sw_type; + + h2c->init.module.ant.type = init->module.ant.type; + h2c->init.module.ant.num = init->module.ant.num; + h2c->init.module.ant.isolation = init->module.ant.isolation; + h2c->init.module.ant.single_pos = init->module.ant.single_pos; + + h2c->init.module.ant.stream_cnt = init->module.ant.stream_cnt; + h2c->init.module.ant.path_pos = init->module.ant.path_pos; + h2c->init.module.ant.btg_pos = init->module.ant.btg_pos; + h2c->init.module.ant.btg1_pos = init->module.ant.btg1_pos; + memcpy(h2c->init.module.ant.func, init->module.ant.func, + sizeof(init->module.ant.func)); + + memcpy(h2c->init.module.ant.ant_xmap, init->module.ant.ant_xmap, + sizeof(init->module.ant.ant_xmap)); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, BTFC_SET, + SET_DRV_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; +} + #define PORT_DATA_OFFSET 4 #define H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN 12 #define H2C_LEN_CXDRVINFO_ROLE_SIZE(max_role_num) \ diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index e86014ca249a..c0a00b721060 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2603,6 +2603,11 @@ struct rtw89_h2c_cxinit_v10 { struct rtw89_btc_init_info_v10 init; } __packed; +struct rtw89_h2c_cxinit_v11 { + struct rtw89_h2c_cxhdr_v7 hdr; + struct rtw89_btc_init_info_v11 init; +} __packed; + #define RTW89_H2C_CXROLE_V101_ROLE_STAT_CONNTECTED BIT(0) #define RTW89_H2C_CXROLE_V101_ROLE_STAT_PID GENMASK(3, 1) #define RTW89_H2C_CXROLE_V101_ROLE_STAT_PHY BIT(4) @@ -5456,6 +5461,7 @@ int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v7(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v10(struct rtw89_dev *rtwdev, u8 type); +int rtw89_fw_h2c_cxdrv_init_v11(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_osi_info(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_osi_info_v6(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 2586fd2df8ab..2d225e009b28 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -2721,25 +2721,33 @@ static u32 rtw8922a_chan_to_rf18_val(struct rtw89_dev *rtwdev, static void rtw8922a_btc_set_rfe(struct rtw89_dev *rtwdev) { - struct rtw89_btc_module *md = &rtwdev->btc.mdinfo; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_module *md = &btc->mdinfo; + u8 i, j; + u8 tx_path_pos, rx_path_pos; md->rfe_type = rtwdev->efuse.rfe_type; md->kt_ver = rtwdev->hal.cv; - md->bt_solo = 0; - md->bt0_sw_type = BTC_SWITCH_INTERNAL; + md->kt_ver_adie = rtwdev->hal.acv; md->wa_type = 0; - md->ant.type = BTC_ANT_SHARED; md->ant.num = 2; - md->ant.isolation = 10; - md->ant.diversity = 0; - md->ant.single_pos = RF_PATH_A; - md->ant.btg_pos = RF_PATH_B; + md->ant.single_pos = BTC_RF_S0; if (md->kt_ver <= 1) md->wa_type |= BTC_WA_HFP_ZB; - rtwdev->btc.cx.bt_ext.func_type = BTC_3CX_NONE; + btc->cx.bt0.ant_iso_to_wl = md->ant.isolation; + btc->cx.bt1.ant_iso_to_wl = md->ant.isolation; + + md->ant.stream_cnt = 2; + md->ant.btg_pos = RF_PATH_B; + md->ant.single_pos = RF_PATH_A; + + btc->cx.bt0.band_56G_support = 0; + btc->cx.bt1.band_56G_support = 0; + btc->cx.bt0.func_type = BTC_BTF_BT; + btc->cx.bt1.func_type = BTC_BTF_NONE; if (md->rfe_type == 0) { rtwdev->btc.dm.error.map.rfe_type0 = true; @@ -2747,17 +2755,69 @@ static void rtw8922a_btc_set_rfe(struct rtw89_dev *rtwdev) } md->ant.num = (md->rfe_type % 2) ? 2 : 3; - if (md->kt_ver == 0) md->ant.num = 2; - if (md->ant.num == 3) { - md->ant.type = BTC_ANT_DEDICATED; - md->bt0_pos = BTC_BT_ALONE; - } else { + memset(btc->dm.ant_xmap, 0, sizeof(btc->dm.ant_xmap)); + + switch (md->ant.num) { + case 1: md->ant.type = BTC_ANT_SHARED; md->bt0_pos = BTC_BT_BTG; + md->bt0_sw_type = BTC_SWITCH_V1_INTERNAL; + md->ant.btg_pos = BTC_RF_S0; + btc->dm.ant_xmap[BTC_RF_S0][BTC_BT_1ST] = 1; + md->ant.func[0] = BTC_EFMAP_BT0; + break; + case 2: /* 2-Ant */ + default: + md->ant.type = BTC_ANT_SHARED; + md->bt0_pos = BTC_BT_BTG; + md->bt0_sw_type = BTC_SWITCH_V1_INTERNAL; + btc->dm.wl_trx_nss_en = 1; + btc->dm.ant_xmap[BTC_RF_S1][BTC_BT_1ST] = 1; + md->ant.func[1] = BTC_EFMAP_BT0; + break; + case 3: /* 3-Ant, 3 different BT-configuration */ + /* WL-S0 + WL-S1 + BT0-S0 */ + md->ant.type = BTC_ANT_DEDICATED; + md->bt0_pos = BTC_BT_ALONE; + md->bt0_sw_type = BTC_SWITCH_V1_NONE; + md->ant.func[2] = BTC_EFMAP_BT0; + } + + tx_path_pos = _btc_get_rf_path_from_ant_num(btc, rtwdev->hal.tx_nss); + rx_path_pos = _btc_get_rf_path_from_ant_num(btc, rtwdev->hal.rx_nss); + /* Combine TX[7:4] and RX[3:0] into path_pos byte */ + md->ant.path_pos = ((tx_path_pos << BTC_ANT_SHIFT) & BTC_ANT_TX_MASK) | + (rx_path_pos & BTC_ANT_RX_MASK); + + switch (btc->cx.bt_ext.chip_id) { + default: + case BTC_ESOC_NONE: + memset(&btc->cx.bt_ext, 0, sizeof(struct rtw89_btc_extsoc_info)); + btc->cx.bt_ext.max_tx_pwr = RTW89_BTC_BT_DEF_LE_TX_PWR_1; + btc->cx.bt_ext.ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; + break; + case BTC_ESOC_8771: + btc->cx.bt_ext.func_type = BTC_BTF_THREAD; + btc->cx.bt_ext.hw_coex = BTC_EXTSOC_INTF_PTA; + btc->cx.bt_ext.rf_band_map = 0x1; /* 2.4G only */ + btc->cx.bt_ext.link_weight[BTC_BT_B2G] = 10; + btc->cx.bt_ext.profile_map[BTC_BT_B2G] |= BTC_BT_THREAD; + /* use GPIO 12~15 for Ext-4-wire-PTA */ + btc->cx.bt_ext.hpta_cfg = BIT(12) | BIT(13) | BIT(14) | BIT(15); + md->ant.func[2] = BTC_EFMAP_ZB; + break; } + + btc->dm.ant_xmap[BTC_RF_S0][BTC_BT_EXT] = 0; + btc->dm.ant_xmap[BTC_RF_S1][BTC_BT_EXT] = 0; + + for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) + for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) + md->ant.ant_xmap[i][j] = btc->dm.ant_xmap[i][j]; + rtwdev->btc.btg_pos = md->ant.btg_pos; rtwdev->btc.ant_type = md->ant.type; } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c index 12c96425a6ff..142e693c87bf 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c @@ -3174,7 +3174,9 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) struct rtw89_btc_dm *dm = &btc->dm; struct rtw89_btc_cx *cx = &btc->cx; u8 efuse_bt_func, efuse_ant_info, bt_sw_gpio_pos; - u8 is_combo, is_bt_share; + u8 is_combo, is_bt_share, is_spdt; + u8 tx_path_pos, rx_path_pos; + u8 i, j; rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s !!\n", __func__); @@ -3192,7 +3194,8 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) cx->bt0.ant_iso_to_wl = md->ant.isolation; cx->bt1.ant_iso_to_wl = md->ant.isolation; - md->ant.stream_cnt = 2; + md->ant.stream_cnt = (rtwdev->hal.tx_nss << BTC_ANT_SHIFT) + + rtwdev->hal.rx_nss; md->ant.btg_pos = BTC_RF_S1; /* BTG0 at WL-S1 */ md->ant.btg1_pos = BTC_RF_S0; /* BTG1 at WL-S0 if Dual-BTGA */ @@ -3203,19 +3206,20 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) efuse_bt_func = rtwdev->efuse.bt_setting_2; - switch ((efuse_bt_func & 0xe0) >> 5) { /* 0xcd[7:5] */ + is_spdt = !!(efuse_bt_func & BIT(5)); + + switch ((efuse_bt_func & 0xc0) >> 6) { /* 0xcd[7:6] */ default: case 0: - case 1: bt_sw_gpio_pos = 5; break; - case 2: + case 1: bt_sw_gpio_pos = 11; break; - case 3: + case 2: bt_sw_gpio_pos = 15; break; - case 4: + case 3: bt_sw_gpio_pos = 20; break; } @@ -3233,9 +3237,8 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) case 1: /* 1-Ant WL-S0 only & BT0 only */ md->ant.type = BTC_ANT_SHARED; md->bt0_pos = BTC_BT_BTG; - md->bt0_sw_type = BTC_SWITCH_INTERNAL; + md->bt0_sw_type = BTC_SWITCH_V1_INTERNAL; md->ant.btg_pos = BTC_RF_S0; /* BTG0 at WL-S0 */ - md->ant.stream_cnt = 1; md->ant.func[0] = BTC_EFMAP_BT0; dm->ant_xmap[BTC_RF_S0][BTC_BT_1ST] = 1; /* BT0 shared with S0*/ dm->ant_xmap[BTC_RF_S1][BTC_BT_1ST] = 0; /* WL 1T1R no RF-S1 */ @@ -3265,13 +3268,13 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) if (md->ant.func[0] == BTC_EFMAP_BT1) { /* if 2nd BT exist */ dm->ant_xmap[BTC_RF_S0][BTC_BT_2ND] = 1; - if (md->rfe_type == 12) { /* WL-S0 & BT1 by SPDT */ + if (is_spdt) { /* WL-S0 & BT1 by SPDT */ md->bt1_pos = BTC_BT_ALONE; /* Todo: set SPDT GPIO-ctrl */ md->bt1_sw_type = bt_sw_gpio_pos; } else { /* WL-S0 & BT1-S1 by BTGA */ md->bt1_pos = BTC_BT_BTG; - md->bt1_sw_type = BTC_SWITCH_INTERNAL; + md->bt1_sw_type = BTC_SWITCH_V1_INTERNAL; } } @@ -3284,7 +3287,7 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) md->ant.func[2] = efuse_bt_func & (~BTC_EFMAP_BT0); md->ant.type = BTC_ANT_SHARED; md->bt0_pos = BTC_BT_BTG; - md->bt0_sw_type = BTC_SWITCH_INTERNAL; + md->bt0_sw_type = BTC_SWITCH_V1_INTERNAL; dm->ant_xmap[BTC_RF_S1][BTC_BT_1ST] = 1; dm->wl_trx_nss_en = 1; /* 1ss MIMO-PS capability */ } else { @@ -3324,6 +3327,12 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) break; } + tx_path_pos = _btc_get_rf_path_from_ant_num(btc, rtwdev->hal.tx_nss); + rx_path_pos = _btc_get_rf_path_from_ant_num(btc, rtwdev->hal.rx_nss); + /* Combine TX[7:4] and RX[3:0] into path_pos byte */ + md->ant.path_pos = ((tx_path_pos << BTC_ANT_SHIFT) & BTC_ANT_TX_MASK) | + (rx_path_pos & BTC_ANT_RX_MASK); + /* * if only BT0 at BTGA: 2-Ant, 3-Ant(BT1 used dedicated-ant) * can setup dm->wl_trx_nss_en = 1, WL MIMO-PS to 1T1R @@ -3373,6 +3382,13 @@ static void rtw8922d_btc_set_rfe(struct rtw89_dev *rtwdev) dm->ant_xmap[BTC_RF_S0][BTC_BT_EXT] = 0; dm->ant_xmap[BTC_RF_S1][BTC_BT_EXT] = 0; + + for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) + for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) + md->ant.ant_xmap[i][j] = dm->ant_xmap[i][j]; + + rtwdev->btc.btg_pos = md->ant.btg_pos; + rtwdev->btc.ant_type = md->ant.type; } static void rtw8922d_btc_init_cfg(struct rtw89_dev *rtwdev) -- 2.25.1 From: Ching-Te Ku The info included MLO status, hardware status, firmware will set corresponding register control to do coexistence (PTA slot priority, RF switch etc.) Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 3 ++ drivers/net/wireless/realtek/rtw89/core.h | 19 ++++++++ drivers/net/wireless/realtek/rtw89/fw.c | 58 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 6 +++ 4 files changed, 86 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index f94866e1f43a..0c5599a23b4a 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -3274,6 +3274,9 @@ static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) else return; + if (ver->fcxmlo == 2) + rtw89_fw_h2c_cxdrv_mlo_v2(rtwdev, index); + break; case CXDRVINFO_OSI: if (!ver->fcxosi || ver->drvinfo_ver == 103) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 7147e186b4a5..0ec63f9510bd 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1783,6 +1783,25 @@ struct rtw89_btc_wl_dbcc_info { u8 role[RTW89_PHY_NUM]; /* role in each phy */ }; +struct rtw89_btc_wl_mlo_info_v2 { + u8 wmode[RTW89_PHY_NUM]; + u8 ch_type[RTW89_PHY_NUM]; + u8 hwb_rf_band[RTW89_PHY_NUM]; + u8 path_rf_band[RTW89_PHY_NUM]; + + u8 wtype; + u8 mrcx_mode; + u8 mrcx_act_hwb_map; + u8 mrcx_bt_slot_rsp; + + u8 rf_combination; + u8 mlo_en; + u8 mlo_adie; + u8 dual_hw_band_en; + + __le32 link_status; +} __packed; + struct rtw89_btc_wl_mlo_info { u8 wmode[RTW89_PHY_NUM]; /* enum phl_mr_wmode */ u8 ch_type[RTW89_PHY_NUM]; /* enum phl_mr_ch_type */ diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index a3a04697e2e6..5ab80bda3ae5 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -6616,6 +6616,64 @@ int rtw89_fw_h2c_cxdrv_role_v10(struct rtw89_dev *rtwdev, u8 type) return ret; } +int rtw89_fw_h2c_cxdrv_mlo_v2(struct rtw89_dev *rtwdev, u8 type) +{ + struct rtw89_btc_wl_mlo_info *mlo = &rtwdev->btc.cx.wl.mlo_info; + struct rtw89_h2c_cxmlo_v2 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_mlo_v2\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cxmlo_v2 *)skb->data; + + h2c->hdr.type = type; + h2c->hdr.ver = 2; + h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7; + + memcpy(h2c->mlo.wmode, mlo->wmode, + sizeof(h2c->mlo.wmode)); + memcpy(h2c->mlo.ch_type, mlo->ch_type, + sizeof(h2c->mlo.ch_type)); + memcpy(h2c->mlo.hwb_rf_band, mlo->hwb_rf_band, + sizeof(h2c->mlo.hwb_rf_band)); + memcpy(h2c->mlo.path_rf_band, mlo->path_rf_band, + sizeof(h2c->mlo.path_rf_band)); + + h2c->mlo.wtype = mlo->wtype; + h2c->mlo.mrcx_mode = mlo->mrcx_mode; + h2c->mlo.mrcx_act_hwb_map = mlo->mrcx_act_hwb_map; + h2c->mlo.mrcx_bt_slot_rsp = mlo->mrcx_bt_slot_rsp; + + h2c->mlo.rf_combination = mlo->rf_combination; + h2c->mlo.mlo_en = mlo->mlo_en; + h2c->mlo.mlo_adie = mlo->mlo_adie; + h2c->mlo.dual_hw_band_en = mlo->dual_hw_band_en; + h2c->mlo.link_status = cpu_to_le32(mlo->link_status); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, BTFC_SET, + SET_DRV_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_cxdrv_osi_info(struct rtw89_dev *rtwdev, u8 type) { struct rtw89_btc *btc = &rtwdev->btc; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index c0a00b721060..538df0fb42cc 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2453,6 +2453,11 @@ struct rtw89_h2c_cxrole_v10 { struct rtw89_btc_wl_role_info_v10 r; } __packed; +struct rtw89_h2c_cxmlo_v2 { + struct rtw89_h2c_cxhdr_v7 hdr; + struct rtw89_btc_wl_mlo_info_v2 mlo; +} __packed; + struct rtw89_h2c_cxosi { struct rtw89_h2c_cxhdr_v7 hdr; struct rtw89_btc_fbtc_outsrc_set_info_v1 osi; @@ -5462,6 +5467,7 @@ int rtw89_fw_h2c_cxdrv_role_v7(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v10(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_init_v11(struct rtw89_dev *rtwdev, u8 type); +int rtw89_fw_h2c_cxdrv_mlo_v2(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_osi_info(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_osi_info_v6(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type); -- 2.25.1 From: Ching-Te Ku Add BTC version table entries for RTL8922A and RTL8922D. The new firmware need driver provide more chip initial related parameters. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 0c5599a23b4a..d873b9482e49 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -133,6 +133,15 @@ static const u32 cxtbl[] = { static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { /* firmware version must be in decreasing order for each chip */ + {RTL8922D, RTW89_FW_VER_CODE(0, 35, 111, 0), + .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, + .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, + .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, + .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, + .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, + .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, + .fcxtrx = 9, + }, {RTL8922D, RTW89_FW_VER_CODE(0, 35, 94, 0), .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, @@ -169,6 +178,15 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, .fcxtrx = 0, }, + {RTL8922A, RTW89_FW_VER_CODE(0, 35, 111, 0), + .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, + .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, + .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, + .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, + .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, + .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, + .fcxtrx = 9, + }, {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0), .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, -- 2.25.1 From: Ching-Te Ku rtw89_btc_wl_link_info is duplicated declaring in the function, remove one of them. We need MAC Address only when Wi-Fi role is station, included the copy operation into if statement. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 79 +++++++++++++++-------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index d873b9482e49..9da3b23b2d14 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -8675,13 +8675,14 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_p2p_noa_attr *noa_attr; + struct ieee80211_p2p_noa_desc *noa_desc; struct ieee80211_bss_conf *bss_conf; struct ieee80211_link_sta *link_sta; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_link_info r = {0}; - struct rtw89_btc_wl_link_info *wlinfo = NULL; - u8 mode = 0; + u8 i, mode = 0; rcu_read_lock(); @@ -8729,34 +8730,60 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); - wlinfo = &wl->rlink_info[rtwvif_link->port][rtwvif_link->phy_idx]; - - wlinfo->mode = mode; - wlinfo->role = rtwvif_link->wifi_role; - wlinfo->phy = rtwvif_link->phy_idx; - wlinfo->pid = rtwvif_link->port; - wlinfo->active = true; - wlinfo->connected = MLME_LINKED; - wlinfo->bcn_period = bss_conf->beacon_int; - wlinfo->dtim_period = bss_conf->dtim_period; - wlinfo->band = chan->band_type; - wlinfo->ch = chan->channel; - wlinfo->bw = chan->band_width; - wlinfo->chdef.band = chan->band_type; - wlinfo->chdef.center_ch = chan->channel; - wlinfo->chdef.bw = chan->band_width; - wlinfo->chdef.chan = chan->primary_channel; - ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + if (vif->type == NL80211_IFTYPE_P2P_GO || + vif->type == NL80211_IFTYPE_P2P_CLIENT) { + noa_attr = &bss_conf->p2p_noa_attr; - rcu_read_unlock(); + for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { + noa_desc = &noa_attr->desc[i]; + if (noa_desc->count != 0) { + r.noa = 1; + r.noa_duration = le32_to_cpu(noa_desc->duration); + break; + } + } + } + + r.mode = mode; + r.role = rtwvif_link->wifi_role; + r.phy = rtwvif_link->phy_idx; + r.pid = rtwvif_link->port; + r.active = true; + if (vif->active_links) { + if (rtwvif_link->link_id < 16) + r.active = !!(vif->active_links & BIT(rtwvif_link->link_id)); + } + r.bcn_period = bss_conf->beacon_int; + r.dtim_period = bss_conf->dtim_period; + r.band = chan->band_type; + r.ch = chan->channel; + r.bw = chan->band_width; + r.chdef.band = chan->band_type; + r.chdef.center_ch = chan->channel; + r.chdef.bw = chan->band_width; + r.chdef.chan = chan->primary_channel; + + if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) { + r.mac_id = rtwsta_link->mac_id; + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + } + + switch (state) { + case BTC_ROLE_MSTS_STA_CONN_END: + case BTC_ROLE_MSTS_AP_START: + r.connected = MLME_LINKED; + break; + default: + r.connected = MLME_NO_LINK; + break; + } - if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) - wlinfo->mac_id = rtwsta_link->mac_id; + rcu_read_unlock(); btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; - if (wlinfo->role == RTW89_WIFI_ROLE_STATION && - wlinfo->connected == MLME_NO_LINK) + if (r.role == RTW89_WIFI_ROLE_STATION && + r.connected == MLME_NO_LINK) btc->dm.leak_ap = 0; if (state == BTC_ROLE_MSTS_STA_CONN_START) { @@ -8774,7 +8801,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, state == BTC_ROLE_MSTS_STA_CONN_END) wl->status.map._4way = false; - _update_wl_info(rtwdev, wlinfo); + _update_wl_info(rtwdev, &r); _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); } -- 2.25.1 From: Ching-Te Ku To make logic more clearly, separate _ntfy_role_info into two function by data collecting and using. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 109 ++++++++++++++++------ 1 file changed, 80 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 9da3b23b2d14..ae458917ecf7 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -7233,6 +7233,7 @@ static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt, notv10); mode_v0 = wl_rinfo->link_mode_v0; } else if (!b2g && b5g && notv10) { + mode = _get_role_link_mode(wl_rinfo, cid_role[0], notv10); mode_v0 = BTC_WLINK_V0_5G; } else if (b2g && b5g) { mode = BTC_WLINK_DB_MCC; @@ -7247,6 +7248,7 @@ static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) } } else { mode = _get_role_link_mode(wl_rinfo, cid_role[0], notv10); + mode_v0 = wl_rinfo->link_mode_v0; } wl_rinfo->link_mode = mode; @@ -8667,6 +8669,78 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); } +static void _ntfy_role_info(struct rtw89_dev *rtwdev, u8 rid, + struct rtw89_btc_wl_link_info *info, + enum btc_role_state reason) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_wl_link_info *wlinfo = NULL; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + const struct rtw89_btc_ver *ver = btc->ver; + u8 rlink_id = info->phy; /* 1 role_id has 2 rlink_id(by HW_Band0/1) */ + bool refresh_role = false; + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(), role_id=%d, reason=%d\n", + __func__, rid, reason); + + if (rid >= ver->max_role_num || rlink_id >= RTW89_PHY_NUM) + return; + + btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; + + wlinfo = &wl->rlink_info[rid][rlink_id]; + memcpy(wlinfo, info, sizeof(struct rtw89_btc_wl_link_info)); + + switch (reason) { + case BTC_ROLE_START: + wlinfo->active = true; + return; + case BTC_ROLE_STOP: + wlinfo->active = false; + return; + case BTC_ROLE_MSTS_STA_CONN_START: + wl->status.map.transacting = 1; + wiphy_delayed_work_cancel(rtwdev->hw->wiphy, + &rtwdev->coex_act1_work); + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->coex_act1_work, + RTW89_COEX_ACT1_WORK_PERIOD); + break; + case BTC_ROLE_MSTS_STA_CONN_END: + wl->status.map.transacting = 0; + refresh_role = true; + break; + case BTC_ROLE_MSTS_STA_DIS_CONN: + wl->status.map.transacting = 1; + refresh_role = false; + wiphy_delayed_work_cancel(rtwdev->hw->wiphy, + &rtwdev->coex_act1_work); + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->coex_act1_work, + RTW89_COEX_ACT1_WORK_PERIOD); + break; + case BTC_ROLE_MSTS_AP_START: + case BTC_ROLE_MSTS_AP_STOP: + refresh_role = true; + break; + case BTC_ROLE_STATE_UNKNOWN: + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(), role_id=%d, Unknown reason return!\n", + __func__, rid); + return; + default: + return; + } + + if (refresh_role) { + _update_wl_info(rtwdev, wlinfo); + _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); + } + + _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); +} + void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -8679,20 +8753,20 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct ieee80211_p2p_noa_desc *noa_desc; struct ieee80211_bss_conf *bss_conf; struct ieee80211_link_sta *link_sta; - struct rtw89_btc *btc = &rtwdev->btc; - struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_link_info r = {0}; - u8 i, mode = 0; + u8 i, role_id, mode = 0; rcu_read_lock(); bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + role_id = rtwvif_link->port; + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], role is STA=%d\n", vif->type == NL80211_IFTYPE_STATION); - rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", role_id); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", chan->band_type, chan->channel, chan->band_width); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", @@ -8747,7 +8821,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, r.mode = mode; r.role = rtwvif_link->wifi_role; r.phy = rtwvif_link->phy_idx; - r.pid = rtwvif_link->port; + r.pid = role_id; r.active = true; if (vif->active_links) { if (rtwvif_link->link_id < 16) @@ -8780,30 +8854,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, rcu_read_unlock(); - btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; - - if (r.role == RTW89_WIFI_ROLE_STATION && - r.connected == MLME_NO_LINK) - btc->dm.leak_ap = 0; - - if (state == BTC_ROLE_MSTS_STA_CONN_START) { - wl->status.map.transacting = 1; - wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); - wiphy_delayed_work_queue(rtwdev->hw->wiphy, - &rtwdev->coex_act1_work, - RTW89_COEX_ACT1_WORK_PERIOD); - } else { - wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); - wl->status.map.transacting = 0; - } - - if (state == BTC_ROLE_MSTS_STA_DIS_CONN || - state == BTC_ROLE_MSTS_STA_CONN_END) - wl->status.map._4way = false; - - _update_wl_info(rtwdev, &r); - - _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); + _ntfy_role_info(rtwdev, role_id, &r, state); } void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) -- 2.25.1 From: Ching-Te Ku While Wi-Fi is doing special packet handshake, or going into some transient state, BT-Coexistence will held timer to fix control logic to protect the segment. Set the protection duration to 1 second, it is enough to cover the situation. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index 41a68ab21d80..355784941edd 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -69,7 +69,7 @@ enum btc_wl_rfk_type { #define NM_EXEC false #define FC_EXEC true -#define RTW89_COEX_ACT1_WORK_PERIOD round_jiffies_relative(HZ * 4) +#define RTW89_COEX_ACT1_WORK_PERIOD round_jiffies_relative(HZ) #define RTW89_COEX_BT_DEVINFO_WORK_PERIOD round_jiffies_relative(HZ * 16) #define RTW89_COEX_RFK_CHK_WORK_PERIOD msecs_to_jiffies(300) #define BTC_RFK_PATH_MAP GENMASK(3, 0) -- 2.25.1 From: Ching-Te Ku Complete the implementation of _fw_set_gpio() function to support all GPIO control configuration types for coexistence. Included debug signal, antenna switch, external I2C mailbox, external PTA related GPIO configuration. This function is called during initialization and when BT re-enables. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 234 +++++++++++++++++++++- drivers/net/wireless/realtek/rtw89/coex.h | 35 ---- drivers/net/wireless/realtek/rtw89/core.h | 162 ++++++++++++++- drivers/net/wireless/realtek/rtw89/fw.h | 10 + 4 files changed, 392 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index ae458917ecf7..96ec5fa20422 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -3206,6 +3206,212 @@ static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps); } +static u8 _get_gpiosig_for_ver(struct rtw89_dev *rtwdev, u8 sig_v8) +{ + const struct rtw89_btc_ver *ver = rtwdev->btc.ver; + + /* v8: gpio_ver >= 8, directly use v8 signal ID */ + if (ver->fcxgpiodbg >= 8) + return sig_v8; + + /* v7: gpio_ver < 8, convert v8 signal ID to v7 signal ID */ + if (sig_v8 <= BTC_DBG_GNT_WL) { + return sig_v8; + } else if (sig_v8 <= BTC_DBG_GNT_WL1) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): sig %d not supported in v7\n", + __func__, sig_v8); + return BTC_DBG_NUM; + } else if (sig_v8 >= BTC_DBG_NUM) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): sig %d not available\n", + __func__, sig_v8); + return BTC_DBG_NUM; + } else { + return sig_v8 - 2; + } +} + +static u32 _convert_gpio_enmap_to_ver(struct rtw89_dev *rtwdev, u32 en_map_v8) +{ + const struct rtw89_btc_ver *ver = rtwdev->btc.ver; + u32 en_map_v7 = 0; + u32 bit; + + /* v8: gpio_ver >= 8, directly use v8 en_map */ + if (ver->fcxgpiodbg >= 8) + return en_map_v8; + + /* v7: gpio_ver < 8, convert v8 en_map bitmap to v7 en_map bitmap */ + /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ + en_map_v7 |= en_map_v8 & GENMASK(1, 0); + + /* bit 2-3: GNT_BT1, GNT_WL1 - not supported in v7, skip these bits */ + + /* bit 4-31: shift right by 2 positions (become bit 2-29 in v7) */ + for (bit = BTC_DBG_BCN_EARLY; bit < BTC_DBG_NUM; bit++) { + if (en_map_v8 & BIT(bit)) + en_map_v7 |= BIT(bit - 2); + } + + return en_map_v7; +} + +static u32 _convert_gpio_enmap_from_ver(struct rtw89_dev *rtwdev, u32 en_map) +{ + const struct rtw89_btc_ver *ver = rtwdev->btc.ver; + u32 en_map_v8 = 0; + u32 bit; + + if (ver->fcxgpiodbg >= 8) + return en_map; + + /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ + en_map_v8 |= en_map & GENMASK(1, 0); + + /* bit 2-29: shift left by 2 positions (become bit 4-31 in v8) */ + for (bit = BTC_DBG_GNT_BT1; bit < BTC_DBG_NUM - 2; bit++) { + if (en_map & BIT(bit)) + en_map_v8 |= BIT(bit + 2); + } + + return en_map_v8; +} + +static void _fw_set_gpio(struct rtw89_dev *rtwdev, u8 type, u32 val) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_fbtc_h2c_set_gpio *gpio = &btc->gpio; + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_fbtc_h2c_set_gpio_2b l2_h2c; + struct rtw89_fbtc_h2c_set_gpio_4b l4_h2c; + u8 gpio_ver = ver->fcxgpiodbg; + u8 buf[sizeof(l4_h2c)]; + u8 len; + + if (gpio_ver < 8 && type > CXDGPIO_MUX_MAP) + return; + + if (type >= CXDGPIO_MAX) + return; + + switch (type) { + case CXDGPIO_EN_MAP: /* GPIO debug signal en-map 0~31 */ + val = _convert_gpio_enmap_to_ver(rtwdev, val); + gpio->en_map.data.type = CXDGPIO_EN_MAP; + gpio->en_map.data.fver = gpio_ver; + gpio->en_map.data.dlen = CXDGPIO_SET_L4; + gpio->en_map.data.en_map = val; + l4_h2c = gpio->en_map.fmt; + put_unaligned_le32(val, (u32 *)l4_h2c.data); + memcpy(buf, &l4_h2c, sizeof(l4_h2c)); + len = sizeof(l4_h2c); + break; + case CXDGPIO_MUX_MAP: /* GPIO dbg: Signal to GPIO Mux */ + gpio->mux.data.type = CXDGPIO_MUX_MAP; + gpio->mux.data.fver = gpio_ver; + gpio->mux.data.dlen = CXDGPIO_SET_L2; + gpio->mux.data.sig = _get_gpiosig_for_ver(rtwdev, + FIELD_GET(GENMASK(7, 0), val)); + if (gpio->mux.data.sig == 0xff) + return; + gpio->mux.data.gpio = FIELD_GET(GENMASK(15, 8), val); + l2_h2c = gpio->mux.fmt; + memcpy(buf, &l2_h2c, sizeof(l2_h2c)); + len = sizeof(l2_h2c); + break; + case CXDGPIO_EXT_HPTA: /* GPIO config for Ext HW-PTA */ + gpio->ext_pta.data.type = CXDGPIO_EXT_HPTA; + gpio->ext_pta.data.fver = gpio_ver; + gpio->ext_pta.data.dlen = CXDGPIO_SET_L2; + gpio->ext_pta.data.map_low = FIELD_GET(GENMASK(7, 0), val); + gpio->ext_pta.data.map_high = FIELD_GET(GENMASK(15, 8), val); + l2_h2c = gpio->ext_pta.fmt; + memcpy(buf, &l2_h2c, sizeof(l2_h2c)); + len = sizeof(l2_h2c); + break; + case CXDGPIO_EXT_HMBX: /* GPIO config for Ext HW-mailbox */ + gpio->ext_mb.data.type = CXDGPIO_EXT_HMBX; + gpio->ext_mb.data.fver = gpio_ver; + gpio->ext_mb.data.dlen = CXDGPIO_SET_L2; + gpio->ext_mb.data.map_low = FIELD_GET(GENMASK(7, 0), val); + gpio->ext_mb.data.map_high = FIELD_GET(GENMASK(15, 8), val); + l2_h2c = gpio->ext_mb.fmt; + memcpy(buf, &l2_h2c, sizeof(l2_h2c)); + len = sizeof(l2_h2c); + break; + case CXDGPIO_EXT_SWOUT: /* GPIO config for Ext SW output (wlan_act) */ + gpio->ext_swout.data.type = CXDGPIO_EXT_SWOUT; + gpio->ext_swout.data.fver = gpio_ver; + gpio->ext_swout.data.dlen = CXDGPIO_SET_L2; + gpio->ext_swout.data.map_low = FIELD_GET(GENMASK(7, 0), val); + gpio->ext_swout.data.map_high = FIELD_GET(GENMASK(15, 8), val); + l2_h2c = gpio->ext_swout.fmt; + memcpy(buf, &l2_h2c, sizeof(l2_h2c)); + len = sizeof(l2_h2c); + break; + case CXDGPIO_EXT_SWIN: /* GPIO config for Ext SW input control */ + gpio->ext_swin.data.type = CXDGPIO_EXT_SWIN; + gpio->ext_swin.data.fver = gpio_ver; + gpio->ext_swin.data.dlen = CXDGPIO_SET_L4; + gpio->ext_swin.data.in_map_low = FIELD_GET(GENMASK(7, 0), val); + gpio->ext_swin.data.in_map_high = FIELD_GET(GENMASK(15, 8), val); + gpio->ext_swin.data.int_map_low = FIELD_GET(GENMASK(23, 16), val); + gpio->ext_swin.data.int_map_high = FIELD_GET(GENMASK(31, 24), val); + l4_h2c = gpio->ext_swin.fmt; + put_unaligned_le32(val, (u32 *)l4_h2c.data); + memcpy(buf, &l4_h2c, sizeof(l4_h2c)); + len = sizeof(l4_h2c); + break; + default: + return; + } + + _send_fw_cmd(rtwdev, BTFC_SET, SET_GPIO_DBG, buf, len); +} + +static void _set_ext_interface(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + u8 bt1_sw_type = BTC_SWITCH_INTERNAL; + u32 val; + + if (btc->ver->fcxgpiodbg < 7) + return; + + /* if BT1+WL-S0, route DBG_GNT_BT1 to control SPDT */ + if ((rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && + btc->ver->fcxinit >= 10) { + if (btc->ver->fcxinit >= 10) + bt1_sw_type = btc->mdinfo.bt1_sw_type; + else + return; + + if (bt1_sw_type > BTC_SWITCH_INTERNAL) { + _fw_set_gpio(rtwdev, CXDGPIO_EN_MAP, + BIT(BTC_DBG_GNT_BT1)); + + val = (bt1_sw_type << 8) + BTC_DBG_GNT_BT1; + _fw_set_gpio(rtwdev, CXDGPIO_MUX_MAP, val); + } + } + + /* set GPIO as Ext-PTA interface wire */ + if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_PTA) + _fw_set_gpio(rtwdev, CXDGPIO_EXT_HPTA, cx->bt_ext.hpta_cfg); + + /* set GPIO as Ext-mailbox interface wire */ + if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_MBX) + _fw_set_gpio(rtwdev, CXDGPIO_EXT_HMBX, cx->bt_ext.hmbx_cfg); + + /* set GPIO as Ext-SWIO interface wire */ + if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_SWIO) { + _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWOUT, cx->bt_ext.swout_cfg); + _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWIN, cx->bt_ext.swin_cfg); + } +} + static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) { struct rtw89_btc *btc = &rtwdev->btc; @@ -8251,6 +8457,7 @@ static void _set_init_info(struct rtw89_dev *rtwdev) _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); rtw89_btc_fw_set_slots(rtwdev); btc_fw_set_monreg(rtwdev); + _set_ext_interface(rtwdev); _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0); } @@ -9779,6 +9986,8 @@ static const char *id_to_gdbg(u32 id) switch (id) { CASE_BTC_GDBG_STR(GNT_BT); CASE_BTC_GDBG_STR(GNT_WL); + CASE_BTC_GDBG_STR(GNT_BT1); + CASE_BTC_GDBG_STR(GNT_WL1); CASE_BTC_GDBG_STR(BCN_EARLY); CASE_BTC_GDBG_STR(WL_NULL0); CASE_BTC_GDBG_STR(WL_NULL1); @@ -9807,8 +10016,6 @@ static const char *id_to_gdbg(u32 id) CASE_BTC_GDBG_STR(SLOT_B1FDD); CASE_BTC_GDBG_STR(BT_CHANGE); CASE_BTC_GDBG_STR(WL_CCA); - CASE_BTC_GDBG_STR(BT_LEAUDIO); - CASE_BTC_GDBG_STR(USER_DEF); default: return "unknown"; } @@ -11487,8 +11694,8 @@ static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; char *p = buf, *end = buf + bufsz; - u8 *gpio_map, i; - u32 en_map; + u32 en_map_raw, en_map; + u8 *gpio_map, i, sig; pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo; @@ -11499,27 +11706,32 @@ static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) goto out; } - if (ver->fcxgpiodbg == 7) { - en_map = le32_to_cpu(gdbg->v7.en_map); + if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) { + en_map_raw = le32_to_cpu(gdbg->v7.en_map); gpio_map = gdbg->v7.gpio_map; } else { - en_map = le32_to_cpu(gdbg->v1.en_map); + en_map_raw = le32_to_cpu(gdbg->v1.en_map); gpio_map = gdbg->v1.gpio_map; } + en_map = _convert_gpio_enmap_from_ver(rtwdev, en_map_raw); if (!en_map) goto out; - p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x", + p += scnprintf(p, end - p, "\n\r %-15s : enable_map:0x%08x", "[gpio_dbg]", en_map); - for (i = 0; i < BTC_DBG_MAX1; i++) { + for (i = 0; i < BTC_DBG_NUM; i++) { if (!(en_map & BIT(i))) continue; + + sig = ver->fcxgpiodbg >= 8 ? i : _get_gpiosig_for_ver(rtwdev, i); + if (sig >= BTC_DBG_NUM) + continue; + p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i), - gpio_map[i]); + gpio_map[sig]); } - p += scnprintf(p, end - p, "\n"); out: return p - buf; diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index 355784941edd..3e9e1510c44f 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -315,41 +315,6 @@ enum btc_mlo_rf_combin { BTC_MLO_RF_2_PLUS_2 = 3, }; -enum btc_wl_gpio_debug { - BTC_DBG_GNT_BT = 0, - BTC_DBG_GNT_WL = 1, - BTC_DBG_BCN_EARLY = 2, - BTC_DBG_WL_NULL0 = 3, - BTC_DBG_WL_NULL1 = 4, - BTC_DBG_WL_RXISR = 5, - BTC_DBG_TDMA_ENTRY = 6, - BTC_DBG_A2DP_EMPTY = 7, - BTC_DBG_BT_RETRY = 8, - BTC_DBG_BT_RELINK = 9, - BTC_DBG_SLOT_WL = 10, - BTC_DBG_SLOT_BT = 11, - BTC_DBG_WL_ERR = 12, - BTC_DBG_WL_OK = 13, - BTC_DBG_SLOT_B2W = 14, - BTC_DBG_SLOT_W1 = 15, - BTC_DBG_SLOT_W2 = 16, - BTC_DBG_SLOT_W2B = 17, - BTC_DBG_SLOT_B1 = 18, - BTC_DBG_SLOT_B2 = 19, - BTC_DBG_SLOT_B3 = 20, - BTC_DBG_SLOT_B4 = 21, - BTC_DBG_SLOT_LK = 22, - BTC_DBG_SLOT_E2G = 23, - BTC_DBG_SLOT_E5G = 24, - BTC_DBG_SLOT_EBT = 25, - BTC_DBG_SLOT_WLK = 26, - BTC_DBG_SLOT_B1FDD = 27, - BTC_DBG_BT_CHANGE = 28, - BTC_DBG_WL_CCA = 29, - BTC_DBG_BT_LEAUDIO = 30, - BTC_DBG_USER_DEF = 31, -}; - void rtw89_btc_init(struct rtw89_dev *rtwdev); void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev); void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 0ec63f9510bd..ba3a9b0d4aa2 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3074,14 +3074,55 @@ enum rtw89_btc_afh_map_type { /*AFH MAP TYPE */ RPT_BT_AFH_SEQ_LE = 0x20 }; -#define BTC_DBG_MAX1 32 +enum btc_wl_gpio_debug { + BTC_DBG_GNT_BT = 0, + BTC_DBG_GNT_WL = 1, + BTC_DBG_GNT_BT1 = 2, + BTC_DBG_GNT_WL1 = 3, + /* The following signals should 0-1 tiggle by each function-call */ + BTC_DBG_BCN_EARLY = 4, + BTC_DBG_WL_NULL0 = 5, + BTC_DBG_WL_NULL1 = 6, + BTC_DBG_WL_RXISR = 7, + BTC_DBG_TDMA_ENTRY = 8, + BTC_DBG_A2DP_EMPTY = 9, + BTC_DBG_BT_RETRY = 10, + /* The following signals should 0-1 tiggle by state L/H */ + BTC_DBG_BT_RELINK = 11, + BTC_DBG_SLOT_WL = 12, + BTC_DBG_SLOT_BT = 13, + /* The following signals should 0-1 tiggle by external*/ + BTC_DBG_WL_ERR = 14, + BTC_DBG_WL_OK = 15, + /* The following signals appear only 1-active at same time*/ + BTC_DBG_SLOT_B2W = 16, + BTC_DBG_SLOT_W1 = 17, + BTC_DBG_SLOT_W2 = 18, + BTC_DBG_SLOT_W2B = 19, + BTC_DBG_SLOT_B1 = 20, + BTC_DBG_SLOT_B2 = 21, + BTC_DBG_SLOT_B3 = 22, + BTC_DBG_SLOT_B4 = 23, + BTC_DBG_SLOT_LK = 24, + BTC_DBG_SLOT_E2G = 25, + BTC_DBG_SLOT_E5G = 26, + BTC_DBG_SLOT_EBT = 27, + BTC_DBG_SLOT_WLK = 28, + BTC_DBG_SLOT_B1FDD = 29, + BTC_DBG_BT_CHANGE = 30, + /* The following signals should 0-1 tiggle by external*/ + BTC_DBG_WL_CCA = 31, + + BTC_DBG_NUM, +}; + struct rtw89_btc_fbtc_gpio_dbg_v1 { u8 fver; /* btc_ver::fcxgpiodbg */ u8 rsvd; __le16 rsvd2; __le32 en_map; /* which debug signal (see btc_wl_gpio_debug) is enable */ __le32 pre_state; /* the debug signal is 1 or 0 */ - u8 gpio_map[BTC_DBG_MAX1]; /*the debug signals to GPIO-Position */ + u8 gpio_map[BTC_DBG_NUM]; /*the debug signals to GPIO-Position */ } __packed; struct rtw89_btc_fbtc_gpio_dbg_v7 { @@ -3090,7 +3131,7 @@ struct rtw89_btc_fbtc_gpio_dbg_v7 { u8 rsvd1; u8 rsvd2; - u8 gpio_map[BTC_DBG_MAX1]; + u8 gpio_map[BTC_DBG_NUM]; __le32 en_map; __le32 pre_state; @@ -3101,6 +3142,120 @@ union rtw89_btc_fbtc_gpio_dbg { struct rtw89_btc_fbtc_gpio_dbg_v7 v7; }; +/* + * SET_GPIO_CTRL payload (max len = 7 bytes) + * + * type = CXDGPIO_EN_MAP + * data.val[31:0] = debug signal enable map + * + * type = CXDGPIO_MUX_MAP + * data.mux.sig = debug signal id + * data.mux.gpio = GPIO id + * + * type = CXDGPIO_EXT_HPTA / CXDGPIO_EXT_HMBX / CXDGPIO_EXT_SWOUT + * data.map.map_low = GPIO 7~0 map + * data.map.map_high = GPIO 15~8 map + * + * type = CXDGPIO_EXT_SWIN + * data.swin.in_map_low = GPIO 7~0 input-en-map + * data.swin.in_map_high = GPIO 15~8 input-en-map + * data.swin.int_map_low = GPIO 7~0 interrupt source map + * data.swin.int_map_high = GPIO 15~8 interrupt source map + */ +#define CXDGPIO_SET_L4 4 +#define CXDGPIO_SET_L2 2 +struct rtw89_fbtc_h2c_set_gpio_en_map { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u32 en_map; +}; + +struct rtw89_fbtc_h2c_set_gpio_mux { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 sig; + u8 gpio; +}; + +struct rtw89_fbtc_h2c_set_gpio_ext_pta { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 map_low; + u8 map_high; +}; + +struct rtw89_fbtc_h2c_set_gpio_ext_mb { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 map_low; + u8 map_high; +}; + +struct rtw89_fbtc_h2c_set_gpio_ext_swout { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 map_low; + u8 map_high; +}; + +struct rtw89_fbtc_h2c_set_gpio_ext_swin { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 in_map_low; + u8 in_map_high; + u8 int_map_low; + u8 int_map_high; +}; + +struct rtw89_fbtc_h2c_set_gpio_2b { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 data[CXDGPIO_SET_L2]; +} __packed; + +struct rtw89_fbtc_h2c_set_gpio_4b { + u8 type; /* gpio_type */ + u8 fver; /* FCX_VER_GPIODBG */ + u8 dlen; + u8 data[CXDGPIO_SET_L4]; +} __packed; + +union rtw89_fbtc_h2c_set_gpio_en_map_u { + struct rtw89_fbtc_h2c_set_gpio_4b fmt; + struct rtw89_fbtc_h2c_set_gpio_en_map data; +}; + +union rtw89_fbtc_h2c_set_gpio_mux_u { + struct rtw89_fbtc_h2c_set_gpio_2b fmt; + struct rtw89_fbtc_h2c_set_gpio_mux data; +}; + +union rtw89_fbtc_h2c_set_gpio_ext_pta_u { + struct rtw89_fbtc_h2c_set_gpio_2b fmt; + struct rtw89_fbtc_h2c_set_gpio_ext_pta data; +}; + +union rtw89_fbtc_h2c_set_gpio_ext_swin_u { + struct rtw89_fbtc_h2c_set_gpio_4b fmt; + struct rtw89_fbtc_h2c_set_gpio_ext_swin data; +}; + +struct rtw89_fbtc_h2c_set_gpio { + union rtw89_fbtc_h2c_set_gpio_en_map_u en_map; + union rtw89_fbtc_h2c_set_gpio_mux_u mux; + union rtw89_fbtc_h2c_set_gpio_ext_pta_u ext_pta; + union rtw89_fbtc_h2c_set_gpio_ext_pta_u ext_mb; + union rtw89_fbtc_h2c_set_gpio_ext_pta_u ext_swout; + union rtw89_fbtc_h2c_set_gpio_ext_swin_u ext_swin; +}; + struct rtw89_btc_fbtc_mreg_val_v1 { u8 fver; /* btc_ver::fcxmreg */ u8 reg_num; @@ -4178,6 +4333,7 @@ struct rtw89_btc { struct rtw89_btc_module mdinfo; struct rtw89_btc_btf_fwinfo fwinfo; struct rtw89_btc_dbg dbg; + struct rtw89_fbtc_h2c_set_gpio gpio; struct wiphy_work eapol_notify_work; struct wiphy_work arp_notify_work; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 538df0fb42cc..6147960521ee 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2391,6 +2391,16 @@ enum rtw89_btc_cxdrvinfo { CXDRVINFO_MAX, }; +enum rtw89_fbtc_gpio_type { + CXDGPIO_EN_MAP = 0x0, + CXDGPIO_MUX_MAP = 0x1, + CXDGPIO_EXT_HPTA = 0x2, + CXDGPIO_EXT_HMBX = 0x3, + CXDGPIO_EXT_SWOUT = 0x4, + CXDGPIO_EXT_SWIN = 0x5, + CXDGPIO_MAX, +}; + enum rtw89_scan_mode { RTW89_SCAN_IMMEDIATE, RTW89_SCAN_DELAY, -- 2.25.1 From: Ching-Te Ku BT-coexistence only needs to record RF calibration is doing or not, don't need to record the status of the calibration steps. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 96ec5fa20422..187e7e70e86d 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -9144,14 +9144,13 @@ static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, wl->rfk_info.state = BTC_WRFK_START; btc->cx.wl.wcnt[BTC_WCNT_RFK_REQ]++; - btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++; btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, true); break; case BTC_WRFK_ONESHOT_START: case BTC_WRFK_ONESHOT_STOP: - wl->rfk_info.state = state; + btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++; if (type != BTC_WRFKT_RXDCK) return BTC_WRFK_ALLOW; break; @@ -9165,7 +9164,7 @@ static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, default: rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s() warning state=%d\n", __func__, state); - break; + return result; } if (result == BTC_WRFK_ALLOW) { -- 2.25.1 From: Ching-Te Ku Fix the log output format in _show_mreg_v7() where the phy-0 gnt_status line was missing the proper field label and newline. Use the standard " %-15s : " format with "[gnt_status]" label consistent with the rest of the dump output. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 167 ++++++++++++---------- 1 file changed, 88 insertions(+), 79 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 187e7e70e86d..5aa06ef430c8 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -9656,8 +9656,10 @@ static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) plink->client_cnt - 1, plink->mode, plink->ch, plink->bw); - if (plink->connected == MLME_NO_LINK) + if (plink->connected == MLME_NO_LINK) { + p += scnprintf(p, end - p, "\n"); continue; + } p += scnprintf(p, end - p, ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", @@ -9747,7 +9749,7 @@ static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t buf if (hid.exist) { p += scnprintf(p, end - p, - "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", + "\n %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", "[HID]", hid.type & BTC_HID_218 ? "2/18," : "", hid.type & BTC_HID_418 ? "4/18," : "", @@ -10345,7 +10347,7 @@ static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) "" : "(Mismatch!!)")); p += scnprintf(p, end - p, - " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n ", + " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n", "[dm_rf_ctrl]", wl->rssi_level, dm->trx_para_level, dm->rf_trx_para.wl_tx_power[RTW89_PHY_0], @@ -10355,7 +10357,7 @@ static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) dm->wl_lna2, dm->wl_stb_chg); p += scnprintf(p, end - p, - " %-15s : pre_agc:%d, btg_rx:%d\n ", + " %-15s : pre_agc:%d, btg_rx:%d\n", "[dm_bb_ctrl]", dm->wl_pre_agc, dm->wl_btg_rx); p += scnprintf(p, end - p, @@ -10467,11 +10469,9 @@ static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) t->bind, t->leak_n, t->ext_ctrl); p += scnprintf(p, end - p, - "policy_type:%d", + "policy_type:%d\n", (u32)btc->policy_type); - p += scnprintf(p, end - p, "\n"); - return p - buf; } @@ -10778,11 +10778,9 @@ static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz le16_to_cpu(pcysta->a2dp_ept.cnt), le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); - p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", + p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", le16_to_cpu(pcysta->a2dp_ept.tavg), le16_to_cpu(pcysta->a2dp_ept.tmax)); - - p += scnprintf(p, end - p, "\n"); } out: @@ -10917,11 +10915,9 @@ static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz le16_to_cpu(pcysta->a2dp_ept.cnt), le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); - p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", + p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", le16_to_cpu(pcysta->a2dp_ept.tavg), le16_to_cpu(pcysta->a2dp_ept.tmax)); - - p += scnprintf(p, end - p, "\n"); } out: @@ -11055,11 +11051,9 @@ static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz le16_to_cpu(pcysta->a2dp_ept.cnt), le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); - p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", + p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", le16_to_cpu(pcysta->a2dp_ept.tavg), le16_to_cpu(pcysta->a2dp_ept.tmax)); - - p += scnprintf(p, end - p, "\n"); } out: @@ -11193,11 +11187,9 @@ static int _show_fbtc_cysta_v105(struct rtw89_dev *rtwdev, char *buf, size_t buf le16_to_cpu(pcysta->a2dp_ept.cnt), le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); - p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", + p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", le16_to_cpu(pcysta->a2dp_ept.tavg), le16_to_cpu(pcysta->a2dp_ept.tmax)); - - p += scnprintf(p, end - p, "\n"); } out: @@ -11246,7 +11238,7 @@ static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz le16_to_cpu(pcysta->skip_cnt)); p += scnprintf(p, end - p, - "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", + "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", "[cycle_stat]", le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), @@ -11267,7 +11259,7 @@ static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz if (a2dp->exist) { p += scnprintf(p, end - p, - "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", + "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", "[a2dp_stat]", le16_to_cpu(pcysta->a2dp_ept.cnt), le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), @@ -11306,10 +11298,10 @@ static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz if (cnt % divide_cnt == 1) { if (a2dp->exist) - p += scnprintf(p, end - p, "\n\r %-15s : ", + p += scnprintf(p, end - p, "\n %-15s : ", "[slotT_wermtan]"); else - p += scnprintf(p, end - p, "\n\r %-15s : ", + p += scnprintf(p, end - p, "\n %-15s : ", "[slotT_rxerr]"); } @@ -11370,7 +11362,7 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) ns = &pfwinfo->rpt_fbtc_nullsta.finfo; if (ver->fcxnullsta == 1) { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); + p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[ok:%d/", le32_to_cpu(ns->v1.result[i][1])); @@ -11389,7 +11381,7 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) } } else if (ver->fcxnullsta == 7) { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); + p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[Tx:%d/", le32_to_cpu(ns->v7.result[i][4])); @@ -11410,7 +11402,7 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) } } else { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); + p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[Tx:%d/", le32_to_cpu(ns->v2.result[i][4])); @@ -11717,7 +11709,7 @@ static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (!en_map) goto out; - p += scnprintf(p, end - p, "\n\r %-15s : enable_map:0x%08x", + p += scnprintf(p, end - p, "\n %-15s : enable_map:0x%08x", "[gpio_dbg]", en_map); for (i = 0; i < BTC_DBG_NUM; i++) { @@ -11943,7 +11935,7 @@ static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (!(dm->coex_info_map & BTC_COEX_INFO_MREG)) return 0; - p += scnprintf(p, end - p, "\n\r========== [HW Status] =========="); + p += scnprintf(p, end - p, "\n========== [HW Status] ==========\n"); p += scnprintf(p, end - p, " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", @@ -11965,18 +11957,31 @@ static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev); p += scnprintf(p, end - p, - "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s", + " %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s\n", "[gnt_status]", rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" : dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", wl->pta_req_mac, id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); - p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", - dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", - dm->gnt_set[RTW89_PHY_0].gnt_wl, - dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", - dm->gnt_set[RTW89_PHY_0].gnt_bt0); + if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) + p += scnprintf(p, end - p, + " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", + "[gnt_status]", + dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_0].gnt_wl, + dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_0].gnt_bt0, + dm->gnt_set[RTW89_PHY_0].gnt_bt1_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_0].gnt_bt1); + else + p += scnprintf(p, end - p, + " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", + "[gnt_status]", + dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_0].gnt_wl, + dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_0].gnt_bt0); if (rtwdev->dbcc_en) { p += scnprintf(p, end - p, @@ -12000,7 +12005,7 @@ static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (cnt % 6 == 0) p += scnprintf(p, end - p, - "\n\r %-15s : %s_0x%x=0x%x", "[reg]", + "\n %-15s : %s_0x%x=0x%x", "[reg]", id_to_regtype(type), offset, val); else p += scnprintf(p, end - p, ", %s_0x%x=0x%x", @@ -12336,12 +12341,11 @@ static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); - p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", "[notify_cnt]", @@ -12457,12 +12461,11 @@ static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); - p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", "[notify_cnt]", @@ -12495,7 +12498,7 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) return 0; p += scnprintf(p, end - p, "%s", - "\n\r========== [Statistics] =========="); + "\n========== [Statistics] ==========\n"); pcinfo = &pfwinfo->rpt_ctrl.cinfo; if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && @@ -12503,7 +12506,7 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) prptctrl = &pfwinfo->rpt_ctrl.finfo.v7; p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," + " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, @@ -12521,16 +12524,17 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (dm->error.map.wl_fw_hang) p += scnprintf(p, end - p, " (WL FW Hang!!)"); + p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, - "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", + " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); p += scnprintf(p, end - p, - "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", + "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), @@ -12538,7 +12542,7 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); p += scnprintf(p, end - p, - "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", + " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], wl->wcnt[BTC_WCNT_RFK_GO], wl->wcnt[BTC_WCNT_RFK_REJECT], @@ -12548,12 +12552,12 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, ", bt_rfk[req:%d]", le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); - p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", + p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); } else { p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", + " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, @@ -12564,19 +12568,19 @@ static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt_sum += dm->cnt_notify[i]; p += scnprintf(p, end - p, - "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", + " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); p += scnprintf(p, end - p, - "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", + " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], @@ -12608,7 +12612,7 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) return 0; p += scnprintf(p, end - p, "%s", - "\n\r========== [Statistics] =========="); + "\n========== [Statistics] ==========\n"); pcinfo = &pfwinfo->rpt_ctrl.cinfo; if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && @@ -12616,7 +12620,7 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) prptctrl = &pfwinfo->rpt_ctrl.finfo.v8; p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", + " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, le16_to_cpu(prptctrl->rpt_info.cnt_h2c), @@ -12634,16 +12638,17 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (dm->error.map.wl_fw_hang) p += scnprintf(p, end - p, " (WL FW Hang!!)"); + p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, - "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", + " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); p += scnprintf(p, end - p, - "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", + "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), @@ -12651,7 +12656,7 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); p += scnprintf(p, end - p, - "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", + " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], wl->wcnt[BTC_WCNT_RFK_GO], wl->wcnt[BTC_WCNT_RFK_REJECT], @@ -12661,12 +12666,12 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, ", bt_rfk[req:%d]", le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); - p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", + p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); } else { p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", + " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, @@ -12677,19 +12682,19 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt_sum += dm->cnt_notify[i]; p += scnprintf(p, end - p, - "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", + " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); p += scnprintf(p, end - p, - "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", + " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], @@ -12721,7 +12726,7 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) return 0; p += scnprintf(p, end - p, "%s", - "\n\r========== [Statistics] =========="); + "\n========== [Statistics] ==========\n"); pcinfo = &pfwinfo->rpt_ctrl.cinfo; if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && @@ -12729,7 +12734,7 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) prptctrl = &pfwinfo->rpt_ctrl.finfo.v9; p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ", + " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, le16_to_cpu(prptctrl->rpt_info.cnt_h2c), @@ -12745,16 +12750,17 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (dm->error.map.wl_fw_hang) p += scnprintf(p, end - p, " (WL FW Hang!!)"); + p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, - "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", + " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); p += scnprintf(p, end - p, - "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", + "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), @@ -12762,7 +12768,7 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); p += scnprintf(p, end - p, - "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", + " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], wl->wcnt[BTC_WCNT_RFK_GO], wl->wcnt[BTC_WCNT_RFK_REJECT], @@ -12772,12 +12778,12 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, ", bt_rfk[req:%d]", le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); - p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", + p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); } else { p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", + " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, @@ -12788,19 +12794,19 @@ static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt_sum += dm->cnt_notify[i]; p += scnprintf(p, end - p, - "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", + " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); p += scnprintf(p, end - p, - "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", + " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], @@ -12832,7 +12838,7 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) return 0; p += scnprintf(p, end - p, "%s", - "\n\r========== [Statistics] =========="); + "\n========== [Statistics] ==========\n"); pcinfo = &pfwinfo->rpt_ctrl.cinfo; if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && @@ -12840,7 +12846,7 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) prptctrl = &pfwinfo->rpt_ctrl.finfo.v11; p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", + " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, le16_to_cpu(prptctrl->rpt_info.cnt_h2c), @@ -12858,16 +12864,17 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (dm->error.map.wl_fw_hang) p += scnprintf(p, end - p, " (WL FW Hang!!)"); + p += scnprintf(p, end - p, "\n"); p += scnprintf(p, end - p, - "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", + " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); p += scnprintf(p, end - p, - "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", + "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), @@ -12875,19 +12882,19 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); p += scnprintf(p, end - p, - "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", + " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], wl->wcnt[BTC_WCNT_RFK_GO], wl->wcnt[BTC_WCNT_RFK_REJECT], wl->wcnt[BTC_WCNT_RFK_TIMEOUT], wl->rfk_info.proc_time); - p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", + p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); } else { p += scnprintf(p, end - p, - "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", + " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, @@ -12898,19 +12905,19 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) cnt_sum += dm->cnt_notify[i]; p += scnprintf(p, end - p, - "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", + " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); p += scnprintf(p, end - p, - "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", + "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], cnt[BTC_NCNT_WL_STA]); p += scnprintf(p, end - p, - "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", + " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], @@ -12993,6 +13000,8 @@ ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) else if (ver->fcxbtcrpt == 11) p += _show_summary_v11(rtwdev, p, end - p); + p += scnprintf(p, end - p, "\n"); + return p - buf; } -- 2.25.1 From: Ching-Te Ku RTL8922A (FW >= 0.35.111) and RTL8922D (FW >= 0.35.94) set fcxbtver, fcxbtscan and fcxbtafh to 8, but the handler in _chk_btc_report only had branches for version 1 and 7. When version 8 arrived pfinfo was left NULL and pcinfo->req_len was left at zero, so the length check at validation stage rejected the report and bt->ver_info.fw was never written, causing BT_FW:0x0 in the BTC dump. BT-scan and BT-afh version 8 hit the goto err path for the same reason, making all BT sub-reports silently broken on these chips. The structural change in version 8 is that the previously reserved second byte in each struct is now bt_id (0 = BT0, 1 = BT1), allowing firmware to send separate reports for each Bluetooth device. All three structs are otherwise layout-compatible with version 7. Add rtw89_btc_fbtc_btver_v8, rtw89_btc_fbtc_btscan_v8 and rtw89_btc_fbtc_btafh_v8 structs with the bt_id field, extend the corresponding unions, add version 8 branches to _chk_btc_report, and update _update_bt_report to route each report to BT0 or BT1 according to BT ID. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 52 ++++++++++++++++++++++- drivers/net/wireless/realtek/rtw89/core.h | 34 +++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 5aa06ef430c8..96bb68f09a01 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -1529,7 +1529,14 @@ static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) switch (rpt_type) { case BTC_RPT_TYPE_BT_VER: - if (ver->fcxbtver == 7) { + if (ver->fcxbtver == 8) { + pver->v8 = *(struct rtw89_btc_fbtc_btver_v8 *)pfinfo; + bt = pver->v8.bt_id ? &btc->cx.bt1 : &btc->cx.bt0; + bt->ver_info.fw = le32_to_cpu(pver->v8.fw_ver); + bt->ver_info.fw_coex = le32_get_bits(pver->v8.coex_ver, + GENMASK(7, 0)); + bt->feature = le32_to_cpu(pver->v8.feature); + } else if (ver->fcxbtver == 7) { pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo; bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver); bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver, @@ -1570,6 +1577,19 @@ static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) pscan_v7->para[i].intvl == 0) scan_update = false; } + } else if (ver->fcxbtscan == 8) { + struct rtw89_btc_fbtc_btscan_v8 *pscan_v8 = + (struct rtw89_btc_fbtc_btscan_v8 *)pfinfo; + struct rtw89_btc_bt_info *tbt = + pscan_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; + + for (i = 0; i < CXSCAN_MAX; i++) { + tbt->scan_info_v2[i] = pscan_v8->para[i]; + if ((pscan_v8->type & BIT(i)) && + pscan_v8->para[i].win == 0 && + pscan_v8->para[i].intvl == 0) + scan_update = false; + } } if (scan_update) bt->scan_info_update = 1; @@ -1597,6 +1617,22 @@ static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4); memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1); } + } else if (ver->fcxbtafh == 8) { + struct rtw89_btc_fbtc_btafh_v8 *pafh_v8 = + (struct rtw89_btc_fbtc_btafh_v8 *)pfinfo; + struct rtw89_btc_bt_info *tbt = + pafh_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; + struct rtw89_btc_bt_link_info *tbt_linfo = &tbt->link_info; + + if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LEGACY) { + memcpy(&tbt_linfo->afh_map[0], pafh_v8->afh_l, 4); + memcpy(&tbt_linfo->afh_map[4], pafh_v8->afh_m, 4); + memcpy(&tbt_linfo->afh_map[8], pafh_v8->afh_h, 2); + } + if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LE) { + memcpy(&tbt_linfo->afh_map_le[0], pafh_v8->afh_le_a, 4); + memcpy(&tbt_linfo->afh_map_le[4], pafh_v8->afh_le_b, 1); + } } else if (ver->fcxbtafh == 1) { pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); @@ -1882,6 +1918,12 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7); fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver; + } else if (ver->fcxbtver == 8) { + pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v8; + pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v8); + fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v8.fver; + } else { + goto err; } pcinfo->req_fver = ver->fcxbtver; break; @@ -1899,6 +1941,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7); fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver; + } else if (ver->fcxbtscan == 8) { + pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v8; + pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v8); + fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v8.fver; } else { goto err; } @@ -1918,6 +1964,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7); fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver; + } else if (ver->fcxbtafh == 8) { + pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v8; + pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v8); + fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v8.fver; } else { goto err; } diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index ba3a9b0d4aa2..aaed155ea423 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -2647,10 +2647,19 @@ struct rtw89_btc_fbtc_btscan_v7 { struct rtw89_btc_bt_scan_info_v2 para[CXSCAN_MAX]; } __packed; +struct rtw89_btc_fbtc_btscan_v8 { + u8 fver; /* btc_ver::fcxbtscan */ + u8 type; + u8 bt_id; /* 0:BT0, 1:BT1 */ + u8 rsvd1; + struct rtw89_btc_bt_scan_info_v2 para[CXSCAN_MAX]; +} __packed; + union rtw89_btc_fbtc_btscan { struct rtw89_btc_fbtc_btscan_v1 v1; struct rtw89_btc_fbtc_btscan_v2 v2; struct rtw89_btc_fbtc_btscan_v7 v7; + struct rtw89_btc_fbtc_btscan_v8 v8; }; struct rtw89_btc_bt_info { @@ -3683,9 +3692,21 @@ struct rtw89_btc_fbtc_btver_v7 { __le32 feature; } __packed; +struct rtw89_btc_fbtc_btver_v8 { + u8 fver; + u8 bt_id; /* 0:BT0, 1:BT1 */ + u8 rsvd1; + u8 rsvd2; + + __le32 coex_ver; /*bit[15:8]->shared, bit[7:0]->non-shared */ + __le32 fw_ver; + __le32 feature; +} __packed; + union rtw89_btc_fbtc_btver { struct rtw89_btc_fbtc_btver_v1 v1; struct rtw89_btc_fbtc_btver_v7 v7; + struct rtw89_btc_fbtc_btver_v8 v8; } __packed; struct rtw89_btc_fbtc_btafh { @@ -3721,6 +3742,18 @@ struct rtw89_btc_fbtc_btafh_v7 { u8 afh_le_b[4]; } __packed; +struct rtw89_btc_fbtc_btafh_v8 { + u8 fver; + u8 map_type; + u8 bt_id; /* 0:BT0, 1:BT1 */ + u8 rsvd1; + u8 afh_l[4]; /*bit0:2402, bit1:2403.... bit31:2433 */ + u8 afh_m[4]; /*bit0:2434, bit1:2435.... bit31:2465 */ + u8 afh_h[4]; /*bit0:2466, bit1:2467.....bit14:2480 */ + u8 afh_le_a[4]; + u8 afh_le_b[4]; +} __packed; + struct rtw89_btc_fbtc_btdevinfo { u8 fver; /* btc_ver::fcxbtdevinfo */ u8 rsvd; @@ -4194,6 +4227,7 @@ union rtw89_btc_fbtc_btafh_info { struct rtw89_btc_fbtc_btafh v1; struct rtw89_btc_fbtc_btafh_v2 v2; struct rtw89_btc_fbtc_btafh_v7 v7; + struct rtw89_btc_fbtc_btafh_v8 v8; }; struct rtw89_btc_report_ctrl_state { -- 2.25.1 From: Ching-Te Ku As RTL8922D support dual Bluetooth, add BT debug info dump for it. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 51 ++++++++++++++++------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 96bb68f09a01..6a718c54de67 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -9779,10 +9779,13 @@ enum btc_bt_a2dp_type { BTC_A2DP_TWS_RELAY = 2, }; -static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) +static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, + size_t bufsz, u8 bid) { struct rtw89_btc *btc = &rtwdev->btc; - struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; + struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? + &btc->cx.bt0 : &btc->cx.bt1; + struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; @@ -9835,15 +9838,16 @@ static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t buf return p - buf; } -static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) +static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, u8 bid) { struct rtw89_btc *btc = &rtwdev->btc; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_cx *cx = &btc->cx; - struct rtw89_btc_bt_info *bt = &cx->bt0; + struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; struct rtw89_btc_wl_info *wl = &cx->wl; struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; struct rtw89_btc_module *md = &btc->mdinfo; + u8 bt_pos = (bid == BTC_BT_1ST) ? md->bt0_pos : md->bt1_pos; s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm; s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm; u8 hw_band = wl->role_info.pta_req_band; @@ -9855,13 +9859,21 @@ static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) return 0; - p += scnprintf(p, end - p, "========== [BT Status] ==========\n"); + if (bid == BTC_BT_2ND) { + if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) + return 0; + if (!bt->enable.now) + return 0; + } + + p += scnprintf(p, end - p, "========== [BT_%s Status] ==========\n", + bid == BTC_BT_1ST ? "1ST" : "2ND"); p += scnprintf(p, end - p, " %-15s : enable:%s, btg:%s%s, connect:%s, ", "[status]", bt->enable.now ? "Y" : "N", bt->btg_type ? "Y" : "N", - (bt->enable.now && (bt->btg_type != md->bt0_pos) ? + (bt->enable.now && (bt->btg_type != bt_pos) ? "(efuse-mismatch!!)" : ""), (bt_linfo->status.map.connect ? "Y" : "N")); @@ -9927,7 +9939,7 @@ static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) bt->bcnt[BTC_BCNT_INQPAG], bt->bcnt[BTC_BCNT_INQ], bt->bcnt[BTC_BCNT_PAGE], bt->bcnt[BTC_BCNT_IGNOWL]); - p += _show_bt_profile_info(rtwdev, p, end - p); + p += _show_bt_profile_info(rtwdev, p, end - p, bid); p += scnprintf(p, end - p, " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", @@ -12034,12 +12046,22 @@ static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) dm->gnt_set[RTW89_PHY_0].gnt_bt0); if (rtwdev->dbcc_en) { - p += scnprintf(p, end - p, - ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", - dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", - dm->gnt_set[RTW89_PHY_1].gnt_wl, - dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", - dm->gnt_set[RTW89_PHY_1].gnt_bt0); + if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) + p += scnprintf(p, end - p, + ", phy-1[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", + dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_1].gnt_wl, + dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_1].gnt_bt0, + dm->gnt_set[RTW89_PHY_1].gnt_bt1_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_1].gnt_bt1); + else + p += scnprintf(p, end - p, + ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", + dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_1].gnt_wl, + dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", + dm->gnt_set[RTW89_PHY_1].gnt_bt0); } pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; @@ -13020,7 +13042,8 @@ ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += _show_cx_info(rtwdev, p, end - p); p += _show_wl_info(rtwdev, p, end - p); - p += _show_bt_info(rtwdev, p, end - p); + p += _show_bt_info(rtwdev, p, end - p, BTC_BT_1ST); + p += _show_bt_info(rtwdev, p, end - p, BTC_BT_2ND); p += _show_dm_info(rtwdev, p, end - p); p += _show_fw_dm_msg(rtwdev, p, end - p); -- 2.25.1 From: Ching-Te Ku fcxtdma=8 was not handled in _chk_btc_report(), causing the parser to hit 'goto err' and return 0 when processing the TDMA sub-report. This broke the _parse_btc_report() loop before reaching BT_VER (type=9), leaving bt->ver_info.fw always zero on RTL8922A/D. TDMA v8 uses the same struct layout as v3/v4/v7 (rtw89_btc_fbtc_tdma_v3, 12 bytes), so add it to the existing v3/v4/v7 branch in both switch cases. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 6a718c54de67..7ab22c60a420 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -1769,7 +1769,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); fwsubver->fcxtdma = 0; } else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || - ver->fcxtdma == 7) { + ver->fcxtdma == 7 || ver->fcxtdma == 8) { pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver; @@ -2300,7 +2300,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, &pfwinfo->rpt_fbtc_tdma.finfo.v1, sizeof(dm->tdma_now))); else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || - ver->fcxtdma == 7) + ver->fcxtdma == 7 || ver->fcxtdma == 8) _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, -- 2.25.1 From: Ching-Te Ku I/O offload higher priority sending event didn't return after H2C command was sent, add a return to prevent send twice in the same time. Update driver info entry which is handling module control info didn't handle the version 9 command format, add if condition to handle it. TX power update H2C command result checker logic was reversed, it will lead to the TX power value never update again after first update, fix the issue. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 7ab22c60a420..6b3e199398cf 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -1073,6 +1073,7 @@ static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, } btc->fwinfo.cnt_h2c++; + return 0; } else { /* Fill H2C MACRO buffer(TLV format) temporarily */ if (btc->hbuf_cnt == 0) _reset_h2c_macro(btc); @@ -3500,6 +3501,8 @@ static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) if (ver->fcxctrl == 7) rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, index); + else if (ver->fcxctrl == 9) + rtw89_fw_h2c_cxdrv_ctrl_v9(rtwdev, index); else rtw89_fw_h2c_cxdrv_ctrl(rtwdev, index); break; @@ -3893,7 +3896,7 @@ static void _set_bt_tx_power(struct rtw89_dev *rtwdev, bool force_exec, u8 bid, if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) len = SET_RF_PARA_AX_LEN; - if (_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { + if (!_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { btc->dm.rf_trx_para.bt_tx_power[i] = level; if (rf_band == RTW89_BAND_2G) bt->tx_power_now = level; -- 2.25.1 From: Ching-Te Ku Implement event handler of BTF_EVNT_BT_LEAUDIO_INFO C2H command, and related coexistence mechanism for Bluetooth LE-Audio feature. Signed-off-by: Ching-Te Ku Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/coex.c | 199 ++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/core.h | 35 +++- 2 files changed, 233 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 6b3e199398cf..0e42c720819a 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -951,6 +951,7 @@ enum btc_reason_and_action { BTC_RSN_ACT1_WORK, BTC_RSN_BT_DEVINFO_WORK, BTC_RSN_RFK_CHK_WORK, + BTC_RSN_UPDATE_BT_LEAUDINFO, BTC_RSN_NUM, BTC_ACT_NONE = 100, BTC_ACT_WL_ONLY, @@ -975,6 +976,8 @@ enum btc_reason_and_action { BTC_ACT_BT_A2DP_PAN, BTC_ACT_BT_PAN_HID, BTC_ACT_BT_A2DP_PAN_HID, + BTC_ACT_BT_BIS, + BTC_ACT_BT_CIS, BTC_ACT_WL_25G_MCC, BTC_ACT_WL_2G_MCC, BTC_ACT_WL_2G_SCC, @@ -6076,6 +6079,43 @@ static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) } } +static void _action_bt_bis(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_dm *dm = &btc->dm; + u16 policy_type; + + if (dm->bis_tdma) + policy_type = BTC_CXP_OFFE_2GBWISOB; + else + policy_type = BTC_CXP_OFF_EQ0; + + _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); + _set_policy(rtwdev, policy_type, BTC_ACT_BT_BIS); +} + +static void _action_bt_cis(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_dm *dm = &btc->dm; + u16 policy_type; + + if (bt_linfo->a2dp_desc.active) { + dm->slot_dur[CXST_W1] = 80; + dm->slot_dur[CXST_B1] = 20; + policy_type = BTC_CXP_PFIX_TDW1B1; + } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { + policy_type = BTC_CXP_OFF_BWB0; + } else { + policy_type = BTC_CXP_OFF_BWB1; + } + + _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); + _set_policy(rtwdev, policy_type, BTC_ACT_BT_CIS); +} + static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -6692,6 +6732,7 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_bt_info *bt = &btc->cx.bt0; struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; + struct rtw89_btc_bt_leaudio_desc leaudio = bt_linfo->leaudio_desc; struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; @@ -6715,6 +6756,12 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) if (bt_linfo->pan_desc.exist) profile_map |= BTC_BT_PAN; + if (leaudio.bis_exist) + profile_map |= BTC_BT_BIS; + + if (leaudio.cis_exist) + profile_map |= BTC_BT_CIS; + switch (profile_map) { case BTC_BT_NOPROFILE: if (pan.active) @@ -6740,6 +6787,13 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_PAN: _action_bt_pan(rtwdev); break; + case BTC_BT_BIS: + _action_bt_bis(rtwdev); + break; + case BTC_BT_CIS: + case BTC_BT_CIS | BTC_BT_HID: + _action_bt_cis(rtwdev); + break; case BTC_BT_A2DP | BTC_BT_HFP: case BTC_BT_A2DP | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: @@ -7909,6 +7963,140 @@ static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid) } } +static void _update_bt_link_cnt(struct rtw89_dev *rtwdev, + struct rtw89_btc_bt_info *bt, bool b56g) +{ + struct rtw89_btc_bt_link_info *b = b56g ? &bt->link_info_56g : + &bt->link_info; + struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc; + struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; + struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; + struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; + struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; + + b->link_cnt.last = b->link_cnt.now; + b->link_cnt.now = 0; + b->link_cnt.chg = 0; + + b->link_cnt.now += hfp->exist; + b->link_cnt.now += hid->exist; + b->link_cnt.now += a2dp->exist; + b->link_cnt.now += pan->exist; + b->link_cnt.now += leaudio->bis_exist; + b->link_cnt.now += leaudio->cis_exist; +} + +static void _update_bt_leaudio_info(struct rtw89_dev *rtwdev, u8 bid, + void *buf, u32 len) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; + struct rtw89_btc_bt_link_info *b = &bt->link_info; + struct rtw89_btc_bt_leaudio_info *src = buf; + struct rtw89_btc_bt_leaudio_desc *leaudio; + bool bt_56g = false, cis_exist, bis_exist; + u8 bis_cnt, cis_cnt; + + if ((src->len & BIT(7)) && bt->band_56G_support) { + b = &bt->link_info_56g; + bt_56g = true; + } + + leaudio = &b->leaudio_desc; + + if (!memcmp(b->leaudio_raw_info, src, BTC_BTINFO_MAX)) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s return by leaudio-info duplicate!\n", + __func__); + bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; + return; + } + + memcpy(b->leaudio_raw_info, src, BTC_BTINFO_MAX); + + bis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_EX); + cis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_EX); + bis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_CNT); + cis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_CNT); + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s: bis_exist:%d bis_cnt:%d cis_exist:%d cis_cnt:%d rssi:%d\n", + __func__, bis_exist, bis_cnt, cis_exist, cis_cnt, src->rssi); + + if (!bis_exist && !cis_exist) + memset(leaudio, 0, sizeof(*leaudio)); + + leaudio->bis_cnt = bis_cnt; + leaudio->bis_exist = bis_exist; + leaudio->cis_cnt = cis_cnt; + leaudio->cis_exist = cis_exist; + + if (leaudio->bis_exist) + b->status.map.profile_map |= BTC_BT_BIS; + else + b->status.map.profile_map &= ~BTC_BT_BIS; + + if (leaudio->cis_exist) + b->status.map.profile_map |= BTC_BT_CIS; + else + b->status.map.profile_map &= ~BTC_BT_CIS; + + _update_bt_link_cnt(rtwdev, bt, bt_56g); + + leaudio->rssi = chip->ops->btc_get_bt_rssi(rtwdev, src->rssi); + + leaudio->bis_cnt_last = leaudio->bis_cnt; + leaudio->bis_exist_last = leaudio->bis_exist; + leaudio->cis_cnt_last = leaudio->cis_cnt; + leaudio->cis_exist_last = leaudio->cis_exist; +} + +static void _update_bt_bistdma_info(struct rtw89_dev *rtwdev, u8 bid, + void *buf, u32 len) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + struct rtw89_btc_dm *dm = &btc->dm; + struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; + struct rtw89_btc_bt_link_info *b = &bt->link_info; + struct rtw89_btc_bt_bistdma_info_le *src = buf; + struct rtw89_btc_bt_leaudio_desc *leaudio; + + if ((src->len & BIT(7)) && bt->band_56G_support) + b = &bt->link_info_56g; + + leaudio = &b->leaudio_desc; + + if (!memcmp(b->bistdma_raw_info, src, BTC_BTINFO_MAX)) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s return by bistdma-info duplicate!\n", + __func__); + bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; + return; + } + + memcpy(b->bistdma_raw_info, src, BTC_BTINFO_MAX); + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s: bis_start_end:%d bis_trx:%d\n", + __func__, + u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_START_END), + u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX)); + + leaudio->bis_trx = u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX); + leaudio->bis_start_end = u8_get_bits(src->bis, + RTW89_BTC_BIS_INFO_L2_START_END); + + leaudio->diff_t = (src->diff_t_hb * 256 + src->diff_t_lb) * 625 / 1000; + + if (btc->ant_type == BTC_ANT_SHARED && leaudio->diff_t > 13) + dm->bis_tdma = true; + else + dm->bis_tdma = false; +} + #define BTC_BTINFO_PWR_LEN 5 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) { @@ -9606,6 +9794,14 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, case BTF_EVNT_CX_RUNINFO: btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; break; + case BTF_EVNT_BT_LEAUDIO_INFO: + bt->bcnt[BTC_BCNT_LEAUDIO_INFOUPDATE]++; + if (buf[BTC_BTINFO_L0] == BTC_BTINFO_BISTDMA) + _update_bt_bistdma_info(rtwdev, bid, buf, len); + else + _update_bt_leaudio_info(rtwdev, bid, buf, len); + _run_coex(rtwdev, BTC_RSN_UPDATE_BT_LEAUDINFO); + break; case BTF_EVNT_BT_QUERY_TXPWR: bt->bcnt[BTC_BCNT_TXPWR_UPDATE]++; _update_bt_txpwr_info(rtwdev, buf, len); @@ -10107,6 +10303,7 @@ static const char *steps_to_str(u16 step) CASE_BTC_RSN_STR(ACT1_WORK); CASE_BTC_RSN_STR(BT_DEVINFO_WORK); CASE_BTC_RSN_STR(RFK_CHK_WORK); + CASE_BTC_RSN_STR(UPDATE_BT_LEAUDINFO); CASE_BTC_ACT_STR(NONE); CASE_BTC_ACT_STR(WL_ONLY); @@ -10131,6 +10328,8 @@ static const char *steps_to_str(u16 step) CASE_BTC_ACT_STR(BT_A2DP_PAN); CASE_BTC_ACT_STR(BT_PAN_HID); CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); + CASE_BTC_ACT_STR(BT_BIS); + CASE_BTC_ACT_STR(BT_CIS); CASE_BTC_ACT_STR(WL_25G_MCC); CASE_BTC_ACT_STR(WL_2G_MCC); CASE_BTC_ACT_STR(WL_2G_SCC); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index aaed155ea423..09c19a6b9058 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1383,6 +1383,8 @@ enum rtw89_btc_btinfo { BTC_BTINFO_MAX }; +#define BTC_BTINFO_BISTDMA 0x48 /* cmd value that identifies BISTDMA data */ + enum rtw89_btc_dcnt { BTC_DCNT_RUN = 0x0, BTC_DCNT_CX_RUNINFO, @@ -2167,6 +2169,31 @@ struct rtw89_btc_bt_txpwr_desc { u8 le_gain_index; }; +struct rtw89_btc_bt_leaudio_info { + u8 cmd; + u8 len; + u8 bis_cis; +#define RTW89_BTC_LEAU_INFO_L2_BIS_EX BIT(0) +#define RTW89_BTC_LEAU_INFO_L2_BIS_CNT GENMASK(3, 1) +#define RTW89_BTC_LEAU_INFO_L2_CIS_EX BIT(4) +#define RTW89_BTC_LEAU_INFO_L2_CIS_CNT GENMASK(7, 5) + u8 rssi; + __le32 hbrsvd; +} __packed; + +struct rtw89_btc_bt_bistdma_info_le { + u8 cmd; + u8 len; + u8 bis; /* BIT(2) ~ BIT(7) is rsvd */ +#define RTW89_BTC_BIS_INFO_L2_START_END BIT(0) /* 0: BIS start, 1: BIS end */ +#define RTW89_BTC_BIS_INFO_L2_TRX BIT(1) /* 0: BIS Tx, 1: BIS Rx */ + u8 diff_t_lb; + u8 diff_t_hb; /* diff_t = (diff_t_hb * 256 + diff_t_lb) * 0.625 ms */ + u8 hb1rsvd; + u8 hb2rsvd; + u8 hb3rsvd; +} __packed; + struct rtw89_btc_bt_leaudio_desc { u32 bis_exist: 1; u32 bis_exist_last: 1; @@ -2177,7 +2204,9 @@ struct rtw89_btc_bt_leaudio_desc { u32 rssi: 8; u32 bis_cnt_last: 3; u32 cis_cnt_last: 3; - u32 rsvd: 8; + u32 bis_trx: 1; + u32 bis_start_end: 1; + u32 rsvd: 6; u16 diff_t; }; @@ -2213,6 +2242,9 @@ struct rtw89_btc_bt_link_info { u8 ble_scan_en: 1; u8 reinit: 1; u8 rsvd: 6; + + u8 leaudio_raw_info[BTC_BTINFO_MAX]; /* raw LE audio info from BT mailbox */ + u8 bistdma_raw_info[BTC_BTINFO_MAX]; /* raw BIS-TDMA info from BT mailbox */ }; struct rtw89_btc_bind_bt_status { @@ -4085,6 +4117,7 @@ struct rtw89_btc_dm { u8 lps_ctrl_scbd: 1; u8 lps_ctrl_scbd_last: 1; u8 lps_ctrl_change: 1; + u8 bis_tdma: 1; /* BIS TDMA mode active */ u8 scbd_write_instant; bool scbd_b2w_update; bool scbd_w2b_update; -- 2.25.1