// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2019-2020 Realtek Corporation
*/
#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "fw.h"
#include "mac.h"
#include "phy.h"
#include "ps.h"
#include "reg.h"
#define RTW89_COEX_VERSION 0x09000013
#define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
#define BTC_E2G_LIMIT_DEF 80
enum btc_fbtc_tdma_template {
CXTD_OFF = 0x0,
CXTD_OFF_B2,
CXTD_OFF_EXT,
CXTD_FIX,
CXTD_PFIX,
CXTD_AUTO,
CXTD_PAUTO,
CXTD_AUTO2,
CXTD_PAUTO2,
CXTD_MAX,
};
enum btc_fbtc_tdma_type {
CXTDMA_OFF = 0x0,
CXTDMA_FIX = 0x1,
CXTDMA_AUTO = 0x2,
CXTDMA_AUTO2 = 0x3,
CXTDMA_MAX
};
enum btc_fbtc_tdma_rx_flow_ctrl {
CXFLC_OFF = 0x0,
CXFLC_NULLP = 0x1,
CXFLC_QOSNULL = 0x2,
CXFLC_CTS = 0x3,
CXFLC_MAX
};
enum btc_fbtc_tdma_wlan_tx_pause {
CXTPS_OFF = 0x0, /* no wl tx pause*/
CXTPS_ON = 0x1,
CXTPS_MAX
};
enum btc_mlme_state {
MLME_NO_LINK,
MLME_LINKING,
MLME_LINKED,
};
struct btc_fbtc_1slot {
u8 fver;
u8 sid; /* slot id */
struct rtw89_btc_fbtc_slot slot;
} __packed;
static const struct rtw89_btc_fbtc_tdma t_def[] = {
[CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
[CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
[CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
[CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
[CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
[CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
[CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
[CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
[CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
};
#define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
{ .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
.cxtype = cpu_to_le16(__cxtype),}
static const struct rtw89_btc_fbtc_slot s_def[] = {
[CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
[CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
[CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
[CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
[CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
[CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
[CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
[CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
[CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
[CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
[CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
[CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX),
[CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO),
[CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
[CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
[CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
[CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
[CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
};
static const u32 cxtbl[] = {
0xffffffff, /* 0 */
0xaaaaaaaa, /* 1 */
0xe5555555, /* 2 */
0xee555555, /* 3 */
0xd5555555, /* 4 */
0x5a5a5a5a, /* 5 */
0xfa5a5a5a, /* 6 */
0xda5a5a5a, /* 7 */
0xea5a5a5a, /* 8 */
0x6a5a5aaa, /* 9 */
0x6a5a6a5a, /* 10 */
0x6a5a6aaa, /* 11 */
0x6afa5afa, /* 12 */
0xaaaa5aaa, /* 13 */
0xaaffffaa, /* 14 */
0xaa5555aa, /* 15 */
0xfafafafa, /* 16 */
0xffffddff, /* 17 */
0xdaffdaff, /* 18 */
0xfafadafa, /* 19 */
0xea6a6a6a, /* 20 */
0xea55556a, /* 21 */
0xaafafafa, /* 22 */
0xfafaaafa, /* 23 */
0xfafffaff, /* 24 */
0xea6a5a5a, /* 25 */
0xfaff5aff, /* 26 */
0xffffdfff, /* 27 */
0xe6555555, /* 28 */
};
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
/* firmware version must be in decreasing order for each chip */
{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 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 = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
.fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
},
{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
.fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
.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, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
},
{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,
.fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
.fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
.fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
},
{RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 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 = 4, .fcxctrl = 7, .fcxinit = 7,
.fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 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 = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
.fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
.max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
{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, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
/* keep it to be the last as default entry */
{0, RTW89_FW_VER_CODE(0, 0, 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, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
.max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
},
};
#define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
static const union rtw89_btc_wl_state_map btc_scanning_map = {
.map = {
.scan = 1,
.connecting = 1,
.roaming = 1,
.dbccing = 1,
._4way = 1,
},
};
static u32 chip_id_to_bt_rom_code_id(u32 id)
{
switch (id) {
case RTL8852A:
case RTL8852B:
case RTL8852C:
case RTL8852BT:
return 0x8852;
case RTL8851B:
return 0x8851;
case RTL8922A:
return 0x8922;
default :
return 0;
}
}
#define CASE_BTC_MLME_STATE(e) case MLME_## e: return #e
static const char *id_to_mlme_state(u32 id)
{
switch (id) {
CASE_BTC_MLME_STATE(NO_LINK);
CASE_BTC_MLME_STATE(LINKING);
CASE_BTC_MLME_STATE(LINKED);
default :
return "unknown" ;
}
}
static char *chip_id_str(u32 id)
{
switch (id) {
case RTL8852A:
return "RTL8852A" ;
case RTL8852B:
return "RTL8852B" ;
case RTL8852C:
return "RTL8852C" ;
case RTL8852BT:
return "RTL8852BT" ;
case RTL8851B:
return "RTL8851B" ;
case RTL8922A:
return "RTL8922A" ;
default :
return "UNKNOWN" ;
}
}
struct rtw89_btc_btf_tlv {
u8 type;
u8 len;
u8 val[];
} __packed;
struct rtw89_btc_btf_tlv_v7 {
u8 type;
u8 ver;
u8 len;
u8 val[];
} __packed;
enum btc_btf_set_report_en {
RPT_EN_TDMA,
RPT_EN_CYCLE,
RPT_EN_MREG,
RPT_EN_BT_VER_INFO,
RPT_EN_BT_SCAN_INFO,
RPT_EN_BT_DEVICE_INFO,
RPT_EN_BT_AFH_MAP,
RPT_EN_BT_AFH_MAP_LE,
RPT_EN_BT_TX_PWR_LVL,
RPT_EN_FW_STEP_INFO,
RPT_EN_TEST,
RPT_EN_WL_ALL,
RPT_EN_BT_ALL,
RPT_EN_ALL,
RPT_EN_MONITER,
};
struct rtw89_btc_btf_set_report_v1 {
u8 fver;
__le32 enable;
__le32 para;
} __packed;
struct rtw89_btc_btf_set_report_v8 {
u8 type;
u8 fver;
u8 len;
__le32 map;
} __packed;
union rtw89_fbtc_rtp_ctrl {
struct rtw89_btc_btf_set_report_v1 v1;
struct rtw89_btc_btf_set_report_v8 v8;
};
#define BTF_SET_SLOT_TABLE_VER 1
struct rtw89_btc_btf_set_slot_table {
u8 fver;
u8 tbl_num;
struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
} __packed;
struct rtw89_btc_btf_set_slot_table_v7 {
u8 type;
u8 ver;
u8 len;
struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
} __packed;
struct rtw89_btc_btf_set_mon_reg_v1 {
u8 fver;
u8 reg_num;
struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
} __packed;
struct rtw89_btc_btf_set_mon_reg_v7 {
u8 type;
u8 fver;
u8 len;
struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
} __packed;
union rtw89_fbtc_set_mon_reg {
struct rtw89_btc_btf_set_mon_reg_v1 v1;
struct rtw89_btc_btf_set_mon_reg_v7 v7;
} __packed;
struct _wl_rinfo_now {
u8 link_mode;
u32 dbcc_2g_phy: 2;
};
enum btc_btf_set_cx_policy {
CXPOLICY_TDMA = 0x0,
CXPOLICY_SLOT = 0x1,
CXPOLICY_TYPE = 0x2,
CXPOLICY_MAX,
};
enum btc_b2w_scoreboard {
BTC_BSCB_ACT = BIT(0),
BTC_BSCB_ON = BIT(1),
BTC_BSCB_WHQL = BIT(2),
BTC_BSCB_BT_S1 = BIT(3),
BTC_BSCB_A2DP_ACT = BIT(4),
BTC_BSCB_RFK_RUN = BIT(5),
BTC_BSCB_RFK_REQ = BIT(6),
BTC_BSCB_LPS = BIT(7),
BTC_BSCB_BT_LNAB0 = BIT(8),
BTC_BSCB_BT_LNAB1 = BIT(10),
BTC_BSCB_WLRFK = BIT(11),
BTC_BSCB_BT_HILNA = BIT(13),
BTC_BSCB_BT_CONNECT = BIT(16),
BTC_BSCB_PATCH_CODE = BIT(30),
BTC_BSCB_ALL = GENMASK(30, 0),
};
enum btc_phymap {
BTC_PHY_0 = BIT(0),
BTC_PHY_1 = BIT(1),
BTC_PHY_ALL = BIT(0) | BIT(1),
};
enum btc_cx_state_map {
BTC_WIDLE = 0,
BTC_WBUSY_BNOSCAN,
BTC_WBUSY_BSCAN,
BTC_WSCAN_BNOSCAN,
BTC_WSCAN_BSCAN,
BTC_WLINKING
};
enum btc_ant_phase {
BTC_ANT_WPOWERON = 0,
BTC_ANT_WINIT,
BTC_ANT_WONLY,
BTC_ANT_WOFF,
BTC_ANT_W2G,
BTC_ANT_W5G,
BTC_ANT_W25G,
BTC_ANT_FREERUN,
BTC_ANT_WRFK,
BTC_ANT_WRFK2,
BTC_ANT_BRFK,
BTC_ANT_MAX
};
enum btc_plt {
BTC_PLT_NONE = 0,
BTC_PLT_LTE_RX = BIT(0),
BTC_PLT_GNT_BT_TX = BIT(1),
BTC_PLT_GNT_BT_RX = BIT(2),
BTC_PLT_GNT_WL = BIT(3),
BTC_PLT_BT = BIT(1) | BIT(2),
BTC_PLT_ALL = 0xf
};
enum btc_cx_poicy_main_type {
BTC_CXP_OFF = 0,
BTC_CXP_OFFB,
BTC_CXP_OFFE,
BTC_CXP_FIX,
BTC_CXP_PFIX,
BTC_CXP_AUTO,
BTC_CXP_PAUTO,
BTC_CXP_AUTO2,
BTC_CXP_PAUTO2,
BTC_CXP_MANUAL,
BTC_CXP_USERDEF0,
BTC_CXP_MAIN_MAX
};
enum btc_cx_poicy_type {
/* TDMA off + pri: BT > WL */
BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
/* TDMA off + pri: WL > BT */
BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
/* TDMA off + pri: BT = WL */
BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
/* TDMA off + pri: BT = WL > BT_Lo */
BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
/* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
/* TDMA off + pri: BT_Hi > WL > BT_Lo */
BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
/* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
/* TDMA off + pri: WL_Hi-Tx = BT */
BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
/* TDMA off + pri: WL > BT, Block-BT*/
BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
/* TDMA off + Ext-Ctrl + pri: default */
BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
/* TDMA off + Ext-Ctrl + pri: default */
BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
/* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
/* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
/* TDMA off + Ext-Ctrl + pri: default */
BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
/* TDMA Fix slot-0: W1:B1 = 30:30 */
BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
/* TDMA Fix slot-1: W1:B1 = 50:50 */
BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
/* TDMA Fix slot-2: W1:B1 = 20:30 */
BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
/* TDMA Fix slot-3: W1:B1 = 40:10 */
BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
/* TDMA Fix slot-4: W1:B1 = 70:10 */
BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
/* TDMA Fix slot-5: W1:B1 = 20:60 */
BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
/* TDMA Fix slot-6: W1:B1 = 30:60 */
BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
/* TDMA Fix slot-7: W1:B1 = 20:80 */
BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
/* TDMA Fix slot-8: W1:B1 = user-define */
BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
/* TDMA Fix slot-9: W1:B1 = 40:10 */
BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
/* TDMA Fix slot-10: W1:B1 = 40:10 */
BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
/* TDMA Fix slot-11: W1:B1 = 40:10 */
BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
/* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
/* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
/* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
/* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
/* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
/* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
/* PS-TDMA Fix slot-6: W1:B1 = user-define */
BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
/* TDMA Auto slot-0: W1:B1 = 50:200 */
BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
/* TDMA Auto slot-1: W1:B1 = 60:200 */
BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
/* TDMA Auto slot-2: W1:B1 = 20:200 */
BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
/* TDMA Auto slot-3: W1:B1 = user-define */
BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
/* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
/* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
/* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
/* PS-TDMA Auto slot-3: W1:B1 = user-define */
BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
/* TDMA Auto slot2-0: W1:B4 = 30:50 */
BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
/* TDMA Auto slot2-1: W1:B4 = 30:70 */
BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
/* TDMA Auto slot2-2: W1:B4 = 50:50 */
BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
/* TDMA Auto slot2-3: W1:B4 = 60:60 */
BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
/* TDMA Auto slot2-4: W1:B4 = 20:80 */
BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
/* TDMA Auto slot2-5: W1:B4 = user-define */
BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
/* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
/* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
/* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
/* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
/* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
/* PS-TDMA Auto slot2-5: W1:B4 = user-define */
BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
BTC_CXP_MAX = 0xffff
};
enum btc_wl_rfk_result {
BTC_WRFK_REJECT = 0,
BTC_WRFK_ALLOW = 1,
};
enum btc_coex_info_map_en {
BTC_COEX_INFO_CX = BIT(0),
BTC_COEX_INFO_WL = BIT(1),
BTC_COEX_INFO_BT = BIT(2),
BTC_COEX_INFO_DM = BIT(3),
BTC_COEX_INFO_MREG = BIT(4),
BTC_COEX_INFO_SUMMARY = BIT(5),
BTC_COEX_INFO_ALL = GENMASK(7, 0),
};
#define BTC_CXP_MASK GENMASK(15, 8)
enum btc_w2b_scoreboard {
BTC_WSCB_ACTIVE = BIT(0),
BTC_WSCB_ON = BIT(1),
BTC_WSCB_SCAN = BIT(2),
BTC_WSCB_UNDERTEST = BIT(3),
BTC_WSCB_RXGAIN = BIT(4),
BTC_WSCB_WLBUSY = BIT(7),
BTC_WSCB_EXTFEM = BIT(8),
BTC_WSCB_TDMA = BIT(9),
BTC_WSCB_FIX2M = BIT(10),
BTC_WSCB_WLRFK = BIT(11),
BTC_WSCB_RXSCAN_PRI = BIT(12),
BTC_WSCB_BT_HILNA = BIT(13),
BTC_WSCB_BTLOG = BIT(14),
BTC_WSCB_ALL = GENMASK(23, 0),
};
enum btc_wl_link_mode {
BTC_WLINK_NOLINK = 0x0,
BTC_WLINK_2G_STA,
BTC_WLINK_2G_AP,
BTC_WLINK_2G_GO,
BTC_WLINK_2G_GC,
BTC_WLINK_2G_SCC,
BTC_WLINK_2G_MCC,
BTC_WLINK_25G_MCC,
BTC_WLINK_25G_DBCC,
BTC_WLINK_5G,
BTC_WLINK_2G_NAN,
BTC_WLINK_OTHER,
BTC_WLINK_MAX
};
#define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
static const char *id_to_linkmode(u8 id)
{
switch (id) {
CASE_BTC_WL_LINK_MODE(NOLINK);
CASE_BTC_WL_LINK_MODE(2G_STA);
CASE_BTC_WL_LINK_MODE(2G_AP);
CASE_BTC_WL_LINK_MODE(2G_GO);
CASE_BTC_WL_LINK_MODE(2G_GC);
CASE_BTC_WL_LINK_MODE(2G_SCC);
CASE_BTC_WL_LINK_MODE(2G_MCC);
CASE_BTC_WL_LINK_MODE(25G_MCC);
CASE_BTC_WL_LINK_MODE(25G_DBCC);
CASE_BTC_WL_LINK_MODE(5G);
CASE_BTC_WL_LINK_MODE(OTHER);
default :
return "unknown" ;
}
}
enum btc_wl_mrole_type {
BTC_WLMROLE_NONE = 0x0,
BTC_WLMROLE_STA_GC,
BTC_WLMROLE_STA_GC_NOA,
BTC_WLMROLE_STA_GO,
BTC_WLMROLE_STA_GO_NOA,
BTC_WLMROLE_STA_STA,
BTC_WLMROLE_MAX
};
enum btc_bt_hid_type {
BTC_HID_218 = BIT(0),
BTC_HID_418 = BIT(1),
BTC_HID_BLE = BIT(2),
BTC_HID_RCU = BIT(3),
BTC_HID_RCU_VOICE = BIT(4),
BTC_HID_OTHER_LEGACY = BIT(5)
};
enum btc_reset_module {
BTC_RESET_CX = BIT(0),
BTC_RESET_DM = BIT(1),
BTC_RESET_CTRL = BIT(2),
BTC_RESET_CXDM = BIT(0) | BIT(1),
BTC_RESET_BTINFO = BIT(3),
BTC_RESET_MDINFO = BIT(4),
BTC_RESET_ALL = GENMASK(7, 0),
};
enum btc_gnt_state {
BTC_GNT_HW = 0,
BTC_GNT_SW_LO,
BTC_GNT_SW_HI,
BTC_GNT_MAX
};
enum btc_ctr_path {
BTC_CTRL_BY_BT = 0,
BTC_CTRL_BY_WL
};
enum btc_wlact_state {
BTC_WLACT_HW = 0,
BTC_WLACT_SW_LO,
BTC_WLACT_SW_HI,
BTC_WLACT_MAX,
};
enum btc_wl_max_tx_time {
BTC_MAX_TX_TIME_L1 = 500,
BTC_MAX_TX_TIME_L2 = 1000,
BTC_MAX_TX_TIME_L3 = 2000,
BTC_MAX_TX_TIME_DEF = 5280
};
enum btc_wl_max_tx_retry {
BTC_MAX_TX_RETRY_L1 = 7,
BTC_MAX_TX_RETRY_L2 = 15,
BTC_MAX_TX_RETRY_DEF = 31,
};
enum btc_reason_and_action {
BTC_RSN_NONE,
BTC_RSN_NTFY_INIT,
BTC_RSN_NTFY_SWBAND,
BTC_RSN_NTFY_WL_STA,
BTC_RSN_NTFY_RADIO_STATE,
BTC_RSN_UPDATE_BT_SCBD,
BTC_RSN_NTFY_WL_RFK,
BTC_RSN_UPDATE_BT_INFO,
BTC_RSN_NTFY_SCAN_START,
BTC_RSN_NTFY_SCAN_FINISH,
BTC_RSN_NTFY_SPECIFIC_PACKET,
BTC_RSN_NTFY_POWEROFF,
BTC_RSN_NTFY_ROLE_INFO,
BTC_RSN_CMD_SET_COEX,
BTC_RSN_ACT1_WORK,
BTC_RSN_BT_DEVINFO_WORK,
BTC_RSN_RFK_CHK_WORK,
BTC_RSN_NUM,
BTC_ACT_NONE = 100,
BTC_ACT_WL_ONLY,
BTC_ACT_WL_5G,
BTC_ACT_WL_OTHER,
BTC_ACT_WL_IDLE,
BTC_ACT_WL_NC,
BTC_ACT_WL_RFK,
BTC_ACT_WL_INIT,
BTC_ACT_WL_OFF,
BTC_ACT_FREERUN,
BTC_ACT_BT_WHQL,
BTC_ACT_BT_RFK,
BTC_ACT_BT_OFF,
BTC_ACT_BT_IDLE,
BTC_ACT_BT_HFP,
BTC_ACT_BT_HID,
BTC_ACT_BT_A2DP,
BTC_ACT_BT_A2DPSINK,
BTC_ACT_BT_PAN,
BTC_ACT_BT_A2DP_HID,
BTC_ACT_BT_A2DP_PAN,
BTC_ACT_BT_PAN_HID,
BTC_ACT_BT_A2DP_PAN_HID,
BTC_ACT_WL_25G_MCC,
BTC_ACT_WL_2G_MCC,
BTC_ACT_WL_2G_SCC,
BTC_ACT_WL_2G_AP,
BTC_ACT_WL_2G_GO,
BTC_ACT_WL_2G_GC,
BTC_ACT_WL_2G_NAN,
BTC_ACT_LAST,
BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
BTC_ACT_EXT_BIT = BIT(14),
BTC_POLICY_EXT_BIT = BIT(15),
};
#define BTC_FREERUN_ANTISO_MIN 30
#define BTC_TDMA_BTHID_MAX 2
#define BTC_BLINK_NOCONNECT 0
#define BTC_B1_MAX 250 /* unit ms */
static void _run_coex(struct rtw89_dev *rtwdev,
enum btc_reason_and_action reason);
static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
void *param, u16 len)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_wl_info *wl = &cx->wl;
struct rtw89_btc_dm *dm = &btc->dm;
int ret;
if (len > BTC_H2C_MAXLEN || len == 0) {
btc->fwinfo.cnt_h2c_fail++;
dm->error.map.h2c_buffer_over = true ;
return -EINVAL;
} else if (!wl->status.map.init_ok) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): return by btc not init!!\n" , __func__);
pfwinfo->cnt_h2c_fail++;
return -EINVAL;
} else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
(wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
wl->status.map.lps == BTC_LPS_RF_OFF)) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): return by wl off!!\n" , __func__);
pfwinfo->cnt_h2c_fail++;
return -EINVAL;
}
ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
false , true );
if (ret)
pfwinfo->cnt_h2c_fail++;
else
pfwinfo->cnt_h2c++;
return ret;
}
#define BTC_BT_DEF_BR_TX_PWR 4
#define BTC_BT_DEF_LE_TX_PWR 4
static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
{
struct rtw89_btc *btc = &rtwdev->btc;
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
struct rtw89_btc_wl_link_info *wl_linfo;
u8 i;
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n" , __func__);
if (type & BTC_RESET_CX)
memset(cx, 0, sizeof (*cx));
if (type & BTC_RESET_BTINFO) /* only for BT enable */
memset(bt, 0, sizeof (*bt));
if (type & BTC_RESET_CTRL) {
memset(&btc->ctrl, 0, sizeof (btc->ctrl));
btc->manual_ctrl = false ;
if (ver->fcxctrl != 7)
btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
}
/* Init Coex variables that are not zero */
if (type & BTC_RESET_DM) {
memset(&btc->dm, 0, sizeof (btc->dm));
memset(bt_linfo->rssi_state, 0, sizeof (bt_linfo->rssi_state));
for (i = 0; i < RTW89_PORT_NUM; i++) {
if (btc->ver->fwlrole == 8)
wl_linfo = &wl->rlink_info[i][0];
else
wl_linfo = &wl->link_info[i];
memset(wl_linfo->rssi_state, 0, sizeof (wl_linfo->rssi_state));
}
/* set the slot_now table to original */
btc->dm.tdma_now = t_def[CXTD_OFF];
btc->dm.tdma = t_def[CXTD_OFF];
if (ver->fcxslots >= 7) {
for (i = 0; i < ARRAY_SIZE(s_def); i++) {
btc->dm.slot.v7[i].dur = s_def[i].dur;
btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
}
memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
sizeof (btc->dm.slot_now.v7));
} else {
memcpy(&btc->dm.slot_now.v1, s_def,
sizeof (btc->dm.slot_now.v1));
memcpy(&btc->dm.slot.v1, s_def,
sizeof (btc->dm.slot.v1));
}
btc->policy_len = 0;
btc->bt_req_len = 0;
btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
}
if (type & BTC_RESET_MDINFO)
memset(&btc->mdinfo, 0, sizeof (btc->mdinfo));
bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR;
bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR;
}
static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 i;
for (i = 0; i < mreg_num; i++)
if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
le32_to_cpu(chip->mon_reg[i].offset) == target) {
return i;
}
return BTC_REG_NOTFOUND;
}
static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
{
struct rtw89_btc *btc = &rtwdev->btc;
const struct rtw89_btc_ver *ver = btc->ver;
union rtw89_btc_module_info *md = &btc->mdinfo;
union rtw89_btc_fbtc_mreg_val *pmreg;
u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
u32 reg_val;
u8 idx, switch_type;
if (ver->fcxinit == 7)
switch_type = md->md_v7.switch_type;
else
switch_type = md->md.switch_type;
if (btc->btg_pos == RF_PATH_A)
pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
switch (type) {
case BTC_CSTATUS_TXDIV_POS:
if (switch_type == BTC_SWITCH_INTERNAL)
*val = BTC_ANT_DIV_MAIN;
break ;
case BTC_CSTATUS_RXDIV_POS:
if (switch_type == BTC_SWITCH_INTERNAL)
*val = BTC_ANT_DIV_MAIN;
break ;
case BTC_CSTATUS_BB_GNT_MUX:
reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
*val = !(reg_val & B_BTC_BB_GNT_MUX);
break ;
case BTC_CSTATUS_BB_GNT_MUX_MON:
if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
return ;
pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
if (ver->fcxmreg == 1) {
idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
REG_BB, R_BTC_BB_BTG_RX);
if (idx == BTC_REG_NOTFOUND) {
*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
} else {
reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
*val = !(reg_val & B_BTC_BB_GNT_MUX);
}
} else if (ver->fcxmreg == 2) {
idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
REG_BB, R_BTC_BB_BTG_RX);
if (idx == BTC_REG_NOTFOUND) {
*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
} else {
reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
*val = !(reg_val & B_BTC_BB_GNT_MUX);
}
}
break ;
case BTC_CSTATUS_BB_PRE_AGC:
reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
reg_val &= B_BTC_BB_PRE_AGC_MASK;
*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
break ;
case BTC_CSTATUS_BB_PRE_AGC_MON:
if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
return ;
pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
if (ver->fcxmreg == 1) {
idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
REG_BB, pre_agc_addr);
if (idx == BTC_REG_NOTFOUND) {
*val = BTC_PREAGC_NOTFOUND;
} else {
reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
B_BTC_BB_PRE_AGC_MASK;
*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
}
} else if (ver->fcxmreg == 2) {
idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
REG_BB, pre_agc_addr);
if (idx == BTC_REG_NOTFOUND) {
*val = BTC_PREAGC_NOTFOUND;
} else {
reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
B_BTC_BB_PRE_AGC_MASK;
*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
}
}
break ;
default :
break ;
}
}
#define BTC_RPT_HDR_SIZE 3
#define BTC_CHK_WLSLOT_DRIFT_MAX 15
#define BTC_CHK_BTSLOT_DRIFT_MAX 15
#define BTC_CHK_HANG_MAX 3
static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_bt_info *bt = &cx->bt;
struct rtw89_btc_wl_info *wl = &cx->wl;
struct rtw89_btc_dm *dm = &btc->dm;
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): type:%d cnt:%d\n" ,
__func__, type, cnt);
switch (type) {
case BTC_DCNT_WL_FW_VER_MATCH:
if ((wl->ver_info.fw_coex & 0xffff0000) !=
rtwdev->chip->wlcx_desired) {
wl->fw_ver_mismatch = true ;
dm->error.map.wl_ver_mismatch = true ;
} else {
wl->fw_ver_mismatch = false ;
dm->error.map.wl_ver_mismatch = false ;
}
break ;
case BTC_DCNT_RPT_HANG:
if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
else
dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.wl_fw_hang = true ;
else
dm->error.map.wl_fw_hang = false ;
dm->cnt_dm[BTC_DCNT_RPT] = cnt;
break ;
case BTC_DCNT_CYCLE_HANG:
if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
(dm->tdma_now.type != CXTDMA_OFF ||
dm->tdma_now.ext_ctrl == CXECTL_EXT))
dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
else
dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.cycle_hang = true ;
else
dm->error.map.cycle_hang = false ;
dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
break ;
case BTC_DCNT_W1_HANG:
if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
dm->tdma_now.type != CXTDMA_OFF)
dm->cnt_dm[BTC_DCNT_W1_HANG]++;
else
dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.w1_hang = true ;
else
dm->error.map.w1_hang = false ;
dm->cnt_dm[BTC_DCNT_W1] = cnt;
break ;
case BTC_DCNT_B1_HANG:
if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
dm->tdma_now.type != CXTDMA_OFF)
dm->cnt_dm[BTC_DCNT_B1_HANG]++;
else
dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.b1_hang = true ;
else
dm->error.map.b1_hang = false ;
dm->cnt_dm[BTC_DCNT_B1] = cnt;
break ;
case BTC_DCNT_E2G_HANG:
if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
dm->tdma_now.ext_ctrl == CXECTL_EXT)
dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
else
dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.wl_e2g_hang = true ;
else
dm->error.map.wl_e2g_hang = false ;
dm->cnt_dm[BTC_DCNT_E2G] = cnt;
break ;
case BTC_DCNT_TDMA_NONSYNC:
if (cnt != 0) /* if tdma not sync between drv/fw */
dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
else
dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
dm->error.map.tdma_no_sync = true ;
else
dm->error.map.tdma_no_sync = false ;
break ;
case BTC_DCNT_SLOT_NONSYNC:
if (cnt != 0) /* if slot not sync between drv/fw */
dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
else
dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
dm->error.map.slot_no_sync = true ;
else
dm->error.map.slot_no_sync = false ;
break ;
case BTC_DCNT_BTTX_HANG:
cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
if (cnt == 0 && bt->link_info.slave_role)
dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
else
dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
dm->error.map.bt_tx_hang = true ;
else
dm->error.map.bt_tx_hang = false ;
break ;
case BTC_DCNT_BTCNT_HANG:
cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
cx->cnt_bt[BTC_BCNT_LOPRI_TX];
if (cnt == 0)
dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
else
dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
!bt->enable.now))
_update_bt_scbd(rtwdev, false );
break ;
case BTC_DCNT_WL_SLOT_DRIFT:
if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
else
dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
dm->error.map.wl_slot_drift = true ;
else
dm->error.map.wl_slot_drift = false ;
break ;
case BTC_DCNT_BT_SLOT_DRIFT:
if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
else
dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
dm->error.map.bt_slot_drift = true ;
else
dm->error.map.bt_slot_drift = false ;
break ;
}
}
static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
{
struct rtw89_btc *btc = &rtwdev->btc;
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
bool scan_update = true ;
int i;
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): rpt_type:%d\n" ,
__func__, rpt_type);
switch (rpt_type) {
case BTC_RPT_TYPE_BT_VER:
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,
GENMASK(7, 0));
bt->feature = le32_to_cpu(pver->v7.feature);
} else {
pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
GENMASK(7, 0));
bt->feature = le32_to_cpu(pver->v1.feature);
}
break ;
case BTC_RPT_TYPE_BT_SCAN:
if (ver->fcxbtscan == 1) {
pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
for (i = 0; i < BTC_SCAN_MAX1; i++) {
bt->scan_info_v1[i] = pscan_v1->scan[i];
if (bt->scan_info_v1[i].win == 0 &&
bt->scan_info_v1[i].intvl == 0)
scan_update = false ;
}
} else if (ver->fcxbtscan == 2) {
pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
for (i = 0; i < CXSCAN_MAX; i++) {
bt->scan_info_v2[i] = pscan_v2->para[i];
if ((pscan_v2->type & BIT(i)) &&
pscan_v2->para[i].win == 0 &&
pscan_v2->para[i].intvl == 0)
scan_update = false ;
}
} else if (ver->fcxbtscan == 7) {
pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
for (i = 0; i < CXSCAN_MAX; i++) {
bt->scan_info_v2[i] = pscan_v7->para[i];
if ((pscan_v7->type & BIT(i)) &&
pscan_v7->para[i].win == 0 &&
pscan_v7->para[i].intvl == 0)
scan_update = false ;
}
}
if (scan_update)
bt->scan_info_update = 1;
break ;
case BTC_RPT_TYPE_BT_AFH:
if (ver->fcxbtafh == 2) {
pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
}
if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
}
} else if (ver->fcxbtafh == 7) {
pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
}
if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
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 == 1) {
pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
}
break ;
case BTC_RPT_TYPE_BT_DEVICE:
pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
a2dp->device_name = le32_to_cpu(pdev->dev_name);
a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
a2dp->flush_time = le32_to_cpu(pdev->flush_time);
break ;
default :
break ;
}
}
static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
{
struct rtw89_btc *btc = &rtwdev->btc;
const struct rtw89_btc_ver *ver = btc->ver;
if (ver->fwevntrptl == 1)
return ;
if (*index <= __BTC_RPT_TYPE_V0_SAME)
return ;
else if (*index <= __BTC_RPT_TYPE_V0_MAX)
(*index)++;
else
*index = BTC_RPT_TYPE_MAX;
}
#define BTC_LEAK_AP_TH 10
#define BTC_CYSTA_CHK_PERIOD 100
struct rtw89_btc_prpt {
u8 type;
__le16 len;
u8 content[];
} __packed;
static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
struct rtw89_btc_btf_fwinfo *pfwinfo,
u8 *prptbuf, u32 index)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
struct rtw89_btc_prpt *btc_prpt = NULL;
void *rpt_content = NULL, *pfinfo = NULL;
u8 rpt_type = 0;
u16 wl_slot_set = 0, wl_slot_real = 0, val16;
u32 trace_step = 0, rpt_len = 0, diff_t = 0;
u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
u8 i, val = 0, val1, val2;
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): index:%d\n" ,
__func__, index);
if (!prptbuf) {
pfwinfo->err[BTFRE_INVALID_INPUT]++;
return 0;
}
btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
rpt_type = btc_prpt->type;
rpt_len = le16_to_cpu(btc_prpt->len);
rpt_content = btc_prpt->content;
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): rpt_type:%d\n" ,
__func__, rpt_type);
rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
switch (rpt_type) {
case BTC_RPT_TYPE_CTRL:
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
prpt = &pfwinfo->rpt_ctrl.finfo;
if (ver->fcxbtcrpt == 1) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v1);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
} else if (ver->fcxbtcrpt == 4) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v4);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
} else if (ver->fcxbtcrpt == 5) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v5);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
} else if (ver->fcxbtcrpt == 105) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v105);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
pcinfo->req_fver = 5;
break ;
} else if (ver->fcxbtcrpt == 8) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v8);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
} else if (ver->fcxbtcrpt == 7) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_ctrl.finfo.v7);
fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxbtcrpt;
break ;
case BTC_RPT_TYPE_TDMA:
pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
if (ver->fcxtdma == 1) {
pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_tdma.finfo.v1);
fwsubver->fcxtdma = 0;
} else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
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;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxtdma;
break ;
case BTC_RPT_TYPE_SLOT:
pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
if (ver->fcxslots == 1) {
pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_slots.finfo.v1);
fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
} else if (ver->fcxslots == 7) {
pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_slots.finfo.v7);
fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxslots;
break ;
case BTC_RPT_TYPE_CYSTA:
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
if (ver->fcxcysta == 2) {
pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_cysta.finfo.v2);
fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
} else if (ver->fcxcysta == 3) {
pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_cysta.finfo.v3);
fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
} else if (ver->fcxcysta == 4) {
pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_cysta.finfo.v4);
fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
} else if (ver->fcxcysta == 5) {
pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_cysta.finfo.v5);
fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
} else if (ver->fcxcysta == 7) {
pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_cysta.finfo.v7);
fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxcysta;
break ;
case BTC_RPT_TYPE_STEP:
pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
if (ver->fcxctrl != 7)
trace_step = btc->ctrl.ctrl.trace_step;
if (ver->fcxstep == 2) {
pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
trace_step +
offsetof(struct rtw89_btc_fbtc_steps_v2, step);
fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
} else if (ver->fcxstep == 3) {
pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
trace_step +
offsetof(struct rtw89_btc_fbtc_steps_v3, step);
fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxstep;
break ;
case BTC_RPT_TYPE_NULLSTA:
pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
if (ver->fcxnullsta == 1) {
pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_nullsta.finfo.v1);
fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
} else if (ver->fcxnullsta == 2) {
pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_nullsta.finfo.v2);
fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
} else if (ver->fcxnullsta == 7) {
pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_nullsta.finfo.v7);
fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxnullsta;
break ;
case BTC_RPT_TYPE_MREG:
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
if (ver->fcxmreg == 1) {
pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_mregval.finfo.v1);
fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
} else if (ver->fcxmreg == 2) {
pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_mregval.finfo.v2);
fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
} else if (ver->fcxmreg == 7) {
pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_mregval.finfo.v7);
fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
} else {
goto err;
}
pcinfo->req_fver = ver->fcxmreg;
break ;
case BTC_RPT_TYPE_GPIO_DBG:
pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
if (ver->fcxgpiodbg == 7) {
pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
} else {
pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
}
pcinfo->req_fver = ver->fcxgpiodbg;
break ;
case BTC_RPT_TYPE_BT_VER:
pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
if (ver->fcxbtver == 1) {
pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btver.finfo.v1);
fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
} else if (ver->fcxbtver == 7) {
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;
}
pcinfo->req_fver = ver->fcxbtver;
break ;
case BTC_RPT_TYPE_BT_SCAN:
pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
if (ver->fcxbtscan == 1) {
pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btscan.finfo.v1);
fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
} else if (ver->fcxbtscan == 2) {
pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btscan.finfo.v2);
fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
} else if (ver->fcxbtscan == 7) {
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 {
goto err;
}
pcinfo->req_fver = ver->fcxbtscan;
break ;
case BTC_RPT_TYPE_BT_AFH:
pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
if (ver->fcxbtafh == 1) {
pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btafh.finfo.v1);
fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
} else if (ver->fcxbtafh == 2) {
pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btafh.finfo.v2);
fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
} else if (ver->fcxbtafh == 7) {
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 {
goto err;
}
pcinfo->req_fver = ver->fcxbtafh;
break ;
case BTC_RPT_TYPE_BT_DEVICE:
pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
pcinfo->req_len = sizeof (pfwinfo->rpt_fbtc_btdev.finfo);
fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
pcinfo->req_fver = ver->fcxbtdevinfo;
break ;
default :
pfwinfo->err[BTFRE_UNDEF_TYPE]++;
return 0;
}
pcinfo->rx_len = rpt_len;
pcinfo->rx_cnt++;
if (rpt_len != pcinfo->req_len) {
if (rpt_type < BTC_RPT_TYPE_MAX)
pfwinfo->len_mismch |= (0x1 << rpt_type);
else
pfwinfo->len_mismch |= BIT(31);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): %d rpt_len:%d!=req_len:%d\n" ,
__func__, rpt_type, rpt_len, pcinfo->req_len);
pcinfo->valid = 0;
return 0;
} else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
pfwinfo->err[BTFRE_EXCEPTION]++;
pcinfo->valid = 0;
return 0;
}
memcpy(pfinfo, rpt_content, pcinfo->req_len);
pcinfo->valid = 1;
switch (rpt_type) {
case BTC_RPT_TYPE_CTRL:
if (ver->fcxbtcrpt == 1) {
prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
wl->ver_info.fw = prpt->v1.wl_fw_ver;
dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
pfwinfo->event[BTF_EVNT_RPT]);
/* To avoid I/O if WL LPS or power-off */
if (wl->status.map.lps != BTC_LPS_RF_OFF &&
!wl->status.map.rf_off) {
rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
btc->cx.cnt_bt[BTC_BCNT_POLUT] =
rtw89_mac_get_plt_cnt(rtwdev,
RTW89_MAC_0);
}
} else if (ver->fcxbtcrpt == 4) {
prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
sizeof (dm->gnt.band[i]));
btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
btc->cx.cnt_bt[BTC_BCNT_POLUT] =
le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
pfwinfo->event[BTF_EVNT_RPT]);
if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
bt->rfk_info.map.timeout = 1;
else
bt->rfk_info.map.timeout = 0;
dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
} else if (ver->fcxbtcrpt == 5) {
prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
dm->wl_fw_cx_offload = 0;
for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
sizeof (dm->gnt.band[i]));
btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
btc->cx.cnt_bt[BTC_BCNT_POLUT] =
le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
pfwinfo->event[BTF_EVNT_RPT]);
dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
} else if (ver->fcxbtcrpt == 105) {
prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
dm->wl_fw_cx_offload = 0;
for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
sizeof (dm->gnt.band[i]));
btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
btc->cx.cnt_bt[BTC_BCNT_POLUT] =
le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
pfwinfo->event[BTF_EVNT_RPT]);
dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
} else if (ver->fcxbtcrpt == 7) {
prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0],
sizeof (dm->gnt.band[i]));
btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
val1 = pfwinfo->event[BTF_EVNT_RPT];
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
} else if (ver->fcxbtcrpt == 8) {
prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
sizeof (dm->gnt.band[i]));
btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
val1 = pfwinfo->event[BTF_EVNT_RPT];
if (((prpt->v8.rpt_len_max_h << 8) +
prpt->v8.rpt_len_max_l) != ver->info_buf)
dm->error.map.h2c_c2h_buffer_mismatch = true ;
else
dm->error.map.h2c_c2h_buffer_mismatch = false ;
_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
} else {
goto err;
}
break ;
case BTC_RPT_TYPE_TDMA:
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): check %d %zu\n" , __func__,
BTC_DCNT_TDMA_NONSYNC,
sizeof (dm->tdma_now));
if (ver->fcxtdma == 1)
_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
memcmp(&dm->tdma_now,
&pfwinfo->rpt_fbtc_tdma.finfo.v1,
sizeof (dm->tdma_now)));
else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
memcmp(&dm->tdma_now,
&pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
sizeof (dm->tdma_now)));
else
goto err;
break ;
case BTC_RPT_TYPE_SLOT:
if (ver->fcxslots == 7) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): check %d %zu\n" ,
__func__, BTC_DCNT_SLOT_NONSYNC,
sizeof (dm->slot_now.v7));
_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
memcmp(dm->slot_now.v7,
pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
sizeof (dm->slot_now.v7)));
} else if (ver->fcxslots == 1) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): check %d %zu\n" ,
__func__, BTC_DCNT_SLOT_NONSYNC,
sizeof (dm->slot_now.v1));
_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
memcmp(dm->slot_now.v1,
pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
sizeof (dm->slot_now.v1)));
}
break ;
case BTC_RPT_TYPE_CYSTA:
if (ver->fcxcysta == 2) {
if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
break ;
/* Check Leak-AP */
if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
dm->leak_ap = 1;
}
/* Check diff time between WL slot and W1/E2G slot */
if (dm->tdma_now.type == CXTDMA_OFF &&
dm->tdma_now.ext_ctrl == CXECTL_EXT) {
if (ver->fcxslots == 1)
wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
else if (ver->fcxslots == 7)
wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
} else {
if (ver->fcxslots == 1)
wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
else if (ver->fcxslots == 7)
wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
}
if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
_chk_btc_err(rtwdev,
BTC_DCNT_WL_SLOT_DRIFT, diff_t);
}
_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
le16_to_cpu(pcysta->v2.cycles));
} else if (ver->fcxcysta == 3) {
if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
break ;
cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
/* Check Leak-AP */
if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
dm->tdma_now.rxflctrl) {
if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
dm->leak_ap = 1;
}
/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
if (ver->fcxslots == 1)
wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
else if (ver->fcxslots == 7)
wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
if (wl_slot_real > wl_slot_set) {
diff_t = wl_slot_real - wl_slot_set;
_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
}
}
/* Check diff time between real BT slot and EBT/E5G slot */
if (dm->tdma_now.type == CXTDMA_OFF &&
dm->tdma_now.ext_ctrl == CXECTL_EXT &&
btc->bt_req_len != 0) {
bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
if (btc->bt_req_len > bt_slot_real) {
diff_t = btc->bt_req_len - bt_slot_real;
_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
}
}
_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
le16_to_cpu(pcysta->v3.cycles));
} else if (ver->fcxcysta == 4) {
if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
break ;
cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
/* Check Leak-AP */
if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
dm->tdma_now.rxflctrl) {
if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
dm->leak_ap = 1;
}
/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
if (ver->fcxslots == 1)
wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
else if (ver->fcxslots == 7)
wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
if (wl_slot_real > wl_slot_set) {
diff_t = wl_slot_real - wl_slot_set;
_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
}
}
/* Check diff time between real BT slot and EBT/E5G slot */
if (dm->tdma_now.type == CXTDMA_OFF &&
dm->tdma_now.ext_ctrl == CXECTL_EXT &&
btc->bt_req_len != 0) {
bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
if (btc->bt_req_len > bt_slot_real) {
diff_t = btc->bt_req_len - bt_slot_real;
_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
}
}
_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
le16_to_cpu(pcysta->v4.cycles));
} else if (ver->fcxcysta == 5) {
if (dm->fddt_train == BTC_FDDT_ENABLE)
break ;
cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
/* Check Leak-AP */
if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
dm->tdma_now.rxflctrl) {
if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
dm->leak_ap = 1;
}
/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
if (ver->fcxslots == 1)
wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
else if (ver->fcxslots == 7)
wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
if (wl_slot_real > wl_slot_set)
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=97 H=92 G=94
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland