1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2019-2020 Realtek Corporation 3 */ 4 5 #include "chan.h" 6 #include "coex.h" 7 #include "debug.h" 8 #include "fw.h" 9 #include "mac.h" 10 #include "phy.h" 11 #include "ps.h" 12 #include "reg.h" 13 14 #define RTW89_COEX_VERSION 0x09180113 15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/ 16 #define BTC_E2G_LIMIT_DEF 80 17 18 enum btc_fbtc_tdma_template { 19 CXTD_OFF = 0x0, 20 CXTD_OFF_B2, 21 CXTD_OFF_EXT, 22 CXTD_FIX, 23 CXTD_PFIX, 24 CXTD_AUTO, 25 CXTD_PAUTO, 26 CXTD_AUTO2, 27 CXTD_PAUTO2, 28 CXTD_MAX, 29 }; 30 31 enum btc_fbtc_tdma_type { 32 CXTDMA_OFF = 0x0, 33 CXTDMA_FIX = 0x1, 34 CXTDMA_AUTO = 0x2, 35 CXTDMA_AUTO2 = 0x3, 36 CXTDMA_MAX 37 }; 38 39 enum btc_fbtc_tdma_rx_flow_ctrl { 40 CXFLC_OFF = 0x0, 41 CXFLC_NULLP = 0x1, 42 CXFLC_QOSNULL = 0x2, 43 CXFLC_CTS = 0x3, 44 CXFLC_MAX 45 }; 46 47 enum btc_fbtc_tdma_wlan_tx_pause { 48 CXTPS_OFF = 0x0, /* no wl tx pause*/ 49 CXTPS_ON = 0x1, 50 CXTPS_MAX 51 }; 52 53 enum btc_mlme_state { 54 MLME_NO_LINK, 55 MLME_LINKING, 56 MLME_LINKED, 57 }; 58 59 struct btc_fbtc_1slot { 60 u8 fver; 61 u8 sid; /* slot id */ 62 struct rtw89_btc_fbtc_slot slot; 63 } __packed; 64 65 static const struct rtw89_btc_fbtc_tdma t_def[] = { 66 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 67 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0}, 68 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0}, 69 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 70 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 71 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 72 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 73 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 74 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0} 75 }; 76 77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \ 78 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \ 79 .cxtype = cpu_to_le16(__cxtype),} 80 81 static const struct rtw89_btc_fbtc_slot s_def[] = { 82 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX), 83 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO), 84 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO), 85 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 86 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 87 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX), 88 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX), 89 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 90 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), 91 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), 92 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), 93 [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX), 94 [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), 95 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 96 [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX), 97 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), 98 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), 99 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), 100 }; 101 102 static const u32 cxtbl[] = { 103 0xffffffff, /* 0 */ 104 0xaaaaaaaa, /* 1 */ 105 0xe5555555, /* 2 */ 106 0xee555555, /* 3 */ 107 0xd5555555, /* 4 */ 108 0x5a5a5a5a, /* 5 */ 109 0xfa5a5a5a, /* 6 */ 110 0xda5a5a5a, /* 7 */ 111 0xea5a5a5a, /* 8 */ 112 0x6a5a5aaa, /* 9 */ 113 0x6a5a6a5a, /* 10 */ 114 0x6a5a6aaa, /* 11 */ 115 0x6afa5afa, /* 12 */ 116 0xaaaa5aaa, /* 13 */ 117 0xaaffffaa, /* 14 */ 118 0xaa5555aa, /* 15 */ 119 0xfafafafa, /* 16 */ 120 0xffffddff, /* 17 */ 121 0xdaffdaff, /* 18 */ 122 0xfafadafa, /* 19 */ 123 0xea6a6a6a, /* 20 */ 124 0xea55556a, /* 21 */ 125 0xaafafafa, /* 22 */ 126 0xfafaaafa, /* 23 */ 127 0xfafffaff, /* 24 */ 128 0xea6a5a5a, /* 25 */ 129 0xfaff5aff, /* 26 */ 130 0xffffdfff, /* 27 */ 131 0xe6555555, /* 28 */ 132 }; 133 134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { 135 /* firmware version must be in decreasing order for each chip */ 136 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 111, 0), 137 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 138 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 139 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 140 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, 141 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 142 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, 143 .fcxtrx = 9, 144 }, 145 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 94, 0), 146 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 147 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 148 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 149 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 10, 150 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 151 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, 152 .fcxtrx = 9, 153 }, 154 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 133, 0), 155 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 156 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 157 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 158 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107, 159 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 160 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 161 .fcxtrx = 107, 162 }, 163 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0), 164 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 165 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 166 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 167 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 168 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800, 169 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 170 .fcxtrx = 0, 171 }, 172 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0), 173 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 174 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 175 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 176 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 177 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800, 178 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 179 .fcxtrx = 0, 180 }, 181 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 111, 0), 182 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 183 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 184 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 185 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, 186 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 187 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, 188 .fcxtrx = 9, 189 }, 190 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0), 191 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 192 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 193 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 194 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7, 195 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 3, .info_buf = 1800, 196 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 197 .fcxtrx = 7, 198 }, 199 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0), 200 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 201 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 202 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 203 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7, 204 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 2, .info_buf = 1800, 205 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 206 .fcxtrx = 0, 207 }, 208 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), 209 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 210 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 211 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 212 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 213 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_ver = 1, .info_buf = 1800, 214 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 215 .fcxtrx = 0, 216 }, 217 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 133, 0), 218 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 219 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 220 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 221 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107, 222 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 223 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 224 .fcxtrx = 107, 225 }, 226 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), 227 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 228 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 229 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 230 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 231 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 232 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 233 .fcxtrx = 0, 234 }, 235 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 97, 0), 236 .fcxbtcrpt = 4, .fcxtdma = 4, .fcxslots = 2, .fcxcysta = 105, 237 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 238 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 239 .fwlrole = 101, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 240 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 241 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 242 .fcxtrx = 107, 243 }, 244 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), 245 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 246 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 247 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 248 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 249 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 250 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 251 .fcxtrx = 0, 252 }, 253 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), 254 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 255 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 256 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 257 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 258 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 259 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 260 .fcxtrx = 0, 261 }, 262 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), 263 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 264 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 265 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 266 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 267 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 268 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 269 .fcxtrx = 0, 270 }, 271 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 133, 0), 272 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 273 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 274 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 275 .fwlrole = 7, .frptmap = 105, .fcxctrl = 7, .fcxinit = 107, 276 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 277 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 278 .fcxtrx = 107, 279 }, 280 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0), 281 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 282 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 283 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 284 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 285 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800, 286 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 287 .fcxtrx = 0, 288 }, 289 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), 290 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 291 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 292 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 293 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 294 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 295 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 296 .fcxtrx = 0, 297 }, 298 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), 299 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, 300 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 301 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 302 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 303 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 304 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 305 .fcxtrx = 0, 306 }, 307 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), 308 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 309 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 310 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 311 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, 312 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 313 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 314 .fcxtrx = 0, 315 }, 316 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), 317 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 318 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 319 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 320 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 321 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1280, 322 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 323 .fcxtrx = 0, 324 }, 325 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), 326 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 327 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 328 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 329 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 330 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1024, 331 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 332 .fcxtrx = 0, 333 }, 334 335 /* keep it to be the last as default entry */ 336 {0, RTW89_FW_VER_CODE(0, 0, 0, 0), 337 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 338 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 339 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 340 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 341 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1024, 342 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 343 .fcxtrx = 0, 344 }, 345 }; 346 347 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1) 348 349 static const union rtw89_btc_wl_state_map btc_scanning_map = { 350 .map = { 351 .scan = 1, 352 .dhcp = 1, 353 .roaming = 1, 354 .transacting = 1, 355 ._4way = 1, 356 .handshake = 1, 357 }, 358 }; 359 360 static u32 chip_id_to_bt_rom_code_id(u32 id) 361 { 362 switch (id) { 363 case RTL8852A: 364 case RTL8852B: 365 case RTL8852C: 366 case RTL8852BT: 367 return 0x8852; 368 case RTL8851B: 369 return 0x8851; 370 case RTL8922A: 371 case RTL8922D: 372 return 0x8922; 373 default: 374 return 0; 375 } 376 } 377 378 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e 379 380 static const char *id_to_mlme_state(u32 id) 381 { 382 switch (id) { 383 CASE_BTC_MLME_STATE(NO_LINK); 384 CASE_BTC_MLME_STATE(LINKING); 385 CASE_BTC_MLME_STATE(LINKED); 386 default: 387 return "unknown"; 388 } 389 } 390 391 static char *chip_id_str(u32 id) 392 { 393 switch (id) { 394 case RTL8852A: 395 return "RTL8852A"; 396 case RTL8852B: 397 return "RTL8852B"; 398 case RTL8852C: 399 return "RTL8852C"; 400 case RTL8852BT: 401 return "RTL8852BT"; 402 case RTL8851B: 403 return "RTL8851B"; 404 case RTL8922A: 405 return "RTL8922A"; 406 case RTL8922D: 407 return "RTL8922D"; 408 default: 409 return "UNKNOWN"; 410 } 411 } 412 413 struct rtw89_btc_btf_tlv { 414 u8 type; 415 u8 len; 416 u8 val[]; 417 } __packed; 418 419 struct rtw89_btc_btf_tlv_v7 { 420 u8 type; 421 u8 ver; 422 u8 len; 423 u8 val[]; 424 } __packed; 425 426 enum btc_btf_set_report_en { 427 RPT_EN_TDMA, 428 RPT_EN_CYCLE, 429 RPT_EN_MREG, 430 RPT_EN_BT_VER_INFO, 431 RPT_EN_BT_SCAN_INFO, 432 RPT_EN_BT_DEVICE_INFO, 433 RPT_EN_BT_AFH_MAP, 434 RPT_EN_BT_AFH_MAP_LE, 435 RPT_EN_BT_TX_PWR_LVL, 436 RPT_EN_FW_STEP_INFO, 437 RPT_EN_TEST, 438 RPT_EN_WL_ALL, 439 RPT_EN_BT_ALL, 440 RPT_EN_ALL, 441 RPT_EN_MONITER, 442 }; 443 444 struct rtw89_btc_btf_set_report_v1 { 445 u8 fver; 446 __le32 enable; 447 __le32 para; 448 } __packed; 449 450 struct rtw89_btc_btf_set_report_v8 { 451 u8 type; 452 u8 fver; 453 u8 len; 454 __le32 map; 455 } __packed; 456 457 union rtw89_fbtc_rtp_ctrl { 458 struct rtw89_btc_btf_set_report_v1 v1; 459 struct rtw89_btc_btf_set_report_v8 v8; 460 }; 461 462 #define BTF_SET_SLOT_TABLE_VER 1 463 struct rtw89_btc_btf_set_slot_table { 464 u8 fver; 465 u8 tbl_num; 466 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); 467 } __packed; 468 469 struct rtw89_btc_btf_set_slot_table_v7 { 470 u8 type; 471 u8 ver; 472 u8 len; 473 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX]; 474 } __packed; 475 476 struct rtw89_btc_btf_set_mon_reg_v1 { 477 u8 fver; 478 u8 reg_num; 479 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); 480 } __packed; 481 482 struct rtw89_btc_btf_set_mon_reg_v7 { 483 u8 type; 484 u8 fver; 485 u8 len; 486 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len); 487 } __packed; 488 489 union rtw89_fbtc_set_mon_reg { 490 struct rtw89_btc_btf_set_mon_reg_v1 v1; 491 struct rtw89_btc_btf_set_mon_reg_v7 v7; 492 } __packed; 493 494 enum btc_btf_set_cx_policy { 495 CXPOLICY_TDMA = 0x0, 496 CXPOLICY_SLOT = 0x1, 497 CXPOLICY_TYPE = 0x2, 498 CXPOLICY_MAX, 499 }; 500 501 enum btc_b2w_scoreboard { 502 BTC_BSCB_ACT = BIT(0), 503 BTC_BSCB_ON = BIT(1), 504 BTC_BSCB_WHQL = BIT(2), 505 BTC_BSCB_BT_S1 = BIT(3), 506 BTC_BSCB_A2DP_ACT = BIT(4), 507 BTC_BSCB_RFK_RUN = BIT(5), 508 BTC_BSCB_RFK_REQ = BIT(6), 509 BTC_BSCB_LPS = BIT(7), 510 BTC_BSCB_BT_LNAB0 = BIT(8), 511 BTC_BSCB_BT_LNAB1 = BIT(10), 512 BTC_BSCB_WLRFK = BIT(11), 513 BTC_BSCB_BT_HILNA = BIT(13), 514 BTC_BSCB_BT_HILNA_56G = BIT(14), 515 BTC_BSCB_CTCODE = BIT(15), 516 BTC_BSCB_BT_CONNECT = BIT(16), 517 BTC_BSCB_BT_CONNECT_56G = BIT(17), 518 BTC_BSCB_BT_LNAB0_56G = BIT(18), 519 BTC_BSCB_BT_LNAB1_56G = BIT(19), 520 BTC_BSCB_BT_15DOT4 = BIT(24), 521 BTC_BSCB_BT_PROTECT = BIT(27), 522 BTC_BSCB_PAN_ACT = BIT(28), 523 BTC_BSCB_HFP_ACT = BIT(29), 524 BTC_BSCB_PATCH_CODE = BIT(30), 525 BTC_BSCB_ALL = GENMASK(30, 0), 526 }; 527 528 enum btc_phymap { 529 BTC_PHY_0 = BIT(0), 530 BTC_PHY_1 = BIT(1), 531 BTC_PHY_ALL = BIT(0) | BIT(1), 532 }; 533 534 enum btc_cx_state_map { 535 BTC_WIDLE = 0, 536 BTC_WBUSY_BNOSCAN, 537 BTC_WBUSY_BSCAN, 538 BTC_WSCAN_BNOSCAN, 539 BTC_WSCAN_BSCAN, 540 BTC_WLINKING 541 }; 542 543 enum btc_ant_phase { 544 BTC_ANT_WPOWERON = 0, 545 BTC_ANT_WINIT, 546 BTC_ANT_WONLY, 547 BTC_ANT_WOFF, 548 BTC_ANT_W2G, 549 BTC_ANT_FDD, 550 BTC_ANT_W25G, 551 BTC_ANT_FREERUN, 552 BTC_ANT_WRFK, 553 BTC_ANT_WRFK2, 554 BTC_ANT_PTA, /* for Multi-PTA, each hw-band has its own PTA */ 555 BTC_ANT_MAX 556 }; 557 558 enum btc_plt { 559 BTC_PLT_NONE = 0, 560 BTC_PLT_LTE_RX = BIT(0), 561 BTC_PLT_GNT_BT_TX = BIT(1), 562 BTC_PLT_GNT_BT_RX = BIT(2), 563 BTC_PLT_GNT_WL = BIT(3), 564 BTC_PLT_BT = BIT(1) | BIT(2), 565 BTC_PLT_ALL = 0xf 566 }; 567 568 enum btc_cx_poicy_main_type { 569 BTC_CXP_OFF = 0, 570 BTC_CXP_OFFB, 571 BTC_CXP_OFFE, 572 BTC_CXP_FIX, 573 BTC_CXP_PFIX, 574 BTC_CXP_AUTO, 575 BTC_CXP_PAUTO, 576 BTC_CXP_AUTO2, 577 BTC_CXP_PAUTO2, 578 BTC_CXP_MANUAL, 579 BTC_CXP_USERDEF0, 580 BTC_CXP_MAIN_MAX 581 }; 582 583 enum btc_bslot_length { 584 BTC_BSLOT_A2DP_HID = 60, 585 BTC_BSLOT_A2DP = 50, 586 BTC_BSLOT_A2DP_2 = 40, 587 BTC_BSLOT_INQ = 30, 588 BTC_BSLOT_IDLE = 20, 589 }; 590 591 enum btc_cx_poicy_type { 592 /* TDMA off + pri: BT > WL */ 593 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0, 594 595 /* TDMA off + pri: WL > BT */ 596 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1, 597 598 /* TDMA off + pri: BT = WL */ 599 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2, 600 601 /* TDMA off + pri: BT = WL > BT_Lo */ 602 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3, 603 604 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */ 605 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4, 606 607 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 608 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5, 609 610 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 611 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6, 612 613 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 614 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7, 615 616 /* TDMA off + pri: BT_Hi > WL > BT_Lo */ 617 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8, 618 619 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 620 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9, 621 622 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 623 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10, 624 625 /* TDMA off + pri: WL_Hi-Tx = BT */ 626 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11, 627 628 /* TDMA off + pri: WL > BT, Block-BT*/ 629 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12, 630 631 /* TDMA off+Bcn-Protect + pri: BT_Hi > WL > BT_Lo */ 632 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0, 633 634 /* TDMA off+Bcn-Protect + pri: BT_Hi_Tx = WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 635 BTC_CXP_OFFB_BWB1 = (BTC_CXP_OFFB << 8) | 1, 636 637 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 638 BTC_CXP_OFFB_BWB2 = (BTC_CXP_OFFB << 8) | 2, 639 640 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx = BT*/ 641 BTC_CXP_OFFB_BWB3 = (BTC_CXP_OFFB << 8) | 3, 642 643 /* TDMA off+Bcn-Protect + pri: BT > WL*/ 644 BTC_CXP_OFFB_BWB4 = (BTC_CXP_OFFB << 8) | 4, 645 646 /* TDMA off + Ext-Ctrl + pri: default */ 647 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0, 648 649 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 650 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1, 651 652 /* TDMA off + Ext-Ctrl + pri: default */ 653 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2, 654 655 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 656 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3, 657 658 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */ 659 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4, 660 661 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */ 662 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5, 663 664 /* TDMA off + Ext-Ctrl + pri: default */ 665 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6, 666 667 /* TDMA Fix slot-0: W1:B1 = 30:30 */ 668 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0, 669 670 /* TDMA Fix slot-1: W1:B1 = 50:50 */ 671 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1, 672 673 /* TDMA Fix slot-2: W1:B1 = 20:30 */ 674 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2, 675 676 /* TDMA Fix slot-3: W1:B1 = 40:10 */ 677 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3, 678 679 /* TDMA Fix slot-4: W1:B1 = 70:10 */ 680 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4, 681 682 /* TDMA Fix slot-5: W1:B1 = 20:60 */ 683 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5, 684 685 /* TDMA Fix slot-6: W1:B1 = 30:60 */ 686 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6, 687 688 /* TDMA Fix slot-7: W1:B1 = 20:80 */ 689 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7, 690 691 /* TDMA Fix slot-8: W1:B1 = user-define */ 692 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8, 693 694 /* TDMA Fix slot-9: W1:B1 = 40:10 */ 695 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9, 696 697 /* TDMA Fix slot-10: W1:B1 = 40:10 */ 698 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10, 699 700 /* TDMA Fix slot-11: W1:B1 = 40:10 */ 701 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11, 702 703 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */ 704 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0, 705 706 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */ 707 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1, 708 709 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */ 710 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2, 711 712 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */ 713 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3, 714 715 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */ 716 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4, 717 718 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */ 719 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5, 720 721 /* PS-TDMA Fix slot-6: W1:B1 = user-define */ 722 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6, 723 724 /* TDMA Auto slot-0: W1:B1 = 50:200 */ 725 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0, 726 727 /* TDMA Auto slot-1: W1:B1 = 60:200 */ 728 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1, 729 730 /* TDMA Auto slot-2: W1:B1 = 20:200 */ 731 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2, 732 733 /* TDMA Auto slot-3: W1:B1 = user-define */ 734 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3, 735 736 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */ 737 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0, 738 739 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */ 740 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1, 741 742 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */ 743 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2, 744 745 /* PS-TDMA Auto slot-3: W1:B1 = user-define */ 746 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3, 747 748 /* TDMA Auto slot2-0: W1:B4 = 30:50 */ 749 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0, 750 751 /* TDMA Auto slot2-1: W1:B4 = 30:70 */ 752 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1, 753 754 /* TDMA Auto slot2-2: W1:B4 = 50:50 */ 755 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2, 756 757 /* TDMA Auto slot2-3: W1:B4 = 60:60 */ 758 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3, 759 760 /* TDMA Auto slot2-4: W1:B4 = 20:80 */ 761 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4, 762 763 /* TDMA Auto slot2-5: W1:B4 = user-define */ 764 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5, 765 766 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */ 767 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0, 768 769 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */ 770 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1, 771 772 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */ 773 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2, 774 775 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */ 776 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3, 777 778 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */ 779 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4, 780 781 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */ 782 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5, 783 784 BTC_CXP_MAX = 0xffff 785 }; 786 787 enum btc_wl_rfk_result { 788 BTC_WRFK_REJECT = 0, 789 BTC_WRFK_ALLOW = 1, 790 }; 791 792 enum btc_coex_info_map_en { 793 BTC_COEX_INFO_CX = BIT(0), 794 BTC_COEX_INFO_WL = BIT(1), 795 BTC_COEX_INFO_BT = BIT(2), 796 BTC_COEX_INFO_DM = BIT(3), 797 BTC_COEX_INFO_MREG = BIT(4), 798 BTC_COEX_INFO_SUMMARY = BIT(5), 799 BTC_COEX_INFO_ALL = GENMASK(7, 0), 800 }; 801 802 #define BTC_CXP_MASK GENMASK(15, 8) 803 804 enum btc_w2b_scoreboard { 805 BTC_WSCB_ACTIVE = BIT(0), 806 BTC_WSCB_ON = BIT(1), 807 BTC_WSCB_SCAN = BIT(2), 808 BTC_WSCB_UNDERTEST = BIT(3), 809 BTC_WSCB_RXGAIN = BIT(4), 810 BTC_WSCB_5GHICH = BIT(6), 811 BTC_WSCB_WLBUSY = BIT(7), 812 BTC_WSCB_EXTFEM = BIT(8), 813 BTC_WSCB_TDMA = BIT(9), 814 BTC_WSCB_FIX2M = BIT(10), 815 BTC_WSCB_WLRFK = BIT(11), 816 BTC_WSCB_RXSCAN_PRI = BIT(12), 817 BTC_WSCB_BT_HILNA = BIT(13), 818 BTC_WSCB_BTLOG = BIT(14), 819 BTC_WSCB_CTCODE = BIT(15), 820 BTC_WSCB_RXGAIN_56G = BIT(16), 821 BTC_WSCB_BT_HILNA_56G = BIT(17), 822 BTC_WSCB_ALL = GENMASK(23, 0), 823 }; 824 825 enum btc_wl_link_mode_v0 { 826 BTC_WLINK_V0_NOLINK = 0x0, 827 BTC_WLINK_V0_2G_STA, 828 BTC_WLINK_V0_2G_AP, 829 BTC_WLINK_V0_2G_GO, 830 BTC_WLINK_V0_2G_GC, 831 BTC_WLINK_V0_2G_SCC, 832 BTC_WLINK_V0_2G_MCC, 833 BTC_WLINK_V0_25G_MCC, 834 BTC_WLINK_V0_25G_DBCC, 835 BTC_WLINK_V0_5G, 836 BTC_WLINK_V0_2G_NAN, 837 BTC_WLINK_V0_OTHER, 838 BTC_WLINK_V0_MAX 839 }; 840 841 enum btc_wl_link_mode_v1 { 842 BTC_WLINK_NOLINK = 0x0, 843 BTC_WLINK_STA, 844 BTC_WLINK_AP, 845 BTC_WLINK_GO, 846 BTC_WLINK_GC, 847 BTC_WLINK_SCC, 848 BTC_WLINK_SB_MCC, 849 BTC_WLINK_DB_MCC, /* 2+0/0+2 Dual-RF-band MCC */ 850 BTC_WLINK_MAX 851 }; 852 853 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e 854 855 static const char *id_to_linkmode(u8 id) 856 { 857 switch (id) { 858 CASE_BTC_WL_LINK_MODE(NOLINK); 859 CASE_BTC_WL_LINK_MODE(STA); 860 CASE_BTC_WL_LINK_MODE(AP); 861 CASE_BTC_WL_LINK_MODE(GO); 862 CASE_BTC_WL_LINK_MODE(GC); 863 CASE_BTC_WL_LINK_MODE(SCC); 864 CASE_BTC_WL_LINK_MODE(SB_MCC); 865 CASE_BTC_WL_LINK_MODE(DB_MCC); 866 default: 867 return "unknown"; 868 } 869 } 870 871 enum btc_wl_mrole_type { 872 BTC_WLMROLE_NONE = 0x0, 873 BTC_WLMROLE_STA_GC, 874 BTC_WLMROLE_STA_GC_NOA, 875 BTC_WLMROLE_STA_GO, 876 BTC_WLMROLE_STA_GO_NOA, 877 BTC_WLMROLE_STA_STA, 878 BTC_WLMROLE_MAX 879 }; 880 881 enum btc_bt_hid_type { 882 BTC_HID_218 = BIT(0), 883 BTC_HID_418 = BIT(1), 884 BTC_HID_BLE = BIT(2), 885 BTC_HID_RCU = BIT(3), 886 BTC_HID_RCU_VOICE = BIT(4), 887 BTC_HID_OTHER_LEGACY = BIT(5) 888 }; 889 890 enum btc_reset_module { 891 BTC_RESET_CX = BIT(0), 892 BTC_RESET_DM = BIT(1), 893 BTC_RESET_CTRL = BIT(2), 894 BTC_RESET_CXDM = BIT(0) | BIT(1), 895 BTC_RESET_BTINFO = BIT(3), 896 BTC_RESET_MDINFO = BIT(4), 897 BTC_RESET_BT_PSD_DM = BIT(5), 898 BTC_RESET_BTINFO2 = BIT(6), 899 BTC_RESET_ALL = GENMASK(7, 0), 900 }; 901 902 enum btc_gnt_state { 903 BTC_GNT_HW = 0, 904 BTC_GNT_SW_LO, 905 BTC_GNT_SW_HI, 906 BTC_GNT_MAX, 907 908 BTC_GNT_SET_SKIP = 0xff, 909 }; 910 911 enum btc_ctr_path { 912 BTC_CTRL_BY_BT = 0, 913 BTC_CTRL_BY_WL 914 }; 915 916 enum btc_wlact_state { 917 BTC_WLACT_HW = 0, 918 BTC_WLACT_SW_LO, 919 BTC_WLACT_SW_HI, 920 BTC_WLACT_MAX, 921 }; 922 923 enum btc_wl_max_tx_time { 924 BTC_MAX_TX_TIME_L1 = 500, 925 BTC_MAX_TX_TIME_L2 = 1000, 926 BTC_MAX_TX_TIME_L3 = 2000, 927 BTC_MAX_TX_TIME_DEF = 5280 928 }; 929 930 enum btc_wl_max_tx_retry { 931 BTC_MAX_TX_RETRY_L1 = 7, 932 BTC_MAX_TX_RETRY_L2 = 15, 933 BTC_MAX_TX_RETRY_DEF = 31, 934 }; 935 936 enum btc_reason_and_action { 937 BTC_RSN_NONE, 938 BTC_RSN_NTFY_INIT, 939 BTC_RSN_NTFY_SWBAND, 940 BTC_RSN_NTFY_WL_STA, 941 BTC_RSN_NTFY_RADIO_STATE, 942 BTC_RSN_UPDATE_BT_SCBD, 943 BTC_RSN_NTFY_WL_RFK, 944 BTC_RSN_UPDATE_BT_INFO, 945 BTC_RSN_NTFY_SCAN_START, 946 BTC_RSN_NTFY_SCAN_FINISH, 947 BTC_RSN_NTFY_SPECIFIC_PACKET, 948 BTC_RSN_NTFY_POWEROFF, 949 BTC_RSN_NTFY_ROLE_INFO, 950 BTC_RSN_CMD_SET_COEX, 951 BTC_RSN_ACT1_WORK, 952 BTC_RSN_BT_DEVINFO_WORK, 953 BTC_RSN_RFK_CHK_WORK, 954 BTC_RSN_UPDATE_BT_LEAUDINFO, 955 BTC_RSN_NUM, 956 BTC_ACT_NONE = 100, 957 BTC_ACT_WL_ONLY, 958 BTC_ACT_WL_5G, 959 BTC_ACT_WL_OTHER, 960 BTC_ACT_WL_IDLE, 961 BTC_ACT_WL_NC, 962 BTC_ACT_WL_RFK, 963 BTC_ACT_WL_INIT, 964 BTC_ACT_WL_OFF, 965 BTC_ACT_FREERUN, 966 BTC_ACT_BT_WHQL, 967 BTC_ACT_BT_RFK, 968 BTC_ACT_BT_OFF, 969 BTC_ACT_BT_IDLE, 970 BTC_ACT_BT_HFP, 971 BTC_ACT_BT_HID, 972 BTC_ACT_BT_A2DP, 973 BTC_ACT_BT_A2DPSINK, 974 BTC_ACT_BT_PAN, 975 BTC_ACT_BT_A2DP_HID, 976 BTC_ACT_BT_A2DP_PAN, 977 BTC_ACT_BT_PAN_HID, 978 BTC_ACT_BT_A2DP_PAN_HID, 979 BTC_ACT_BT_BIS, 980 BTC_ACT_BT_CIS, 981 BTC_ACT_WL_25G_MCC, 982 BTC_ACT_WL_2G_MCC, 983 BTC_ACT_WL_2G_SCC, 984 BTC_ACT_WL_2G_AP, 985 BTC_ACT_WL_2G_GO, 986 BTC_ACT_WL_2G_GC, 987 BTC_ACT_WL_2G_NAN, 988 BTC_ACT_LAST, 989 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE, 990 BTC_ACT_EXT_BIT = BIT(14), 991 BTC_POLICY_EXT_BIT = BIT(15), 992 }; 993 994 #define BTC_FREERUN_ANTISO_MIN 30 995 #define BTC_TDMA_BTHID_MAX 2 996 #define BTC_BLINK_NOCONNECT 0 997 #define BTC_B1_MAX 250 /* unit ms */ 998 999 static void _run_coex(struct rtw89_dev *rtwdev, 1000 enum btc_reason_and_action reason); 1001 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state); 1002 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid); 1003 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid); 1004 static const char *id_to_h2c(u32 id); 1005 1006 static void _reset_h2c_macro(struct rtw89_btc *btc) 1007 { 1008 btc->hbuf_len = 0; 1009 btc->hbuf_cnt = 0; 1010 memset(btc->hbuf, 0, BTC_H2C_MAXLEN); 1011 } 1012 1013 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, 1014 void *param, u16 len) 1015 { 1016 struct rtw89_btc *btc = &rtwdev->btc; 1017 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 1018 struct rtw89_btc_cx *cx = &btc->cx; 1019 struct rtw89_btc_wl_info *wl = &cx->wl; 1020 struct rtw89_btc_dm *dm = &btc->dm; 1021 u8 h2c_func_mask, bid = BTC_BT_1ST; 1022 u8 *buf = param; 1023 int ret; 1024 1025 if (len > BTC_H2C_MAXLEN || len == 0) { 1026 btc->fwinfo.cnt_h2c_fail++; 1027 dm->error.map.h2c_buffer_over = true; 1028 return -EINVAL; 1029 } else if (!wl->status.map.init_ok) { 1030 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1031 "[BTC], %s(): return by btc not init!!\n", __func__); 1032 pfwinfo->cnt_h2c_fail++; 1033 return -EINVAL; 1034 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF && 1035 wl->status.map.rf_off == BTC_LPS_RF_OFF) || 1036 (wl->status.map.lps_pre == BTC_LPS_RF_OFF && 1037 wl->status.map.lps == BTC_LPS_RF_OFF)) { 1038 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1039 "[BTC], %s(): return by wl off!!\n", __func__); 1040 pfwinfo->cnt_h2c_fail++; 1041 return -EINVAL; 1042 } 1043 1044 h2c_func_mask = h2c_func & (~BT_H2C_FUNC_BT2ND); 1045 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 1046 bid = !!(h2c_func & BT_H2C_FUNC_BT2ND); 1047 1048 if (btc->io_oflld_type != BTC_IO_OFLD_BTC_H2C || btc->cli_h2c_cmd || 1049 h2c_func_mask == SET_H2C_MACRO || 1050 (h2c_func_mask == SET_DRV_INFO && buf[0] == CXDRVINFO_TRX) || 1051 (h2c_func_mask == SET_IOFLD_SCBD && dm->scbd_write_instant) || 1052 h2c_func_mask == SET_BT_LNA_CONSTRAIN) { 1053 h2c_class = BTFC_SET; 1054 1055 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, 1056 buf, len, false, true); 1057 1058 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1059 "[BTC], %s():class=%d, bt%d-func=%s, len=%d\n", 1060 __func__, h2c_class, bid, 1061 id_to_h2c(h2c_func_mask), len); 1062 1063 if (h2c_func_mask == SET_H2C_MACRO) { 1064 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1065 "[BTC], %s():Send H2C-MACRO cnt=%d, len=%d\n", 1066 __func__, btc->hbuf_cnt, btc->hbuf_len); 1067 _reset_h2c_macro(btc); /* clear H2C MACRO buffer */ 1068 } 1069 1070 if (ret != 0) { /* Send H2C fail */ 1071 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1072 "[BTC], %s():return by rtw_hal_mac_send_h2c\n", 1073 __func__); 1074 btc->fwinfo.cnt_h2c_fail++; 1075 return 0; 1076 } 1077 1078 btc->fwinfo.cnt_h2c++; 1079 return 0; 1080 } else { /* Fill H2C MACRO buffer(TLV format) temporarily */ 1081 if (btc->hbuf_cnt == 0) 1082 _reset_h2c_macro(btc); 1083 1084 /* Type:1 byte, Length:2 Bytes, Data:len bytes */ 1085 if (btc->hbuf_len + len + 3 >= BTC_H2C_MAXLEN) { 1086 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1087 "[BTC], %s():return by MACRO buf full(%d)\n", 1088 __func__, btc->hbuf_len + len + 3); 1089 btc->fwinfo.cnt_h2c_fail++; 1090 return 0; 1091 } 1092 1093 btc->hbuf[btc->hbuf_len] = h2c_func; 1094 btc->hbuf[btc->hbuf_len + 1] = len & GENMASK(7, 0); 1095 btc->hbuf[btc->hbuf_len + 2] = (len & GENMASK(15, 8)) >> 8; 1096 1097 memcpy(&btc->hbuf[btc->hbuf_len + 3], buf, len); 1098 btc->hbuf_len = btc->hbuf_len + len + 3; 1099 btc->hbuf_cnt++; 1100 1101 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1102 "[BTC], %s():Buffer H2C-MACRO cnt=%d/bt%d-func=%s/len=%d\n", 1103 __func__, btc->hbuf_cnt, bid, 1104 id_to_h2c(h2c_func_mask), len); 1105 } 1106 1107 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, buf, len, 1108 false, true); 1109 if (ret) 1110 pfwinfo->cnt_h2c_fail++; 1111 else 1112 pfwinfo->cnt_h2c++; 1113 1114 return ret; 1115 } 1116 1117 #define BTC_DEFAULT_SIR_THRES 51 /* dB, BT Pin - This = TDD/FDD swtch thres */ 1118 #define BTC_FDDR_TP_SETUP_TIME 1 /* in second */ 1119 #define BTC_FDDR_TP_HOLD_TIME 3 /* in second */ 1120 #define BTC_FDDR_RX_LOW_RATE_THRES 4 /* low rate for TDD swotch */ 1121 1122 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) 1123 { 1124 struct rtw89_btc *btc = &rtwdev->btc; 1125 struct rtw89_btc_cx *cx = &btc->cx; 1126 const struct rtw89_btc_ver *ver = btc->ver; 1127 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 1128 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 1129 u8 i; 1130 1131 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 1132 1133 if (type & BTC_RESET_CX) { 1134 memset(cx, 0, sizeof(*cx)); 1135 cx->bt_ext.max_tx_pwr = RTW89_BTC_BT_DEF_LE_TX_PWR; 1136 cx->bt_ext.ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1137 } 1138 1139 if (type & BTC_RESET_BTINFO) {/* only for BT enable */ 1140 memset(bt0, 0, sizeof(*bt0)); 1141 bt0->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1142 bt0->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1143 bt0->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1144 bt0->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1145 bt0->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1146 } else if (type & BTC_RESET_BTINFO2) { 1147 memset(bt1, 0, sizeof(*bt1)); 1148 bt1->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1149 bt1->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1150 bt1->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1151 bt1->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1152 bt1->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1153 } 1154 1155 if (type & BTC_RESET_CTRL) { 1156 memset(&btc->ctrl, 0, sizeof(btc->ctrl)); 1157 btc->ctrl.trace_step = FCXDEF_STEP; 1158 } 1159 1160 /* Init Coex variables that are not zero */ 1161 if (type & BTC_RESET_DM) { 1162 memset(&btc->dm, 0, sizeof(btc->dm)); 1163 1164 /* set the slot_now table to original */ 1165 btc->dm.tdma_now = t_def[CXTD_OFF]; 1166 btc->dm.tdma = t_def[CXTD_OFF]; 1167 if (ver->fcxslots >= 2) { 1168 for (i = 0; i < ARRAY_SIZE(s_def); i++) { 1169 btc->dm.slot.v7[i].dur = s_def[i].dur; 1170 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype; 1171 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl; 1172 } 1173 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7, 1174 sizeof(btc->dm.slot_now.v7)); 1175 } else { 1176 memcpy(&btc->dm.slot_now.v1, s_def, 1177 sizeof(btc->dm.slot_now.v1)); 1178 memcpy(&btc->dm.slot.v1, s_def, 1179 sizeof(btc->dm.slot.v1)); 1180 } 1181 1182 btc->policy_len = 0; 1183 btc->bt_req_len[RTW89_PHY_0] = 0; 1184 btc->bt_req_len[RTW89_PHY_1] = 0; 1185 btc->hubmsg_cnt = 0; 1186 1187 btc->dm.coex_info_map = BTC_COEX_INFO_ALL; 1188 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF; 1189 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF; 1190 btc->dm.bt_slot_flood = BTC_B1_MAX; 1191 btc->dm.sir_thres = BTC_DEFAULT_SIR_THRES; 1192 btc->dm.fddr_info.tp_setup_time = BTC_FDDR_TP_SETUP_TIME; 1193 btc->dm.fddr_info.tp_hold_time = BTC_FDDR_TP_HOLD_TIME; 1194 btc->dm.fddr_info.wl_rx_rate_thres = BTC_FDDR_RX_LOW_RATE_THRES; 1195 btc->dm.fddt_info.type = BTC_FDDT_TYPE_AUTO; 1196 1197 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND; 1198 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1199 } 1200 1201 if (type & BTC_RESET_MDINFO) { 1202 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); 1203 btc->mdinfo.ant.isolation = RTW89_BTC_DEFAULT_ANISO; 1204 } 1205 } 1206 1207 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target) 1208 { 1209 const struct rtw89_chip_info *chip = rtwdev->chip; 1210 u8 i; 1211 1212 for (i = 0; i < mreg_num; i++) 1213 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type && 1214 le32_to_cpu(chip->mon_reg[i].offset) == target) { 1215 return i; 1216 } 1217 return BTC_REG_NOTFOUND; 1218 } 1219 1220 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val) 1221 { 1222 struct rtw89_btc *btc = &rtwdev->btc; 1223 const struct rtw89_btc_ver *ver = btc->ver; 1224 struct rtw89_btc_module *md = &btc->mdinfo; 1225 union rtw89_btc_fbtc_mreg_val *pmreg; 1226 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1; 1227 u32 reg_val; 1228 u8 idx; 1229 1230 if (btc->btg_pos == RF_PATH_A) 1231 pre_agc_addr = R_BTC_BB_PRE_AGC_S0; 1232 1233 switch (type) { 1234 case BTC_CSTATUS_TXDIV_POS: 1235 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL) 1236 *val = BTC_ANT_DIV_MAIN; 1237 break; 1238 case BTC_CSTATUS_RXDIV_POS: 1239 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL) 1240 *val = BTC_ANT_DIV_MAIN; 1241 break; 1242 case BTC_CSTATUS_BB_GNT_MUX: 1243 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX); 1244 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1245 break; 1246 case BTC_CSTATUS_BB_GNT_MUX_MON: 1247 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1248 return; 1249 1250 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1251 if (ver->fcxmreg == 1) { 1252 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1253 REG_BB, R_BTC_BB_BTG_RX); 1254 if (idx == BTC_REG_NOTFOUND) { 1255 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1256 } else { 1257 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]); 1258 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1259 } 1260 } else if (ver->fcxmreg == 2) { 1261 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1262 REG_BB, R_BTC_BB_BTG_RX); 1263 if (idx == BTC_REG_NOTFOUND) { 1264 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1265 } else { 1266 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]); 1267 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1268 } 1269 } 1270 break; 1271 case BTC_CSTATUS_BB_PRE_AGC: 1272 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr); 1273 reg_val &= B_BTC_BB_PRE_AGC_MASK; 1274 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1275 break; 1276 case BTC_CSTATUS_BB_PRE_AGC_MON: 1277 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1278 return; 1279 1280 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1281 if (ver->fcxmreg == 1) { 1282 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1283 REG_BB, pre_agc_addr); 1284 if (idx == BTC_REG_NOTFOUND) { 1285 *val = BTC_PREAGC_NOTFOUND; 1286 } else { 1287 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) & 1288 B_BTC_BB_PRE_AGC_MASK; 1289 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1290 } 1291 } else if (ver->fcxmreg == 2) { 1292 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1293 REG_BB, pre_agc_addr); 1294 if (idx == BTC_REG_NOTFOUND) { 1295 *val = BTC_PREAGC_NOTFOUND; 1296 } else { 1297 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) & 1298 B_BTC_BB_PRE_AGC_MASK; 1299 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1300 } 1301 } 1302 break; 1303 default: 1304 break; 1305 } 1306 } 1307 1308 #define BTC_RPT_HDR_SIZE 3 1309 #define BTC_CHK_WLSLOT_DRIFT_MAX 15 1310 #define BTC_CHK_BTSLOT_DRIFT_MAX 15 1311 #define BTC_CHK_HANG_MAX 3 1312 1313 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt) 1314 { 1315 struct rtw89_btc *btc = &rtwdev->btc; 1316 struct rtw89_btc_cx *cx = &btc->cx; 1317 struct rtw89_btc_bt_info *bt = &cx->bt0; 1318 struct rtw89_btc_wl_info *wl = &cx->wl; 1319 struct rtw89_btc_dm *dm = &btc->dm; 1320 1321 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1322 "[BTC], %s(): type:%d cnt:%d\n", 1323 __func__, type, cnt); 1324 1325 switch (type) { 1326 case BTC_DCNT_WL_FW_VER_MATCH: 1327 if ((wl->ver_info.fw_coex & 0xffff0000) != 1328 rtwdev->chip->wlcx_desired) { 1329 wl->fw_ver_mismatch = true; 1330 dm->error.map.wl_ver_mismatch = true; 1331 } else { 1332 wl->fw_ver_mismatch = false; 1333 dm->error.map.wl_ver_mismatch = false; 1334 } 1335 break; 1336 case BTC_DCNT_RPT_HANG: 1337 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map) 1338 dm->cnt_dm[BTC_DCNT_RPT_HANG]++; 1339 else 1340 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0; 1341 1342 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX) 1343 dm->error.map.wl_fw_hang = true; 1344 else 1345 dm->error.map.wl_fw_hang = false; 1346 1347 dm->cnt_dm[BTC_DCNT_RPT] = cnt; 1348 break; 1349 case BTC_DCNT_CYCLE_HANG: 1350 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt && 1351 (dm->tdma_now.type != CXTDMA_OFF || 1352 dm->tdma_now.ext_ctrl == CXECTL_EXT)) 1353 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++; 1354 else 1355 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0; 1356 1357 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX) 1358 dm->error.map.cycle_hang = true; 1359 else 1360 dm->error.map.cycle_hang = false; 1361 1362 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt; 1363 break; 1364 case BTC_DCNT_W1_HANG: 1365 if (dm->cnt_dm[BTC_DCNT_W1] == cnt && 1366 dm->tdma_now.type != CXTDMA_OFF) 1367 dm->cnt_dm[BTC_DCNT_W1_HANG]++; 1368 else 1369 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0; 1370 1371 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX) 1372 dm->error.map.w1_hang = true; 1373 else 1374 dm->error.map.w1_hang = false; 1375 1376 dm->cnt_dm[BTC_DCNT_W1] = cnt; 1377 break; 1378 case BTC_DCNT_B1_HANG: 1379 if (dm->cnt_dm[BTC_DCNT_B1] == cnt && 1380 dm->tdma_now.type != CXTDMA_OFF) 1381 dm->cnt_dm[BTC_DCNT_B1_HANG]++; 1382 else 1383 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0; 1384 1385 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX) 1386 dm->error.map.b1_hang = true; 1387 else 1388 dm->error.map.b1_hang = false; 1389 1390 dm->cnt_dm[BTC_DCNT_B1] = cnt; 1391 break; 1392 case BTC_DCNT_E2G_HANG: 1393 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt && 1394 dm->tdma_now.ext_ctrl == CXECTL_EXT) 1395 dm->cnt_dm[BTC_DCNT_E2G_HANG]++; 1396 else 1397 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0; 1398 1399 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX) 1400 dm->error.map.wl_e2g_hang = true; 1401 else 1402 dm->error.map.wl_e2g_hang = false; 1403 1404 dm->cnt_dm[BTC_DCNT_E2G] = cnt; 1405 break; 1406 case BTC_DCNT_TDMA_NONSYNC: 1407 if (cnt != 0) /* if tdma not sync between drv/fw */ 1408 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++; 1409 else 1410 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0; 1411 1412 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX) 1413 dm->error.map.tdma_no_sync = true; 1414 else 1415 dm->error.map.tdma_no_sync = false; 1416 break; 1417 case BTC_DCNT_SLOT_NONSYNC: 1418 if (cnt != 0) /* if slot not sync between drv/fw */ 1419 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++; 1420 else 1421 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0; 1422 1423 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX) 1424 dm->error.map.slot_no_sync = true; 1425 else 1426 dm->error.map.slot_no_sync = false; 1427 break; 1428 case BTC_DCNT_BTTX_HANG: 1429 cnt = bt->bcnt[BTC_BCNT_LOPRI_TX]; 1430 1431 if (cnt == 0 && bt->link_info.slave_role) 1432 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++; 1433 else 1434 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0; 1435 1436 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX) 1437 dm->error.map.bt_tx_hang = true; 1438 else 1439 dm->error.map.bt_tx_hang = false; 1440 break; 1441 case BTC_DCNT_BTCNT_HANG: 1442 cnt = bt->bcnt[BTC_BCNT_HIPRI_RX] + 1443 bt->bcnt[BTC_BCNT_HIPRI_TX] + 1444 bt->bcnt[BTC_BCNT_LOPRI_RX] + 1445 bt->bcnt[BTC_BCNT_LOPRI_TX]; 1446 1447 if (cnt == 0) 1448 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++; 1449 else 1450 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 1451 break; 1452 case BTC_DCNT_WL_SLOT_DRIFT: 1453 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX) 1454 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++; 1455 else 1456 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0; 1457 1458 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1459 dm->error.map.wl_slot_drift = true; 1460 else 1461 dm->error.map.wl_slot_drift = false; 1462 break; 1463 case BTC_DCNT_BT_SLOT_DRIFT: 1464 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX) 1465 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++; 1466 else 1467 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0; 1468 1469 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1470 dm->error.map.bt_slot_drift = true; 1471 else 1472 dm->error.map.bt_slot_drift = false; 1473 1474 break; 1475 case BTC_DCNT_WL_STA_NTFY: 1476 cnt = dm->cnt_notify[BTC_NCNT_WL_STA] - 1477 dm->cnt_notify[BTC_NCNT_WL_STA_LAST]; 1478 1479 dm->cnt_notify[BTC_NCNT_WL_STA_LAST] = 1480 dm->cnt_notify[BTC_NCNT_WL_STA]; 1481 1482 if (cnt == 0 && 1483 (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK || 1484 dm->fdd_bind.wl_link_mode != BTC_WLINK_NOLINK)) 1485 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY]++; 1486 else 1487 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] = 0; 1488 1489 if (dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] >= BTC_CHK_HANG_MAX) 1490 dm->error.map.wl_no_sta_ntfy = true; 1491 else 1492 dm->error.map.wl_no_sta_ntfy = false; 1493 break; 1494 case BTC_DCNT_W2B_SCBD_NOSYNC: 1495 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) 1496 return; /* return if no-support W2B scbd readback */ 1497 1498 if (wl->scbd_rb[BTC_BT_1ST] != wl->scbd[BTC_BT_1ST] || 1499 wl->scbd_rb[BTC_BT_2ND] != wl->scbd[BTC_BT_2ND]) 1500 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC]++; 1501 else 1502 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] = 0; 1503 1504 if (dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] >= BTC_CHK_HANG_MAX) 1505 dm->error.map.w2b_scbd_no_sync = true; 1506 else 1507 dm->error.map.w2b_scbd_no_sync = false; 1508 break; 1509 } 1510 } 1511 1512 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) 1513 { 1514 struct rtw89_btc *btc = &rtwdev->btc; 1515 const struct rtw89_btc_ver *ver = btc->ver; 1516 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 1517 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 1518 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc; 1519 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo; 1520 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL; 1521 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL; 1522 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL; 1523 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL; 1524 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1; 1525 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2; 1526 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7; 1527 bool scan_update = true; 1528 int i; 1529 1530 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1531 "[BTC], %s(): rpt_type:%d\n", 1532 __func__, rpt_type); 1533 1534 switch (rpt_type) { 1535 case BTC_RPT_TYPE_BT_VER: 1536 if (ver->fcxbtver == 8) { 1537 pver->v8 = *(struct rtw89_btc_fbtc_btver_v8 *)pfinfo; 1538 bt = pver->v8.bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1539 bt->ver_info.fw = le32_to_cpu(pver->v8.fw_ver); 1540 bt->ver_info.fw_coex = le32_get_bits(pver->v8.coex_ver, 1541 GENMASK(7, 0)); 1542 bt->feature = le32_to_cpu(pver->v8.feature); 1543 } else if (ver->fcxbtver == 7) { 1544 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo; 1545 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver); 1546 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver, 1547 GENMASK(7, 0)); 1548 bt->feature = le32_to_cpu(pver->v7.feature); 1549 } else { 1550 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo; 1551 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver); 1552 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver, 1553 GENMASK(7, 0)); 1554 bt->feature = le32_to_cpu(pver->v1.feature); 1555 } 1556 break; 1557 case BTC_RPT_TYPE_BT_SCAN: 1558 if (ver->fcxbtscan == 1) { 1559 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo; 1560 for (i = 0; i < BTC_SCAN_MAX1; i++) { 1561 bt->scan_info_v1[i] = pscan_v1->scan[i]; 1562 if (bt->scan_info_v1[i].win == 0 && 1563 bt->scan_info_v1[i].intvl == 0) 1564 scan_update = false; 1565 } 1566 } else if (ver->fcxbtscan == 2) { 1567 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo; 1568 for (i = 0; i < CXSCAN_MAX; i++) { 1569 bt->scan_info_v2[i] = pscan_v2->para[i]; 1570 if ((pscan_v2->type & BIT(i)) && 1571 pscan_v2->para[i].win == 0 && 1572 pscan_v2->para[i].intvl == 0) 1573 scan_update = false; 1574 } 1575 } else if (ver->fcxbtscan == 7) { 1576 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo; 1577 for (i = 0; i < CXSCAN_MAX; i++) { 1578 bt->scan_info_v2[i] = pscan_v7->para[i]; 1579 if ((pscan_v7->type & BIT(i)) && 1580 pscan_v7->para[i].win == 0 && 1581 pscan_v7->para[i].intvl == 0) 1582 scan_update = false; 1583 } 1584 } else if (ver->fcxbtscan == 8) { 1585 struct rtw89_btc_fbtc_btscan_v8 *pscan_v8 = 1586 (struct rtw89_btc_fbtc_btscan_v8 *)pfinfo; 1587 struct rtw89_btc_bt_info *tbt = 1588 pscan_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1589 1590 for (i = 0; i < CXSCAN_MAX; i++) { 1591 tbt->scan_info_v2[i] = pscan_v8->para[i]; 1592 if ((pscan_v8->type & BIT(i)) && 1593 pscan_v8->para[i].win == 0 && 1594 pscan_v8->para[i].intvl == 0) 1595 scan_update = false; 1596 } 1597 } 1598 if (scan_update) 1599 bt->scan_info_update = 1; 1600 break; 1601 case BTC_RPT_TYPE_BT_AFH: 1602 if (ver->fcxbtafh == 2) { 1603 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo; 1604 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1605 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4); 1606 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4); 1607 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2); 1608 } 1609 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) { 1610 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4); 1611 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1); 1612 } 1613 } else if (ver->fcxbtafh == 7) { 1614 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo; 1615 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1616 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4); 1617 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4); 1618 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2); 1619 } 1620 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) { 1621 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4); 1622 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1); 1623 } 1624 } else if (ver->fcxbtafh == 8) { 1625 struct rtw89_btc_fbtc_btafh_v8 *pafh_v8 = 1626 (struct rtw89_btc_fbtc_btafh_v8 *)pfinfo; 1627 struct rtw89_btc_bt_info *tbt = 1628 pafh_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1629 struct rtw89_btc_bt_link_info *tbt_linfo = &tbt->link_info; 1630 1631 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1632 memcpy(&tbt_linfo->afh_map[0], pafh_v8->afh_l, 4); 1633 memcpy(&tbt_linfo->afh_map[4], pafh_v8->afh_m, 4); 1634 memcpy(&tbt_linfo->afh_map[8], pafh_v8->afh_h, 2); 1635 } 1636 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LE) { 1637 memcpy(&tbt_linfo->afh_map_le[0], pafh_v8->afh_le_a, 4); 1638 memcpy(&tbt_linfo->afh_map_le[4], pafh_v8->afh_le_b, 1); 1639 } 1640 } else if (ver->fcxbtafh == 1) { 1641 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; 1642 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); 1643 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4); 1644 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2); 1645 } 1646 break; 1647 case BTC_RPT_TYPE_BT_DEVICE: 1648 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo; 1649 a2dp->device_name = le32_to_cpu(pdev->dev_name); 1650 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id); 1651 a2dp->flush_time = le32_to_cpu(pdev->flush_time); 1652 break; 1653 default: 1654 break; 1655 } 1656 } 1657 1658 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index) 1659 { 1660 struct rtw89_btc *btc = &rtwdev->btc; 1661 const struct rtw89_btc_ver *ver = btc->ver; 1662 1663 if (ver->fwevntrptl == 1) 1664 return; 1665 1666 if (*index <= __BTC_RPT_TYPE_V0_SAME) 1667 return; 1668 else if (*index <= __BTC_RPT_TYPE_V0_MAX) 1669 (*index)++; 1670 else 1671 *index = BTC_RPT_TYPE_MAX; 1672 } 1673 1674 #define BTC_LEAK_AP_TH 10 1675 #define BTC_CYSTA_CHK_PERIOD 100 1676 1677 struct rtw89_btc_prpt { 1678 u8 type; 1679 __le16 len; 1680 u8 content[]; 1681 } __packed; 1682 1683 static u32 _chk_btc_report(struct rtw89_dev *rtwdev, 1684 struct rtw89_btc_btf_fwinfo *pfwinfo, 1685 u8 *prptbuf, u32 index) 1686 { 1687 struct rtw89_btc *btc = &rtwdev->btc; 1688 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 1689 const struct rtw89_btc_ver *ver = btc->ver; 1690 struct rtw89_btc_dm *dm = &btc->dm; 1691 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 1692 struct rtw89_btc_cx *cx = &btc->cx; 1693 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1694 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 1695 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL; 1696 union rtw89_btc_fbtc_cysta_info *pcysta = NULL; 1697 struct rtw89_btc_prpt *btc_prpt = NULL; 1698 void *rpt_content = NULL, *pfinfo = NULL; 1699 u8 rpt_type = 0; 1700 u16 wl_slot_set = 0, wl_slot_real = 0, val16; 1701 u32 trace_step = 0, rpt_len = 0, diff_t = 0; 1702 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr; 1703 u8 i, j, val = 0, val1, val2; 1704 u32 *bt_cnt, start_idx; 1705 1706 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1707 "[BTC], %s(): index:%d\n", 1708 __func__, index); 1709 1710 if (!prptbuf) { 1711 pfwinfo->err[BTFRE_INVALID_INPUT]++; 1712 return 0; 1713 } 1714 1715 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index]; 1716 rpt_type = btc_prpt->type; 1717 rpt_len = le16_to_cpu(btc_prpt->len); 1718 rpt_content = btc_prpt->content; 1719 1720 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1721 "[BTC], %s(): rpt_type:%d\n", 1722 __func__, rpt_type); 1723 1724 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type); 1725 1726 switch (rpt_type) { 1727 case BTC_RPT_TYPE_CTRL: 1728 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 1729 prpt = &pfwinfo->rpt_ctrl.finfo; 1730 if (ver->fcxbtcrpt == 1) { 1731 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; 1732 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); 1733 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver; 1734 } else if (ver->fcxbtcrpt == 4) { 1735 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; 1736 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); 1737 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver; 1738 } else if (ver->fcxbtcrpt == 5) { 1739 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; 1740 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); 1741 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver; 1742 } else if (ver->fcxbtcrpt == 105) { 1743 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; 1744 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); 1745 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver; 1746 pcinfo->req_fver = 5; 1747 break; 1748 } else if (ver->fcxbtcrpt == 8) { 1749 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8; 1750 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8); 1751 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver; 1752 } else if (ver->fcxbtcrpt == 7) { 1753 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7; 1754 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7); 1755 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver; 1756 } else if (ver->fcxbtcrpt == 9) { 1757 pfinfo = &pfwinfo->rpt_ctrl.finfo.v9; 1758 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v9); 1759 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v9.fver; 1760 } else if (ver->fcxbtcrpt == 11) { 1761 pfinfo = &pfwinfo->rpt_ctrl.finfo.v11; 1762 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v11); 1763 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v11.fver; 1764 } else { 1765 goto err; 1766 } 1767 pcinfo->req_fver = ver->fcxbtcrpt; 1768 break; 1769 case BTC_RPT_TYPE_TDMA: 1770 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 1771 if (ver->fcxtdma == 1) { 1772 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 1773 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); 1774 fwsubver->fcxtdma = 0; 1775 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || 1776 ver->fcxtdma == 7 || ver->fcxtdma == 8) { 1777 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; 1778 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); 1779 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver; 1780 } else { 1781 goto err; 1782 } 1783 pcinfo->req_fver = ver->fcxtdma; 1784 break; 1785 case BTC_RPT_TYPE_SLOT: 1786 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 1787 if (ver->fcxslots == 1) { 1788 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1; 1789 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1); 1790 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver; 1791 } else if (ver->fcxslots == 2) { 1792 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v2; 1793 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v2); 1794 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v2.fver; 1795 } else if (ver->fcxslots == 7) { 1796 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7; 1797 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7); 1798 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver; 1799 } else { 1800 goto err; 1801 } 1802 pcinfo->req_fver = ver->fcxslots; 1803 break; 1804 case BTC_RPT_TYPE_CYSTA: 1805 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 1806 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 1807 if (ver->fcxcysta == 2) { 1808 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 1809 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 1810 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); 1811 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver; 1812 } else if (ver->fcxcysta == 3) { 1813 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 1814 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 1815 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); 1816 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver; 1817 } else if (ver->fcxcysta == 4) { 1818 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 1819 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 1820 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); 1821 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver; 1822 } else if (ver->fcxcysta == 5) { 1823 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 1824 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 1825 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); 1826 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver; 1827 } else if (ver->fcxcysta == 105) { 1828 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v105; 1829 pcysta->v105 = pfwinfo->rpt_fbtc_cysta.finfo.v105; 1830 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v105); 1831 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v105.fver; 1832 } else if (ver->fcxcysta == 7) { 1833 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 1834 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 1835 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7); 1836 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver; 1837 } else { 1838 goto err; 1839 } 1840 pcinfo->req_fver = ver->fcxcysta; 1841 break; 1842 case BTC_RPT_TYPE_STEP: 1843 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 1844 if (ver->fcxctrl != 7) 1845 trace_step = btc->ctrl.trace_step; 1846 1847 if (ver->fcxstep == 2) { 1848 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2; 1849 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * 1850 trace_step + 1851 offsetof(struct rtw89_btc_fbtc_steps_v2, step); 1852 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver; 1853 } else if (ver->fcxstep == 3) { 1854 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; 1855 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * 1856 trace_step + 1857 offsetof(struct rtw89_btc_fbtc_steps_v3, step); 1858 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver; 1859 } else { 1860 goto err; 1861 } 1862 pcinfo->req_fver = ver->fcxstep; 1863 break; 1864 case BTC_RPT_TYPE_NULLSTA: 1865 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 1866 if (ver->fcxnullsta == 1) { 1867 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; 1868 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); 1869 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver; 1870 } else if (ver->fcxnullsta == 2) { 1871 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; 1872 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); 1873 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver; 1874 } else if (ver->fcxnullsta == 7) { 1875 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7; 1876 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7); 1877 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver; 1878 } else { 1879 goto err; 1880 } 1881 pcinfo->req_fver = ver->fcxnullsta; 1882 break; 1883 case BTC_RPT_TYPE_MREG: 1884 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 1885 if (ver->fcxmreg == 1) { 1886 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 1887 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); 1888 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver; 1889 } else if (ver->fcxmreg == 2) { 1890 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 1891 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); 1892 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver; 1893 } else if (ver->fcxmreg == 7) { 1894 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 1895 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7); 1896 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver; 1897 } else { 1898 goto err; 1899 } 1900 pcinfo->req_fver = ver->fcxmreg; 1901 break; 1902 case BTC_RPT_TYPE_GPIO_DBG: 1903 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 1904 if (ver->fcxgpiodbg == 7) { 1905 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7; 1906 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7); 1907 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver; 1908 } else { 1909 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1; 1910 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1); 1911 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver; 1912 } 1913 pcinfo->req_fver = ver->fcxgpiodbg; 1914 break; 1915 case BTC_RPT_TYPE_BT_VER: 1916 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo; 1917 if (ver->fcxbtver == 1) { 1918 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1; 1919 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1); 1920 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver; 1921 } else if (ver->fcxbtver == 7) { 1922 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7; 1923 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7); 1924 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver; 1925 } else if (ver->fcxbtver == 8) { 1926 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v8; 1927 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v8); 1928 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v8.fver; 1929 } else { 1930 goto err; 1931 } 1932 pcinfo->req_fver = ver->fcxbtver; 1933 break; 1934 case BTC_RPT_TYPE_BT_SCAN: 1935 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo; 1936 if (ver->fcxbtscan == 1) { 1937 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; 1938 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); 1939 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver; 1940 } else if (ver->fcxbtscan == 2) { 1941 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; 1942 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); 1943 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver; 1944 } else if (ver->fcxbtscan == 7) { 1945 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7; 1946 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7); 1947 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver; 1948 } else if (ver->fcxbtscan == 8) { 1949 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v8; 1950 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v8); 1951 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v8.fver; 1952 } else { 1953 goto err; 1954 } 1955 pcinfo->req_fver = ver->fcxbtscan; 1956 break; 1957 case BTC_RPT_TYPE_BT_AFH: 1958 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo; 1959 if (ver->fcxbtafh == 1) { 1960 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; 1961 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); 1962 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver; 1963 } else if (ver->fcxbtafh == 2) { 1964 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; 1965 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); 1966 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver; 1967 } else if (ver->fcxbtafh == 7) { 1968 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7; 1969 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7); 1970 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver; 1971 } else if (ver->fcxbtafh == 8) { 1972 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v8; 1973 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v8); 1974 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v8.fver; 1975 } else { 1976 goto err; 1977 } 1978 pcinfo->req_fver = ver->fcxbtafh; 1979 break; 1980 case BTC_RPT_TYPE_BT_DEVICE: 1981 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; 1982 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; 1983 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); 1984 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver; 1985 pcinfo->req_fver = ver->fcxbtdevinfo; 1986 break; 1987 default: 1988 pfwinfo->err[BTFRE_UNDEF_TYPE]++; 1989 return 0; 1990 } 1991 1992 pcinfo->rx_len = rpt_len; 1993 pcinfo->rx_cnt++; 1994 1995 if (rpt_len != pcinfo->req_len) { 1996 if (rpt_type < BTC_RPT_TYPE_MAX) 1997 pfwinfo->len_mismch |= (0x1 << rpt_type); 1998 else 1999 pfwinfo->len_mismch |= BIT(31); 2000 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2001 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n", 2002 __func__, rpt_type, rpt_len, pcinfo->req_len); 2003 2004 pcinfo->valid = 0; 2005 return 0; 2006 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) { 2007 pfwinfo->err[BTFRE_EXCEPTION]++; 2008 pcinfo->valid = 0; 2009 return 0; 2010 } 2011 2012 memcpy(pfinfo, rpt_content, pcinfo->req_len); 2013 pcinfo->valid = 1; 2014 2015 switch (rpt_type) { 2016 case BTC_RPT_TYPE_CTRL: 2017 if (ver->fcxbtcrpt == 1) { 2018 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1; 2019 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable; 2020 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver; 2021 wl->ver_info.fw = prpt->v1.wl_fw_ver; 2022 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload; 2023 2024 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2025 pfwinfo->event[BTF_EVNT_RPT]); 2026 2027 /* To avoid I/O if WL LPS or power-off */ 2028 if (wl->status.map.lps != BTC_LPS_RF_OFF && 2029 !wl->status.map.rf_off) { 2030 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev); 2031 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2032 2033 bt->bcnt[BTC_BCNT_POLLUTED] = 2034 rtw89_mac_get_plt_cnt(rtwdev, 2035 RTW89_MAC_0); 2036 } 2037 } else if (ver->fcxbtcrpt == 4) { 2038 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4; 2039 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en); 2040 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver); 2041 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver); 2042 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload); 2043 2044 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2045 memcpy(&dm->gnt_val[i], &prpt->v4.gnt_val[i], 2046 sizeof(dm->gnt_val[i])); 2047 2048 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2049 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]); 2050 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2051 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]); 2052 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2053 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]); 2054 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2055 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]); 2056 bt->bcnt[BTC_BCNT_POLLUTED] = 2057 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]); 2058 2059 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2060 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2061 pfwinfo->event[BTF_EVNT_RPT]); 2062 2063 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 2064 bt->rfk_info.map.timeout = 1; 2065 else 2066 bt->rfk_info.map.timeout = 0; 2067 2068 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2069 } else if (ver->fcxbtcrpt == 5) { 2070 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5; 2071 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en); 2072 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver); 2073 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver); 2074 dm->wl_fw_cx_offload = 0; 2075 2076 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2077 memcpy(&dm->gnt_val[i], &prpt->v5.gnt_val[i], 2078 sizeof(dm->gnt_val[i])); 2079 2080 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2081 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]); 2082 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2083 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]); 2084 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2085 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]); 2086 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2087 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]); 2088 bt->bcnt[BTC_BCNT_POLLUTED] = 2089 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]); 2090 2091 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2092 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2093 pfwinfo->event[BTF_EVNT_RPT]); 2094 2095 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2096 } else if (ver->fcxbtcrpt == 105) { 2097 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105; 2098 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en); 2099 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver); 2100 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver); 2101 dm->wl_fw_cx_offload = 0; 2102 2103 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2104 memcpy(&dm->gnt_val[i], &prpt->v105.gnt_val[i], 2105 sizeof(dm->gnt_val[i])); 2106 2107 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2108 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]); 2109 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2110 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]); 2111 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2112 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]); 2113 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2114 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]); 2115 bt->bcnt[BTC_BCNT_POLLUTED] = 2116 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2117 2118 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2119 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2120 pfwinfo->event[BTF_EVNT_RPT]); 2121 2122 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2123 } else if (ver->fcxbtcrpt == 7) { 2124 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7; 2125 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en); 2126 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver); 2127 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver); 2128 2129 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2130 memcpy(&dm->gnt_val[i], &prpt->v7.gnt_val[i], 2131 sizeof(dm->gnt_val[i])); 2132 2133 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2134 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]); 2135 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2136 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]); 2137 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2138 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]); 2139 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2140 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]); 2141 2142 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2143 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2144 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2145 2146 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2147 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2148 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2149 2150 val1 = pfwinfo->event[BTF_EVNT_RPT]; 2151 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2152 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2153 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2154 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2155 } else if (ver->fcxbtcrpt == 8) { 2156 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8; 2157 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en); 2158 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver); 2159 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver); 2160 2161 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2162 memcpy(&dm->gnt_val[i], &prpt->v8.gnt_val[i], 2163 sizeof(dm->gnt_val[i])); 2164 2165 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2166 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]); 2167 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2168 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]); 2169 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2170 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]); 2171 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2172 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]); 2173 2174 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2175 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2176 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2177 2178 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2179 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2180 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2181 2182 val1 = pfwinfo->event[BTF_EVNT_RPT]; 2183 if (((prpt->v8.rpt_len_max_h << 8) + 2184 prpt->v8.rpt_len_max_l) != ver->info_buf) 2185 dm->error.map.h2c_c2h_buffer_mismatch = true; 2186 else 2187 dm->error.map.h2c_c2h_buffer_mismatch = false; 2188 2189 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2190 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2191 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2192 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2193 } else if (ver->fcxbtcrpt == 9) { 2194 prpt->v9 = pfwinfo->rpt_ctrl.finfo.v9; 2195 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v9.rpt_info.en); 2196 wl->ver_info.fw_coex = le32_to_cpu(prpt->v9.rpt_info.cx_ver); 2197 wl->ver_info.fw = le32_to_cpu(prpt->v9.rpt_info.fw_ver); 2198 2199 memcpy(wl->ver_info.build_time, 2200 prpt->v9.build_time, 2201 sizeof(wl->ver_info.build_time)); 2202 memcpy(wl->ver_info.build_date, 2203 prpt->v9.build_date, 2204 sizeof(wl->ver_info.build_date)); 2205 2206 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2207 memcpy(&dm->gnt_val[i], &prpt->v9.gnt_val[i], 2208 sizeof(dm->gnt_val[i])); 2209 2210 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2211 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_TX_V105]); 2212 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2213 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_RX_V105]); 2214 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2215 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_TX_V105]); 2216 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2217 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_RX_V105]); 2218 2219 val1 = le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2220 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2221 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2222 2223 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2224 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2225 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2226 2227 dm->pta_owner = prpt->v9.pta_owner; 2228 2229 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2230 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2231 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2232 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2233 } else if (ver->fcxbtcrpt == 11) { 2234 prpt->v11 = pfwinfo->rpt_ctrl.finfo.v11; 2235 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v11.rpt_info.en); 2236 wl->ver_info.fw_coex = le32_to_cpu(prpt->v11.rpt_info.cx_ver); 2237 wl->ver_info.fw = le32_to_cpu(prpt->v11.rpt_info.fw_ver); 2238 2239 memcpy(wl->ver_info.build_time, 2240 prpt->v11.build_time, 2241 sizeof(wl->ver_info.build_time)); 2242 memcpy(wl->ver_info.build_date, 2243 prpt->v11.build_date, 2244 sizeof(wl->ver_info.build_date)); 2245 2246 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2247 memcpy(&dm->gnt_val[i], &prpt->v11.gnt_val[i][0], 2248 sizeof(dm->gnt_val[i])); 2249 2250 for (i = BTC_BT_1ST; i <= BTC_BT_EXT; i++) { 2251 if (i == BTC_BT_EXT) { 2252 if (cx->bt_ext.func_type == BTC_BTF_NONE) 2253 continue; 2254 bt_cnt = cx->bt_ext.bcnt; 2255 } else if (i == BTC_BT_2ND) { 2256 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 2257 continue; 2258 bt_cnt = cx->bt1.bcnt; 2259 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]); 2260 cx->bt1.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]); 2261 } else { 2262 bt_cnt = cx->bt0.bcnt; 2263 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]); 2264 cx->bt0.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]); 2265 } 2266 2267 start_idx = BTC_BCNT_HIPRI_TX; 2268 for (j = BTC_BCNT_HI_TX_V105; j <= BTC_BCNT_LO_RX_V105 ; j++) 2269 bt_cnt[start_idx++] = le16_to_cpu(prpt->v11.bt_cnt[i][j]); 2270 2271 /* check if polut counter increase */ 2272 val1 = le16_to_cpu(prpt->v11.bt_cnt[i][BTC_BCNT_POLLUTED_V105]); 2273 if (val1 > bt_cnt[BTC_BCNT_POLUT_NOW]) /* cnt increase*/ 2274 val2 = val1 - bt_cnt[BTC_BCNT_POLUT_NOW]; 2275 else 2276 val2 = val1; /* overflow */ 2277 2278 bt_cnt[BTC_BCNT_POLUT_DIFF] = val2; 2279 bt_cnt[BTC_BCNT_POLUT_NOW] = val1; 2280 2281 if (i <= BTC_BT_2ND) 2282 bt_cnt[BTC_BCNT_SCBDREAD]++; 2283 } 2284 dm->scbd_w2b_update = true; 2285 dm->scbd_b2w_update = true; 2286 2287 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2288 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2289 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2290 _chk_btc_err(rtwdev, BTC_DCNT_WL_STA_NTFY, 0); 2291 _chk_btc_err(rtwdev, BTC_DCNT_W2B_SCBD_NOSYNC, 0); 2292 } else { 2293 goto err; 2294 } 2295 break; 2296 case BTC_RPT_TYPE_TDMA: 2297 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2298 "[BTC], %s(): check %d %zu\n", __func__, 2299 BTC_DCNT_TDMA_NONSYNC, 2300 sizeof(dm->tdma_now)); 2301 if (ver->fcxtdma == 1) 2302 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 2303 memcmp(&dm->tdma_now, 2304 &pfwinfo->rpt_fbtc_tdma.finfo.v1, 2305 sizeof(dm->tdma_now))); 2306 else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || 2307 ver->fcxtdma == 7 || ver->fcxtdma == 8) 2308 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 2309 memcmp(&dm->tdma_now, 2310 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, 2311 sizeof(dm->tdma_now))); 2312 else 2313 goto err; 2314 break; 2315 case BTC_RPT_TYPE_SLOT: 2316 if (ver->fcxslots == 7) { 2317 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2318 "[BTC], %s(): check %d %zu\n", 2319 __func__, BTC_DCNT_SLOT_NONSYNC, 2320 sizeof(dm->slot_now.v7)); 2321 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2322 memcmp(dm->slot_now.v7, 2323 pfwinfo->rpt_fbtc_slots.finfo.v7.slot, 2324 sizeof(dm->slot_now.v7))); 2325 } else if (ver->fcxslots == 2) { 2326 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2327 "[BTC], %s(): check %d %zu\n", 2328 __func__, BTC_DCNT_SLOT_NONSYNC, 2329 sizeof(dm->slot_now.v7)); 2330 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2331 memcmp(dm->slot_now.v7, 2332 pfwinfo->rpt_fbtc_slots.finfo.v2.slot, 2333 sizeof(dm->slot_now.v7))); 2334 } else if (ver->fcxslots == 1) { 2335 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2336 "[BTC], %s(): check %d %zu\n", 2337 __func__, BTC_DCNT_SLOT_NONSYNC, 2338 sizeof(dm->slot_now.v1)); 2339 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2340 memcmp(dm->slot_now.v1, 2341 pfwinfo->rpt_fbtc_slots.finfo.v1.slot, 2342 sizeof(dm->slot_now.v1))); 2343 } 2344 break; 2345 case BTC_RPT_TYPE_CYSTA: 2346 if (ver->fcxcysta == 2) { 2347 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD) 2348 break; 2349 /* Check Leak-AP */ 2350 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 && 2351 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) { 2352 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) < 2353 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt)) 2354 dm->leak_ap = 1; 2355 } 2356 2357 /* Check diff time between WL slot and W1/E2G slot */ 2358 if (dm->tdma_now.type == CXTDMA_OFF && 2359 dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2360 if (ver->fcxslots == 1) 2361 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur); 2362 else if (ver->fcxslots == 7) 2363 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur); 2364 } else { 2365 if (ver->fcxslots == 1) 2366 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2367 else if (ver->fcxslots == 7) 2368 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2369 } 2370 2371 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) { 2372 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set; 2373 _chk_btc_err(rtwdev, 2374 BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2375 } 2376 2377 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2378 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1])); 2379 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2380 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1])); 2381 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2382 le16_to_cpu(pcysta->v2.cycles)); 2383 } else if (ver->fcxcysta == 3) { 2384 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD) 2385 break; 2386 2387 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]); 2388 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr); 2389 2390 /* Check Leak-AP */ 2391 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2392 dm->tdma_now.rxflctrl) { 2393 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2394 dm->leak_ap = 1; 2395 } 2396 2397 /* Check diff time between real WL slot and W1 slot */ 2398 if (dm->tdma_now.type == CXTDMA_OFF) { 2399 if (ver->fcxslots == 1) 2400 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2401 else if (ver->fcxslots == 7) 2402 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2403 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]); 2404 if (wl_slot_real > wl_slot_set) { 2405 diff_t = wl_slot_real - wl_slot_set; 2406 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2407 } 2408 } 2409 2410 /* Check diff time between real BT slot and EBT/E5G slot */ 2411 if (dm->tdma_now.type == CXTDMA_OFF && 2412 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2413 btc->bt_req_len[RTW89_PHY_0] != 0) { 2414 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]); 2415 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) { 2416 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real; 2417 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2418 } 2419 } 2420 2421 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2422 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1])); 2423 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2424 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1])); 2425 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2426 le16_to_cpu(pcysta->v3.cycles)); 2427 } else if (ver->fcxcysta == 4) { 2428 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD) 2429 break; 2430 2431 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]); 2432 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr); 2433 2434 /* Check Leak-AP */ 2435 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2436 dm->tdma_now.rxflctrl) { 2437 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2438 dm->leak_ap = 1; 2439 } 2440 2441 /* Check diff time between real WL slot and W1 slot */ 2442 if (dm->tdma_now.type == CXTDMA_OFF) { 2443 if (ver->fcxslots == 1) 2444 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2445 else if (ver->fcxslots == 7) 2446 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2447 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]); 2448 if (wl_slot_real > wl_slot_set) { 2449 diff_t = wl_slot_real - wl_slot_set; 2450 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2451 } 2452 } 2453 2454 /* Check diff time between real BT slot and EBT/E5G slot */ 2455 if (dm->tdma_now.type == CXTDMA_OFF && 2456 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2457 btc->bt_req_len[RTW89_PHY_0] != 0) { 2458 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]); 2459 2460 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) { 2461 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real; 2462 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2463 } 2464 } 2465 2466 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2467 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1])); 2468 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2469 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1])); 2470 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2471 le16_to_cpu(pcysta->v4.cycles)); 2472 } else if (ver->fcxcysta == 5) { 2473 if (dm->fddt_train == BTC_FDDT_ENABLE) 2474 break; 2475 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]); 2476 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr); 2477 2478 /* Check Leak-AP */ 2479 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2480 dm->tdma_now.rxflctrl) { 2481 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 2482 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2483 dm->leak_ap = 1; 2484 } 2485 2486 /* Check diff time between real WL slot and W1 slot */ 2487 if (dm->tdma_now.type == CXTDMA_OFF) { 2488 if (ver->fcxslots == 1) 2489 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2490 else if (ver->fcxslots == 7) 2491 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2492 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]); 2493 2494 if (wl_slot_real > wl_slot_set) 2495 diff_t = wl_slot_real - wl_slot_set; 2496 else 2497 diff_t = wl_slot_set - wl_slot_real; 2498 } 2499 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2500 2501 /* Check diff time between real BT slot and EBT/E5G slot */ 2502 bt_slot_set = btc->bt_req_len[RTW89_PHY_0]; 2503 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]); 2504 diff_t = 0; 2505 if (dm->tdma_now.type == CXTDMA_OFF && 2506 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2507 bt_slot_set != 0) { 2508 if (bt_slot_set > bt_slot_real) 2509 diff_t = bt_slot_set - bt_slot_real; 2510 else 2511 diff_t = bt_slot_real - bt_slot_set; 2512 } 2513 2514 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2515 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2516 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G])); 2517 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2518 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1])); 2519 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2520 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1])); 2521 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2522 le16_to_cpu(pcysta->v5.cycles)); 2523 } else if (ver->fcxcysta == 105) { 2524 if (dm->fddt_train == BTC_FDDT_ENABLE) 2525 break; 2526 2527 cnt_leak_slot = le16_to_cpu(pcysta->v105.slot_cnt[CXST_LK]); 2528 cnt_rx_imr = le32_to_cpu(pcysta->v105.leak_slot.cnt_rximr); 2529 2530 /* Check Leak-AP */ 2531 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2532 dm->tdma_now.rxflctrl) { 2533 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 2534 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2535 dm->leak_ap = 1; 2536 } 2537 2538 /* Check diff time between real WL slot and W1 slot */ 2539 if (dm->tdma_now.type == CXTDMA_OFF) { 2540 if (ver->fcxslots == 1) 2541 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2542 else if (ver->fcxslots == 7) 2543 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2544 wl_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_WL]); 2545 2546 if (wl_slot_real > wl_slot_set) 2547 diff_t = wl_slot_real - wl_slot_set; 2548 else 2549 diff_t = wl_slot_set - wl_slot_real; 2550 } 2551 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2552 2553 /* Check diff time between real BT slot and EBT/E5G slot */ 2554 bt_slot_set = btc->bt_req_len[RTW89_PHY_0]; 2555 bt_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_BT]); 2556 diff_t = 0; 2557 if (dm->tdma_now.type == CXTDMA_OFF && 2558 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2559 bt_slot_set != 0) { 2560 if (bt_slot_set > bt_slot_real) 2561 diff_t = bt_slot_set - bt_slot_real; 2562 else 2563 diff_t = bt_slot_real - bt_slot_set; 2564 } 2565 2566 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2567 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2568 le16_to_cpu(pcysta->v105.slot_cnt[CXST_E2G])); 2569 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2570 le16_to_cpu(pcysta->v105.slot_cnt[CXST_W1])); 2571 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2572 le16_to_cpu(pcysta->v105.slot_cnt[CXST_B1])); 2573 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2574 le16_to_cpu(pcysta->v105.cycles)); 2575 } else if (ver->fcxcysta == 7) { 2576 if (dm->fddt_train == BTC_FDDT_ENABLE) 2577 break; 2578 2579 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 2580 2581 if (dm->tdma_now.type != CXTDMA_OFF) { 2582 /* Check diff time between real WL slot and W1 slot */ 2583 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]); 2584 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16); 2585 2586 /* Check Leak-AP */ 2587 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) * 2588 BTC_LEAK_AP_TH; 2589 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]); 2590 2591 val16 = le16_to_cpu(pcysta->v7.cycles); 2592 if (dm->tdma_now.rxflctrl && 2593 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2594 dm->leak_ap = 1; 2595 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2596 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]); 2597 /* Check diff between real BT slot and EBT/E5G slot */ 2598 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16); 2599 2600 /* Check bt slot length for P2P mode*/ 2601 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) * 2602 BTC_SLOT_REQ_TH; 2603 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt); 2604 2605 val16 = le16_to_cpu(pcysta->v7.cycles); 2606 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2607 dm->slot_req_more = 1; 2608 else if (bt->link_info.status.map.connect == 0) 2609 dm->slot_req_more = 0; 2610 } 2611 2612 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2613 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G])); 2614 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2615 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1])); 2616 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2617 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1])); 2618 2619 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */ 2620 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD, 2621 le16_to_cpu(pcysta->v7.cycles)); 2622 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2623 le16_to_cpu(pcysta->v7.cycles)); 2624 } else { 2625 goto err; 2626 } 2627 break; 2628 case BTC_RPT_TYPE_MREG: 2629 if (ver->fcxmreg == 7) 2630 break; 2631 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val); 2632 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL) 2633 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL; 2634 else 2635 dm->wl_btg_rx_rb = val; 2636 2637 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val); 2638 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL) 2639 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL; 2640 else 2641 dm->wl_pre_agc_rb = val; 2642 break; 2643 case BTC_RPT_TYPE_BT_VER: 2644 case BTC_RPT_TYPE_BT_SCAN: 2645 case BTC_RPT_TYPE_BT_AFH: 2646 case BTC_RPT_TYPE_BT_DEVICE: 2647 _update_bt_report(rtwdev, rpt_type, pfinfo); 2648 break; 2649 } 2650 return (rpt_len + BTC_RPT_HDR_SIZE); 2651 2652 err: 2653 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2654 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type); 2655 return 0; 2656 } 2657 2658 static void _parse_btc_report(struct rtw89_dev *rtwdev, 2659 struct rtw89_btc_btf_fwinfo *pfwinfo, 2660 u8 *pbuf, u32 buf_len) 2661 { 2662 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 2663 struct rtw89_btc_prpt *btc_prpt = NULL; 2664 u32 index = 0, rpt_len = 0; 2665 2666 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2667 "[BTC], %s(): buf_len:%d\n", 2668 __func__, buf_len); 2669 2670 while (pbuf) { 2671 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index]; 2672 if (index + 2 >= ver->info_buf) 2673 break; 2674 /* At least 3 bytes: type(1) & len(2) */ 2675 rpt_len = le16_to_cpu(btc_prpt->len); 2676 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len) 2677 break; 2678 2679 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index); 2680 if (!rpt_len) 2681 break; 2682 index += rpt_len; 2683 } 2684 } 2685 2686 #define BTC_TLV_HDR_LEN 2 2687 #define BTC_TLV_HDR_LEN_V7 3 2688 2689 static void _append_tdma(struct rtw89_dev *rtwdev) 2690 { 2691 struct rtw89_btc *btc = &rtwdev->btc; 2692 const struct rtw89_btc_ver *ver = btc->ver; 2693 struct rtw89_btc_dm *dm = &btc->dm; 2694 struct rtw89_btc_btf_tlv *tlv; 2695 struct rtw89_btc_btf_tlv_v7 *tlv_v7; 2696 struct rtw89_btc_fbtc_tdma *v; 2697 struct rtw89_btc_fbtc_tdma_v3 *v3; 2698 u16 len = btc->policy_len; 2699 2700 if (!btc->update_policy_force && 2701 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) { 2702 rtw89_debug(rtwdev, 2703 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n", 2704 __func__); 2705 return; 2706 } 2707 2708 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 2709 tlv->type = CXPOLICY_TDMA; 2710 if (ver->fcxtdma == 1) { 2711 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0]; 2712 tlv->len = sizeof(*v); 2713 *v = dm->tdma; 2714 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 2715 } else if (ver->fcxtdma == 7 || ver->fcxtdma == 4) { 2716 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 2717 tlv_v7->len = sizeof(dm->tdma); 2718 tlv_v7->ver = ver->fcxtdma; 2719 tlv_v7->type = CXPOLICY_TDMA; 2720 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len); 2721 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len; 2722 } else { 2723 tlv->len = sizeof(*v3); 2724 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0]; 2725 v3->fver = ver->fcxtdma; 2726 v3->tdma = dm->tdma; 2727 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3); 2728 } 2729 2730 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2731 "[BTC], %s(): type:%d, rxflctrl=%d, txflctrl=%d, bind=%d, leak_n=%d, ext_ctrl=%d\n", 2732 __func__, dm->tdma.type, dm->tdma.rxflctrl, 2733 dm->tdma.txflctrl, dm->tdma.bind, dm->tdma.leak_n, 2734 dm->tdma.ext_ctrl); 2735 } 2736 2737 static void _append_slot_v1(struct rtw89_dev *rtwdev) 2738 { 2739 struct rtw89_btc *btc = &rtwdev->btc; 2740 struct rtw89_btc_dm *dm = &btc->dm; 2741 struct rtw89_btc_btf_tlv *tlv = NULL; 2742 struct btc_fbtc_1slot *v = NULL; 2743 u16 len = 0; 2744 u8 i, cnt = 0; 2745 2746 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2747 "[BTC], %s(): A:btc->policy_len = %d\n", 2748 __func__, btc->policy_len); 2749 2750 for (i = 0; i < CXST_MAX; i++) { 2751 if (!btc->update_policy_force && 2752 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i], 2753 sizeof(dm->slot.v1[i]))) 2754 continue; 2755 2756 len = btc->policy_len; 2757 2758 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 2759 v = (struct btc_fbtc_1slot *)&tlv->val[0]; 2760 tlv->type = CXPOLICY_SLOT; 2761 tlv->len = sizeof(*v); 2762 2763 v->fver = btc->ver->fcxslots; 2764 v->sid = i; 2765 v->slot = dm->slot.v1[i]; 2766 2767 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2768 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n", 2769 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl, 2770 dm->slot.v1[i].cxtype); 2771 cnt++; 2772 2773 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 2774 } 2775 2776 if (cnt > 0) 2777 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2778 "[BTC], %s(): slot update (cnt=%d)!!\n", 2779 __func__, cnt); 2780 } 2781 2782 static void _append_slot_v7(struct rtw89_dev *rtwdev) 2783 { 2784 struct rtw89_btc_btf_tlv_v7 *tlv = NULL; 2785 struct rtw89_btc *btc = &rtwdev->btc; 2786 struct rtw89_btc_dm *dm = &btc->dm; 2787 u8 i, cnt = 0; 2788 u16 len; 2789 2790 for (i = 0; i < CXST_MAX; i++) { 2791 if (!btc->update_policy_force && 2792 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i], 2793 sizeof(dm->slot.v7[i]))) 2794 continue; 2795 2796 len = btc->policy_len; 2797 2798 if (!tlv) { 2799 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) { 2800 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2801 "[BTC], %s(): buff overflow!\n", __func__); 2802 break; 2803 } 2804 2805 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 2806 tlv->type = CXPOLICY_SLOT; 2807 tlv->ver = btc->ver->fcxslots; 2808 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7; 2809 len += BTC_TLV_HDR_LEN_V7; 2810 } 2811 2812 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) { 2813 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2814 "[BTC], %s(): buff overflow!\n", __func__); 2815 break; 2816 } 2817 2818 btc->policy[len] = i; /* slot-id */ 2819 memcpy(&btc->policy[len + 1], &dm->slot.v7[i], 2820 sizeof(dm->slot.v7[0])); 2821 len += tlv->len; 2822 2823 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2824 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n", 2825 __func__, btc->policy_len, i, dm->slot.v7[i].dur, 2826 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl); 2827 cnt++; 2828 btc->policy_len = len; /* update total length */ 2829 } 2830 2831 if (cnt > 0) 2832 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2833 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n", 2834 __func__, cnt, btc->policy_len); 2835 } 2836 2837 static void _append_slot(struct rtw89_dev *rtwdev) 2838 { 2839 struct rtw89_btc *btc = &rtwdev->btc; 2840 2841 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7) 2842 _append_slot_v7(rtwdev); 2843 else 2844 _append_slot_v1(rtwdev); 2845 } 2846 2847 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) 2848 { 2849 struct rtw89_btc *btc = &rtwdev->btc; 2850 const struct rtw89_btc_ver *ver = btc->ver; 2851 u32 bit_map = 0; 2852 2853 switch (rpt_map) { 2854 case RPT_EN_TDMA: 2855 bit_map = BIT(0); 2856 break; 2857 case RPT_EN_CYCLE: 2858 bit_map = BIT(1); 2859 break; 2860 case RPT_EN_MREG: 2861 bit_map = BIT(2); 2862 break; 2863 case RPT_EN_BT_VER_INFO: 2864 bit_map = BIT(3); 2865 break; 2866 case RPT_EN_BT_SCAN_INFO: 2867 bit_map = BIT(4); 2868 break; 2869 case RPT_EN_BT_DEVICE_INFO: 2870 switch (ver->frptmap) { 2871 case 0: 2872 case 1: 2873 case 2: 2874 bit_map = BIT(6); 2875 break; 2876 case 3: 2877 case 4: 2878 case 5: 2879 case 105: 2880 bit_map = BIT(5); 2881 break; 2882 default: 2883 break; 2884 } 2885 break; 2886 case RPT_EN_BT_AFH_MAP: 2887 switch (ver->frptmap) { 2888 case 0: 2889 case 1: 2890 case 2: 2891 bit_map = BIT(5); 2892 break; 2893 case 3: 2894 case 4: 2895 case 5: 2896 case 105: 2897 bit_map = BIT(6); 2898 break; 2899 default: 2900 break; 2901 } 2902 break; 2903 case RPT_EN_BT_AFH_MAP_LE: 2904 switch (ver->frptmap) { 2905 case 2: 2906 bit_map = BIT(8); 2907 break; 2908 case 3: 2909 case 4: 2910 case 5: 2911 case 105: 2912 bit_map = BIT(7); 2913 break; 2914 default: 2915 break; 2916 } 2917 break; 2918 case RPT_EN_BT_TX_PWR_LVL: 2919 switch (ver->frptmap) { 2920 case 0: 2921 case 1: 2922 case 2: 2923 case 3: 2924 case 105: 2925 break; 2926 case 4: 2927 case 5: 2928 bit_map = BIT(8); 2929 break; 2930 default: 2931 break; 2932 } 2933 break; 2934 case RPT_EN_FW_STEP_INFO: 2935 switch (ver->frptmap) { 2936 case 1: 2937 case 2: 2938 bit_map = BIT(7); 2939 break; 2940 case 3: 2941 case 105: 2942 bit_map = BIT(8); 2943 break; 2944 case 4: 2945 case 5: 2946 bit_map = BIT(9); 2947 break; 2948 default: 2949 break; 2950 } 2951 break; 2952 case RPT_EN_TEST: 2953 if (ver->frptmap == 5) 2954 bit_map = BIT(10); 2955 else if (ver->frptmap == 105) 2956 bit_map = BIT(9); 2957 else 2958 bit_map = BIT(31); 2959 break; 2960 case RPT_EN_WL_ALL: 2961 switch (ver->frptmap) { 2962 case 0: 2963 case 1: 2964 case 2: 2965 bit_map = GENMASK(2, 0); 2966 break; 2967 case 3: 2968 case 105: 2969 bit_map = GENMASK(2, 0) | BIT(8); 2970 break; 2971 case 4: 2972 case 5: 2973 bit_map = GENMASK(2, 0) | BIT(9); 2974 break; 2975 default: 2976 break; 2977 } 2978 break; 2979 case RPT_EN_BT_ALL: 2980 switch (ver->frptmap) { 2981 case 0: 2982 case 1: 2983 bit_map = GENMASK(6, 3); 2984 break; 2985 case 2: 2986 bit_map = GENMASK(6, 3) | BIT(8); 2987 break; 2988 case 3: 2989 case 105: 2990 bit_map = GENMASK(7, 3); 2991 break; 2992 case 4: 2993 case 5: 2994 bit_map = GENMASK(8, 3); 2995 break; 2996 default: 2997 break; 2998 } 2999 break; 3000 case RPT_EN_ALL: 3001 switch (ver->frptmap) { 3002 case 0: 3003 bit_map = GENMASK(6, 0); 3004 break; 3005 case 1: 3006 bit_map = GENMASK(7, 0); 3007 break; 3008 case 2: 3009 case 3: 3010 bit_map = GENMASK(8, 0); 3011 break; 3012 case 4: 3013 case 5: 3014 case 105: 3015 bit_map = GENMASK(9, 0); 3016 break; 3017 default: 3018 break; 3019 } 3020 break; 3021 case RPT_EN_MONITER: 3022 switch (ver->frptmap) { 3023 case 0: 3024 case 1: 3025 bit_map = GENMASK(6, 2); 3026 break; 3027 case 2: 3028 bit_map = GENMASK(6, 2) | BIT(8); 3029 break; 3030 case 3: 3031 case 105: 3032 bit_map = GENMASK(8, 2); 3033 break; 3034 case 4: 3035 case 5: 3036 bit_map = GENMASK(9, 2); 3037 break; 3038 default: 3039 break; 3040 } 3041 break; 3042 } 3043 3044 return bit_map; 3045 } 3046 3047 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev) 3048 { 3049 struct rtw89_btc *btc = &rtwdev->btc; 3050 const struct rtw89_btc_ver *ver = btc->ver; 3051 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL; 3052 struct rtw89_btc_btf_set_slot_table *tbl; 3053 struct rtw89_btc_dm *dm = &btc->dm; 3054 u16 n, len; 3055 3056 if (ver->fcxslots == 2 || ver->fcxslots == 7) { 3057 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7); 3058 tlv_v7 = kmalloc(len, GFP_KERNEL); 3059 if (!tlv_v7) 3060 return; 3061 3062 tlv_v7->type = SET_SLOT_TABLE; 3063 tlv_v7->ver = ver->fcxslots; 3064 tlv_v7->len = ARRAY_SIZE(dm->slot.v7); 3065 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7)); 3066 3067 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len); 3068 3069 kfree(tlv_v7); 3070 } else { 3071 n = struct_size(tbl, tbls, CXST_MAX); 3072 tbl = kmalloc(n, GFP_KERNEL); 3073 if (!tbl) 3074 return; 3075 3076 tbl->fver = BTF_SET_SLOT_TABLE_VER; 3077 tbl->tbl_num = CXST_MAX; 3078 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX)); 3079 3080 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); 3081 3082 kfree(tbl); 3083 } 3084 } 3085 3086 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, 3087 bool force_exec, u32 rpt_map) 3088 { 3089 struct rtw89_btc *btc = &rtwdev->btc; 3090 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo; 3091 union rtw89_fbtc_rtp_ctrl r; 3092 int ret; 3093 u32 i; 3094 3095 if (!force_exec && rpt_map == fwinfo->rpt_en_map) 3096 return; 3097 3098 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rpt_map=%x\n", 3099 __func__, fwinfo->rpt_en_map); 3100 3101 if (btc->ver->fcxbtcrpt == 7 || 3102 btc->ver->fcxbtcrpt == 8 || 3103 btc->ver->fcxbtcrpt == 9 || 3104 btc->ver->fcxbtcrpt == 11) { 3105 r.v8.type = SET_REPORT_EN; 3106 r.v8.fver = btc->ver->fcxbtcrpt; 3107 r.v8.len = sizeof(r.v8.map); 3108 r.v8.map = cpu_to_le32(rpt_map); 3109 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8, 3110 sizeof(r.v8)); 3111 } else { 3112 if (btc->ver->fcxbtcrpt == 105) 3113 r.v1.fver = 5; 3114 else 3115 r.v1.fver = btc->ver->fcxbtcrpt; 3116 3117 for (i = 0; i < RPT_EN_MONITER; i++) { 3118 r.v1.enable = cpu_to_le32(i); 3119 if (rpt_map & BIT(i)) 3120 r.v1.para = cpu_to_le32(1); 3121 else 3122 r.v1.para = 0; 3123 3124 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, 3125 &r.v1, sizeof(r.v1)); 3126 } 3127 } 3128 3129 if (!ret) 3130 fwinfo->rpt_en_map = rpt_map; 3131 } 3132 3133 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) 3134 { 3135 const struct rtw89_chip_info *chip = rtwdev->chip; 3136 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3137 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL; 3138 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL; 3139 u8 i, n, ulen, cxmreg_max; 3140 u16 sz = 0; 3141 3142 n = chip->mon_reg_num; 3143 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3144 "[BTC], %s(): mon_reg_num=%d\n", __func__, n); 3145 3146 if (ver->fcxmreg == 1) 3147 cxmreg_max = CXMREG_MAX; 3148 else 3149 cxmreg_max = CXMREG_MAX_V2; 3150 3151 if (n > cxmreg_max) { 3152 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3153 "[BTC], %s(): mon reg count %d > %d\n", 3154 __func__, n, cxmreg_max); 3155 return; 3156 } 3157 3158 ulen = sizeof(struct rtw89_btc_fbtc_mreg); 3159 3160 if (ver->fcxmreg == 7) { 3161 sz = struct_size(v7, regs, n); 3162 v7 = kmalloc(sz, GFP_KERNEL); 3163 if (!v7) 3164 return; 3165 v7->type = RPT_EN_MREG; 3166 v7->fver = ver->fcxmreg; 3167 v7->len = n; 3168 for (i = 0; i < n; i++) { 3169 v7->regs[i].type = chip->mon_reg[i].type; 3170 v7->regs[i].bytes = chip->mon_reg[i].bytes; 3171 v7->regs[i].offset = chip->mon_reg[i].offset; 3172 } 3173 3174 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz); 3175 kfree(v7); 3176 } else { 3177 sz = struct_size(v1, regs, n); 3178 v1 = kmalloc(sz, GFP_KERNEL); 3179 if (!v1) 3180 return; 3181 v1->fver = ver->fcxmreg; 3182 v1->reg_num = n; 3183 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n)); 3184 3185 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz); 3186 kfree(v1); 3187 } 3188 3189 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3190 "[BTC], %s(): sz=%d ulen=%d n=%d\n", 3191 __func__, sz, ulen, n); 3192 } 3193 3194 static void _update_dm_step(struct rtw89_dev *rtwdev, 3195 enum btc_reason_and_action reason_or_action) 3196 { 3197 struct rtw89_btc *btc = &rtwdev->btc; 3198 struct rtw89_btc_dm *dm = &btc->dm; 3199 3200 /* use ring-structure to store dm step */ 3201 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action; 3202 dm->dm_step.step_pos++; 3203 3204 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) { 3205 dm->dm_step.step_pos = 0; 3206 dm->dm_step.step_ov = true; 3207 } 3208 } 3209 3210 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 3211 enum btc_reason_and_action action) 3212 { 3213 struct rtw89_btc *btc = &rtwdev->btc; 3214 struct rtw89_btc_dm *dm = &btc->dm; 3215 int ret; 3216 3217 dm->run_action = action; 3218 3219 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT); 3220 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT); 3221 3222 btc->policy_len = 0; 3223 btc->policy_type = policy_type; 3224 3225 _append_tdma(rtwdev); 3226 _append_slot(rtwdev); 3227 3228 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN) 3229 return; 3230 3231 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3232 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n", 3233 __func__, action, policy_type, btc->policy_len); 3234 3235 if (dm->tdma.rxflctrl == CXFLC_NULLP || 3236 dm->tdma.rxflctrl == CXFLC_QOSNULL) 3237 btc->btc_ctrl_lps = 1; 3238 else 3239 btc->btc_ctrl_lps = dm->lps_ctrl_scbd; 3240 3241 if (btc->btc_ctrl_lps == 1) 3242 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps); 3243 3244 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY, 3245 btc->policy, btc->policy_len); 3246 if (!ret) { 3247 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now)); 3248 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7) 3249 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7)); 3250 else 3251 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1)); 3252 } 3253 3254 if (btc->update_policy_force) 3255 btc->update_policy_force = false; 3256 3257 if (btc->btc_ctrl_lps == 0) 3258 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps); 3259 } 3260 3261 static u8 _get_gpiosig_for_ver(struct rtw89_dev *rtwdev, u8 sig_v8) 3262 { 3263 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3264 3265 /* v8: gpio_ver >= 8, directly use v8 signal ID */ 3266 if (ver->fcxgpiodbg >= 8) 3267 return sig_v8; 3268 3269 /* v7: gpio_ver < 8, convert v8 signal ID to v7 signal ID */ 3270 if (sig_v8 <= BTC_DBG_GNT_WL) { 3271 return sig_v8; 3272 } else if (sig_v8 <= BTC_DBG_GNT_WL1) { 3273 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3274 "[BTC], %s(): sig %d not supported in v7\n", 3275 __func__, sig_v8); 3276 return BTC_DBG_NUM; 3277 } else if (sig_v8 >= BTC_DBG_NUM) { 3278 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3279 "[BTC], %s(): sig %d not available\n", 3280 __func__, sig_v8); 3281 return BTC_DBG_NUM; 3282 } else { 3283 return sig_v8 - 2; 3284 } 3285 } 3286 3287 static u32 _convert_gpio_enmap_to_ver(struct rtw89_dev *rtwdev, u32 en_map_v8) 3288 { 3289 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3290 u32 en_map_v7 = 0; 3291 u32 bit; 3292 3293 /* v8: gpio_ver >= 8, directly use v8 en_map */ 3294 if (ver->fcxgpiodbg >= 8) 3295 return en_map_v8; 3296 3297 /* v7: gpio_ver < 8, convert v8 en_map bitmap to v7 en_map bitmap */ 3298 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ 3299 en_map_v7 |= en_map_v8 & GENMASK(1, 0); 3300 3301 /* bit 2-3: GNT_BT1, GNT_WL1 - not supported in v7, skip these bits */ 3302 3303 /* bit 4-31: shift right by 2 positions (become bit 2-29 in v7) */ 3304 for (bit = BTC_DBG_BCN_EARLY; bit < BTC_DBG_NUM; bit++) { 3305 if (en_map_v8 & BIT(bit)) 3306 en_map_v7 |= BIT(bit - 2); 3307 } 3308 3309 return en_map_v7; 3310 } 3311 3312 static u32 _convert_gpio_enmap_from_ver(struct rtw89_dev *rtwdev, u32 en_map) 3313 { 3314 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3315 u32 en_map_v8 = 0; 3316 u32 bit; 3317 3318 if (ver->fcxgpiodbg >= 8) 3319 return en_map; 3320 3321 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ 3322 en_map_v8 |= en_map & GENMASK(1, 0); 3323 3324 /* bit 2-29: shift left by 2 positions (become bit 4-31 in v8) */ 3325 for (bit = BTC_DBG_GNT_BT1; bit < BTC_DBG_NUM - 2; bit++) { 3326 if (en_map & BIT(bit)) 3327 en_map_v8 |= BIT(bit + 2); 3328 } 3329 3330 return en_map_v8; 3331 } 3332 3333 static void _fw_set_gpio(struct rtw89_dev *rtwdev, u8 type, u32 val) 3334 { 3335 struct rtw89_btc *btc = &rtwdev->btc; 3336 struct rtw89_fbtc_h2c_set_gpio *gpio = &btc->gpio; 3337 const struct rtw89_btc_ver *ver = btc->ver; 3338 struct rtw89_fbtc_h2c_set_gpio_2b l2_h2c; 3339 struct rtw89_fbtc_h2c_set_gpio_4b l4_h2c; 3340 u8 gpio_ver = ver->fcxgpiodbg; 3341 u8 buf[sizeof(l4_h2c)]; 3342 u8 len; 3343 3344 if (gpio_ver < 8 && type > CXDGPIO_MUX_MAP) 3345 return; 3346 3347 if (type >= CXDGPIO_MAX) 3348 return; 3349 3350 switch (type) { 3351 case CXDGPIO_EN_MAP: /* GPIO debug signal en-map 0~31 */ 3352 val = _convert_gpio_enmap_to_ver(rtwdev, val); 3353 gpio->en_map.data.type = CXDGPIO_EN_MAP; 3354 gpio->en_map.data.fver = gpio_ver; 3355 gpio->en_map.data.dlen = CXDGPIO_SET_L4; 3356 gpio->en_map.data.en_map = val; 3357 l4_h2c = gpio->en_map.fmt; 3358 put_unaligned_le32(val, (u32 *)l4_h2c.data); 3359 memcpy(buf, &l4_h2c, sizeof(l4_h2c)); 3360 len = sizeof(l4_h2c); 3361 break; 3362 case CXDGPIO_MUX_MAP: /* GPIO dbg: Signal to GPIO Mux */ 3363 gpio->mux.data.type = CXDGPIO_MUX_MAP; 3364 gpio->mux.data.fver = gpio_ver; 3365 gpio->mux.data.dlen = CXDGPIO_SET_L2; 3366 gpio->mux.data.sig = _get_gpiosig_for_ver(rtwdev, 3367 FIELD_GET(GENMASK(7, 0), val)); 3368 if (gpio->mux.data.sig == 0xff) 3369 return; 3370 gpio->mux.data.gpio = FIELD_GET(GENMASK(15, 8), val); 3371 l2_h2c = gpio->mux.fmt; 3372 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3373 len = sizeof(l2_h2c); 3374 break; 3375 case CXDGPIO_EXT_HPTA: /* GPIO config for Ext HW-PTA */ 3376 gpio->ext_pta.data.type = CXDGPIO_EXT_HPTA; 3377 gpio->ext_pta.data.fver = gpio_ver; 3378 gpio->ext_pta.data.dlen = CXDGPIO_SET_L2; 3379 gpio->ext_pta.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3380 gpio->ext_pta.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3381 l2_h2c = gpio->ext_pta.fmt; 3382 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3383 len = sizeof(l2_h2c); 3384 break; 3385 case CXDGPIO_EXT_HMBX: /* GPIO config for Ext HW-mailbox */ 3386 gpio->ext_mb.data.type = CXDGPIO_EXT_HMBX; 3387 gpio->ext_mb.data.fver = gpio_ver; 3388 gpio->ext_mb.data.dlen = CXDGPIO_SET_L2; 3389 gpio->ext_mb.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3390 gpio->ext_mb.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3391 l2_h2c = gpio->ext_mb.fmt; 3392 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3393 len = sizeof(l2_h2c); 3394 break; 3395 case CXDGPIO_EXT_SWOUT: /* GPIO config for Ext SW output (wlan_act) */ 3396 gpio->ext_swout.data.type = CXDGPIO_EXT_SWOUT; 3397 gpio->ext_swout.data.fver = gpio_ver; 3398 gpio->ext_swout.data.dlen = CXDGPIO_SET_L2; 3399 gpio->ext_swout.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3400 gpio->ext_swout.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3401 l2_h2c = gpio->ext_swout.fmt; 3402 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3403 len = sizeof(l2_h2c); 3404 break; 3405 case CXDGPIO_EXT_SWIN: /* GPIO config for Ext SW input control */ 3406 gpio->ext_swin.data.type = CXDGPIO_EXT_SWIN; 3407 gpio->ext_swin.data.fver = gpio_ver; 3408 gpio->ext_swin.data.dlen = CXDGPIO_SET_L4; 3409 gpio->ext_swin.data.in_map_low = FIELD_GET(GENMASK(7, 0), val); 3410 gpio->ext_swin.data.in_map_high = FIELD_GET(GENMASK(15, 8), val); 3411 gpio->ext_swin.data.int_map_low = FIELD_GET(GENMASK(23, 16), val); 3412 gpio->ext_swin.data.int_map_high = FIELD_GET(GENMASK(31, 24), val); 3413 l4_h2c = gpio->ext_swin.fmt; 3414 put_unaligned_le32(val, (u32 *)l4_h2c.data); 3415 memcpy(buf, &l4_h2c, sizeof(l4_h2c)); 3416 len = sizeof(l4_h2c); 3417 break; 3418 default: 3419 return; 3420 } 3421 3422 _send_fw_cmd(rtwdev, BTFC_SET, SET_GPIO_DBG, buf, len); 3423 } 3424 3425 static void _set_ext_interface(struct rtw89_dev *rtwdev) 3426 { 3427 struct rtw89_btc *btc = &rtwdev->btc; 3428 struct rtw89_btc_cx *cx = &btc->cx; 3429 u8 bt1_sw_type = BTC_SWITCH_INTERNAL; 3430 u32 val; 3431 3432 if (btc->ver->fcxgpiodbg < 7) 3433 return; 3434 3435 /* if BT1+WL-S0, route DBG_GNT_BT1 to control SPDT */ 3436 if ((rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && 3437 btc->ver->fcxinit >= 10) { 3438 if (btc->ver->fcxinit >= 10) 3439 bt1_sw_type = btc->mdinfo.bt1_sw_type; 3440 else 3441 return; 3442 3443 if (bt1_sw_type > BTC_SWITCH_INTERNAL) { 3444 _fw_set_gpio(rtwdev, CXDGPIO_EN_MAP, 3445 BIT(BTC_DBG_GNT_BT1)); 3446 3447 val = (bt1_sw_type << 8) + BTC_DBG_GNT_BT1; 3448 _fw_set_gpio(rtwdev, CXDGPIO_MUX_MAP, val); 3449 } 3450 } 3451 3452 /* set GPIO as Ext-PTA interface wire */ 3453 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_PTA) 3454 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HPTA, cx->bt_ext.hpta_cfg); 3455 3456 /* set GPIO as Ext-mailbox interface wire */ 3457 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_MBX) 3458 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HMBX, cx->bt_ext.hmbx_cfg); 3459 3460 /* set GPIO as Ext-SWIO interface wire */ 3461 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_SWIO) { 3462 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWOUT, cx->bt_ext.swout_cfg); 3463 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWIN, cx->bt_ext.swin_cfg); 3464 } 3465 } 3466 3467 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) 3468 { 3469 struct rtw89_btc *btc = &rtwdev->btc; 3470 const struct rtw89_btc_ver *ver = btc->ver; 3471 3472 switch (index) { 3473 case CXDRVINFO_INIT: 3474 if (ver->fcxinit == 7 || ver->fcxinit == 107) 3475 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, index); 3476 else if (ver->fcxinit == 10) 3477 rtw89_fw_h2c_cxdrv_init_v10(rtwdev, index); 3478 else if (ver->fcxinit == 11) 3479 rtw89_fw_h2c_cxdrv_init_v11(rtwdev, index); 3480 else 3481 rtw89_fw_h2c_cxdrv_init(rtwdev, index); 3482 break; 3483 case CXDRVINFO_ROLE: 3484 if (ver->fwlrole == 0) 3485 rtw89_fw_h2c_cxdrv_role(rtwdev, index); 3486 else if (ver->fwlrole == 1) 3487 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, index); 3488 else if (ver->fwlrole == 101) 3489 rtw89_fw_h2c_cxdrv_role_v101(rtwdev, index); 3490 else if (ver->fwlrole == 2) 3491 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, index); 3492 else if (ver->fwlrole == 7) 3493 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, index); 3494 else if (ver->fwlrole == 8) 3495 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, index); 3496 else if (ver->fwlrole == 10) 3497 rtw89_fw_h2c_cxdrv_role_v10(rtwdev, index); 3498 break; 3499 case CXDRVINFO_CTRL: 3500 if (ver->drvinfo_ver != 0) 3501 index = 2; 3502 3503 if (ver->fcxctrl == 7) 3504 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, index); 3505 else if (ver->fcxctrl == 9) 3506 rtw89_fw_h2c_cxdrv_ctrl_v9(rtwdev, index); 3507 else 3508 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, index); 3509 break; 3510 case CXDRVINFO_TRX: 3511 if (ver->drvinfo_ver > 1) 3512 index = 3; 3513 3514 if (ver->fcxtrx == 0) 3515 return; 3516 3517 if (ver->fcxtrx == 7) 3518 rtw89_fw_h2c_cxdrv_trx_v7(rtwdev, index); 3519 else if (ver->fcxtrx == 9) 3520 rtw89_fw_h2c_cxdrv_trx_v9(rtwdev, index); 3521 else if (ver->fcxtrx == 107) 3522 rtw89_fw_h2c_cxdrv_trx_v107(rtwdev, index); 3523 break; 3524 case CXDRVINFO_RFK: 3525 if (ver->drvinfo_ver != 0) 3526 return; 3527 3528 rtw89_fw_h2c_cxdrv_rfk(rtwdev, index); 3529 break; 3530 case CXDRVINFO_TXPWR: 3531 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103) 3532 index = 4; 3533 3534 if (ver->fcxtrx == 7 || ver->fcxtrx == 107) 3535 rtw89_fw_h2c_cxtxpwr_v7(rtwdev, index); 3536 else if (ver->fcxtrx == 9) 3537 rtw89_fw_h2c_cxtxpwr_v9(rtwdev, index); 3538 break; 3539 case CXDRVINFO_FDDT: 3540 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103) 3541 index = 5; 3542 else 3543 return; 3544 3545 break; 3546 case CXDRVINFO_MLO: 3547 if (!ver->fcxmlo || ver->drvinfo_ver == 103) 3548 return; 3549 3550 if (ver->drvinfo_ver == 3) 3551 index = 6; 3552 else 3553 return; 3554 3555 if (ver->fcxmlo == 2) 3556 rtw89_fw_h2c_cxdrv_mlo_v2(rtwdev, index); 3557 3558 break; 3559 case CXDRVINFO_OSI: 3560 if (!ver->fcxosi || ver->drvinfo_ver == 103) 3561 return; 3562 3563 if (ver->drvinfo_ver == 3) 3564 index = 7; 3565 else 3566 return; 3567 3568 if (ver->fcxosi == 1) 3569 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, index); 3570 else if (ver->fcxosi == 6) 3571 rtw89_fw_h2c_cxdrv_osi_info_v6(rtwdev, index); 3572 else 3573 return; 3574 break; 3575 default: 3576 break; 3577 } 3578 } 3579 3580 static 3581 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len) 3582 { 3583 struct rtw89_btc *btc = &rtwdev->btc; 3584 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 3585 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 3586 u8 i; 3587 3588 _parse_btc_report(rtwdev, pfwinfo, data, len); 3589 3590 if (!rtwdev->chip->scbd) 3591 return; 3592 3593 if (!btc->dm.scbd_b2w_update) 3594 return; /* skip if init or no-update */ 3595 3596 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) { 3597 bt = (i == BTC_BT_1ST) ? &btc->cx.bt0 : &btc->cx.bt1; 3598 3599 if (bt->scbd_c2h != bt->scbd_rb) { 3600 /* if btx b2w scbd non-sync */ 3601 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3602 "[BTC], %s() bt%d:c2h->0x%08x, rb->0x%08x\n", 3603 __func__, i, bt->scbd_c2h, bt->scbd_rb); 3604 bt->scbd_c2h = bt->scbd_rb; 3605 _update_bt_scbd(rtwdev, i); 3606 btc->dm.scbd_b2w_update = false; 3607 } 3608 } 3609 3610 if (!btc->dm.scbd_b2w_update) 3611 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 3612 else 3613 btc->dm.scbd_b2w_update = 0; 3614 } 3615 3616 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, 3617 u8 wl_state, u8 bt_state, u8 wlact_state) 3618 { 3619 struct rtw89_btc *btc = &rtwdev->btc; 3620 struct rtw89_btc_dm *dm = &btc->dm; 3621 struct rtw89_btc_fbtc_outsrc_set_info *o = &dm->ost_info; 3622 struct rtw89_mac_ax_wl_act *wlact_set; 3623 struct rtw89_mac_ax_coex_gnt mg; 3624 u8 i; 3625 3626 if (phy_map > BTC_PHY_ALL) 3627 return; 3628 3629 for (i = 0; i < RTW89_PHY_NUM; i++) { 3630 if (!(phy_map & BIT(i))) 3631 continue; 3632 3633 switch (wl_state) { 3634 case BTC_GNT_HW: 3635 dm->gnt_set[i].gnt_wl_sw_en = 0; 3636 dm->gnt_set[i].gnt_wl = 0; 3637 break; 3638 case BTC_GNT_SW_LO: 3639 dm->gnt_set[i].gnt_wl_sw_en = 1; 3640 dm->gnt_set[i].gnt_wl = 0; 3641 break; 3642 case BTC_GNT_SW_HI: 3643 dm->gnt_set[i].gnt_wl_sw_en = 1; 3644 dm->gnt_set[i].gnt_wl = 1; 3645 break; 3646 case BTC_GNT_SET_SKIP: 3647 default: 3648 break; 3649 } 3650 3651 switch (bt_state) { 3652 case BTC_GNT_HW: 3653 dm->gnt_set[i].gnt_bt0_sw_en = 0; 3654 dm->gnt_set[i].gnt_bt0 = 0; 3655 dm->gnt_set[i].gnt_bt1_sw_en = 0; 3656 dm->gnt_set[i].gnt_bt1 = 0; 3657 dm->gnt_set[i].gnt_zb_sw_en = 0; 3658 dm->gnt_set[i].gnt_zb = 0; 3659 break; 3660 case BTC_GNT_SW_LO: 3661 dm->gnt_set[i].gnt_bt0_sw_en = 1; 3662 dm->gnt_set[i].gnt_bt0 = 0; 3663 dm->gnt_set[i].gnt_bt1_sw_en = 1; 3664 dm->gnt_set[i].gnt_bt1 = 0; 3665 dm->gnt_set[i].gnt_zb_sw_en = 1; 3666 dm->gnt_set[i].gnt_zb = 0; 3667 break; 3668 case BTC_GNT_SW_HI: 3669 dm->gnt_set[i].gnt_bt0_sw_en = 1; 3670 dm->gnt_set[i].gnt_bt0 = 1; 3671 dm->gnt_set[i].gnt_bt1_sw_en = 1; 3672 dm->gnt_set[i].gnt_bt1 = 1; 3673 dm->gnt_set[i].gnt_zb_sw_en = 1; 3674 dm->gnt_set[i].gnt_zb = 1; 3675 break; 3676 case BTC_GNT_SET_SKIP: 3677 default: 3678 break; 3679 } 3680 } 3681 3682 for (i = 0; i < BTC_ALL_BT_EZL; i++) { 3683 if (!(rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX)) 3684 break; 3685 3686 switch (wlact_state) { 3687 case BTC_WLACT_HW: 3688 dm->wlact_set[i].wlan_act_en = 0; 3689 dm->wlact_set[i].wlan_act = 0; 3690 break; 3691 case BTC_WLACT_SW_LO: 3692 dm->wlact_set[i].wlan_act_en = 1; 3693 dm->wlact_set[i].wlan_act = 0; 3694 break; 3695 case BTC_WLACT_SW_HI: 3696 dm->wlact_set[i].wlan_act_en = 1; 3697 dm->wlact_set[i].wlan_act = 1; 3698 break; 3699 default: 3700 break; 3701 } 3702 3703 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 3704 break; 3705 } 3706 3707 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3708 "[BTC], %s(): phy_map=0x%x, gnt_wl:%d, gnt_bt:%d, wl_act:%d\n", 3709 __func__, phy_map, wl_state, bt_state, wlact_state); 3710 3711 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) { 3712 if (o->rf_band[BTC_RF_S0] == 1 && o->rf_band[BTC_RF_S1] == 0) 3713 o->rf_gbt_source = BTC_RF_S1; 3714 else 3715 o->rf_gbt_source = BTC_RF_S0; 3716 3717 memcpy(o->wlact_set, dm->wlact_set, sizeof(o->wlact_set)); 3718 3719 if (btc->ver->fcxosi == 6) { 3720 memcpy(o->gnt_set_be, dm->gnt_set, sizeof(o->gnt_set_be)); 3721 return; 3722 } else if (btc->ver->fcxosi == 1) { 3723 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */ 3724 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en; 3725 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0; 3726 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en; 3727 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl; 3728 memcpy(o->gnt_set, mg.band, sizeof(o->gnt_set)); 3729 } 3730 return; 3731 } 3732 } 3733 3734 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */ 3735 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en; 3736 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0; 3737 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en; 3738 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl; 3739 } 3740 for (i = 0; i < BTC_ALL_BT; i++) { /* wlact[BT0/BT1] */ 3741 wlact_set = &dm->wlact_set[i]; 3742 mg.bt[i].wlan_act_en = wlact_set->wlan_act_en; 3743 mg.bt[i].wlan_act = wlact_set->wlan_act; 3744 } 3745 3746 rtw89_chip_mac_cfg_gnt(rtwdev, &mg); 3747 } 3748 3749 #define BTC_TDMA_WLROLE_MAX 3 3750 3751 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable) 3752 { 3753 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3754 "[BTC], %s(): set bt %s wlan_act\n", __func__, 3755 enable ? "ignore" : "do not ignore"); 3756 3757 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1); 3758 } 3759 3760 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0) 3761 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0) 3762 #define WL_TX_POWER_WITH_BT GENMASK(31, 16) 3763 #define WL_TX_POWER_INT_PART GENMASK(8, 2) 3764 #define WL_TX_POWER_FRA_PART GENMASK(1, 0) 3765 #define B_BTC_WL_TX_POWER_SIGN BIT(7) 3766 #define B_TSSI_WL_TX_POWER_SIGN BIT(8) 3767 #define SET_RF_PARA_AX_LEN 1 3768 3769 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level, u8 phy_map) 3770 { 3771 const struct rtw89_chip_info *chip = rtwdev->chip; 3772 struct rtw89_btc *btc = &rtwdev->btc; 3773 const struct rtw89_btc_ver *ver = btc->ver; 3774 struct rtw89_btc_dm *dm = &btc->dm; 3775 bool level_chg = false; 3776 u32 pwr_val; 3777 3778 if (phy_map & BIT(RTW89_PHY_0)) 3779 level_chg = !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] == level); 3780 3781 if (phy_map & BIT(RTW89_PHY_1)) 3782 level_chg |= !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] == level); 3783 3784 if (!level_chg && !btc->cli_h2c_cmd) 3785 return; 3786 3787 if (phy_map & BIT(RTW89_PHY_0)) 3788 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] = level; 3789 3790 if (phy_map & BIT(RTW89_PHY_1)) 3791 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] = level; 3792 3793 dm->wl_tx_pwr_phy_map = phy_map; 3794 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3795 "[BTC], %s(): phy_map=0x%x, wl_tx_pwr-> phy0=%d, phy1=%d\n", 3796 __func__, phy_map, 3797 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0], 3798 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1]); 3799 3800 if ((ver->fcxtrx == 7 && chip->chip_id == RTL8922A) || 3801 ver->fcxtrx == 107) { 3802 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR); 3803 } else if (ver->fcxtrx == 9) { 3804 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR); 3805 } else { 3806 if (level == RTW89_BTC_WL_DEF_TX_PWR) { 3807 pwr_val = WL_TX_POWER_NO_BTC_CTRL; 3808 } else { /* only apply "force tx power" */ 3809 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level); 3810 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR) 3811 pwr_val = RTW89_BTC_WL_DEF_TX_PWR; 3812 3813 if (level & B_BTC_WL_TX_POWER_SIGN) 3814 pwr_val |= B_TSSI_WL_TX_POWER_SIGN; 3815 pwr_val |= WL_TX_POWER_WITH_BT; 3816 } 3817 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); 3818 } 3819 } 3820 3821 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level, u8 phy_map) 3822 { 3823 const struct rtw89_chip_info *chip = rtwdev->chip; 3824 struct rtw89_btc *btc = &rtwdev->btc; 3825 struct rtw89_btc_dm *dm = &btc->dm; 3826 bool level_chg = false; 3827 3828 if (phy_map & BIT(RTW89_PHY_0)) 3829 level_chg = !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] == level); 3830 3831 if (phy_map & BIT(RTW89_PHY_1)) 3832 level_chg |= !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] == level); 3833 3834 if (!level_chg && !btc->cli_h2c_cmd) 3835 return; 3836 3837 if (phy_map & BIT(RTW89_PHY_0)) 3838 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] = level; 3839 3840 if (phy_map & BIT(RTW89_PHY_1)) 3841 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] = level; 3842 3843 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3844 "[BTC], %s(): phy_map=0x%x, wl_rx_gain-> phy0=%d, phy1=%d\n", 3845 __func__, phy_map, 3846 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0], 3847 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1]); 3848 3849 chip->ops->btc_set_wl_rx_gain(rtwdev, level); 3850 } 3851 3852 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, bool force_exec, u8 bid, 3853 u8 rf_band, u8 level) 3854 { 3855 struct rtw89_btc *btc = &rtwdev->btc; 3856 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 3857 u8 h2c_func = SET_BT_TX_PWR; 3858 u8 i, id_start, id_stop; 3859 u8 buf[2] = {}; 3860 u8 len = sizeof(*buf); 3861 3862 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band) 3863 return; 3864 3865 if (bt->rf_para.tx_pwr_freerun == level) 3866 return; 3867 3868 if (bid == BTC_ALL_BT) { 3869 id_start = BTC_BT_1ST; 3870 id_stop = BTC_BT_2ND; 3871 } else { 3872 id_start = bid; 3873 id_stop = bid; 3874 } 3875 3876 for (i = id_start; i <= id_stop; i++) { 3877 if (i == BTC_BT_2ND) { 3878 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 3879 continue; 3880 3881 bt = &btc->cx.bt1; 3882 h2c_func |= BT_H2C_FUNC_BT2ND; 3883 } 3884 3885 buf[0] = (s8)(-level); 3886 buf[1] = rf_band; /* bit-map: bit1->5GHz/6Ghz, bit0->2.4GHz */ 3887 3888 if (!force_exec && !btc->cli_h2c_cmd) { 3889 if (rf_band == RTW89_BAND_2G && 3890 bt->tx_power_now == level) 3891 continue; 3892 else if (rf_band != RTW89_BAND_2G && 3893 bt->tx_power_now_6g == level) 3894 continue; 3895 } 3896 3897 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) 3898 len = SET_RF_PARA_AX_LEN; 3899 3900 if (!_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { 3901 btc->dm.rf_trx_para.bt_tx_power[i] = level; 3902 if (rf_band == RTW89_BAND_2G) 3903 bt->tx_power_now = level; 3904 else 3905 bt->tx_power_now_6g = level; 3906 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3907 "[BTC], %s(): bt%d_tx_power_level = %d\n", 3908 __func__, i, level); 3909 } 3910 } 3911 } 3912 3913 #define BTC_BT_RX_NORMAL_LVL 7 3914 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, bool force_exec, u8 bid, 3915 u8 rf_band, u8 level) 3916 { 3917 struct rtw89_btc *btc = &rtwdev->btc; 3918 struct rtw89_btc_cx *cx = &btc->cx; 3919 struct rtw89_btc_bt_info *bt = &cx->bt0; 3920 u8 h2c_func = SET_BT_LNA_CONSTRAIN; 3921 u8 i, id_start, id_stop; 3922 bool state = false; 3923 u32 scbd_bit = 0; 3924 u8 buf[2] = {}; 3925 u8 len = sizeof(*buf); 3926 3927 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band) 3928 return; 3929 3930 if (bt->rf_para.rx_gain_freerun == level || 3931 level > BTC_BT_RX_NORMAL_LVL || !rtwdev->chip->scbd || 3932 bid > BTC_ALL_BT) 3933 return; 3934 3935 if (bid == BTC_ALL_BT) { 3936 id_start = BTC_BT_1ST; 3937 id_stop = BTC_BT_2ND; 3938 } else { 3939 id_start = bid; 3940 id_stop = bid; 3941 } 3942 3943 if (rf_band == RTW89_BAND_2G) 3944 scbd_bit |= BTC_WSCB_RXGAIN; 3945 else 3946 scbd_bit |= BTC_WSCB_RXGAIN_56G; 3947 3948 for (i = id_start; i <= id_stop; i++) { 3949 if (i == BTC_BT_2ND) { 3950 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 3951 continue; 3952 3953 bt = &cx->bt1; 3954 h2c_func |= BT_H2C_FUNC_BT2ND; 3955 } 3956 3957 /* return if same setup */ 3958 if (!force_exec && !btc->cli_h2c_cmd) { 3959 if (rf_band == RTW89_BAND_2G && 3960 bt->lna_constrain == level) 3961 continue; 3962 else if (rf_band != RTW89_BAND_2G && 3963 bt->lna_constrain_6g == level) 3964 continue; 3965 } 3966 3967 buf[0] = level; 3968 buf[1] = rf_band; 3969 3970 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) 3971 len = SET_RF_PARA_AX_LEN; 3972 3973 if (_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { 3974 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3975 "[BTC], %s(): bt%d_rx_gain_level = %d\n", 3976 __func__, i, level); 3977 } 3978 3979 btc->dm.rf_trx_para.bt_rx_gain[i] = level; 3980 3981 if (buf[0] != BTC_BT_RX_NORMAL_LVL) 3982 state = true; 3983 3984 _write_scbd(rtwdev, bid, scbd_bit, state); 3985 } 3986 } 3987 3988 static void _set_bt_corx_table(struct rtw89_dev *rtwdev, bool en) 3989 { 3990 struct rtw89_btc *btc = &rtwdev->btc; 3991 struct rtw89_btc_cx *cx = &btc->cx; 3992 struct rtw89_btc_bt_info *bt = &cx->bt0; 3993 struct rtw89_btc_dm *dm = &btc->dm; 3994 u8 is_24g, is_56g, i; 3995 u32 scbd_bit; 3996 3997 /* 3998 * true: bt use Hi-LNA rx gain table (f/e/3/2) in -3x~-9xdBm for co-rx 3999 * false: bt use original rx gain table (f/b/7/3/2) 4000 */ 4001 4002 if (btc->dm.fdd_bind.bt_sel == BIT(BTC_BT_EXT)) 4003 return; 4004 4005 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) { 4006 scbd_bit = 0; 4007 if (i == BTC_BT_2ND) { 4008 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 4009 continue; 4010 bt = &cx->bt1; 4011 } 4012 4013 is_24g = (dm->corx_map[BTC_RF_S0][i] || 4014 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_2G); 4015 is_56g = (dm->corx_map[BTC_RF_S0][i] || 4016 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_5G); 4017 if (is_24g) 4018 scbd_bit |= BTC_WSCB_BT_HILNA; 4019 if (is_56g) 4020 scbd_bit |= BTC_WSCB_BT_HILNA_56G; 4021 4022 if ((is_24g && (en != (!!bt->hi_lna_rx))) || 4023 (is_56g && (en != (!!bt->hi_lna_rx_6g)))) 4024 _write_scbd(rtwdev, i, scbd_bit, en); 4025 } 4026 } 4027 4028 static void _set_rf_trx_para_v9(struct rtw89_dev *rtwdev) 4029 { 4030 struct rtw89_btc *btc = &rtwdev->btc; 4031 struct rtw89_btc_cx *cx = &btc->cx; 4032 struct rtw89_btc_wl_smap *wl_smap = &cx->wl.status.map; 4033 struct rtw89_btc_dm *dm = &btc->dm; 4034 bool bt_2r = false; 4035 u8 wl_stb_chg = 0; 4036 4037 if (wl_smap->rf_off || wl_smap->lps == BTC_LPS_RF_OFF) 4038 return; 4039 4040 /* must call after _set_halbb_btg_ctrl() */ 4041 if (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK) { 4042 wl_stb_chg = 1; 4043 if (dm->wl_btg_rx) 4044 bt_2r = true; 4045 } 4046 4047 _set_bt_corx_table(rtwdev, bt_2r); 4048 4049 if (wl_stb_chg != dm->wl_stb_chg) { 4050 dm->wl_stb_chg = wl_stb_chg; 4051 dm->ost_info.wl_btg_standby_chg = wl_stb_chg; 4052 rtwdev->chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 4053 } 4054 } 4055 4056 static void _set_rf_trx_para(struct rtw89_dev *rtwdev) 4057 { 4058 const struct rtw89_chip_info *chip = rtwdev->chip; 4059 struct rtw89_btc *btc = &rtwdev->btc; 4060 const struct rtw89_btc_ver *ver = btc->ver; 4061 struct rtw89_btc_dm *dm = &btc->dm; 4062 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4063 struct rtw89_btc_wl_role_info *r = &wl->role_info; 4064 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 4065 struct rtw89_btc_bt_link_info *b = &bt->link_info; 4066 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 4067 struct rtw89_btc_rf_trx_para_v9 para; 4068 u8 bmode = dm->tdd_bind.wl_link_mode; 4069 u8 rf_band = dm->tdd_bind.rf_band; 4070 u8 i, ul_para_num, dl_para_num; 4071 u8 mode = BTC_WLINK_NOLINK; 4072 u8 bid = BTC_BT_1ST, lv; 4073 u32 wl_stb_chg; 4074 4075 if (ver->fcxtrx == 9) { 4076 /* Early v9 need to assign UL/DL RF para at driver */ 4077 if (chip->rf_para_ulink_v9) { 4078 ul_para_num = chip->rf_para_ulink_num_v9; 4079 dl_para_num = chip->rf_para_dlink_num_v9; 4080 } else { 4081 _set_rf_trx_para_v9(rtwdev); 4082 return; 4083 } 4084 } else if ((ver->fcxtrx == 0 || ver->fcxtrx == 7 || ver->fcxtrx == 107) && 4085 chip->rf_para_ulink_v0) { 4086 ul_para_num = chip->rf_para_ulink_num_v0; 4087 dl_para_num = chip->rf_para_dlink_num_v0; 4088 } else { 4089 rtw89_warn(rtwdev, "[BTC]%s(), No rf_para for verseion %d\n", 4090 __func__, ver->fcxtrx); 4091 goto next; 4092 } 4093 4094 if (bmode == BTC_WLINK_NOLINK) { 4095 return; 4096 } else if (rf_band == RTW89_BAND_5G) { 4097 mode = BTC_WLINK_V0_5G; 4098 } else if (rf_band == RTW89_BAND_2G && bmode == BTC_WLINK_STA) { 4099 mode = BTC_WLINK_V0_2G_STA; 4100 } 4101 4102 /* decide trx_para_level */ 4103 if (btc->ant_type == BTC_ANT_SHARED) { 4104 /* fix LNA2 + TIA gain not change by GNT_BT */ 4105 if ((btc->dm.wl_btg_rx && b->link_cnt.now != 0) || 4106 dm->bt_only == 1) 4107 dm->trx_para_level = 1; /* for better BT ACI issue */ 4108 else 4109 dm->trx_para_level = 0; 4110 } else { /* non-shared antenna */ 4111 dm->trx_para_level = 5; 4112 /* modify trx_para if WK 2.4G-STA-DL + bt link */ 4113 if (b->link_cnt.now != 0 && 4114 mode == BTC_WLINK_V0_2G_STA && 4115 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */ 4116 if (wl->rssi_level == 4 && bt->rssi_level > 2) 4117 dm->trx_para_level = 6; 4118 else if (wl->rssi_level == 3 && bt->rssi_level > 3) 4119 dm->trx_para_level = 7; 4120 } 4121 } 4122 4123 lv = dm->trx_para_level; 4124 if (lv >= ul_para_num || 4125 lv >= dl_para_num) { 4126 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4127 "[BTC], %s(): invalid level_id: %d\n", 4128 __func__, lv); 4129 return; 4130 } 4131 4132 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4133 if (ver->fcxtrx == 9) { 4134 para = chip->rf_para_ulink_v9[lv]; 4135 } else { 4136 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 4137 para.wl_tx_power[i] = chip->rf_para_ulink_v0[lv].wl_tx_power; 4138 para.wl_rx_gain[i] = chip->rf_para_ulink_v0[lv].wl_rx_gain; 4139 } 4140 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) { 4141 para.bt_tx_power[i] = chip->rf_para_ulink_v0[lv].bt_tx_power; 4142 para.bt_rx_gain[i] = chip->rf_para_ulink_v0[lv].bt_rx_gain; 4143 } 4144 } 4145 } else { 4146 if (ver->fcxtrx == 9) { 4147 para = chip->rf_para_dlink_v9[lv]; 4148 } else { 4149 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 4150 para.wl_tx_power[i] = chip->rf_para_dlink_v0[lv].wl_tx_power; 4151 para.wl_rx_gain[i] = chip->rf_para_dlink_v0[lv].wl_rx_gain; 4152 } 4153 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) { 4154 para.bt_tx_power[i] = chip->rf_para_dlink_v0[lv].bt_tx_power; 4155 para.bt_rx_gain[i] = chip->rf_para_dlink_v0[lv].bt_rx_gain; 4156 } 4157 } 4158 } 4159 4160 if (dm->fddt_train) { 4161 _set_wl_rx_gain(rtwdev, 1, RTW89_PHY_0); 4162 _write_scbd(rtwdev, bid, BTC_WSCB_RXGAIN, true); 4163 } else { 4164 _set_wl_tx_power(rtwdev, para.wl_tx_power[RTW89_PHY_0], RTW89_PHY_0); 4165 _set_wl_rx_gain(rtwdev, para.wl_rx_gain[RTW89_PHY_0], RTW89_PHY_0); 4166 _set_bt_tx_power(rtwdev, true, bid, rf_band, para.bt_tx_power[BTC_BT_1ST]); 4167 _set_bt_rx_gain(rtwdev, true, bid, rf_band, para.bt_rx_gain[BTC_BT_1ST]); 4168 } 4169 4170 next: 4171 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off || 4172 wl_smap->lps == BTC_LPS_RF_OFF || mode == BTC_WLINK_V0_5G || 4173 (rtwdev->dbcc_en && r->dbcc_2g_phy != RTW89_PHY_1)) 4174 wl_stb_chg = 0; 4175 else 4176 wl_stb_chg = 1; 4177 4178 if (wl_stb_chg != dm->wl_stb_chg) { 4179 dm->wl_stb_chg = wl_stb_chg; 4180 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 4181 } 4182 } 4183 4184 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 4185 { 4186 struct rtw89_btc *btc = &rtwdev->btc; 4187 struct rtw89_btc_cx *cx = &btc->cx; 4188 struct rtw89_btc_wl_info *wl = &cx->wl; 4189 struct rtw89_btc_bt_info *bt = &cx->bt0; 4190 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4191 4192 if (wl->status.map.dhcp || wl->status.map._4way || 4193 wl->status.map.roaming || wl->status.map.transacting || 4194 wl->status.map.handshake) { 4195 cx->state_map = BTC_WLINKING; 4196 } else if (wl->status.map.scan) { /* wl scan */ 4197 if (bt_linfo->status.map.inq_pag) 4198 cx->state_map = BTC_WSCAN_BSCAN; 4199 else 4200 cx->state_map = BTC_WSCAN_BNOSCAN; 4201 } else if (wl->status.map.busy) { /* only busy */ 4202 if (bt_linfo->status.map.inq_pag) 4203 cx->state_map = BTC_WBUSY_BSCAN; 4204 else 4205 cx->state_map = BTC_WBUSY_BNOSCAN; 4206 } else { /* wl idle */ 4207 cx->state_map = BTC_WIDLE; 4208 } 4209 } 4210 4211 static u8 _get_wl_guard_bw(struct rtw89_dev *rtwdev, u8 index) 4212 { 4213 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4214 u8 guard_ch = rtwdev->chip->afh_guard_ch; 4215 u8 bw = 0; 4216 4217 /* default AFH channel sapn = center-ch +- 6MHz */ 4218 switch (index) { 4219 case RTW89_CHANNEL_WIDTH_20: 4220 if (dm->freerun || dm->fddt_train) 4221 bw = 48; 4222 else 4223 bw = 20 + guard_ch * 2; 4224 break; 4225 case RTW89_CHANNEL_WIDTH_40: 4226 bw = 40 + guard_ch * 2; 4227 break; 4228 case RTW89_CHANNEL_WIDTH_80: 4229 bw = 80 + guard_ch * 2; 4230 break; 4231 case RTW89_CHANNEL_WIDTH_160: 4232 case RTW89_CHANNEL_WIDTH_80_80: 4233 bw = 160 + guard_ch * 2; 4234 break; 4235 case RTW89_CHANNEL_WIDTH_320: 4236 bw = 320 + guard_ch * 2; 4237 break; 4238 case RTW89_CHANNEL_WIDTH_5: 4239 bw = 5 + guard_ch * 2; 4240 break; 4241 case RTW89_CHANNEL_WIDTH_10: 4242 bw = 10 + guard_ch * 2; 4243 break; 4244 default: 4245 bw = 0; 4246 break; 4247 } 4248 4249 return bw; 4250 } 4251 4252 static void _set_wl_ch_map(struct rtw89_dev *rtwdev) 4253 { 4254 struct rtw89_btc *btc = &rtwdev->btc; 4255 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4256 struct rtw89_btc_wl_afh_info *afh; 4257 u16 ch_start, ch_end, i; 4258 u8 b_group, b_pos; /* byte-group, bit-position */ 4259 u8 hwb; 4260 4261 if (wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].en && 4262 wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) { 4263 /* select wilder bw if 1+1 */ 4264 if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].bw > 4265 wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].bw) 4266 hwb = RTW89_MAC_1; 4267 else 4268 hwb = RTW89_MAC_0; 4269 } else if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) { 4270 hwb = RTW89_MAC_1; 4271 } else { 4272 hwb = RTW89_MAC_0; 4273 } 4274 4275 afh = &wl->afh_info[hwb][RTW89_BAND_2G]; 4276 4277 /* focus on WL 2.4GHz link */ 4278 if (!afh->en || afh->band != RTW89_BAND_2G) 4279 return; 4280 4281 memset(wl->ch_map, 0x0, sizeof(wl->ch_map)); 4282 memset(wl->ch_map_le, 0x0, sizeof(wl->ch_map_le)); 4283 4284 ch_start = afh->ch * 5 + 2407 - afh->bw / 2; 4285 ch_end = ch_start + afh->bw; 4286 4287 for (i = ch_start; i < ch_end; i++) { 4288 if (i < 2402 || i > 2480) 4289 continue; 4290 b_group = (i - 2402) / 8; 4291 b_pos = 7 - ((i - 2402) % 8); 4292 wl->ch_map[b_group] |= BIT(b_pos); 4293 4294 if (i % 2) /* BLE ch = even-freq (ex:2402,2404) */ 4295 continue; 4296 4297 b_group = (i - 2402) / 16; 4298 b_pos = 7 - (((i - 2402) / 2) % 8); 4299 wl->ch_map_le[b_group] |= BIT(b_pos); 4300 } 4301 } 4302 4303 static u8 _get_w2b_fbd_ch(struct rtw89_dev *rtwdev, 4304 u8 bt_fb_band, u32 wl_vco_freq, 4305 u32 *ch_lo_bound, u32 *ch_up_bound) 4306 { 4307 u32 ch_lo, ch_pup, ch_min, ch_max; 4308 u8 out_of_range = 0; 4309 s32 val_lo, val_up; 4310 u32 vco_lo_in_KHz; /* VCO pulling lower bound */ 4311 u32 vco_up_in_KHz; /* VCO pulling Upper bound */ 4312 u32 freq_start; 4313 4314 vco_lo_in_KHz = wl_vco_freq - BTC_VCO_GUARD_W2B * 1000; /* KHz */ 4315 vco_up_in_KHz = wl_vco_freq + BTC_VCO_GUARD_W2B * 1000; 4316 4317 switch (bt_fb_band) { 4318 default: 4319 case BTC_BT_B2G: /* BT 2GHz forbiddened Channel */ 4320 val_lo = vco_lo_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR; 4321 val_up = vco_up_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR; 4322 freq_start = BTC_FREQ_B2G * 1000; /* KHz */ 4323 ch_min = BTC_CH_B2G_MIN; 4324 ch_max = BTC_CH_B2G_MAX; 4325 break; 4326 case BTC_BT_B5G: /* BT 5/6GHz forbiddened Channel */ 4327 val_lo = vco_lo_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR; 4328 val_up = vco_up_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR; 4329 freq_start = BTC_FREQ_B6G * 1000; /* KHz */ 4330 ch_min = BTC_CH_B5G_MIN; 4331 ch_max = BTC_CH_B5G_MAX; 4332 break; 4333 } 4334 4335 /* Search forbiddened Channel (un-process range)*/ 4336 ch_lo = (val_lo - freq_start) / 1000; 4337 if ((val_lo - freq_start) % 1000 != 0) /* Round-UP */ 4338 ch_lo++; 4339 4340 ch_pup = (val_up - freq_start) / 1000; /* Round-down */ 4341 4342 /* Search forbiddened Channel */ 4343 if (ch_lo > ch_max || ch_pup < ch_min) { /* out-of-range -> NA */ 4344 out_of_range = 1; 4345 *ch_lo_bound = 0; 4346 *ch_up_bound = 0; 4347 } 4348 4349 if (ch_lo < ch_min) 4350 *ch_lo_bound = ch_min; 4351 else if (ch_lo <= ch_max) 4352 *ch_lo_bound = ch_lo; 4353 4354 if (ch_pup > ch_max) 4355 *ch_up_bound = ch_max; 4356 else if (ch_pup >= ch_min) 4357 *ch_up_bound = ch_pup; 4358 4359 if (bt_fb_band == BTC_BT_B5G) { /* BT ch is 8MHz-spacing for 5/6GHz */ 4360 *ch_lo_bound = *ch_lo_bound / 8; /* low-bound -> Round-down */ 4361 4362 if (*ch_up_bound % 8 != 0) /* Up-bound -> cover wider range */ 4363 *ch_up_bound = *ch_up_bound / 8 + 1; 4364 else 4365 *ch_up_bound = *ch_up_bound / 8; 4366 } 4367 4368 return out_of_range; 4369 } 4370 4371 static void _set_wl_ch_info(struct rtw89_dev *rtwdev) 4372 { 4373 static const u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 4374 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4375 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 4376 struct rtw89_btc_wl_info *wl = &cx->wl; 4377 u32 vco_freq, ch_lo = 0, ch_up = 0; 4378 u16 rf_band, freq, f_diff; 4379 u8 i, j, ch; 4380 4381 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) /* only new-PTA require setup */ 4382 return; 4383 4384 for (i = RTW89_PHY_0; i <= RTW89_PHY_1; i++) { 4385 if (wl->mlo_info.wmode[i] == RTW89_MR_WMODE_NONE) { /* no-connect */ 4386 dm->ost_info.rf_center_freq[i] = 0; 4387 dm->ost_info.fbd_group_en[i][0] = 0; 4388 dm->ost_info.fbd_group_en[i][1] = 0; 4389 dm->ost_info.fbd_group_bound[i][0] = 0; 4390 dm->ost_info.fbd_group_bound[i][1] = 0; 4391 continue; 4392 } 4393 4394 ch = wl->rf_ch_info[i].center_ch; 4395 switch (wl->rf_ch_info[i].band) { 4396 case RTW89_BAND_2G: 4397 default: 4398 rf_band = 0; 4399 if (ch == 14) 4400 freq = BTC_FREQ_W2G_CH14; 4401 else 4402 freq = BTC_FREQ_W2G + (ch - 1) * 5; 4403 vco_freq = freq * 1000 * BTC_LO_2G_NMR / BTC_LO_2G_DNM; 4404 break; 4405 case RTW89_BAND_5G: 4406 rf_band = BIT(15); 4407 freq = BTC_FREQ_W5G + (ch - 1) * 5; 4408 vco_freq = freq * 1000 * BTC_LO_5G_NMR / BTC_LO_5G_DNM; 4409 break; 4410 case RTW89_BAND_6G: 4411 rf_band = BIT(15); 4412 freq = BTC_FREQ_W6G + (ch - 1) * 5; 4413 vco_freq = freq * 1000 * BTC_LO_6G_NMR / BTC_LO_6G_DNM; 4414 break; 4415 } 4416 4417 dm->ost_info.rf_center_freq[i] = rf_band + freq; 4418 4419 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) { 4420 /* no WL->BT forbidden channel */ 4421 if (_get_w2b_fbd_ch(rtwdev, j, vco_freq, &ch_lo, &ch_up)) { 4422 dm->ost_info.fbd_group_en[i][j] = j << 1; 4423 dm->ost_info.fbd_group_bound[i][j] = 0; 4424 continue; 4425 } 4426 4427 dm->ost_info.fbd_group_en[i][j] = (j << 1) + 0x1; 4428 dm->ost_info.fbd_group_bound[i][j] = (ch_up << 8) + ch_lo; 4429 } 4430 } 4431 4432 for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) { 4433 for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) { 4434 /* 4435 * If WL & BT share same ANT/Path, set freq-diff > 2GHz, 4436 * because TDD will always run in 5/6GHz band. 4437 * Otherwise, the frq-diff thres is decided by the RF 4438 * out-of-channel rejection capability. 4439 */ 4440 if (dm->ant_xmap[i][j]) 4441 f_diff = 0x7ff; /* 2047MHz */ 4442 else 4443 f_diff = rtwdev->chip->fdd_iso_freq; 4444 4445 dm->ost_info.freq_diff_thres[path_hwb[i]][j] = f_diff; 4446 } 4447 } 4448 } 4449 4450 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 4451 { 4452 struct rtw89_btc *btc = &rtwdev->btc; 4453 struct rtw89_btc_cx *cx = &btc->cx; 4454 struct rtw89_btc_wl_info *wl = &cx->wl; 4455 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4456 struct rtw89_btc_wl_rlink *rlink; 4457 u8 h2c_func, hwb, bt_link_chg; 4458 u8 i, j, sz, bw; 4459 u8 buf[4]; 4460 4461 if (btc->manual_ctrl || wl->status.map.rf_off || 4462 (wl->status.val & btc_scanning_map.val)) 4463 return; 4464 4465 memset(wl->afh_info, 0, sizeof(wl->afh_info)); 4466 4467 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) { 4468 /* skip HW-Band if no fdd/fdd bind */ 4469 if ((!(btc->dm.tdd_bind.wl_hwb_sel & BIT(j))) && 4470 (!(btc->dm.fdd_bind.wl_hwb_sel & BIT(j)))) 4471 continue; 4472 4473 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 4474 rlink = &wl_rinfo->rlink[i][j]; 4475 4476 /* Skip no-active case */ 4477 if (!rlink->connected || !rlink->active || 4478 rlink->rf_band >= RTW89_BAND_NUM) 4479 continue; 4480 4481 /* In addition to AP/P2P, skip if same-rf-band*/ 4482 if (wl->afh_info[j][rlink->rf_band].en && 4483 (rlink->role != RTW89_WIFI_ROLE_AP && 4484 rlink->role != RTW89_WIFI_ROLE_P2P_GO && 4485 rlink->role != RTW89_WIFI_ROLE_P2P_CLIENT)) 4486 continue; 4487 4488 bw = _get_wl_guard_bw(rtwdev, rlink->bw); 4489 wl->afh_info[j][rlink->rf_band].en = 1; 4490 wl->afh_info[j][rlink->rf_band].ch = rlink->ch; 4491 wl->afh_info[j][rlink->rf_band].bw = bw; 4492 wl->afh_info[j][rlink->rf_band].band = rlink->rf_band; 4493 } 4494 } 4495 4496 for (j = RTW89_BAND_2G; j < RTW89_BAND_NUM; j++) { 4497 /* skip non-2.4GHz if BT is 2.4GHz only*/ 4498 if (!(rtwdev->chip->para_ver & BTC_FEAT_BT_6G)) { 4499 if (j != RTW89_BAND_2G) 4500 continue; 4501 sz = 3; 4502 } else { 4503 sz = 4; 4504 } 4505 4506 if (wl->afh_info[RTW89_MAC_0][j].en && 4507 wl->afh_info[RTW89_MAC_1][j].en) { 4508 /* select wilder bw if 1+1 */ 4509 if (wl->afh_info[RTW89_MAC_1][j].bw > 4510 wl->afh_info[RTW89_MAC_0][j].bw) 4511 hwb = RTW89_MAC_1; 4512 else 4513 hwb = RTW89_MAC_0; 4514 } else if (wl->afh_info[RTW89_MAC_1][j].en) { 4515 hwb = RTW89_MAC_1; 4516 } else { 4517 hwb = RTW89_MAC_0; 4518 } 4519 4520 if (j == RTW89_BAND_2G) { 4521 if (cx->bt0.link_info.link_cnt.chg || 4522 cx->bt1.link_info.link_cnt.chg) 4523 bt_link_chg = 1; 4524 else 4525 bt_link_chg = 0; 4526 } else { 4527 if (cx->bt0.link_info_56g.link_cnt.chg || 4528 cx->bt1.link_info_56g.link_cnt.chg) 4529 bt_link_chg = 1; 4530 else 4531 bt_link_chg = 0; 4532 } 4533 4534 /* return if no-afh-info-change/no wl-bt link change */ 4535 if (!memcmp(&wl->afh_info_last[hwb][j], 4536 &wl->afh_info[hwb][j], 4537 sizeof(struct rtw89_btc_wl_afh_info)) && 4538 !bt_link_chg && 4539 !wl->link_mode_chg) 4540 continue; 4541 4542 memcpy(&wl->afh_info_last[hwb][j], 4543 &wl->afh_info[hwb][j], 4544 sizeof(struct rtw89_btc_wl_afh_info)); 4545 4546 buf[0] = wl->afh_info[hwb][j].en; 4547 buf[1] = wl->afh_info[hwb][j].ch; 4548 buf[2] = wl->afh_info[hwb][j].bw; 4549 buf[3] = wl->afh_info[hwb][j].band; 4550 4551 h2c_func = SET_BT_WL_CH_INFO; 4552 if (cx->bt0.enable.now) 4553 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz); 4554 4555 /* send mailbox to 2nd-BT if exist */ 4556 if (cx->bt1.enable.now) { 4557 h2c_func |= BT_H2C_FUNC_BT2ND; 4558 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz); 4559 } 4560 4561 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4562 "[BTC], %s(): en=%d, ch=%d, bw=%d, rf_band=%d\n", 4563 __func__, buf[0], buf[1], buf[2], buf[3]); 4564 4565 wl->wcnt[BTC_WCNT_CH_UPDATE]++; 4566 4567 /* ToDo: Remove if BT update new-define to support 6GHz */ 4568 if (j == RTW89_BAND_2G) 4569 break; 4570 } 4571 4572 /* for AFH map display in coex log */ 4573 _set_wl_ch_map(rtwdev); 4574 4575 /* set HWB center-ch/forbidden group to ost_info for CR setup in FW */ 4576 _set_wl_ch_info(rtwdev); 4577 } 4578 4579 static bool _check_freerun(struct rtw89_dev *rtwdev) 4580 { 4581 struct rtw89_btc *btc = &rtwdev->btc; 4582 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4583 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 4584 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4585 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4586 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 4587 struct rtw89_btc_module *md = &btc->mdinfo; 4588 4589 if (btc->ant_type == BTC_ANT_SHARED) { 4590 btc->dm.trx_para_level = 0; 4591 return false; 4592 } 4593 4594 /* The below is dedicated antenna case */ 4595 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) { 4596 btc->dm.trx_para_level = 5; 4597 return true; 4598 } 4599 4600 if (bt_linfo->link_cnt.now == 0) { 4601 btc->dm.trx_para_level = 5; 4602 return true; 4603 } 4604 4605 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 4606 btc->dm.trx_para_level = 5; 4607 return true; 4608 } 4609 4610 /* TODO get isolation by BT psd */ 4611 if (md->ant.isolation >= BTC_FREERUN_ANTISO_MIN) { 4612 btc->dm.trx_para_level = 5; 4613 return true; 4614 } 4615 4616 if (!wl->status.map.busy) {/* wl idle -> freerun */ 4617 btc->dm.trx_para_level = 5; 4618 return true; 4619 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 4620 btc->dm.trx_para_level = 0; 4621 return false; 4622 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4623 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 4624 btc->dm.trx_para_level = 6; 4625 return true; 4626 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 4627 btc->dm.trx_para_level = 7; 4628 return true; 4629 } 4630 btc->dm.trx_para_level = 0; 4631 return false; 4632 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 4633 if (bt_linfo->rssi > 28) { 4634 btc->dm.trx_para_level = 6; 4635 return true; 4636 } 4637 } 4638 4639 btc->dm.trx_para_level = 0; 4640 return false; 4641 } 4642 4643 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 4644 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 4645 #define _tdma_set_rxflctrl(btc, rxflc) ({(btc)->dm.tdma.rxflctrl = rxflc; }) 4646 #define _tdma_set_txflctrl(btc, txflc) ({(btc)->dm.tdma.txflctrl = txflc; }) 4647 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 4648 4649 struct btc_btinfo_lb2 { 4650 u8 connect: 1; 4651 u8 sco_busy: 1; 4652 u8 inq_pag: 1; 4653 u8 acl_busy: 1; 4654 u8 hfp: 1; 4655 u8 hid: 1; 4656 u8 a2dp: 1; 4657 u8 pan: 1; 4658 }; 4659 4660 struct btc_btinfo_lb3 { 4661 u8 retry: 4; 4662 u8 cqddr: 1; 4663 u8 inq: 1; 4664 u8 mesh_busy: 1; 4665 u8 pag: 1; 4666 }; 4667 4668 struct btc_btinfo_hb0 { 4669 s8 rssi; 4670 }; 4671 4672 struct btc_btinfo_hb1 { 4673 u8 ble_connect: 1; 4674 u8 reinit: 1; 4675 u8 relink: 1; 4676 u8 igno_wl: 1; 4677 u8 voice: 1; 4678 u8 ble_scan: 1; 4679 u8 role_sw: 1; 4680 u8 multi_link: 1; 4681 }; 4682 4683 struct btc_btinfo_hb2 { 4684 u8 pan_active: 1; 4685 u8 afh_update: 1; 4686 u8 a2dp_active: 1; 4687 u8 slave: 1; 4688 u8 hid_slot: 2; 4689 u8 hid_cnt: 2; 4690 }; 4691 4692 struct btc_btinfo_hb3 { 4693 u8 a2dp_bitpool: 6; 4694 u8 tx_3m: 1; 4695 u8 a2dp_sink: 1; 4696 }; 4697 4698 union btc_btinfo { 4699 u8 val; 4700 struct btc_btinfo_lb2 lb2; 4701 struct btc_btinfo_lb3 lb3; 4702 struct btc_btinfo_hb0 hb0; 4703 struct btc_btinfo_hb1 hb1; 4704 struct btc_btinfo_hb2 hb2; 4705 struct btc_btinfo_hb3 hb3; 4706 }; 4707 4708 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 4709 enum btc_reason_and_action action) 4710 { 4711 const struct rtw89_chip_info *chip = rtwdev->chip; 4712 4713 chip->ops->btc_set_policy(rtwdev, policy_type); 4714 _fw_set_policy(rtwdev, policy_type, action); 4715 } 4716 4717 static void _set_tdma_bind(struct rtw89_dev *rtwdev, bool tdma_on) 4718 { 4719 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4720 struct rtw89_btc_bind_info *bind; 4721 u8 null_role = RTW89_WIFI_ROLE_STATION; 4722 u8 bt_sel; 4723 4724 if (dm->tdd_en) 4725 bind = &dm->tdd_bind; /* tdd = 1 && fdd = 0 or 1 */ 4726 else 4727 bind = &dm->fdd_bind; /* tdd = 0 && fdd = 1 */ 4728 4729 if (bind->bt_sel >= (BIT(BTC_BT_1ST) | BIT(BTC_BT_2ND))) 4730 bt_sel = BTC_ALL_BT; 4731 else if (bind->bt_sel == BIT(BTC_BT_2ND)) 4732 bt_sel = BTC_BT_2ND; 4733 else 4734 bt_sel = BTC_BT_1ST; 4735 4736 /* notify BT TDMA on/off by scoreboard for ACL/Scan schedule */ 4737 _write_scbd(rtwdev, bt_sel, BTC_WSCB_TDMA, tdma_on); 4738 4739 /* 4740 * set hwb/bt bind to TDMA policy parameter 4741 * FW-BTC will setup related hwbx vs. BTx coex tables by slot toggle 4742 * ex: HWb0 + BT0 + BT1, HWB0-BT0/HWB0-BT1 coex by WL/BT slot toggle 4743 */ 4744 dm->tdma.bind = ((bind->bt_sel & 0xf) << 4) + (bind->wl_hwb_sel & 0x3); 4745 if (dm->tdd_en) 4746 dm->tdma.bind |= BIT(2); 4747 if (dm->fdd_en) 4748 dm->tdma.bind |= BIT(3); 4749 if (rtwdev->btc.ver->fcxtdma != 8) 4750 dm->tdma.bind |= 0; 4751 4752 /* set Null-tx role for 2 HW-BAND TDMA (MLMR) */ 4753 if (!dm->eslot_ctrl.en && dm->tdma.rxflctrl && 4754 (bind->wl_hwb_sel == (BIT(RTW89_PHY_1) | BIT(RTW89_PHY_0)))) { 4755 null_role = (null_role << 4) + null_role; 4756 _tdma_set_flctrl_role(&rtwdev->btc, null_role); 4757 } 4758 } 4759 4760 #define BTC_B1_MAX 250 /* unit ms */ 4761 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 4762 { 4763 struct rtw89_btc *btc = &rtwdev->btc; 4764 struct rtw89_btc_dm *dm = &btc->dm; 4765 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 4766 u8 type; 4767 u32 tbl_w1, tbl_b1, tbl_b4; 4768 bool tdma_on = false; 4769 4770 if (btc->ant_type == BTC_ANT_SHARED) { 4771 if (btc->cx.wl.status.map._4way) 4772 tbl_w1 = cxtbl[1]; 4773 else 4774 tbl_w1 = cxtbl[8]; 4775 tbl_b1 = cxtbl[3]; 4776 tbl_b4 = cxtbl[3]; 4777 } else { 4778 tbl_w1 = cxtbl[16]; 4779 tbl_b1 = cxtbl[17]; 4780 tbl_b4 = cxtbl[17]; 4781 } 4782 4783 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 4784 btc->bt_req_en = false; 4785 4786 switch (type) { 4787 case BTC_CXP_USERDEF0: 4788 *t = t_def[CXTD_OFF]; 4789 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4790 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4791 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 4792 btc->update_policy_force = true; 4793 break; 4794 case BTC_CXP_OFF: /* TDMA off */ 4795 tdma_on = false; 4796 *t = t_def[CXTD_OFF]; 4797 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4798 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4799 4800 switch (policy_type) { 4801 case BTC_CXP_OFF_BT: 4802 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 4803 break; 4804 case BTC_CXP_OFF_WL: 4805 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 4806 break; 4807 case BTC_CXP_OFF_EQ0: 4808 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 4809 break; 4810 case BTC_CXP_OFF_EQ1: 4811 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 4812 break; 4813 case BTC_CXP_OFF_EQ2: 4814 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 4815 break; 4816 case BTC_CXP_OFF_EQ3: 4817 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 4818 break; 4819 case BTC_CXP_OFF_BWB0: 4820 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 4821 break; 4822 case BTC_CXP_OFF_BWB1: 4823 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 4824 break; 4825 case BTC_CXP_OFF_BWB3: 4826 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 4827 break; 4828 } 4829 break; 4830 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 4831 tdma_on = false; 4832 *t = t_def[CXTD_OFF_B2]; 4833 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4834 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4835 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO); 4836 4837 switch (policy_type) { 4838 case BTC_CXP_OFFB_BWB0: 4839 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 4840 break; 4841 case BTC_CXP_OFFB_BWB1: 4842 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 4843 break; 4844 case BTC_CXP_OFFB_BWB2: 4845 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 4846 break; 4847 case BTC_CXP_OFFB_BWB3: 4848 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 4849 break; 4850 case BTC_CXP_OFFB_BWB4: 4851 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 4852 break; 4853 } 4854 break; 4855 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 4856 btc->bt_req_en = true; 4857 tdma_on = true; 4858 *t = t_def[CXTD_OFF_EXT]; 4859 switch (policy_type) { 4860 case BTC_CXP_OFFE_DEF: 4861 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 4862 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 4863 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4864 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4865 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4866 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4867 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 4868 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 4869 break; 4870 case BTC_CXP_OFFE_DEF2: 4871 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 4872 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4873 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4874 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4875 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4876 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 4877 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 4878 break; 4879 } 4880 break; 4881 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 4882 tdma_on = true; 4883 *t = t_def[CXTD_FIX]; 4884 switch (policy_type) { 4885 case BTC_CXP_FIX_TD3030: 4886 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4887 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4888 break; 4889 case BTC_CXP_FIX_TD5050: 4890 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4891 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 4892 break; 4893 case BTC_CXP_FIX_TD2030: 4894 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4895 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4896 break; 4897 case BTC_CXP_FIX_TD4010: 4898 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 4899 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4900 break; 4901 case BTC_CXP_FIX_TD4010ISO: 4902 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 4903 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4904 break; 4905 case BTC_CXP_FIX_TD4010ISO_DL: 4906 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 4907 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 4908 break; 4909 case BTC_CXP_FIX_TD4010ISO_UL: 4910 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 4911 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 4912 break; 4913 case BTC_CXP_FIX_TD7010: 4914 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 4915 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4916 break; 4917 case BTC_CXP_FIX_TD2060: 4918 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4919 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4920 break; 4921 case BTC_CXP_FIX_TD3060: 4922 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4923 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4924 break; 4925 case BTC_CXP_FIX_TD2080: 4926 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4927 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 4928 break; 4929 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 4930 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4931 tbl_w1, SLOT_ISO); 4932 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4933 tbl_b1, SLOT_MIX); 4934 break; 4935 } 4936 break; 4937 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 4938 tdma_on = true; 4939 *t = t_def[CXTD_PFIX]; 4940 if (btc->cx.wl.role_info.role_map & BIT(RTW89_WIFI_ROLE_AP)) 4941 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 4942 4943 switch (policy_type) { 4944 case BTC_CXP_PFIX_TD3030: 4945 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4946 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4947 break; 4948 case BTC_CXP_PFIX_TD5050: 4949 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4950 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 4951 break; 4952 case BTC_CXP_PFIX_TD2030: 4953 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4954 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4955 break; 4956 case BTC_CXP_PFIX_TD2060: 4957 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4958 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4959 break; 4960 case BTC_CXP_PFIX_TD3070: 4961 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4962 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4963 break; 4964 case BTC_CXP_PFIX_TD2080: 4965 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4966 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 4967 break; 4968 } 4969 break; 4970 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 4971 tdma_on = true; 4972 *t = t_def[CXTD_AUTO]; 4973 switch (policy_type) { 4974 case BTC_CXP_AUTO_TD50B1: 4975 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4976 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4977 break; 4978 case BTC_CXP_AUTO_TD60B1: 4979 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 4980 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4981 break; 4982 case BTC_CXP_AUTO_TD20B1: 4983 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4984 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4985 break; 4986 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 4987 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4988 tbl_w1, SLOT_ISO); 4989 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4990 tbl_b1, SLOT_MIX); 4991 break; 4992 } 4993 break; 4994 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 4995 tdma_on = true; 4996 *t = t_def[CXTD_PAUTO]; 4997 switch (policy_type) { 4998 case BTC_CXP_PAUTO_TD50B1: 4999 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5000 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5001 break; 5002 case BTC_CXP_PAUTO_TD60B1: 5003 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5004 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5005 break; 5006 case BTC_CXP_PAUTO_TD20B1: 5007 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5008 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5009 break; 5010 case BTC_CXP_PAUTO_TDW1B1: 5011 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5012 tbl_w1, SLOT_ISO); 5013 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5014 tbl_b1, SLOT_MIX); 5015 break; 5016 } 5017 break; 5018 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 5019 tdma_on = true; 5020 *t = t_def[CXTD_AUTO2]; 5021 switch (policy_type) { 5022 case BTC_CXP_AUTO2_TD3050: 5023 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5024 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5025 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5026 break; 5027 case BTC_CXP_AUTO2_TD3070: 5028 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5029 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5030 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5031 break; 5032 case BTC_CXP_AUTO2_TD5050: 5033 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5034 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5035 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5036 break; 5037 case BTC_CXP_AUTO2_TD6060: 5038 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5039 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5040 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5041 break; 5042 case BTC_CXP_AUTO2_TD2080: 5043 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5044 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5045 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5046 break; 5047 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 5048 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5049 tbl_w1, SLOT_ISO); 5050 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5051 tbl_b4, SLOT_MIX); 5052 break; 5053 } 5054 break; 5055 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 5056 tdma_on = true; 5057 *t = t_def[CXTD_PAUTO2]; 5058 switch (policy_type) { 5059 case BTC_CXP_PAUTO2_TD3050: 5060 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5061 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5062 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5063 break; 5064 case BTC_CXP_PAUTO2_TD3070: 5065 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5066 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5067 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5068 break; 5069 case BTC_CXP_PAUTO2_TD5050: 5070 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5071 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5072 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5073 break; 5074 case BTC_CXP_PAUTO2_TD6060: 5075 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5076 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5077 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5078 break; 5079 case BTC_CXP_PAUTO2_TD2080: 5080 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5081 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5082 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5083 break; 5084 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 5085 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5086 tbl_w1, SLOT_ISO); 5087 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5088 tbl_b4, SLOT_MIX); 5089 break; 5090 } 5091 break; 5092 } 5093 _set_tdma_bind(rtwdev, tdma_on); 5094 } 5095 EXPORT_SYMBOL(rtw89_btc_set_policy); 5096 5097 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 5098 { 5099 struct rtw89_btc *btc = &rtwdev->btc; 5100 struct rtw89_btc_dm *dm = &btc->dm; 5101 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 5102 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 5103 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt0.link_info.hid_desc; 5104 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt0.link_info.hfp_desc; 5105 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5106 u8 type, null_role; 5107 u32 tbl_w1, tbl_b1, tbl_b4; 5108 bool tdma_on = false; 5109 u16 dur_1 = 0, dur_2; 5110 5111 if (wl->status.map.lps) { 5112 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 5113 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 5114 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5115 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5116 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5117 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5118 } 5119 5120 type = FIELD_GET(BTC_CXP_MASK, policy_type); 5121 5122 if (btc->ant_type == BTC_ANT_SHARED) { 5123 if (btc->cx.wl.status.map._4way) 5124 tbl_w1 = cxtbl[1]; 5125 else if (hid->exist && hid->type == BTC_HID_218) 5126 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 5127 else 5128 tbl_w1 = cxtbl[8]; 5129 5130 if (dm->leak_ap && 5131 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 5132 tbl_b1 = cxtbl[3]; 5133 tbl_b4 = cxtbl[3]; 5134 } else if (hid->exist && hid->type == BTC_HID_218) { 5135 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 5136 tbl_b4 = cxtbl[4]; 5137 } else { 5138 tbl_b1 = cxtbl[2]; 5139 tbl_b4 = cxtbl[2]; 5140 } 5141 } else { 5142 tbl_b1 = cxtbl[17]; 5143 tbl_b4 = cxtbl[17]; 5144 5145 if (wl->bg_mode) 5146 tbl_w1 = cxtbl[8]; 5147 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) && 5148 hid->exist) 5149 tbl_w1 = cxtbl[19]; 5150 else 5151 tbl_w1 = cxtbl[16]; 5152 } 5153 5154 switch (type) { 5155 case BTC_CXP_USERDEF0: 5156 btc->update_policy_force = true; 5157 *t = t_def[CXTD_OFF]; 5158 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5159 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5160 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5161 break; 5162 case BTC_CXP_OFF: /* TDMA off */ 5163 tdma_on = false; 5164 *t = t_def[CXTD_OFF]; 5165 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5166 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5167 5168 switch (policy_type) { 5169 case BTC_CXP_OFF_BT: 5170 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5171 break; 5172 case BTC_CXP_OFF_WL: 5173 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 5174 break; 5175 case BTC_CXP_OFF_WL2: 5176 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 5177 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 5178 break; 5179 case BTC_CXP_OFF_EQ0: 5180 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 5181 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 5182 break; 5183 case BTC_CXP_OFF_EQ1: 5184 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 5185 break; 5186 case BTC_CXP_OFF_EQ2: 5187 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 5188 break; 5189 case BTC_CXP_OFF_EQ3: 5190 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); 5191 break; 5192 case BTC_CXP_OFF_EQ4: 5193 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); 5194 break; 5195 case BTC_CXP_OFF_EQ5: 5196 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); 5197 break; 5198 case BTC_CXP_OFF_BWB0: 5199 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5200 break; 5201 case BTC_CXP_OFF_BWB1: 5202 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5203 break; 5204 case BTC_CXP_OFF_BWB2: 5205 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 5206 break; 5207 case BTC_CXP_OFF_BWB3: 5208 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5209 break; 5210 default: 5211 break; 5212 } 5213 break; 5214 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 5215 tdma_on = false; 5216 *t = t_def[CXTD_OFF_B2]; 5217 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5218 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5219 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO); 5220 5221 switch (policy_type) { 5222 case BTC_CXP_OFFB_BWB0: 5223 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5224 break; 5225 case BTC_CXP_OFFB_BWB1: 5226 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5227 break; 5228 case BTC_CXP_OFFB_BWB2: 5229 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 5230 break; 5231 case BTC_CXP_OFFB_BWB3: 5232 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5233 break; 5234 case BTC_CXP_OFFB_BWB4: 5235 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5236 break; 5237 } 5238 break; 5239 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 5240 tdma_on = true; 5241 *t = t_def[CXTD_OFF_EXT]; 5242 5243 /* To avoid wl-s0 tx break by hid/hfp tx */ 5244 if (hid->exist || hfp->exist) 5245 tbl_w1 = cxtbl[16]; 5246 5247 if (dm->eslot_ctrl.en) { 5248 null_role = u8_encode_bits(dm->eslot_ctrl.nulltx_role1, 0x0f) | 5249 u8_encode_bits(dm->eslot_ctrl.nulltx_role2, 0xf0); 5250 _tdma_set_flctrl_role(btc, null_role); 5251 _tdma_set_rxflctrl(btc, 1); 5252 _tdma_set_txflctrl(btc, 1); 5253 /* Set Null-Tx time-tick by E2G duration */ 5254 dm->eslot_ctrl.nulltx_pre_time = 5; /* TODO: BIS COEX */ 5255 dur_1 = dm->eslot_ctrl.nulltx_pre_time; 5256 } 5257 5258 dur_2 = dm->e2g_slot_limit; 5259 5260 switch (policy_type) { 5261 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */ 5262 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_ISO); 5263 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5264 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5265 _slot_set_dur(btc, CXST_EBT, dur_2); 5266 break; 5267 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */ 5268 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_ISO); 5269 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5270 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5271 _slot_set_dur(btc, CXST_EBT, dur_2); 5272 break; 5273 case BTC_CXP_OFFE_DEF: 5274 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 5275 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 5276 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5277 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5278 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5279 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5280 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5281 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5282 _slot_set_dur(btc, CXST_EBT, dur_2); 5283 break; 5284 case BTC_CXP_OFFE_DEF2: 5285 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 5286 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5287 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5288 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5289 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5290 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5291 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5292 _slot_set_dur(btc, CXST_EBT, dur_2); 5293 break; 5294 case BTC_CXP_OFFE_2GBWMIXB: 5295 if (a2dp->exist) 5296 _slot_set(btc, CXST_E2G, dur_1, cxtbl[2], SLOT_MIX); 5297 else 5298 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_MIX); 5299 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40), 5300 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5301 _slot_set_dur(btc, CXST_EBT, dur_2); 5302 break; 5303 case BTC_CXP_OFFE_WL: /* for 4-way */ 5304 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_MIX); 5305 _slot_set(btc, CXST_EBT, dur_1, cxtbl[1], SLOT_MIX); 5306 break; 5307 default: 5308 break; 5309 } 5310 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5311 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5312 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5313 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5314 break; 5315 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 5316 tdma_on = true; 5317 *t = t_def[CXTD_FIX]; 5318 5319 switch (policy_type) { 5320 case BTC_CXP_FIX_TD3030: 5321 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5322 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5323 break; 5324 case BTC_CXP_FIX_TD5050: 5325 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5326 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5327 break; 5328 case BTC_CXP_FIX_TD2030: 5329 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5330 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5331 break; 5332 case BTC_CXP_FIX_TD4010: 5333 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 5334 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5335 break; 5336 case BTC_CXP_FIX_TD4010ISO: 5337 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 5338 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5339 break; 5340 case BTC_CXP_FIX_TD4010ISO_DL: 5341 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 5342 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 5343 break; 5344 case BTC_CXP_FIX_TD4010ISO_UL: 5345 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 5346 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 5347 break; 5348 case BTC_CXP_FIX_TD7010: 5349 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 5350 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5351 break; 5352 case BTC_CXP_FIX_TD2060: 5353 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5354 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5355 break; 5356 case BTC_CXP_FIX_TD3060: 5357 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5358 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5359 break; 5360 case BTC_CXP_FIX_TD2080: 5361 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5362 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5363 break; 5364 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 5365 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5366 tbl_w1, SLOT_ISO); 5367 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5368 tbl_b1, SLOT_MIX); 5369 break; 5370 default: 5371 break; 5372 } 5373 break; 5374 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 5375 tdma_on = true; 5376 *t = t_def[CXTD_PFIX]; 5377 5378 switch (policy_type) { 5379 case BTC_CXP_PFIX_TD3030: 5380 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5381 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5382 break; 5383 case BTC_CXP_PFIX_TD5050: 5384 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5385 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5386 break; 5387 case BTC_CXP_PFIX_TD2030: 5388 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5389 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5390 break; 5391 case BTC_CXP_PFIX_TD2060: 5392 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5393 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5394 break; 5395 case BTC_CXP_PFIX_TD3070: 5396 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5397 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5398 break; 5399 case BTC_CXP_PFIX_TD2080: 5400 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5401 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5402 break; 5403 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 5404 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5405 tbl_w1, SLOT_ISO); 5406 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5407 tbl_b1, SLOT_MIX); 5408 break; 5409 default: 5410 break; 5411 } 5412 break; 5413 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 5414 tdma_on = true; 5415 *t = t_def[CXTD_AUTO]; 5416 5417 switch (policy_type) { 5418 case BTC_CXP_AUTO_TD50B1: 5419 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5420 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5421 break; 5422 case BTC_CXP_AUTO_TD60B1: 5423 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5424 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5425 break; 5426 case BTC_CXP_AUTO_TD20B1: 5427 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5428 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5429 break; 5430 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 5431 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5432 tbl_w1, SLOT_ISO); 5433 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5434 tbl_b1, SLOT_MIX); 5435 break; 5436 default: 5437 break; 5438 } 5439 break; 5440 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 5441 tdma_on = true; 5442 *t = t_def[CXTD_PAUTO]; 5443 5444 switch (policy_type) { 5445 case BTC_CXP_PAUTO_TD50B1: 5446 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5447 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5448 break; 5449 case BTC_CXP_PAUTO_TD60B1: 5450 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5451 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5452 break; 5453 case BTC_CXP_PAUTO_TD20B1: 5454 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5455 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5456 break; 5457 case BTC_CXP_PAUTO_TDW1B1: 5458 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5459 tbl_w1, SLOT_ISO); 5460 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5461 tbl_b1, SLOT_MIX); 5462 break; 5463 default: 5464 break; 5465 } 5466 break; 5467 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 5468 tdma_on = true; 5469 *t = t_def[CXTD_AUTO2]; 5470 5471 switch (policy_type) { 5472 case BTC_CXP_AUTO2_TD3050: 5473 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5474 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5475 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5476 break; 5477 case BTC_CXP_AUTO2_TD3070: 5478 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5479 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5480 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5481 break; 5482 case BTC_CXP_AUTO2_TD5050: 5483 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5484 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5485 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5486 break; 5487 case BTC_CXP_AUTO2_TD6060: 5488 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5489 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5490 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5491 break; 5492 case BTC_CXP_AUTO2_TD2080: 5493 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5494 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5495 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5496 break; 5497 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 5498 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5499 tbl_w1, SLOT_ISO); 5500 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5501 tbl_b1, SLOT_MIX); 5502 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5503 tbl_b4, SLOT_MIX); 5504 break; 5505 default: 5506 break; 5507 } 5508 break; 5509 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 5510 tdma_on = true; 5511 *t = t_def[CXTD_PAUTO2]; 5512 5513 switch (policy_type) { 5514 case BTC_CXP_PAUTO2_TD3050: 5515 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5516 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5517 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5518 break; 5519 case BTC_CXP_PAUTO2_TD3070: 5520 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5521 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5522 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5523 break; 5524 case BTC_CXP_PAUTO2_TD5050: 5525 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5526 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5527 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5528 break; 5529 case BTC_CXP_PAUTO2_TD6060: 5530 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5531 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5532 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5533 break; 5534 case BTC_CXP_PAUTO2_TD2080: 5535 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5536 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5537 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5538 break; 5539 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 5540 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5541 tbl_w1, SLOT_ISO); 5542 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5543 tbl_b1, SLOT_MIX); 5544 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5545 tbl_b4, SLOT_MIX); 5546 break; 5547 default: 5548 break; 5549 } 5550 break; 5551 } 5552 5553 /* enter leak_slot after each null-1 */ 5554 if (dm->leak_ap && dm->tdma.leak_n > 1) 5555 _tdma_set_lek(btc, 1); 5556 5557 if (dm->tdma_instant_excute || 5558 dm->error.map.tdma_no_sync || 5559 dm->error.map.slot_no_sync || 5560 dm->lps_ctrl_change) { 5561 btc->dm.tdma.option_ctrl |= BIT(0); 5562 btc->update_policy_force = true; 5563 } 5564 5565 if (btc->cli_h2c_cmd) 5566 btc->update_policy_force = true; 5567 5568 _set_tdma_bind(rtwdev, tdma_on); 5569 } 5570 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 5571 5572 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 5573 u8 tx_val, u8 rx_val) 5574 { 5575 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 5576 struct rtw89_mac_ax_plt plt; 5577 5578 plt.tx = tx_val; 5579 plt.rx = rx_val; 5580 5581 if (rtwdev->btc.ver->fwlrole == 8) { 5582 plt.band = wl->pta_req_mac; 5583 if (wl->bt_polut_type[plt.band] == tx_val) 5584 return; 5585 5586 wl->bt_polut_type[plt.band] = tx_val; 5587 rtw89_mac_cfg_plt(rtwdev, &plt); 5588 } else { 5589 plt.band = RTW89_MAC_0; 5590 5591 if (phy_map & BTC_PHY_0) 5592 rtw89_mac_cfg_plt(rtwdev, &plt); 5593 5594 if (!rtwdev->dbcc_en) 5595 return; 5596 5597 plt.band = RTW89_MAC_1; 5598 if (phy_map & BTC_PHY_1) 5599 rtw89_mac_cfg_plt(rtwdev, &plt); 5600 } 5601 } 5602 5603 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 5604 u8 phy_map, u8 type) 5605 { 5606 struct rtw89_btc *btc = &rtwdev->btc; 5607 struct rtw89_btc_cx *cx = &btc->cx; 5608 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5609 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5610 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type); 5611 struct rtw89_btc_dm *dm = &btc->dm; 5612 u8 gwl = BTC_GNT_HW, gwl0, gwl1, gbt; 5613 bool cx_ctrl; 5614 5615 if (btc->cli_h2c_cmd || wl_rinfo->dbcc_chg || 5616 dm->run_reason == BTC_RSN_NTFY_POWEROFF || 5617 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 5618 dm->run_reason == BTC_RSN_CMD_SET_COEX) 5619 force_exec = FC_EXEC; 5620 5621 if (wl_rinfo->link_mode != BTC_WLINK_DB_MCC && 5622 btc->dm.wl_btg_rx == 2) 5623 force_exec = FC_EXEC; 5624 5625 if (!force_exec && ant_path_type == dm->set_ant_path) { 5626 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5627 "[BTC], %s(): return by no change!!\n", 5628 __func__); 5629 return; 5630 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 5631 wl->rfk_info.state != BTC_WRFK_STOP) { 5632 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5633 "[BTC], %s(): return by wl rfk!!\n", __func__); 5634 return; 5635 } 5636 5637 dm->set_ant_path = ant_path_type; 5638 5639 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5640 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 5641 __func__, phy_map, dm->set_ant_path & 0xff); 5642 5643 switch (type) { 5644 case BTC_ANT_WPOWERON: 5645 cx_ctrl = BTC_CTRL_BY_BT; 5646 break; 5647 case BTC_ANT_WINIT: 5648 cx_ctrl = BTC_CTRL_BY_WL; 5649 /* To avoid BT MP driver case (bt_enable but no mailbox) */ 5650 if ((cx->bt0.enable.now && cx->bt0.run_patch_code) || 5651 (cx->bt1.enable.now && cx->bt1.run_patch_code)) 5652 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 5653 BTC_WLACT_SW_LO); 5654 else 5655 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5656 BTC_WLACT_SW_HI); 5657 break; 5658 case BTC_ANT_WONLY: 5659 cx_ctrl = BTC_CTRL_BY_WL; 5660 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5661 BTC_WLACT_SW_HI); 5662 break; 5663 case BTC_ANT_WOFF: 5664 cx_ctrl = BTC_CTRL_BY_BT; 5665 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 5666 BTC_WLACT_SW_LO); 5667 break; 5668 case BTC_ANT_PTA: 5669 default: 5670 cx_ctrl = BTC_CTRL_BY_WL; 5671 gbt = BTC_GNT_HW; 5672 if ((rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA) || 5673 !wl_rinfo->dbcc_en) { 5674 gwl = BTC_GNT_HW; 5675 _set_gnt(rtwdev, BTC_PHY_ALL, gwl, gbt, BTC_WLACT_HW); 5676 } else { 5677 /* for DBCC Only-1-PTA */ 5678 if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_0) { 5679 gwl0 = BTC_GNT_HW; 5680 gwl1 = BTC_GNT_SW_HI; 5681 } else { 5682 gwl0 = BTC_GNT_SW_HI; 5683 gwl1 = BTC_GNT_HW; 5684 } 5685 _set_gnt(rtwdev, BTC_PHY_0, gwl0, gbt, BTC_WLACT_HW); 5686 _set_gnt(rtwdev, BTC_PHY_1, gwl1, gbt, BTC_WLACT_HW); 5687 } 5688 break; 5689 case BTC_ANT_FDD: 5690 cx_ctrl = BTC_CTRL_BY_WL; 5691 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_HW, 5692 BTC_WLACT_HW); 5693 break; 5694 case BTC_ANT_FREERUN: 5695 cx_ctrl = BTC_CTRL_BY_WL; 5696 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_HI, 5697 BTC_WLACT_SW_LO); 5698 break; 5699 case BTC_ANT_WRFK: 5700 cx_ctrl = BTC_CTRL_BY_WL; 5701 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5702 BTC_WLACT_HW); 5703 break; 5704 case BTC_ANT_WRFK2: 5705 cx_ctrl = BTC_CTRL_BY_WL; 5706 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5707 BTC_WLACT_SW_HI); /* no BT-Tx */ 5708 break; 5709 } 5710 5711 rtw89_chip_cfg_ctrl_path(rtwdev, cx_ctrl); 5712 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 5713 } 5714 5715 static void _action_wl_only(struct rtw89_dev *rtwdev) 5716 { 5717 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 5718 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 5719 } 5720 5721 static void _action_wl_init(struct rtw89_dev *rtwdev) 5722 { 5723 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5724 5725 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 5726 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 5727 } 5728 5729 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode) 5730 { 5731 struct rtw89_btc *btc = &rtwdev->btc; 5732 struct rtw89_btc_dm *dm = &btc->dm; 5733 struct rtw89_btc_cx *cx = &btc->cx; 5734 struct rtw89_btc_wl_info *wl = &cx->wl; 5735 5736 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5737 5738 if (wl->status.map.rf_off || btc->dm.bt_only) 5739 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 5740 else if (wl->status.map.lps == BTC_LPS_RF_ON || 5741 cx->bt0.whql_test || cx->bt1.whql_test) 5742 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 5743 5744 if (dm->out_of_band) 5745 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF); 5746 else if (cx->bt0.whql_test || cx->bt1.whql_test) 5747 _set_policy(rtwdev, BTC_CXP_OFFB_BWB4, BTC_ACT_WL_OFF); 5748 else 5749 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 5750 } 5751 5752 static void _action_freerun(struct rtw89_dev *rtwdev) 5753 { 5754 struct rtw89_btc *btc = &rtwdev->btc; 5755 5756 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5757 5758 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 5759 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 5760 5761 btc->dm.freerun = true; 5762 } 5763 5764 static void _action_bt_whql(struct rtw89_dev *rtwdev) 5765 { 5766 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5767 5768 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5769 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 5770 } 5771 5772 static void _action_bt_off(struct rtw89_dev *rtwdev) 5773 { 5774 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5775 5776 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 5777 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 5778 } 5779 5780 static void _action_bt_idle(struct rtw89_dev *rtwdev) 5781 { 5782 struct rtw89_btc *btc = &rtwdev->btc; 5783 struct rtw89_btc_bt_link_info *b = &btc->cx.bt0.link_info; 5784 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5785 5786 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5787 5788 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5789 switch (btc->cx.state_map) { 5790 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 5791 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 5792 if (b->status.map.connect) 5793 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE); 5794 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 5795 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE); 5796 else 5797 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE); 5798 break; 5799 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 5800 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 5801 BTC_ACT_BT_IDLE); 5802 break; 5803 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 5804 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 5805 BTC_ACT_BT_IDLE); 5806 break; 5807 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 5808 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 5809 BTC_ACT_BT_IDLE); 5810 break; 5811 case BTC_WIDLE: /* wl-idle + bt-idle */ 5812 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 5813 break; 5814 } 5815 } else { /* dedicated-antenna */ 5816 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 5817 } 5818 } 5819 5820 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 5821 { 5822 struct rtw89_btc *btc = &rtwdev->btc; 5823 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5824 5825 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5826 5827 if (btc->ant_type == BTC_ANT_SHARED) { 5828 if (btc->cx.wl.status.map._4way) { 5829 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 5830 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 5831 btc->cx.bt0.scan_rx_low_pri = true; 5832 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 5833 } else { 5834 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 5835 } 5836 } else { 5837 if (wl->bg_mode) 5838 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 5839 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 5840 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP); 5841 else 5842 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 5843 } 5844 } 5845 5846 static void _action_bt_hid(struct rtw89_dev *rtwdev) 5847 { 5848 const struct rtw89_chip_info *chip = rtwdev->chip; 5849 struct rtw89_btc *btc = &rtwdev->btc; 5850 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5851 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 5852 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 5853 u16 policy_type = BTC_CXP_OFF_BT; 5854 5855 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5856 5857 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5858 if (wl->status.map._4way) { 5859 policy_type = BTC_CXP_OFF_WL; 5860 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 5861 btc->cx.bt0.scan_rx_low_pri = true; 5862 if (hid->type & BTC_HID_BLE) 5863 policy_type = BTC_CXP_OFF_BWB0; 5864 else 5865 policy_type = BTC_CXP_OFF_BWB2; 5866 } else if (hid->type == BTC_HID_218) { 5867 bt->scan_rx_low_pri = true; 5868 policy_type = BTC_CXP_OFF_BWB2; 5869 } else if (chip->para_ver == 0x1) { 5870 policy_type = BTC_CXP_OFF_BWB3; 5871 } else { 5872 policy_type = BTC_CXP_OFF_BWB1; 5873 } 5874 } else { /* dedicated-antenna */ 5875 if (wl->bg_mode) 5876 policy_type = BTC_CXP_OFF_BWB1; 5877 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 5878 policy_type = BTC_CXP_OFF_EQ4; 5879 else 5880 policy_type = BTC_CXP_OFF_EQ3; 5881 } 5882 5883 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 5884 } 5885 5886 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 5887 { 5888 struct rtw89_btc *btc = &rtwdev->btc; 5889 struct rtw89_btc_dm *dm = &btc->dm; 5890 5891 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5892 5893 dm->slot_dur[CXST_W1] = 20; 5894 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 5895 5896 switch (btc->cx.state_map) { 5897 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 5898 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 5899 break; 5900 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 5901 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 5902 break; 5903 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 5904 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 5905 break; 5906 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 5907 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 5908 if (btc->cx.wl.rfk_info.con_rfk) 5909 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP); 5910 else 5911 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP); 5912 break; 5913 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 5914 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 5915 break; 5916 } 5917 } 5918 5919 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 5920 { 5921 struct rtw89_btc *btc = &rtwdev->btc; 5922 5923 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5924 5925 switch (btc->cx.state_map) { 5926 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 5927 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 5928 break; 5929 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 5930 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 5931 break; 5932 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 5933 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 5934 break; 5935 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 5936 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 5937 break; 5938 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 5939 if (btc->cx.wl.rfk_info.con_rfk) 5940 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK); 5941 else 5942 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 5943 break; 5944 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 5945 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 5946 break; 5947 } 5948 } 5949 5950 static void _action_bt_pan(struct rtw89_dev *rtwdev) 5951 { 5952 struct rtw89_btc *btc = &rtwdev->btc; 5953 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 5954 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 5955 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 5956 5957 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5958 5959 switch (btc->cx.state_map) { 5960 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 5961 if (a2dp.active || !pan.exist) { 5962 btc->dm.slot_dur[CXST_W1] = 80; 5963 btc->dm.slot_dur[CXST_B1] = 20; 5964 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); 5965 } else { 5966 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 5967 } 5968 break; 5969 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 5970 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 5971 break; 5972 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 5973 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 5974 break; 5975 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 5976 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 5977 break; 5978 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 5979 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN); 5980 break; 5981 case BTC_WIDLE: /* wl-idle + bt-pan */ 5982 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 5983 break; 5984 } 5985 } 5986 5987 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 5988 { 5989 struct rtw89_btc *btc = &rtwdev->btc; 5990 struct rtw89_btc_dm *dm = &btc->dm; 5991 5992 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5993 5994 dm->slot_dur[CXST_W1] = 20; 5995 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 5996 5997 switch (btc->cx.state_map) { 5998 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 5999 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 6000 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 6001 break; 6002 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 6003 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID); 6004 break; 6005 6006 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 6007 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 6008 break; 6009 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 6010 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 6011 if (btc->cx.wl.rfk_info.con_rfk) 6012 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID); 6013 else 6014 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 6015 break; 6016 } 6017 } 6018 6019 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 6020 { 6021 struct rtw89_btc *btc = &rtwdev->btc; 6022 6023 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6024 6025 switch (btc->cx.state_map) { 6026 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 6027 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6028 break; 6029 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 6030 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6031 break; 6032 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 6033 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 6034 break; 6035 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 6036 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6037 break; 6038 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 6039 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 6040 break; 6041 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 6042 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 6043 break; 6044 } 6045 } 6046 6047 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 6048 { 6049 struct rtw89_btc *btc = &rtwdev->btc; 6050 6051 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6052 6053 switch (btc->cx.state_map) { 6054 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 6055 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 6056 break; 6057 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 6058 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 6059 break; 6060 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 6061 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 6062 break; 6063 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 6064 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 6065 break; 6066 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 6067 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 6068 break; 6069 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 6070 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 6071 break; 6072 } 6073 } 6074 6075 static void _action_bt_bis(struct rtw89_dev *rtwdev) 6076 { 6077 struct rtw89_btc *btc = &rtwdev->btc; 6078 struct rtw89_btc_dm *dm = &btc->dm; 6079 u16 policy_type; 6080 6081 if (dm->bis_tdma) 6082 policy_type = BTC_CXP_OFFE_2GBWISOB; 6083 else 6084 policy_type = BTC_CXP_OFF_EQ0; 6085 6086 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6087 _set_policy(rtwdev, policy_type, BTC_ACT_BT_BIS); 6088 } 6089 6090 static void _action_bt_cis(struct rtw89_dev *rtwdev) 6091 { 6092 struct rtw89_btc *btc = &rtwdev->btc; 6093 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 6094 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6095 struct rtw89_btc_dm *dm = &btc->dm; 6096 u16 policy_type; 6097 6098 if (bt_linfo->a2dp_desc.active) { 6099 dm->slot_dur[CXST_W1] = 80; 6100 dm->slot_dur[CXST_B1] = 20; 6101 policy_type = BTC_CXP_PFIX_TDW1B1; 6102 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 6103 policy_type = BTC_CXP_OFF_BWB0; 6104 } else { 6105 policy_type = BTC_CXP_OFF_BWB1; 6106 } 6107 6108 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6109 _set_policy(rtwdev, policy_type, BTC_ACT_BT_CIS); 6110 } 6111 6112 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 6113 { 6114 struct rtw89_btc *btc = &rtwdev->btc; 6115 6116 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6117 6118 switch (btc->cx.state_map) { 6119 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 6120 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 6121 BTC_ACT_BT_A2DP_PAN_HID); 6122 break; 6123 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 6124 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 6125 BTC_ACT_BT_A2DP_PAN_HID); 6126 break; 6127 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 6128 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 6129 BTC_ACT_BT_A2DP_PAN_HID); 6130 break; 6131 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 6132 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 6133 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 6134 BTC_ACT_BT_A2DP_PAN_HID); 6135 break; 6136 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 6137 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 6138 BTC_ACT_BT_A2DP_PAN_HID); 6139 break; 6140 } 6141 } 6142 6143 static void _action_wl_5g(struct rtw89_dev *rtwdev) 6144 { 6145 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_FDD); 6146 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 6147 } 6148 6149 static void _action_wl_other(struct rtw89_dev *rtwdev) 6150 { 6151 struct rtw89_btc *btc = &rtwdev->btc; 6152 6153 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6154 6155 if (btc->ant_type == BTC_ANT_SHARED) 6156 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 6157 else 6158 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 6159 } 6160 6161 static void _action_wl_nc(struct rtw89_dev *rtwdev) 6162 { 6163 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6164 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 6165 } 6166 6167 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 6168 { 6169 struct rtw89_btc *btc = &rtwdev->btc; 6170 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 6171 6172 if (rfk.state != BTC_WRFK_START) 6173 return; 6174 6175 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 6176 __func__, rfk.band); 6177 6178 btc->dm.tdma_instant_excute = 1; 6179 6180 if (rfk.state == BTC_WRFK_ONESHOT_START || 6181 btc->ant_type == BTC_ANT_SHARED) { 6182 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); 6183 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); 6184 } else { 6185 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 6186 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 6187 } 6188 } 6189 6190 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 6191 { 6192 struct rtw89_btc *btc = &rtwdev->btc; 6193 struct rtw89_btc_dm *dm = &btc->dm; 6194 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &dm->ost_info; 6195 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6196 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6197 const struct rtw89_chip_info *chip = rtwdev->chip; 6198 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6199 u32 is_btg = BTC_BTGCTRL_DISABLE; 6200 6201 if (btc->manual_ctrl) 6202 return; 6203 6204 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ 6205 if (btc->ant_type == BTC_ANT_SHARED) { 6206 if (!(bt->run_patch_code && bt->enable.now)) 6207 is_btg = BTC_BTGCTRL_DISABLE; 6208 else if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) || 6209 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) 6210 is_btg = BTC_BTGCTRL_ENABLE; 6211 else 6212 is_btg = BTC_BTGCTRL_DISABLE; 6213 6214 /* bb call ctrl_btg() in WL FW by slot */ 6215 if (!btc->ver->fcxosi && 6216 wl_rinfo->link_mode == BTC_WLINK_DB_MCC) 6217 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; 6218 } 6219 6220 if (is_btg == dm->wl_btg_rx) 6221 return; 6222 else 6223 dm->wl_btg_rx = is_btg; 6224 6225 /* skip setup if btg_ctrl set by wl fw */ 6226 if (!btc->ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE) 6227 return; 6228 6229 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */ 6230 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 6231 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 6232 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE; 6233 else 6234 o_info->btg_rx[BTC_RF_S0] = is_btg; 6235 6236 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 6237 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE; 6238 else 6239 o_info->btg_rx[BTC_RF_S1] = is_btg; 6240 } else { /* 2+0 or 0+2 */ 6241 o_info->btg_rx[BTC_RF_S0] = is_btg; 6242 o_info->btg_rx[BTC_RF_S1] = is_btg; 6243 } 6244 6245 if (btc->ver->fcxosi) 6246 return; 6247 6248 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0], 6249 RTW89_PHY_0); 6250 if (chip->chip_id != RTL8922A) 6251 return; 6252 6253 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1], 6254 RTW89_PHY_1); 6255 } 6256 6257 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) 6258 { 6259 struct rtw89_btc *btc = &rtwdev->btc; 6260 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; 6261 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 6262 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6263 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 6264 const struct rtw89_chip_info *chip = rtwdev->chip; 6265 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6266 struct rtw89_btc_dm *dm = &btc->dm; 6267 u8 is_preagc, val; 6268 6269 if (btc->manual_ctrl) 6270 return; 6271 6272 if (!(bt->run_patch_code && bt->enable.now)) { 6273 is_preagc = BTC_PREAGC_DISABLE; 6274 } else if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) { 6275 is_preagc = BTC_PREAGC_DISABLE; 6276 } else if (rinfo->link_mode == BTC_WLINK_NOLINK || 6277 btc->cx.bt0.link_info.link_cnt.now == 0) { 6278 is_preagc = BTC_PREAGC_DISABLE; 6279 } else if (dm->tdma_now.type != CXTDMA_OFF && 6280 !bt_linfo->hfp_desc.exist && 6281 !bt_linfo->hid_desc.exist && 6282 dm->fddt_train == BTC_FDDT_DISABLE) { 6283 is_preagc = BTC_PREAGC_DISABLE; 6284 } else if (rinfo->dbcc_en && (rinfo->dbcc_2g_phy != RTW89_PHY_1)) { 6285 is_preagc = BTC_PREAGC_DISABLE; 6286 } else if (btc->ant_type == BTC_ANT_SHARED) { 6287 is_preagc = BTC_PREAGC_DISABLE; 6288 } else { 6289 is_preagc = BTC_PREAGC_ENABLE; 6290 } 6291 6292 if (!btc->ver->fcxosi && rinfo->link_mode == BTC_WLINK_DB_MCC) 6293 is_preagc = BTC_PREAGC_BB_FWCTRL; 6294 6295 if (dm->wl_pre_agc_rb != dm->wl_pre_agc && 6296 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { 6297 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); 6298 dm->wl_pre_agc_rb = val; 6299 } 6300 6301 if ((wl->coex_mode == BTC_MODE_NORMAL && 6302 (dm->run_reason == BTC_RSN_NTFY_INIT || 6303 dm->run_reason == BTC_RSN_NTFY_SWBAND || 6304 dm->wl_pre_agc_rb != dm->wl_pre_agc)) || 6305 is_preagc != dm->wl_pre_agc) { 6306 dm->wl_pre_agc = is_preagc; 6307 6308 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE) 6309 return; 6310 6311 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 6312 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 6313 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE; 6314 else 6315 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 6316 6317 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 6318 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE; 6319 else 6320 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 6321 6322 } else { /* 2+0 or 0+2 */ 6323 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 6324 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 6325 } 6326 6327 if (btc->ver->fcxosi) 6328 return; 6329 6330 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0], 6331 RTW89_PHY_0); 6332 if (chip->chip_id != RTL8922A) 6333 return; 6334 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1], 6335 RTW89_PHY_1); 6336 } 6337 } 6338 6339 struct rtw89_txtime_data { 6340 struct rtw89_dev *rtwdev; 6341 int type; 6342 u32 tx_time; 6343 u8 tx_retry; 6344 u16 enable; 6345 bool reenable; 6346 }; 6347 6348 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, 6349 struct rtw89_sta_link *rtwsta_link, 6350 struct rtw89_txtime_data *iter_data) 6351 { 6352 struct rtw89_dev *rtwdev = iter_data->rtwdev; 6353 struct rtw89_btc *btc = &rtwdev->btc; 6354 struct rtw89_btc_cx *cx = &btc->cx; 6355 struct rtw89_btc_wl_info *wl = &cx->wl; 6356 struct rtw89_btc_wl_link_info *plink = NULL; 6357 u8 port = rtwvif_link->port; 6358 u32 tx_time = iter_data->tx_time; 6359 u8 tx_retry = iter_data->tx_retry; 6360 u16 enable = iter_data->enable; 6361 bool reenable = iter_data->reenable; 6362 6363 plink = &wl->rlink_info[port][rtwsta_link->link_id]; 6364 6365 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6366 "[BTC], %s(): port = %d\n", __func__, port); 6367 6368 if (!plink->connected) { 6369 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6370 "[BTC], %s(): connected = %d\n", 6371 __func__, plink->connected); 6372 return; 6373 } 6374 6375 /* backup the original tx time before tx-limit on */ 6376 if (reenable) { 6377 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); 6378 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); 6379 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6380 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 6381 __func__, plink->tx_time, plink->tx_retry); 6382 } 6383 6384 /* restore the original tx time if no tx-limit */ 6385 if (!enable) { 6386 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); 6387 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, 6388 plink->tx_retry); 6389 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6390 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 6391 __func__, plink->tx_time, plink->tx_retry); 6392 6393 } else { 6394 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); 6395 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); 6396 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6397 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 6398 __func__, tx_time, tx_retry); 6399 } 6400 } 6401 6402 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 6403 { 6404 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 6405 struct rtw89_txtime_data *iter_data = 6406 (struct rtw89_txtime_data *)data; 6407 struct rtw89_vif_link *rtwvif_link; 6408 struct rtw89_sta_link *rtwsta_link; 6409 unsigned int link_id; 6410 6411 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 6412 rtwvif_link = rtwsta_link->rtwvif_link; 6413 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); 6414 } 6415 } 6416 6417 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 6418 { 6419 struct rtw89_btc *btc = &rtwdev->btc; 6420 struct rtw89_btc_cx *cx = &btc->cx; 6421 struct rtw89_btc_dm *dm = &btc->dm; 6422 struct rtw89_btc_wl_info *wl = &cx->wl; 6423 struct rtw89_btc_bt_info *bt = &cx->bt0; 6424 struct rtw89_btc_bt_link_info *b = &bt->link_info; 6425 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 6426 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 6427 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6428 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 6429 bool reenable = false; 6430 u8 tx_retry; 6431 u32 tx_time; 6432 u16 enable; 6433 6434 if (btc->manual_ctrl) 6435 return; 6436 6437 if (btc->dm.freerun || btc->ctrl.igno_bt || b->link_cnt.now == 0 || 6438 dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G) || 6439 wl_rinfo->link_mode == BTC_WLINK_NOLINK) { 6440 enable = 0; 6441 tx_time = BTC_MAX_TX_TIME_DEF; 6442 tx_retry = BTC_MAX_TX_RETRY_DEF; 6443 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 6444 enable = 1; 6445 tx_time = BTC_MAX_TX_TIME_L2; 6446 tx_retry = BTC_MAX_TX_RETRY_L1; 6447 } else if (hfp->exist || hid->exist) { 6448 enable = 1; 6449 tx_time = BTC_MAX_TX_TIME_L3; 6450 tx_retry = BTC_MAX_TX_RETRY_L1; 6451 } else { 6452 enable = 0; 6453 tx_time = BTC_MAX_TX_TIME_DEF; 6454 tx_retry = BTC_MAX_TX_RETRY_DEF; 6455 } 6456 6457 if (dm->wl_tx_limit.enable == enable && 6458 dm->wl_tx_limit.tx_time == tx_time && 6459 dm->wl_tx_limit.tx_retry == tx_retry) 6460 return; 6461 6462 if (!dm->wl_tx_limit.enable && enable) 6463 reenable = true; 6464 6465 dm->wl_tx_limit.enable = enable; 6466 dm->wl_tx_limit.tx_time = tx_time; 6467 dm->wl_tx_limit.tx_retry = tx_retry; 6468 6469 data.enable = enable; 6470 data.tx_time = tx_time; 6471 data.tx_retry = tx_retry; 6472 data.reenable = reenable; 6473 6474 ieee80211_iterate_stations_atomic(rtwdev->hw, 6475 rtw89_tx_time_iter, 6476 &data); 6477 } 6478 6479 static void _set_phl_bt_slot_req(struct rtw89_dev *rtwdev) 6480 { 6481 struct rtw89_btc *btc = &rtwdev->btc; 6482 struct rtw89_btc_cx *cx = &btc->cx; 6483 struct rtw89_btc_wl_info *wl = &cx->wl; 6484 struct rtw89_btc_dm *dm = &btc->dm; 6485 u8 len = 0; 6486 u8 i; 6487 6488 /* don't change bt slot req state during RFK for p2p/mcc case */ 6489 if (dm->run_reason == BTC_RSN_NTFY_WL_RFK || 6490 wl->status.map.transacting) 6491 return; 6492 6493 /* enable bt-slot req if ext-slot-control */ 6494 if (dm->tdma_now.type == CXTDMA_OFF && 6495 dm->tdma_now.ext_ctrl == CXECTL_EXT && 6496 dm->tdd_bind.bt_sel != 0) { 6497 if (btc->cx.wl.status.val & btc_scanning_map.val) 6498 btc->bt_req_en = false; 6499 else 6500 btc->bt_req_en = true; 6501 } else { 6502 btc->bt_req_en = false; 6503 } 6504 6505 if (dm->slot_req_more) { 6506 len = BTC_BSLOT_A2DP_HID; 6507 } else { 6508 if (dm->tdd_bind.bt_link_weight >= BTC_BSLOT_A2DP_HID) 6509 len = BTC_BSLOT_A2DP_HID; 6510 else if (dm->tdd_bind.bt_link_weight <= BTC_BSLOT_IDLE) 6511 len = BTC_BSLOT_IDLE; 6512 else 6513 len = dm->tdd_bind.bt_link_weight; 6514 } 6515 6516 if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) 6517 len = 100 - len; 6518 6519 if (!btc->bt_req_en) 6520 len = 0; 6521 6522 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 6523 if (!(dm->tdd_bind.wl_hwb_sel & BIT(i))) 6524 continue; 6525 6526 if (len == btc->bt_req_len[i]) 6527 continue; 6528 6529 btc->bt_req_len[i] = len; 6530 6531 rtw89_core_ntfy_btc_event(rtwdev, 6532 RTW89_BTC_HMSG_SET_BT_REQ_SLOT, i); 6533 6534 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6535 "[BTC], %s(): HWB%d bt_req_len = %d\n", 6536 __func__, i, btc->bt_req_len[i]); 6537 } 6538 } 6539 6540 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 6541 { 6542 struct rtw89_btc *btc = &rtwdev->btc; 6543 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6544 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6545 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6546 bool bt_hi_lna_rx = false; 6547 6548 if (wl_rinfo->link_mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 6549 bt_hi_lna_rx = true; 6550 6551 if (bt_hi_lna_rx == bt->hi_lna_rx) 6552 return; 6553 6554 _write_scbd(rtwdev, BTC_BT_1ST, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 6555 } 6556 6557 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 6558 { 6559 struct rtw89_btc *btc = &rtwdev->btc; 6560 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6561 6562 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_RXSCAN_PRI, 6563 (bool)(!!bt->scan_rx_low_pri)); 6564 } 6565 6566 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) 6567 { 6568 struct rtw89_btc *btc = &rtwdev->btc; 6569 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6570 struct rtw89_btc_dm *dm = &btc->dm; 6571 u32 add; 6572 6573 if (mac == wl->pta_req_mac) 6574 return; 6575 6576 dm->ost_info.pta_req_hw_band = mac; 6577 wl->pta_req_mac = mac; 6578 wl->pta_reg_mac_chg = true; 6579 6580 if (btc->ver->fcxosi) 6581 return; 6582 6583 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) 6584 add = R_BE_BTC_CFG; 6585 else 6586 add = R_AX_BTC_CFG; 6587 6588 if (mac == RTW89_MAC_0) 6589 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC); 6590 else 6591 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC); 6592 } 6593 6594 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev) 6595 { 6596 struct rtw89_btc *btc = &rtwdev->btc; 6597 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a; 6598 u8 link_mode_chg = btc->cx.wl.link_mode_chg; 6599 u8 mode = btc->cx.wl.role_info.link_mode; 6600 6601 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && !link_mode_chg) 6602 return; 6603 6604 if (!(btc->mdinfo.wa_type & BTC_WA_HFP_ZB)) 6605 return; 6606 6607 if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G) || 6608 rtwdev->btc.dm.freerun) { 6609 zb_tbl0 = 0xffffffff; 6610 zb_tbl1 = 0xffffffff; 6611 } else if (mode == BTC_WLINK_DB_MCC) { 6612 zb_tbl0 = 0xffffffff; /* for E5G slot */ 6613 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */ 6614 } 6615 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0); 6616 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1); 6617 } 6618 6619 static void _set_fw_report_map(struct rtw89_dev *rtwdev) 6620 { 6621 struct rtw89_btc *btc = &rtwdev->btc; 6622 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map; 6623 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 6624 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 6625 u32 rpt_map = btc->fwinfo.rpt_en_map; 6626 u32 bt_rom_code_id, bt_fw_ver; 6627 bool bt_ver_unknown = false; 6628 u32 bitmap; 6629 6630 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) { 6631 rtw89_btc_fw_en_rpt(rtwdev, false, 0); 6632 return; 6633 } 6634 6635 rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_MREG); 6636 6637 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_SCAN_INFO); 6638 if ((bt0->run_patch_code && bt0->enable.now) || 6639 (bt1->run_patch_code && bt1->enable.now)) 6640 rpt_map |= bitmap; 6641 else 6642 rpt_map &= ~bitmap; 6643 6644 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id); 6645 bt_fw_ver = bt0->ver_info.fw & 0xffff; 6646 if (bt_fw_ver == 0 || 6647 (bt_fw_ver == bt_rom_code_id && bt0->run_patch_code)) 6648 bt_ver_unknown = true; 6649 6650 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_VER_INFO); 6651 if (bt0->enable.now && bt_ver_unknown) 6652 rpt_map |= bitmap; 6653 else 6654 rpt_map &= ~bitmap; 6655 6656 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP) | 6657 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP_LE) | 6658 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_TX_PWR_LVL); 6659 if (bt0->link_info.link_cnt.now || 6660 bt0->link_info_56g.link_cnt.now || 6661 bt1->link_info.link_cnt.now || 6662 bt1->link_info_56g.link_cnt.now) 6663 rpt_map |= bitmap; 6664 else 6665 rpt_map &= ~bitmap; 6666 6667 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_DEVICE_INFO); 6668 if ((bt0->link_info.a2dp_desc.exist && 6669 bt0->link_info.a2dp_desc.play_latency) || 6670 (bt1->link_info.a2dp_desc.exist && 6671 bt1->link_info.a2dp_desc.play_latency)) 6672 rpt_map |= bitmap; 6673 else 6674 rpt_map &= ~bitmap; 6675 6676 rtw89_btc_fw_en_rpt(rtwdev, false, rpt_map); 6677 } 6678 6679 static void _action_common(struct rtw89_dev *rtwdev) 6680 { 6681 struct rtw89_btc *btc = &rtwdev->btc; 6682 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6683 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 6684 struct rtw89_btc_dm *dm = &btc->dm; 6685 u8 i; 6686 6687 _wl_req_mac(rtwdev, rinfo->pta_req_band); 6688 _update_zb_coex_tbl(rtwdev); 6689 _set_btg_ctrl(rtwdev); 6690 _set_wl_preagc_ctrl(rtwdev); 6691 _set_wl_tx_limit(rtwdev); 6692 _set_phl_bt_slot_req(rtwdev); 6693 _set_bt_afh_info(rtwdev); 6694 _set_bt_rx_agc(rtwdev); 6695 _set_rf_trx_para(rtwdev); 6696 _set_bt_rx_scan_pri(rtwdev); 6697 _set_fw_report_map(rtwdev); 6698 6699 if (dm->run_reason == BTC_RSN_NTFY_INIT || 6700 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 6701 dm->run_reason == BTC_RSN_NTFY_POWEROFF) 6702 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6703 6704 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) 6705 _sned_h2c_w2bscbd(rtwdev, false, i); 6706 6707 if (btc->ver->fcxosi) { 6708 if (memcmp(&dm->ost_info_last, &dm->ost_info, 6709 sizeof(dm->ost_info_last)) || 6710 dm->run_reason == BTC_RSN_NTFY_INIT || 6711 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) { 6712 dm->ost_info_last = dm->ost_info; 6713 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI); 6714 } 6715 } 6716 dm->tdma_instant_excute = 0; 6717 dm->lps_ctrl_change = false; 6718 wl->role_info.link_mode_chg = 0; 6719 wl->pta_reg_mac_chg = false; 6720 dm->pre_agc_chg = false; 6721 wl->dbcc_chg = 0; 6722 } 6723 6724 static void _action_by_bt(struct rtw89_dev *rtwdev) 6725 { 6726 struct rtw89_btc *btc = &rtwdev->btc; 6727 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6728 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 6729 struct rtw89_btc_bt_leaudio_desc leaudio = bt_linfo->leaudio_desc; 6730 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 6731 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 6732 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 6733 struct rtw89_btc_dm *dm = &btc->dm; 6734 u8 profile_map = 0; 6735 6736 if (dm->freerun_chk) { 6737 _action_freerun(rtwdev); 6738 return; 6739 } 6740 6741 if (bt_linfo->hfp_desc.exist) 6742 profile_map |= BTC_BT_HFP; 6743 6744 if (bt_linfo->hid_desc.exist) 6745 profile_map |= BTC_BT_HID; 6746 6747 if (bt_linfo->a2dp_desc.exist) 6748 profile_map |= BTC_BT_A2DP; 6749 6750 if (bt_linfo->pan_desc.exist) 6751 profile_map |= BTC_BT_PAN; 6752 6753 if (leaudio.bis_exist) 6754 profile_map |= BTC_BT_BIS; 6755 6756 if (leaudio.cis_exist) 6757 profile_map |= BTC_BT_CIS; 6758 6759 switch (profile_map) { 6760 case BTC_BT_NOPROFILE: 6761 if (pan.active) 6762 _action_bt_pan(rtwdev); 6763 else 6764 _action_bt_idle(rtwdev); 6765 break; 6766 case BTC_BT_HFP: 6767 _action_bt_hfp(rtwdev); 6768 break; 6769 case BTC_BT_HFP | BTC_BT_HID: 6770 case BTC_BT_HID: 6771 _action_bt_hid(rtwdev); 6772 break; 6773 case BTC_BT_A2DP: 6774 if (a2dp.sink) 6775 _action_bt_a2dpsink(rtwdev); 6776 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 6777 _action_bt_a2dp_pan(rtwdev); 6778 else 6779 _action_bt_a2dp(rtwdev); 6780 break; 6781 case BTC_BT_PAN: 6782 _action_bt_pan(rtwdev); 6783 break; 6784 case BTC_BT_BIS: 6785 _action_bt_bis(rtwdev); 6786 break; 6787 case BTC_BT_CIS: 6788 case BTC_BT_CIS | BTC_BT_HID: 6789 _action_bt_cis(rtwdev); 6790 break; 6791 case BTC_BT_A2DP | BTC_BT_HFP: 6792 case BTC_BT_A2DP | BTC_BT_HID: 6793 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 6794 if (a2dp.sink) 6795 _action_bt_a2dpsink(rtwdev); 6796 else if (pan.active) 6797 _action_bt_a2dp_pan_hid(rtwdev); 6798 else 6799 _action_bt_a2dp_hid(rtwdev); 6800 break; 6801 case BTC_BT_A2DP | BTC_BT_PAN: 6802 if (a2dp.sink) 6803 _action_bt_a2dpsink(rtwdev); 6804 else 6805 _action_bt_a2dp_pan(rtwdev); 6806 break; 6807 case BTC_BT_PAN | BTC_BT_HFP: 6808 case BTC_BT_PAN | BTC_BT_HID: 6809 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 6810 _action_bt_pan_hid(rtwdev); 6811 break; 6812 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 6813 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 6814 default: 6815 if (a2dp.sink) 6816 _action_bt_a2dpsink(rtwdev); 6817 else 6818 _action_bt_a2dp_pan_hid(rtwdev); 6819 break; 6820 } 6821 } 6822 6823 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 6824 { 6825 _action_by_bt(rtwdev); 6826 } 6827 6828 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 6829 { 6830 struct rtw89_btc *btc = &rtwdev->btc; 6831 u16 policy_type = BTC_CXP_OFF_BT; 6832 6833 if (btc->ant_type == BTC_ANT_SHARED) { 6834 if (btc->cx.wl.status.map._4way) 6835 policy_type = BTC_CXP_OFFE_WL; 6836 else if (btc->cx.wl.status.val & btc_scanning_map.val) 6837 policy_type = BTC_CXP_OFFE_2GBWMIXB; 6838 else if (btc->cx.bt0.link_info.status.map.connect == 0) 6839 policy_type = BTC_CXP_OFFE_2GISOB; 6840 else 6841 policy_type = BTC_CXP_OFFE_2GBWISOB; 6842 } else { /* dedicated-antenna */ 6843 policy_type = BTC_CXP_OFF_EQ0; 6844 } 6845 6846 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF; 6847 6848 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 6849 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC); 6850 } 6851 6852 static void _action_wl_scan(struct rtw89_dev *rtwdev) 6853 { 6854 struct rtw89_btc *btc = &rtwdev->btc; 6855 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6856 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6857 6858 if (btc->cx.state_map != BTC_WLINKING && 6859 btc->ctrl.wl_ctrl_info.fw_scan) { 6860 _action_wl_25g_mcc(rtwdev); 6861 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 6862 } else if (rtwdev->dbcc_en) { 6863 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 6864 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 6865 _action_wl_5g(rtwdev); 6866 else 6867 _action_by_bt(rtwdev); 6868 } else { 6869 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 6870 _action_wl_5g(rtwdev); 6871 else 6872 _action_by_bt(rtwdev); 6873 } 6874 } 6875 6876 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 6877 { struct rtw89_btc *btc = &rtwdev->btc; 6878 6879 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6880 6881 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6882 if (btc->cx.bt0.link_info.link_cnt.now == 0) 6883 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 6884 BTC_ACT_WL_2G_MCC); 6885 else 6886 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 6887 BTC_ACT_WL_2G_MCC); 6888 } else { /* dedicated-antenna */ 6889 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 6890 } 6891 } 6892 6893 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 6894 { 6895 struct rtw89_btc *btc = &rtwdev->btc; 6896 struct rtw89_btc_dm *dm = &btc->dm; 6897 u16 policy_type; 6898 6899 if (!dm->tdd_bind.bt_smap.connect) 6900 policy_type = BTC_CXP_OFFE_2GISOB; 6901 else 6902 policy_type = BTC_CXP_OFFE_2GBWISOB; 6903 6904 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6905 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 6906 } 6907 6908 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 6909 { 6910 struct rtw89_btc *btc = &rtwdev->btc; 6911 6912 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6913 6914 if (btc->ant_type == BTC_ANT_SHARED) { 6915 if (btc->cx.bt0.link_info.link_cnt.now == 0) 6916 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 6917 BTC_ACT_WL_2G_AP); 6918 else 6919 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 6920 } else {/* dedicated-antenna */ 6921 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 6922 } 6923 } 6924 6925 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 6926 { 6927 struct rtw89_btc *btc = &rtwdev->btc; 6928 6929 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6930 6931 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6932 if (btc->cx.bt0.link_info.link_cnt.now == 0) 6933 _set_policy(rtwdev, 6934 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 6935 else 6936 _set_policy(rtwdev, 6937 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 6938 } else { /* dedicated-antenna */ 6939 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 6940 } 6941 } 6942 6943 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 6944 { 6945 struct rtw89_btc *btc = &rtwdev->btc; 6946 6947 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6948 6949 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6950 _action_by_bt(rtwdev); 6951 } else {/* dedicated-antenna */ 6952 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 6953 } 6954 } 6955 6956 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 6957 { 6958 struct rtw89_btc *btc = &rtwdev->btc; 6959 6960 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6961 6962 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6963 if (btc->cx.bt0.link_info.link_cnt.now == 0) 6964 _set_policy(rtwdev, 6965 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 6966 else 6967 _set_policy(rtwdev, 6968 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 6969 } else { /* dedicated-antenna */ 6970 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 6971 } 6972 } 6973 6974 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid) 6975 { 6976 struct rtw89_btc *btc = &rtwdev->btc; 6977 struct rtw89_btc_cx *cx = &btc->cx; 6978 struct rtw89_btc_wl_info *wl = &cx->wl; 6979 u8 cnt_idx = BTC_WCNT_SCBDUPDATE; 6980 u8 h2c_func = SET_IOFLD_SCBD; 6981 u8 buf[4]; 6982 6983 if (bid == BTC_BT_2ND) { 6984 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 6985 return 0; 6986 6987 h2c_func |= BT_H2C_FUNC_BT2ND; 6988 cnt_idx = BTC_WCNT_SCBDUPDATE2; 6989 } 6990 6991 if (wl->scbd_chg[bid] || force_exec) { 6992 /* Add delay to avoid BT FW loss information */ 6993 6994 btc_dw2b(buf, 0, (wl->scbd[bid] | BIT(31))); /* trig */ 6995 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) { 6996 if (!_send_fw_cmd(rtwdev, BTFC_SET, 6997 h2c_func, buf, sizeof(buf))) 6998 return 0; 6999 } else { 7000 rtw89_mac_cfg_sb(rtwdev, wl->scbd[bid]); 7001 } 7002 wl->scbd_chg[bid] = 0; 7003 wl->wcnt[cnt_idx]++; 7004 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7005 "[BTC], %s() write BT%d scbd:0x%08x\n", 7006 __func__, bid, wl->scbd[bid]); 7007 } 7008 return 1; 7009 } 7010 7011 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state) 7012 { 7013 const struct rtw89_chip_info *chip = rtwdev->chip; 7014 struct rtw89_btc *btc = &rtwdev->btc; 7015 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7016 struct rtw89_btc_dm *dm = &btc->dm; 7017 u8 force_exec, id, id_start, id_stop; 7018 u32 scbd = 0; 7019 7020 if (!chip->scbd) 7021 return; 7022 7023 if (bid == BTC_ALL_BT) { 7024 id_start = BTC_BT_1ST; 7025 id_stop = BTC_BT_2ND; 7026 } else { 7027 id_start = bid; 7028 id_stop = bid; 7029 } 7030 7031 for (id = id_start; id <= id_stop; id++) { 7032 force_exec = false; 7033 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && 7034 id == BTC_BT_2ND) 7035 continue; 7036 7037 if (state) 7038 scbd = wl->scbd[id] | val; 7039 else 7040 scbd = wl->scbd[id] & (~val); 7041 7042 if (val & BTC_WSCB_CTCODE || 7043 val & BTC_WSCB_RXGAIN || 7044 val & BTC_WSCB_RXGAIN_56G) { /* instant exec */ 7045 force_exec = true; 7046 wl->scbd[id] = scbd; 7047 dm->scbd_write_instant = 1; 7048 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) 7049 _sned_h2c_w2bscbd(rtwdev, force_exec, id); 7050 else 7051 rtw89_mac_cfg_sb(rtwdev, wl->scbd[id]); 7052 dm->scbd_write_instant = 0; 7053 } else if ((val & BTC_WSCB_ACTIVE || 7054 val & BTC_WSCB_ON || 7055 val & BTC_WSCB_WLRFK) || 7056 scbd != wl->scbd[id]) { 7057 /* 7058 * Just update wl->scbd[] and set wl->scbd_chg[], 7059 * moved "Write scoreboard I/O" to _action_common() 7060 * _write_scbd will be executed if run_coex() 7061 */ 7062 wl->scbd[id] = scbd; 7063 wl->scbd_chg[id] = 1; 7064 } 7065 } 7066 } 7067 7068 static u8 7069 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 7070 { 7071 const struct rtw89_chip_info *chip = rtwdev->chip; 7072 u8 next_state, tol = chip->rssi_tol; 7073 7074 if (pre_state == BTC_RSSI_ST_LOW || 7075 pre_state == BTC_RSSI_ST_STAY_LOW) { 7076 if (rssi >= (thresh + tol)) 7077 next_state = BTC_RSSI_ST_HIGH; 7078 else 7079 next_state = BTC_RSSI_ST_STAY_LOW; 7080 } else { 7081 if (rssi < thresh) 7082 next_state = BTC_RSSI_ST_LOW; 7083 else 7084 next_state = BTC_RSSI_ST_STAY_HIGH; 7085 } 7086 7087 return next_state; 7088 } 7089 7090 static 7091 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 7092 { 7093 struct rtw89_btc *btc = &rtwdev->btc; 7094 7095 btc->cx.wl.dbcc_info.real_band[phy_idx] = 7096 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 7097 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 7098 btc->cx.wl.dbcc_info.op_band[phy_idx]; 7099 } 7100 7101 #define BTC_CHK_HANG_MAX 3 7102 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 7103 7104 static u8 _get_role_link_mode(u8 role) 7105 { 7106 switch (role) { 7107 case RTW89_WIFI_ROLE_STATION: 7108 default: 7109 return BTC_WLINK_STA; 7110 case RTW89_WIFI_ROLE_P2P_GO: 7111 return BTC_WLINK_GO; 7112 case RTW89_WIFI_ROLE_P2P_CLIENT: 7113 return BTC_WLINK_GC; 7114 case RTW89_WIFI_ROLE_AP: 7115 return BTC_WLINK_AP; 7116 } 7117 } 7118 7119 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1, 7120 const struct rtw89_btc_chdef *r2) 7121 { 7122 if (r1->chan != r2->chan) { /* primary ch is different */ 7123 return false; 7124 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 && 7125 r2->bw == RTW89_CHANNEL_WIDTH_40) { 7126 if (r1->offset != r2->offset) 7127 return false; 7128 } 7129 return true; 7130 } 7131 7132 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, 7133 u8 *phy, u8 *role, u8 link_cnt) 7134 { 7135 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7136 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 7137 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false; 7138 u8 j, k, dbcc_2g_cid = 0, dbcc_2g_cid2 = 0; 7139 7140 /* find out the 2G-PHY by connect-id ->ch */ 7141 for (j = 0; j < link_cnt; j++) { 7142 if (ch[j].center_ch <= 14) { 7143 is_2g_ch_exist = true; 7144 break; 7145 } 7146 } 7147 7148 /* If no any 2G-port exist, it's impossible because 5G-exclude */ 7149 if (!is_2g_ch_exist) 7150 return BTC_WLINK_SB_MCC; 7151 7152 dbcc_2g_cid = j; 7153 rinfo->dbcc_2g_phy = phy[dbcc_2g_cid]; 7154 7155 if (rinfo->dbcc_2g_phy == RTW89_PHY_1) 7156 rinfo->pta_req_band = RTW89_PHY_1; 7157 else 7158 rinfo->pta_req_band = RTW89_PHY_0; 7159 7160 /* connect_cnt <= 2 */ 7161 if (link_cnt < BTC_TDMA_WLROLE_MAX) 7162 return _get_role_link_mode(role[dbcc_2g_cid]); 7163 7164 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */ 7165 for (k = 0; k < link_cnt; k++) { 7166 if (k == dbcc_2g_cid) 7167 continue; 7168 7169 if (phy[k] == rinfo->dbcc_2g_phy) { 7170 is_multi_role_in_2g_phy = true; 7171 dbcc_2g_cid2 = k; 7172 break; 7173 } 7174 } 7175 7176 /* Single-role in 2G-PHY */ 7177 if (!is_multi_role_in_2g_phy) 7178 return _get_role_link_mode(role[dbcc_2g_cid]); 7179 7180 /* 2-role in 2G-PHY */ 7181 if (ch[dbcc_2g_cid2].center_ch > 14) 7182 return BTC_WLINK_DB_MCC; 7183 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2])) 7184 return BTC_WLINK_SCC; 7185 else 7186 return BTC_WLINK_SB_MCC; 7187 } 7188 7189 static void _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type) 7190 { 7191 struct rtw89_btc *btc = &rtwdev->btc; 7192 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7193 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 7194 struct rtw89_btc_wl_role_info *r = &wl->role_info; 7195 u8 p2p_exist = wl->role_info.p2p_exist; 7196 7197 if (hw_band == RTW89_PHY_1) 7198 p2p_exist = wl->role_info.p2p_exist_hb1; 7199 7200 /* MLD: nLmR --> 2L1R: 2-Link by 1-RF, 2L2R: 2-link by 2-RF */ 7201 switch (type) { 7202 case RTW89_MR_WTYPE_NONE: /* no-link */ 7203 r->link_mode = BTC_WLINK_NOLINK; 7204 break; 7205 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */ 7206 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */ 7207 if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { 7208 r->link_mode = BTC_WLINK_GO; 7209 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT && 7210 p2p_exist) { 7211 r->link_mode = BTC_WLINK_GC; 7212 } else { 7213 r->link_mode = BTC_WLINK_STA; 7214 } 7215 break; 7216 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */ 7217 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */ 7218 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ || 7219 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) { 7220 r->link_mode = BTC_WLINK_DB_MCC; 7221 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ || 7222 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ || 7223 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_6GHZ || 7224 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ_6GHZ) { 7225 r->link_mode = BTC_WLINK_SB_MCC; 7226 } else { 7227 r->link_mode = BTC_WLINK_SCC; 7228 } 7229 break; 7230 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */ 7231 if (p2p_exist) /* MLO_MLSR only support STA/GC */ 7232 r->link_mode = BTC_WLINK_GC; 7233 else 7234 r->link_mode = BTC_WLINK_STA; 7235 break; 7236 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */ 7237 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2*/ 7238 /* driver may doze 1-link (1+1) or 2+0->0+2->1+1 7239 * 2G+5G -> TDMA slot switch by E2G/E5G 7240 * 5G only -> TDMA slot switch by E5G 7241 */ 7242 r->link_mode = BTC_WLINK_DB_MCC; 7243 break; 7244 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */ 7245 /* MLMR only support STA now (2024) */ 7246 r->link_mode = BTC_WLINK_STA; 7247 break; 7248 } 7249 } 7250 7251 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev, u8 hw_band) 7252 { 7253 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7254 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7255 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 7256 struct rtw89_mr_chanctx_info qinfo; 7257 struct rtw89_chanctx *ch; 7258 u8 rf_band = RTW89_BAND_2G; 7259 u8 i, type; 7260 7261 /* parse MLO info form PHL API for each HW-band */ 7262 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { 7263 memset(&qinfo, 0, sizeof(qinfo)); 7264 7265 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo); 7266 7267 switch (qinfo.ctxtype) { 7268 default: 7269 mlo_info->hwb_rf_band[i] = 0; 7270 break; 7271 case RTW89_MR_CTX1_2GHZ: 7272 case RTW89_MR_CTX2_2GHZ: 7273 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G); 7274 break; 7275 case RTW89_MR_CTX1_5GHZ: 7276 case RTW89_MR_CTX2_5GHZ: 7277 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G); 7278 break; 7279 case RTW89_MR_CTX1_6GHZ: 7280 case RTW89_MR_CTX2_6GHZ: 7281 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_6G); 7282 break; 7283 case RTW89_MR_CTX2_2GHZ_5GHZ: 7284 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) | 7285 BIT(RTW89_BAND_5G); 7286 break; 7287 case RTW89_MR_CTX2_2GHZ_6GHZ: 7288 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) | 7289 BIT(RTW89_BAND_6G); 7290 break; 7291 case RTW89_MR_CTX2_5GHZ_6GHZ: 7292 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G) | 7293 BIT(RTW89_BAND_6G); 7294 break; 7295 } 7296 mlo_info->wmode[i] = qinfo.wmode; 7297 mlo_info->ch_type[i] = qinfo.ctxtype; 7298 mlo_info->wtype = qinfo.wtype; 7299 wl->rf_band_map[i] = mlo_info->hwb_rf_band[i]; 7300 ch = &rtwdev->hal.chanctx[i]; 7301 wl->rf_ch_info[i].center_ch = ch->chan.channel; 7302 wl->rf_ch_info[i].band = ch->chan.band_type; 7303 wl->rf_ch_info[i].chan = ch->chan.channel; 7304 wl->rf_ch_info[i].offset = ch->chan.pri_ch_idx; 7305 wl->rf_ch_info[i].bw = ch->chan.band_width; 7306 } 7307 7308 mlo_info->link_status = rtwdev->mlo_dbcc_mode; 7309 type = mlo_info->wtype; 7310 7311 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R || 7312 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R || 7313 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R || 7314 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD || 7315 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD || 7316 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD) 7317 mlo_info->mlo_en = 1; 7318 else 7319 mlo_info->mlo_en = 0; 7320 7321 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE && 7322 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN && 7323 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE && 7324 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN) 7325 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */ 7326 else 7327 mlo_info->dual_hw_band_en = 0; 7328 7329 if (mlo_info->link_status == MLO_2_PLUS_0_2RF || 7330 mlo_info->link_status == MLO_0_PLUS_2_2RF || 7331 mlo_info->link_status == MLO_2_PLUS_2_2RF) 7332 mlo_info->mlo_adie = 2; 7333 else 7334 mlo_info->mlo_adie = 1; 7335 7336 switch (mlo_info->link_status) { 7337 default: 7338 case MLO_2_PLUS_0_1RF: /* 2+0 */ 7339 case MLO_2_PLUS_0_2RF: 7340 _update_wl_link_mode(rtwdev, RTW89_MAC_0, type); 7341 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode; 7342 wl_rinfo->pta_req_band = RTW89_MAC_0; 7343 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7344 wl_rinfo->dbcc_en = 0; 7345 7346 rf_band = wl->rf_band_map[RTW89_PHY_0]; 7347 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7348 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7349 break; 7350 case MLO_0_PLUS_2_1RF: /* 0+2 */ 7351 case MLO_0_PLUS_2_2RF: 7352 _update_wl_link_mode(rtwdev, RTW89_MAC_1, type); 7353 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode; 7354 wl_rinfo->pta_req_band = RTW89_MAC_1; 7355 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7356 wl_rinfo->dbcc_en = 0; 7357 7358 rf_band = wl->rf_band_map[RTW89_PHY_1]; 7359 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7360 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7361 break; 7362 case MLO_1_PLUS_1_1RF: /* 1+1 */ 7363 case MLO_1_PLUS_1_2RF: /* 1+1 */ 7364 case MLO_2_PLUS_2_2RF: /* 2+2 */ 7365 case DBCC_LEGACY: /* DBCC 1+1 */ 7366 /* Check ch count from ch_type and modify type*/ 7367 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ || 7368 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_5GHZ || 7369 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_6GHZ) 7370 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role */ 7371 else 7372 type = RTW89_MR_WTYPE_NONMLD_NONMLD; 7373 7374 rf_band = wl->rf_band_map[hw_band]; 7375 _update_wl_link_mode(rtwdev, hw_band, type); 7376 7377 if (hw_band == RTW89_MAC_0) { 7378 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7379 } else { 7380 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode; 7381 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7382 } 7383 7384 /* set pta_req_band for 1-PTA architecture */ 7385 if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G)) { 7386 wl_rinfo->pta_req_band = RTW89_MAC_0; 7387 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7388 } else if (wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) { 7389 wl_rinfo->pta_req_band = RTW89_MAC_1; 7390 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7391 } else { /* Both HW-BAND are not on 2.4G*/ 7392 wl_rinfo->pta_req_band = RTW89_MAC_0; 7393 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7394 } 7395 break; 7396 } 7397 7398 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d", 7399 __func__, id_to_linkmode(wl_rinfo->link_mode), 7400 wl_rinfo->pta_req_band); 7401 } 7402 7403 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) 7404 { 7405 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7406 struct rtw89_btc_wl_rlink *rlink = NULL; 7407 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7408 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7409 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7410 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7411 bool b2g = false, b5g = false, outloop = false; 7412 u8 mode = BTC_WLINK_NOLINK; 7413 u8 cnt_2g = 0, cnt_5g = 0; 7414 u8 i, j, cnt = 0; 7415 7416 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) { 7417 wl->rf_band_map[j] = 0; /* j=link id, is the link use which band */ 7418 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 7419 rlink = &wl_rinfo->rlink[i][j]; 7420 7421 if (!rlink->active || !rlink->connected) 7422 continue; 7423 7424 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) { 7425 outloop = true; 7426 break; 7427 } 7428 7429 cid_ch[cnt] = wl->rlink_info[i][j].chdef; 7430 cid_phy[cnt] = rlink->phy; 7431 cid_role[cnt] = rlink->role; 7432 cnt++; 7433 7434 if (rlink->rf_band != RTW89_BAND_2G) { 7435 cnt_5g++; 7436 b5g = true; 7437 } else { 7438 cnt_2g++; 7439 b2g = true; 7440 } 7441 wl->rf_band_map[j] |= BIT(rlink->rf_band); 7442 } 7443 if (outloop) 7444 break; 7445 } 7446 7447 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7448 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g); 7449 7450 wl_rinfo->pta_req_band = RTW89_PHY_0; /* no 0+2 for non-MLO */ 7451 wl_rinfo->dbcc_en = rtwdev->dbcc_en; 7452 7453 /* Be careful to change the following sequence!! */ 7454 if (cnt == 0) { 7455 mode = BTC_WLINK_NOLINK; 7456 } else if (wl_rinfo->dbcc_en) { 7457 /* update pta_req_band to 2.4GHz HW-BAND for DBCC = 1*/ 7458 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); 7459 } else if (!b2g && b5g) { 7460 mode = _get_role_link_mode(cid_role[0]); 7461 } else if (b2g && b5g) { 7462 mode = BTC_WLINK_DB_MCC; 7463 } else if (cnt >= 2) { 7464 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1])) 7465 mode = BTC_WLINK_SCC; 7466 else 7467 mode = BTC_WLINK_SB_MCC; 7468 } else { 7469 mode = _get_role_link_mode(cid_role[0]); 7470 } 7471 7472 wl_rinfo->link_mode = mode; 7473 wl_rinfo->link_mode_hb1 = mode; 7474 } 7475 7476 static void _sync_wl_link_mode_v0(struct rtw89_dev *rtwdev) 7477 { 7478 struct rtw89_btc_wl_role_info *r = &rtwdev->btc.cx.wl.role_info; 7479 bool has_2g = false; 7480 int i, j; 7481 7482 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER && !has_2g; i++) 7483 for (j = 0; j < RTW89_MAC_NUM && !has_2g; j++) 7484 if (r->rlink[i][j].connected && 7485 r->rlink[i][j].rf_band == RTW89_BAND_2G) 7486 has_2g = true; 7487 7488 if (!has_2g && r->link_mode != BTC_WLINK_NOLINK) { 7489 r->link_mode_v0 = BTC_WLINK_V0_5G; 7490 return; 7491 } 7492 7493 switch (r->link_mode) { 7494 case BTC_WLINK_NOLINK: 7495 r->link_mode_v0 = BTC_WLINK_V0_NOLINK; 7496 break; 7497 case BTC_WLINK_STA: 7498 r->link_mode_v0 = BTC_WLINK_V0_2G_STA; 7499 break; 7500 case BTC_WLINK_AP: 7501 r->link_mode_v0 = BTC_WLINK_V0_2G_AP; 7502 break; 7503 case BTC_WLINK_GO: 7504 r->link_mode_v0 = BTC_WLINK_V0_2G_GO; 7505 break; 7506 case BTC_WLINK_GC: 7507 r->link_mode_v0 = BTC_WLINK_V0_2G_GC; 7508 break; 7509 case BTC_WLINK_SCC: 7510 r->link_mode_v0 = BTC_WLINK_V0_2G_SCC; 7511 break; 7512 case BTC_WLINK_SB_MCC: 7513 r->link_mode_v0 = BTC_WLINK_V0_2G_MCC; 7514 break; 7515 case BTC_WLINK_DB_MCC: 7516 r->link_mode_v0 = BTC_WLINK_V0_25G_MCC; 7517 break; 7518 default: 7519 r->link_mode_v0 = BTC_WLINK_V0_OTHER; 7520 break; 7521 } 7522 } 7523 7524 static void _modify_role_link_mode(struct rtw89_dev *rtwdev, u8 hw_band) 7525 { 7526 struct rtw89_btc *btc = &rtwdev->btc; 7527 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7528 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7529 u8 go_cleint_exist = wl->go_client_exist; 7530 u8 *link_mode = &wl_rinfo->link_mode; 7531 u32 role_map = wl_rinfo->role_map; 7532 u8 noa_exist = wl->noa_exist; 7533 u32 mrole = BTC_WLMROLE_NONE; 7534 7535 if (hw_band == RTW89_PHY_1) { 7536 *link_mode = wl_rinfo->link_mode_hb1; 7537 role_map = wl_rinfo->role_map_hb1; 7538 go_cleint_exist = wl->go_client_exist_hb1; 7539 } 7540 7541 /* if no client_joined, don't care P2P-GO/AP role */ 7542 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 7543 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) { 7544 if (*link_mode == BTC_WLINK_SCC) { 7545 *link_mode = BTC_WLINK_STA; 7546 } else if (*link_mode == BTC_WLINK_GO || 7547 *link_mode == BTC_WLINK_AP) { 7548 *link_mode = BTC_WLINK_NOLINK; 7549 } 7550 } 7551 7552 /* Identify 2-Role type */ 7553 if (*link_mode == BTC_WLINK_SCC || 7554 *link_mode == BTC_WLINK_SB_MCC || 7555 *link_mode == BTC_WLINK_DB_MCC) { 7556 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 7557 (role_map & BIT(RTW89_WIFI_ROLE_AP))) { 7558 if (noa_exist) 7559 mrole = BTC_WLMROLE_STA_GO_NOA; 7560 else 7561 mrole = BTC_WLMROLE_STA_GO; 7562 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) { 7563 if (noa_exist) 7564 mrole = BTC_WLMROLE_STA_GC_NOA; 7565 else 7566 mrole = BTC_WLMROLE_STA_GC; 7567 } else { 7568 mrole = BTC_WLMROLE_STA_STA; 7569 } 7570 7571 if (hw_band == RTW89_PHY_0) { 7572 wl_rinfo->mrole_type &= GENMASK(31, 16); /* clear Low-Word */ 7573 wl_rinfo->mrole_type |= mrole; 7574 } else { 7575 wl_rinfo->mrole_type &= GENMASK(15, 0); /* clear high-Word */ 7576 wl_rinfo->mrole_type |= (mrole << 16); 7577 } 7578 } else { 7579 wl_rinfo->mrole_type = BTC_WLMROLE_NONE; 7580 } 7581 7582 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7583 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__, 7584 id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type); 7585 } 7586 7587 static void _update_wl_info(struct rtw89_dev *rtwdev, struct rtw89_btc_wl_link_info *wl_linfo) 7588 { 7589 struct rtw89_btc *btc = &rtwdev->btc; 7590 struct rtw89_btc_dm *dm = &btc->dm; 7591 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7592 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7593 struct rtw89_btc_wl_rlink *rlink = NULL; 7594 u8 dbcc_en_ori, is_5g_hi_ch = 0, bg_mode = 0, p2p_exist = 0; 7595 u8 go_client_exist = 0, noa_exist = 0; 7596 u8 rlink_id = wl_linfo->phy; 7597 u8 role_id = wl_linfo->pid; 7598 u8 i, link_mode_ori; 7599 u32 role_map = 0; 7600 7601 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_BAND_NUM) 7602 return; 7603 7604 /* 7605 * Extract wl->link_info[role_id][rlink_id] to wl->role_info 7606 * role_id: role index 7607 * rlink_id: rlink index (= HW-band index) 7608 * pid: port_index 7609 */ 7610 rlink = &wl_rinfo->rlink[role_id][rlink_id]; 7611 7612 rlink->role = wl_linfo->role; 7613 rlink->active = wl_linfo->active; /* Doze or not */ 7614 rlink->pid = wl_linfo->pid; 7615 rlink->mac_id = wl_linfo->mac_id; 7616 rlink->phy = wl_linfo->phy; 7617 rlink->rf_band = wl_linfo->chdef.band; 7618 rlink->ch = wl_linfo->chdef.center_ch; 7619 rlink->bw = wl_linfo->chdef.bw; 7620 rlink->noa = wl_linfo->noa; 7621 rlink->noa_dur = wl_linfo->noa_duration / 1000; 7622 rlink->client_cnt = wl_linfo->client_cnt; 7623 rlink->mode = wl_linfo->mode; 7624 7625 /* check if rlink connect? */ 7626 switch (wl_linfo->connected) { 7627 case MLME_NO_LINK: 7628 rlink->connected = 0; 7629 break; 7630 case MLME_LINKED: 7631 rlink->connected = 1; 7632 7633 /* reset special-AP flag if station mode linked */ 7634 dm->leak_ap = 0; 7635 break; 7636 default: 7637 return; 7638 } 7639 7640 /* update by HW-Band */ 7641 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { /* i = role_id */ 7642 rlink = &wl_rinfo->rlink[i][rlink_id]; 7643 7644 if (!rlink->active || !rlink->connected) 7645 continue; 7646 7647 role_map |= BIT(rlink->role); 7648 7649 /* Identify if P2P-Go (GO/GC/AP) exist at 2GHz band */ 7650 if (((rlink->role == RTW89_WIFI_ROLE_P2P_GO || 7651 rlink->role == RTW89_WIFI_ROLE_AP) && 7652 rlink->client_cnt > 1)) { 7653 p2p_exist = 1; 7654 go_client_exist = 1; 7655 } 7656 7657 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT) 7658 p2p_exist = 1; 7659 7660 /* only one noa-role exist */ 7661 if (rlink->noa && rlink->noa_dur > 0) 7662 noa_exist = 1; 7663 7664 /* for WL 5G-Rx interfered with BT issue */ 7665 if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100) 7666 is_5g_hi_ch = 1; 7667 7668 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || 7669 (rlink->mode & BIT(BTC_WL_MODE_11G))) 7670 bg_mode = 1; 7671 } 7672 7673 if (rlink_id == RTW89_PHY_0) { 7674 link_mode_ori = wl_rinfo->link_mode; 7675 wl->is_5g_hi_ch = is_5g_hi_ch; 7676 wl->bg_mode = bg_mode; 7677 wl->go_client_exist = go_client_exist; 7678 wl->noa_exist = noa_exist; 7679 wl_rinfo->p2p_exist = p2p_exist; 7680 wl_rinfo->role_map = role_map; 7681 } else { 7682 link_mode_ori = wl_rinfo->link_mode_hb1; 7683 wl->is_5g_hi_ch_hb1 = is_5g_hi_ch; 7684 wl->bg_mode_hb1 = bg_mode; 7685 wl->go_client_exist_hb1 = go_client_exist; 7686 wl->noa_exist_hb1 = noa_exist; 7687 wl_rinfo->p2p_exist_hb1 = p2p_exist; 7688 wl_rinfo->role_map_hb1 = role_map; 7689 } 7690 7691 dbcc_en_ori = wl_rinfo->dbcc_en; 7692 7693 /* for MLO-supported, link-mode from driver directly */ 7694 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { 7695 _update_wl_mlo_info(rtwdev, rlink_id); 7696 } else { /* for non-MLO-supported, link-mode by BTC */ 7697 _update_wl_non_mlo_info(rtwdev); 7698 } 7699 7700 _modify_role_link_mode(rtwdev, rlink_id); 7701 _sync_wl_link_mode_v0(rtwdev); 7702 7703 if ((rlink_id == RTW89_PHY_0 && wl_rinfo->link_mode != link_mode_ori) || 7704 (rlink_id == RTW89_PHY_1 && wl_rinfo->link_mode_hb1 != link_mode_ori)) { 7705 wl_rinfo->link_mode_chg = 1; 7706 wl->link_mode_chg = 1; 7707 } 7708 7709 if (wl_rinfo->dbcc_en != dbcc_en_ori) { 7710 wl->dbcc_chg = 1; 7711 wl->role_info.dbcc_chg = 1; 7712 wl->wcnt[BTC_WCNT_DBCC_CHG]++; 7713 } 7714 } 7715 7716 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work) 7717 { 7718 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7719 coex_act1_work.work); 7720 struct rtw89_btc *btc = &rtwdev->btc; 7721 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7722 struct rtw89_btc_cx *cx = &btc->cx; 7723 struct rtw89_btc_wl_info *wl = &cx->wl; 7724 7725 lockdep_assert_wiphy(wiphy); 7726 7727 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7728 dm->cnt_notify[BTC_NCNT_TIMER]++; 7729 if (wl->status.map.handshake || 7730 wl->status.map._4way || 7731 wl->status.map.dhcp) { 7732 wl->status.map._4way = 0; 7733 wl->status.map.dhcp = 0; 7734 wl->status.map.handshake = 0; 7735 } 7736 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 7737 } 7738 7739 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work) 7740 { 7741 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7742 coex_bt_devinfo_work.work); 7743 struct rtw89_btc *btc = &rtwdev->btc; 7744 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7745 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 7746 7747 lockdep_assert_wiphy(wiphy); 7748 7749 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7750 dm->cnt_notify[BTC_NCNT_TIMER]++; 7751 a2dp->play_latency = 0; 7752 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 7753 } 7754 7755 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work) 7756 { 7757 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7758 coex_rfk_chk_work.work); 7759 struct rtw89_btc *btc = &rtwdev->btc; 7760 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7761 struct rtw89_btc_cx *cx = &btc->cx; 7762 struct rtw89_btc_wl_info *wl = &cx->wl; 7763 7764 lockdep_assert_wiphy(wiphy); 7765 7766 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7767 dm->cnt_notify[BTC_NCNT_TIMER]++; 7768 if (wl->rfk_info.state != BTC_WRFK_STOP) { 7769 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7770 "[BTC], %s(): RFK timeout\n", __func__); 7771 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]++; 7772 dm->error.map.wl_rfk_timeout = true; 7773 wl->rfk_info.state = BTC_WRFK_STOP; 7774 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false); 7775 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 7776 } 7777 } 7778 7779 static void _update_bt_ctrl_lps(struct rtw89_dev *rtwdev) 7780 { 7781 struct rtw89_btc *btc = &rtwdev->btc; 7782 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 7783 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 7784 struct rtw89_btc_dm *dm = &btc->dm; 7785 bool lps_ctrl = false; 7786 7787 if (dm->out_of_band || dm->freerun) 7788 lps_ctrl = false; 7789 else if (bt0->whql_test || bt1->whql_test) 7790 lps_ctrl = true; 7791 else if (bt0->link_info.a2dp_desc.exist || 7792 bt0->link_info.hfp_desc.exist || 7793 bt0->link_info.pan_desc.exist) 7794 lps_ctrl = true; 7795 else if (bt1->link_info.a2dp_desc.exist || 7796 bt1->link_info.hfp_desc.exist || 7797 bt1->link_info.pan_desc.exist) 7798 lps_ctrl = true; 7799 7800 if (dm->lps_ctrl_scbd != lps_ctrl) { 7801 dm->lps_ctrl_scbd = lps_ctrl; 7802 dm->lps_ctrl_change = true; 7803 } else { 7804 dm->lps_ctrl_change = false; 7805 } 7806 } 7807 7808 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid) 7809 { 7810 struct rtw89_btc_bt_link_info *bt_2g, *bt_56g; 7811 struct rtw89_btc *btc = &rtwdev->btc; 7812 struct rtw89_btc_cx *cx = &btc->cx; 7813 struct rtw89_btc_dm *dm = &btc->dm; 7814 struct rtw89_btc_bt_info *bt; 7815 u32 val, any_bt_connect, any_bt_6g_connect = 0; 7816 bool bt_link_change = false; 7817 u8 id, id_start, id_stop; 7818 7819 if (!rtwdev->chip->scbd || bid > BTC_ALL_BT) 7820 return; 7821 7822 if (bid == BTC_ALL_BT) { 7823 id_start = BTC_BT_1ST; 7824 id_stop = BTC_BT_2ND; 7825 } else { 7826 id_start = bid; 7827 id_stop = bid; 7828 } 7829 7830 dm->lps_ctrl_change = false; 7831 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s()\n", __func__); 7832 7833 for (id = id_start; id <= id_stop; id++) { 7834 bt = (id == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 7835 bt_2g = &bt->link_info; 7836 bt_56g = &bt->link_info_56g; 7837 7838 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && id == BTC_BT_2ND) 7839 break; 7840 7841 val = bt->scbd_c2h; 7842 7843 if (val == 0xffffffff) { 7844 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7845 "[BTC], %s return by invalid scbd value\n", 7846 __func__); 7847 return; 7848 } 7849 7850 if (!(val & BTC_BSCB_ON)) 7851 bt->enable.now = 0; 7852 else 7853 bt->enable.now = 1; 7854 7855 if (bt->enable.now != bt->enable.last) 7856 bt_link_change = true; 7857 7858 /* reset bt info if bt re-enable */ 7859 if (bt->enable.now && !bt->enable.last) { 7860 if (id == BTC_BT_1ST) 7861 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 7862 else 7863 _reset_btc_var(rtwdev, BTC_RESET_BTINFO2); 7864 7865 bt->bcnt[BTC_BCNT_REENABLE]++; 7866 bt->enable.now = 1; 7867 bt->rf_band_map = BIT(RTW89_BAND_2G); 7868 bt->link_weight[BTC_BT_B2G] = 5; /* no-profile */ 7869 } 7870 bt->enable.last = bt->enable.now; 7871 7872 /* if BT will disconnect and adopt protect plan */ 7873 if ((val & BTC_BSCB_BT_PROTECT) && 7874 !(bt->scbd & BTC_BSCB_BT_PROTECT)) 7875 bt->bcnt[BTC_BCNT_PROTECT]++; 7876 7877 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 7878 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 7879 bt_link_change = true; 7880 7881 bt->whql_test = !!(val & BTC_BSCB_WHQL); 7882 bt->btg_type = (val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE); 7883 7884 bt_2g->a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 7885 bt_2g->pan_desc.exist = !!(val & BTC_BSCB_PAN_ACT); 7886 bt_2g->hfp_desc.exist = !!(val & BTC_BSCB_HFP_ACT); 7887 7888 bt->lna_constrain = 4 + !!(val & BTC_BSCB_BT_LNAB0) + 7889 !!(val & BTC_BSCB_BT_LNAB1) * 2; 7890 7891 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 7892 if (val & BTC_BSCB_BT_15DOT4) 7893 bt->func_type |= (BTC_BTF_THREAD | BTC_BTF_ZB); 7894 else 7895 bt->func_type &= ~(BTC_BTF_THREAD | BTC_BTF_ZB); 7896 } 7897 7898 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 7899 any_bt_connect = !!(val & BTC_BSCB_BT_CONNECT); 7900 7901 /* if connect change */ 7902 if (bt_2g->status.map.connect != any_bt_connect || 7903 bt_56g->status.map.connect != any_bt_6g_connect) { 7904 bt_link_change = true; 7905 bt_2g->status.map.connect = any_bt_connect; 7906 bt_56g->status.map.connect = any_bt_6g_connect; 7907 } 7908 7909 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 7910 bt->scbd = val; 7911 } 7912 7913 _update_bt_ctrl_lps(rtwdev); 7914 7915 if (bt_link_change) { 7916 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7917 "[BTC], %s: bt status change!!\n", __func__); 7918 /* TODO: Need to notify driver to update EXT-CTRL-BT-SLOT */ 7919 } 7920 } 7921 7922 static void _update_bt_link_cnt(struct rtw89_dev *rtwdev, 7923 struct rtw89_btc_bt_info *bt, bool b56g) 7924 { 7925 struct rtw89_btc_bt_link_info *b = b56g ? &bt->link_info_56g : 7926 &bt->link_info; 7927 struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc; 7928 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 7929 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 7930 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 7931 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 7932 u8 bt_rf_band = b56g ? BTC_BT_B5G : BTC_BT_B2G; 7933 u8 val; 7934 7935 b->link_cnt.last = b->link_cnt.now; 7936 b->link_cnt.now = 0; 7937 b->link_cnt.chg = 0; 7938 7939 b->link_cnt.now += hfp->exist; 7940 b->link_cnt.now += hid->exist; 7941 b->link_cnt.now += a2dp->exist; 7942 b->link_cnt.now += pan->exist; 7943 b->link_cnt.now += leaudio->bis_exist; 7944 b->link_cnt.now += leaudio->cis_exist; 7945 7946 if (leaudio->bis_exist || a2dp->sink) { 7947 val = 70; 7948 } else if (a2dp->exist) { 7949 val = 40; 7950 if (a2dp->vendor_id == 0x4c) 7951 val += 10; 7952 if (hid->exist) 7953 val += 10; 7954 } else if (pan->exist || pan->active || a2dp->active || 7955 b->status.map.inq_pag) { 7956 val = 30; 7957 } else if (b->link_cnt.now == 0) { 7958 val = 5; 7959 } else { 7960 val = 9; 7961 } 7962 bt->link_weight[bt_rf_band] = val; 7963 7964 if (b->link_cnt.last != b->link_cnt.now) 7965 b->link_cnt.chg = 1; 7966 } 7967 7968 static void _update_bt_leaudio_info(struct rtw89_dev *rtwdev, u8 bid, 7969 void *buf, u32 len) 7970 { 7971 const struct rtw89_chip_info *chip = rtwdev->chip; 7972 struct rtw89_btc *btc = &rtwdev->btc; 7973 struct rtw89_btc_cx *cx = &btc->cx; 7974 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 7975 struct rtw89_btc_bt_link_info *b = &bt->link_info; 7976 struct rtw89_btc_bt_leaudio_info *src = buf; 7977 struct rtw89_btc_bt_leaudio_desc *leaudio; 7978 bool bt_56g = false, cis_exist, bis_exist; 7979 u8 bis_cnt, cis_cnt; 7980 7981 if ((src->len & BIT(7)) && bt->band_56G_support) { 7982 b = &bt->link_info_56g; 7983 bt_56g = true; 7984 } 7985 7986 leaudio = &b->leaudio_desc; 7987 7988 if (!memcmp(b->leaudio_raw_info, src, BTC_BTINFO_MAX)) { 7989 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7990 "[BTC], %s return by leaudio-info duplicate!\n", 7991 __func__); 7992 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; 7993 return; 7994 } 7995 7996 memcpy(b->leaudio_raw_info, src, BTC_BTINFO_MAX); 7997 7998 bis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_EX); 7999 cis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_EX); 8000 bis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_CNT); 8001 cis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_CNT); 8002 8003 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8004 "[BTC], %s: bis_exist:%d bis_cnt:%d cis_exist:%d cis_cnt:%d rssi:%d\n", 8005 __func__, bis_exist, bis_cnt, cis_exist, cis_cnt, src->rssi); 8006 8007 if (!bis_exist && !cis_exist) 8008 memset(leaudio, 0, sizeof(*leaudio)); 8009 8010 leaudio->bis_cnt = bis_cnt; 8011 leaudio->bis_exist = bis_exist; 8012 leaudio->cis_cnt = cis_cnt; 8013 leaudio->cis_exist = cis_exist; 8014 8015 if (leaudio->bis_exist) 8016 b->status.map.profile_map |= BTC_BT_BIS; 8017 else 8018 b->status.map.profile_map &= ~BTC_BT_BIS; 8019 8020 if (leaudio->cis_exist) 8021 b->status.map.profile_map |= BTC_BT_CIS; 8022 else 8023 b->status.map.profile_map &= ~BTC_BT_CIS; 8024 8025 _update_bt_link_cnt(rtwdev, bt, bt_56g); 8026 8027 leaudio->rssi = chip->ops->btc_get_bt_rssi(rtwdev, src->rssi); 8028 8029 leaudio->bis_cnt_last = leaudio->bis_cnt; 8030 leaudio->bis_exist_last = leaudio->bis_exist; 8031 leaudio->cis_cnt_last = leaudio->cis_cnt; 8032 leaudio->cis_exist_last = leaudio->cis_exist; 8033 } 8034 8035 static void _update_bt_bistdma_info(struct rtw89_dev *rtwdev, u8 bid, 8036 void *buf, u32 len) 8037 { 8038 struct rtw89_btc *btc = &rtwdev->btc; 8039 struct rtw89_btc_cx *cx = &btc->cx; 8040 struct rtw89_btc_dm *dm = &btc->dm; 8041 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 8042 struct rtw89_btc_bt_link_info *b = &bt->link_info; 8043 struct rtw89_btc_bt_bistdma_info_le *src = buf; 8044 struct rtw89_btc_bt_leaudio_desc *leaudio; 8045 8046 if ((src->len & BIT(7)) && bt->band_56G_support) 8047 b = &bt->link_info_56g; 8048 8049 leaudio = &b->leaudio_desc; 8050 8051 if (!memcmp(b->bistdma_raw_info, src, BTC_BTINFO_MAX)) { 8052 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8053 "[BTC], %s return by bistdma-info duplicate!\n", 8054 __func__); 8055 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; 8056 return; 8057 } 8058 8059 memcpy(b->bistdma_raw_info, src, BTC_BTINFO_MAX); 8060 8061 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8062 "[BTC], %s: bis_start_end:%d bis_trx:%d\n", 8063 __func__, 8064 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_START_END), 8065 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX)); 8066 8067 leaudio->bis_trx = u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX); 8068 leaudio->bis_start_end = u8_get_bits(src->bis, 8069 RTW89_BTC_BIS_INFO_L2_START_END); 8070 8071 leaudio->diff_t = (src->diff_t_hb * 256 + src->diff_t_lb) * 625 / 1000; 8072 8073 if (btc->ant_type == BTC_ANT_SHARED && leaudio->diff_t > 13) 8074 dm->bis_tdma = true; 8075 else 8076 dm->bis_tdma = false; 8077 } 8078 8079 #define BTC_BTINFO_PWR_LEN 5 8080 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 8081 { 8082 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 8083 struct rtw89_btc_bt_link_info *b = &bt->link_info; 8084 8085 if (len != BTC_BTINFO_PWR_LEN) 8086 return; 8087 8088 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) { 8089 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8090 "[BTC], %s return by info duplicate!\n", __func__); 8091 return; 8092 } 8093 8094 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX); 8095 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc)); 8096 } 8097 8098 static void _set_bind_info(struct rtw89_btc *btc, u8 type) 8099 { 8100 struct rtw89_btc_cx *cx = &btc->cx; 8101 struct rtw89_btc_dm *dm = &btc->dm; 8102 struct rtw89_btc_wl_info *wl = &cx->wl; 8103 struct rtw89_btc_bt_info *bt = &cx->bt0; 8104 struct rtw89_btc_bt_link_info *b; 8105 struct rtw89_btc_bind_info *bd; 8106 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 8107 u8 link_weight[BTC_ALL_BT_EZL][BTC_BT_BMAX]; 8108 u8 map[BTC_RF_NUM][BTC_ALL_BT_EZL]; 8109 u8 b2g_score = 0, b5g_score = 0; 8110 u8 i, j, rf_band_map, thres; 8111 u8 weight[BTC_BT_BMAX] = {}; 8112 8113 if (type == BTC_MECH_TDD) { 8114 bd = &dm->tdd_bind; 8115 memcpy(map, dm->tdd_map, sizeof(map)); 8116 thres = 30; /* BT profile score threshold for TDMA */ 8117 } else { 8118 bd = &dm->fdd_bind; 8119 memcpy(map, dm->fdd_map, sizeof(map)); 8120 thres = 5; 8121 } 8122 8123 memset(bd, 0, sizeof(*bd)); 8124 /* compare BT 2GHz/5GHz profile by link-weighting */ 8125 for (i = 0; i < BTC_BT_BMAX; i++) { 8126 if (!cx->bt0.enable.now) 8127 cx->bt0.link_weight[i] = 0; 8128 if (!cx->bt1.enable.now) 8129 cx->bt1.link_weight[i] = 0; 8130 link_weight[BTC_BT_1ST][i] = cx->bt0.link_weight[i]; 8131 link_weight[BTC_BT_2ND][i] = cx->bt1.link_weight[i]; 8132 link_weight[BTC_BT_EXT][i] = cx->bt_ext.link_weight[i]; 8133 } 8134 8135 /* 8136 * get 2GHz/5GHz link weight score by "band-overlap" map 8137 * link_weight from _update_bt_link_cnt(), 8138 * if link_weight >30 --> TDMA-required 8139 */ 8140 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8141 rf_band_map = map[BTC_RF_S0][j] | map[BTC_RF_S1][j]; 8142 if (rf_band_map & BIT(RTW89_BAND_2G)) 8143 b2g_score += link_weight[j][BTC_BT_B2G]; 8144 if (rf_band_map & BIT(RTW89_BAND_5G)) 8145 b5g_score += link_weight[j][BTC_BT_B5G]; 8146 } 8147 8148 /* rf-band bound by comparing link weight */ 8149 if (b2g_score == 0 && b5g_score == 0) /* no-rf-band overlap */ 8150 bd->rf_band = 0; 8151 else if (b5g_score > b2g_score) 8152 bd->rf_band = BIT(BTC_BT_B5G); 8153 else 8154 bd->rf_band = BIT(BTC_BT_B2G); 8155 8156 /* 8157 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1 8158 * Therefore, BTC_MLO_RF_xxx is not real-time state. 8159 * In this case, RF_S0->HWB0, RF_S1->HWB1 8160 * If link-mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO) 8161 * HW-Band is decided by wl->mlo_info.mrcx_act_hwb_map 8162 */ 8163 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) { 8164 if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) { /* mode chg */ 8165 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_MAC_1)) 8166 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* S0/1->HWB1 */ 8167 else 8168 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* S0/1->HWB0 */ 8169 } 8170 } else { 8171 /* 8172 * Dual-RF_band(HWB)TDMA if BT-profile is TDMA-type at both 8173 * 2GHz and 5GHz. 8174 * ex: 1+1: HWB0 5GHz + BT0 5GHz (BIS, HDT) 8175 * && HWB1 2.4GHz + BT1 2.4GHz(PAN) 8176 * for TDD: the link score must > 30 (from _bt_link_cnt) 8177 * for FDD: the link score must > 5 (bt enable) 8178 */ 8179 if ((wl->mlo_info.rf_combination == BTC_MLO_RF_1_PLUS_1 || 8180 wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_2) && 8181 (b2g_score >= thres && b5g_score >= thres)) { 8182 bd->rf_band = BIT(BTC_BT_B2G) | BIT(BTC_BT_B5G); 8183 } 8184 8185 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0) 8186 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */ 8187 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2) 8188 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */ 8189 } 8190 8191 /* Get HWB-sel and BT-sel by rf-band-binding */ 8192 for (i = 0; i < BTC_RF_NUM; i++) { 8193 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8194 if (!(map[i][j] & bd->rf_band)) /* no-overlap */ 8195 continue; 8196 8197 bd->wl_hwb_sel |= BIT(path_hwb[i]); 8198 bd->bt_sel |= BIT(j); 8199 } 8200 } 8201 8202 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L2R && 8203 (bd->wl_hwb_sel == (BIT(RTW89_MAC_1) | BIT(RTW89_MAC_0)))) { 8204 if (wl->role_info.link_mode == BTC_WLINK_AP || 8205 wl->role_info.link_mode_hb1 == BTC_WLINK_AP) 8206 bd->wl_link_mode = BTC_WLINK_DB_MCC; 8207 else 8208 bd->wl_link_mode = BTC_WLINK_STA; 8209 bd->wl_bg_mode = wl->bg_mode | wl->bg_mode_hb1; 8210 } else if (bd->wl_hwb_sel == (BIT(RTW89_MAC_1))) { 8211 bd->wl_link_mode = wl->role_info.link_mode_hb1; 8212 bd->wl_bg_mode = wl->bg_mode_hb1; 8213 } else {/* HW-BAND-0 or no-hw-band */ 8214 bd->wl_hwb_sel = BIT(RTW89_MAC_0); 8215 bd->wl_link_mode = wl->role_info.link_mode; 8216 bd->wl_bg_mode = wl->bg_mode; 8217 } 8218 8219 /* update Bind-BT status map for BT0/BT1 */ 8220 for (i = BTC_BT_1ST; i < BTC_ALL_BT_EZL; i++) { 8221 if (!(bd->bt_sel & BIT(i))) 8222 continue; 8223 8224 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) { 8225 if (!(bd->rf_band & BIT(j))) 8226 continue; 8227 8228 if (i == BTC_BT_EXT) { 8229 bd->bt_profile |= cx->bt_ext.profile_map[j]; 8230 weight[j] = cx->bt_ext.link_weight[j]; 8231 if (weight[j] > bd->bt_link_weight) /* max */ 8232 bd->bt_link_weight = weight[j]; 8233 continue; 8234 } else if (i == BTC_BT_1ST) { 8235 bt = &cx->bt0; 8236 } else { 8237 bt = &cx->bt1; 8238 } 8239 8240 if (j == BTC_BT_B2G) 8241 b = &bt->link_info; 8242 else 8243 b = &bt->link_info_56g; 8244 8245 bd->bt_profile |= b->status.map.profile_map; 8246 bd->bt_smap.a2dp_active |= b->a2dp_desc.active; 8247 bd->bt_smap.a2dp_sink |= b->a2dp_desc.sink; 8248 bd->bt_smap.pan_active |= b->pan_desc.active; 8249 bd->bt_smap.connect |= b->status.map.connect; 8250 bd->bt_smap.hid_cnt += b->hid_desc.pair_cnt; 8251 bd->bt_smap.hid_type |= b->hid_desc.type; 8252 bd->bt_smap.cis_cnt += b->leaudio_desc.cis_cnt; 8253 bd->bt_smap.link_cnt += b->link_cnt.now; 8254 bd->bt_smap.inq_page |= b->status.map.inq_pag; 8255 bd->bt_smap.page |= b->pag; 8256 8257 if (bt->link_weight[j] > bd->bt_link_weight) /* max */ 8258 bd->bt_link_weight = bt->link_weight[j]; 8259 8260 if (b->slave_role) 8261 bd->bt_smap.slave_role = b->slave_role; 8262 8263 if (b->a2dp_desc.vendor_id != 0) 8264 bd->bt_smap.a2dp_vendor_id = 8265 b->a2dp_desc.vendor_id; 8266 } 8267 } 8268 8269 if (bd->bt_profile & BTC_BT_HFP) 8270 bd->bt_smap.hfp_exist = 1; 8271 if (bd->bt_profile & BTC_BT_HID) 8272 bd->bt_smap.hid_exist = 1; 8273 if (bd->bt_profile & BTC_BT_A2DP) 8274 bd->bt_smap.a2dp_exist = 1; 8275 if (bd->bt_profile & BTC_BT_PAN) 8276 bd->bt_smap.pan_exist = 1; 8277 if (bd->bt_profile & BTC_BT_BIS) 8278 bd->bt_smap.bis_exist = 1; 8279 if (bd->bt_profile & BTC_BT_CIS) 8280 bd->bt_smap.cis_exist = 1; 8281 if (bd->bt_profile & BTC_BT_THREAD) 8282 bd->bt_smap.thread_exist = 1; 8283 if (bd->bt_profile & BTC_BT_ULL) 8284 bd->bt_smap.ull_exist = 1; 8285 } 8286 8287 #define _bind_is_btonly 0x7 8288 static void _set_coex_binding(struct rtw89_btc *btc) 8289 { 8290 struct rtw89_btc_cx *cx = &btc->cx; 8291 struct rtw89_btc_extsoc_info *bt2 = &cx->bt_ext; 8292 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 8293 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 8294 struct rtw89_btc_wl_info *wl = &cx->wl; 8295 struct rtw89_btc_dm *dm = &btc->dm; 8296 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 8297 u8 wl_rf_band[RTW89_BAND_NUM] = {}; 8298 u8 i, j, val = 0; 8299 8300 /* 8301 * sit_xmap(Space-Interaction) = ant_xmap | xtk_xmap 8302 * 1: WL-BT space-interference, always 1 if BTG/BTA/SPDT = 1 8303 * if dedicated-ant, it may be 1 if BT-Tx is bigger than WL-Rx(xtk_xmap) 8304 * 8305 * ant_xmap(ANT-Division-Multiplexing) 8306 * ==> dedicated-ant->0, BTG/BTA/SPDT->1 8307 * 8308 * xtk_xmap(Cross-talk map)-> calculate WL/BT interference by SIR 8309 * ==> 1: interference, 0: no-interference 8310 * 8311 * fdm_map(Frequency-Division-Multiplexing): WL/BT RF_Band overlap-map 8312 * 2bit-map: bit[1]:5/6GHz, bit[0]:2.4GHz 8313 */ 8314 for (i = 0; i < RTW89_PHY_NUM; i++) { 8315 if (wl->rf_band_map[i] & BIT(RTW89_BAND_2G)) 8316 wl_rf_band[i] |= BIT(RTW89_BAND_2G); 8317 8318 if (wl->rf_band_map[i] & (BIT(RTW89_BAND_5G) | BIT(RTW89_BAND_6G))) 8319 wl_rf_band[i] |= BIT(RTW89_BAND_5G); 8320 8321 dm->fit_xmap[i][BTC_BT_1ST] = wl_rf_band[i] & bt0->rf_band_map; 8322 dm->fit_xmap[i][BTC_BT_2ND] = wl_rf_band[i] & bt1->rf_band_map; 8323 dm->fit_xmap[i][BTC_BT_EXT] = wl_rf_band[i] & bt2->rf_band_map; 8324 } 8325 8326 /* 8327 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1 8328 * Therefore, BTC_MLO_RF_xxx is not real-time state. 8329 * if link mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO) 8330 * the HW-BAND is decided by wl->mlo_info.mrcx_act_hwb_map 8331 * In this case, BTC_RF_S0->HWB0, BTC_RF_S1->HWB1 8332 */ 8333 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) { 8334 if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) {/* mode chg */ 8335 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_PHY_1)) 8336 path_hwb[BTC_RF_S0] = RTW89_PHY_1;/* S0/1->HWB1 */ 8337 else 8338 path_hwb[BTC_RF_S1] = RTW89_PHY_0;/* S0/1->HWB0 */ 8339 } 8340 } else { 8341 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0) 8342 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */ 8343 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2) 8344 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */ 8345 } 8346 8347 /* 8348 * tdd_map = sit_xmap * fdm_map, 1: WL-RF-Sx vs. BTx take TDD-Action 8349 * fdd_map =(!sit_xmap) * fdm_map, 1: WL-RF-Sx vs.BTx take FDD-Action 8350 * co-rx map = ant_xmap * fdm_map 1:WL/BT co-rx (for halbb-btg-ctrl) 8351 * sit_xmap,ant_xmap = 0 or 1, so tdd/fdd use multiplication (*) 8352 */ 8353 8354 for (i = 0; i < BTC_RF_NUM; i++) 8355 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8356 dm->tdd_map[i][j] = dm->sit_xmap[i][j] * 8357 dm->fit_xmap[path_hwb[i]][j]; 8358 dm->fdd_map[i][j] = !dm->sit_xmap[i][j] * 8359 dm->fit_xmap[path_hwb[i]][j]; 8360 dm->corx_map[i][j] = dm->ant_xmap[i][j] * 8361 dm->fit_xmap[path_hwb[i]][j]; 8362 } 8363 8364 /* TDD-Binding */ 8365 _set_bind_info(btc, BTC_MECH_TDD); 8366 8367 /* FDD-Binding */ 8368 _set_bind_info(btc, BTC_MECH_FDD); 8369 8370 dm->out_of_band = !dm->tdd_bind.rf_band && !dm->fdd_bind.rf_band; 8371 dm->fdd_en = !!dm->fdd_bind.rf_band; 8372 dm->tdd_en = !!dm->tdd_bind.rf_band; 8373 8374 /* set BT on/off state for GNT_WL Combined-MUX control */ 8375 if (bt0->enable.now) 8376 val |= BIT(0); 8377 8378 if (bt1->enable.now) 8379 val |= BIT(1); 8380 8381 if (bt2->func_type) 8382 val |= BIT(2); 8383 8384 dm->ost_info.bt_enable_state = dm->bt_only ? _bind_is_btonly : val; 8385 } 8386 8387 static void _update_run_ctrl_info(struct rtw89_dev *rtwdev) 8388 { 8389 struct rtw89_btc *btc = &rtwdev->btc; 8390 struct rtw89_btc_dm *dm = &btc->dm; 8391 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8392 struct rtw89_btc_ctrl ctrl = btc->ctrl; 8393 struct rtw89_fbtc_wl_ctrl_info *wl_ctrl_info = &ctrl.wl_ctrl_info; 8394 u8 i; 8395 8396 ctrl.wl_only = dm->wl_only; 8397 ctrl.bt_only = dm->bt_only; 8398 ctrl.ntfy_type = dm->run_reason; 8399 8400 wl_ctrl_info->smap_val = wl->status.val; 8401 wl_ctrl_info->rfk_state = wl->rfk_info.state; 8402 wl_ctrl_info->rfk_type = wl->rfk_info.type; 8403 wl_ctrl_info->client_pstdma_on = dm->client_ps_tdma_on; 8404 wl_ctrl_info->fw_scan = wl->scan_info.fw_scan; 8405 8406 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { 8407 wl_ctrl_info->rf_band_map[i] = wl->rf_band_map[i]; 8408 wl_ctrl_info->rf_ch[i] = wl->rf_ch_info[i].center_ch; 8409 } 8410 8411 if (!memcmp(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl))) { 8412 memcpy(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl)); 8413 if (btc->ver->fcxctrl >= 9) 8414 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 8415 } 8416 } 8417 8418 static 8419 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 8420 { 8421 struct rtw89_btc *btc = &rtwdev->btc; 8422 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8423 struct rtw89_btc_cx *cx = &btc->cx; 8424 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8425 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 8426 u8 mode = btc->dm.tdd_bind.wl_link_mode; 8427 u8 mode_v0 = BTC_WLINK_V0_OTHER; 8428 bool has_2ghz; 8429 8430 lockdep_assert_wiphy(rtwdev->hw->wiphy); 8431 8432 dm->run_reason = reason; 8433 _update_dm_step(rtwdev, reason); 8434 8435 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 8436 __func__, reason, mode); 8437 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 8438 __func__, dm->wl_only, dm->bt_only); 8439 8440 /* Be careful to change the following function sequence!! */ 8441 if (btc->manual_ctrl) { 8442 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8443 "[BTC], %s(): return for Manual CTRL!!\n", 8444 __func__); 8445 return; 8446 } 8447 8448 if (!wl->status.map.init_ok) { 8449 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8450 "[BTC], %s(): return for WL init fail!!\n", 8451 __func__); 8452 return; 8453 } 8454 8455 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 8456 wl->status.map.lps_pre == wl->status.map.lps && 8457 !dm->lps_ctrl_change && !dm->lps_ctrl_scbd) { 8458 if (reason == BTC_RSN_NTFY_POWEROFF || 8459 reason == BTC_RSN_NTFY_RADIO_STATE) { 8460 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8461 "[BTC], %s(): return for WL rf off state no change!!\n", 8462 __func__); 8463 return; 8464 } 8465 if (wl->status.map.rf_off == 1 || 8466 wl->status.map.lps == BTC_LPS_RF_OFF) { 8467 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8468 "[BTC], %s(): return for WL rf off state!!\n", 8469 __func__); 8470 return; 8471 } 8472 } 8473 8474 _update_run_ctrl_info(rtwdev); 8475 8476 if (reason == BTC_RSN_NTFY_INIT || reason == BTC_RSN_NTFY_RADIO_STATE) 8477 _update_bt_scbd(rtwdev, false); 8478 8479 dm->freerun = false; 8480 dm->cnt_dm[BTC_DCNT_RUN]++; 8481 dm->fddt_train = BTC_FDDT_DISABLE; 8482 bt->scan_rx_low_pri = false; 8483 8484 _set_coex_binding(btc); 8485 _update_btc_state_map(rtwdev); 8486 8487 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ 8488 8489 if (btc->ctrl.always_freerun) { 8490 _action_freerun(rtwdev); 8491 goto exit; 8492 } 8493 8494 if (dm->wl_only) { 8495 _action_wl_only(rtwdev); 8496 goto exit; 8497 } 8498 8499 if (wl->status.map.rf_off || dm->bt_only || wl->status.map.lps) { 8500 _action_wl_off(rtwdev, mode); 8501 goto exit; 8502 } 8503 8504 if (reason == BTC_RSN_NTFY_INIT) { 8505 _action_wl_init(rtwdev); 8506 goto exit; 8507 } 8508 8509 if (!cx->bt0.enable.now && !cx->bt_ext.func_type) { 8510 _action_bt_off(rtwdev); 8511 goto exit; 8512 } 8513 8514 if (cx->bt0.whql_test) { 8515 _action_bt_whql(rtwdev); 8516 goto exit; 8517 } 8518 8519 if (wl->rfk_info.state != BTC_WRFK_STOP) { 8520 _action_wl_rfk(rtwdev); 8521 goto exit; 8522 } 8523 8524 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) { 8525 _action_wl_scan(rtwdev); 8526 bt->scan_rx_low_pri = true; 8527 goto exit; 8528 } 8529 8530 if (mode == BTC_WLINK_NOLINK) { 8531 mode_v0 = BTC_WLINK_V0_NOLINK; 8532 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G)) { 8533 mode_v0 = BTC_WLINK_V0_5G; 8534 } else if (btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_5G) && 8535 btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_2G)) { 8536 mode_v0 = BTC_WLINK_V0_25G_MCC; 8537 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_2G)) { 8538 switch (mode) { 8539 case BTC_WLINK_STA: 8540 mode_v0 = BTC_WLINK_V0_2G_STA; 8541 break; 8542 case BTC_WLINK_AP: 8543 mode_v0 = BTC_WLINK_V0_2G_AP; 8544 break; 8545 case BTC_WLINK_GO: 8546 mode_v0 = BTC_WLINK_V0_2G_GO; 8547 break; 8548 case BTC_WLINK_GC: 8549 mode_v0 = BTC_WLINK_V0_2G_GC; 8550 break; 8551 case BTC_WLINK_SCC: 8552 mode_v0 = BTC_WLINK_V0_2G_SCC; 8553 break; 8554 case BTC_WLINK_SB_MCC: 8555 mode_v0 = BTC_WLINK_V0_2G_MCC; 8556 break; 8557 default: 8558 mode_v0 = BTC_WLINK_V0_OTHER; 8559 break; 8560 } 8561 } else { 8562 /* No binding (out_of_band): derive mode_v0 from link_mode + rf_band_map */ 8563 has_2ghz = wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) || 8564 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G); 8565 8566 if (!has_2ghz) { 8567 mode_v0 = BTC_WLINK_V0_5G; 8568 } else if (mode == BTC_WLINK_DB_MCC) { 8569 mode_v0 = BTC_WLINK_V0_25G_MCC; 8570 } else { 8571 switch (mode) { 8572 case BTC_WLINK_STA: 8573 mode_v0 = BTC_WLINK_V0_2G_STA; 8574 break; 8575 case BTC_WLINK_AP: 8576 mode_v0 = BTC_WLINK_V0_2G_AP; 8577 break; 8578 case BTC_WLINK_GO: 8579 mode_v0 = BTC_WLINK_V0_2G_GO; 8580 break; 8581 case BTC_WLINK_GC: 8582 mode_v0 = BTC_WLINK_V0_2G_GC; 8583 break; 8584 case BTC_WLINK_SCC: 8585 mode_v0 = BTC_WLINK_V0_2G_SCC; 8586 break; 8587 case BTC_WLINK_SB_MCC: 8588 mode_v0 = BTC_WLINK_V0_2G_MCC; 8589 break; 8590 default: 8591 mode_v0 = BTC_WLINK_V0_OTHER; 8592 break; 8593 } 8594 } 8595 } 8596 8597 switch (mode_v0) { 8598 case BTC_WLINK_NOLINK: 8599 _action_wl_nc(rtwdev); 8600 break; 8601 case BTC_WLINK_V0_2G_STA: 8602 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 8603 bt->scan_rx_low_pri = true; 8604 _action_wl_2g_sta(rtwdev); 8605 break; 8606 case BTC_WLINK_V0_2G_AP: 8607 bt->scan_rx_low_pri = true; 8608 _action_wl_2g_ap(rtwdev); 8609 break; 8610 case BTC_WLINK_V0_2G_GO: 8611 bt->scan_rx_low_pri = true; 8612 _action_wl_2g_go(rtwdev); 8613 break; 8614 case BTC_WLINK_V0_2G_GC: 8615 bt->scan_rx_low_pri = true; 8616 _action_wl_2g_gc(rtwdev); 8617 break; 8618 case BTC_WLINK_V0_2G_SCC: 8619 bt->scan_rx_low_pri = true; 8620 _action_wl_2g_scc(rtwdev); 8621 break; 8622 case BTC_WLINK_V0_2G_MCC: 8623 bt->scan_rx_low_pri = true; 8624 _action_wl_2g_mcc(rtwdev); 8625 break; 8626 case BTC_WLINK_V0_25G_MCC: 8627 bt->scan_rx_low_pri = true; 8628 _action_wl_25g_mcc(rtwdev); 8629 break; 8630 case BTC_WLINK_V0_5G: 8631 _action_wl_5g(rtwdev); 8632 break; 8633 case BTC_WLINK_V0_2G_NAN: 8634 _action_wl_2g_nan(rtwdev); 8635 break; 8636 default: 8637 _action_wl_other(rtwdev); 8638 break; 8639 } 8640 8641 exit: 8642 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 8643 _action_common(rtwdev); 8644 } 8645 8646 void rtw89_btc_init(struct rtw89_dev *rtwdev) 8647 { 8648 const struct rtw89_chip_info *chip = rtwdev->chip; 8649 struct rtw89_btc *btc = &rtwdev->btc; 8650 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8651 8652 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8653 "[BTC], %s(): Init %s !!\n", __func__, 8654 chip_id_str(chip->chip_id)); 8655 8656 _reset_btc_var(rtwdev, BTC_RESET_ALL); 8657 8658 btc->dm.run_reason = BTC_RSN_NONE; 8659 btc->dm.run_action = BTC_ACT_NONE; 8660 wl->status.map.init_ok = true; 8661 } 8662 8663 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 8664 { 8665 struct rtw89_btc *btc = &rtwdev->btc; 8666 8667 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 8668 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 8669 } 8670 8671 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 8672 { 8673 struct rtw89_btc *btc = &rtwdev->btc; 8674 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8675 8676 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 8677 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 8678 8679 btc->cx.wl.status.map.rf_off = 1; 8680 btc->cx.wl.status.map.busy = 0; 8681 wl->status.map.lps = BTC_LPS_OFF; 8682 8683 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false); 8684 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 8685 8686 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 8687 } 8688 8689 #define BTC_PLATFORM_LITTLE_ENDIAN 0 8690 static void _set_init_info(struct rtw89_dev *rtwdev) 8691 { 8692 const struct rtw89_chip_info *chip = rtwdev->chip; 8693 struct rtw89_btc *btc = &rtwdev->btc; 8694 struct rtw89_btc_dm *dm = &btc->dm; 8695 struct rtw89_btc_cx *cx = &btc->cx; 8696 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8697 8698 dm->init_info.init_mode = wl->coex_mode; 8699 dm->init_info.wl_init_ok = wl->status.map.init_ok; 8700 dm->init_info.endian_type = BTC_PLATFORM_LITTLE_ENDIAN; 8701 dm->init_info.bt0_function = cx->bt0.func_type; 8702 dm->init_info.bt1_function = cx->bt1.func_type; 8703 dm->init_info.bt2_function = cx->bt_ext.func_type; 8704 dm->init_info.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE; 8705 dm->init_info.pta_direction = RTW89_MAC_AX_COEX_INNER; 8706 dm->init_info.wl_only = dm->wl_only; 8707 dm->init_info.bt_only = dm->bt_only; 8708 dm->init_info.wl_init_ok = wl->status.map.init_ok; 8709 dm->init_info.cx_other = btc->cx.bt_ext.func_type; 8710 dm->init_info.wl_guard_ch = chip->afh_guard_ch; 8711 dm->init_info.dbcc_en = rtwdev->dbcc_en; 8712 8713 dm->init_info.module = btc->mdinfo; 8714 8715 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 8716 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 8717 rtw89_btc_fw_set_slots(rtwdev); 8718 btc_fw_set_monreg(rtwdev); 8719 _set_ext_interface(rtwdev); 8720 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0); 8721 } 8722 8723 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 8724 { 8725 struct rtw89_btc *btc = &rtwdev->btc; 8726 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8727 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8728 const struct rtw89_chip_info *chip = rtwdev->chip; 8729 8730 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8731 "[BTC], %s(): mode=%d\n", __func__, mode); 8732 8733 wl->coex_mode = mode; 8734 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 8735 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 8736 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 8737 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 8738 dm->vid = rtwdev->custid; 8739 btc->ctrl.always_freerun = mode == BTC_MODE_COTX; 8740 8741 if (!wl->status.map.init_ok) { 8742 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8743 "[BTC], %s(): return for WL init fail!!\n", 8744 __func__); 8745 dm->error.map.init = true; 8746 return; 8747 } 8748 8749 btc->cx.bt0.enable.now = 1; 8750 btc->cx.bt0.run_patch_code = 1; 8751 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 8752 btc->cx.bt1.enable.now = 1; 8753 btc->cx.bt1.run_patch_code = 1; 8754 } 8755 8756 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) 8757 btc->io_oflld_type = BTC_IO_OFLD_BTC_H2C; 8758 else 8759 btc->io_oflld_type = BTC_IO_OFLD_NO_SUPPORT; 8760 8761 chip->ops->btc_set_rfe(rtwdev); 8762 chip->ops->btc_init_cfg(rtwdev); 8763 8764 _write_scbd(rtwdev, BTC_ALL_BT, 8765 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 8766 8767 if (rtw89_mac_get_ctrl_path(rtwdev)) { 8768 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8769 "[BTC], %s(): PTA owner warning!!\n", 8770 __func__); 8771 dm->error.map.pta_owner = true; 8772 } 8773 8774 _set_init_info(rtwdev); 8775 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0); 8776 btc_fw_set_monreg(rtwdev); 8777 rtw89_btc_fw_set_slots(rtwdev); 8778 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 8779 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 8780 8781 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 8782 } 8783 8784 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 8785 { 8786 struct rtw89_btc *btc = &rtwdev->btc; 8787 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8788 8789 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8790 "[BTC], %s(): phy_idx=%d, band=%d\n", 8791 __func__, phy_idx, band); 8792 8793 if (phy_idx >= RTW89_PHY_NUM) 8794 return; 8795 8796 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 8797 wl->status.map.scan = true; 8798 wl->scan_info.band[phy_idx] = band; 8799 wl->scan_info.phy_map |= BIT(phy_idx); 8800 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 8801 8802 if (rtwdev->dbcc_en) { 8803 wl->dbcc_info.scan_band[phy_idx] = band; 8804 _update_dbcc_band(rtwdev, phy_idx); 8805 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 8806 } 8807 8808 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) 8809 btc->ctrl.wl_ctrl_info.fw_scan = 1; 8810 8811 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 8812 } 8813 8814 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 8815 { 8816 struct rtw89_btc *btc = &rtwdev->btc; 8817 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8818 8819 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8820 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 8821 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 8822 8823 wl->status.map.scan = false; 8824 wl->scan_info.phy_map &= ~BIT(phy_idx); 8825 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 8826 8827 if (rtwdev->dbcc_en) { 8828 _update_dbcc_band(rtwdev, phy_idx); 8829 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 8830 } 8831 8832 btc->dm.tdma_instant_excute = 1; 8833 8834 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 8835 } 8836 8837 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 8838 { 8839 struct rtw89_btc *btc = &rtwdev->btc; 8840 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8841 8842 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8843 "[BTC], %s(): phy_idx=%d, band=%d\n", 8844 __func__, phy_idx, band); 8845 8846 if (phy_idx >= RTW89_PHY_NUM) 8847 return; 8848 8849 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 8850 8851 if (rtwdev->dbcc_en) { 8852 wl->dbcc_info.scan_band[phy_idx] = band; 8853 _update_dbcc_band(rtwdev, phy_idx); 8854 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 8855 } 8856 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 8857 } 8858 8859 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 8860 enum btc_pkt_type pkt_type) 8861 { 8862 struct rtw89_btc *btc = &rtwdev->btc; 8863 struct rtw89_btc_cx *cx = &btc->cx; 8864 struct rtw89_btc_wl_info *wl = &cx->wl; 8865 struct rtw89_btc_bt_link_info *b = &cx->bt0.link_info; 8866 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 8867 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 8868 u32 cnt; 8869 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 8870 bool delay_work = false; 8871 8872 switch (pkt_type) { 8873 case PACKET_DHCP: 8874 cnt = ++wl->wcnt[BTC_WCNT_DHCP]; 8875 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8876 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 8877 wl->status.map.handshake = 0; 8878 wl->status.map._4way = 0; 8879 wl->status.map.dhcp = 1; 8880 delay_work = true; 8881 break; 8882 case PACKET_EAPOL: 8883 cnt = ++wl->wcnt[BTC_WCNT_EAPOL]; 8884 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8885 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 8886 wl->status.map.handshake = 0; 8887 wl->status.map._4way = 1; 8888 wl->status.map.dhcp = 0; 8889 delay_work = true; 8890 if (hfp->exist || hid->exist) 8891 delay /= 2; 8892 break; 8893 case PACKET_EAPOL_END: 8894 cnt = ++wl->wcnt[BTC_WCNT_EAPOL]; 8895 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8896 "[BTC], %s(): EAPOL_End cnt=%d\n", 8897 __func__, cnt); 8898 wl->status.map._4way = 0; 8899 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 8900 break; 8901 case PACKET_ARP: 8902 cnt = ++wl->wcnt[BTC_WCNT_ARP]; 8903 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8904 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 8905 return; 8906 case PACKET_ICMP: 8907 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8908 "[BTC], %s(): ICMP pkt\n", __func__); 8909 return; 8910 default: 8911 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8912 "[BTC], %s(): unknown packet type %d\n", 8913 __func__, pkt_type); 8914 return; 8915 } 8916 8917 if (delay_work) { 8918 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 8919 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 8920 &rtwdev->coex_act1_work, delay); 8921 } 8922 8923 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 8924 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 8925 } 8926 8927 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 8928 { 8929 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8930 btc.eapol_notify_work); 8931 8932 lockdep_assert_wiphy(wiphy); 8933 8934 rtw89_leave_ps_mode(rtwdev); 8935 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 8936 } 8937 8938 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 8939 { 8940 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8941 btc.arp_notify_work); 8942 8943 lockdep_assert_wiphy(wiphy); 8944 8945 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 8946 } 8947 8948 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 8949 { 8950 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8951 btc.dhcp_notify_work); 8952 8953 lockdep_assert_wiphy(wiphy); 8954 8955 rtw89_leave_ps_mode(rtwdev); 8956 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 8957 } 8958 8959 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 8960 { 8961 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8962 btc.icmp_notify_work); 8963 8964 lockdep_assert_wiphy(wiphy); 8965 8966 rtw89_leave_ps_mode(rtwdev); 8967 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 8968 } 8969 8970 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi) 8971 { 8972 const struct rtw89_chip_info *chip = rtwdev->chip; 8973 struct rtw89_btc *btc = &rtwdev->btc; 8974 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 8975 u8 *rssi_st, rssi_th, rssi_level = 0; 8976 u8 i; 8977 8978 /* for rssi locate in which {40, 36, 31, 28} 8979 * if rssi >= 40% (-60dBm) --> rssi_level = 4 8980 * if 36% <= rssi < 40% --> rssi_level = 3 8981 * if 31% <= rssi < 36% --> rssi_level = 2 8982 * if 28% <= rssi < 31% --> rssi_level = 1 8983 * if rssi < 28% --> rssi_level = 0 8984 */ 8985 8986 /* check if rssi across bt_rssi_thres boundary */ 8987 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) { 8988 rssi_th = chip->bt_rssi_thres[i]; 8989 rssi_st = &bt->link_info.rssi_state[i]; 8990 8991 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th); 8992 8993 if (BTC_RSSI_HIGH(*rssi_st)) { 8994 rssi_level = BTC_BT_RSSI_THMAX - i; 8995 break; 8996 } 8997 } 8998 return rssi_level; 8999 } 9000 9001 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 9002 9003 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 bid, u8 *buf, u32 len) 9004 { 9005 const struct rtw89_chip_info *chip = rtwdev->chip; 9006 struct rtw89_btc *btc = &rtwdev->btc; 9007 struct rtw89_btc_bt_a2dp_desc *a2dp; 9008 struct rtw89_btc_cx *cx = &btc->cx; 9009 struct rtw89_btc_bt_hfp_desc *hfp; 9010 struct rtw89_btc_bt_hid_desc *hid; 9011 struct rtw89_btc_bt_pan_desc *pan; 9012 struct rtw89_btc_bt_link_info *b; 9013 struct rtw89_btc_bt_info *bt; 9014 union btc_btinfo btinfo; 9015 u8 is_bt_56g = 0; 9016 u8 *raw_info; 9017 9018 /* Bit7 is used for RF-band: 0:BT_2.4 GHz, 1:BT_5/6 GHz */ 9019 if ((buf[BTC_BTINFO_L1] & 0x7f) != 6) 9020 return; 9021 9022 bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 9023 9024 if ((buf[BTC_BTINFO_L1] & BIT(7)) && bt->band_56G_support) { 9025 b = &bt->link_info_56g; 9026 is_bt_56g = 1; 9027 if (b->status.map.connect) 9028 bt->rf_band_map |= BIT(RTW89_BAND_5G); 9029 else 9030 bt->rf_band_map &= ~BIT(RTW89_BAND_5G); 9031 } else { 9032 b = &bt->link_info; 9033 bt->rf_band_map |= BIT(RTW89_BAND_2G); 9034 } 9035 9036 hfp = &b->hfp_desc; 9037 hid = &b->hid_desc; 9038 a2dp = &b->a2dp_desc; 9039 pan = &b->pan_desc; 9040 raw_info = is_bt_56g ? bt->raw_info_56g : bt->raw_info; 9041 9042 if (!memcmp(raw_info, buf, BTC_BTINFO_MAX)) { 9043 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9044 "[BTC], %s(): return by bt-info duplicate!!\n", 9045 __func__); 9046 bt->bcnt[BTC_BCNT_INFOSAME]++; 9047 return; 9048 } 9049 9050 memcpy(raw_info, buf, BTC_BTINFO_MAX); 9051 9052 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9053 "[BTC], %s(): bt_info[2]=0x%02x\n", 9054 __func__, raw_info[2]); 9055 9056 hid->type = 0; 9057 9058 /* parse raw info low-Byte2 */ 9059 btinfo.val = raw_info[BTC_BTINFO_L2]; 9060 b->status.map.connect = btinfo.lb2.connect; 9061 b->status.map.sco_busy = btinfo.lb2.sco_busy; 9062 b->status.map.acl_busy = btinfo.lb2.acl_busy; 9063 b->status.map.inq_pag = btinfo.lb2.inq_pag; 9064 bt->inq_pag.now = btinfo.lb2.inq_pag; 9065 bt->bcnt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 9066 9067 hfp->exist = btinfo.lb2.hfp; 9068 hid->exist = btinfo.lb2.hid; 9069 a2dp->exist = btinfo.lb2.a2dp; 9070 pan->exist = btinfo.lb2.pan; 9071 _update_bt_link_cnt(rtwdev, bt, is_bt_56g); 9072 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 9073 9074 /* parse raw info low-Byte3 */ 9075 btinfo.val = raw_info[BTC_BTINFO_L3]; 9076 if (btinfo.lb3.retry != 0) 9077 bt->bcnt[BTC_BCNT_RETRY]++; 9078 b->cqddr = btinfo.lb3.cqddr; 9079 bt->bcnt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 9080 bt->inq = btinfo.lb3.inq; 9081 bt->bcnt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 9082 bt->pag = btinfo.lb3.pag; 9083 9084 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 9085 /* parse raw info high-Byte0 */ 9086 btinfo.val = raw_info[BTC_BTINFO_H0]; 9087 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 9088 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 9089 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi); 9090 btc->dm.trx_info.bt_rssi = bt->rssi_level; 9091 9092 /* parse raw info high-Byte1 */ 9093 btinfo.val = raw_info[BTC_BTINFO_H1]; 9094 b->status.map.ble_connect = btinfo.hb1.ble_connect; 9095 if (btinfo.hb1.ble_connect) { 9096 if (hid->exist) 9097 hid->type |= BTC_HID_BLE; 9098 else if (btinfo.hb1.voice) 9099 hid->type |= BTC_HID_RCU_VOICE; 9100 else 9101 hid->type |= BTC_HID_RCU; 9102 } 9103 9104 bt->bcnt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 9105 bt->reinit = btinfo.hb1.reinit; 9106 bt->bcnt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 9107 b->relink.now = btinfo.hb1.relink; 9108 bt->bcnt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 9109 bt->igno_wl = btinfo.hb1.igno_wl; 9110 9111 if (bt->igno_wl && !cx->wl.status.map.rf_off) 9112 _set_bt_ignore_wlan_act(rtwdev, false); 9113 9114 bt->ble_scan_en = btinfo.hb1.ble_scan; 9115 9116 bt->bcnt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 9117 b->role_sw = btinfo.hb1.role_sw; 9118 9119 b->multi_link.now = btinfo.hb1.multi_link; 9120 9121 /* parse raw info high-Byte2 */ 9122 btinfo.val = raw_info[BTC_BTINFO_H2]; 9123 pan->active = !!btinfo.hb2.pan_active; 9124 9125 bt->bcnt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 9126 b->afh_update = btinfo.hb2.afh_update; 9127 a2dp->active = btinfo.hb2.a2dp_active; 9128 b->slave_role = btinfo.hb2.slave; 9129 hid->slot_info = btinfo.hb2.hid_slot; 9130 hid->pair_cnt = btinfo.hb2.hid_cnt; 9131 if (!b->status.map.ble_connect || hid->pair_cnt > 1) 9132 hid->type |= (hid->slot_info == BTC_HID_218 ? 9133 BTC_HID_218 : BTC_HID_418); 9134 /* parse raw info high-Byte3 */ 9135 btinfo.val = raw_info[BTC_BTINFO_H3]; 9136 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 9137 9138 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 9139 bt->bcnt[BTC_BCNT_RATECHG]++; 9140 b->tx_3m = (u32)btinfo.hb3.tx_3m; 9141 9142 a2dp->sink = btinfo.hb3.a2dp_sink; 9143 9144 if (!a2dp->exist_last && a2dp->exist) { 9145 a2dp->vendor_id = 0; 9146 a2dp->flush_time = 0; 9147 a2dp->play_latency = 1; 9148 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9149 &rtwdev->coex_bt_devinfo_work, 9150 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 9151 } 9152 9153 _update_bt_ctrl_lps(rtwdev); 9154 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 9155 } 9156 9157 static void _ntfy_role_info(struct rtw89_dev *rtwdev, u8 rid, 9158 struct rtw89_btc_wl_link_info *info, 9159 enum btc_role_state reason) 9160 { 9161 struct rtw89_btc *btc = &rtwdev->btc; 9162 struct rtw89_btc_wl_link_info *wlinfo = NULL; 9163 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9164 const struct rtw89_btc_ver *ver = btc->ver; 9165 u8 rlink_id = info->phy; /* 1 role_id has 2 rlink_id(by HW_Band0/1) */ 9166 bool refresh_role = false; 9167 9168 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9169 "[BTC], %s(), role_id=%d, reason=%d\n", 9170 __func__, rid, reason); 9171 9172 if (rid >= ver->max_role_num || rlink_id >= RTW89_PHY_NUM) 9173 return; 9174 9175 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 9176 9177 wlinfo = &wl->rlink_info[rid][rlink_id]; 9178 memcpy(wlinfo, info, sizeof(struct rtw89_btc_wl_link_info)); 9179 9180 switch (reason) { 9181 case BTC_ROLE_START: 9182 wlinfo->active = true; 9183 return; 9184 case BTC_ROLE_STOP: 9185 wlinfo->active = false; 9186 return; 9187 case BTC_ROLE_MSTS_STA_CONN_START: 9188 wl->status.map.transacting = 1; 9189 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, 9190 &rtwdev->coex_act1_work); 9191 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9192 &rtwdev->coex_act1_work, 9193 RTW89_COEX_ACT1_WORK_PERIOD); 9194 break; 9195 case BTC_ROLE_MSTS_STA_CONN_END: 9196 wl->status.map.transacting = 0; 9197 refresh_role = true; 9198 break; 9199 case BTC_ROLE_MSTS_STA_DIS_CONN: 9200 wl->status.map.transacting = 1; 9201 refresh_role = false; 9202 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, 9203 &rtwdev->coex_act1_work); 9204 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9205 &rtwdev->coex_act1_work, 9206 RTW89_COEX_ACT1_WORK_PERIOD); 9207 break; 9208 case BTC_ROLE_MSTS_AP_START: 9209 case BTC_ROLE_MSTS_AP_STOP: 9210 refresh_role = true; 9211 break; 9212 case BTC_ROLE_STATE_UNKNOWN: 9213 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9214 "[BTC], %s(), role_id=%d, Unknown reason return!\n", 9215 __func__, rid); 9216 return; 9217 default: 9218 return; 9219 } 9220 9221 if (refresh_role) { 9222 _update_wl_info(rtwdev, wlinfo); 9223 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 9224 } 9225 9226 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 9227 } 9228 9229 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, 9230 struct rtw89_vif_link *rtwvif_link, 9231 struct rtw89_sta_link *rtwsta_link, 9232 enum btc_role_state state) 9233 { 9234 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 9235 rtwvif_link->chanctx_idx); 9236 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); 9237 struct ieee80211_p2p_noa_attr *noa_attr; 9238 struct ieee80211_p2p_noa_desc *noa_desc; 9239 struct ieee80211_bss_conf *bss_conf; 9240 struct ieee80211_link_sta *link_sta; 9241 struct rtw89_btc_wl_link_info r = {0}; 9242 u8 i, role_id, mode = 0; 9243 9244 rcu_read_lock(); 9245 9246 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); 9247 9248 role_id = rtwvif_link->port; 9249 9250 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 9251 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9252 "[BTC], role is STA=%d\n", 9253 vif->type == NL80211_IFTYPE_STATION); 9254 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", role_id); 9255 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 9256 chan->band_type, chan->channel, chan->band_width); 9257 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 9258 state == BTC_ROLE_MSTS_STA_CONN_END); 9259 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9260 "[BTC], bcn_period=%d dtim_period=%d\n", 9261 bss_conf->beacon_int, bss_conf->dtim_period); 9262 9263 if (rtwsta_link) { 9264 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); 9265 9266 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 9267 rtwsta_link->mac_id); 9268 9269 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9270 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 9271 link_sta->he_cap.has_he, 9272 link_sta->vht_cap.vht_supported, 9273 link_sta->ht_cap.ht_supported); 9274 if (link_sta->he_cap.has_he) 9275 mode |= BIT(BTC_WL_MODE_HE); 9276 if (link_sta->vht_cap.vht_supported) 9277 mode |= BIT(BTC_WL_MODE_VHT); 9278 if (link_sta->ht_cap.ht_supported) 9279 mode |= BIT(BTC_WL_MODE_HT); 9280 9281 r.mode = mode; 9282 } 9283 9284 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { 9285 rcu_read_unlock(); 9286 return; 9287 } 9288 9289 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9290 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); 9291 9292 if (vif->type == NL80211_IFTYPE_P2P_GO || 9293 vif->type == NL80211_IFTYPE_P2P_CLIENT) { 9294 noa_attr = &bss_conf->p2p_noa_attr; 9295 9296 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { 9297 noa_desc = &noa_attr->desc[i]; 9298 if (noa_desc->count != 0) { 9299 r.noa = 1; 9300 r.noa_duration = le32_to_cpu(noa_desc->duration); 9301 break; 9302 } 9303 } 9304 } 9305 9306 r.mode = mode; 9307 r.role = rtwvif_link->wifi_role; 9308 r.phy = rtwvif_link->phy_idx; 9309 r.pid = role_id; 9310 r.active = true; 9311 if (vif->active_links) { 9312 if (rtwvif_link->link_id < 16) 9313 r.active = !!(vif->active_links & BIT(rtwvif_link->link_id)); 9314 } 9315 r.bcn_period = bss_conf->beacon_int; 9316 r.dtim_period = bss_conf->dtim_period; 9317 r.band = chan->band_type; 9318 r.ch = chan->channel; 9319 r.bw = chan->band_width; 9320 r.chdef.band = chan->band_type; 9321 r.chdef.center_ch = chan->channel; 9322 r.chdef.bw = chan->band_width; 9323 r.chdef.chan = chan->primary_channel; 9324 9325 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) { 9326 r.mac_id = rtwsta_link->mac_id; 9327 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); 9328 } 9329 9330 switch (state) { 9331 case BTC_ROLE_MSTS_STA_CONN_END: 9332 case BTC_ROLE_MSTS_AP_START: 9333 r.connected = MLME_LINKED; 9334 break; 9335 default: 9336 r.connected = MLME_NO_LINK; 9337 break; 9338 } 9339 9340 rcu_read_unlock(); 9341 9342 _ntfy_role_info(rtwdev, role_id, &r, state); 9343 } 9344 9345 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 9346 { 9347 const struct rtw89_chip_info *chip = rtwdev->chip; 9348 struct rtw89_btc *btc = &rtwdev->btc; 9349 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9350 u32 val; 9351 9352 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 9353 __func__, rf_state); 9354 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 9355 9356 switch (rf_state) { 9357 case BTC_RFCTRL_WL_OFF: 9358 wl->status.map.rf_off = 1; 9359 wl->status.map.lps = BTC_LPS_OFF; 9360 wl->status.map.busy = 0; 9361 break; 9362 case BTC_RFCTRL_FW_CTRL: 9363 wl->status.map.rf_off = 0; 9364 wl->status.map.lps = BTC_LPS_RF_OFF; 9365 wl->status.map.busy = 0; 9366 break; 9367 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 9368 wl->status.map.rf_off = 0; 9369 wl->status.map.lps = BTC_LPS_RF_ON; 9370 wl->status.map.busy = 0; 9371 break; 9372 case BTC_RFCTRL_WL_ON: 9373 default: 9374 wl->status.map.rf_off = 0; 9375 wl->status.map.lps = BTC_LPS_OFF; 9376 break; 9377 } 9378 9379 if (rf_state == BTC_RFCTRL_WL_ON) { 9380 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 9381 _write_scbd(rtwdev, BTC_ALL_BT, val, true); 9382 chip->ops->btc_init_cfg(rtwdev); 9383 } else { 9384 if (rf_state == BTC_RFCTRL_FW_CTRL) 9385 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false); 9386 else if (rf_state == BTC_RFCTRL_WL_OFF) 9387 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false); 9388 else 9389 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false); 9390 } 9391 9392 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 9393 btc->dm.tdma_instant_excute = 1; 9394 9395 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 9396 wl->status.map.rf_off_pre = wl->status.map.rf_off; 9397 wl->status.map.lps_pre = wl->status.map.lps; 9398 } 9399 9400 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 9401 enum btc_wl_rfk_type type, 9402 enum btc_wl_rfk_state state) 9403 { 9404 struct rtw89_btc *btc = &rtwdev->btc; 9405 struct rtw89_btc_cx *cx = &btc->cx; 9406 struct rtw89_btc_wl_info *wl = &cx->wl; 9407 bool result = BTC_WRFK_REJECT; 9408 9409 wl->rfk_info.type = type; 9410 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 9411 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 9412 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 9413 9414 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9415 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 9416 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 9417 type, state); 9418 9419 switch (state) { 9420 case BTC_WRFK_START: 9421 result = BTC_WRFK_ALLOW; 9422 wl->rfk_info.state = BTC_WRFK_START; 9423 9424 btc->cx.wl.wcnt[BTC_WCNT_RFK_REQ]++; 9425 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 9426 9427 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, true); 9428 break; 9429 case BTC_WRFK_ONESHOT_START: 9430 case BTC_WRFK_ONESHOT_STOP: 9431 btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++; 9432 if (type != BTC_WRFKT_RXDCK) 9433 return BTC_WRFK_ALLOW; 9434 break; 9435 case BTC_WRFK_STOP: 9436 result = BTC_WRFK_ALLOW; 9437 wl->rfk_info.state = BTC_WRFK_STOP; 9438 9439 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false); 9440 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work); 9441 break; 9442 default: 9443 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9444 "[BTC], %s() warning state=%d\n", __func__, state); 9445 return result; 9446 } 9447 9448 if (result == BTC_WRFK_ALLOW) { 9449 if (wl->rfk_info.state == BTC_WRFK_START || 9450 wl->rfk_info.state == BTC_WRFK_STOP) 9451 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 9452 9453 if (wl->rfk_info.state == BTC_WRFK_START) 9454 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9455 &rtwdev->coex_rfk_chk_work, 9456 RTW89_COEX_RFK_CHK_WORK_PERIOD); 9457 } 9458 9459 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9460 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 9461 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 9462 9463 return result; 9464 } 9465 9466 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 9467 enum btc_wl_rfk_type type, 9468 enum btc_wl_rfk_state state) 9469 { 9470 u8 band; 9471 bool allow; 9472 int ret; 9473 9474 lockdep_assert_wiphy(rtwdev->hw->wiphy); 9475 9476 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 9477 9478 rtw89_debug(rtwdev, RTW89_DBG_RFK, 9479 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 9480 band == RTW89_BAND_2G ? "2G" : 9481 band == RTW89_BAND_5G ? "5G" : "6G", 9482 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 9483 type, 9484 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 9485 state == BTC_WRFK_STOP ? "RFK_STOP" : 9486 state == BTC_WRFK_START ? "RFK_START" : 9487 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 9488 "ONE-SHOT_STOP"); 9489 9490 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 9491 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 9492 return; 9493 } 9494 9495 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 9496 rtwdev, phy_map, type, state); 9497 if (ret) { 9498 rtw89_warn(rtwdev, "RFK notify timeout\n"); 9499 rtwdev->is_bt_iqk_timeout = true; 9500 } 9501 } 9502 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 9503 9504 struct rtw89_btc_wl_sta_iter_data { 9505 struct rtw89_dev *rtwdev; 9506 u8 busy_all; 9507 u8 dir_all; 9508 u8 rssi_map_all; 9509 bool is_sta_change; 9510 bool is_traffic_change; 9511 }; 9512 9513 static 9514 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, 9515 struct rtw89_sta_link *rtwsta_link, 9516 struct rtw89_btc_wl_sta_iter_data *iter_data) 9517 { 9518 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 9519 struct rtw89_dev *rtwdev = iter_data->rtwdev; 9520 struct rtw89_btc *btc = &rtwdev->btc; 9521 struct rtw89_btc_dm *dm = &btc->dm; 9522 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9523 struct rtw89_btc_wl_link_info *link_info = NULL; 9524 struct rtw89_traffic_stats *link_info_t = NULL; 9525 struct rtw89_traffic_stats *stats = &rtwvif->stats; 9526 const struct rtw89_chip_info *chip = rtwdev->chip; 9527 struct rtw89_btc_wl_role_info *r; 9528 u32 last_tx_rate, last_rx_rate; 9529 u8 link = rtwvif_link->phy_idx; 9530 u16 last_tx_lvl, last_rx_lvl; 9531 u8 port = rtwvif_link->port; 9532 u8 rssi; 9533 u8 busy = 0; 9534 u8 dir = 0; 9535 u8 rssi_map = 0; 9536 u8 i = 0; 9537 bool is_sta_change = false, is_traffic_change = false; 9538 9539 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; 9540 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 9541 9542 link_info = &wl->rlink_info[port][link]; 9543 9544 link_info->stat.traffic = *stats; 9545 link_info_t = &link_info->stat.traffic; 9546 9547 if (link_info->connected == MLME_NO_LINK) { 9548 link_info->rx_rate_drop_cnt = 0; 9549 return; 9550 } 9551 9552 link_info->stat.rssi = rssi; 9553 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 9554 link_info->rssi_state[i] = 9555 _update_rssi_state(rtwdev, 9556 link_info->rssi_state[i], 9557 link_info->stat.rssi, 9558 chip->wl_rssi_thres[i]); 9559 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 9560 rssi_map |= BIT(i); 9561 9562 if (btc->ant_type == BTC_ANT_DEDICATED && 9563 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 9564 is_sta_change = true; 9565 } 9566 iter_data->rssi_map_all |= rssi_map; 9567 9568 last_tx_rate = link_info_t->tx_rate; 9569 last_rx_rate = link_info_t->rx_rate; 9570 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 9571 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 9572 9573 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 9574 stats->rx_tfc_lv != RTW89_TFC_IDLE) 9575 busy = 1; 9576 9577 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 9578 dir = RTW89_TFC_UL; 9579 else 9580 dir = RTW89_TFC_DL; 9581 9582 if (link_info->busy != busy || link_info->dir != dir) { 9583 is_sta_change = true; 9584 link_info->busy = busy; 9585 link_info->dir = dir; 9586 } 9587 9588 iter_data->busy_all |= busy; 9589 iter_data->dir_all |= BIT(dir); 9590 9591 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 9592 last_rx_rate > RTW89_HW_RATE_CCK2 && 9593 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 9594 link_info->rx_rate_drop_cnt++; 9595 9596 if (last_tx_rate != rtwsta_link->ra_report.hw_rate || 9597 last_rx_rate != rtwsta_link->rx_hw_rate || 9598 last_tx_lvl != link_info_t->tx_tfc_lv || 9599 last_rx_lvl != link_info_t->rx_tfc_lv) 9600 is_traffic_change = true; 9601 9602 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; 9603 link_info_t->rx_rate = rtwsta_link->rx_hw_rate; 9604 9605 if (link_info->role == RTW89_WIFI_ROLE_STATION || 9606 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 9607 dm->trx_info.tx_rate = link_info_t->tx_rate; 9608 dm->trx_info.rx_rate = link_info_t->rx_rate; 9609 } 9610 9611 r = &wl->role_info; 9612 r->rlink[port][link].tx_lvl = stats->tx_tfc_lv; 9613 r->rlink[port][link].rx_lvl = stats->rx_tfc_lv; 9614 r->rlink[port][link].tx_rate = rtwsta_link->ra_report.hw_rate; 9615 r->rlink[port][link].rx_rate = rtwsta_link->rx_hw_rate; 9616 9617 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 9618 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 9619 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; 9620 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; 9621 dm->trx_info.tx_tp = link_info_t->tx_throughput; 9622 dm->trx_info.rx_tp = link_info_t->rx_throughput; 9623 9624 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */ 9625 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx && 9626 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) || 9627 (dm->wl_pre_agc_rb != dm->wl_pre_agc && 9628 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND)) 9629 iter_data->is_sta_change = true; 9630 9631 if (is_sta_change) 9632 iter_data->is_sta_change = true; 9633 9634 if (is_traffic_change) 9635 iter_data->is_traffic_change = true; 9636 } 9637 9638 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 9639 { 9640 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 9641 struct rtw89_btc_wl_sta_iter_data *iter_data = 9642 (struct rtw89_btc_wl_sta_iter_data *)data; 9643 struct rtw89_vif_link *rtwvif_link; 9644 struct rtw89_sta_link *rtwsta_link; 9645 unsigned int link_id; 9646 9647 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 9648 rtwvif_link = rtwsta_link->rtwvif_link; 9649 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); 9650 } 9651 } 9652 9653 #define BTC_NHM_CHK_INTVL 20 9654 9655 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 9656 { 9657 struct rtw89_btc *btc = &rtwdev->btc; 9658 struct rtw89_btc_dm *dm = &btc->dm; 9659 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9660 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 9661 u8 i; 9662 9663 ieee80211_iterate_stations_atomic(rtwdev->hw, 9664 rtw89_btc_ntfy_wl_sta_iter, 9665 &data); 9666 9667 wl->rssi_level = 0; 9668 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 9669 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 9670 /* set RSSI level 4 ~ 0 if rssi bit map match */ 9671 if (data.rssi_map_all & BIT(i - 1)) { 9672 wl->rssi_level = i; 9673 break; 9674 } 9675 } 9676 9677 if (dm->trx_info.wl_rssi != wl->rssi_level) 9678 dm->trx_info.wl_rssi = wl->rssi_level; 9679 9680 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 9681 __func__, !!wl->status.map.busy); 9682 9683 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 9684 9685 if (data.is_traffic_change) 9686 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 9687 if (data.is_sta_change) { 9688 wl->status.map.busy = data.busy_all; 9689 wl->status.map.traffic_dir = data.dir_all; 9690 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 9691 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 9692 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 9693 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 9694 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 9695 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 9696 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 9697 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 9698 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 9699 } 9700 } 9701 9702 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) 9703 { 9704 struct rtw89_btc *btc = &rtwdev->btc; 9705 const struct rtw89_btc_ver *ver = btc->ver; 9706 9707 switch (func) { 9708 case BTF_EVNT_RPT: 9709 case BTF_EVNT_BT_INFO: 9710 case BTF_EVNT_BT_SCBD: 9711 case BTF_EVNT_BT_REG: 9712 case BTF_EVNT_CX_RUNINFO: 9713 case BTF_EVNT_BT_PSD: 9714 return func; 9715 case BTF_EVNT_BT_DEV_INFO: 9716 if (ver->fwc2hfunc == 0) 9717 return BTF_EVNT_BUF_OVERFLOW; 9718 else 9719 return BTF_EVNT_BT_DEV_INFO; 9720 case BTF_EVNT_BT_LEAUDIO_INFO: 9721 if (ver->fwc2hfunc == 0) 9722 return BTF_EVNT_C2H_LOOPBACK; 9723 else if (ver->fwc2hfunc == 1) 9724 return BTF_EVNT_BUF_OVERFLOW; 9725 else if (ver->fwc2hfunc == 2) 9726 return func; 9727 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 9728 return BTF_EVNT_BUF_OVERFLOW; 9729 else 9730 return BTF_EVNT_MAX; 9731 case BTF_EVNT_BUF_OVERFLOW: 9732 if (ver->fwc2hfunc == 0) 9733 return BTF_EVNT_MAX; 9734 else if (ver->fwc2hfunc == 1) 9735 return BTF_EVNT_C2H_LOOPBACK; 9736 else if (ver->fwc2hfunc == 2) 9737 return func; 9738 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 9739 return BTF_EVNT_C2H_LOOPBACK; 9740 else 9741 return BTF_EVNT_MAX; 9742 case BTF_EVNT_C2H_LOOPBACK: 9743 if (ver->fwc2hfunc == 2) 9744 return func; 9745 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 9746 return BTF_EVNT_BT_LEAUDIO_INFO; 9747 else 9748 return BTF_EVNT_MAX; 9749 case BTF_EVNT_BT_QUERY_TXPWR: 9750 if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 9751 return func; 9752 else 9753 return BTF_EVNT_MAX; 9754 case BTF_EVNT_ZB_INFO: 9755 case BTF_EVNT_ZB_CH: 9756 case BTF_EVNT_ZB_QUERY_TXPWR: 9757 if (ver->fwc2hfunc == 4) 9758 return func; 9759 else 9760 return BTF_EVNT_MAX; 9761 case BTF_EVNT_MAX: 9762 default: 9763 return BTF_EVNT_MAX; 9764 } 9765 } 9766 9767 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 9768 u32 len, u8 class, u8 func) 9769 { 9770 struct rtw89_btc *btc = &rtwdev->btc; 9771 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 9772 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9773 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 9774 u8 bid = BTC_BT_1ST; 9775 9776 len -= RTW89_C2H_HEADER_LEN; 9777 9778 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9779 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 9780 __func__, len, class, func); 9781 9782 if (class != BTFC_FW_EVENT) 9783 return; 9784 9785 if (func & BT_C2H_FUNC_BT2ND) { 9786 bid = BTC_BT_2ND; 9787 func &= ~BT_C2H_FUNC_BT2ND; 9788 bt = &btc->cx.bt1; 9789 } 9790 9791 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); 9792 pfwinfo->cnt_c2h++; 9793 9794 switch (func) { 9795 case BTF_EVNT_BUF_OVERFLOW: 9796 pfwinfo->event[func]++; 9797 break; 9798 case BTF_EVNT_RPT: 9799 pfwinfo->event[func]++; 9800 /* Don't need rtw89_leave_ps_mode() */ 9801 btc_fw_event(rtwdev, func, buf, len); 9802 break; 9803 case BTF_EVNT_BT_INFO: 9804 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9805 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 9806 bt->bcnt[BTC_BCNT_INFOUPDATE]++; 9807 _update_bt_info(rtwdev, bid, buf, len); 9808 break; 9809 case BTF_EVNT_BT_SCBD: 9810 bt->bcnt[BTC_BCNT_SCBDUPDATE]++; 9811 bt->scbd_c2h = ((buf[3] << 24) | (buf[2] << 16) | 9812 (buf[1] << 8) | (buf[0])); 9813 bt->scbd_rb = bt->scbd_c2h; 9814 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9815 "[BTC], handle C2H BT%d SCBD with data 0x%08x\n", 9816 bid, bt->scbd_c2h); 9817 _update_bt_scbd(rtwdev, bid); 9818 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 9819 break; 9820 case BTF_EVNT_BT_PSD: 9821 break; 9822 case BTF_EVNT_BT_REG: 9823 btc->dbg.rb_done = true; 9824 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 9825 9826 break; 9827 case BTF_EVNT_C2H_LOOPBACK: 9828 btc->dbg.rb_done = true; 9829 btc->dbg.rb_val = buf[0]; 9830 break; 9831 case BTF_EVNT_CX_RUNINFO: 9832 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 9833 break; 9834 case BTF_EVNT_BT_LEAUDIO_INFO: 9835 bt->bcnt[BTC_BCNT_LEAUDIO_INFOUPDATE]++; 9836 if (buf[BTC_BTINFO_L0] == BTC_BTINFO_BISTDMA) 9837 _update_bt_bistdma_info(rtwdev, bid, buf, len); 9838 else 9839 _update_bt_leaudio_info(rtwdev, bid, buf, len); 9840 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_LEAUDINFO); 9841 break; 9842 case BTF_EVNT_BT_QUERY_TXPWR: 9843 bt->bcnt[BTC_BCNT_TXPWR_UPDATE]++; 9844 _update_bt_txpwr_info(rtwdev, buf, len); 9845 } 9846 } 9847 9848 #define BTC_CX_FW_OFFLOAD 0 9849 9850 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9851 { 9852 struct rtw89_btc_module *md = &rtwdev->btc.mdinfo; 9853 const struct rtw89_chip_info *chip = rtwdev->chip; 9854 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 9855 struct rtw89_hal *hal = &rtwdev->hal; 9856 struct rtw89_btc *btc = &rtwdev->btc; 9857 struct rtw89_btc_dm *dm = &btc->dm; 9858 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 9859 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9860 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 9861 char *p = buf, *end = buf + bufsz; 9862 9863 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 9864 return 0; 9865 9866 p += scnprintf(p, end - p, 9867 "\n========== [BTC COEX INFO (%s)] ==========\n", 9868 chip_id_str(chip->chip_id)); 9869 9870 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 9871 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 9872 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 9873 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 9874 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ", 9875 "[coex_version]", ver_main, ver_sub, ver_hotfix, 9876 id_branch); 9877 9878 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 9879 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 9880 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 9881 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 9882 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)", 9883 ver_main, ver_sub, ver_hotfix, id_branch); 9884 9885 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 9886 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 9887 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 9888 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ", 9889 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 9890 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 9891 9892 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n", 9893 bt->ver_info.fw_coex, 9894 (bt->ver_info.fw_coex >= ver->bt_desired ? 9895 "Match" : "Mismatch"), ver->bt_desired); 9896 9897 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 9898 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 9899 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 9900 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 9901 p += scnprintf(p, end - p, 9902 " %-15s : WL_FW:%d.%d.%d.%d(built:%.12s-%.12s), BT_FW:0x%x(%s)\n", 9903 "[sub_module]", 9904 ver_main, ver_sub, ver_hotfix, id_branch, 9905 wl->ver_info.build_time, wl->ver_info.build_date, 9906 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 9907 9908 p += scnprintf(p, end - p, 9909 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 9910 "[hw_info]", 9911 md->kt_ver, md->rfe_type, md->ant.isolation, 9912 md->ant.num, md->ant.num > 1 ? "" : 9913 md->ant.single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, "); 9914 9915 p += scnprintf(p, end - p, 9916 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 9917 btc->cx.bt_ext.func_type, rtwdev->dbcc_en, hal->tx_nss, 9918 hal->rx_nss); 9919 9920 return p - buf; 9921 } 9922 9923 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9924 { 9925 struct rtw89_btc *btc = &rtwdev->btc; 9926 struct rtw89_btc_wl_link_info *plink = NULL; 9927 struct rtw89_traffic_stats *t; 9928 char *p = buf, *end = buf + bufsz; 9929 u8 i, j; 9930 9931 for (i = 0; i < btc->ver->max_role_num; i++) { 9932 for (j = 0; j < RTW89_MAC_NUM; j++) { 9933 plink = &btc->cx.wl.rlink_info[i][j]; 9934 9935 if (!plink->active) 9936 continue; 9937 9938 p += scnprintf(p, end - p, 9939 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 9940 plink->pid, plink->role, plink->phy, 9941 id_to_mlme_state(plink->connected), 9942 plink->client_cnt - 1, plink->mode, 9943 plink->ch, plink->bw); 9944 9945 if (plink->connected == MLME_NO_LINK) { 9946 p += scnprintf(p, end - p, "\n"); 9947 continue; 9948 } 9949 9950 p += scnprintf(p, end - p, 9951 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 9952 plink->mac_id, plink->tx_time, plink->tx_retry); 9953 9954 p += scnprintf(p, end - p, 9955 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 9956 plink->pid, 110 - plink->stat.rssi, 9957 plink->stat.rssi, plink->busy, 9958 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 9959 9960 t = &plink->stat.traffic; 9961 9962 p += scnprintf(p, end - p, 9963 "tx[rate:%d/busy_level:%d], ", 9964 t->tx_rate, t->tx_tfc_lv); 9965 9966 p += scnprintf(p, end - p, 9967 "rx[rate:%d/busy_level:%d/drop:%d]\n", 9968 t->rx_rate, 9969 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 9970 } 9971 } 9972 return p - buf; 9973 } 9974 9975 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9976 { 9977 struct rtw89_btc *btc = &rtwdev->btc; 9978 struct rtw89_btc_cx *cx = &btc->cx; 9979 struct rtw89_btc_wl_info *wl = &cx->wl; 9980 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 9981 char *p = buf, *end = buf + bufsz; 9982 u8 mode; 9983 9984 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 9985 return 0; 9986 9987 p += scnprintf(p, end - p, "========== [WL Status] ==========\n"); 9988 9989 mode = wl_rinfo->link_mode; 9990 9991 p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]", 9992 id_to_linkmode(mode)); 9993 9994 p += scnprintf(p, end - p, 9995 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 9996 wl->status.map.rf_off, wl->status.map.lps, 9997 wl->status.map.scan ? "Y" : "N", 9998 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 9999 10000 p += scnprintf(p, end - p, 10001 "handshake:%s, roam:%s, 4way:%s, init_ok:%s\n", 10002 wl->status.map.handshake ? "Y" : "N", 10003 wl->status.map.roaming ? "Y" : "N", 10004 wl->status.map._4way ? "Y" : "N", 10005 wl->status.map.init_ok ? "Y" : "N"); 10006 10007 p += _show_wl_role_info(rtwdev, p, end - p); 10008 10009 return p - buf; 10010 } 10011 10012 enum btc_bt_a2dp_type { 10013 BTC_A2DP_LEGACY = 0, 10014 BTC_A2DP_TWS_SNIFF = 1, 10015 BTC_A2DP_TWS_RELAY = 2, 10016 }; 10017 10018 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, 10019 size_t bufsz, u8 bid) 10020 { 10021 struct rtw89_btc *btc = &rtwdev->btc; 10022 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? 10023 &btc->cx.bt0 : &btc->cx.bt1; 10024 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 10025 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 10026 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 10027 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 10028 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 10029 char *p = buf, *end = buf + bufsz; 10030 10031 if (hfp.exist) { 10032 p += scnprintf(p, end - p, 10033 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 10034 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 10035 bt_linfo->sut_pwr_level[0], 10036 bt_linfo->golden_rx_shift[0]); 10037 } 10038 10039 if (hid.exist) { 10040 p += scnprintf(p, end - p, 10041 "\n %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 10042 "[HID]", 10043 hid.type & BTC_HID_218 ? "2/18," : "", 10044 hid.type & BTC_HID_418 ? "4/18," : "", 10045 hid.type & BTC_HID_BLE ? "BLE," : "", 10046 hid.type & BTC_HID_RCU ? "RCU," : "", 10047 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 10048 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 10049 bt_linfo->golden_rx_shift[1]); 10050 } 10051 10052 if (a2dp.exist) { 10053 p += scnprintf(p, end - p, 10054 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 10055 "[A2DP]", 10056 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 10057 a2dp.bitpool, a2dp.flush_time); 10058 10059 p += scnprintf(p, end - p, 10060 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 10061 a2dp.vendor_id, a2dp.device_name, 10062 bt_linfo->sut_pwr_level[2], 10063 bt_linfo->golden_rx_shift[2]); 10064 } 10065 10066 if (pan.exist) { 10067 p += scnprintf(p, end - p, 10068 " %-15s : sut_pwr:%d, golden-rx:%d\n", 10069 "[PAN]", 10070 bt_linfo->sut_pwr_level[3], 10071 bt_linfo->golden_rx_shift[3]); 10072 } 10073 10074 return p - buf; 10075 } 10076 10077 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, u8 bid) 10078 { 10079 struct rtw89_btc *btc = &rtwdev->btc; 10080 const struct rtw89_btc_ver *ver = btc->ver; 10081 struct rtw89_btc_cx *cx = &btc->cx; 10082 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 10083 struct rtw89_btc_wl_info *wl = &cx->wl; 10084 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 10085 struct rtw89_btc_module *md = &btc->mdinfo; 10086 u8 bt_pos = (bid == BTC_BT_1ST) ? md->bt0_pos : md->bt1_pos; 10087 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm; 10088 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm; 10089 u8 hw_band = wl->role_info.pta_req_band; 10090 struct rtw89_btc_wl_afh_info *wl_afh; 10091 char *p = buf, *end = buf + bufsz; 10092 u8 *afh = bt_linfo->afh_map; 10093 u8 *afh_le = bt_linfo->afh_map_le; 10094 10095 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 10096 return 0; 10097 10098 if (bid == BTC_BT_2ND) { 10099 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 10100 return 0; 10101 if (!bt->enable.now) 10102 return 0; 10103 } 10104 10105 p += scnprintf(p, end - p, "========== [BT_%s Status] ==========\n", 10106 bid == BTC_BT_1ST ? "1ST" : "2ND"); 10107 10108 p += scnprintf(p, end - p, 10109 " %-15s : enable:%s, btg:%s%s, connect:%s, ", 10110 "[status]", bt->enable.now ? "Y" : "N", 10111 bt->btg_type ? "Y" : "N", 10112 (bt->enable.now && (bt->btg_type != bt_pos) ? 10113 "(efuse-mismatch!!)" : ""), 10114 (bt_linfo->status.map.connect ? "Y" : "N")); 10115 10116 p += scnprintf(p, end - p, 10117 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 10118 bt->igno_wl ? "Y" : "N", 10119 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 10120 10121 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ", 10122 "[profile]", 10123 (bt_linfo->link_cnt.now == 0) ? "None," : "", 10124 bt_linfo->hfp_desc.exist ? "HFP," : "", 10125 bt_linfo->hid_desc.exist ? "HID," : "", 10126 bt_linfo->a2dp_desc.exist ? 10127 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 10128 bt_linfo->pan_desc.exist ? "PAN," : ""); 10129 10130 p += scnprintf(p, end - p, 10131 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 10132 bt_linfo->multi_link.now ? "Y" : "N", 10133 bt_linfo->slave_role ? "Slave" : "Master", 10134 bt_linfo->status.map.ble_connect ? "Y" : "N", 10135 bt_linfo->cqddr ? "Y" : "N", 10136 bt_linfo->a2dp_desc.active ? "Y" : "N", 10137 bt_linfo->pan_desc.active ? "Y" : "N"); 10138 10139 p += scnprintf(p, end - p, 10140 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s", 10141 "[link]", bt_linfo->rssi - 100, 10142 bt->rssi_level, 10143 bt_linfo->tx_3m ? 3 : 2, 10144 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 10145 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 10146 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 10147 10148 p += scnprintf(p, end - p, 10149 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 10150 bt_linfo->relink.now ? " ReLink!!" : "", 10151 afh[0], afh[1], afh[2], afh[3], afh[4], 10152 afh[5], afh[6], afh[7], afh[8], afh[9]); 10153 10154 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 10155 p += scnprintf(p, end - p, 10156 "LE[%02x%02x_%02x_%02x%02x]", 10157 afh_le[0], afh_le[1], afh_le[2], 10158 afh_le[3], afh_le[4]); 10159 10160 wl_afh = &wl->afh_info[hw_band][RTW89_BAND_2G]; 10161 p += scnprintf(p, end - p, "wl_ch_map[hwb:%d/en:%d/ch:%d/bw:%d/rf_band:%d]\n", 10162 hw_band, wl_afh->en, wl_afh->ch, wl_afh->bw, wl_afh->band); 10163 10164 p += scnprintf(p, end - p, 10165 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 10166 "[stat_cnt]", bt->bcnt[BTC_BCNT_RETRY], 10167 bt->bcnt[BTC_BCNT_RELINK], 10168 bt->bcnt[BTC_BCNT_RATECHG], 10169 bt->bcnt[BTC_BCNT_REINIT], 10170 bt->bcnt[BTC_BCNT_REENABLE]); 10171 10172 p += scnprintf(p, end - p, 10173 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 10174 bt->bcnt[BTC_BCNT_ROLESW], bt->bcnt[BTC_BCNT_AFH], 10175 bt->bcnt[BTC_BCNT_INQPAG], bt->bcnt[BTC_BCNT_INQ], 10176 bt->bcnt[BTC_BCNT_PAGE], bt->bcnt[BTC_BCNT_IGNOWL]); 10177 10178 p += _show_bt_profile_info(rtwdev, p, end - p, bid); 10179 10180 p += scnprintf(p, end - p, 10181 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 10182 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 10183 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 10184 bt->raw_info[7], 10185 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 10186 bt->bcnt[BTC_BCNT_INFOUPDATE], 10187 bt->bcnt[BTC_BCNT_INFOSAME]); 10188 10189 p += scnprintf(p, end - p, 10190 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 10191 "[trx_req_cnt]", bt->bcnt[BTC_BCNT_HIPRI_RX], 10192 bt->bcnt[BTC_BCNT_HIPRI_TX], 10193 bt->bcnt[BTC_BCNT_LOPRI_RX], 10194 bt->bcnt[BTC_BCNT_LOPRI_TX], 10195 bt->bcnt[BTC_BCNT_POLLUTED]); 10196 10197 if (ver->fcxbtscan == 1) { 10198 p += scnprintf(p, end - p, 10199 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 10200 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 10201 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 10202 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 10203 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 10204 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 10205 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 10206 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 10207 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 10208 } else if (ver->fcxbtscan == 2) { 10209 p += scnprintf(p, end - p, 10210 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 10211 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 10212 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 10213 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 10214 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 10215 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 10216 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 10217 } 10218 p += scnprintf(p, end - p, "\n"); 10219 10220 if (bt->bcnt[BTC_BCNT_TXPWR_UPDATE]) { 10221 p += scnprintf(p, end - p, 10222 " %-15s : br_index:0x%x, le_index:0x%x", 10223 "[bt_txpwr_lvl]", 10224 bt->link_info.bt_txpwr_desc.br_gain_index, 10225 bt->link_info.bt_txpwr_desc.le_gain_index); 10226 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm); 10227 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm); 10228 } else { 10229 p += scnprintf(p, end - p, 10230 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]", 10231 "[bt_txpwr_lvl]", 10232 bt->link_info.bt_txpwr_desc.br_dbm, 10233 bt->link_info.bt_txpwr_desc.le_dbm); 10234 } 10235 p += scnprintf(p, end - p, "\n"); 10236 10237 return p - buf; 10238 } 10239 10240 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 10241 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 10242 #define CASE_BTC_POLICY_STR(e) \ 10243 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 10244 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 10245 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 10246 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e 10247 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e 10248 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e 10249 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e 10250 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e 10251 #define CASE_BTC_H2CCMD(e) case SET_##e: return #e 10252 10253 static const char *id_to_polut(u32 id) 10254 { 10255 switch (id) { 10256 CASE_BTC_POLUT_STR(NONE); 10257 CASE_BTC_POLUT_STR(GNT_BT_TX); 10258 CASE_BTC_POLUT_STR(GNT_BT_RX); 10259 CASE_BTC_POLUT_STR(GNT_WL); 10260 CASE_BTC_POLUT_STR(BT); 10261 CASE_BTC_POLUT_STR(ALL); 10262 default: 10263 return "unknown"; 10264 } 10265 } 10266 10267 static const char *id_to_regtype(u32 id) 10268 { 10269 switch (id) { 10270 CASE_BTC_REGTYPE_STR(MAC); 10271 CASE_BTC_REGTYPE_STR(BB); 10272 CASE_BTC_REGTYPE_STR(RF); 10273 CASE_BTC_REGTYPE_STR(BT_RF); 10274 CASE_BTC_REGTYPE_STR(BT_MODEM); 10275 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE); 10276 CASE_BTC_REGTYPE_STR(BT_VENDOR); 10277 CASE_BTC_REGTYPE_STR(BT_LE); 10278 default: 10279 return "unknown"; 10280 } 10281 } 10282 10283 static const char *id_to_gdbg(u32 id) 10284 { 10285 switch (id) { 10286 CASE_BTC_GDBG_STR(GNT_BT); 10287 CASE_BTC_GDBG_STR(GNT_WL); 10288 CASE_BTC_GDBG_STR(GNT_BT1); 10289 CASE_BTC_GDBG_STR(GNT_WL1); 10290 CASE_BTC_GDBG_STR(BCN_EARLY); 10291 CASE_BTC_GDBG_STR(WL_NULL0); 10292 CASE_BTC_GDBG_STR(WL_NULL1); 10293 CASE_BTC_GDBG_STR(WL_RXISR); 10294 CASE_BTC_GDBG_STR(TDMA_ENTRY); 10295 CASE_BTC_GDBG_STR(A2DP_EMPTY); 10296 CASE_BTC_GDBG_STR(BT_RETRY); 10297 CASE_BTC_GDBG_STR(BT_RELINK); 10298 CASE_BTC_GDBG_STR(SLOT_WL); 10299 CASE_BTC_GDBG_STR(SLOT_BT); 10300 CASE_BTC_GDBG_STR(WL_ERR); 10301 CASE_BTC_GDBG_STR(WL_OK); 10302 CASE_BTC_GDBG_STR(SLOT_B2W); 10303 CASE_BTC_GDBG_STR(SLOT_W1); 10304 CASE_BTC_GDBG_STR(SLOT_W2); 10305 CASE_BTC_GDBG_STR(SLOT_W2B); 10306 CASE_BTC_GDBG_STR(SLOT_B1); 10307 CASE_BTC_GDBG_STR(SLOT_B2); 10308 CASE_BTC_GDBG_STR(SLOT_B3); 10309 CASE_BTC_GDBG_STR(SLOT_B4); 10310 CASE_BTC_GDBG_STR(SLOT_LK); 10311 CASE_BTC_GDBG_STR(SLOT_E2G); 10312 CASE_BTC_GDBG_STR(SLOT_E5G); 10313 CASE_BTC_GDBG_STR(SLOT_EBT); 10314 CASE_BTC_GDBG_STR(SLOT_WLK); 10315 CASE_BTC_GDBG_STR(SLOT_B1FDD); 10316 CASE_BTC_GDBG_STR(BT_CHANGE); 10317 CASE_BTC_GDBG_STR(WL_CCA); 10318 default: 10319 return "unknown"; 10320 } 10321 } 10322 10323 static const char *steps_to_str(u16 step) 10324 { 10325 switch (step) { 10326 CASE_BTC_RSN_STR(NONE); 10327 CASE_BTC_RSN_STR(NTFY_INIT); 10328 CASE_BTC_RSN_STR(NTFY_SWBAND); 10329 CASE_BTC_RSN_STR(NTFY_WL_STA); 10330 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 10331 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 10332 CASE_BTC_RSN_STR(NTFY_WL_RFK); 10333 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 10334 CASE_BTC_RSN_STR(NTFY_SCAN_START); 10335 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 10336 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 10337 CASE_BTC_RSN_STR(NTFY_POWEROFF); 10338 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 10339 CASE_BTC_RSN_STR(CMD_SET_COEX); 10340 CASE_BTC_RSN_STR(ACT1_WORK); 10341 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 10342 CASE_BTC_RSN_STR(RFK_CHK_WORK); 10343 CASE_BTC_RSN_STR(UPDATE_BT_LEAUDINFO); 10344 10345 CASE_BTC_ACT_STR(NONE); 10346 CASE_BTC_ACT_STR(WL_ONLY); 10347 CASE_BTC_ACT_STR(WL_5G); 10348 CASE_BTC_ACT_STR(WL_OTHER); 10349 CASE_BTC_ACT_STR(WL_IDLE); 10350 CASE_BTC_ACT_STR(WL_NC); 10351 CASE_BTC_ACT_STR(WL_RFK); 10352 CASE_BTC_ACT_STR(WL_INIT); 10353 CASE_BTC_ACT_STR(WL_OFF); 10354 CASE_BTC_ACT_STR(FREERUN); 10355 CASE_BTC_ACT_STR(BT_WHQL); 10356 CASE_BTC_ACT_STR(BT_RFK); 10357 CASE_BTC_ACT_STR(BT_OFF); 10358 CASE_BTC_ACT_STR(BT_IDLE); 10359 CASE_BTC_ACT_STR(BT_HFP); 10360 CASE_BTC_ACT_STR(BT_HID); 10361 CASE_BTC_ACT_STR(BT_A2DP); 10362 CASE_BTC_ACT_STR(BT_A2DPSINK); 10363 CASE_BTC_ACT_STR(BT_PAN); 10364 CASE_BTC_ACT_STR(BT_A2DP_HID); 10365 CASE_BTC_ACT_STR(BT_A2DP_PAN); 10366 CASE_BTC_ACT_STR(BT_PAN_HID); 10367 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 10368 CASE_BTC_ACT_STR(BT_BIS); 10369 CASE_BTC_ACT_STR(BT_CIS); 10370 CASE_BTC_ACT_STR(WL_25G_MCC); 10371 CASE_BTC_ACT_STR(WL_2G_MCC); 10372 CASE_BTC_ACT_STR(WL_2G_SCC); 10373 CASE_BTC_ACT_STR(WL_2G_AP); 10374 CASE_BTC_ACT_STR(WL_2G_GO); 10375 CASE_BTC_ACT_STR(WL_2G_GC); 10376 CASE_BTC_ACT_STR(WL_2G_NAN); 10377 10378 CASE_BTC_POLICY_STR(OFF_BT); 10379 CASE_BTC_POLICY_STR(OFF_WL); 10380 CASE_BTC_POLICY_STR(OFF_EQ0); 10381 CASE_BTC_POLICY_STR(OFF_EQ1); 10382 CASE_BTC_POLICY_STR(OFF_EQ2); 10383 CASE_BTC_POLICY_STR(OFF_EQ3); 10384 CASE_BTC_POLICY_STR(OFF_EQ4); 10385 CASE_BTC_POLICY_STR(OFF_EQ5); 10386 CASE_BTC_POLICY_STR(OFF_BWB0); 10387 CASE_BTC_POLICY_STR(OFF_BWB1); 10388 CASE_BTC_POLICY_STR(OFF_BWB2); 10389 CASE_BTC_POLICY_STR(OFF_BWB3); 10390 CASE_BTC_POLICY_STR(OFF_WL2); 10391 CASE_BTC_POLICY_STR(OFFB_BWB0); 10392 CASE_BTC_POLICY_STR(OFFE_DEF); 10393 CASE_BTC_POLICY_STR(OFFE_DEF2); 10394 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 10395 CASE_BTC_POLICY_STR(OFFE_2GISOB); 10396 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 10397 CASE_BTC_POLICY_STR(OFFE_WL); 10398 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 10399 CASE_BTC_POLICY_STR(FIX_TD3030); 10400 CASE_BTC_POLICY_STR(FIX_TD5050); 10401 CASE_BTC_POLICY_STR(FIX_TD2030); 10402 CASE_BTC_POLICY_STR(FIX_TD4010); 10403 CASE_BTC_POLICY_STR(FIX_TD7010); 10404 CASE_BTC_POLICY_STR(FIX_TD2060); 10405 CASE_BTC_POLICY_STR(FIX_TD3060); 10406 CASE_BTC_POLICY_STR(FIX_TD2080); 10407 CASE_BTC_POLICY_STR(FIX_TDW1B1); 10408 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 10409 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL); 10410 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL); 10411 CASE_BTC_POLICY_STR(PFIX_TD3030); 10412 CASE_BTC_POLICY_STR(PFIX_TD5050); 10413 CASE_BTC_POLICY_STR(PFIX_TD2030); 10414 CASE_BTC_POLICY_STR(PFIX_TD2060); 10415 CASE_BTC_POLICY_STR(PFIX_TD3070); 10416 CASE_BTC_POLICY_STR(PFIX_TD2080); 10417 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 10418 CASE_BTC_POLICY_STR(AUTO_TD50B1); 10419 CASE_BTC_POLICY_STR(AUTO_TD60B1); 10420 CASE_BTC_POLICY_STR(AUTO_TD20B1); 10421 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 10422 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 10423 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 10424 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 10425 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 10426 CASE_BTC_POLICY_STR(AUTO2_TD3050); 10427 CASE_BTC_POLICY_STR(AUTO2_TD3070); 10428 CASE_BTC_POLICY_STR(AUTO2_TD5050); 10429 CASE_BTC_POLICY_STR(AUTO2_TD6060); 10430 CASE_BTC_POLICY_STR(AUTO2_TD2080); 10431 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 10432 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 10433 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 10434 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 10435 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 10436 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 10437 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 10438 default: 10439 return "unknown step"; 10440 } 10441 } 10442 10443 static const char *id_to_slot(u32 id) 10444 { 10445 switch (id) { 10446 CASE_BTC_SLOT_STR(OFF); 10447 CASE_BTC_SLOT_STR(B2W); 10448 CASE_BTC_SLOT_STR(W1); 10449 CASE_BTC_SLOT_STR(W2); 10450 CASE_BTC_SLOT_STR(W2B); 10451 CASE_BTC_SLOT_STR(B1); 10452 CASE_BTC_SLOT_STR(B2); 10453 CASE_BTC_SLOT_STR(B3); 10454 CASE_BTC_SLOT_STR(B4); 10455 CASE_BTC_SLOT_STR(LK); 10456 CASE_BTC_SLOT_STR(BLK); 10457 CASE_BTC_SLOT_STR(E2G); 10458 CASE_BTC_SLOT_STR(E5G); 10459 CASE_BTC_SLOT_STR(EBT); 10460 CASE_BTC_SLOT_STR(ENULL); 10461 CASE_BTC_SLOT_STR(WLK); 10462 CASE_BTC_SLOT_STR(W1FDD); 10463 CASE_BTC_SLOT_STR(B1FDD); 10464 default: 10465 return "unknown"; 10466 } 10467 } 10468 10469 static const char *id_to_evt(u32 id) 10470 { 10471 switch (id) { 10472 CASE_BTC_EVT_STR(TDMA_ENTRY); 10473 CASE_BTC_EVT_STR(WL_TMR); 10474 CASE_BTC_EVT_STR(B1_TMR); 10475 CASE_BTC_EVT_STR(B2_TMR); 10476 CASE_BTC_EVT_STR(B3_TMR); 10477 CASE_BTC_EVT_STR(B4_TMR); 10478 CASE_BTC_EVT_STR(W2B_TMR); 10479 CASE_BTC_EVT_STR(B2W_TMR); 10480 CASE_BTC_EVT_STR(BCN_EARLY); 10481 CASE_BTC_EVT_STR(A2DP_EMPTY); 10482 CASE_BTC_EVT_STR(LK_END); 10483 CASE_BTC_EVT_STR(RX_ISR); 10484 CASE_BTC_EVT_STR(RX_FC0); 10485 CASE_BTC_EVT_STR(RX_FC1); 10486 CASE_BTC_EVT_STR(BT_RELINK); 10487 CASE_BTC_EVT_STR(BT_RETRY); 10488 CASE_BTC_EVT_STR(E2G); 10489 CASE_BTC_EVT_STR(E5G); 10490 CASE_BTC_EVT_STR(EBT); 10491 CASE_BTC_EVT_STR(ENULL); 10492 CASE_BTC_EVT_STR(DRV_WLK); 10493 CASE_BTC_EVT_STR(BCN_OK); 10494 CASE_BTC_EVT_STR(BT_CHANGE); 10495 CASE_BTC_EVT_STR(EBT_EXTEND); 10496 CASE_BTC_EVT_STR(E2G_NULL1); 10497 CASE_BTC_EVT_STR(B1FDD_TMR); 10498 default: 10499 return "unknown"; 10500 } 10501 } 10502 10503 static const char *id_to_mode(u8 id) 10504 { 10505 switch (id) { 10506 CASE_BTC_INIT(NORMAL); 10507 CASE_BTC_INIT(WL); 10508 CASE_BTC_INIT(BT); 10509 CASE_BTC_INIT(WLOFF); 10510 default: 10511 return "unknown"; 10512 } 10513 } 10514 10515 static const char *id_to_ant(u32 id) 10516 { 10517 switch (id) { 10518 CASE_BTC_ANTPATH_STR(WPOWERON); 10519 CASE_BTC_ANTPATH_STR(WINIT); 10520 CASE_BTC_ANTPATH_STR(WONLY); 10521 CASE_BTC_ANTPATH_STR(WOFF); 10522 CASE_BTC_ANTPATH_STR(W2G); 10523 CASE_BTC_ANTPATH_STR(FDD); 10524 CASE_BTC_ANTPATH_STR(W25G); 10525 CASE_BTC_ANTPATH_STR(FREERUN); 10526 CASE_BTC_ANTPATH_STR(WRFK); 10527 CASE_BTC_ANTPATH_STR(WRFK2); 10528 CASE_BTC_ANTPATH_STR(PTA); 10529 CASE_BTC_ANTPATH_STR(MAX); 10530 default: 10531 return "unknown"; 10532 } 10533 } 10534 10535 static const char *id_to_h2c(u32 id) 10536 { 10537 switch (id) { 10538 CASE_BTC_H2CCMD(REPORT_EN); 10539 CASE_BTC_H2CCMD(SLOT_TABLE); 10540 CASE_BTC_H2CCMD(MREG_TABLE); 10541 CASE_BTC_H2CCMD(CX_POLICY); 10542 CASE_BTC_H2CCMD(GPIO_DBG); 10543 CASE_BTC_H2CCMD(DRV_INFO); 10544 CASE_BTC_H2CCMD(DRV_EVENT); 10545 CASE_BTC_H2CCMD(BT_WREG_ADDR); 10546 CASE_BTC_H2CCMD(BT_WREG_VAL); 10547 CASE_BTC_H2CCMD(BT_RREG_ADDR); 10548 CASE_BTC_H2CCMD(BT_WL_CH_INFO); 10549 CASE_BTC_H2CCMD(BT_INFO_REPORT); 10550 CASE_BTC_H2CCMD(BT_IGNORE_WLAN_ACT); 10551 CASE_BTC_H2CCMD(BT_TX_PWR); 10552 CASE_BTC_H2CCMD(BT_LNA_CONSTRAIN); 10553 CASE_BTC_H2CCMD(BT_QUERY_DEV_LIST); 10554 CASE_BTC_H2CCMD(BT_QUERY_DEV_INFO); 10555 CASE_BTC_H2CCMD(BT_PSD_REPORT); 10556 CASE_BTC_H2CCMD(H2C_TEST); 10557 CASE_BTC_H2CCMD(IOFLD_RF); 10558 CASE_BTC_H2CCMD(IOFLD_BB); 10559 CASE_BTC_H2CCMD(IOFLD_MAC); 10560 CASE_BTC_H2CCMD(IOFLD_SCBD); 10561 CASE_BTC_H2CCMD(H2C_MACRO); 10562 default: 10563 return "unknown"; 10564 } 10565 } 10566 10567 static 10568 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data, 10569 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 10570 { 10571 char *p = buf, *end = buf + bufsz; 10572 u8 cur_index; 10573 u8 i; 10574 10575 for (i = 0; i < len ; i++) { 10576 if ((i % seg_len) == 0) 10577 p += scnprintf(p, end - p, " %-15s : ", prefix); 10578 cur_index = (start_idx + i) % ring_len; 10579 if (i % 3 == 0) 10580 p += scnprintf(p, end - p, "-> %-20s", 10581 steps_to_str(*(data + cur_index))); 10582 else if (i % 3 == 1) 10583 p += scnprintf(p, end - p, "-> %-15s", 10584 steps_to_str(*(data + cur_index))); 10585 else 10586 p += scnprintf(p, end - p, "-> %-13s", 10587 steps_to_str(*(data + cur_index))); 10588 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 10589 p += scnprintf(p, end - p, "\n"); 10590 } 10591 10592 return p - buf; 10593 } 10594 10595 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10596 { 10597 struct rtw89_btc *btc = &rtwdev->btc; 10598 struct rtw89_btc_dm *dm = &btc->dm; 10599 char *p = buf, *end = buf + bufsz; 10600 u8 start_idx; 10601 u8 len; 10602 10603 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 10604 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 10605 10606 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len, 10607 6, start_idx, ARRAY_SIZE(dm->dm_step.step)); 10608 10609 return p - buf; 10610 } 10611 10612 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10613 { 10614 struct rtw89_btc *btc = &rtwdev->btc; 10615 struct rtw89_btc_dm *dm = &btc->dm; 10616 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10617 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 10618 char *p = buf, *end = buf + bufsz; 10619 10620 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 10621 return 0; 10622 10623 p += scnprintf(p, end - p, 10624 "========== [Mechanism Status %s] ==========\n", 10625 (btc->manual_ctrl ? "(Manual)" : "(Auto)")); 10626 10627 p += scnprintf(p, end - p, 10628 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n", 10629 "[status]", 10630 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated", 10631 steps_to_str(dm->run_reason), 10632 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 10633 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)), 10634 id_to_mode(wl->coex_mode), 10635 dm->cnt_dm[BTC_DCNT_RUN]); 10636 10637 p += _show_dm_step(rtwdev, p, end - p); 10638 10639 p += scnprintf(p, end - p, 10640 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 10641 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt, 10642 dm->freerun, btc->btc_ctrl_lps, dm->wl_mimo_ps); 10643 10644 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n", 10645 dm->leak_ap, 10646 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 10647 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 10648 "" : "(Mismatch!!)")); 10649 10650 p += scnprintf(p, end - p, 10651 " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n", 10652 "[dm_rf_ctrl]", 10653 wl->rssi_level, dm->trx_para_level, 10654 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0], 10655 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1], 10656 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0], 10657 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1], 10658 dm->wl_lna2, dm->wl_stb_chg); 10659 10660 p += scnprintf(p, end - p, 10661 " %-15s : pre_agc:%d, btg_rx:%d\n", 10662 "[dm_bb_ctrl]", dm->wl_pre_agc, dm->wl_btg_rx); 10663 10664 p += scnprintf(p, end - p, 10665 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 10666 "[dm_ctrl]", dm->wl_tx_limit.enable, 10667 dm->wl_tx_limit.tx_time, 10668 dm->wl_tx_limit.tx_retry, btc->bt_req_len[RTW89_PHY_0], 10669 bt->scan_rx_low_pri); 10670 10671 return p - buf; 10672 } 10673 10674 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10675 { 10676 struct rtw89_btc *btc = &rtwdev->btc; 10677 const struct rtw89_btc_ver *ver = btc->ver; 10678 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10679 union rtw89_btc_fbtc_cysta_info *pcysta; 10680 char *p = buf, *end = buf + bufsz; 10681 u32 except_cnt, exception_map; 10682 10683 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 10684 if (ver->fcxcysta == 2) { 10685 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 10686 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 10687 exception_map = le32_to_cpu(pcysta->v2.exception); 10688 } else if (ver->fcxcysta == 3) { 10689 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 10690 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 10691 exception_map = le32_to_cpu(pcysta->v3.except_map); 10692 } else if (ver->fcxcysta == 4) { 10693 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 10694 except_cnt = pcysta->v4.except_cnt; 10695 exception_map = le32_to_cpu(pcysta->v4.except_map); 10696 } else if (ver->fcxcysta == 5) { 10697 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 10698 except_cnt = pcysta->v5.except_cnt; 10699 exception_map = le32_to_cpu(pcysta->v5.except_map); 10700 } else if (ver->fcxcysta == 7) { 10701 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 10702 except_cnt = pcysta->v7.except_cnt; 10703 exception_map = le32_to_cpu(pcysta->v7.except_map); 10704 } else { 10705 return 0; 10706 } 10707 10708 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 10709 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 10710 return 0; 10711 10712 p += scnprintf(p, end - p, " %-15s : ", "[error]"); 10713 10714 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 10715 p += scnprintf(p, end - p, 10716 "overflow-cnt: %d, ", 10717 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 10718 } 10719 10720 if (pfwinfo->len_mismch) { 10721 p += scnprintf(p, end - p, 10722 "len-mismatch: 0x%x, ", 10723 pfwinfo->len_mismch); 10724 } 10725 10726 if (pfwinfo->fver_mismch) { 10727 p += scnprintf(p, end - p, 10728 "fver-mismatch: 0x%x, ", 10729 pfwinfo->fver_mismch); 10730 } 10731 10732 /* cycle statistics exceptions */ 10733 if (exception_map || except_cnt) { 10734 p += scnprintf(p, end - p, 10735 "exception-type: 0x%x, exception-cnt = %d", 10736 exception_map, except_cnt); 10737 } 10738 p += scnprintf(p, end - p, "\n"); 10739 10740 return p - buf; 10741 } 10742 10743 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10744 { 10745 struct rtw89_btc *btc = &rtwdev->btc; 10746 const struct rtw89_btc_ver *ver = btc->ver; 10747 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10748 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10749 struct rtw89_btc_fbtc_tdma *t = NULL; 10750 char *p = buf, *end = buf + bufsz; 10751 10752 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 10753 if (!pcinfo->valid) 10754 return 0; 10755 10756 if (ver->fcxtdma == 1) 10757 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 10758 else 10759 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 10760 10761 p += scnprintf(p, end - p, 10762 " %-15s : ", "[tdma_policy]"); 10763 p += scnprintf(p, end - p, 10764 "type:%d, rx_flow_ctrl:%d, txflctrl:%d, ", 10765 (u32)t->type, 10766 t->rxflctrl, t->txflctrl); 10767 10768 p += scnprintf(p, end - p, 10769 "bind:%d, leak_n:%d, ext_ctrl:%d, ", 10770 t->bind, t->leak_n, t->ext_ctrl); 10771 10772 p += scnprintf(p, end - p, 10773 "policy_type:%d\n", 10774 (u32)btc->policy_type); 10775 10776 return p - buf; 10777 } 10778 10779 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10780 { 10781 struct rtw89_btc *btc = &rtwdev->btc; 10782 const struct rtw89_btc_ver *ver = btc->ver; 10783 struct rtw89_btc_dm *dm = &btc->dm; 10784 char *p = buf, *end = buf + bufsz; 10785 u16 dur, cxtype; 10786 u32 tbl; 10787 u8 i = 0; 10788 10789 for (i = 0; i < CXST_MAX; i++) { 10790 if (ver->fcxslots == 1) { 10791 dur = le16_to_cpu(dm->slot_now.v1[i].dur); 10792 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl); 10793 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype); 10794 } else if (ver->fcxslots == 2 || ver->fcxslots == 7) { 10795 dur = le16_to_cpu(dm->slot_now.v7[i].dur); 10796 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl); 10797 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype); 10798 } else { 10799 return 0; 10800 } 10801 10802 if (i % 5 == 0) 10803 p += scnprintf(p, end - p, 10804 " %-15s : %5s[%03d/0x%x/%d]", 10805 "[slot_list]", 10806 id_to_slot((u32)i), 10807 dur, tbl, cxtype); 10808 else 10809 p += scnprintf(p, end - p, 10810 ", %5s[%03d/0x%x/%d]", 10811 id_to_slot((u32)i), 10812 dur, tbl, cxtype); 10813 10814 if (i % 5 == 4) 10815 p += scnprintf(p, end - p, "\n"); 10816 } 10817 10818 return p - buf; 10819 } 10820 10821 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10822 { 10823 struct rtw89_btc *btc = &rtwdev->btc; 10824 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10825 struct rtw89_btc_dm *dm = &btc->dm; 10826 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 10827 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10828 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 10829 union rtw89_btc_fbtc_rxflct r; 10830 u16 cycle, c_begin, c_end, store_index; 10831 char *p = buf, *end = buf + bufsz; 10832 u8 i, cnt = 0, slot_pair; 10833 10834 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 10835 if (!pcinfo->valid) 10836 return 0; 10837 10838 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 10839 p += scnprintf(p, end - p, 10840 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 10841 "[cycle_cnt]", 10842 le16_to_cpu(pcysta_le32->cycles), 10843 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 10844 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 10845 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 10846 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 10847 10848 for (i = 0; i < CXST_MAX; i++) { 10849 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 10850 continue; 10851 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i), 10852 le32_to_cpu(pcysta_le32->slot_cnt[i])); 10853 } 10854 10855 if (dm->tdma_now.rxflctrl) { 10856 p += scnprintf(p, end - p, ", leak_rx:%d", 10857 le32_to_cpu(pcysta_le32->leakrx_cnt)); 10858 } 10859 10860 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 10861 p += scnprintf(p, end - p, ", collision:%d", 10862 le32_to_cpu(pcysta_le32->collision_cnt)); 10863 } 10864 10865 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 10866 p += scnprintf(p, end - p, ", skip:%d", 10867 le32_to_cpu(pcysta_le32->skip_cnt)); 10868 } 10869 p += scnprintf(p, end - p, "\n"); 10870 10871 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 10872 "[cycle_time]", 10873 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 10874 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 10875 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 10876 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 10877 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 10878 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 10879 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 10880 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 10881 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 10882 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n", 10883 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 10884 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 10885 10886 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 10887 goto out; 10888 10889 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 10890 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 10891 10892 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 10893 c_begin = 1; 10894 else 10895 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 10896 10897 c_end = le16_to_cpu(pcysta_le32->cycles); 10898 10899 for (cycle = c_begin; cycle <= c_end; cycle++) { 10900 cnt++; 10901 store_index = ((cycle - 1) % slot_pair) * 2; 10902 10903 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 10904 p += scnprintf(p, end - p, 10905 " %-15s : ->b%02d->w%02d", 10906 "[cycle_step]", 10907 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 10908 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 10909 else 10910 p += scnprintf(p, end - p, 10911 "->b%02d->w%02d", 10912 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 10913 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 10914 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 10915 p += scnprintf(p, end - p, "\n"); 10916 } 10917 10918 if (a2dp->exist) { 10919 p += scnprintf(p, end - p, 10920 " %-15s : a2dp_ept:%d, a2dp_late:%d", 10921 "[a2dp_t_sta]", 10922 le16_to_cpu(pcysta_le32->a2dpept), 10923 le16_to_cpu(pcysta_le32->a2dpeptto)); 10924 10925 p += scnprintf(p, end - p, 10926 ", avg_t:%d, max_t:%d", 10927 le16_to_cpu(pcysta_le32->tavg_a2dpept), 10928 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 10929 r.val = dm->tdma_now.rxflctrl; 10930 10931 if (r.type && r.tgln_n) { 10932 p += scnprintf(p, end - p, 10933 ", cycle[PSTDMA:%d/TDMA:%d], ", 10934 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 10935 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 10936 10937 p += scnprintf(p, end - p, 10938 "avg_t[PSTDMA:%d/TDMA:%d], ", 10939 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 10940 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 10941 10942 p += scnprintf(p, end - p, 10943 "max_t[PSTDMA:%d/TDMA:%d]", 10944 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 10945 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 10946 } 10947 p += scnprintf(p, end - p, "\n"); 10948 } 10949 10950 out: 10951 return p - buf; 10952 } 10953 10954 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10955 { 10956 struct rtw89_btc *btc = &rtwdev->btc; 10957 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 10958 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10959 struct rtw89_btc_dm *dm = &btc->dm; 10960 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 10961 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 10962 struct rtw89_btc_rpt_cmn_info *pcinfo; 10963 u8 i, cnt = 0, slot_pair, divide_cnt; 10964 u16 cycle, c_begin, c_end, store_index; 10965 char *p = buf, *end = buf + bufsz; 10966 10967 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 10968 if (!pcinfo->valid) 10969 return 0; 10970 10971 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 10972 p += scnprintf(p, end - p, 10973 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 10974 "[cycle_cnt]", 10975 le16_to_cpu(pcysta->cycles), 10976 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 10977 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 10978 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 10979 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 10980 10981 for (i = 0; i < CXST_MAX; i++) { 10982 if (!le32_to_cpu(pcysta->slot_cnt[i])) 10983 continue; 10984 10985 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 10986 le32_to_cpu(pcysta->slot_cnt[i])); 10987 } 10988 10989 if (dm->tdma_now.rxflctrl) 10990 p += scnprintf(p, end - p, ", leak_rx:%d", 10991 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 10992 10993 if (le32_to_cpu(pcysta->collision_cnt)) 10994 p += scnprintf(p, end - p, ", collision:%d", 10995 le32_to_cpu(pcysta->collision_cnt)); 10996 10997 if (le32_to_cpu(pcysta->skip_cnt)) 10998 p += scnprintf(p, end - p, ", skip:%d", 10999 le32_to_cpu(pcysta->skip_cnt)); 11000 11001 p += scnprintf(p, end - p, "\n"); 11002 11003 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11004 "[cycle_time]", 11005 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11006 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11007 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11008 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11009 p += scnprintf(p, end - p, 11010 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 11011 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11012 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11013 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 11014 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 11015 p += scnprintf(p, end - p, 11016 ", maxdiff_t[wl:%d/bt:%d]\n", 11017 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 11018 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 11019 11020 cycle = le16_to_cpu(pcysta->cycles); 11021 if (cycle <= 1) 11022 goto out; 11023 11024 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11025 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11026 11027 if (cycle <= slot_pair) 11028 c_begin = 1; 11029 else 11030 c_begin = cycle - slot_pair + 1; 11031 11032 c_end = cycle; 11033 11034 if (a2dp->exist) 11035 divide_cnt = 3; 11036 else 11037 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 11038 11039 for (cycle = c_begin; cycle <= c_end; cycle++) { 11040 cnt++; 11041 store_index = ((cycle - 1) % slot_pair) * 2; 11042 11043 if (cnt % divide_cnt == 1) 11044 p += scnprintf(p, end - p, " %-15s : ", 11045 "[cycle_step]"); 11046 11047 p += scnprintf(p, end - p, "->b%02d", 11048 le16_to_cpu(pcysta->slot_step_time[store_index])); 11049 if (a2dp->exist) { 11050 a2dp_trx = &pcysta->a2dp_trx[store_index]; 11051 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11052 a2dp_trx->empty_cnt, 11053 a2dp_trx->retry_cnt, 11054 a2dp_trx->tx_rate ? 3 : 2, 11055 a2dp_trx->tx_cnt, 11056 a2dp_trx->ack_cnt, 11057 a2dp_trx->nack_cnt); 11058 } 11059 p += scnprintf(p, end - p, "->w%02d", 11060 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 11061 if (a2dp->exist) { 11062 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 11063 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11064 a2dp_trx->empty_cnt, 11065 a2dp_trx->retry_cnt, 11066 a2dp_trx->tx_rate ? 3 : 2, 11067 a2dp_trx->tx_cnt, 11068 a2dp_trx->ack_cnt, 11069 a2dp_trx->nack_cnt); 11070 } 11071 if (cnt % divide_cnt == 0 || cnt == c_end) 11072 p += scnprintf(p, end - p, "\n"); 11073 } 11074 11075 if (a2dp->exist) { 11076 p += scnprintf(p, end - p, 11077 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11078 "[a2dp_t_sta]", 11079 le16_to_cpu(pcysta->a2dp_ept.cnt), 11080 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 11081 11082 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 11083 le16_to_cpu(pcysta->a2dp_ept.tavg), 11084 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11085 } 11086 11087 out: 11088 return p - buf; 11089 } 11090 11091 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11092 { 11093 struct rtw89_btc *btc = &rtwdev->btc; 11094 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11095 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11096 struct rtw89_btc_dm *dm = &btc->dm; 11097 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 11098 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 11099 struct rtw89_btc_rpt_cmn_info *pcinfo; 11100 u8 i, cnt = 0, slot_pair, divide_cnt; 11101 u16 cycle, c_begin, c_end, store_index; 11102 char *p = buf, *end = buf + bufsz; 11103 11104 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11105 if (!pcinfo->valid) 11106 return 0; 11107 11108 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 11109 p += scnprintf(p, end - p, 11110 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11111 "[cycle_cnt]", 11112 le16_to_cpu(pcysta->cycles), 11113 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11114 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11115 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11116 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11117 11118 for (i = 0; i < CXST_MAX; i++) { 11119 if (!le16_to_cpu(pcysta->slot_cnt[i])) 11120 continue; 11121 11122 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 11123 le16_to_cpu(pcysta->slot_cnt[i])); 11124 } 11125 11126 if (dm->tdma_now.rxflctrl) 11127 p += scnprintf(p, end - p, ", leak_rx:%d", 11128 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11129 11130 if (pcysta->collision_cnt) 11131 p += scnprintf(p, end - p, ", collision:%d", 11132 pcysta->collision_cnt); 11133 11134 if (le16_to_cpu(pcysta->skip_cnt)) 11135 p += scnprintf(p, end - p, ", skip:%d", 11136 le16_to_cpu(pcysta->skip_cnt)); 11137 11138 p += scnprintf(p, end - p, "\n"); 11139 11140 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11141 "[cycle_time]", 11142 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11143 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11144 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11145 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11146 p += scnprintf(p, end - p, 11147 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 11148 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11149 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11150 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 11151 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 11152 p += scnprintf(p, end - p, 11153 ", maxdiff_t[wl:%d/bt:%d]\n", 11154 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 11155 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 11156 11157 cycle = le16_to_cpu(pcysta->cycles); 11158 if (cycle <= 1) 11159 goto out; 11160 11161 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11162 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11163 11164 if (cycle <= slot_pair) 11165 c_begin = 1; 11166 else 11167 c_begin = cycle - slot_pair + 1; 11168 11169 c_end = cycle; 11170 11171 if (a2dp->exist) 11172 divide_cnt = 3; 11173 else 11174 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 11175 11176 for (cycle = c_begin; cycle <= c_end; cycle++) { 11177 cnt++; 11178 store_index = ((cycle - 1) % slot_pair) * 2; 11179 11180 if (cnt % divide_cnt == 1) 11181 p += scnprintf(p, end - p, " %-15s : ", 11182 "[cycle_step]"); 11183 11184 p += scnprintf(p, end - p, "->b%02d", 11185 le16_to_cpu(pcysta->slot_step_time[store_index])); 11186 if (a2dp->exist) { 11187 a2dp_trx = &pcysta->a2dp_trx[store_index]; 11188 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11189 a2dp_trx->empty_cnt, 11190 a2dp_trx->retry_cnt, 11191 a2dp_trx->tx_rate ? 3 : 2, 11192 a2dp_trx->tx_cnt, 11193 a2dp_trx->ack_cnt, 11194 a2dp_trx->nack_cnt); 11195 } 11196 p += scnprintf(p, end - p, "->w%02d", 11197 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 11198 if (a2dp->exist) { 11199 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 11200 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11201 a2dp_trx->empty_cnt, 11202 a2dp_trx->retry_cnt, 11203 a2dp_trx->tx_rate ? 3 : 2, 11204 a2dp_trx->tx_cnt, 11205 a2dp_trx->ack_cnt, 11206 a2dp_trx->nack_cnt); 11207 } 11208 if (cnt % divide_cnt == 0 || cnt == c_end) 11209 p += scnprintf(p, end - p, "\n"); 11210 } 11211 11212 if (a2dp->exist) { 11213 p += scnprintf(p, end - p, 11214 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11215 "[a2dp_t_sta]", 11216 le16_to_cpu(pcysta->a2dp_ept.cnt), 11217 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 11218 11219 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 11220 le16_to_cpu(pcysta->a2dp_ept.tavg), 11221 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11222 } 11223 11224 out: 11225 return p - buf; 11226 } 11227 11228 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11229 { 11230 struct rtw89_btc *btc = &rtwdev->btc; 11231 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11232 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11233 struct rtw89_btc_dm *dm = &btc->dm; 11234 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 11235 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 11236 struct rtw89_btc_rpt_cmn_info *pcinfo; 11237 u8 i, cnt = 0, slot_pair, divide_cnt; 11238 u16 cycle, c_begin, c_end, store_index; 11239 char *p = buf, *end = buf + bufsz; 11240 11241 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11242 if (!pcinfo->valid) 11243 return 0; 11244 11245 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 11246 p += scnprintf(p, end - p, 11247 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11248 "[cycle_cnt]", 11249 le16_to_cpu(pcysta->cycles), 11250 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11251 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11252 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11253 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11254 11255 for (i = 0; i < CXST_MAX; i++) { 11256 if (!le16_to_cpu(pcysta->slot_cnt[i])) 11257 continue; 11258 11259 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 11260 le16_to_cpu(pcysta->slot_cnt[i])); 11261 } 11262 11263 if (dm->tdma_now.rxflctrl) 11264 p += scnprintf(p, end - p, ", leak_rx:%d", 11265 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11266 11267 if (pcysta->collision_cnt) 11268 p += scnprintf(p, end - p, ", collision:%d", 11269 pcysta->collision_cnt); 11270 11271 if (le16_to_cpu(pcysta->skip_cnt)) 11272 p += scnprintf(p, end - p, ", skip:%d", 11273 le16_to_cpu(pcysta->skip_cnt)); 11274 11275 p += scnprintf(p, end - p, "\n"); 11276 11277 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11278 "[cycle_time]", 11279 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11280 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11281 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11282 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11283 p += scnprintf(p, end - p, 11284 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 11285 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11286 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11287 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 11288 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 11289 11290 cycle = le16_to_cpu(pcysta->cycles); 11291 if (cycle <= 1) 11292 goto out; 11293 11294 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11295 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11296 11297 if (cycle <= slot_pair) 11298 c_begin = 1; 11299 else 11300 c_begin = cycle - slot_pair + 1; 11301 11302 c_end = cycle; 11303 11304 if (a2dp->exist) 11305 divide_cnt = 3; 11306 else 11307 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 11308 11309 if (c_begin > c_end) 11310 goto out; 11311 11312 for (cycle = c_begin; cycle <= c_end; cycle++) { 11313 cnt++; 11314 store_index = ((cycle - 1) % slot_pair) * 2; 11315 11316 if (cnt % divide_cnt == 1) 11317 p += scnprintf(p, end - p, " %-15s : ", 11318 "[cycle_step]"); 11319 11320 p += scnprintf(p, end - p, "->b%02d", 11321 le16_to_cpu(pcysta->slot_step_time[store_index])); 11322 if (a2dp->exist) { 11323 a2dp_trx = &pcysta->a2dp_trx[store_index]; 11324 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11325 a2dp_trx->empty_cnt, 11326 a2dp_trx->retry_cnt, 11327 a2dp_trx->tx_rate ? 3 : 2, 11328 a2dp_trx->tx_cnt, 11329 a2dp_trx->ack_cnt, 11330 a2dp_trx->nack_cnt); 11331 } 11332 p += scnprintf(p, end - p, "->w%02d", 11333 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 11334 if (a2dp->exist) { 11335 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 11336 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11337 a2dp_trx->empty_cnt, 11338 a2dp_trx->retry_cnt, 11339 a2dp_trx->tx_rate ? 3 : 2, 11340 a2dp_trx->tx_cnt, 11341 a2dp_trx->ack_cnt, 11342 a2dp_trx->nack_cnt); 11343 } 11344 if (cnt % divide_cnt == 0 || cnt == c_end) 11345 p += scnprintf(p, end - p, "\n"); 11346 } 11347 11348 if (a2dp->exist) { 11349 p += scnprintf(p, end - p, 11350 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11351 "[a2dp_t_sta]", 11352 le16_to_cpu(pcysta->a2dp_ept.cnt), 11353 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 11354 11355 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 11356 le16_to_cpu(pcysta->a2dp_ept.tavg), 11357 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11358 } 11359 11360 out: 11361 return p - buf; 11362 } 11363 11364 static int _show_fbtc_cysta_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11365 { 11366 struct rtw89_btc *btc = &rtwdev->btc; 11367 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11368 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11369 struct rtw89_btc_dm *dm = &btc->dm; 11370 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 11371 struct rtw89_btc_fbtc_cysta_v105 *pcysta; 11372 struct rtw89_btc_rpt_cmn_info *pcinfo; 11373 u8 i, cnt = 0, slot_pair, divide_cnt; 11374 u16 cycle, c_begin, c_end, store_index; 11375 char *p = buf, *end = buf + bufsz; 11376 11377 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11378 if (!pcinfo->valid) 11379 return 0; 11380 11381 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v105; 11382 p += scnprintf(p, end - p, 11383 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11384 "[cycle_cnt]", 11385 le16_to_cpu(pcysta->cycles), 11386 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11387 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11388 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11389 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11390 11391 for (i = 0; i < CXST_MAX; i++) { 11392 if (!le16_to_cpu(pcysta->slot_cnt[i])) 11393 continue; 11394 11395 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 11396 le16_to_cpu(pcysta->slot_cnt[i])); 11397 } 11398 11399 if (dm->tdma_now.rxflctrl) 11400 p += scnprintf(p, end - p, ", leak_rx:%d", 11401 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11402 11403 if (pcysta->collision_cnt) 11404 p += scnprintf(p, end - p, ", collision:%d", 11405 pcysta->collision_cnt); 11406 11407 if (le16_to_cpu(pcysta->skip_cnt)) 11408 p += scnprintf(p, end - p, ", skip:%d", 11409 le16_to_cpu(pcysta->skip_cnt)); 11410 11411 p += scnprintf(p, end - p, "\n"); 11412 11413 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11414 "[cycle_time]", 11415 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11416 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11417 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11418 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11419 p += scnprintf(p, end - p, 11420 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 11421 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11422 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11423 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 11424 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 11425 11426 cycle = le16_to_cpu(pcysta->cycles); 11427 if (cycle <= 1) 11428 goto out; 11429 11430 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11431 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11432 11433 if (cycle <= slot_pair) 11434 c_begin = 1; 11435 else 11436 c_begin = cycle - slot_pair + 1; 11437 11438 c_end = cycle; 11439 11440 if (a2dp->exist) 11441 divide_cnt = 3; 11442 else 11443 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 11444 11445 if (c_begin > c_end) 11446 goto out; 11447 11448 for (cycle = c_begin; cycle <= c_end; cycle++) { 11449 cnt++; 11450 store_index = ((cycle - 1) % slot_pair) * 2; 11451 11452 if (cnt % divide_cnt == 1) 11453 p += scnprintf(p, end - p, " %-15s : ", 11454 "[cycle_step]"); 11455 11456 p += scnprintf(p, end - p, "->b%02d", 11457 le16_to_cpu(pcysta->slot_step_time[store_index])); 11458 if (a2dp->exist) { 11459 a2dp_trx = &pcysta->a2dp_trx[store_index]; 11460 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11461 a2dp_trx->empty_cnt, 11462 a2dp_trx->retry_cnt, 11463 a2dp_trx->tx_rate ? 3 : 2, 11464 a2dp_trx->tx_cnt, 11465 a2dp_trx->ack_cnt, 11466 a2dp_trx->nack_cnt); 11467 } 11468 p += scnprintf(p, end - p, "->w%02d", 11469 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 11470 if (a2dp->exist) { 11471 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 11472 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11473 a2dp_trx->empty_cnt, 11474 a2dp_trx->retry_cnt, 11475 a2dp_trx->tx_rate ? 3 : 2, 11476 a2dp_trx->tx_cnt, 11477 a2dp_trx->ack_cnt, 11478 a2dp_trx->nack_cnt); 11479 } 11480 if (cnt % divide_cnt == 0 || cnt == c_end) 11481 p += scnprintf(p, end - p, "\n"); 11482 } 11483 11484 if (a2dp->exist) { 11485 p += scnprintf(p, end - p, 11486 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11487 "[a2dp_t_sta]", 11488 le16_to_cpu(pcysta->a2dp_ept.cnt), 11489 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 11490 11491 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 11492 le16_to_cpu(pcysta->a2dp_ept.tavg), 11493 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11494 } 11495 11496 out: 11497 return p - buf; 11498 } 11499 11500 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11501 { 11502 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 11503 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 11504 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 11505 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL; 11506 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 11507 struct rtw89_btc_rpt_cmn_info *pcinfo; 11508 char *p = buf, *end = buf + bufsz; 11509 u16 cycle, c_begin, c_end, s_id; 11510 u8 i, cnt = 0, divide_cnt; 11511 u8 slot_pair; 11512 11513 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11514 if (!pcinfo->valid) 11515 return 0; 11516 11517 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 11518 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]", 11519 le16_to_cpu(pcysta->cycles)); 11520 11521 for (i = 0; i < CXST_MAX; i++) { 11522 if (!le16_to_cpu(pcysta->slot_cnt[i])) 11523 continue; 11524 p += scnprintf(p, end - p, ", %s:%d", 11525 id_to_slot(i), 11526 le16_to_cpu(pcysta->slot_cnt[i])); 11527 } 11528 11529 if (dm->tdma_now.rxflctrl) 11530 p += scnprintf(p, end - p, ", leak_rx:%d", 11531 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11532 11533 if (pcysta->collision_cnt) 11534 p += scnprintf(p, end - p, ", collision:%d", 11535 pcysta->collision_cnt); 11536 11537 if (pcysta->skip_cnt) 11538 p += scnprintf(p, end - p, ", skip:%d", 11539 le16_to_cpu(pcysta->skip_cnt)); 11540 11541 p += scnprintf(p, end - p, 11542 "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11543 "[cycle_stat]", 11544 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11545 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11546 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11547 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11548 p += scnprintf(p, end - p, 11549 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]", 11550 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11551 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11552 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD], 11553 le16_to_cpu(pcysta->leak_slot.tamx) / 1000, 11554 le16_to_cpu(pcysta->leak_slot.tamx) % 1000); 11555 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]", 11556 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11557 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11558 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11559 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11560 11561 if (a2dp->exist) { 11562 p += scnprintf(p, end - p, 11563 "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", 11564 "[a2dp_stat]", 11565 le16_to_cpu(pcysta->a2dp_ept.cnt), 11566 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), 11567 a2dp->no_empty_streak_2s, 11568 a2dp->no_empty_streak_max); 11569 11570 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 11571 le16_to_cpu(pcysta->a2dp_ept.tavg), 11572 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11573 } 11574 11575 if (le16_to_cpu(pcysta->cycles) <= 1) 11576 goto out; 11577 11578 /* 1 cycle = 1 wl-slot + 1 bt-slot */ 11579 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11580 11581 if (le16_to_cpu(pcysta->cycles) <= slot_pair) 11582 c_begin = 1; 11583 else 11584 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1; 11585 11586 c_end = le16_to_cpu(pcysta->cycles); 11587 11588 if (a2dp->exist) 11589 divide_cnt = 2; 11590 else 11591 divide_cnt = 6; 11592 11593 if (c_begin > c_end) 11594 goto out; 11595 11596 for (cycle = c_begin; cycle <= c_end; cycle++) { 11597 cnt++; 11598 s_id = ((cycle - 1) % slot_pair) * 2; 11599 11600 if (cnt % divide_cnt == 1) { 11601 if (a2dp->exist) 11602 p += scnprintf(p, end - p, "\n %-15s : ", 11603 "[slotT_wermtan]"); 11604 else 11605 p += scnprintf(p, end - p, "\n %-15s : ", 11606 "[slotT_rxerr]"); 11607 } 11608 11609 p += scnprintf(p, end - p, "->b%d", 11610 le16_to_cpu(pcysta->slot_step_time[s_id])); 11611 11612 if (a2dp->exist) 11613 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 11614 pcysta->wl_rx_err_ratio[s_id], 11615 pcysta->a2dp_trx[s_id].empty_cnt, 11616 pcysta->a2dp_trx[s_id].retry_cnt, 11617 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2), 11618 pcysta->a2dp_trx[s_id].tx_cnt, 11619 pcysta->a2dp_trx[s_id].ack_cnt, 11620 pcysta->a2dp_trx[s_id].nack_cnt); 11621 else 11622 p += scnprintf(p, end - p, "(%d)", 11623 pcysta->wl_rx_err_ratio[s_id]); 11624 11625 p += scnprintf(p, end - p, "->w%d", 11626 le16_to_cpu(pcysta->slot_step_time[s_id + 1])); 11627 11628 if (a2dp->exist) 11629 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 11630 pcysta->wl_rx_err_ratio[s_id + 1], 11631 pcysta->a2dp_trx[s_id + 1].empty_cnt, 11632 pcysta->a2dp_trx[s_id + 1].retry_cnt, 11633 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2), 11634 pcysta->a2dp_trx[s_id + 1].tx_cnt, 11635 pcysta->a2dp_trx[s_id + 1].ack_cnt, 11636 pcysta->a2dp_trx[s_id + 1].nack_cnt); 11637 else 11638 p += scnprintf(p, end - p, "(%d)", 11639 pcysta->wl_rx_err_ratio[s_id + 1]); 11640 } 11641 11642 out: 11643 return p - buf; 11644 } 11645 11646 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11647 { 11648 struct rtw89_btc *btc = &rtwdev->btc; 11649 const struct rtw89_btc_ver *ver = btc->ver; 11650 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11651 struct rtw89_btc_rpt_cmn_info *pcinfo; 11652 union rtw89_btc_fbtc_cynullsta_info *ns; 11653 char *p = buf, *end = buf + bufsz; 11654 u8 i = 0; 11655 11656 if (!btc->dm.tdma_now.rxflctrl) 11657 return 0; 11658 11659 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 11660 if (!pcinfo->valid) 11661 return 0; 11662 11663 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 11664 if (ver->fcxnullsta == 1) { 11665 for (i = 0; i < 2; i++) { 11666 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 11667 p += scnprintf(p, end - p, "null-%d", i); 11668 p += scnprintf(p, end - p, "[ok:%d/", 11669 le32_to_cpu(ns->v1.result[i][1])); 11670 p += scnprintf(p, end - p, "fail:%d/", 11671 le32_to_cpu(ns->v1.result[i][0])); 11672 p += scnprintf(p, end - p, "on_time:%d/", 11673 le32_to_cpu(ns->v1.result[i][2])); 11674 p += scnprintf(p, end - p, "retry:%d/", 11675 le32_to_cpu(ns->v1.result[i][3])); 11676 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 11677 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 11678 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 11679 p += scnprintf(p, end - p, "max_t:%d.%03d]", 11680 le32_to_cpu(ns->v1.max_t[i]) / 1000, 11681 le32_to_cpu(ns->v1.max_t[i]) % 1000); 11682 } 11683 } else if (ver->fcxnullsta == 7) { 11684 for (i = 0; i < 2; i++) { 11685 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 11686 p += scnprintf(p, end - p, "null-%d", i); 11687 p += scnprintf(p, end - p, "[Tx:%d/", 11688 le32_to_cpu(ns->v7.result[i][4])); 11689 p += scnprintf(p, end - p, "[ok:%d/", 11690 le32_to_cpu(ns->v7.result[i][1])); 11691 p += scnprintf(p, end - p, "fail:%d/", 11692 le32_to_cpu(ns->v7.result[i][0])); 11693 p += scnprintf(p, end - p, "on_time:%d/", 11694 le32_to_cpu(ns->v7.result[i][2])); 11695 p += scnprintf(p, end - p, "retry:%d/", 11696 le32_to_cpu(ns->v7.result[i][3])); 11697 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 11698 le32_to_cpu(ns->v7.tavg[i]) / 1000, 11699 le32_to_cpu(ns->v7.tavg[i]) % 1000); 11700 p += scnprintf(p, end - p, "max_t:%d.%03d]", 11701 le32_to_cpu(ns->v7.tmax[i]) / 1000, 11702 le32_to_cpu(ns->v7.tmax[i]) % 1000); 11703 } 11704 } else { 11705 for (i = 0; i < 2; i++) { 11706 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 11707 p += scnprintf(p, end - p, "null-%d", i); 11708 p += scnprintf(p, end - p, "[Tx:%d/", 11709 le32_to_cpu(ns->v2.result[i][4])); 11710 p += scnprintf(p, end - p, "[ok:%d/", 11711 le32_to_cpu(ns->v2.result[i][1])); 11712 p += scnprintf(p, end - p, "fail:%d/", 11713 le32_to_cpu(ns->v2.result[i][0])); 11714 p += scnprintf(p, end - p, "on_time:%d/", 11715 le32_to_cpu(ns->v2.result[i][2])); 11716 p += scnprintf(p, end - p, "retry:%d/", 11717 le32_to_cpu(ns->v2.result[i][3])); 11718 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 11719 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 11720 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 11721 p += scnprintf(p, end - p, "max_t:%d.%03d]", 11722 le32_to_cpu(ns->v2.max_t[i]) / 1000, 11723 le32_to_cpu(ns->v2.max_t[i]) % 1000); 11724 } 11725 } 11726 11727 return p - buf; 11728 } 11729 11730 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11731 { 11732 struct rtw89_btc *btc = &rtwdev->btc; 11733 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11734 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11735 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 11736 const struct rtw89_btc_ver *ver = btc->ver; 11737 char *p = buf, *end = buf + bufsz; 11738 u8 type, val, cnt = 0, state = 0; 11739 bool outloop = false; 11740 u16 i, diff_t, n_start = 0, n_stop = 0; 11741 u16 pos_old, pos_new, trace_step; 11742 11743 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 11744 if (!pcinfo->valid) 11745 return 0; 11746 11747 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 11748 pos_old = le16_to_cpu(pstep->pos_old); 11749 pos_new = le16_to_cpu(pstep->pos_new); 11750 11751 if (pcinfo->req_fver != pstep->fver) 11752 return 0; 11753 11754 /* store step info by using ring instead of FIFO*/ 11755 do { 11756 switch (state) { 11757 case 0: 11758 if (ver->fcxctrl == 7 || ver->fcxctrl == 1) 11759 trace_step = 50; 11760 else 11761 trace_step = btc->ctrl.trace_step; 11762 11763 n_start = pos_old; 11764 if (pos_new >= pos_old) 11765 n_stop = pos_new; 11766 else 11767 n_stop = trace_step - 1; 11768 11769 state = 1; 11770 break; 11771 case 1: 11772 for (i = n_start; i <= n_stop; i++) { 11773 type = pstep->step[i].type; 11774 val = pstep->step[i].val; 11775 diff_t = le16_to_cpu(pstep->step[i].difft); 11776 11777 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 11778 continue; 11779 11780 if (cnt % 10 == 0) 11781 p += scnprintf(p, end - p, 11782 " %-15s : ", "[steps]"); 11783 11784 p += scnprintf(p, end - p, 11785 "-> %s(%02d)(%02d)", 11786 (type == CXSTEP_SLOT ? "SLT" : 11787 "EVT"), (u32)val, diff_t); 11788 if (cnt % 10 == 9) 11789 p += scnprintf(p, end - p, "\n"); 11790 cnt++; 11791 } 11792 11793 state = 2; 11794 break; 11795 case 2: 11796 if (pos_new < pos_old && n_start != 0) { 11797 n_start = 0; 11798 n_stop = pos_new; 11799 state = 1; 11800 } else { 11801 outloop = true; 11802 } 11803 break; 11804 } 11805 } while (!outloop); 11806 11807 return p - buf; 11808 } 11809 11810 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11811 { 11812 struct rtw89_btc *btc = &rtwdev->btc; 11813 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11814 struct rtw89_btc_rpt_cmn_info *pcinfo; 11815 struct rtw89_btc_fbtc_steps_v3 *pstep; 11816 u32 i, n_begin, n_end, array_idx, cnt = 0; 11817 char *p = buf, *end = buf + bufsz; 11818 u8 type, val; 11819 u16 diff_t; 11820 11821 if ((pfwinfo->rpt_en_map & 11822 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 11823 return 0; 11824 11825 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 11826 if (!pcinfo->valid) 11827 return 0; 11828 11829 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 11830 if (pcinfo->req_fver != pstep->fver) 11831 return 0; 11832 11833 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 11834 n_begin = 1; 11835 else 11836 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 11837 11838 n_end = le32_to_cpu(pstep->cnt); 11839 11840 if (n_begin > n_end) 11841 return 0; 11842 11843 /* restore step info by using ring instead of FIFO */ 11844 for (i = n_begin; i <= n_end; i++) { 11845 array_idx = (i - 1) % FCXDEF_STEP; 11846 type = pstep->step[array_idx].type; 11847 val = pstep->step[array_idx].val; 11848 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 11849 11850 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 11851 continue; 11852 11853 if (cnt % 10 == 0) 11854 p += scnprintf(p, end - p, " %-15s : ", "[steps]"); 11855 11856 p += scnprintf(p, end - p, "-> %s(%02d)", 11857 (type == CXSTEP_SLOT ? 11858 id_to_slot((u32)val) : 11859 id_to_evt((u32)val)), diff_t); 11860 11861 if (cnt % 10 == 9) 11862 p += scnprintf(p, end - p, "\n"); 11863 11864 cnt++; 11865 } 11866 11867 return p - buf; 11868 } 11869 11870 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11871 { 11872 struct rtw89_btc *btc = &rtwdev->btc; 11873 const struct rtw89_btc_ver *ver = btc->ver; 11874 char *p = buf, *end = buf + bufsz; 11875 11876 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 11877 goto out; 11878 11879 p += _show_error(rtwdev, p, end - p); 11880 p += _show_fbtc_tdma(rtwdev, p, end - p); 11881 p += _show_fbtc_slots(rtwdev, p, end - p); 11882 11883 if (ver->fcxcysta == 2) 11884 p += _show_fbtc_cysta_v2(rtwdev, p, end - p); 11885 else if (ver->fcxcysta == 3) 11886 p += _show_fbtc_cysta_v3(rtwdev, p, end - p); 11887 else if (ver->fcxcysta == 4) 11888 p += _show_fbtc_cysta_v4(rtwdev, p, end - p); 11889 else if (ver->fcxcysta == 5) 11890 p += _show_fbtc_cysta_v5(rtwdev, p, end - p); 11891 else if (ver->fcxcysta == 105) 11892 p += _show_fbtc_cysta_v105(rtwdev, p, end - p); 11893 else if (ver->fcxcysta == 7) 11894 p += _show_fbtc_cysta_v7(rtwdev, p, end - p); 11895 11896 p += _show_fbtc_nullsta(rtwdev, p, end - p); 11897 11898 if (ver->fcxstep == 2) 11899 p += _show_fbtc_step_v2(rtwdev, p, end - p); 11900 else if (ver->fcxstep == 3) 11901 p += _show_fbtc_step_v3(rtwdev, p, end - p); 11902 11903 out: 11904 return p - buf; 11905 } 11906 11907 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 11908 { 11909 const struct rtw89_chip_info *chip = rtwdev->chip; 11910 struct rtw89_mac_ax_wl_act *bt; 11911 struct rtw89_mac_ax_gnt *gnt; 11912 u32 val, status; 11913 11914 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || 11915 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) { 11916 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 11917 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 11918 11919 gnt = &gnt_cfg->band[0]; 11920 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 11921 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 11922 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 11923 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 11924 11925 gnt = &gnt_cfg->band[1]; 11926 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 11927 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 11928 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 11929 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 11930 } else if (chip->chip_id == RTL8852C) { 11931 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 11932 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 11933 11934 gnt = &gnt_cfg->band[0]; 11935 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 11936 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 11937 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 11938 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 11939 11940 gnt = &gnt_cfg->band[1]; 11941 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 11942 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 11943 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 11944 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 11945 11946 bt = &gnt_cfg->bt[0]; 11947 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL); 11948 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL); 11949 11950 bt = &gnt_cfg->bt[1]; 11951 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL); 11952 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL); 11953 } else if (chip->chip_id == RTL8922A) { 11954 val = rtw89_read32(rtwdev, R_BE_GNT_SW_CTRL); 11955 status = rtw89_read32(rtwdev, R_BE_PTA_GNT_VAL); 11956 11957 gnt = &gnt_cfg->band[0]; 11958 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB0_SWCTRL); 11959 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB0_VAL); 11960 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB0_SWCTRL); 11961 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB0_VAL); 11962 11963 gnt = &gnt_cfg->band[1]; 11964 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB1_SWCTRL); 11965 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB1_VAL); 11966 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB1_SWCTRL); 11967 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB1_VAL); 11968 11969 bt = &gnt_cfg->bt[0]; 11970 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL); 11971 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL); 11972 11973 bt = &gnt_cfg->bt[1]; 11974 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL); 11975 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL); 11976 } else if (chip->chip_id == RTL8922D) { 11977 /* Get from firmware */ 11978 return; 11979 } 11980 } 11981 11982 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11983 { 11984 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 11985 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 11986 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11987 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 11988 char *p = buf, *end = buf + bufsz; 11989 u32 en_map_raw, en_map; 11990 u8 *gpio_map, i, sig; 11991 11992 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 11993 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo; 11994 if (!pcinfo->valid) { 11995 rtw89_debug(rtwdev, RTW89_DBG_BTC, 11996 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 11997 __func__); 11998 goto out; 11999 } 12000 12001 if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) { 12002 en_map_raw = le32_to_cpu(gdbg->v7.en_map); 12003 gpio_map = gdbg->v7.gpio_map; 12004 } else { 12005 en_map_raw = le32_to_cpu(gdbg->v1.en_map); 12006 gpio_map = gdbg->v1.gpio_map; 12007 } 12008 12009 en_map = _convert_gpio_enmap_from_ver(rtwdev, en_map_raw); 12010 if (!en_map) 12011 goto out; 12012 12013 p += scnprintf(p, end - p, "\n %-15s : enable_map:0x%08x", 12014 "[gpio_dbg]", en_map); 12015 12016 for (i = 0; i < BTC_DBG_NUM; i++) { 12017 if (!(en_map & BIT(i))) 12018 continue; 12019 12020 sig = ver->fcxgpiodbg >= 8 ? i : _get_gpiosig_for_ver(rtwdev, i); 12021 if (sig >= BTC_DBG_NUM) 12022 continue; 12023 12024 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i), 12025 gpio_map[sig]); 12026 } 12027 12028 out: 12029 return p - buf; 12030 } 12031 12032 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12033 { 12034 const struct rtw89_chip_info *chip = rtwdev->chip; 12035 struct rtw89_btc *btc = &rtwdev->btc; 12036 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12037 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 12038 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 12039 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 12040 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12041 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 12042 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 12043 struct rtw89_mac_ax_gnt gnt; 12044 char *p = buf, *end = buf + bufsz; 12045 u8 i = 0, type = 0, cnt = 0; 12046 u32 val, offset; 12047 12048 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 12049 return 0; 12050 12051 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 12052 12053 p += scnprintf(p, end - p, 12054 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 12055 "[scoreboard]", wl->scbd[BTC_BT_1ST], 12056 wl->wcnt[BTC_WCNT_SCBDUPDATE], 12057 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 12058 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 12059 12060 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 12061 p += scnprintf(p, end - p, 12062 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 12063 "[scoreboard]", wl->scbd[BTC_BT_2ND], 12064 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 12065 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 12066 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 12067 } 12068 12069 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 12070 _get_gnt(rtwdev, &gnt_cfg); 12071 12072 gnt = gnt_cfg.band[0]; 12073 p += scnprintf(p, end - p, 12074 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 12075 "[gnt_status]", 12076 chip->chip_id == RTL8852C ? "HW" : 12077 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 12078 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 12079 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 12080 12081 gnt = gnt_cfg.band[1]; 12082 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 12083 gnt.gnt_wl_sw_en ? "SW" : "HW", 12084 gnt.gnt_wl, 12085 gnt.gnt_bt_sw_en ? "SW" : "HW", 12086 gnt.gnt_bt); 12087 12088 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 12089 if (!pcinfo->valid) { 12090 rtw89_debug(rtwdev, RTW89_DBG_BTC, 12091 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 12092 __func__); 12093 goto out; 12094 } 12095 12096 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 12097 rtw89_debug(rtwdev, RTW89_DBG_BTC, 12098 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 12099 __func__, pmreg->reg_num); 12100 12101 for (i = 0; i < pmreg->reg_num; i++) { 12102 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 12103 offset = le32_to_cpu(chip->mon_reg[i].offset); 12104 val = le32_to_cpu(pmreg->mreg_val[i]); 12105 12106 if (cnt % 6 == 0) 12107 p += scnprintf(p, end - p, 12108 " %-15s : %d_0x%04x=0x%08x", 12109 "[reg]", (u32)type, offset, val); 12110 else 12111 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 12112 (u32)type, 12113 offset, val); 12114 if (cnt % 6 == 5) 12115 p += scnprintf(p, end - p, "\n"); 12116 cnt++; 12117 12118 if (i >= pmreg->reg_num) 12119 p += scnprintf(p, end - p, "\n"); 12120 } 12121 12122 out: 12123 return p - buf; 12124 } 12125 12126 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12127 { 12128 const struct rtw89_chip_info *chip = rtwdev->chip; 12129 struct rtw89_btc *btc = &rtwdev->btc; 12130 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12131 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 12132 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 12133 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 12134 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12135 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 12136 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 12137 struct rtw89_mac_ax_gnt gnt; 12138 char *p = buf, *end = buf + bufsz; 12139 u8 i = 0, type = 0, cnt = 0; 12140 u32 val, offset; 12141 12142 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 12143 return 0; 12144 12145 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 12146 12147 p += scnprintf(p, end - p, 12148 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 12149 "[scoreboard]", wl->scbd[BTC_BT_1ST], 12150 wl->wcnt[BTC_WCNT_SCBDUPDATE], 12151 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 12152 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 12153 12154 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 12155 p += scnprintf(p, end - p, 12156 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 12157 "[scoreboard]", wl->scbd[BTC_BT_2ND], 12158 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 12159 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 12160 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 12161 } 12162 12163 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 12164 _get_gnt(rtwdev, &gnt_cfg); 12165 12166 gnt = gnt_cfg.band[0]; 12167 p += scnprintf(p, end - p, 12168 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s", 12169 "[gnt_status]", 12170 chip->chip_id == RTL8852C ? "HW" : 12171 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 12172 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 12173 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt, 12174 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 12175 12176 gnt = gnt_cfg.band[1]; 12177 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 12178 gnt.gnt_wl_sw_en ? "SW" : "HW", 12179 gnt.gnt_wl, 12180 gnt.gnt_bt_sw_en ? "SW" : "HW", 12181 gnt.gnt_bt); 12182 12183 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 12184 if (!pcinfo->valid) { 12185 rtw89_debug(rtwdev, RTW89_DBG_BTC, 12186 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 12187 __func__); 12188 goto out; 12189 } 12190 12191 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 12192 rtw89_debug(rtwdev, RTW89_DBG_BTC, 12193 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 12194 __func__, pmreg->reg_num); 12195 12196 for (i = 0; i < pmreg->reg_num; i++) { 12197 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 12198 offset = le32_to_cpu(chip->mon_reg[i].offset); 12199 val = le32_to_cpu(pmreg->mreg_val[i]); 12200 12201 if (cnt % 6 == 0) 12202 p += scnprintf(p, end - p, 12203 " %-15s : %d_0x%04x=0x%08x", 12204 "[reg]", (u32)type, offset, val); 12205 else 12206 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 12207 (u32)type, 12208 offset, val); 12209 if (cnt % 6 == 5) 12210 p += scnprintf(p, end - p, "\n"); 12211 cnt++; 12212 12213 if (i >= pmreg->reg_num) 12214 p += scnprintf(p, end - p, "\n"); 12215 } 12216 12217 out: 12218 return p - buf; 12219 } 12220 12221 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12222 { 12223 struct rtw89_btc *btc = &rtwdev->btc; 12224 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12225 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL; 12226 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12227 struct rtw89_btc_cx *cx = &btc->cx; 12228 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 12229 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 12230 struct rtw89_btc_wl_info *wl = &cx->wl; 12231 struct rtw89_btc_dm *dm = &btc->dm; 12232 char *p = buf, *end = buf + bufsz; 12233 u8 i, type, cnt = 0; 12234 u32 val, offset; 12235 12236 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG)) 12237 return 0; 12238 12239 p += scnprintf(p, end - p, "\n========== [HW Status] ==========\n"); 12240 12241 p += scnprintf(p, end - p, 12242 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 12243 "[scoreboard]", wl->scbd[BTC_BT_1ST], 12244 wl->wcnt[BTC_WCNT_SCBDUPDATE], 12245 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 12246 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 12247 12248 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 12249 p += scnprintf(p, end - p, 12250 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 12251 "[scoreboard]", wl->scbd[BTC_BT_2ND], 12252 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 12253 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 12254 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 12255 } 12256 12257 /* To avoid I/O if WL LPS or power-off */ 12258 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 12259 12260 p += scnprintf(p, end - p, 12261 " %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s\n", 12262 "[gnt_status]", 12263 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" : 12264 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 12265 wl->pta_req_mac, 12266 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 12267 12268 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 12269 p += scnprintf(p, end - p, 12270 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", 12271 "[gnt_status]", 12272 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", 12273 dm->gnt_set[RTW89_PHY_0].gnt_wl, 12274 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", 12275 dm->gnt_set[RTW89_PHY_0].gnt_bt0, 12276 dm->gnt_set[RTW89_PHY_0].gnt_bt1_sw_en ? "SW" : "HW", 12277 dm->gnt_set[RTW89_PHY_0].gnt_bt1); 12278 else 12279 p += scnprintf(p, end - p, 12280 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", 12281 "[gnt_status]", 12282 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", 12283 dm->gnt_set[RTW89_PHY_0].gnt_wl, 12284 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", 12285 dm->gnt_set[RTW89_PHY_0].gnt_bt0); 12286 12287 if (rtwdev->dbcc_en) { 12288 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 12289 p += scnprintf(p, end - p, 12290 ", phy-1[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", 12291 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", 12292 dm->gnt_set[RTW89_PHY_1].gnt_wl, 12293 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", 12294 dm->gnt_set[RTW89_PHY_1].gnt_bt0, 12295 dm->gnt_set[RTW89_PHY_1].gnt_bt1_sw_en ? "SW" : "HW", 12296 dm->gnt_set[RTW89_PHY_1].gnt_bt1); 12297 else 12298 p += scnprintf(p, end - p, 12299 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", 12300 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", 12301 dm->gnt_set[RTW89_PHY_1].gnt_wl, 12302 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", 12303 dm->gnt_set[RTW89_PHY_1].gnt_bt0); 12304 } 12305 12306 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 12307 if (!pcinfo->valid) 12308 goto out; 12309 12310 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 12311 12312 for (i = 0; i < pmreg->reg_num; i++) { 12313 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type); 12314 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset); 12315 val = le32_to_cpu(pmreg->mreg_val[i]); 12316 12317 if (cnt % 6 == 0) 12318 p += scnprintf(p, end - p, 12319 "\n %-15s : %s_0x%x=0x%x", "[reg]", 12320 id_to_regtype(type), offset, val); 12321 else 12322 p += scnprintf(p, end - p, ", %s_0x%x=0x%x", 12323 id_to_regtype(type), offset, val); 12324 cnt++; 12325 } 12326 12327 out: 12328 return p - buf; 12329 } 12330 12331 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12332 { 12333 struct rtw89_btc *btc = &rtwdev->btc; 12334 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12335 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12336 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 12337 struct rtw89_btc_cx *cx = &btc->cx; 12338 struct rtw89_btc_dm *dm = &btc->dm; 12339 struct rtw89_btc_wl_info *wl = &cx->wl; 12340 struct rtw89_btc_bt_info *bt = &cx->bt0; 12341 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 12342 char *p = buf, *end = buf + bufsz; 12343 u8 i; 12344 12345 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12346 return 0; 12347 12348 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 12349 12350 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12351 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 12352 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 12353 12354 p += scnprintf(p, end - p, 12355 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 12356 "[summary]", pfwinfo->cnt_h2c, 12357 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 12358 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 12359 12360 p += scnprintf(p, end - p, 12361 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 12362 pfwinfo->event[BTF_EVNT_RPT], 12363 prptctrl->rpt_cnt, 12364 prptctrl->rpt_enable, dm->error.val); 12365 12366 if (dm->error.map.wl_fw_hang) 12367 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12368 p += scnprintf(p, end - p, "\n"); 12369 p += scnprintf(p, end - p, 12370 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 12371 "[mailbox]", prptctrl->mb_send_ok_cnt, 12372 prptctrl->mb_send_fail_cnt, 12373 prptctrl->mb_recv_cnt); 12374 12375 p += scnprintf(p, end - p, 12376 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 12377 prptctrl->mb_a2dp_empty_cnt, 12378 prptctrl->mb_a2dp_flct_cnt, 12379 prptctrl->mb_a2dp_full_cnt); 12380 12381 p += scnprintf(p, end - p, 12382 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 12383 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ], 12384 wl->wcnt[BTC_WCNT_RFK_GO], 12385 wl->wcnt[BTC_WCNT_RFK_REJECT], 12386 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 12387 12388 p += scnprintf(p, end - p, 12389 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 12390 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 12391 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 12392 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 12393 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 12394 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 12395 12396 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 12397 bt->rfk_info.map.timeout = 1; 12398 else 12399 bt->rfk_info.map.timeout = 0; 12400 12401 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 12402 } else { 12403 p += scnprintf(p, end - p, 12404 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 12405 "[summary]", pfwinfo->cnt_h2c, 12406 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 12407 pfwinfo->event[BTF_EVNT_RPT], 12408 btc->fwinfo.rpt_en_map); 12409 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 12410 } 12411 12412 for (i = 0; i < BTC_NCNT_NUM; i++) 12413 cnt_sum += dm->cnt_notify[i]; 12414 12415 p += scnprintf(p, end - p, 12416 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12417 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12418 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 12419 12420 p += scnprintf(p, end - p, 12421 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 12422 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 12423 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 12424 cnt[BTC_NCNT_WL_STA]); 12425 12426 p += scnprintf(p, end - p, 12427 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 12428 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 12429 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 12430 cnt[BTC_NCNT_SPECIAL_PACKET]); 12431 12432 p += scnprintf(p, end - p, 12433 "timer=%d, control=%d, customerize=%d\n", 12434 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 12435 cnt[BTC_NCNT_CUSTOMERIZE]); 12436 12437 return p - buf; 12438 } 12439 12440 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12441 { 12442 struct rtw89_btc *btc = &rtwdev->btc; 12443 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12444 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 12445 struct rtw89_btc_rpt_cmn_info *pcinfo; 12446 struct rtw89_btc_cx *cx = &btc->cx; 12447 struct rtw89_btc_dm *dm = &btc->dm; 12448 struct rtw89_btc_wl_info *wl = &cx->wl; 12449 struct rtw89_btc_bt_info *bt = &cx->bt0; 12450 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 12451 char *p = buf, *end = buf + bufsz; 12452 u8 i; 12453 12454 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12455 return 0; 12456 12457 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 12458 12459 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12460 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 12461 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 12462 12463 p += scnprintf(p, end - p, 12464 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 12465 "[summary]", pfwinfo->cnt_h2c, 12466 pfwinfo->cnt_h2c_fail, 12467 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 12468 pfwinfo->cnt_c2h, 12469 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 12470 12471 p += scnprintf(p, end - p, 12472 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 12473 pfwinfo->event[BTF_EVNT_RPT], 12474 le32_to_cpu(prptctrl->rpt_info.cnt), 12475 le32_to_cpu(prptctrl->rpt_info.en), 12476 dm->error.val); 12477 12478 if (dm->error.map.wl_fw_hang) 12479 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12480 p += scnprintf(p, end - p, "\n"); 12481 p += scnprintf(p, end - p, 12482 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 12483 "[mailbox]", 12484 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 12485 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 12486 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 12487 12488 p += scnprintf(p, end - p, 12489 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 12490 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 12491 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 12492 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 12493 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 12494 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 12495 12496 p += scnprintf(p, end - p, 12497 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 12498 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ], 12499 wl->wcnt[BTC_WCNT_RFK_GO], 12500 wl->wcnt[BTC_WCNT_RFK_REJECT], 12501 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 12502 12503 p += scnprintf(p, end - p, 12504 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 12505 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 12506 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 12507 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 12508 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 12509 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 12510 12511 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 12512 bt->rfk_info.map.timeout = 1; 12513 else 12514 bt->rfk_info.map.timeout = 0; 12515 12516 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 12517 } else { 12518 p += scnprintf(p, end - p, 12519 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 12520 "[summary]", pfwinfo->cnt_h2c, 12521 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 12522 pfwinfo->event[BTF_EVNT_RPT], 12523 btc->fwinfo.rpt_en_map); 12524 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 12525 } 12526 12527 for (i = 0; i < BTC_NCNT_NUM; i++) 12528 cnt_sum += dm->cnt_notify[i]; 12529 12530 p += scnprintf(p, end - p, 12531 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12532 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12533 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 12534 12535 p += scnprintf(p, end - p, 12536 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 12537 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 12538 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 12539 cnt[BTC_NCNT_WL_STA]); 12540 12541 p += scnprintf(p, end - p, 12542 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 12543 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 12544 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 12545 cnt[BTC_NCNT_SPECIAL_PACKET]); 12546 12547 p += scnprintf(p, end - p, 12548 "timer=%d, control=%d, customerize=%d\n", 12549 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 12550 cnt[BTC_NCNT_CUSTOMERIZE]); 12551 12552 return p - buf; 12553 } 12554 12555 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12556 { 12557 struct rtw89_btc *btc = &rtwdev->btc; 12558 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12559 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 12560 struct rtw89_btc_rpt_cmn_info *pcinfo; 12561 struct rtw89_btc_cx *cx = &btc->cx; 12562 struct rtw89_btc_dm *dm = &btc->dm; 12563 struct rtw89_btc_wl_info *wl = &cx->wl; 12564 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 12565 char *p = buf, *end = buf + bufsz; 12566 u8 i; 12567 12568 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12569 return 0; 12570 12571 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 12572 12573 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12574 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 12575 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 12576 12577 p += scnprintf(p, end - p, 12578 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 12579 "[summary]", pfwinfo->cnt_h2c, 12580 pfwinfo->cnt_h2c_fail, 12581 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 12582 pfwinfo->cnt_c2h, 12583 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 12584 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 12585 12586 p += scnprintf(p, end - p, 12587 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 12588 pfwinfo->event[BTF_EVNT_RPT], 12589 le16_to_cpu(prptctrl->rpt_info.cnt), 12590 le32_to_cpu(prptctrl->rpt_info.en)); 12591 12592 if (dm->error.map.wl_fw_hang) 12593 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12594 p += scnprintf(p, end - p, "\n"); 12595 p += scnprintf(p, end - p, 12596 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 12597 "[mailbox]", 12598 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 12599 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 12600 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 12601 12602 p += scnprintf(p, end - p, 12603 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 12604 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 12605 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 12606 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 12607 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 12608 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 12609 12610 p += scnprintf(p, end - p, 12611 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 12612 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 12613 wl->wcnt[BTC_WCNT_RFK_GO], 12614 wl->wcnt[BTC_WCNT_RFK_REJECT], 12615 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 12616 12617 p += scnprintf(p, end - p, 12618 ", bt_rfk[req:%d]", 12619 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 12620 12621 p += scnprintf(p, end - p, 12622 ", AOAC[RF_on:%d/RF_off:%d]", 12623 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 12624 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 12625 } else { 12626 p += scnprintf(p, end - p, 12627 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 12628 "[summary]", pfwinfo->cnt_h2c, 12629 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 12630 } 12631 12632 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 12633 pfwinfo->err[BTFRE_EXCEPTION]) { 12634 p += scnprintf(p, end - p, "\n"); 12635 p += scnprintf(p, end - p, 12636 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 12637 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 12638 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 12639 pfwinfo->fver_mismch, 12640 pfwinfo->err[BTFRE_EXCEPTION], 12641 wl->status.map.lps, wl->status.map.rf_off); 12642 } 12643 12644 for (i = 0; i < BTC_NCNT_NUM; i++) 12645 cnt_sum += dm->cnt_notify[i]; 12646 12647 p += scnprintf(p, end - p, "\n"); 12648 p += scnprintf(p, end - p, 12649 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12650 "[notify_cnt]", 12651 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12652 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 12653 12654 p += scnprintf(p, end - p, 12655 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 12656 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 12657 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 12658 cnt[BTC_NCNT_WL_STA]); 12659 12660 p += scnprintf(p, end - p, 12661 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 12662 "[notify_cnt]", 12663 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 12664 cnt[BTC_NCNT_SWITCH_BAND], 12665 cnt[BTC_NCNT_SPECIAL_PACKET]); 12666 12667 p += scnprintf(p, end - p, 12668 "timer=%d, control=%d, customerize=%d", 12669 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 12670 cnt[BTC_NCNT_CUSTOMERIZE]); 12671 12672 return p - buf; 12673 } 12674 12675 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12676 { 12677 struct rtw89_btc *btc = &rtwdev->btc; 12678 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12679 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 12680 struct rtw89_btc_rpt_cmn_info *pcinfo; 12681 struct rtw89_btc_cx *cx = &btc->cx; 12682 struct rtw89_btc_dm *dm = &btc->dm; 12683 struct rtw89_btc_wl_info *wl = &cx->wl; 12684 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 12685 char *p = buf, *end = buf + bufsz; 12686 u8 i; 12687 12688 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12689 return 0; 12690 12691 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 12692 12693 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12694 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 12695 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 12696 12697 p += scnprintf(p, end - p, 12698 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 12699 "[summary]", pfwinfo->cnt_h2c, 12700 pfwinfo->cnt_h2c_fail, 12701 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 12702 pfwinfo->cnt_c2h, 12703 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 12704 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 12705 12706 p += scnprintf(p, end - p, 12707 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 12708 pfwinfo->event[BTF_EVNT_RPT], 12709 le16_to_cpu(prptctrl->rpt_info.cnt), 12710 le32_to_cpu(prptctrl->rpt_info.en)); 12711 12712 if (dm->error.map.wl_fw_hang) 12713 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12714 p += scnprintf(p, end - p, "\n"); 12715 p += scnprintf(p, end - p, 12716 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 12717 "[mailbox]", 12718 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 12719 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 12720 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 12721 12722 p += scnprintf(p, end - p, 12723 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 12724 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 12725 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 12726 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 12727 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 12728 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 12729 12730 p += scnprintf(p, end - p, 12731 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 12732 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 12733 wl->wcnt[BTC_WCNT_RFK_GO], 12734 wl->wcnt[BTC_WCNT_RFK_REJECT], 12735 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 12736 12737 p += scnprintf(p, end - p, 12738 ", bt_rfk[req:%d]", 12739 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 12740 12741 p += scnprintf(p, end - p, 12742 ", AOAC[RF_on:%d/RF_off:%d]", 12743 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 12744 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 12745 } else { 12746 p += scnprintf(p, end - p, 12747 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 12748 "[summary]", pfwinfo->cnt_h2c, 12749 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 12750 } 12751 12752 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 12753 pfwinfo->err[BTFRE_EXCEPTION]) { 12754 p += scnprintf(p, end - p, "\n"); 12755 p += scnprintf(p, end - p, 12756 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 12757 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 12758 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 12759 pfwinfo->fver_mismch, 12760 pfwinfo->err[BTFRE_EXCEPTION], 12761 wl->status.map.lps, wl->status.map.rf_off); 12762 } 12763 12764 for (i = 0; i < BTC_NCNT_NUM; i++) 12765 cnt_sum += dm->cnt_notify[i]; 12766 12767 p += scnprintf(p, end - p, "\n"); 12768 p += scnprintf(p, end - p, 12769 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12770 "[notify_cnt]", 12771 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12772 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 12773 12774 p += scnprintf(p, end - p, 12775 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 12776 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 12777 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 12778 cnt[BTC_NCNT_WL_STA]); 12779 12780 p += scnprintf(p, end - p, 12781 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 12782 "[notify_cnt]", 12783 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 12784 cnt[BTC_NCNT_SWITCH_BAND], 12785 cnt[BTC_NCNT_SPECIAL_PACKET]); 12786 12787 p += scnprintf(p, end - p, 12788 "timer=%d, control=%d, customerize=%d", 12789 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 12790 cnt[BTC_NCNT_CUSTOMERIZE]); 12791 12792 return p - buf; 12793 } 12794 12795 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12796 { 12797 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 12798 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL; 12799 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12800 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 12801 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 12802 struct rtw89_btc_wl_info *wl = &cx->wl; 12803 u32 *cnt = rtwdev->btc.dm.cnt_notify; 12804 char *p = buf, *end = buf + bufsz; 12805 u32 cnt_sum = 0; 12806 u8 i; 12807 12808 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12809 return 0; 12810 12811 p += scnprintf(p, end - p, "%s", 12812 "\n========== [Statistics] ==========\n"); 12813 12814 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12815 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 12816 !wl->status.map.rf_off) { 12817 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7; 12818 12819 p += scnprintf(p, end - p, 12820 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," 12821 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ", 12822 "[summary]", pfwinfo->cnt_h2c, 12823 pfwinfo->cnt_h2c_fail, 12824 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 12825 pfwinfo->cnt_c2h, 12826 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 12827 le16_to_cpu(prptctrl->rpt_info.len_c2h), 12828 rtwdev->btc.ver->info_buf); 12829 12830 p += scnprintf(p, end - p, 12831 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 12832 pfwinfo->event[BTF_EVNT_RPT], 12833 le16_to_cpu(prptctrl->rpt_info.cnt), 12834 le32_to_cpu(prptctrl->rpt_info.en)); 12835 12836 if (dm->error.map.wl_fw_hang) 12837 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12838 p += scnprintf(p, end - p, "\n"); 12839 12840 p += scnprintf(p, end - p, 12841 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 12842 "[mailbox]", 12843 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 12844 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 12845 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 12846 12847 p += scnprintf(p, end - p, 12848 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 12849 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 12850 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 12851 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 12852 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 12853 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 12854 12855 p += scnprintf(p, end - p, 12856 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 12857 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 12858 wl->wcnt[BTC_WCNT_RFK_GO], 12859 wl->wcnt[BTC_WCNT_RFK_REJECT], 12860 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 12861 wl->rfk_info.proc_time); 12862 12863 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 12864 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 12865 12866 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 12867 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 12868 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 12869 } else { 12870 p += scnprintf(p, end - p, 12871 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 12872 "[summary]", 12873 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 12874 pfwinfo->cnt_c2h, 12875 wl->status.map.lps, wl->status.map.rf_off); 12876 } 12877 12878 for (i = 0; i < BTC_NCNT_NUM; i++) 12879 cnt_sum += dm->cnt_notify[i]; 12880 12881 p += scnprintf(p, end - p, 12882 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12883 "[notify_cnt]", 12884 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12885 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 12886 12887 p += scnprintf(p, end - p, 12888 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 12889 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 12890 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 12891 cnt[BTC_NCNT_WL_STA]); 12892 12893 p += scnprintf(p, end - p, 12894 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 12895 "[notify_cnt]", 12896 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 12897 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 12898 cnt[BTC_NCNT_SPECIAL_PACKET]); 12899 12900 p += scnprintf(p, end - p, 12901 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 12902 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 12903 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 12904 cnt[BTC_NCNT_COUNTRYCODE]); 12905 12906 return p - buf; 12907 } 12908 12909 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12910 { 12911 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 12912 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12913 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL; 12914 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 12915 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 12916 struct rtw89_btc_wl_info *wl = &cx->wl; 12917 u32 *cnt = rtwdev->btc.dm.cnt_notify; 12918 char *p = buf, *end = buf + bufsz; 12919 u32 cnt_sum = 0; 12920 u8 i; 12921 12922 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 12923 return 0; 12924 12925 p += scnprintf(p, end - p, "%s", 12926 "\n========== [Statistics] ==========\n"); 12927 12928 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 12929 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 12930 !wl->status.map.rf_off) { 12931 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8; 12932 12933 p += scnprintf(p, end - p, 12934 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 12935 "[summary]", pfwinfo->cnt_h2c, 12936 pfwinfo->cnt_h2c_fail, 12937 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 12938 pfwinfo->cnt_c2h, 12939 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 12940 le16_to_cpu(prptctrl->rpt_info.len_c2h), 12941 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 12942 rtwdev->btc.ver->info_buf); 12943 12944 p += scnprintf(p, end - p, 12945 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 12946 pfwinfo->event[BTF_EVNT_RPT], 12947 le16_to_cpu(prptctrl->rpt_info.cnt), 12948 le32_to_cpu(prptctrl->rpt_info.en)); 12949 12950 if (dm->error.map.wl_fw_hang) 12951 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 12952 p += scnprintf(p, end - p, "\n"); 12953 12954 p += scnprintf(p, end - p, 12955 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 12956 "[mailbox]", 12957 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 12958 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 12959 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 12960 12961 p += scnprintf(p, end - p, 12962 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 12963 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 12964 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 12965 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 12966 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 12967 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 12968 12969 p += scnprintf(p, end - p, 12970 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 12971 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 12972 wl->wcnt[BTC_WCNT_RFK_GO], 12973 wl->wcnt[BTC_WCNT_RFK_REJECT], 12974 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 12975 wl->rfk_info.proc_time); 12976 12977 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 12978 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 12979 12980 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 12981 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 12982 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 12983 } else { 12984 p += scnprintf(p, end - p, 12985 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 12986 "[summary]", 12987 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 12988 pfwinfo->cnt_c2h, 12989 wl->status.map.lps, wl->status.map.rf_off); 12990 } 12991 12992 for (i = 0; i < BTC_NCNT_NUM; i++) 12993 cnt_sum += dm->cnt_notify[i]; 12994 12995 p += scnprintf(p, end - p, 12996 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 12997 "[notify_cnt]", 12998 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 12999 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13000 13001 p += scnprintf(p, end - p, 13002 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13003 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13004 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13005 cnt[BTC_NCNT_WL_STA]); 13006 13007 p += scnprintf(p, end - p, 13008 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 13009 "[notify_cnt]", 13010 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13011 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 13012 cnt[BTC_NCNT_SPECIAL_PACKET]); 13013 13014 p += scnprintf(p, end - p, 13015 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 13016 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 13017 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 13018 cnt[BTC_NCNT_COUNTRYCODE]); 13019 13020 return p - buf; 13021 } 13022 13023 static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13024 { 13025 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 13026 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13027 struct rtw89_btc_fbtc_rpt_ctrl_v9 *prptctrl = NULL; 13028 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 13029 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 13030 struct rtw89_btc_wl_info *wl = &cx->wl; 13031 u32 *cnt = rtwdev->btc.dm.cnt_notify; 13032 char *p = buf, *end = buf + bufsz; 13033 u32 cnt_sum = 0; 13034 u8 i; 13035 13036 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13037 return 0; 13038 13039 p += scnprintf(p, end - p, "%s", 13040 "\n========== [Statistics] ==========\n"); 13041 13042 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13043 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 13044 !wl->status.map.rf_off) { 13045 prptctrl = &pfwinfo->rpt_ctrl.finfo.v9; 13046 13047 p += scnprintf(p, end - p, 13048 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ", 13049 "[summary]", pfwinfo->cnt_h2c, 13050 pfwinfo->cnt_h2c_fail, 13051 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13052 pfwinfo->cnt_c2h, 13053 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13054 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 13055 13056 p += scnprintf(p, end - p, 13057 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13058 pfwinfo->event[BTF_EVNT_RPT], 13059 le16_to_cpu(prptctrl->rpt_info.cnt), 13060 le32_to_cpu(prptctrl->rpt_info.en)); 13061 13062 if (dm->error.map.wl_fw_hang) 13063 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13064 p += scnprintf(p, end - p, "\n"); 13065 13066 p += scnprintf(p, end - p, 13067 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13068 "[mailbox]", 13069 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13070 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13071 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13072 13073 p += scnprintf(p, end - p, 13074 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 13075 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13076 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13077 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13078 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13079 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13080 13081 p += scnprintf(p, end - p, 13082 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 13083 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13084 wl->wcnt[BTC_WCNT_RFK_GO], 13085 wl->wcnt[BTC_WCNT_RFK_REJECT], 13086 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 13087 wl->rfk_info.proc_time); 13088 13089 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 13090 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 13091 13092 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 13093 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13094 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13095 } else { 13096 p += scnprintf(p, end - p, 13097 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 13098 "[summary]", 13099 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 13100 pfwinfo->cnt_c2h, 13101 wl->status.map.lps, wl->status.map.rf_off); 13102 } 13103 13104 for (i = 0; i < BTC_NCNT_NUM; i++) 13105 cnt_sum += dm->cnt_notify[i]; 13106 13107 p += scnprintf(p, end - p, 13108 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13109 "[notify_cnt]", 13110 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13111 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13112 13113 p += scnprintf(p, end - p, 13114 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13115 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13116 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13117 cnt[BTC_NCNT_WL_STA]); 13118 13119 p += scnprintf(p, end - p, 13120 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 13121 "[notify_cnt]", 13122 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13123 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 13124 cnt[BTC_NCNT_SPECIAL_PACKET]); 13125 13126 p += scnprintf(p, end - p, 13127 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 13128 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 13129 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 13130 cnt[BTC_NCNT_COUNTRYCODE]); 13131 13132 return p - buf; 13133 } 13134 13135 static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13136 { 13137 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 13138 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13139 struct rtw89_btc_fbtc_rpt_ctrl_v11 *prptctrl = NULL; 13140 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 13141 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 13142 struct rtw89_btc_wl_info *wl = &cx->wl; 13143 u32 *cnt = rtwdev->btc.dm.cnt_notify; 13144 char *p = buf, *end = buf + bufsz; 13145 u32 cnt_sum = 0; 13146 u8 i; 13147 13148 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13149 return 0; 13150 13151 p += scnprintf(p, end - p, "%s", 13152 "\n========== [Statistics] ==========\n"); 13153 13154 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13155 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 13156 !wl->status.map.rf_off) { 13157 prptctrl = &pfwinfo->rpt_ctrl.finfo.v11; 13158 13159 p += scnprintf(p, end - p, 13160 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 13161 "[summary]", pfwinfo->cnt_h2c, 13162 pfwinfo->cnt_h2c_fail, 13163 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13164 pfwinfo->cnt_c2h, 13165 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13166 le16_to_cpu(prptctrl->rpt_info.len_c2h), 13167 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 13168 rtwdev->btc.ver->info_buf); 13169 13170 p += scnprintf(p, end - p, 13171 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13172 pfwinfo->event[BTF_EVNT_RPT], 13173 le16_to_cpu(prptctrl->rpt_info.cnt), 13174 le32_to_cpu(prptctrl->rpt_info.en)); 13175 13176 if (dm->error.map.wl_fw_hang) 13177 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13178 p += scnprintf(p, end - p, "\n"); 13179 13180 p += scnprintf(p, end - p, 13181 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13182 "[mailbox]", 13183 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13184 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13185 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13186 13187 p += scnprintf(p, end - p, 13188 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 13189 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13190 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13191 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13192 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13193 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13194 13195 p += scnprintf(p, end - p, 13196 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 13197 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13198 wl->wcnt[BTC_WCNT_RFK_GO], 13199 wl->wcnt[BTC_WCNT_RFK_REJECT], 13200 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 13201 wl->rfk_info.proc_time); 13202 13203 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 13204 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13205 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13206 } else { 13207 p += scnprintf(p, end - p, 13208 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 13209 "[summary]", 13210 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 13211 pfwinfo->cnt_c2h, 13212 wl->status.map.lps, wl->status.map.rf_off); 13213 } 13214 13215 for (i = 0; i < BTC_NCNT_NUM; i++) 13216 cnt_sum += dm->cnt_notify[i]; 13217 13218 p += scnprintf(p, end - p, 13219 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13220 "[notify_cnt]", 13221 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13222 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13223 13224 p += scnprintf(p, end - p, 13225 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13226 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13227 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13228 cnt[BTC_NCNT_WL_STA]); 13229 13230 p += scnprintf(p, end - p, 13231 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 13232 "[notify_cnt]", 13233 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13234 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 13235 cnt[BTC_NCNT_SPECIAL_PACKET]); 13236 13237 p += scnprintf(p, end - p, 13238 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 13239 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 13240 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 13241 cnt[BTC_NCNT_COUNTRYCODE]); 13242 13243 return p - buf; 13244 } 13245 13246 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13247 { 13248 struct rtw89_btc *btc = &rtwdev->btc; 13249 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 13250 const struct rtw89_btc_ver *ver = btc->ver; 13251 struct rtw89_btc_dm *dm = &btc->dm; 13252 char *p = buf, *end = buf + bufsz; 13253 13254 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 13255 13256 p += scnprintf(p, end - p, 13257 "\n\n\n** Page:%3d/RunCNT:%3d **", 13258 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO], 13259 dm->cnt_dm[BTC_DCNT_RUN]); 13260 p += scnprintf(p, end - p, 13261 "\n========== [BTC FEATURE SUB VER] =========="); 13262 p += scnprintf(p, end - p, 13263 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]", 13264 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt, 13265 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots, 13266 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta); 13267 p += scnprintf(p, end - p, 13268 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]", 13269 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep, 13270 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg, 13271 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg); 13272 p += scnprintf(p, end - p, 13273 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]", 13274 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver, 13275 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh, 13276 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo); 13277 p += scnprintf(p, end - p, 13278 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],", 13279 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi, 13280 fwsubver->fcxmlo, ver->fcxmlo); 13281 13282 p += _show_cx_info(rtwdev, p, end - p); 13283 p += _show_wl_info(rtwdev, p, end - p); 13284 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_1ST); 13285 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_2ND); 13286 p += _show_dm_info(rtwdev, p, end - p); 13287 p += _show_fw_dm_msg(rtwdev, p, end - p); 13288 13289 if (ver->fcxmreg == 1) 13290 p += _show_mreg_v1(rtwdev, p, end - p); 13291 else if (ver->fcxmreg == 2) 13292 p += _show_mreg_v2(rtwdev, p, end - p); 13293 else if (ver->fcxmreg == 7) 13294 p += _show_mreg_v7(rtwdev, p, end - p); 13295 13296 p += _show_gpio_dbg(rtwdev, p, end - p); 13297 13298 if (ver->fcxbtcrpt == 1) 13299 p += _show_summary_v1(rtwdev, p, end - p); 13300 else if (ver->fcxbtcrpt == 4) 13301 p += _show_summary_v4(rtwdev, p, end - p); 13302 else if (ver->fcxbtcrpt == 5) 13303 p += _show_summary_v5(rtwdev, p, end - p); 13304 else if (ver->fcxbtcrpt == 105) 13305 p += _show_summary_v105(rtwdev, p, end - p); 13306 else if (ver->fcxbtcrpt == 7) 13307 p += _show_summary_v7(rtwdev, p, end - p); 13308 else if (ver->fcxbtcrpt == 8) 13309 p += _show_summary_v8(rtwdev, p, end - p); 13310 else if (ver->fcxbtcrpt == 9) 13311 p += _show_summary_v9(rtwdev, p, end - p); 13312 else if (ver->fcxbtcrpt == 11) 13313 p += _show_summary_v11(rtwdev, p, end - p); 13314 13315 p += scnprintf(p, end - p, "\n"); 13316 13317 return p - buf; 13318 } 13319 13320 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 13321 { 13322 const struct rtw89_chip_info *chip = rtwdev->chip; 13323 struct rtw89_btc *btc = &rtwdev->btc; 13324 const struct rtw89_btc_ver *btc_ver_def; 13325 const struct rtw89_fw_suit *fw_suit; 13326 u32 suit_ver_code; 13327 int i; 13328 13329 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 13330 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 13331 13332 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 13333 btc_ver_def = &rtw89_btc_ver_defs[i]; 13334 13335 if (chip->chip_id != btc_ver_def->chip_id) 13336 continue; 13337 13338 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 13339 btc->ver = btc_ver_def; 13340 goto out; 13341 } 13342 } 13343 13344 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 13345 13346 out: 13347 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 13348 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 13349 } 13350 13351 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms) 13352 { 13353 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt0.link_info; 13354 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 13355 13356 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) 13357 return; 13358 13359 if (!a2dp.exist) 13360 return; 13361 13362 fsleep(ms * 1000); 13363 } 13364 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time); 13365 13366 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state) 13367 { 13368 rtwdev->btc.cx.wl.rfk_info.con_rfk = state; 13369 } 13370 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk); 13371