diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/coex.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/coex.c | 383 |
1 files changed, 256 insertions, 127 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index df51b29142aa..989e6e882c6e 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -125,6 +125,9 @@ static const u32 cxtbl[] = { 0xfafaaafa, /* 23 */ 0xfafffaff, /* 24 */ 0xea6a5a5a, /* 25 */ + 0xfaff5aff, /* 26 */ + 0xffffdfff, /* 27 */ + 0xe6555555, /* 28 */ }; static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { @@ -134,77 +137,88 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, /* keep it to be the last as default entry */ @@ -213,7 +227,8 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, }; @@ -224,7 +239,7 @@ static const union rtw89_btc_wl_state_map btc_scanning_map = { .scan = 1, .connecting = 1, .roaming = 1, - .transacting = 1, + .dbccing = 1, ._4way = 1, }, }; @@ -3017,7 +3032,7 @@ static void _update_btc_state_map(struct rtw89_dev *rtwdev) struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; if (wl->status.map.connecting || wl->status.map._4way || - wl->status.map.roaming) { + wl->status.map.roaming || wl->status.map.dbccing) { cx->state_map = BTC_WLINKING; } else if (wl->status.map.scan) { /* wl scan */ if (bt_linfo->status.map.inq_pag) @@ -3721,8 +3736,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) tbl_w1 = cxtbl[16]; } - btc->bt_req_en = false; - switch (type) { case BTC_CXP_USERDEF0: btc->update_policy_force = true; @@ -3744,6 +3757,10 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_WL: _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); break; + case BTC_CXP_OFF_WL2: + _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); + _slot_set_type(btc, CXST_OFF, SLOT_ISO); + break; case BTC_CXP_OFF_EQ0: _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); _slot_set_type(btc, CXST_OFF, SLOT_ISO); @@ -3757,6 +3774,12 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_EQ3: _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); break; + case BTC_CXP_OFF_EQ4: + _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); + break; + case BTC_CXP_OFF_EQ5: + _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); + break; case BTC_CXP_OFF_BWB0: _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); break; @@ -3788,7 +3811,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) } break; case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ - btc->bt_req_en = true; _write_scbd(rtwdev, BTC_WSCB_TDMA, true); *t = t_def[CXTD_OFF_EXT]; @@ -3831,9 +3853,9 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); break; case BTC_CXP_OFFE_2GBWMIXB: - _slot_set(btc, CXST_E2G, 0, 0x55555555, SLOT_MIX); + _slot_set(btc, CXST_E2G, 0, 0xea5a5555, SLOT_MIX); _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - cpu_to_le32(0x55555555), s_def[CXST_EBT].cxtype); + s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); break; case BTC_CXP_OFFE_WL: /* for 4-way */ _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX); @@ -3842,6 +3864,8 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) default: break; } + _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, + s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); break; @@ -4246,6 +4270,7 @@ static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec, _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); break; case BTC_ANT_WRFK: + case BTC_ANT_WRFK2: rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); @@ -4623,12 +4648,21 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) static void _action_bt_pan(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; + struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; + struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); switch (btc->cx.state_map) { case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ - _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + if (a2dp.active || !pan.exist) { + btc->dm.slot_dur[CXST_W1] = 80; + btc->dm.slot_dur[CXST_B1] = 20; + _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); + } else { + _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + } break; case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); @@ -4814,8 +4848,16 @@ static void _action_wl_rfk(struct rtw89_dev *rtwdev) rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", __func__, rfk.band); - _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); - _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + btc->dm.tdma_instant_excute = 1; + + if (rfk.state == BTC_WRFK_ONESHOT_START || + btc->ant_type == BTC_ANT_SHARED) { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); + _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); + } else { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); + _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + } } static void _set_btg_ctrl(struct rtw89_dev *rtwdev) @@ -4855,6 +4897,8 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev) if (rtwdev->dbcc_en) { if (ver->fwlrole == 0) { + wl_rinfo.dbcc_2g_phy = RTW89_PHY_MAX; + for (i = 0; i < RTW89_PHY_MAX; i++) { if (wl_dinfo->real_band[i] == RTW89_BAND_2G) wl_rinfo.dbcc_2g_phy = i; @@ -4989,18 +5033,16 @@ struct rtw89_txtime_data { bool reenable; }; -static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_txtime_data *iter_data) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_txtime_data *iter_data = - (struct rtw89_txtime_data *)data; struct rtw89_dev *rtwdev = iter_data->rtwdev; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_cx *cx = &btc->cx; struct rtw89_btc_wl_info *wl = &cx->wl; struct rtw89_btc_wl_link_info *plink = NULL; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 tx_time = iter_data->tx_time; u8 tx_retry = iter_data->tx_retry; u16 enable = iter_data->enable; @@ -5023,8 +5065,8 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* backup the original tx time before tx-limit on */ if (reenable) { - rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); - rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); + rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); + rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); @@ -5032,22 +5074,37 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* restore the original tx time if no tx-limit */ if (!enable) { - rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); } else { - rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", __func__, tx_time, tx_retry); } } +static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_txtime_data *iter_data = + (struct rtw89_txtime_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -5231,8 +5288,14 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) 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; + struct rtw89_btc_dm *dm = &btc->dm; u8 profile_map = 0; + if (dm->freerun_chk) { + _action_freerun(rtwdev); + return; + } + if (bt_linfo->hfp_desc.exist) profile_map |= BTC_BT_HFP; @@ -5247,30 +5310,20 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) switch (profile_map) { case BTC_BT_NOPROFILE: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (pan.active) + if (pan.active) _action_bt_pan(rtwdev); else _action_bt_idle(rtwdev); break; case BTC_BT_HFP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hfp(rtwdev); + _action_bt_hfp(rtwdev); break; case BTC_BT_HFP | BTC_BT_HID: case BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hid(rtwdev); + _action_bt_hid(rtwdev); break; case BTC_BT_A2DP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (a2dp.sink) + if (a2dp.sink) _action_bt_a2dpsink(rtwdev); else if (bt_linfo->multi_link.now && !hid.pair_cnt) _action_bt_a2dp_pan(rtwdev); @@ -5283,13 +5336,18 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_HFP: case BTC_BT_A2DP | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else if (pan.active) + _action_bt_a2dp_pan_hid(rtwdev); else _action_bt_a2dp_hid(rtwdev); break; case BTC_BT_A2DP | BTC_BT_PAN: - _action_bt_a2dp_pan(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan(rtwdev); break; case BTC_BT_PAN | BTC_BT_HFP: case BTC_BT_PAN | BTC_BT_HID: @@ -5299,7 +5357,10 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: default: - _action_bt_a2dp_pan_hid(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan_hid(rtwdev); break; } } @@ -5319,7 +5380,7 @@ static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) policy_type = BTC_CXP_OFFE_WL; else if (btc->cx.wl.status.val & btc_scanning_map.val) policy_type = BTC_CXP_OFFE_2GBWMIXB; - else if (btc->cx.bt.link_info.profile_cnt.now == 0) + else if (btc->cx.bt.link_info.status.map.connect == 0) policy_type = BTC_CXP_OFFE_2GISOB; else policy_type = BTC_CXP_OFFE_2GBWISOB; @@ -6891,6 +6952,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) bt->scan_rx_low_pri = false; igno_bt = false; + dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ + if (always_freerun) { _action_freerun(rtwdev); igno_bt = true; @@ -6929,18 +6992,9 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) goto exit; } - if (cx->state_map == BTC_WLINKING) { - if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || - mode == BTC_WLINK_5G) { - _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; - goto exit; - } - } - - if (wl->status.map.scan) { + if (wl->status.val & btc_scanning_map.val) { _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; + bt->scan_rx_low_pri = true; goto exit; } @@ -7176,10 +7230,6 @@ void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; - wl->scan_info.band[phy_idx] = band; - wl->scan_info.phy_map |= BIT(phy_idx); - _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); - if (rtwdev->dbcc_en) { wl->dbcc_info.scan_band[phy_idx] = band; _update_dbcc_band(rtwdev, phy_idx); @@ -7374,13 +7424,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) "[BTC], %s(): bt_info[2]=0x%02x\n", __func__, bt->raw_info[2]); - /* reset to mo-connect before update */ - b->status.val = BTC_BLINK_NOCONNECT; b->profile_cnt.last = b->profile_cnt.now; - b->relink.last = b->relink.now; - a2dp->exist_last = a2dp->exist; - b->multi_link.last = b->multi_link.now; - bt->inq_pag.last = bt->inq_pag.now; b->profile_cnt.now = 0; hid->type = 0; @@ -7399,7 +7443,8 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->profile_cnt.now += (u8)hid->exist; a2dp->exist = btinfo.lb2.a2dp; b->profile_cnt.now += (u8)a2dp->exist; - pan->active = btinfo.lb2.pan; + pan->exist = btinfo.lb2.pan; + b->profile_cnt.now += (u8)pan->exist; btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); /* parse raw info low-Byte3 */ @@ -7423,8 +7468,14 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte1 */ btinfo.val = bt->raw_info[BTC_BTINFO_H1]; b->status.map.ble_connect = btinfo.hb1.ble_connect; - if (btinfo.hb1.ble_connect) - hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); + if (btinfo.hb1.ble_connect) { + if (hid->exist) + hid->type |= BTC_HID_BLE; + else if (btinfo.hb1.voice) + hid->type |= BTC_HID_RCU_VOICE; + else + hid->type |= BTC_HID_RCU; + } cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); bt->reinit = btinfo.hb1.reinit; @@ -7436,7 +7487,6 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) if (bt->igno_wl && !cx->wl.status.map.rf_off) _set_bt_ignore_wlan_act(rtwdev, false); - hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); bt->ble_scan_en = btinfo.hb1.ble_scan; cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); @@ -7446,8 +7496,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte2 */ btinfo.val = bt->raw_info[BTC_BTINFO_H2]; - pan->exist = btinfo.hb2.pan_active; - b->profile_cnt.now += (u8)pan->exist; + pan->active = !!btinfo.hb2.pan_active; cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); b->afh_update = btinfo.hb2.afh_update; @@ -7455,8 +7504,9 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->slave_role = btinfo.hb2.slave; hid->slot_info = btinfo.hb2.hid_slot; hid->pair_cnt = btinfo.hb2.hid_cnt; - hid->type |= (hid->slot_info == BTC_HID_218 ? - BTC_HID_218 : BTC_HID_418); + if (!b->status.map.ble_connect || hid->pair_cnt > 1) + hid->type |= (hid->slot_info == BTC_HID_218 ? + BTC_HID_218 : BTC_HID_418); /* parse raw info high-Byte3 */ btinfo.val = bt->raw_info[BTC_BTINFO_H3]; a2dp->bitpool = btinfo.hb3.a2dp_bitpool; @@ -7479,13 +7529,16 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); } -void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, enum btc_role_state state) +void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + enum btc_role_state state) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; struct rtw89_btc *btc = &rtwdev->btc; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; @@ -7493,51 +7546,59 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif struct rtw89_btc_wl_link_info *wlinfo = NULL; u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + 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->port); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); 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", state == BTC_ROLE_MSTS_STA_CONN_END); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], bcn_period=%d dtim_period=%d\n", - vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); + bss_conf->beacon_int, bss_conf->dtim_period); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); - if (rtwsta) { rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", - rtwsta->mac_id); + rtwsta_link->mac_id); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA support HE=%d VHT=%d HT=%d\n", - sta->deflink.he_cap.has_he, - sta->deflink.vht_cap.vht_supported, - sta->deflink.ht_cap.ht_supported); - if (sta->deflink.he_cap.has_he) + link_sta->he_cap.has_he, + link_sta->vht_cap.vht_supported, + link_sta->ht_cap.ht_supported); + if (link_sta->he_cap.has_he) mode |= BIT(BTC_WL_MODE_HE); - if (sta->deflink.vht_cap.vht_supported) + if (link_sta->vht_cap.vht_supported) mode |= BIT(BTC_WL_MODE_VHT); - if (sta->deflink.ht_cap.ht_supported) + if (link_sta->ht_cap.ht_supported) mode |= BIT(BTC_WL_MODE_HT); r.mode = mode; } - if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) + if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { + rcu_read_unlock(); return; + } rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC], wifi_role=%d\n", rtwvif->wifi_role); + "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); - r.role = rtwvif->wifi_role; - r.phy = rtwvif->phy_idx; - r.pid = rtwvif->port; + r.role = rtwvif_link->wifi_role; + r.phy = rtwvif_link->phy_idx; + r.pid = rtwvif_link->port; r.active = true; r.connected = MLME_LINKED; - r.bcn_period = vif->bss_conf.beacon_int; - r.dtim_period = vif->bss_conf.dtim_period; + 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; @@ -7545,10 +7606,12 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif r.chdef.center_ch = chan->channel; r.chdef.bw = chan->band_width; r.chdef.chan = chan->primary_channel; - ether_addr_copy(r.mac_addr, rtwvif->mac_addr); + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + + rcu_read_unlock(); - if (rtwsta && vif->type == NL80211_IFTYPE_STATION) - r.mac_id = rtwsta->mac_id; + if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) + r.mac_id = rtwsta_link->mac_id; btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; @@ -7779,26 +7842,26 @@ struct rtw89_btc_wl_sta_iter_data { bool is_traffic_change; }; -static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +static +void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_btc_wl_sta_iter_data *iter_data) { - struct rtw89_btc_wl_sta_iter_data *iter_data = - (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_dev *rtwdev = iter_data->rtwdev; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_link_info *link_info = NULL; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_traffic_stats *link_info_t = NULL; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_traffic_stats *stats = &rtwvif->stats; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_btc_wl_role_info *r; struct rtw89_btc_wl_role_info_v1 *r1; u32 last_tx_rate, last_rx_rate; u16 last_tx_lvl, last_rx_lvl; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u8 rssi; u8 busy = 0; u8 dir = 0; @@ -7806,11 +7869,11 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) u8 i = 0; bool is_sta_change = false, is_traffic_change = false; - rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); link_info = &wl->link_info[port]; - link_info->stat.traffic = rtwvif->stats; + link_info->stat.traffic = *stats; link_info_t = &link_info->stat.traffic; if (link_info->connected == MLME_NO_LINK) { @@ -7858,19 +7921,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->busy_all |= busy; iter_data->dir_all |= BIT(dir); - if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && + if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && last_rx_rate > RTW89_HW_RATE_CCK2 && link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) link_info->rx_rate_drop_cnt++; - if (last_tx_rate != rtwsta->ra_report.hw_rate || - last_rx_rate != rtwsta->rx_hw_rate || + if (last_tx_rate != rtwsta_link->ra_report.hw_rate || + last_rx_rate != rtwsta_link->rx_hw_rate || last_tx_lvl != link_info_t->tx_tfc_lv || last_rx_lvl != link_info_t->rx_tfc_lv) is_traffic_change = true; - link_info_t->tx_rate = rtwsta->ra_report.hw_rate; - link_info_t->rx_rate = rtwsta->rx_hw_rate; + link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; + link_info_t->rx_rate = rtwsta_link->rx_hw_rate; if (link_info->role == RTW89_WIFI_ROLE_STATION || link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { @@ -7882,19 +7945,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) r = &wl->role_info; r->active_role[port].tx_lvl = stats->tx_tfc_lv; r->active_role[port].rx_lvl = stats->rx_tfc_lv; - r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; - r->active_role[port].rx_rate = rtwsta->rx_hw_rate; + r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 1) { r1 = &wl->role_info_v1; r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; - r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; - r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; + r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 2) { dm->trx_info.tx_lvl = stats->tx_tfc_lv; dm->trx_info.rx_lvl = stats->rx_tfc_lv; - dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; - dm->trx_info.rx_rate = rtwsta->rx_hw_rate; + dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; + dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; } dm->trx_info.tx_tp = link_info_t->tx_throughput; @@ -7914,6 +7977,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->is_traffic_change = true; } +static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_btc_wl_sta_iter_data *iter_data = + (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + #define BTC_NHM_CHK_INTVL 20 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) @@ -7963,6 +8041,53 @@ void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) } } +static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) +{ + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + + switch (func) { + case BTF_EVNT_RPT: + case BTF_EVNT_BT_INFO: + case BTF_EVNT_BT_SCBD: + case BTF_EVNT_BT_REG: + case BTF_EVNT_CX_RUNINFO: + case BTF_EVNT_BT_PSD: + return func; + case BTF_EVNT_BT_DEV_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_BUF_OVERFLOW; + else + return BTF_EVNT_BT_DEV_INFO; + case BTF_EVNT_BT_LEAUDIO_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_BUF_OVERFLOW; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_BUF_OVERFLOW: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_MAX; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_C2H_LOOPBACK: + if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_MAX: + default: + return BTF_EVNT_MAX; + } +} + void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func) { @@ -7979,10 +8104,14 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (class != BTFC_FW_EVENT) return; + func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); + switch (func) { - case BTF_EVNT_RPT: case BTF_EVNT_BUF_OVERFLOW: pfwinfo->event[func]++; + break; + case BTF_EVNT_RPT: + pfwinfo->event[func]++; /* Don't need rtw89_leave_ps_mode() */ btc_fw_event(rtwdev, func, buf, len); break; |