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 0x09180213 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, 119, 3), 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 = 11, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, 141 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 142 .max_role_num = 6, .fcxosi = 7, .fcxmlo = 2, .bt_desired = 8, 143 .fcxtrx = 9, .fcxtxpwr = 1, 144 }, 145 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 111, 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 = 11, 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, .fcxtxpwr = 1, 153 }, 154 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 94, 0), 155 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 156 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 157 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 158 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 10, 159 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 160 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, 161 .fcxtrx = 9, .fcxtxpwr = 1, 162 }, 163 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 133, 0), 164 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 165 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 166 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 167 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107, 168 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 169 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 170 .fcxtrx = 107, .fcxtxpwr = 0, 171 }, 172 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0), 173 .fcxbtcrpt = 8, .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, .fcxtxpwr = 0, 180 }, 181 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0), 182 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 183 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 184 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 185 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 186 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800, 187 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 188 .fcxtrx = 0, .fcxtxpwr = 0, 189 }, 190 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 119, 3), 191 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 192 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 193 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 194 .fwlrole = 11, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, 195 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 196 .max_role_num = 6, .fcxosi = 7, .fcxmlo = 2, .bt_desired = 8, 197 .fcxtrx = 9, .fcxtxpwr = 1, 198 }, 199 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 111, 0), 200 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8, 201 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 202 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8, 203 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11, 204 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800, 205 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8, 206 .fcxtrx = 9, .fcxtxpwr = 1, 207 }, 208 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 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 = 4, .fcxctrl = 7, .fcxinit = 7, 213 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 3, .info_buf = 1800, 214 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 215 .fcxtrx = 7, .fcxtxpwr = 0, 216 }, 217 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0), 218 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 219 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 220 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 221 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7, 222 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 2, .info_buf = 1800, 223 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 224 .fcxtrx = 0, .fcxtxpwr = 0, 225 }, 226 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), 227 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 228 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 229 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 230 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 231 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_ver = 1, .info_buf = 1800, 232 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 233 .fcxtrx = 0, .fcxtxpwr = 0, 234 }, 235 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 133, 0), 236 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 237 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 238 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 239 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107, 240 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 241 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 242 .fcxtrx = 107, .fcxtxpwr = 0, 243 }, 244 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), 245 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 246 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 247 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 248 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 249 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 250 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 251 .fcxtrx = 0, .fcxtxpwr = 0, 252 }, 253 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 130, 1), 254 .fcxbtcrpt = 205, .fcxtdma = 4, .fcxslots = 2, .fcxcysta = 105, 255 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 256 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 257 .fwlrole = 101, .frptmap = 3, .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 = 107, .fcxtxpwr = 0, 261 }, 262 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 97, 0), 263 .fcxbtcrpt = 4, .fcxtdma = 4, .fcxslots = 2, .fcxcysta = 105, 264 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 265 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 266 .fwlrole = 101, .frptmap = 3, .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 = 107, .fcxtxpwr = 0, 270 }, 271 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), 272 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 273 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 274 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 275 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 276 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 277 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 278 .fcxtrx = 0, .fcxtxpwr = 0, 279 }, 280 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), 281 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 282 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 283 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 284 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 285 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 286 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 287 .fcxtrx = 0, .fcxtxpwr = 0, 288 }, 289 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), 290 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 291 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 292 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 293 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 294 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 295 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 296 .fcxtrx = 0, .fcxtxpwr = 0, 297 }, 298 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 133, 0), 299 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 300 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8, 301 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 302 .fwlrole = 7, .frptmap = 105, .fcxctrl = 7, .fcxinit = 107, 303 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800, 304 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 305 .fcxtrx = 107, .fcxtxpwr = 0, 306 }, 307 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0), 308 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 309 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 310 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 311 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 312 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800, 313 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 314 .fcxtrx = 0, .fcxtxpwr = 0, 315 }, 316 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), 317 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 318 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 319 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 320 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 321 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 322 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 323 .fcxtrx = 0, .fcxtxpwr = 0, 324 }, 325 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), 326 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, 327 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 328 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 329 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 330 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800, 331 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 332 .fcxtrx = 0, .fcxtxpwr = 0, 333 }, 334 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), 335 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 336 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 337 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 338 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, 339 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280, 340 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 341 .fcxtrx = 0, .fcxtxpwr = 0, 342 }, 343 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), 344 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 345 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 346 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 347 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 348 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1280, 349 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 350 .fcxtrx = 0, .fcxtxpwr = 0, 351 }, 352 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), 353 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 354 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 355 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 356 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 357 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1024, 358 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 359 .fcxtrx = 0, .fcxtxpwr = 0, 360 }, 361 362 /* keep it to be the last as default entry */ 363 {0, RTW89_FW_VER_CODE(0, 0, 0, 0), 364 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 365 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 366 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 367 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 368 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1024, 369 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 370 .fcxtrx = 0, .fcxtxpwr = 0, 371 }, 372 }; 373 374 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1) 375 376 static const union rtw89_btc_wl_state_map btc_scanning_map = { 377 .map = { 378 .scan = 1, 379 .dhcp = 1, 380 .roaming = 1, 381 .transacting = 1, 382 ._4way = 1, 383 .handshake = 1, 384 }, 385 }; 386 387 static u32 chip_id_to_bt_rom_code_id(u32 id) 388 { 389 switch (id) { 390 case RTL8852A: 391 case RTL8852B: 392 case RTL8852C: 393 case RTL8852BT: 394 return 0x8852; 395 case RTL8851B: 396 return 0x8851; 397 case RTL8922A: 398 case RTL8922D: 399 return 0x8922; 400 default: 401 return 0; 402 } 403 } 404 405 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e 406 407 static const char *id_to_mlme_state(u32 id) 408 { 409 switch (id) { 410 CASE_BTC_MLME_STATE(NO_LINK); 411 CASE_BTC_MLME_STATE(LINKING); 412 CASE_BTC_MLME_STATE(LINKED); 413 default: 414 return "unknown"; 415 } 416 } 417 418 static char *chip_id_str(u32 id) 419 { 420 switch (id) { 421 case RTL8852A: 422 return "RTL8852A"; 423 case RTL8852B: 424 return "RTL8852B"; 425 case RTL8852C: 426 return "RTL8852C"; 427 case RTL8852BT: 428 return "RTL8852BT"; 429 case RTL8851B: 430 return "RTL8851B"; 431 case RTL8922A: 432 return "RTL8922A"; 433 case RTL8922D: 434 return "RTL8922D"; 435 default: 436 return "UNKNOWN"; 437 } 438 } 439 440 struct rtw89_btc_btf_tlv { 441 u8 type; 442 u8 len; 443 u8 val[]; 444 } __packed; 445 446 struct rtw89_btc_btf_tlv_v7 { 447 u8 type; 448 u8 ver; 449 u8 len; 450 u8 val[]; 451 } __packed; 452 453 enum btc_btf_set_report_en { 454 RPT_EN_TDMA, 455 RPT_EN_CYCLE, 456 RPT_EN_MREG, 457 RPT_EN_BT_VER_INFO, 458 RPT_EN_BT_SCAN_INFO, 459 RPT_EN_BT_DEVICE_INFO, 460 RPT_EN_BT_AFH_MAP, 461 RPT_EN_BT_AFH_MAP_LE, 462 RPT_EN_BT_TX_PWR_LVL, 463 RPT_EN_FW_STEP_INFO, 464 RPT_EN_TEST, 465 RPT_EN_WL_ALL, 466 RPT_EN_BT_ALL, 467 RPT_EN_ALL, 468 RPT_EN_MONITER, 469 }; 470 471 struct rtw89_btc_btf_set_report_v1 { 472 u8 fver; 473 __le32 enable; 474 __le32 para; 475 } __packed; 476 477 struct rtw89_btc_btf_set_report_v8 { 478 u8 type; 479 u8 fver; 480 u8 len; 481 __le32 map; 482 } __packed; 483 484 union rtw89_fbtc_rtp_ctrl { 485 struct rtw89_btc_btf_set_report_v1 v1; 486 struct rtw89_btc_btf_set_report_v8 v8; 487 }; 488 489 #define BTF_SET_SLOT_TABLE_VER 1 490 struct rtw89_btc_btf_set_slot_table { 491 u8 fver; 492 u8 tbl_num; 493 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); 494 } __packed; 495 496 struct rtw89_btc_btf_set_slot_table_v7 { 497 u8 type; 498 u8 ver; 499 u8 len; 500 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX]; 501 } __packed; 502 503 struct rtw89_btc_btf_set_mon_reg_v1 { 504 u8 fver; 505 u8 reg_num; 506 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); 507 } __packed; 508 509 struct rtw89_btc_btf_set_mon_reg_v7 { 510 u8 type; 511 u8 fver; 512 u8 len; 513 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len); 514 } __packed; 515 516 union rtw89_fbtc_set_mon_reg { 517 struct rtw89_btc_btf_set_mon_reg_v1 v1; 518 struct rtw89_btc_btf_set_mon_reg_v7 v7; 519 } __packed; 520 521 enum btc_btf_set_cx_policy { 522 CXPOLICY_TDMA = 0x0, 523 CXPOLICY_SLOT = 0x1, 524 CXPOLICY_TYPE = 0x2, 525 CXPOLICY_MAX, 526 }; 527 528 enum btc_b2w_scoreboard { 529 BTC_BSCB_ACT = BIT(0), 530 BTC_BSCB_ON = BIT(1), 531 BTC_BSCB_WHQL = BIT(2), 532 BTC_BSCB_BT_S1 = BIT(3), 533 BTC_BSCB_A2DP_ACT = BIT(4), 534 BTC_BSCB_RFK_RUN = BIT(5), 535 BTC_BSCB_RFK_REQ = BIT(6), 536 BTC_BSCB_LPS = BIT(7), 537 BTC_BSCB_BT_LNAB0 = BIT(8), 538 BTC_BSCB_BT_LNAB1 = BIT(10), 539 BTC_BSCB_WLRFK = BIT(11), 540 BTC_BSCB_BT_HILNA = BIT(13), 541 BTC_BSCB_BT_HILNA_56G = BIT(14), 542 BTC_BSCB_CTCODE = BIT(15), 543 BTC_BSCB_BT_CONNECT = BIT(16), 544 BTC_BSCB_BT_CONNECT_56G = BIT(17), 545 BTC_BSCB_BT_LNAB0_56G = BIT(18), 546 BTC_BSCB_BT_LNAB1_56G = BIT(19), 547 BTC_BSCB_BT_BACKOFF_LNA = BIT(21), 548 BTC_BSCB_BT_15DOT4_TRX = BIT(22), 549 BTC_BSCB_HID_ACT = BIT(23), 550 BTC_BSCB_BT_15DOT4 = BIT(24), 551 BTC_BSCB_BT_PROTECT = BIT(27), 552 BTC_BSCB_PAN_ACT = BIT(28), 553 BTC_BSCB_HFP_ACT = BIT(29), 554 BTC_BSCB_PATCH_CODE = BIT(30), 555 BTC_BSCB_ALL = GENMASK(30, 0), 556 }; 557 558 enum btc_phymap { 559 BTC_PHY_0 = BIT(0), 560 BTC_PHY_1 = BIT(1), 561 BTC_PHY_ALL = BIT(0) | BIT(1), 562 }; 563 564 enum btc_cx_state_map { 565 BTC_WIDLE = 0, 566 BTC_WBUSY_BNOSCAN, 567 BTC_WBUSY_BSCAN, 568 BTC_WSCAN_BNOSCAN, 569 BTC_WSCAN_BSCAN, 570 BTC_WLINKING 571 }; 572 573 enum btc_ant_phase { 574 BTC_ANT_WPOWERON = 0, 575 BTC_ANT_WINIT, 576 BTC_ANT_WONLY, 577 BTC_ANT_WOFF, 578 BTC_ANT_W2G, 579 BTC_ANT_FDD, 580 BTC_ANT_W25G, 581 BTC_ANT_FREERUN, 582 BTC_ANT_WRFK, 583 BTC_ANT_WRFK2, 584 BTC_ANT_PTA, /* for Multi-PTA, each hw-band has its own PTA */ 585 BTC_ANT_MAX 586 }; 587 588 enum btc_plt { 589 BTC_PLT_NONE = 0, 590 BTC_PLT_LTE_RX = BIT(0), 591 BTC_PLT_GNT_BT_TX = BIT(1), 592 BTC_PLT_GNT_BT_RX = BIT(2), 593 BTC_PLT_GNT_WL = BIT(3), 594 BTC_PLT_BT = BIT(1) | BIT(2), 595 BTC_PLT_ALL = 0xf 596 }; 597 598 enum btc_cx_poicy_main_type { 599 BTC_CXP_OFF = 0, 600 BTC_CXP_OFFB, 601 BTC_CXP_OFFE, 602 BTC_CXP_FIX, 603 BTC_CXP_PFIX, 604 BTC_CXP_AUTO, 605 BTC_CXP_PAUTO, 606 BTC_CXP_AUTO2, 607 BTC_CXP_PAUTO2, 608 BTC_CXP_MANUAL, 609 BTC_CXP_USERDEF0, 610 BTC_CXP_MAIN_MAX 611 }; 612 613 enum btc_bslot_length { 614 BTC_BSLOT_A2DP_HID = 60, 615 BTC_BSLOT_A2DP = 50, 616 BTC_BSLOT_A2DP_2 = 40, 617 BTC_BSLOT_INQ = 30, 618 BTC_BSLOT_IDLE = 20, 619 }; 620 621 enum btc_cx_poicy_type { 622 /* TDMA off + pri: BT > WL */ 623 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0, 624 625 /* TDMA off + pri: WL > BT */ 626 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1, 627 628 /* TDMA off + pri: BT = WL */ 629 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2, 630 631 /* TDMA off + pri: BT = WL > BT_Lo */ 632 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3, 633 634 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */ 635 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4, 636 637 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 638 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5, 639 640 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 641 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6, 642 643 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 644 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7, 645 646 /* TDMA off + pri: BT_Hi > WL > BT_Lo */ 647 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8, 648 649 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 650 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9, 651 652 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 653 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10, 654 655 /* TDMA off + pri: WL_Hi-Tx = BT */ 656 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11, 657 658 /* TDMA off + pri: WL > BT, Block-BT*/ 659 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12, 660 661 /* TDMA off+Bcn-Protect + pri: BT_Hi > WL > BT_Lo */ 662 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0, 663 664 /* TDMA off+Bcn-Protect + pri: BT_Hi_Tx = WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 665 BTC_CXP_OFFB_BWB1 = (BTC_CXP_OFFB << 8) | 1, 666 667 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 668 BTC_CXP_OFFB_BWB2 = (BTC_CXP_OFFB << 8) | 2, 669 670 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx = BT*/ 671 BTC_CXP_OFFB_BWB3 = (BTC_CXP_OFFB << 8) | 3, 672 673 /* TDMA off+Bcn-Protect + pri: BT > WL*/ 674 BTC_CXP_OFFB_BWB4 = (BTC_CXP_OFFB << 8) | 4, 675 676 /* TDMA off + Ext-Ctrl + pri: default */ 677 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0, 678 679 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 680 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1, 681 682 /* TDMA off + Ext-Ctrl + pri: default */ 683 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2, 684 685 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 686 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3, 687 688 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */ 689 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4, 690 691 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */ 692 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5, 693 694 /* TDMA off + Ext-Ctrl + pri: default */ 695 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6, 696 697 /* TDMA Fix slot-0: W1:B1 = 30:30 */ 698 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0, 699 700 /* TDMA Fix slot-1: W1:B1 = 50:50 */ 701 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1, 702 703 /* TDMA Fix slot-2: W1:B1 = 20:30 */ 704 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2, 705 706 /* TDMA Fix slot-3: W1:B1 = 40:10 */ 707 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3, 708 709 /* TDMA Fix slot-4: W1:B1 = 70:10 */ 710 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4, 711 712 /* TDMA Fix slot-5: W1:B1 = 20:60 */ 713 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5, 714 715 /* TDMA Fix slot-6: W1:B1 = 30:60 */ 716 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6, 717 718 /* TDMA Fix slot-7: W1:B1 = 20:80 */ 719 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7, 720 721 /* TDMA Fix slot-8: W1:B1 = user-define */ 722 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8, 723 724 /* TDMA Fix slot-9: W1:B1 = 40:10 */ 725 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9, 726 727 /* TDMA Fix slot-10: W1:B1 = 40:10 */ 728 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10, 729 730 /* TDMA Fix slot-11: W1:B1 = 40:10 */ 731 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11, 732 733 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */ 734 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0, 735 736 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */ 737 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1, 738 739 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */ 740 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2, 741 742 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */ 743 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3, 744 745 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */ 746 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4, 747 748 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */ 749 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5, 750 751 /* PS-TDMA Fix slot-6: W1:B1 = user-define */ 752 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6, 753 754 /* TDMA Auto slot-0: W1:B1 = 50:200 */ 755 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0, 756 757 /* TDMA Auto slot-1: W1:B1 = 60:200 */ 758 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1, 759 760 /* TDMA Auto slot-2: W1:B1 = 20:200 */ 761 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2, 762 763 /* TDMA Auto slot-3: W1:B1 = user-define */ 764 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3, 765 766 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */ 767 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0, 768 769 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */ 770 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1, 771 772 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */ 773 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2, 774 775 /* PS-TDMA Auto slot-3: W1:B1 = user-define */ 776 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3, 777 778 /* TDMA Auto slot2-0: W1:B4 = 30:50 */ 779 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0, 780 781 /* TDMA Auto slot2-1: W1:B4 = 30:70 */ 782 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1, 783 784 /* TDMA Auto slot2-2: W1:B4 = 50:50 */ 785 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2, 786 787 /* TDMA Auto slot2-3: W1:B4 = 60:60 */ 788 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3, 789 790 /* TDMA Auto slot2-4: W1:B4 = 20:80 */ 791 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4, 792 793 /* TDMA Auto slot2-5: W1:B4 = user-define */ 794 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5, 795 796 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */ 797 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0, 798 799 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */ 800 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1, 801 802 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */ 803 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2, 804 805 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */ 806 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3, 807 808 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */ 809 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4, 810 811 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */ 812 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5, 813 814 BTC_CXP_MAX = 0xffff 815 }; 816 817 enum btc_wl_rfk_result { 818 BTC_WRFK_REJECT = 0, 819 BTC_WRFK_ALLOW = 1, 820 }; 821 822 enum btc_coex_info_map_en { 823 BTC_COEX_INFO_CX = BIT(0), 824 BTC_COEX_INFO_WL = BIT(1), 825 BTC_COEX_INFO_BT = BIT(2), 826 BTC_COEX_INFO_DM = BIT(3), 827 BTC_COEX_INFO_MREG = BIT(4), 828 BTC_COEX_INFO_SUMMARY = BIT(5), 829 BTC_COEX_INFO_ALL = GENMASK(7, 0), 830 }; 831 832 #define BTC_CXP_MASK GENMASK(15, 8) 833 834 enum btc_w2b_scoreboard { 835 BTC_WSCB_ACTIVE = BIT(0), 836 BTC_WSCB_ON = BIT(1), 837 BTC_WSCB_SCAN = BIT(2), 838 BTC_WSCB_UNDERTEST = BIT(3), 839 BTC_WSCB_RXGAIN = BIT(4), 840 BTC_WSCB_5GHICH = BIT(6), 841 BTC_WSCB_WLBUSY = BIT(7), 842 BTC_WSCB_EXTFEM = BIT(8), 843 BTC_WSCB_TDMA = BIT(9), 844 BTC_WSCB_FIX2M = BIT(10), 845 BTC_WSCB_WLRFK = BIT(11), 846 BTC_WSCB_RXSCAN_PRI = BIT(12), 847 BTC_WSCB_BT_HILNA = BIT(13), 848 BTC_WSCB_BTLOG = BIT(14), 849 BTC_WSCB_CTCODE = BIT(15), 850 BTC_WSCB_RXGAIN_56G = BIT(16), 851 BTC_WSCB_BT_HILNA_56G = BIT(17), 852 BTC_WSCB_BT_BACKOFF_LNA = BIT(18), 853 BTC_WSCB_ALL = GENMASK(23, 0), 854 }; 855 856 enum btc_wl_link_mode_v0 { 857 BTC_WLINK_V0_NOLINK = 0x0, 858 BTC_WLINK_V0_2G_STA, 859 BTC_WLINK_V0_2G_AP, 860 BTC_WLINK_V0_2G_GO, 861 BTC_WLINK_V0_2G_GC, 862 BTC_WLINK_V0_2G_SCC, 863 BTC_WLINK_V0_2G_MCC, 864 BTC_WLINK_V0_25G_MCC, 865 BTC_WLINK_V0_25G_DBCC, 866 BTC_WLINK_V0_5G, 867 BTC_WLINK_V0_2G_NAN, 868 BTC_WLINK_V0_OTHER, 869 BTC_WLINK_V0_MAX 870 }; 871 872 enum btc_wl_link_mode_v1 { 873 BTC_WLINK_NOLINK = 0x0, 874 BTC_WLINK_STA, 875 BTC_WLINK_AP, 876 BTC_WLINK_GO, 877 BTC_WLINK_GC, 878 BTC_WLINK_SCC, 879 BTC_WLINK_SB_MCC, 880 BTC_WLINK_DB_MCC, /* 2+0/0+2 Dual-RF-band MCC */ 881 BTC_WLINK_MAX 882 }; 883 884 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e 885 886 static const char *id_to_linkmode(u8 id) 887 { 888 switch (id) { 889 CASE_BTC_WL_LINK_MODE(NOLINK); 890 CASE_BTC_WL_LINK_MODE(STA); 891 CASE_BTC_WL_LINK_MODE(AP); 892 CASE_BTC_WL_LINK_MODE(GO); 893 CASE_BTC_WL_LINK_MODE(GC); 894 CASE_BTC_WL_LINK_MODE(SCC); 895 CASE_BTC_WL_LINK_MODE(SB_MCC); 896 CASE_BTC_WL_LINK_MODE(DB_MCC); 897 default: 898 return "unknown"; 899 } 900 } 901 902 enum btc_wl_mrole_type { 903 BTC_WLMROLE_NONE = 0x0, 904 BTC_WLMROLE_STA_GC, 905 BTC_WLMROLE_STA_GC_NOA, 906 BTC_WLMROLE_STA_GO, 907 BTC_WLMROLE_STA_GO_NOA, 908 BTC_WLMROLE_STA_STA, 909 BTC_WLMROLE_MAX 910 }; 911 912 enum btc_bt_hid_type { 913 BTC_HID_218 = BIT(0), 914 BTC_HID_418 = BIT(1), 915 BTC_HID_BLE = BIT(2), 916 BTC_HID_RCU = BIT(3), 917 BTC_HID_RCU_VOICE = BIT(4), 918 BTC_HID_OTHER_LEGACY = BIT(5) 919 }; 920 921 enum btc_reset_module { 922 BTC_RESET_CX = BIT(0), 923 BTC_RESET_DM = BIT(1), 924 BTC_RESET_CTRL = BIT(2), 925 BTC_RESET_CXDM = BIT(0) | BIT(1), 926 BTC_RESET_BTINFO = BIT(3), 927 BTC_RESET_MDINFO = BIT(4), 928 BTC_RESET_BT_PSD_DM = BIT(5), 929 BTC_RESET_BTINFO2 = BIT(6), 930 BTC_RESET_ALL = GENMASK(7, 0), 931 }; 932 933 enum btc_gnt_state { 934 BTC_GNT_HW = 0, 935 BTC_GNT_SW_LO, 936 BTC_GNT_SW_HI, 937 BTC_GNT_MAX, 938 939 BTC_GNT_SET_SKIP = 0xff, 940 }; 941 942 enum btc_ctr_path { 943 BTC_CTRL_BY_BT = 0, 944 BTC_CTRL_BY_WL 945 }; 946 947 enum btc_wlact_state { 948 BTC_WLACT_HW = 0, 949 BTC_WLACT_SW_LO, 950 BTC_WLACT_SW_HI, 951 BTC_WLACT_MAX, 952 }; 953 954 enum btc_wl_max_tx_time { 955 BTC_MAX_TX_TIME_L1 = 500, 956 BTC_MAX_TX_TIME_L2 = 1000, 957 BTC_MAX_TX_TIME_L3 = 2000, 958 BTC_MAX_TX_TIME_DEF = 5280 959 }; 960 961 enum btc_wl_max_tx_retry { 962 BTC_MAX_TX_RETRY_L1 = 7, 963 BTC_MAX_TX_RETRY_L2 = 15, 964 BTC_MAX_TX_RETRY_DEF = 31, 965 }; 966 967 enum btc_reason_and_action { 968 BTC_RSN_NONE, 969 BTC_RSN_NTFY_INIT, 970 BTC_RSN_NTFY_SWBAND, 971 BTC_RSN_NTFY_WL_STA, 972 BTC_RSN_NTFY_RADIO_STATE, 973 BTC_RSN_UPDATE_BT_SCBD, 974 BTC_RSN_NTFY_WL_RFK, 975 BTC_RSN_UPDATE_BT_INFO, 976 BTC_RSN_NTFY_SCAN_START, 977 BTC_RSN_NTFY_SCAN_FINISH, 978 BTC_RSN_NTFY_SPECIFIC_PACKET, 979 BTC_RSN_NTFY_POWEROFF, 980 BTC_RSN_NTFY_ROLE_INFO, 981 BTC_RSN_CMD_SET_COEX, 982 BTC_RSN_ACT1_WORK, 983 BTC_RSN_BT_DEVINFO_WORK, 984 BTC_RSN_RFK_CHK_WORK, 985 BTC_RSN_UPDATE_BT_LEAUDINFO, 986 BTC_RSN_NUM, 987 BTC_ACT_NONE = 100, 988 BTC_ACT_WL_ONLY, 989 BTC_ACT_WL_5G, 990 BTC_ACT_WL_OTHER, 991 BTC_ACT_WL_IDLE, 992 BTC_ACT_WL_NC, 993 BTC_ACT_WL_RFK, 994 BTC_ACT_WL_INIT, 995 BTC_ACT_WL_OFF, 996 BTC_ACT_FREERUN, 997 BTC_ACT_BT_WHQL, 998 BTC_ACT_BT_RFK, 999 BTC_ACT_BT_OFF, 1000 BTC_ACT_BT_IDLE, 1001 BTC_ACT_BT_HFP, 1002 BTC_ACT_BT_HID, 1003 BTC_ACT_BT_A2DP, 1004 BTC_ACT_BT_A2DPSINK, 1005 BTC_ACT_BT_PAN, 1006 BTC_ACT_BT_A2DP_HID, 1007 BTC_ACT_BT_A2DP_PAN, 1008 BTC_ACT_BT_PAN_HID, 1009 BTC_ACT_BT_A2DP_PAN_HID, 1010 BTC_ACT_BT_BIS, 1011 BTC_ACT_BT_CIS, 1012 BTC_ACT_WL_25G_MCC, 1013 BTC_ACT_WL_2G_MCC, 1014 BTC_ACT_WL_2G_SCC, 1015 BTC_ACT_WL_2G_AP, 1016 BTC_ACT_WL_2G_GO, 1017 BTC_ACT_WL_2G_GC, 1018 BTC_ACT_WL_2G_NAN, 1019 BTC_ACT_LAST, 1020 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE, 1021 BTC_ACT_EXT_BIT = BIT(14), 1022 BTC_POLICY_EXT_BIT = BIT(15), 1023 }; 1024 1025 #define BTC_FREERUN_ANTISO_MIN 30 1026 #define BTC_TDMA_BTHID_MAX 2 1027 #define BTC_BLINK_NOCONNECT 0 1028 #define BTC_B1_MAX 250 /* unit ms */ 1029 1030 static void _run_coex(struct rtw89_dev *rtwdev, 1031 enum btc_reason_and_action reason); 1032 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state); 1033 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid); 1034 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid, bool is_c2h); 1035 static void _update_sdm_map(struct rtw89_dev *rtwdev); 1036 static const char *id_to_h2c(u32 id); 1037 1038 static void _reset_h2c_macro(struct rtw89_btc *btc) 1039 { 1040 btc->hbuf_len = 0; 1041 btc->hbuf_cnt = 0; 1042 memset(btc->hbuf, 0, BTC_H2C_MAXLEN); 1043 } 1044 1045 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, 1046 void *param, u16 len) 1047 { 1048 struct rtw89_btc *btc = &rtwdev->btc; 1049 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 1050 struct rtw89_btc_cx *cx = &btc->cx; 1051 struct rtw89_btc_wl_info *wl = &cx->wl; 1052 struct rtw89_btc_dm *dm = &btc->dm; 1053 u8 h2c_func_mask, bid = BTC_BT_1ST; 1054 u8 *buf = param; 1055 int ret; 1056 1057 if (len > BTC_H2C_MAXLEN || len == 0) { 1058 btc->fwinfo.cnt_h2c_fail++; 1059 dm->error.map.h2c_buffer_over = true; 1060 return -EINVAL; 1061 } else if (!wl->status.map.init_ok) { 1062 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1063 "[BTC], %s(): return by btc not init!!\n", __func__); 1064 pfwinfo->cnt_h2c_fail++; 1065 return -EINVAL; 1066 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF && 1067 wl->status.map.rf_off == BTC_LPS_RF_OFF) || 1068 (wl->status.map.lps_pre == BTC_LPS_RF_OFF && 1069 wl->status.map.lps == BTC_LPS_RF_OFF)) { 1070 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1071 "[BTC], %s(): return by wl off!!\n", __func__); 1072 pfwinfo->cnt_h2c_fail++; 1073 return -EINVAL; 1074 } 1075 1076 h2c_func_mask = h2c_func & (~BT_H2C_FUNC_BT2ND); 1077 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 1078 bid = !!(h2c_func & BT_H2C_FUNC_BT2ND); 1079 1080 if (btc->io_oflld_type != BTC_IO_OFLD_BTC_H2C || btc->cli_h2c_cmd || 1081 h2c_func_mask == SET_H2C_MACRO || 1082 (h2c_func_mask == SET_DRV_INFO && buf[0] == CXDRVINFO_TRX) || 1083 (h2c_func_mask == SET_IOFLD_SCBD && dm->scbd_write_instant) || 1084 h2c_func_mask == SET_BT_LNA_CONSTRAIN) { 1085 h2c_class = BTFC_SET; 1086 1087 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, 1088 buf, len, false, true); 1089 1090 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1091 "[BTC], %s():class=%d, bt%d-func=%s, len=%d\n", 1092 __func__, h2c_class, bid, 1093 id_to_h2c(h2c_func_mask), len); 1094 1095 if (h2c_func_mask == SET_H2C_MACRO) { 1096 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1097 "[BTC], %s():Send H2C-MACRO cnt=%d, len=%d\n", 1098 __func__, btc->hbuf_cnt, btc->hbuf_len); 1099 _reset_h2c_macro(btc); /* clear H2C MACRO buffer */ 1100 } 1101 1102 if (ret != 0) { /* Send H2C fail */ 1103 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1104 "[BTC], %s():return by rtw_hal_mac_send_h2c\n", 1105 __func__); 1106 btc->fwinfo.cnt_h2c_fail++; 1107 return 0; 1108 } 1109 1110 btc->fwinfo.cnt_h2c++; 1111 return 0; 1112 } else { /* Fill H2C MACRO buffer(TLV format) temporarily */ 1113 if (btc->hbuf_cnt == 0) 1114 _reset_h2c_macro(btc); 1115 1116 /* Type:1 byte, Length:2 Bytes, Data:len bytes */ 1117 if (btc->hbuf_len + len + 3 > BTC_H2C_MAXLEN) { 1118 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1119 "[BTC], %s():return by MACRO buf full(%d)\n", 1120 __func__, btc->hbuf_len + len + 3); 1121 btc->fwinfo.cnt_h2c_fail++; 1122 return 0; 1123 } 1124 1125 btc->hbuf[btc->hbuf_len] = h2c_func; 1126 btc->hbuf[btc->hbuf_len + 1] = len & GENMASK(7, 0); 1127 btc->hbuf[btc->hbuf_len + 2] = (len & GENMASK(15, 8)) >> 8; 1128 1129 memcpy(&btc->hbuf[btc->hbuf_len + 3], buf, len); 1130 btc->hbuf_len = btc->hbuf_len + len + 3; 1131 btc->hbuf_cnt++; 1132 1133 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1134 "[BTC], %s():Buffer H2C-MACRO cnt=%d/bt%d-func=%s/len=%d\n", 1135 __func__, btc->hbuf_cnt, bid, 1136 id_to_h2c(h2c_func_mask), len); 1137 1138 h2c_func = SET_H2C_MACRO; 1139 buf = btc->hbuf; 1140 len = btc->hbuf_len; 1141 } 1142 1143 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, buf, len, 1144 false, true); 1145 if (ret) 1146 pfwinfo->cnt_h2c_fail++; 1147 else 1148 pfwinfo->cnt_h2c++; 1149 1150 if (h2c_func == SET_H2C_MACRO) 1151 _reset_h2c_macro(btc); 1152 1153 return ret; 1154 } 1155 1156 #define BTC_DEFAULT_SIR_THRES 51 /* dB, BT Pin - This = TDD/FDD swtch thres */ 1157 #define BTC_FDDR_TP_SETUP_TIME 1 /* in second */ 1158 #define BTC_FDDR_TP_HOLD_TIME 3 /* in second */ 1159 #define BTC_FDDR_RX_LOW_RATE_THRES 4 /* low rate for TDD swotch */ 1160 1161 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) 1162 { 1163 struct rtw89_btc *btc = &rtwdev->btc; 1164 struct rtw89_btc_cx *cx = &btc->cx; 1165 const struct rtw89_btc_ver *ver = btc->ver; 1166 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 1167 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 1168 u8 i; 1169 1170 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 1171 1172 if (type & BTC_RESET_CX) { 1173 memset(cx, 0, sizeof(*cx)); 1174 cx->bt_ext.max_tx_pwr = RTW89_BTC_BT_DEF_LE_TX_PWR; 1175 cx->bt_ext.ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1176 } 1177 1178 if (type & BTC_RESET_BTINFO) {/* only for BT enable */ 1179 memset(bt0, 0, sizeof(*bt0)); 1180 bt0->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1181 bt0->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1182 bt0->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1183 bt0->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1184 bt0->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1185 } else if (type & BTC_RESET_BTINFO2) { 1186 memset(bt1, 0, sizeof(*bt1)); 1187 bt1->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1188 bt1->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR; 1189 bt1->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1190 bt1->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR; 1191 bt1->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO; 1192 } 1193 1194 if (type & BTC_RESET_CTRL) { 1195 memset(&btc->ctrl, 0, sizeof(btc->ctrl)); 1196 btc->ctrl.trace_step = FCXDEF_STEP; 1197 } 1198 1199 /* Init Coex variables that are not zero */ 1200 if (type & BTC_RESET_DM) { 1201 memset(&btc->dm, 0, sizeof(btc->dm)); 1202 1203 /* set the slot_now table to original */ 1204 btc->dm.tdma_now = t_def[CXTD_OFF]; 1205 btc->dm.tdma = t_def[CXTD_OFF]; 1206 if (ver->fcxslots >= 2) { 1207 for (i = 0; i < ARRAY_SIZE(s_def); i++) { 1208 btc->dm.slot.v7[i].dur = s_def[i].dur; 1209 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype; 1210 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl; 1211 } 1212 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7, 1213 sizeof(btc->dm.slot_now.v7)); 1214 } else { 1215 memcpy(&btc->dm.slot_now.v1, s_def, 1216 sizeof(btc->dm.slot_now.v1)); 1217 memcpy(&btc->dm.slot.v1, s_def, 1218 sizeof(btc->dm.slot.v1)); 1219 } 1220 1221 btc->policy_len = 0; 1222 btc->bt_req_len[RTW89_PHY_0] = 0; 1223 btc->bt_req_len[RTW89_PHY_1] = 0; 1224 btc->hubmsg_cnt = 0; 1225 1226 btc->dm.coex_info_map = BTC_COEX_INFO_ALL; 1227 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF; 1228 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF; 1229 btc->dm.bt_slot_flood = BTC_B1_MAX; 1230 btc->dm.sir_thres = BTC_DEFAULT_SIR_THRES; 1231 btc->dm.fddr_info.tp_setup_time = BTC_FDDR_TP_SETUP_TIME; 1232 btc->dm.fddr_info.tp_hold_time = BTC_FDDR_TP_HOLD_TIME; 1233 btc->dm.fddr_info.wl_rx_rate_thres = BTC_FDDR_RX_LOW_RATE_THRES; 1234 btc->dm.fddt_info.type = BTC_FDDT_TYPE_AUTO; 1235 1236 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND; 1237 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1238 } 1239 1240 if (type & BTC_RESET_MDINFO) { 1241 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); 1242 btc->mdinfo.ant.isolation = RTW89_BTC_DEFAULT_ANISO; 1243 } 1244 } 1245 1246 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target) 1247 { 1248 const struct rtw89_chip_info *chip = rtwdev->chip; 1249 u8 i; 1250 1251 for (i = 0; i < mreg_num; i++) 1252 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type && 1253 le32_to_cpu(chip->mon_reg[i].offset) == target) { 1254 return i; 1255 } 1256 return BTC_REG_NOTFOUND; 1257 } 1258 1259 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val) 1260 { 1261 struct rtw89_btc *btc = &rtwdev->btc; 1262 const struct rtw89_btc_ver *ver = btc->ver; 1263 struct rtw89_btc_module *md = &btc->mdinfo; 1264 union rtw89_btc_fbtc_mreg_val *pmreg; 1265 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1; 1266 u32 reg_val; 1267 u8 idx; 1268 1269 if (btc->btg_pos == RF_PATH_A) 1270 pre_agc_addr = R_BTC_BB_PRE_AGC_S0; 1271 1272 switch (type) { 1273 case BTC_CSTATUS_TXDIV_POS: 1274 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL) 1275 *val = BTC_ANT_DIV_MAIN; 1276 break; 1277 case BTC_CSTATUS_RXDIV_POS: 1278 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL) 1279 *val = BTC_ANT_DIV_MAIN; 1280 break; 1281 case BTC_CSTATUS_BB_GNT_MUX: 1282 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX); 1283 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1284 break; 1285 case BTC_CSTATUS_BB_GNT_MUX_MON: 1286 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1287 return; 1288 1289 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1290 if (ver->fcxmreg == 1) { 1291 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1292 REG_BB, R_BTC_BB_BTG_RX); 1293 if (idx == BTC_REG_NOTFOUND) { 1294 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1295 } else { 1296 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]); 1297 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1298 } 1299 } else if (ver->fcxmreg == 2) { 1300 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1301 REG_BB, R_BTC_BB_BTG_RX); 1302 if (idx == BTC_REG_NOTFOUND) { 1303 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1304 } else { 1305 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]); 1306 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1307 } 1308 } 1309 break; 1310 case BTC_CSTATUS_BB_PRE_AGC: 1311 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr); 1312 reg_val &= B_BTC_BB_PRE_AGC_MASK; 1313 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1314 break; 1315 case BTC_CSTATUS_BB_PRE_AGC_MON: 1316 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1317 return; 1318 1319 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1320 if (ver->fcxmreg == 1) { 1321 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1322 REG_BB, pre_agc_addr); 1323 if (idx == BTC_REG_NOTFOUND) { 1324 *val = BTC_PREAGC_NOTFOUND; 1325 } else { 1326 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) & 1327 B_BTC_BB_PRE_AGC_MASK; 1328 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1329 } 1330 } else if (ver->fcxmreg == 2) { 1331 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1332 REG_BB, pre_agc_addr); 1333 if (idx == BTC_REG_NOTFOUND) { 1334 *val = BTC_PREAGC_NOTFOUND; 1335 } else { 1336 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) & 1337 B_BTC_BB_PRE_AGC_MASK; 1338 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1339 } 1340 } 1341 break; 1342 default: 1343 break; 1344 } 1345 } 1346 1347 #define BTC_RPT_HDR_SIZE 3 1348 #define BTC_CHK_WLSLOT_DRIFT_MAX 15 1349 #define BTC_CHK_BTSLOT_DRIFT_MAX 15 1350 #define BTC_CHK_HANG_MAX 3 1351 #define BTC_NULLTX_CHK_PERIOD 100 1352 #define BTC_NULLTX_FAIL_TH 8 1353 1354 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt) 1355 { 1356 struct rtw89_btc *btc = &rtwdev->btc; 1357 union rtw89_btc_fbtc_cynullsta_info *ns = &btc->fwinfo.rpt_fbtc_nullsta.finfo; 1358 union rtw89_btc_fbtc_cysta_info *pcysta = &btc->fwinfo.rpt_fbtc_cysta.finfo; 1359 struct rtw89_btc_cx *cx = &btc->cx; 1360 struct rtw89_btc_bt_info *bt = &cx->bt0; 1361 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 1362 struct rtw89_btc_wl_info *wl = &cx->wl; 1363 struct rtw89_btc_dm *dm = &btc->dm; 1364 const struct rtw89_btc_ver *ver = btc->ver; 1365 u32 empty_streak = 0, empty_streak_max = 0; 1366 u32 slot_pair, c_begin, c_end, cycle, s_id; 1367 u32 tx_cnt, late, ok; 1368 1369 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1370 "[BTC], %s(): type:%d cnt:%d\n", 1371 __func__, type, cnt); 1372 1373 switch (type) { 1374 case BTC_DCNT_WL_FW_VER_MATCH: 1375 if ((wl->ver_info.fw_coex & 0xffff0000) != 1376 rtwdev->chip->wlcx_desired) { 1377 wl->fw_ver_mismatch = true; 1378 dm->error.map.wl_ver_mismatch = true; 1379 } else { 1380 wl->fw_ver_mismatch = false; 1381 dm->error.map.wl_ver_mismatch = false; 1382 } 1383 break; 1384 case BTC_DCNT_RPT_HANG: 1385 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map) 1386 dm->cnt_dm[BTC_DCNT_RPT_HANG]++; 1387 else 1388 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0; 1389 1390 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX) 1391 dm->error.map.wl_fw_hang = true; 1392 else 1393 dm->error.map.wl_fw_hang = false; 1394 1395 dm->cnt_dm[BTC_DCNT_RPT] = cnt; 1396 break; 1397 case BTC_DCNT_CYCLE_HANG: 1398 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt && 1399 (dm->tdma_now.type != CXTDMA_OFF || 1400 dm->tdma_now.ext_ctrl == CXECTL_EXT)) 1401 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++; 1402 else 1403 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0; 1404 1405 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX) 1406 dm->error.map.cycle_hang = true; 1407 else 1408 dm->error.map.cycle_hang = false; 1409 1410 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt; 1411 break; 1412 case BTC_DCNT_W1_HANG: 1413 if (dm->cnt_dm[BTC_DCNT_W1] == cnt && 1414 dm->tdma_now.type != CXTDMA_OFF) 1415 dm->cnt_dm[BTC_DCNT_W1_HANG]++; 1416 else 1417 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0; 1418 1419 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX) 1420 dm->error.map.w1_hang = true; 1421 else 1422 dm->error.map.w1_hang = false; 1423 1424 dm->cnt_dm[BTC_DCNT_W1] = cnt; 1425 break; 1426 case BTC_DCNT_B1_HANG: 1427 if (dm->cnt_dm[BTC_DCNT_B1] == cnt && 1428 dm->tdma_now.type != CXTDMA_OFF) 1429 dm->cnt_dm[BTC_DCNT_B1_HANG]++; 1430 else 1431 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0; 1432 1433 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX) 1434 dm->error.map.b1_hang = true; 1435 else 1436 dm->error.map.b1_hang = false; 1437 1438 dm->cnt_dm[BTC_DCNT_B1] = cnt; 1439 break; 1440 case BTC_DCNT_E2G_HANG: 1441 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt && 1442 dm->tdma_now.ext_ctrl == CXECTL_EXT) 1443 dm->cnt_dm[BTC_DCNT_E2G_HANG]++; 1444 else 1445 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0; 1446 1447 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX) 1448 dm->error.map.wl_e2g_hang = true; 1449 else 1450 dm->error.map.wl_e2g_hang = false; 1451 1452 dm->cnt_dm[BTC_DCNT_E2G] = cnt; 1453 break; 1454 case BTC_DCNT_TDMA_NONSYNC: 1455 if (cnt != 0) /* if tdma not sync between drv/fw */ 1456 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++; 1457 else 1458 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0; 1459 1460 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX) 1461 dm->error.map.tdma_no_sync = true; 1462 else 1463 dm->error.map.tdma_no_sync = false; 1464 break; 1465 case BTC_DCNT_SLOT_NONSYNC: 1466 if (cnt != 0) /* if slot not sync between drv/fw */ 1467 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++; 1468 else 1469 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0; 1470 1471 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX) 1472 dm->error.map.slot_no_sync = true; 1473 else 1474 dm->error.map.slot_no_sync = false; 1475 break; 1476 case BTC_DCNT_BTTX_HANG: 1477 cnt = bt->bcnt[BTC_BCNT_LOPRI_TX]; 1478 1479 if (cnt == 0 && bt->link_info.slave_role) 1480 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++; 1481 else 1482 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0; 1483 1484 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX) 1485 dm->error.map.bt_tx_hang = true; 1486 else 1487 dm->error.map.bt_tx_hang = false; 1488 break; 1489 case BTC_DCNT_BTCNT_HANG: 1490 cnt = bt->bcnt[BTC_BCNT_HIPRI_RX] + 1491 bt->bcnt[BTC_BCNT_HIPRI_TX] + 1492 bt->bcnt[BTC_BCNT_LOPRI_RX] + 1493 bt->bcnt[BTC_BCNT_LOPRI_TX]; 1494 1495 if (cnt == 0) 1496 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++; 1497 else 1498 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 1499 break; 1500 case BTC_DCNT_WL_SLOT_DRIFT: 1501 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX) 1502 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++; 1503 else 1504 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0; 1505 1506 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1507 dm->error.map.wl_slot_drift = true; 1508 else 1509 dm->error.map.wl_slot_drift = false; 1510 break; 1511 case BTC_DCNT_BT_SLOT_DRIFT: 1512 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX) 1513 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++; 1514 else 1515 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0; 1516 1517 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1518 dm->error.map.bt_slot_drift = true; 1519 else 1520 dm->error.map.bt_slot_drift = false; 1521 1522 break; 1523 case BTC_DCNT_BT_SLOT_FLOOD: 1524 if (!btc->fwinfo.rpt_fbtc_cysta.cinfo.valid || 1525 dm->cnt_dm[BTC_DCNT_CYCLE] == cnt) 1526 break; 1527 1528 if (cnt < BTC_CYCLE_SLOT_MAX || 1529 (dm->tdma_now.type != CXTDMA_AUTO && 1530 dm->tdma_now.type != CXTDMA_AUTO2 && 1531 dm->tdma_now.ext_ctrl != CXECTL_EXT)) { 1532 dm->error.map.bt_slot_flood = false; 1533 dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD] = 0; 1534 a2dp->no_empty_streak_2s = 0; 1535 a2dp->no_empty_streak_max = 0; 1536 break; 1537 } 1538 1539 /* 1 cycle = 1 wl-slot + 1 bt-slot */ 1540 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 1541 if (cnt - dm->cnt_dm[BTC_DCNT_CYCLE] > slot_pair) 1542 c_begin = cnt - slot_pair + 1; 1543 else 1544 c_begin = dm->cnt_dm[BTC_DCNT_CYCLE] + 1; 1545 1546 c_end = cnt; 1547 for (cycle = c_begin; cycle <= c_end; cycle++) { 1548 s_id = ((cycle - 1) % slot_pair) * 2; 1549 if (le16_to_cpu(pcysta->v7.slot_step_time[s_id]) >= 1550 dm->bt_slot_flood) 1551 dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD]++; 1552 /* calculate no-A2DP-empty streak count */ 1553 if (pcysta->v7.a2dp_trx[s_id].empty_cnt == 0 && 1554 pcysta->v7.a2dp_trx[s_id + 1].empty_cnt == 0) { 1555 empty_streak++; 1556 if (empty_streak > empty_streak_max) 1557 empty_streak_max = empty_streak; 1558 } else { 1559 empty_streak = 0; 1560 } 1561 } 1562 1563 a2dp->no_empty_streak_2s = empty_streak_max; 1564 if (a2dp->no_empty_streak_2s > a2dp->no_empty_streak_max) 1565 a2dp->no_empty_streak_max = a2dp->no_empty_streak_2s; 1566 1567 dm->error.map.bt_slot_flood = 1568 !!dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD]; 1569 break; 1570 case BTC_DCNT_WL_STA_NTFY: 1571 cnt = dm->cnt_notify[BTC_NCNT_WL_STA] - 1572 dm->cnt_notify[BTC_NCNT_WL_STA_LAST]; 1573 1574 dm->cnt_notify[BTC_NCNT_WL_STA_LAST] = 1575 dm->cnt_notify[BTC_NCNT_WL_STA]; 1576 1577 if (cnt == 0 && 1578 (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK || 1579 dm->fdd_bind.wl_link_mode != BTC_WLINK_NOLINK)) 1580 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY]++; 1581 else 1582 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] = 0; 1583 1584 if (dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] >= BTC_CHK_HANG_MAX) 1585 dm->error.map.wl_no_sta_ntfy = true; 1586 else 1587 dm->error.map.wl_no_sta_ntfy = false; 1588 break; 1589 case BTC_DCNT_W2B_SCBD_NOSYNC: 1590 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) 1591 return; /* return if no-support W2B scbd readback */ 1592 1593 if (wl->scbd_rb[BTC_BT_1ST] != wl->scbd[BTC_BT_1ST] || 1594 wl->scbd_rb[BTC_BT_2ND] != wl->scbd[BTC_BT_2ND]) 1595 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC]++; 1596 else 1597 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] = 0; 1598 1599 if (dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] >= BTC_CHK_HANG_MAX) 1600 dm->error.map.w2b_scbd_no_sync = true; 1601 else 1602 dm->error.map.w2b_scbd_no_sync = false; 1603 break; 1604 case BTC_DCNT_NULL_TX_FAIL: 1605 if (dm->fddt_train) 1606 break; 1607 1608 if (ver->fcxnullsta == 7) { 1609 ok = le32_to_cpu(ns->v7.result[1][1]); 1610 late = le32_to_cpu(ns->v7.result[1][2]); 1611 tx_cnt = le32_to_cpu(ns->v7.result[1][4]); 1612 } else if (ver->fcxnullsta == 2) { 1613 ok = le32_to_cpu(ns->v2.result[1][1]); 1614 late = le32_to_cpu(ns->v2.result[1][2]); 1615 tx_cnt = le32_to_cpu(ns->v2.result[1][4]); 1616 } else if (ver->fcxnullsta == 1) { 1617 ok = le32_to_cpu(ns->v1.result[1][1]); 1618 late = le32_to_cpu(ns->v1.result[1][2]); 1619 tx_cnt = 0; 1620 } else { 1621 break; 1622 } 1623 1624 if (tx_cnt < BTC_NULLTX_CHK_PERIOD) 1625 break; 1626 1627 if (late * BTC_NULLTX_FAIL_TH > ok) 1628 dm->cnt_dm[BTC_DCNT_NULL_TX_FAIL]++; 1629 else 1630 dm->cnt_dm[BTC_DCNT_NULL_TX_FAIL] = 0; 1631 1632 dm->error.map.null1_tx_late = 1633 dm->cnt_dm[BTC_DCNT_NULL_TX_FAIL] >= BTC_CHK_HANG_MAX; 1634 break; 1635 } 1636 } 1637 1638 static void _update_bt_afh_conflict(struct rtw89_dev *rtwdev, 1639 struct rtw89_btc_bt_info *bt, 1640 u8 map_type) 1641 { 1642 struct rtw89_btc *btc = &rtwdev->btc; 1643 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1644 struct rtw89_btc_dm *dm = &btc->dm; 1645 struct rtw89_btc_bt_link_info *b = &bt->link_info; 1646 struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc; 1647 u8 hw_band = wl->role_info.pta_req_band; 1648 u32 cnt, cnt_ch, cnt_le, cnt_ch_le; 1649 u8 i, omap, xmap, afh_en; 1650 1651 if (map_type & RPT_BT_AFH_SEQ_LEGACY) { 1652 bt->bcnt[BTC_BCNT_AFH_UPDATE]++; 1653 bt->bcnt[BTC_BCNT_AFH_CONFLICT] = 0; 1654 dm->error.map.bt_afh_conflict = 0; 1655 } 1656 1657 afh_en = wl->afh_info[hw_band][RTW89_BAND_2G].en; 1658 1659 for (i = 0; i < 12; i++) { 1660 if (!(map_type & RPT_BT_AFH_SEQ_LEGACY) || 1661 !b->status.map.connect) 1662 break; 1663 1664 omap = b->afh_map[i]; 1665 xmap = omap & wl->ch_map[i]; 1666 cnt_ch = hweight8(omap); 1667 cnt = afh_en ? hweight8(xmap) : 0; 1668 1669 if (i == 11) { 1670 bt->bcnt[BTC_BCNT_AFH_CHN] = cnt_ch; 1671 bt->bcnt[BTC_BCNT_AFH_CONFLICT] = cnt; 1672 dm->error.map.bt_afh_conflict = !!cnt; 1673 } 1674 } 1675 1676 if (map_type & RPT_BT_AFH_SEQ_LE) { 1677 bt->bcnt[BTC_BCNT_AFH_LE_UPDATE]++; 1678 bt->bcnt[BTC_BCNT_AFH_LE_CONFLICT] = 0; 1679 dm->error.map.bt_leafh_conflict = 0; 1680 } 1681 1682 for (i = 0; i < 5; i++) { 1683 if (!(map_type & RPT_BT_AFH_SEQ_LE) || 1684 (!b->status.map.ble_connect && 1685 !leaudio->bis_exist && !leaudio->cis_exist)) 1686 break; 1687 1688 omap = b->afh_map_le[i]; 1689 xmap = omap & wl->ch_map_le[i]; 1690 cnt_ch_le = hweight8(omap); 1691 cnt_le = afh_en ? hweight8(xmap) : 0; 1692 1693 if (i == 4) { 1694 bt->bcnt[BTC_BCNT_AFH_LE_CHN] = cnt_ch_le; 1695 bt->bcnt[BTC_BCNT_AFH_LE_CONFLICT] = cnt_le; 1696 dm->error.map.bt_leafh_conflict = !!cnt_le; 1697 } 1698 } 1699 } 1700 1701 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) 1702 { 1703 struct rtw89_btc *btc = &rtwdev->btc; 1704 const struct rtw89_btc_ver *ver = btc->ver; 1705 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 1706 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 1707 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc; 1708 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo; 1709 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL; 1710 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL; 1711 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL; 1712 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL; 1713 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1; 1714 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2; 1715 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7; 1716 bool scan_update = true; 1717 int i; 1718 1719 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1720 "[BTC], %s(): rpt_type:%d\n", 1721 __func__, rpt_type); 1722 1723 switch (rpt_type) { 1724 case BTC_RPT_TYPE_BT_VER: 1725 if (ver->fcxbtver == 8) { 1726 pver->v8 = *(struct rtw89_btc_fbtc_btver_v8 *)pfinfo; 1727 bt = pver->v8.bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1728 bt->ver_info.fw = le32_to_cpu(pver->v8.fw_ver); 1729 bt->ver_info.fw_coex = le32_get_bits(pver->v8.coex_ver, 1730 GENMASK(7, 0)); 1731 bt->feature = le32_to_cpu(pver->v8.feature); 1732 } else if (ver->fcxbtver == 7) { 1733 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo; 1734 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver); 1735 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver, 1736 GENMASK(7, 0)); 1737 bt->feature = le32_to_cpu(pver->v7.feature); 1738 } else { 1739 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo; 1740 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver); 1741 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver, 1742 GENMASK(7, 0)); 1743 bt->feature = le32_to_cpu(pver->v1.feature); 1744 } 1745 break; 1746 case BTC_RPT_TYPE_BT_SCAN: 1747 if (ver->fcxbtscan == 1) { 1748 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo; 1749 for (i = 0; i < BTC_SCAN_MAX1; i++) { 1750 bt->scan_info_v1[i] = pscan_v1->scan[i]; 1751 if (bt->scan_info_v1[i].win == 0 && 1752 bt->scan_info_v1[i].intvl == 0) 1753 scan_update = false; 1754 } 1755 } else if (ver->fcxbtscan == 2) { 1756 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo; 1757 for (i = 0; i < CXSCAN_MAX; i++) { 1758 bt->scan_info_v2[i] = pscan_v2->para[i]; 1759 if ((pscan_v2->type & BIT(i)) && 1760 pscan_v2->para[i].win == 0 && 1761 pscan_v2->para[i].intvl == 0) 1762 scan_update = false; 1763 } 1764 } else if (ver->fcxbtscan == 7) { 1765 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo; 1766 for (i = 0; i < CXSCAN_MAX; i++) { 1767 bt->scan_info_v2[i] = pscan_v7->para[i]; 1768 if ((pscan_v7->type & BIT(i)) && 1769 pscan_v7->para[i].win == 0 && 1770 pscan_v7->para[i].intvl == 0) 1771 scan_update = false; 1772 } 1773 } else if (ver->fcxbtscan == 8) { 1774 struct rtw89_btc_fbtc_btscan_v8 *pscan_v8 = 1775 (struct rtw89_btc_fbtc_btscan_v8 *)pfinfo; 1776 1777 bt = pscan_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1778 for (i = 0; i < CXSCAN_MAX; i++) { 1779 bt->scan_info_v2[i] = pscan_v8->para[i]; 1780 if ((pscan_v8->type & BIT(i)) && 1781 pscan_v8->para[i].win == 0 && 1782 pscan_v8->para[i].intvl == 0) 1783 scan_update = false; 1784 } 1785 } 1786 if (scan_update) 1787 bt->scan_info_update = 1; 1788 break; 1789 case BTC_RPT_TYPE_BT_AFH: 1790 if (ver->fcxbtafh == 2) { 1791 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo; 1792 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1793 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4); 1794 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4); 1795 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2); 1796 } 1797 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) { 1798 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4); 1799 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1); 1800 } 1801 _update_bt_afh_conflict(rtwdev, bt, pafh_v2->map_type); 1802 } else if (ver->fcxbtafh == 7) { 1803 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo; 1804 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1805 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4); 1806 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4); 1807 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2); 1808 } 1809 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) { 1810 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4); 1811 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1); 1812 } 1813 _update_bt_afh_conflict(rtwdev, bt, pafh_v7->map_type); 1814 } else if (ver->fcxbtafh == 8) { 1815 struct rtw89_btc_fbtc_btafh_v8 *pafh_v8 = 1816 (struct rtw89_btc_fbtc_btafh_v8 *)pfinfo; 1817 struct rtw89_btc_bt_info *tbt = 1818 pafh_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0; 1819 struct rtw89_btc_bt_link_info *tbt_linfo = &tbt->link_info; 1820 1821 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1822 memcpy(&tbt_linfo->afh_map[0], pafh_v8->afh_l, 4); 1823 memcpy(&tbt_linfo->afh_map[4], pafh_v8->afh_m, 4); 1824 memcpy(&tbt_linfo->afh_map[8], pafh_v8->afh_h, 2); 1825 } 1826 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LE) { 1827 memcpy(&tbt_linfo->afh_map_le[0], pafh_v8->afh_le_a, 4); 1828 memcpy(&tbt_linfo->afh_map_le[4], pafh_v8->afh_le_b, 1); 1829 } 1830 _update_bt_afh_conflict(rtwdev, tbt, pafh_v8->map_type); 1831 } else if (ver->fcxbtafh == 1) { 1832 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; 1833 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); 1834 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4); 1835 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2); 1836 } 1837 break; 1838 case BTC_RPT_TYPE_BT_DEVICE: 1839 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo; 1840 if (ver->fcxbtdevinfo == 8) { 1841 bt = pdev->rsvd ? &btc->cx.bt1 : &btc->cx.bt0; 1842 a2dp = &bt->link_info.a2dp_desc; 1843 } 1844 a2dp->device_name = le32_to_cpu(pdev->dev_name); 1845 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id); 1846 a2dp->flush_time = le32_to_cpu(pdev->flush_time); 1847 break; 1848 default: 1849 break; 1850 } 1851 } 1852 1853 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index) 1854 { 1855 struct rtw89_btc *btc = &rtwdev->btc; 1856 const struct rtw89_btc_ver *ver = btc->ver; 1857 1858 if (ver->fwevntrptl == 1) 1859 return; 1860 1861 if (*index <= __BTC_RPT_TYPE_V0_SAME) 1862 return; 1863 else if (*index <= __BTC_RPT_TYPE_V0_MAX) 1864 (*index)++; 1865 else 1866 *index = BTC_RPT_TYPE_MAX; 1867 } 1868 1869 #define BTC_LEAK_AP_TH 10 1870 #define BTC_CYSTA_CHK_PERIOD 100 1871 1872 struct rtw89_btc_prpt { 1873 u8 type; 1874 __le16 len; 1875 u8 content[]; 1876 } __packed; 1877 1878 static u32 _chk_btc_report(struct rtw89_dev *rtwdev, 1879 struct rtw89_btc_btf_fwinfo *pfwinfo, 1880 u8 *prptbuf, u32 index) 1881 { 1882 struct rtw89_btc *btc = &rtwdev->btc; 1883 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 1884 const struct rtw89_btc_ver *ver = btc->ver; 1885 struct rtw89_btc_dm *dm = &btc->dm; 1886 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 1887 struct rtw89_btc_cx *cx = &btc->cx; 1888 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1889 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 1890 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL; 1891 union rtw89_btc_fbtc_cysta_info *pcysta = NULL; 1892 struct rtw89_btc_prpt *btc_prpt = NULL; 1893 void *rpt_content = NULL, *pfinfo = NULL; 1894 u8 rpt_type = 0; 1895 u16 wl_slot_set = 0, wl_slot_real = 0, val16; 1896 u32 trace_step = 0, rpt_len = 0, diff_t = 0; 1897 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr; 1898 u8 i, j, val = 0, val1, val2; 1899 u32 *bt_cnt, start_idx; 1900 const u8 *rpt_fver; 1901 1902 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1903 "[BTC], %s(): index:%d\n", 1904 __func__, index); 1905 1906 if (!prptbuf) { 1907 pfwinfo->err[BTFRE_INVALID_INPUT]++; 1908 return 0; 1909 } 1910 1911 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index]; 1912 rpt_type = btc_prpt->type; 1913 rpt_len = le16_to_cpu(btc_prpt->len); 1914 rpt_content = btc_prpt->content; 1915 1916 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1917 "[BTC], %s(): rpt_type:%d\n", 1918 __func__, rpt_type); 1919 1920 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type); 1921 1922 switch (rpt_type) { 1923 case BTC_RPT_TYPE_CTRL: 1924 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 1925 prpt = &pfwinfo->rpt_ctrl.finfo; 1926 if (ver->fcxbtcrpt == 1) { 1927 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; 1928 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); 1929 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver; 1930 } else if (ver->fcxbtcrpt == 4) { 1931 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; 1932 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); 1933 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver; 1934 } else if (ver->fcxbtcrpt == 5) { 1935 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; 1936 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); 1937 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver; 1938 } else if (ver->fcxbtcrpt == 105) { 1939 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; 1940 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); 1941 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver; 1942 pcinfo->req_fver = 5; 1943 break; 1944 } else if (ver->fcxbtcrpt == 205) { 1945 pfinfo = &pfwinfo->rpt_ctrl.finfo.v205; 1946 pcinfo->req_len = 1947 sizeof(pfwinfo->rpt_ctrl.finfo.v205); 1948 fwsubver->fcxbtcrpt = 1949 pfwinfo->rpt_ctrl.finfo.v205.fver; 1950 pcinfo->req_fver = 5; 1951 break; 1952 } else if (ver->fcxbtcrpt == 8) { 1953 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8; 1954 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8); 1955 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver; 1956 } else if (ver->fcxbtcrpt == 7) { 1957 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7; 1958 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7); 1959 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver; 1960 } else if (ver->fcxbtcrpt == 9) { 1961 pfinfo = &pfwinfo->rpt_ctrl.finfo.v9; 1962 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v9); 1963 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v9.fver; 1964 } else if (ver->fcxbtcrpt == 11) { 1965 pfinfo = &pfwinfo->rpt_ctrl.finfo.v11; 1966 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v11); 1967 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v11.fver; 1968 } else { 1969 goto err; 1970 } 1971 pcinfo->req_fver = ver->fcxbtcrpt; 1972 break; 1973 case BTC_RPT_TYPE_TDMA: 1974 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 1975 if (ver->fcxtdma == 1) { 1976 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 1977 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); 1978 fwsubver->fcxtdma = 0; 1979 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || 1980 ver->fcxtdma == 7 || ver->fcxtdma == 8) { 1981 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; 1982 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); 1983 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver; 1984 } else { 1985 goto err; 1986 } 1987 pcinfo->req_fver = ver->fcxtdma; 1988 break; 1989 case BTC_RPT_TYPE_SLOT: 1990 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 1991 if (ver->fcxslots == 1) { 1992 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1; 1993 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1); 1994 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver; 1995 } else if (ver->fcxslots == 2) { 1996 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v2; 1997 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v2); 1998 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v2.fver; 1999 } else if (ver->fcxslots == 7) { 2000 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7; 2001 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7); 2002 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver; 2003 } else { 2004 goto err; 2005 } 2006 pcinfo->req_fver = ver->fcxslots; 2007 break; 2008 case BTC_RPT_TYPE_CYSTA: 2009 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 2010 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 2011 if (ver->fcxcysta == 2) { 2012 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 2013 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 2014 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); 2015 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver; 2016 } else if (ver->fcxcysta == 3) { 2017 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 2018 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 2019 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); 2020 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver; 2021 } else if (ver->fcxcysta == 4) { 2022 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 2023 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 2024 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); 2025 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver; 2026 } else if (ver->fcxcysta == 5) { 2027 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 2028 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 2029 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); 2030 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver; 2031 } else if (ver->fcxcysta == 105) { 2032 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v105; 2033 pcysta->v105 = pfwinfo->rpt_fbtc_cysta.finfo.v105; 2034 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v105); 2035 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v105.fver; 2036 } else if (ver->fcxcysta == 7) { 2037 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 2038 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 2039 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7); 2040 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver; 2041 } else if (ver->fcxcysta == 8) { 2042 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v8; 2043 pcysta->v8 = pfwinfo->rpt_fbtc_cysta.finfo.v8; 2044 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v8); 2045 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v8.fver; 2046 } else { 2047 goto err; 2048 } 2049 pcinfo->req_fver = ver->fcxcysta; 2050 break; 2051 case BTC_RPT_TYPE_STEP: 2052 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 2053 if (ver->fcxctrl != 7) 2054 trace_step = btc->ctrl.trace_step; 2055 2056 if (ver->fcxstep == 2) { 2057 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2; 2058 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * 2059 trace_step + 2060 offsetof(struct rtw89_btc_fbtc_steps_v2, step); 2061 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver; 2062 } else if (ver->fcxstep == 3) { 2063 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; 2064 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * 2065 trace_step + 2066 offsetof(struct rtw89_btc_fbtc_steps_v3, step); 2067 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver; 2068 } else { 2069 goto err; 2070 } 2071 pcinfo->req_fver = ver->fcxstep; 2072 break; 2073 case BTC_RPT_TYPE_NULLSTA: 2074 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 2075 if (ver->fcxnullsta == 1) { 2076 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; 2077 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); 2078 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver; 2079 } else if (ver->fcxnullsta == 2) { 2080 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; 2081 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); 2082 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver; 2083 } else if (ver->fcxnullsta == 7) { 2084 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7; 2085 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7); 2086 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver; 2087 } else { 2088 goto err; 2089 } 2090 pcinfo->req_fver = ver->fcxnullsta; 2091 break; 2092 case BTC_RPT_TYPE_MREG: 2093 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 2094 if (ver->fcxmreg == 1) { 2095 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 2096 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); 2097 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver; 2098 } else if (ver->fcxmreg == 2) { 2099 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 2100 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); 2101 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver; 2102 } else if (ver->fcxmreg == 7) { 2103 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 2104 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7); 2105 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver; 2106 } else { 2107 goto err; 2108 } 2109 pcinfo->req_fver = ver->fcxmreg; 2110 break; 2111 case BTC_RPT_TYPE_GPIO_DBG: 2112 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 2113 if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) { 2114 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7; 2115 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7); 2116 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver; 2117 } else { 2118 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1; 2119 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1); 2120 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver; 2121 } 2122 pcinfo->req_fver = ver->fcxgpiodbg; 2123 break; 2124 case BTC_RPT_TYPE_BT_VER: 2125 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo; 2126 if (ver->fcxbtver == 1) { 2127 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1; 2128 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1); 2129 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver; 2130 } else if (ver->fcxbtver == 7) { 2131 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7; 2132 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7); 2133 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver; 2134 } else if (ver->fcxbtver == 8) { 2135 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v8; 2136 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v8); 2137 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v8.fver; 2138 } else { 2139 goto err; 2140 } 2141 pcinfo->req_fver = ver->fcxbtver; 2142 break; 2143 case BTC_RPT_TYPE_BT_SCAN: 2144 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo; 2145 if (ver->fcxbtscan == 1) { 2146 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; 2147 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); 2148 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver; 2149 } else if (ver->fcxbtscan == 2) { 2150 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; 2151 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); 2152 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver; 2153 } else if (ver->fcxbtscan == 7) { 2154 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7; 2155 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7); 2156 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver; 2157 } else if (ver->fcxbtscan == 8) { 2158 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v8; 2159 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v8); 2160 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v8.fver; 2161 } else { 2162 goto err; 2163 } 2164 pcinfo->req_fver = ver->fcxbtscan; 2165 break; 2166 case BTC_RPT_TYPE_BT_AFH: 2167 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo; 2168 if (ver->fcxbtafh == 1) { 2169 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; 2170 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); 2171 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver; 2172 } else if (ver->fcxbtafh == 2) { 2173 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; 2174 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); 2175 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver; 2176 } else if (ver->fcxbtafh == 7) { 2177 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7; 2178 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7); 2179 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver; 2180 } else if (ver->fcxbtafh == 8) { 2181 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v8; 2182 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v8); 2183 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v8.fver; 2184 } else { 2185 goto err; 2186 } 2187 pcinfo->req_fver = ver->fcxbtafh; 2188 break; 2189 case BTC_RPT_TYPE_BT_DEVICE: 2190 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; 2191 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; 2192 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); 2193 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver; 2194 pcinfo->req_fver = ver->fcxbtdevinfo; 2195 break; 2196 default: 2197 pfwinfo->err[BTFRE_UNDEF_TYPE]++; 2198 return 0; 2199 } 2200 2201 pcinfo->rx_len = rpt_len; 2202 pcinfo->rx_cnt++; 2203 2204 if (rpt_len != pcinfo->req_len) { 2205 if (rpt_type < BTC_RPT_TYPE_MAX) 2206 pfwinfo->len_mismch |= (0x1 << rpt_type); 2207 else 2208 pfwinfo->len_mismch |= BIT(31); 2209 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2210 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n", 2211 __func__, rpt_type, rpt_len, pcinfo->req_len); 2212 2213 pcinfo->valid = 0; 2214 return 0; 2215 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) { 2216 pfwinfo->err[BTFRE_EXCEPTION]++; 2217 pcinfo->valid = 0; 2218 return 0; 2219 } 2220 2221 memcpy(pfinfo, rpt_content, pcinfo->req_len); 2222 pcinfo->valid = 1; 2223 2224 /* 2225 * fver is the leading field of every report struct. A mismatch 2226 * vs the driver-selected version means ver_defs needs a fix, so 2227 * flag it for debug but keep processing the length-valid report. 2228 */ 2229 rpt_fver = pfinfo; 2230 pcinfo->rsp_fver = rpt_fver[0]; 2231 if (pcinfo->rsp_fver != pcinfo->req_fver) { 2232 pfwinfo->fver_mismch |= BIT(rpt_type); 2233 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2234 "[BTC], %s(): %d rsp_fver:%d!=req_fver:%d\n", 2235 __func__, rpt_type, pcinfo->rsp_fver, 2236 pcinfo->req_fver); 2237 } 2238 2239 switch (rpt_type) { 2240 case BTC_RPT_TYPE_CTRL: 2241 if (ver->fcxbtcrpt == 1) { 2242 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1; 2243 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable; 2244 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver; 2245 wl->ver_info.fw = prpt->v1.wl_fw_ver; 2246 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload; 2247 2248 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2249 pfwinfo->event[BTF_EVNT_RPT]); 2250 2251 /* To avoid I/O if WL LPS or power-off */ 2252 if (wl->status.map.lps != BTC_LPS_RF_OFF && 2253 !wl->status.map.rf_off) { 2254 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev); 2255 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2256 2257 bt->bcnt[BTC_BCNT_POLLUTED] = 2258 rtw89_mac_get_plt_cnt(rtwdev, 2259 RTW89_MAC_0); 2260 } 2261 } else if (ver->fcxbtcrpt == 4) { 2262 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4; 2263 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en); 2264 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver); 2265 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver); 2266 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload); 2267 2268 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2269 memcpy(&dm->gnt_val[i], &prpt->v4.gnt_val[i], 2270 sizeof(prpt->v4.gnt_val[i])); 2271 2272 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2273 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]); 2274 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2275 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]); 2276 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2277 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]); 2278 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2279 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]); 2280 bt->bcnt[BTC_BCNT_POLLUTED] = 2281 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]); 2282 2283 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2284 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2285 pfwinfo->event[BTF_EVNT_RPT]); 2286 2287 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 2288 bt->rfk_info.map.timeout = 1; 2289 else 2290 bt->rfk_info.map.timeout = 0; 2291 2292 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2293 } else if (ver->fcxbtcrpt == 5) { 2294 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5; 2295 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en); 2296 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver); 2297 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver); 2298 dm->wl_fw_cx_offload = 0; 2299 2300 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2301 memcpy(&dm->gnt_val[i], &prpt->v5.gnt_val[i], 2302 sizeof(prpt->v5.gnt_val[i])); 2303 2304 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2305 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]); 2306 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2307 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]); 2308 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2309 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]); 2310 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2311 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]); 2312 bt->bcnt[BTC_BCNT_POLLUTED] = 2313 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]); 2314 2315 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2316 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2317 pfwinfo->event[BTF_EVNT_RPT]); 2318 2319 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2320 } else if (ver->fcxbtcrpt == 105) { 2321 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105; 2322 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en); 2323 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver); 2324 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver); 2325 dm->wl_fw_cx_offload = 0; 2326 2327 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2328 memcpy(&dm->gnt_val[i], &prpt->v105.gnt_val[i], 2329 sizeof(prpt->v105.gnt_val[i])); 2330 2331 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2332 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]); 2333 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2334 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]); 2335 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2336 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]); 2337 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2338 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]); 2339 bt->bcnt[BTC_BCNT_POLLUTED] = 2340 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2341 2342 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2343 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2344 pfwinfo->event[BTF_EVNT_RPT]); 2345 2346 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2347 } else if (ver->fcxbtcrpt == 205) { 2348 prpt->v205 = pfwinfo->rpt_ctrl.finfo.v205; 2349 pfwinfo->rpt_en_map = 2350 le32_to_cpu(prpt->v205.rpt_info.en); 2351 wl->ver_info.fw_coex = 2352 le32_to_cpu(prpt->v205.wl_fw_info.cx_ver); 2353 wl->ver_info.fw = 2354 le32_to_cpu(prpt->v205.wl_fw_info.fw_ver); 2355 dm->wl_fw_cx_offload = 2356 !!le32_to_cpu(prpt->v205.wl_fw_info.cx_offload); 2357 2358 memcpy(wl->ver_info.build_time, 2359 prpt->v205.build_time, 2360 sizeof(wl->ver_info.build_time)); 2361 memcpy(wl->ver_info.build_date, 2362 prpt->v205.build_date, 2363 sizeof(wl->ver_info.build_date)); 2364 2365 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2366 memcpy(&dm->gnt_val[i], 2367 &prpt->v205.gnt_val[i], 2368 sizeof(prpt->v205.gnt_val[i])); 2369 2370 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2371 le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_HI_TX]); 2372 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2373 le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_HI_RX]); 2374 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2375 le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_LO_TX]); 2376 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2377 le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_LO_RX]); 2378 bt->bcnt[BTC_BCNT_POLLUTED] = 2379 le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_POLLUTED]); 2380 2381 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2382 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 2383 pfwinfo->event[BTF_EVNT_RPT]); 2384 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2385 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2386 2387 if (le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 2388 bt->rfk_info.map.timeout = 1; 2389 else 2390 bt->rfk_info.map.timeout = 0; 2391 2392 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 2393 } else if (ver->fcxbtcrpt == 7) { 2394 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7; 2395 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en); 2396 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver); 2397 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver); 2398 2399 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2400 memcpy(&dm->gnt_val[i], &prpt->v7.gnt_val[i], 2401 sizeof(prpt->v7.gnt_val[i])); 2402 2403 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2404 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]); 2405 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2406 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]); 2407 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2408 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]); 2409 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2410 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]); 2411 2412 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2413 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2414 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2415 2416 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2417 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2418 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2419 2420 val1 = pfwinfo->event[BTF_EVNT_RPT]; 2421 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2422 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2423 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2424 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2425 } else if (ver->fcxbtcrpt == 8) { 2426 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8; 2427 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en); 2428 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver); 2429 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver); 2430 2431 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2432 memcpy(&dm->gnt_val[i], &prpt->v8.gnt_val[i], 2433 sizeof(prpt->v8.gnt_val[i])); 2434 2435 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2436 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]); 2437 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2438 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]); 2439 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2440 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]); 2441 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2442 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]); 2443 2444 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2445 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2446 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2447 2448 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2449 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2450 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2451 2452 val1 = pfwinfo->event[BTF_EVNT_RPT]; 2453 if (((prpt->v8.rpt_len_max_h << 8) + 2454 prpt->v8.rpt_len_max_l) != ver->info_buf) 2455 dm->error.map.h2c_c2h_buffer_mismatch = true; 2456 else 2457 dm->error.map.h2c_c2h_buffer_mismatch = false; 2458 2459 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2460 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2461 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2462 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2463 } else if (ver->fcxbtcrpt == 9) { 2464 prpt->v9 = pfwinfo->rpt_ctrl.finfo.v9; 2465 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v9.rpt_info.en); 2466 wl->ver_info.fw_coex = le32_to_cpu(prpt->v9.rpt_info.cx_ver); 2467 wl->ver_info.fw = le32_to_cpu(prpt->v9.rpt_info.fw_ver); 2468 2469 memcpy(wl->ver_info.build_time, 2470 prpt->v9.build_time, 2471 sizeof(wl->ver_info.build_time)); 2472 memcpy(wl->ver_info.build_date, 2473 prpt->v9.build_date, 2474 sizeof(wl->ver_info.build_date)); 2475 2476 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2477 memcpy(&dm->gnt_val[i], &prpt->v9.gnt_val[i], 2478 sizeof(prpt->v9.gnt_val[i])); 2479 2480 bt->bcnt[BTC_BCNT_HIPRI_TX] = 2481 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_TX_V105]); 2482 bt->bcnt[BTC_BCNT_HIPRI_RX] = 2483 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_RX_V105]); 2484 bt->bcnt[BTC_BCNT_LOPRI_TX] = 2485 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_TX_V105]); 2486 bt->bcnt[BTC_BCNT_LOPRI_RX] = 2487 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_RX_V105]); 2488 2489 val1 = le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2490 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW]) 2491 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */ 2492 2493 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1; 2494 bt->bcnt[BTC_BCNT_POLUT_NOW] = 2495 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]); 2496 2497 dm->pta_owner = prpt->v9.pta_owner; 2498 2499 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2500 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 2501 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2502 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2503 } else if (ver->fcxbtcrpt == 11) { 2504 prpt->v11 = pfwinfo->rpt_ctrl.finfo.v11; 2505 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v11.rpt_info.en); 2506 wl->ver_info.fw_coex = le32_to_cpu(prpt->v11.rpt_info.cx_ver); 2507 wl->ver_info.fw = le32_to_cpu(prpt->v11.rpt_info.fw_ver); 2508 2509 memcpy(wl->ver_info.build_time, 2510 prpt->v11.build_time, 2511 sizeof(wl->ver_info.build_time)); 2512 memcpy(wl->ver_info.build_date, 2513 prpt->v11.build_date, 2514 sizeof(wl->ver_info.build_date)); 2515 2516 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 2517 memcpy(&dm->gnt_val[i], &prpt->v11.gnt_val[i][0], 2518 sizeof(dm->gnt_val[i])); 2519 2520 for (i = BTC_BT_1ST; i <= BTC_BT_EXT; i++) { 2521 if (i == BTC_BT_EXT) { 2522 if (cx->bt_ext.func_type == BTC_BTF_NONE) 2523 continue; 2524 bt_cnt = cx->bt_ext.bcnt; 2525 } else if (i == BTC_BT_2ND) { 2526 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 2527 continue; 2528 bt_cnt = cx->bt1.bcnt; 2529 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]); 2530 cx->bt1.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]); 2531 } else { 2532 bt_cnt = cx->bt0.bcnt; 2533 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]); 2534 cx->bt0.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]); 2535 } 2536 2537 start_idx = BTC_BCNT_HIPRI_TX; 2538 for (j = BTC_BCNT_HI_TX_V105; j <= BTC_BCNT_LO_RX_V105 ; j++) 2539 bt_cnt[start_idx++] = le16_to_cpu(prpt->v11.bt_cnt[i][j]); 2540 2541 /* check if polut counter increase */ 2542 val1 = le16_to_cpu(prpt->v11.bt_cnt[i][BTC_BCNT_POLLUTED_V105]); 2543 if (val1 > bt_cnt[BTC_BCNT_POLUT_NOW]) /* cnt increase*/ 2544 val2 = val1 - bt_cnt[BTC_BCNT_POLUT_NOW]; 2545 else 2546 val2 = val1; /* overflow */ 2547 2548 bt_cnt[BTC_BCNT_POLUT_DIFF] = val2; 2549 bt_cnt[BTC_BCNT_POLUT_NOW] = val1; 2550 2551 if (i <= BTC_BT_2ND) 2552 bt_cnt[BTC_BCNT_SCBDREAD]++; 2553 } 2554 dm->scbd_w2b_update = true; 2555 dm->scbd_b2w_update = true; 2556 2557 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 2558 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 2559 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 2560 _chk_btc_err(rtwdev, BTC_DCNT_WL_STA_NTFY, 0); 2561 _chk_btc_err(rtwdev, BTC_DCNT_W2B_SCBD_NOSYNC, 0); 2562 } else { 2563 goto err; 2564 } 2565 break; 2566 case BTC_RPT_TYPE_TDMA: 2567 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2568 "[BTC], %s(): check %d %zu\n", __func__, 2569 BTC_DCNT_TDMA_NONSYNC, 2570 sizeof(dm->tdma_now)); 2571 if (ver->fcxtdma == 1) 2572 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 2573 memcmp(&dm->tdma_now, 2574 &pfwinfo->rpt_fbtc_tdma.finfo.v1, 2575 sizeof(dm->tdma_now))); 2576 else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 || 2577 ver->fcxtdma == 7 || ver->fcxtdma == 8) 2578 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 2579 memcmp(&dm->tdma_now, 2580 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, 2581 sizeof(dm->tdma_now))); 2582 else 2583 goto err; 2584 break; 2585 case BTC_RPT_TYPE_SLOT: 2586 if (ver->fcxslots == 7) { 2587 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2588 "[BTC], %s(): check %d %zu\n", 2589 __func__, BTC_DCNT_SLOT_NONSYNC, 2590 sizeof(dm->slot_now.v7)); 2591 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2592 memcmp(dm->slot_now.v7, 2593 pfwinfo->rpt_fbtc_slots.finfo.v7.slot, 2594 sizeof(dm->slot_now.v7))); 2595 } else if (ver->fcxslots == 2) { 2596 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2597 "[BTC], %s(): check %d %zu\n", 2598 __func__, BTC_DCNT_SLOT_NONSYNC, 2599 sizeof(dm->slot_now.v7)); 2600 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2601 memcmp(dm->slot_now.v7, 2602 pfwinfo->rpt_fbtc_slots.finfo.v2.slot, 2603 sizeof(dm->slot_now.v7))); 2604 } else if (ver->fcxslots == 1) { 2605 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2606 "[BTC], %s(): check %d %zu\n", 2607 __func__, BTC_DCNT_SLOT_NONSYNC, 2608 sizeof(dm->slot_now.v1)); 2609 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 2610 memcmp(dm->slot_now.v1, 2611 pfwinfo->rpt_fbtc_slots.finfo.v1.slot, 2612 sizeof(dm->slot_now.v1))); 2613 } 2614 break; 2615 case BTC_RPT_TYPE_CYSTA: 2616 if (ver->fcxcysta == 2) { 2617 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD) 2618 break; 2619 /* Check Leak-AP */ 2620 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 && 2621 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) { 2622 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) < 2623 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt)) 2624 dm->leak_ap = 1; 2625 } 2626 2627 /* Check diff time between WL slot and W1/E2G slot */ 2628 if (dm->tdma_now.type == CXTDMA_OFF && 2629 dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2630 if (ver->fcxslots == 1) 2631 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur); 2632 else if (ver->fcxslots == 7) 2633 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur); 2634 } else { 2635 if (ver->fcxslots == 1) 2636 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2637 else if (ver->fcxslots == 7) 2638 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2639 } 2640 2641 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) { 2642 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set; 2643 _chk_btc_err(rtwdev, 2644 BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2645 } 2646 2647 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2648 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1])); 2649 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2650 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1])); 2651 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2652 le16_to_cpu(pcysta->v2.cycles)); 2653 } else if (ver->fcxcysta == 3) { 2654 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD) 2655 break; 2656 2657 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]); 2658 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr); 2659 2660 /* Check Leak-AP */ 2661 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2662 dm->tdma_now.rxflctrl) { 2663 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2664 dm->leak_ap = 1; 2665 } 2666 2667 /* Check diff time between real WL slot and W1 slot */ 2668 if (dm->tdma_now.type == CXTDMA_OFF) { 2669 if (ver->fcxslots == 1) 2670 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2671 else if (ver->fcxslots == 7) 2672 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2673 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]); 2674 if (wl_slot_real > wl_slot_set) { 2675 diff_t = wl_slot_real - wl_slot_set; 2676 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2677 } 2678 } 2679 2680 /* Check diff time between real BT slot and EBT/E5G slot */ 2681 if (dm->tdma_now.type == CXTDMA_OFF && 2682 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2683 btc->bt_req_len[RTW89_PHY_0] != 0) { 2684 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]); 2685 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) { 2686 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real; 2687 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2688 } 2689 } 2690 2691 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2692 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1])); 2693 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2694 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1])); 2695 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2696 le16_to_cpu(pcysta->v3.cycles)); 2697 } else if (ver->fcxcysta == 4) { 2698 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD) 2699 break; 2700 2701 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]); 2702 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr); 2703 2704 /* Check Leak-AP */ 2705 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2706 dm->tdma_now.rxflctrl) { 2707 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2708 dm->leak_ap = 1; 2709 } 2710 2711 /* Check diff time between real WL slot and W1 slot */ 2712 if (dm->tdma_now.type == CXTDMA_OFF) { 2713 if (ver->fcxslots == 1) 2714 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2715 else if (ver->fcxslots == 7) 2716 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2717 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]); 2718 if (wl_slot_real > wl_slot_set) { 2719 diff_t = wl_slot_real - wl_slot_set; 2720 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2721 } 2722 } 2723 2724 /* Check diff time between real BT slot and EBT/E5G slot */ 2725 if (dm->tdma_now.type == CXTDMA_OFF && 2726 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2727 btc->bt_req_len[RTW89_PHY_0] != 0) { 2728 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]); 2729 2730 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) { 2731 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real; 2732 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2733 } 2734 } 2735 2736 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2737 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1])); 2738 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2739 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1])); 2740 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2741 le16_to_cpu(pcysta->v4.cycles)); 2742 } else if (ver->fcxcysta == 5) { 2743 if (dm->fddt_train == BTC_FDDT_ENABLE) 2744 break; 2745 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]); 2746 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr); 2747 2748 /* Check Leak-AP */ 2749 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2750 dm->tdma_now.rxflctrl) { 2751 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 2752 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2753 dm->leak_ap = 1; 2754 } 2755 2756 /* Check diff time between real WL slot and W1 slot */ 2757 if (dm->tdma_now.type == CXTDMA_OFF) { 2758 if (ver->fcxslots == 1) 2759 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2760 else if (ver->fcxslots == 7) 2761 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2762 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]); 2763 2764 if (wl_slot_real > wl_slot_set) 2765 diff_t = wl_slot_real - wl_slot_set; 2766 else 2767 diff_t = wl_slot_set - wl_slot_real; 2768 } 2769 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2770 2771 /* Check diff time between real BT slot and EBT/E5G slot */ 2772 bt_slot_set = btc->bt_req_len[RTW89_PHY_0]; 2773 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]); 2774 diff_t = 0; 2775 if (dm->tdma_now.type == CXTDMA_OFF && 2776 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2777 bt_slot_set != 0) { 2778 if (bt_slot_set > bt_slot_real) 2779 diff_t = bt_slot_set - bt_slot_real; 2780 else 2781 diff_t = bt_slot_real - bt_slot_set; 2782 } 2783 2784 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2785 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2786 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G])); 2787 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2788 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1])); 2789 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2790 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1])); 2791 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2792 le16_to_cpu(pcysta->v5.cycles)); 2793 } else if (ver->fcxcysta == 105) { 2794 if (dm->fddt_train == BTC_FDDT_ENABLE) 2795 break; 2796 2797 cnt_leak_slot = le16_to_cpu(pcysta->v105.slot_cnt[CXST_LK]); 2798 cnt_rx_imr = le32_to_cpu(pcysta->v105.leak_slot.cnt_rximr); 2799 2800 /* Check Leak-AP */ 2801 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2802 dm->tdma_now.rxflctrl) { 2803 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 2804 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2805 dm->leak_ap = 1; 2806 } 2807 2808 /* Check diff time between real WL slot and W1 slot */ 2809 if (dm->tdma_now.type == CXTDMA_OFF) { 2810 if (ver->fcxslots == 1) 2811 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2812 else if (ver->fcxslots == 7) 2813 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2814 wl_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_WL]); 2815 2816 if (wl_slot_real > wl_slot_set) 2817 diff_t = wl_slot_real - wl_slot_set; 2818 else 2819 diff_t = wl_slot_set - wl_slot_real; 2820 } 2821 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2822 2823 /* Check diff time between real BT slot and EBT/E5G slot */ 2824 bt_slot_set = btc->bt_req_len[RTW89_PHY_0]; 2825 bt_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_BT]); 2826 diff_t = 0; 2827 if (dm->tdma_now.type == CXTDMA_OFF && 2828 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2829 bt_slot_set != 0) { 2830 if (bt_slot_set > bt_slot_real) 2831 diff_t = bt_slot_set - bt_slot_real; 2832 else 2833 diff_t = bt_slot_real - bt_slot_set; 2834 } 2835 2836 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2837 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2838 le16_to_cpu(pcysta->v105.slot_cnt[CXST_E2G])); 2839 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2840 le16_to_cpu(pcysta->v105.slot_cnt[CXST_W1])); 2841 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2842 le16_to_cpu(pcysta->v105.slot_cnt[CXST_B1])); 2843 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2844 le16_to_cpu(pcysta->v105.cycles)); 2845 } else if (ver->fcxcysta == 7) { 2846 if (dm->fddt_train == BTC_FDDT_ENABLE) 2847 break; 2848 2849 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 2850 2851 if (dm->tdma_now.type != CXTDMA_OFF) { 2852 /* Check diff time between real WL slot and W1 slot */ 2853 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]); 2854 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16); 2855 2856 /* Check Leak-AP */ 2857 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) * 2858 BTC_LEAK_AP_TH; 2859 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]); 2860 2861 val16 = le16_to_cpu(pcysta->v7.cycles); 2862 if (dm->tdma_now.rxflctrl && 2863 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2864 dm->leak_ap = 1; 2865 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2866 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]); 2867 /* Check diff between real BT slot and EBT/E5G slot */ 2868 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16); 2869 2870 /* Check bt slot length for P2P mode*/ 2871 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) * 2872 BTC_SLOT_REQ_TH; 2873 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt); 2874 2875 val16 = le16_to_cpu(pcysta->v7.cycles); 2876 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2877 dm->slot_req_more = 1; 2878 else if (bt->link_info.status.map.connect == 0) 2879 dm->slot_req_more = 0; 2880 } 2881 2882 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2883 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G])); 2884 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2885 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1])); 2886 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2887 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1])); 2888 2889 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */ 2890 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD, 2891 le16_to_cpu(pcysta->v7.cycles)); 2892 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2893 le16_to_cpu(pcysta->v7.cycles)); 2894 } else if (ver->fcxcysta == 8) { 2895 if (dm->fddt_train == BTC_FDDT_ENABLE) 2896 break; 2897 2898 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 2899 2900 if (dm->tdma_now.type != CXTDMA_OFF) { 2901 val16 = le16_to_cpu(pcysta->v8.cycle_time.tavg[CXT_WL]); 2902 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16); 2903 2904 val1 = le32_to_cpu(pcysta->v8.leak_slot.cnt_rximr) * 2905 BTC_LEAK_AP_TH; 2906 val2 = le16_to_cpu(pcysta->v8.slot_cnt[CXST_LK]); 2907 2908 val16 = le16_to_cpu(pcysta->v8.cycles); 2909 if (dm->tdma_now.rxflctrl && 2910 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2911 dm->leak_ap = 1; 2912 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2913 val16 = le16_to_cpu(pcysta->v8.cycle_time.tavg[CXT_BT]); 2914 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16); 2915 2916 val1 = le16_to_cpu(pcysta->v8.a2dp_ept.cnt_timeout) * 2917 BTC_SLOT_REQ_TH; 2918 val2 = le16_to_cpu(pcysta->v8.a2dp_ept.cnt); 2919 2920 val16 = le16_to_cpu(pcysta->v8.cycles); 2921 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2922 dm->slot_req_more = 1; 2923 else if (bt->link_info.status.map.connect == 0) 2924 dm->slot_req_more = 0; 2925 } 2926 2927 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2928 le16_to_cpu(pcysta->v8.slot_cnt[CXST_E2G])); 2929 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2930 le16_to_cpu(pcysta->v8.slot_cnt[CXST_W1])); 2931 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2932 le16_to_cpu(pcysta->v8.slot_cnt[CXST_B1])); 2933 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD, 2934 le16_to_cpu(pcysta->v8.cycles)); 2935 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2936 le16_to_cpu(pcysta->v8.cycles)); 2937 } else { 2938 goto err; 2939 } 2940 break; 2941 case BTC_RPT_TYPE_NULLSTA: 2942 _chk_btc_err(rtwdev, BTC_DCNT_NULL_TX_FAIL, 0); 2943 break; 2944 case BTC_RPT_TYPE_MREG: 2945 if (ver->fcxmreg == 7) 2946 break; 2947 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val); 2948 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL) 2949 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL; 2950 else 2951 dm->wl_btg_rx_rb = val; 2952 2953 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val); 2954 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL) 2955 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL; 2956 else 2957 dm->wl_pre_agc_rb = val; 2958 break; 2959 case BTC_RPT_TYPE_BT_VER: 2960 case BTC_RPT_TYPE_BT_SCAN: 2961 case BTC_RPT_TYPE_BT_AFH: 2962 case BTC_RPT_TYPE_BT_DEVICE: 2963 _update_bt_report(rtwdev, rpt_type, pfinfo); 2964 break; 2965 } 2966 return (rpt_len + BTC_RPT_HDR_SIZE); 2967 2968 err: 2969 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2970 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type); 2971 return 0; 2972 } 2973 2974 static void _parse_btc_report(struct rtw89_dev *rtwdev, 2975 struct rtw89_btc_btf_fwinfo *pfwinfo, 2976 u8 *pbuf, u32 buf_len) 2977 { 2978 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 2979 struct rtw89_btc_prpt *btc_prpt = NULL; 2980 u32 index = 0, rpt_len = 0; 2981 2982 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2983 "[BTC], %s(): buf_len:%d\n", 2984 __func__, buf_len); 2985 2986 while (pbuf) { 2987 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index]; 2988 if (index + 2 >= ver->info_buf) 2989 break; 2990 /* At least 3 bytes: type(1) & len(2) */ 2991 rpt_len = le16_to_cpu(btc_prpt->len); 2992 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len) 2993 break; 2994 2995 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index); 2996 if (!rpt_len) 2997 break; 2998 index += rpt_len; 2999 } 3000 } 3001 3002 #define BTC_TLV_HDR_LEN 2 3003 #define BTC_TLV_HDR_LEN_V7 3 3004 3005 static void _append_tdma(struct rtw89_dev *rtwdev) 3006 { 3007 struct rtw89_btc *btc = &rtwdev->btc; 3008 const struct rtw89_btc_ver *ver = btc->ver; 3009 struct rtw89_btc_dm *dm = &btc->dm; 3010 struct rtw89_btc_btf_tlv *tlv; 3011 struct rtw89_btc_btf_tlv_v7 *tlv_v7; 3012 struct rtw89_btc_fbtc_tdma *v; 3013 struct rtw89_btc_fbtc_tdma_v3 *v3; 3014 u16 len = btc->policy_len; 3015 3016 if (!btc->update_policy_force && 3017 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) { 3018 rtw89_debug(rtwdev, 3019 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n", 3020 __func__); 3021 return; 3022 } 3023 3024 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 3025 tlv->type = CXPOLICY_TDMA; 3026 if (ver->fcxtdma == 1) { 3027 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0]; 3028 tlv->len = sizeof(*v); 3029 *v = dm->tdma; 3030 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 3031 } else if (ver->fcxtdma == 4 || ver->fcxtdma == 7 || ver->fcxtdma == 8) { 3032 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 3033 tlv_v7->len = sizeof(dm->tdma); 3034 tlv_v7->ver = ver->fcxtdma; 3035 tlv_v7->type = CXPOLICY_TDMA; 3036 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len); 3037 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len; 3038 } else { 3039 tlv->len = sizeof(*v3); 3040 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0]; 3041 v3->fver = ver->fcxtdma; 3042 v3->tdma = dm->tdma; 3043 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3); 3044 } 3045 3046 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3047 "[BTC], %s(): type:%d, rxflctrl=%d, txflctrl=%d, bind=%d, leak_n=%d, ext_ctrl=%d\n", 3048 __func__, dm->tdma.type, dm->tdma.rxflctrl, 3049 dm->tdma.txflctrl, dm->tdma.bind, dm->tdma.leak_n, 3050 dm->tdma.ext_ctrl); 3051 } 3052 3053 static void _append_slot_v1(struct rtw89_dev *rtwdev) 3054 { 3055 struct rtw89_btc *btc = &rtwdev->btc; 3056 struct rtw89_btc_dm *dm = &btc->dm; 3057 struct rtw89_btc_btf_tlv *tlv = NULL; 3058 struct btc_fbtc_1slot *v = NULL; 3059 u16 len = 0; 3060 u8 i, cnt = 0; 3061 3062 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3063 "[BTC], %s(): A:btc->policy_len = %d\n", 3064 __func__, btc->policy_len); 3065 3066 for (i = 0; i < CXST_MAX; i++) { 3067 if (!btc->update_policy_force && 3068 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i], 3069 sizeof(dm->slot.v1[i]))) 3070 continue; 3071 3072 len = btc->policy_len; 3073 3074 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 3075 v = (struct btc_fbtc_1slot *)&tlv->val[0]; 3076 tlv->type = CXPOLICY_SLOT; 3077 tlv->len = sizeof(*v); 3078 3079 v->fver = btc->ver->fcxslots; 3080 v->sid = i; 3081 v->slot = dm->slot.v1[i]; 3082 3083 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3084 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n", 3085 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl, 3086 dm->slot.v1[i].cxtype); 3087 cnt++; 3088 3089 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 3090 } 3091 3092 if (cnt > 0) 3093 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3094 "[BTC], %s(): slot update (cnt=%d)!!\n", 3095 __func__, cnt); 3096 } 3097 3098 static void _append_slot_v7(struct rtw89_dev *rtwdev) 3099 { 3100 struct rtw89_btc_btf_tlv_v7 *tlv = NULL; 3101 struct rtw89_btc *btc = &rtwdev->btc; 3102 struct rtw89_btc_dm *dm = &btc->dm; 3103 u8 i, cnt = 0; 3104 u16 len; 3105 3106 for (i = 0; i < CXST_MAX; i++) { 3107 if (!btc->update_policy_force && 3108 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i], 3109 sizeof(dm->slot.v7[i]))) 3110 continue; 3111 3112 len = btc->policy_len; 3113 3114 if (!tlv) { 3115 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) { 3116 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3117 "[BTC], %s(): buff overflow!\n", __func__); 3118 break; 3119 } 3120 3121 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 3122 tlv->type = CXPOLICY_SLOT; 3123 tlv->ver = btc->ver->fcxslots; 3124 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7; 3125 len += BTC_TLV_HDR_LEN_V7; 3126 } 3127 3128 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) { 3129 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3130 "[BTC], %s(): buff overflow!\n", __func__); 3131 break; 3132 } 3133 3134 btc->policy[len] = i; /* slot-id */ 3135 memcpy(&btc->policy[len + 1], &dm->slot.v7[i], 3136 sizeof(dm->slot.v7[0])); 3137 len += tlv->len; 3138 3139 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3140 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n", 3141 __func__, btc->policy_len, i, dm->slot.v7[i].dur, 3142 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl); 3143 cnt++; 3144 btc->policy_len = len; /* update total length */ 3145 } 3146 3147 if (cnt > 0) 3148 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3149 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n", 3150 __func__, cnt, btc->policy_len); 3151 } 3152 3153 static void _append_slot(struct rtw89_dev *rtwdev) 3154 { 3155 struct rtw89_btc *btc = &rtwdev->btc; 3156 3157 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7) 3158 _append_slot_v7(rtwdev); 3159 else 3160 _append_slot_v1(rtwdev); 3161 } 3162 3163 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) 3164 { 3165 struct rtw89_btc *btc = &rtwdev->btc; 3166 const struct rtw89_btc_ver *ver = btc->ver; 3167 u32 bit_map = 0; 3168 3169 switch (rpt_map) { 3170 case RPT_EN_TDMA: 3171 bit_map = BIT(0); 3172 break; 3173 case RPT_EN_CYCLE: 3174 bit_map = BIT(1); 3175 break; 3176 case RPT_EN_MREG: 3177 bit_map = BIT(2); 3178 break; 3179 case RPT_EN_BT_VER_INFO: 3180 bit_map = BIT(3); 3181 break; 3182 case RPT_EN_BT_SCAN_INFO: 3183 bit_map = BIT(4); 3184 break; 3185 case RPT_EN_BT_DEVICE_INFO: 3186 switch (ver->frptmap) { 3187 case 0: 3188 case 1: 3189 case 2: 3190 bit_map = BIT(6); 3191 break; 3192 case 3: 3193 case 4: 3194 case 5: 3195 case 105: 3196 bit_map = BIT(5); 3197 break; 3198 default: 3199 break; 3200 } 3201 break; 3202 case RPT_EN_BT_AFH_MAP: 3203 switch (ver->frptmap) { 3204 case 0: 3205 case 1: 3206 case 2: 3207 bit_map = BIT(5); 3208 break; 3209 case 3: 3210 case 4: 3211 case 5: 3212 case 105: 3213 bit_map = BIT(6); 3214 break; 3215 default: 3216 break; 3217 } 3218 break; 3219 case RPT_EN_BT_AFH_MAP_LE: 3220 switch (ver->frptmap) { 3221 case 2: 3222 bit_map = BIT(8); 3223 break; 3224 case 3: 3225 case 4: 3226 case 5: 3227 case 105: 3228 bit_map = BIT(7); 3229 break; 3230 default: 3231 break; 3232 } 3233 break; 3234 case RPT_EN_BT_TX_PWR_LVL: 3235 switch (ver->frptmap) { 3236 case 0: 3237 case 1: 3238 case 2: 3239 case 3: 3240 case 105: 3241 break; 3242 case 4: 3243 case 5: 3244 bit_map = BIT(8); 3245 break; 3246 default: 3247 break; 3248 } 3249 break; 3250 case RPT_EN_FW_STEP_INFO: 3251 switch (ver->frptmap) { 3252 case 1: 3253 case 2: 3254 bit_map = BIT(7); 3255 break; 3256 case 3: 3257 case 105: 3258 bit_map = BIT(8); 3259 break; 3260 case 4: 3261 case 5: 3262 bit_map = BIT(9); 3263 break; 3264 default: 3265 break; 3266 } 3267 break; 3268 case RPT_EN_TEST: 3269 if (ver->frptmap == 5) 3270 bit_map = BIT(10); 3271 else if (ver->frptmap == 105) 3272 bit_map = BIT(9); 3273 else 3274 bit_map = BIT(31); 3275 break; 3276 case RPT_EN_WL_ALL: 3277 switch (ver->frptmap) { 3278 case 0: 3279 case 1: 3280 case 2: 3281 bit_map = GENMASK(2, 0); 3282 break; 3283 case 3: 3284 case 105: 3285 bit_map = GENMASK(2, 0) | BIT(8); 3286 break; 3287 case 4: 3288 case 5: 3289 bit_map = GENMASK(2, 0) | BIT(9); 3290 break; 3291 default: 3292 break; 3293 } 3294 break; 3295 case RPT_EN_BT_ALL: 3296 switch (ver->frptmap) { 3297 case 0: 3298 case 1: 3299 bit_map = GENMASK(6, 3); 3300 break; 3301 case 2: 3302 bit_map = GENMASK(6, 3) | BIT(8); 3303 break; 3304 case 3: 3305 case 105: 3306 bit_map = GENMASK(7, 3); 3307 break; 3308 case 4: 3309 case 5: 3310 bit_map = GENMASK(8, 3); 3311 break; 3312 default: 3313 break; 3314 } 3315 break; 3316 case RPT_EN_ALL: 3317 switch (ver->frptmap) { 3318 case 0: 3319 bit_map = GENMASK(6, 0); 3320 break; 3321 case 1: 3322 bit_map = GENMASK(7, 0); 3323 break; 3324 case 2: 3325 case 3: 3326 bit_map = GENMASK(8, 0); 3327 break; 3328 case 4: 3329 case 5: 3330 case 105: 3331 bit_map = GENMASK(9, 0); 3332 break; 3333 default: 3334 break; 3335 } 3336 break; 3337 case RPT_EN_MONITER: 3338 switch (ver->frptmap) { 3339 case 0: 3340 case 1: 3341 bit_map = GENMASK(6, 2); 3342 break; 3343 case 2: 3344 bit_map = GENMASK(6, 2) | BIT(8); 3345 break; 3346 case 3: 3347 case 105: 3348 bit_map = GENMASK(8, 2); 3349 break; 3350 case 4: 3351 case 5: 3352 bit_map = GENMASK(9, 2); 3353 break; 3354 default: 3355 break; 3356 } 3357 break; 3358 } 3359 3360 return bit_map; 3361 } 3362 3363 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev) 3364 { 3365 struct rtw89_btc *btc = &rtwdev->btc; 3366 const struct rtw89_btc_ver *ver = btc->ver; 3367 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL; 3368 struct rtw89_btc_btf_set_slot_table *tbl; 3369 struct rtw89_btc_dm *dm = &btc->dm; 3370 u16 n, len; 3371 3372 if (ver->fcxslots == 2 || ver->fcxslots == 7) { 3373 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7); 3374 tlv_v7 = kmalloc(len, GFP_KERNEL); 3375 if (!tlv_v7) 3376 return; 3377 3378 tlv_v7->type = SET_SLOT_TABLE; 3379 tlv_v7->ver = ver->fcxslots; 3380 tlv_v7->len = ARRAY_SIZE(dm->slot.v7); 3381 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7)); 3382 3383 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len); 3384 3385 kfree(tlv_v7); 3386 } else { 3387 n = struct_size(tbl, tbls, CXST_MAX); 3388 tbl = kmalloc(n, GFP_KERNEL); 3389 if (!tbl) 3390 return; 3391 3392 tbl->fver = BTF_SET_SLOT_TABLE_VER; 3393 tbl->tbl_num = CXST_MAX; 3394 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX)); 3395 3396 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); 3397 3398 kfree(tbl); 3399 } 3400 } 3401 3402 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, 3403 bool force_exec, u32 rpt_map) 3404 { 3405 struct rtw89_btc *btc = &rtwdev->btc; 3406 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo; 3407 union rtw89_fbtc_rtp_ctrl r; 3408 int ret; 3409 u32 i; 3410 3411 if (!force_exec && rpt_map == fwinfo->rpt_en_map) 3412 return; 3413 3414 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rpt_map=%x\n", 3415 __func__, fwinfo->rpt_en_map); 3416 3417 if (btc->ver->fcxbtcrpt == 7 || 3418 btc->ver->fcxbtcrpt == 8 || 3419 btc->ver->fcxbtcrpt == 9 || 3420 btc->ver->fcxbtcrpt == 11 || 3421 btc->ver->fcxbtcrpt == 205) { 3422 r.v8.type = SET_REPORT_EN; 3423 if (btc->ver->fcxbtcrpt == 205) 3424 r.v8.fver = 5; 3425 else 3426 r.v8.fver = btc->ver->fcxbtcrpt; 3427 r.v8.len = sizeof(r.v8.map); 3428 r.v8.map = cpu_to_le32(rpt_map); 3429 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8, 3430 sizeof(r.v8)); 3431 } else { 3432 if (btc->ver->fcxbtcrpt == 105) 3433 r.v1.fver = 5; 3434 else 3435 r.v1.fver = btc->ver->fcxbtcrpt; 3436 3437 for (i = 0; i < RPT_EN_MONITER; i++) { 3438 r.v1.enable = cpu_to_le32(i); 3439 if (rpt_map & BIT(i)) 3440 r.v1.para = cpu_to_le32(1); 3441 else 3442 r.v1.para = 0; 3443 3444 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, 3445 &r.v1, sizeof(r.v1)); 3446 } 3447 } 3448 3449 if (!ret) 3450 fwinfo->rpt_en_map = rpt_map; 3451 } 3452 3453 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) 3454 { 3455 const struct rtw89_chip_info *chip = rtwdev->chip; 3456 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3457 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL; 3458 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL; 3459 u8 i, n, ulen, cxmreg_max; 3460 u16 sz = 0; 3461 3462 n = chip->mon_reg_num; 3463 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3464 "[BTC], %s(): mon_reg_num=%d\n", __func__, n); 3465 3466 if (ver->fcxmreg == 1) 3467 cxmreg_max = CXMREG_MAX; 3468 else 3469 cxmreg_max = CXMREG_MAX_V2; 3470 3471 if (n > cxmreg_max) { 3472 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3473 "[BTC], %s(): mon reg count %d > %d\n", 3474 __func__, n, cxmreg_max); 3475 return; 3476 } 3477 3478 ulen = sizeof(struct rtw89_btc_fbtc_mreg); 3479 3480 if (ver->fcxmreg == 7) { 3481 sz = struct_size(v7, regs, n); 3482 v7 = kmalloc(sz, GFP_KERNEL); 3483 if (!v7) 3484 return; 3485 v7->type = RPT_EN_MREG; 3486 v7->fver = ver->fcxmreg; 3487 v7->len = n; 3488 for (i = 0; i < n; i++) { 3489 v7->regs[i].type = chip->mon_reg[i].type; 3490 v7->regs[i].bytes = chip->mon_reg[i].bytes; 3491 v7->regs[i].offset = chip->mon_reg[i].offset; 3492 } 3493 3494 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz); 3495 kfree(v7); 3496 } else { 3497 sz = struct_size(v1, regs, n); 3498 v1 = kmalloc(sz, GFP_KERNEL); 3499 if (!v1) 3500 return; 3501 v1->fver = ver->fcxmreg; 3502 v1->reg_num = n; 3503 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n)); 3504 3505 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz); 3506 kfree(v1); 3507 } 3508 3509 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3510 "[BTC], %s(): sz=%d ulen=%d n=%d\n", 3511 __func__, sz, ulen, n); 3512 } 3513 3514 static void _update_dm_step(struct rtw89_dev *rtwdev, 3515 enum btc_reason_and_action reason_or_action) 3516 { 3517 struct rtw89_btc *btc = &rtwdev->btc; 3518 struct rtw89_btc_dm *dm = &btc->dm; 3519 3520 /* use ring-structure to store dm step */ 3521 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action; 3522 dm->dm_step.step_pos++; 3523 3524 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) { 3525 dm->dm_step.step_pos = 0; 3526 dm->dm_step.step_ov = true; 3527 } 3528 } 3529 3530 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 3531 enum btc_reason_and_action action) 3532 { 3533 struct rtw89_btc *btc = &rtwdev->btc; 3534 struct rtw89_btc_dm *dm = &btc->dm; 3535 int ret; 3536 3537 dm->run_action = action; 3538 3539 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT); 3540 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT); 3541 3542 btc->policy_len = 0; 3543 btc->policy_type = policy_type; 3544 3545 _append_tdma(rtwdev); 3546 _append_slot(rtwdev); 3547 3548 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN) 3549 return; 3550 3551 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3552 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n", 3553 __func__, action, policy_type, btc->policy_len); 3554 3555 if (dm->tdma.rxflctrl == CXFLC_NULLP || 3556 dm->tdma.rxflctrl == CXFLC_QOSNULL) 3557 btc->btc_ctrl_lps = 1; 3558 else 3559 btc->btc_ctrl_lps = dm->lps_ctrl_scbd; 3560 3561 if (btc->btc_ctrl_lps == 1) 3562 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps); 3563 3564 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY, 3565 btc->policy, btc->policy_len); 3566 if (!ret) { 3567 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now)); 3568 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7) 3569 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7)); 3570 else 3571 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1)); 3572 } 3573 3574 if (btc->update_policy_force) 3575 btc->update_policy_force = false; 3576 3577 if (btc->btc_ctrl_lps == 0) 3578 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps); 3579 } 3580 3581 static u8 _get_gpiosig_for_ver(struct rtw89_dev *rtwdev, u8 sig_v8) 3582 { 3583 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3584 3585 /* v8: gpio_ver >= 8, directly use v8 signal ID */ 3586 if (ver->fcxgpiodbg >= 8) 3587 return sig_v8; 3588 3589 /* v7: gpio_ver < 8, convert v8 signal ID to v7 signal ID */ 3590 if (sig_v8 <= BTC_DBG_GNT_WL) { 3591 return sig_v8; 3592 } else if (sig_v8 <= BTC_DBG_GNT_WL1) { 3593 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3594 "[BTC], %s(): sig %d not supported in v7\n", 3595 __func__, sig_v8); 3596 return BTC_DBG_NUM; 3597 } else if (sig_v8 >= BTC_DBG_NUM) { 3598 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3599 "[BTC], %s(): sig %d not available\n", 3600 __func__, sig_v8); 3601 return BTC_DBG_NUM; 3602 } else { 3603 return sig_v8 - 2; 3604 } 3605 } 3606 3607 static u32 _convert_gpio_enmap_to_ver(struct rtw89_dev *rtwdev, u32 en_map_v8) 3608 { 3609 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3610 u32 en_map_v7 = 0; 3611 u32 bit; 3612 3613 /* v8: gpio_ver >= 8, directly use v8 en_map */ 3614 if (ver->fcxgpiodbg >= 8) 3615 return en_map_v8; 3616 3617 /* v7: gpio_ver < 8, convert v8 en_map bitmap to v7 en_map bitmap */ 3618 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ 3619 en_map_v7 |= en_map_v8 & GENMASK(1, 0); 3620 3621 /* bit 2-3: GNT_BT1, GNT_WL1 - not supported in v7, skip these bits */ 3622 3623 /* bit 4-31: shift right by 2 positions (become bit 2-29 in v7) */ 3624 for (bit = BTC_DBG_BCN_EARLY; bit < BTC_DBG_NUM; bit++) { 3625 if (en_map_v8 & BIT(bit)) 3626 en_map_v7 |= BIT(bit - 2); 3627 } 3628 3629 return en_map_v7; 3630 } 3631 3632 static u32 _convert_gpio_enmap_from_ver(struct rtw89_dev *rtwdev, u32 en_map) 3633 { 3634 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 3635 u32 en_map_v8 = 0; 3636 u32 bit; 3637 3638 if (ver->fcxgpiodbg >= 8) 3639 return en_map; 3640 3641 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */ 3642 en_map_v8 |= en_map & GENMASK(1, 0); 3643 3644 /* bit 2-29: shift left by 2 positions (become bit 4-31 in v8) */ 3645 for (bit = BTC_DBG_GNT_BT1; bit < BTC_DBG_NUM - 2; bit++) { 3646 if (en_map & BIT(bit)) 3647 en_map_v8 |= BIT(bit + 2); 3648 } 3649 3650 return en_map_v8; 3651 } 3652 3653 static void _fw_set_gpio(struct rtw89_dev *rtwdev, u8 type, u32 val) 3654 { 3655 struct rtw89_btc *btc = &rtwdev->btc; 3656 struct rtw89_fbtc_h2c_set_gpio *gpio = &btc->gpio; 3657 const struct rtw89_btc_ver *ver = btc->ver; 3658 struct rtw89_fbtc_h2c_set_gpio_2b l2_h2c; 3659 struct rtw89_fbtc_h2c_set_gpio_4b l4_h2c; 3660 u8 gpio_ver = ver->fcxgpiodbg; 3661 u8 buf[sizeof(l4_h2c)]; 3662 u8 len; 3663 3664 if (gpio_ver < 8 && type > CXDGPIO_MUX_MAP) 3665 return; 3666 3667 if (type >= CXDGPIO_MAX) 3668 return; 3669 3670 switch (type) { 3671 case CXDGPIO_EN_MAP: /* GPIO debug signal en-map 0~31 */ 3672 val = _convert_gpio_enmap_to_ver(rtwdev, val); 3673 gpio->en_map.data.type = CXDGPIO_EN_MAP; 3674 gpio->en_map.data.fver = gpio_ver; 3675 gpio->en_map.data.dlen = CXDGPIO_SET_L4; 3676 gpio->en_map.data.en_map = val; 3677 l4_h2c = gpio->en_map.fmt; 3678 put_unaligned_le32(val, (u32 *)l4_h2c.data); 3679 memcpy(buf, &l4_h2c, sizeof(l4_h2c)); 3680 len = sizeof(l4_h2c); 3681 break; 3682 case CXDGPIO_MUX_MAP: /* GPIO dbg: Signal to GPIO Mux */ 3683 gpio->mux.data.type = CXDGPIO_MUX_MAP; 3684 gpio->mux.data.fver = gpio_ver; 3685 gpio->mux.data.dlen = CXDGPIO_SET_L2; 3686 gpio->mux.data.sig = _get_gpiosig_for_ver(rtwdev, 3687 FIELD_GET(GENMASK(7, 0), val)); 3688 if (gpio->mux.data.sig >= BTC_DBG_NUM) 3689 return; 3690 gpio->mux.data.gpio = FIELD_GET(GENMASK(15, 8), val); 3691 l2_h2c = gpio->mux.fmt; 3692 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3693 len = sizeof(l2_h2c); 3694 break; 3695 case CXDGPIO_EXT_HPTA: /* GPIO config for Ext HW-PTA */ 3696 gpio->ext_pta.data.type = CXDGPIO_EXT_HPTA; 3697 gpio->ext_pta.data.fver = gpio_ver; 3698 gpio->ext_pta.data.dlen = CXDGPIO_SET_L2; 3699 gpio->ext_pta.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3700 gpio->ext_pta.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3701 l2_h2c = gpio->ext_pta.fmt; 3702 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3703 len = sizeof(l2_h2c); 3704 break; 3705 case CXDGPIO_EXT_HMBX: /* GPIO config for Ext HW-mailbox */ 3706 gpio->ext_mb.data.type = CXDGPIO_EXT_HMBX; 3707 gpio->ext_mb.data.fver = gpio_ver; 3708 gpio->ext_mb.data.dlen = CXDGPIO_SET_L2; 3709 gpio->ext_mb.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3710 gpio->ext_mb.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3711 l2_h2c = gpio->ext_mb.fmt; 3712 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3713 len = sizeof(l2_h2c); 3714 break; 3715 case CXDGPIO_EXT_SWOUT: /* GPIO config for Ext SW output (wlan_act) */ 3716 gpio->ext_swout.data.type = CXDGPIO_EXT_SWOUT; 3717 gpio->ext_swout.data.fver = gpio_ver; 3718 gpio->ext_swout.data.dlen = CXDGPIO_SET_L2; 3719 gpio->ext_swout.data.map_low = FIELD_GET(GENMASK(7, 0), val); 3720 gpio->ext_swout.data.map_high = FIELD_GET(GENMASK(15, 8), val); 3721 l2_h2c = gpio->ext_swout.fmt; 3722 memcpy(buf, &l2_h2c, sizeof(l2_h2c)); 3723 len = sizeof(l2_h2c); 3724 break; 3725 case CXDGPIO_EXT_SWIN: /* GPIO config for Ext SW input control */ 3726 gpio->ext_swin.data.type = CXDGPIO_EXT_SWIN; 3727 gpio->ext_swin.data.fver = gpio_ver; 3728 gpio->ext_swin.data.dlen = CXDGPIO_SET_L4; 3729 gpio->ext_swin.data.in_map_low = FIELD_GET(GENMASK(7, 0), val); 3730 gpio->ext_swin.data.in_map_high = FIELD_GET(GENMASK(15, 8), val); 3731 gpio->ext_swin.data.int_map_low = FIELD_GET(GENMASK(23, 16), val); 3732 gpio->ext_swin.data.int_map_high = FIELD_GET(GENMASK(31, 24), val); 3733 l4_h2c = gpio->ext_swin.fmt; 3734 put_unaligned_le32(val, (u32 *)l4_h2c.data); 3735 memcpy(buf, &l4_h2c, sizeof(l4_h2c)); 3736 len = sizeof(l4_h2c); 3737 break; 3738 default: 3739 return; 3740 } 3741 3742 _send_fw_cmd(rtwdev, BTFC_SET, SET_GPIO_DBG, buf, len); 3743 } 3744 3745 static void _set_ext_interface(struct rtw89_dev *rtwdev) 3746 { 3747 struct rtw89_btc *btc = &rtwdev->btc; 3748 struct rtw89_btc_cx *cx = &btc->cx; 3749 u8 bt1_sw_type = BTC_SWITCH_INTERNAL; 3750 u32 val; 3751 3752 if (btc->ver->fcxgpiodbg < 7) 3753 return; 3754 3755 /* if BT1+WL-S0, route DBG_GNT_BT1 to control SPDT */ 3756 if ((rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && 3757 btc->ver->fcxinit >= 10) { 3758 if (btc->ver->fcxinit >= 10) 3759 bt1_sw_type = btc->mdinfo.bt1_sw_type; 3760 else 3761 return; 3762 3763 if (bt1_sw_type > BTC_SWITCH_INTERNAL) { 3764 _fw_set_gpio(rtwdev, CXDGPIO_EN_MAP, 3765 BIT(BTC_DBG_GNT_BT1)); 3766 3767 val = (bt1_sw_type << 8) + BTC_DBG_GNT_BT1; 3768 _fw_set_gpio(rtwdev, CXDGPIO_MUX_MAP, val); 3769 } 3770 } 3771 3772 /* set GPIO as Ext-PTA interface wire */ 3773 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_PTA) 3774 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HPTA, cx->bt_ext.hpta_cfg); 3775 3776 /* set GPIO as Ext-mailbox interface wire */ 3777 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_MBX) 3778 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HMBX, cx->bt_ext.hmbx_cfg); 3779 3780 /* set GPIO as Ext-SWIO interface wire */ 3781 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_SWIO) { 3782 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWOUT, cx->bt_ext.swout_cfg); 3783 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWIN, cx->bt_ext.swin_cfg); 3784 } 3785 } 3786 3787 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index) 3788 { 3789 struct rtw89_btc *btc = &rtwdev->btc; 3790 const struct rtw89_btc_ver *ver = btc->ver; 3791 3792 switch (index) { 3793 case CXDRVINFO_INIT: 3794 if (ver->fcxinit == 7 || ver->fcxinit == 107) 3795 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, index); 3796 else if (ver->fcxinit == 10) 3797 rtw89_fw_h2c_cxdrv_init_v10(rtwdev, index); 3798 else if (ver->fcxinit == 11) 3799 rtw89_fw_h2c_cxdrv_init_v11(rtwdev, index); 3800 else 3801 rtw89_fw_h2c_cxdrv_init(rtwdev, index); 3802 break; 3803 case CXDRVINFO_ROLE: 3804 if (ver->fwlrole == 0) 3805 rtw89_fw_h2c_cxdrv_role(rtwdev, index); 3806 else if (ver->fwlrole == 1) 3807 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, index); 3808 else if (ver->fwlrole == 101) 3809 rtw89_fw_h2c_cxdrv_role_v101(rtwdev, index); 3810 else if (ver->fwlrole == 2) 3811 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, index); 3812 else if (ver->fwlrole == 7) 3813 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, index); 3814 else if (ver->fwlrole == 8) 3815 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, index); 3816 else if (ver->fwlrole == 10) 3817 rtw89_fw_h2c_cxdrv_role_v10(rtwdev, index); 3818 else if (ver->fwlrole == 11) 3819 rtw89_fw_h2c_cxdrv_role_v11(rtwdev, index); 3820 break; 3821 case CXDRVINFO_CTRL: 3822 if (ver->drvinfo_ver != 0) 3823 index = 2; 3824 3825 if (ver->fcxctrl == 7) 3826 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, index); 3827 else if (ver->fcxctrl == 9) 3828 rtw89_fw_h2c_cxdrv_ctrl_v9(rtwdev, index); 3829 else 3830 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, index); 3831 break; 3832 case CXDRVINFO_TRX: 3833 if (ver->drvinfo_ver > 1) 3834 index = 3; 3835 3836 if (ver->fcxtrx == 0) 3837 return; 3838 3839 if (ver->fcxtrx == 7) 3840 rtw89_fw_h2c_cxdrv_trx_v7(rtwdev, index); 3841 else if (ver->fcxtrx == 9) 3842 rtw89_fw_h2c_cxdrv_trx_v9(rtwdev, index); 3843 else if (ver->fcxtrx == 107) 3844 rtw89_fw_h2c_cxdrv_trx_v107(rtwdev, index); 3845 break; 3846 case CXDRVINFO_RFK: 3847 if (ver->drvinfo_ver != 0) 3848 return; 3849 3850 rtw89_fw_h2c_cxdrv_rfk(rtwdev, index); 3851 break; 3852 case CXDRVINFO_TXPWR: 3853 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103) 3854 index = 4; 3855 3856 if (ver->fcxtxpwr == 1) 3857 rtw89_fw_h2c_cxtxpwr_v9(rtwdev, index, 1); 3858 else if (ver->fcxtrx == 7 || ver->fcxtrx == 107) 3859 rtw89_fw_h2c_cxtxpwr_v7(rtwdev, index); 3860 else if (ver->fcxtrx == 9) 3861 rtw89_fw_h2c_cxtxpwr_v9(rtwdev, index, 9); 3862 break; 3863 case CXDRVINFO_FDDT: 3864 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103) 3865 index = 5; 3866 else 3867 return; 3868 3869 break; 3870 case CXDRVINFO_MLO: 3871 if (!ver->fcxmlo || ver->drvinfo_ver == 103) 3872 return; 3873 3874 if (ver->drvinfo_ver == 3) 3875 index = 6; 3876 else 3877 return; 3878 3879 if (ver->fcxmlo == 2) 3880 rtw89_fw_h2c_cxdrv_mlo_v2(rtwdev, index); 3881 3882 break; 3883 case CXDRVINFO_OSI: 3884 if (!ver->fcxosi || ver->drvinfo_ver == 103) 3885 return; 3886 3887 if (ver->drvinfo_ver == 3) 3888 index = 7; 3889 else 3890 return; 3891 3892 if (ver->fcxosi == 1) 3893 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, index); 3894 else if (ver->fcxosi == 6) 3895 rtw89_fw_h2c_cxdrv_osi_info_v6(rtwdev, index); 3896 else if (ver->fcxosi == 7) 3897 rtw89_fw_h2c_cxdrv_osi_info_v7(rtwdev, index); 3898 else 3899 return; 3900 break; 3901 default: 3902 break; 3903 } 3904 } 3905 3906 static 3907 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len) 3908 { 3909 struct rtw89_btc *btc = &rtwdev->btc; 3910 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 3911 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 3912 u8 i; 3913 3914 _parse_btc_report(rtwdev, pfwinfo, data, len); 3915 3916 if (!rtwdev->chip->scbd) 3917 return; 3918 3919 if (!btc->dm.scbd_b2w_update) 3920 return; /* skip if init or no-update */ 3921 3922 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) { 3923 bt = (i == BTC_BT_1ST) ? &btc->cx.bt0 : &btc->cx.bt1; 3924 3925 if (bt->scbd_c2h != bt->scbd_rb) { 3926 /* if btx b2w scbd non-sync */ 3927 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3928 "[BTC], %s() bt%d:c2h->0x%08x, rb->0x%08x\n", 3929 __func__, i, bt->scbd_c2h, bt->scbd_rb); 3930 bt->scbd_c2h = bt->scbd_rb; 3931 _update_bt_scbd(rtwdev, i, true); 3932 btc->dm.scbd_b2w_update = false; 3933 } 3934 } 3935 3936 if (!btc->dm.scbd_b2w_update) 3937 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 3938 else 3939 btc->dm.scbd_b2w_update = 0; 3940 } 3941 3942 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, 3943 u8 wl_state, u8 bt_state, u8 wlact_state) 3944 { 3945 struct rtw89_btc *btc = &rtwdev->btc; 3946 struct rtw89_btc_dm *dm = &btc->dm; 3947 struct rtw89_btc_fbtc_outsrc_set_info *o = &dm->ost_info; 3948 struct rtw89_mac_ax_wl_act *wlact_set; 3949 struct rtw89_mac_ax_coex_gnt mg; 3950 u8 i; 3951 3952 if (phy_map > BTC_PHY_ALL) 3953 return; 3954 3955 for (i = 0; i < RTW89_PHY_NUM; i++) { 3956 if (!(phy_map & BIT(i))) 3957 continue; 3958 3959 switch (wl_state) { 3960 case BTC_GNT_HW: 3961 dm->gnt_set[i].gnt_wl_sw_en = 0; 3962 dm->gnt_set[i].gnt_wl = 0; 3963 break; 3964 case BTC_GNT_SW_LO: 3965 dm->gnt_set[i].gnt_wl_sw_en = 1; 3966 dm->gnt_set[i].gnt_wl = 0; 3967 break; 3968 case BTC_GNT_SW_HI: 3969 dm->gnt_set[i].gnt_wl_sw_en = 1; 3970 dm->gnt_set[i].gnt_wl = 1; 3971 break; 3972 case BTC_GNT_SET_SKIP: 3973 default: 3974 break; 3975 } 3976 3977 switch (bt_state) { 3978 case BTC_GNT_HW: 3979 dm->gnt_set[i].gnt_bt0_sw_en = 0; 3980 dm->gnt_set[i].gnt_bt0 = 0; 3981 dm->gnt_set[i].gnt_bt1_sw_en = 0; 3982 dm->gnt_set[i].gnt_bt1 = 0; 3983 dm->gnt_set[i].gnt_zb_sw_en = 0; 3984 dm->gnt_set[i].gnt_zb = 0; 3985 break; 3986 case BTC_GNT_SW_LO: 3987 dm->gnt_set[i].gnt_bt0_sw_en = 1; 3988 dm->gnt_set[i].gnt_bt0 = 0; 3989 dm->gnt_set[i].gnt_bt1_sw_en = 1; 3990 dm->gnt_set[i].gnt_bt1 = 0; 3991 dm->gnt_set[i].gnt_zb_sw_en = 1; 3992 dm->gnt_set[i].gnt_zb = 0; 3993 break; 3994 case BTC_GNT_SW_HI: 3995 dm->gnt_set[i].gnt_bt0_sw_en = 1; 3996 dm->gnt_set[i].gnt_bt0 = 1; 3997 dm->gnt_set[i].gnt_bt1_sw_en = 1; 3998 dm->gnt_set[i].gnt_bt1 = 1; 3999 dm->gnt_set[i].gnt_zb_sw_en = 1; 4000 dm->gnt_set[i].gnt_zb = 1; 4001 break; 4002 case BTC_GNT_SET_SKIP: 4003 default: 4004 break; 4005 } 4006 } 4007 4008 for (i = 0; i < BTC_ALL_BT_EZL; i++) { 4009 if (!(rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX)) 4010 break; 4011 4012 switch (wlact_state) { 4013 case BTC_WLACT_HW: 4014 dm->wlact_set[i].wlan_act_en = 0; 4015 dm->wlact_set[i].wlan_act = 0; 4016 break; 4017 case BTC_WLACT_SW_LO: 4018 dm->wlact_set[i].wlan_act_en = 1; 4019 dm->wlact_set[i].wlan_act = 0; 4020 break; 4021 case BTC_WLACT_SW_HI: 4022 dm->wlact_set[i].wlan_act_en = 1; 4023 dm->wlact_set[i].wlan_act = 1; 4024 break; 4025 default: 4026 break; 4027 } 4028 4029 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 4030 break; 4031 } 4032 4033 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4034 "[BTC], %s(): phy_map=0x%x, gnt_wl:%d, gnt_bt:%d, wl_act:%d\n", 4035 __func__, phy_map, wl_state, bt_state, wlact_state); 4036 4037 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) { 4038 if (o->rf_band[BTC_RF_S0] == 1 && o->rf_band[BTC_RF_S1] == 0) 4039 o->rf_gbt_source = BTC_RF_S1; 4040 else 4041 o->rf_gbt_source = BTC_RF_S0; 4042 4043 memcpy(o->wlact_set, dm->wlact_set, sizeof(o->wlact_set)); 4044 4045 if (btc->ver->fcxosi == 6 || btc->ver->fcxosi == 7) { 4046 memcpy(o->gnt_set_be, dm->gnt_set, sizeof(o->gnt_set_be)); 4047 return; 4048 } else if (btc->ver->fcxosi == 1) { 4049 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */ 4050 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en; 4051 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0; 4052 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en; 4053 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl; 4054 memcpy(o->gnt_set, mg.band, sizeof(o->gnt_set)); 4055 } 4056 return; 4057 } 4058 } 4059 4060 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */ 4061 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en; 4062 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0; 4063 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en; 4064 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl; 4065 } 4066 for (i = 0; i < BTC_ALL_BT; i++) { /* wlact[BT0/BT1] */ 4067 wlact_set = &dm->wlact_set[i]; 4068 mg.bt[i].wlan_act_en = wlact_set->wlan_act_en; 4069 mg.bt[i].wlan_act = wlact_set->wlan_act; 4070 } 4071 4072 rtw89_chip_mac_cfg_gnt(rtwdev, &mg); 4073 } 4074 4075 #define BTC_TDMA_WLROLE_MAX 3 4076 4077 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable) 4078 { 4079 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4080 "[BTC], %s(): set bt %s wlan_act\n", __func__, 4081 enable ? "ignore" : "do not ignore"); 4082 4083 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1); 4084 } 4085 4086 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0) 4087 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0) 4088 #define WL_TX_POWER_WITH_BT GENMASK(31, 16) 4089 #define WL_TX_POWER_INT_PART GENMASK(8, 2) 4090 #define WL_TX_POWER_FRA_PART GENMASK(1, 0) 4091 #define B_BTC_WL_TX_POWER_SIGN BIT(7) 4092 #define B_TSSI_WL_TX_POWER_SIGN BIT(8) 4093 #define SET_RF_PARA_AX_LEN 1 4094 4095 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level, u8 phy_map) 4096 { 4097 const struct rtw89_chip_info *chip = rtwdev->chip; 4098 struct rtw89_btc *btc = &rtwdev->btc; 4099 const struct rtw89_btc_ver *ver = btc->ver; 4100 struct rtw89_btc_dm *dm = &btc->dm; 4101 bool level_chg = false; 4102 u32 pwr_val; 4103 4104 if (phy_map & BIT(RTW89_PHY_0)) 4105 level_chg = !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] == level); 4106 4107 if (phy_map & BIT(RTW89_PHY_1)) 4108 level_chg |= !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] == level); 4109 4110 if (!level_chg && !btc->cli_h2c_cmd) 4111 return; 4112 4113 if (phy_map & BIT(RTW89_PHY_0)) 4114 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] = level; 4115 4116 if (phy_map & BIT(RTW89_PHY_1)) 4117 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] = level; 4118 4119 dm->wl_tx_pwr_phy_map = phy_map; 4120 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4121 "[BTC], %s(): phy_map=0x%x, wl_tx_pwr-> phy0=%d, phy1=%d\n", 4122 __func__, phy_map, 4123 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0], 4124 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1]); 4125 4126 if ((ver->fcxtrx == 7 && chip->chip_id == RTL8922A) || 4127 ver->fcxtrx == 107) { 4128 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR); 4129 } else if (ver->fcxtrx == 9) { 4130 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR); 4131 } else { 4132 if (level == RTW89_BTC_WL_DEF_TX_PWR) { 4133 pwr_val = WL_TX_POWER_NO_BTC_CTRL; 4134 } else { /* only apply "force tx power" */ 4135 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level); 4136 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR) 4137 pwr_val = RTW89_BTC_WL_DEF_TX_PWR; 4138 4139 if (level & B_BTC_WL_TX_POWER_SIGN) 4140 pwr_val |= B_TSSI_WL_TX_POWER_SIGN; 4141 pwr_val |= WL_TX_POWER_WITH_BT; 4142 } 4143 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); 4144 } 4145 } 4146 4147 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level, u8 phy_map) 4148 { 4149 const struct rtw89_chip_info *chip = rtwdev->chip; 4150 struct rtw89_btc *btc = &rtwdev->btc; 4151 struct rtw89_btc_dm *dm = &btc->dm; 4152 bool level_chg = false; 4153 4154 if (phy_map & BIT(RTW89_PHY_0)) 4155 level_chg = !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] == level); 4156 4157 if (phy_map & BIT(RTW89_PHY_1)) 4158 level_chg |= !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] == level); 4159 4160 if (!level_chg && !btc->cli_h2c_cmd) 4161 return; 4162 4163 if (phy_map & BIT(RTW89_PHY_0)) 4164 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] = level; 4165 4166 if (phy_map & BIT(RTW89_PHY_1)) 4167 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] = level; 4168 4169 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4170 "[BTC], %s(): phy_map=0x%x, wl_rx_gain-> phy0=%d, phy1=%d\n", 4171 __func__, phy_map, 4172 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0], 4173 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1]); 4174 4175 chip->ops->btc_set_wl_rx_gain(rtwdev, level); 4176 } 4177 4178 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, bool force_exec, u8 bid, 4179 u8 rf_band, u8 level) 4180 { 4181 struct rtw89_btc *btc = &rtwdev->btc; 4182 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 4183 u8 h2c_func = SET_BT_TX_PWR; 4184 u8 i, id_start, id_stop; 4185 u8 buf[2] = {}; 4186 u8 len = sizeof(*buf); 4187 4188 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0) 4189 return; 4190 4191 if (bt->rf_para.tx_pwr_freerun == level) 4192 return; 4193 4194 if (bid == BTC_ALL_BT) { 4195 id_start = BTC_BT_1ST; 4196 id_stop = BTC_BT_2ND; 4197 } else { 4198 id_start = bid; 4199 id_stop = bid; 4200 } 4201 4202 for (i = id_start; i <= id_stop; i++) { 4203 if (i == BTC_BT_2ND) { 4204 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 4205 continue; 4206 4207 bt = &btc->cx.bt1; 4208 h2c_func |= BT_H2C_FUNC_BT2ND; 4209 } 4210 4211 buf[0] = (s8)(-level); 4212 buf[1] = rf_band; /* bit-map: bit1->5GHz/6Ghz, bit0->2.4GHz */ 4213 4214 if (!force_exec && !btc->cli_h2c_cmd) { 4215 if (rf_band == BIT(RTW89_BAND_2G) && 4216 bt->tx_power_now == level) 4217 continue; 4218 else if (rf_band != BIT(RTW89_BAND_2G) && 4219 bt->tx_power_now_6g == level) 4220 continue; 4221 } 4222 4223 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) 4224 len = SET_RF_PARA_AX_LEN; 4225 4226 if (!_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { 4227 btc->dm.rf_trx_para.bt_tx_power[i] = level; 4228 if (rf_band == BIT(RTW89_BAND_2G)) 4229 bt->tx_power_now = level; 4230 else 4231 bt->tx_power_now_6g = level; 4232 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4233 "[BTC], %s(): bt%d_tx_power_level = %d\n", 4234 __func__, i, level); 4235 } 4236 } 4237 } 4238 4239 #define BTC_BT_RX_NORMAL_LVL 7 4240 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, bool force_exec, u8 bid, 4241 u8 rf_band, u8 level) 4242 { 4243 struct rtw89_btc *btc = &rtwdev->btc; 4244 struct rtw89_btc_cx *cx = &btc->cx; 4245 struct rtw89_btc_bt_info *bt = &cx->bt0; 4246 u8 h2c_func = SET_BT_LNA_CONSTRAIN; 4247 u8 i, id_start, id_stop; 4248 bool state = false; 4249 u32 scbd_bit = 0; 4250 u8 buf[2] = {}; 4251 u8 len = sizeof(*buf); 4252 4253 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band) 4254 return; 4255 4256 if (bt->rf_para.rx_gain_freerun == level || 4257 level > BTC_BT_RX_NORMAL_LVL || !rtwdev->chip->scbd || 4258 bid > BTC_ALL_BT) 4259 return; 4260 4261 if (bid == BTC_ALL_BT) { 4262 id_start = BTC_BT_1ST; 4263 id_stop = BTC_BT_2ND; 4264 } else { 4265 id_start = bid; 4266 id_stop = bid; 4267 } 4268 4269 if (rf_band == BIT(RTW89_BAND_2G)) 4270 scbd_bit |= BTC_WSCB_RXGAIN; 4271 else 4272 scbd_bit |= BTC_WSCB_RXGAIN_56G; 4273 4274 for (i = id_start; i <= id_stop; i++) { 4275 if (i == BTC_BT_2ND) { 4276 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 4277 continue; 4278 4279 bt = &cx->bt1; 4280 h2c_func |= BT_H2C_FUNC_BT2ND; 4281 } 4282 4283 /* return if same setup */ 4284 if (!force_exec && !btc->cli_h2c_cmd) { 4285 if (rf_band == BIT(RTW89_BAND_2G) && 4286 bt->lna_constrain == level) 4287 continue; 4288 else if (rf_band != BIT(RTW89_BAND_2G) && 4289 bt->lna_constrain_6g == level) 4290 continue; 4291 } 4292 4293 buf[0] = level; 4294 buf[1] = rf_band; 4295 4296 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) 4297 len = SET_RF_PARA_AX_LEN; 4298 4299 if (_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) { 4300 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4301 "[BTC], %s(): bt%d_rx_gain_level = %d\n", 4302 __func__, i, level); 4303 } 4304 4305 btc->dm.rf_trx_para.bt_rx_gain[i] = level; 4306 4307 if (buf[0] != BTC_BT_RX_NORMAL_LVL) 4308 state = true; 4309 4310 _write_scbd(rtwdev, bid, scbd_bit, state); 4311 } 4312 } 4313 4314 static void _set_bt_corx_table(struct rtw89_dev *rtwdev, bool en) 4315 { 4316 struct rtw89_btc *btc = &rtwdev->btc; 4317 struct rtw89_btc_cx *cx = &btc->cx; 4318 struct rtw89_btc_bt_info *bt = &cx->bt0; 4319 struct rtw89_btc_dm *dm = &btc->dm; 4320 bool is_24g, is_56g, en_24g, en_56g; 4321 u8 i; 4322 4323 /* 4324 * true: bt use Hi-LNA rx gain table (f/e/3/2) in -3x~-9xdBm for co-rx 4325 * false: bt use original rx gain table (f/b/7/3/2) 4326 */ 4327 4328 if (btc->dm.fdd_bind.bt_sel == BIT(BTC_BT_EXT)) 4329 return; 4330 4331 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) { 4332 if (i == BTC_BT_2ND) { 4333 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 4334 continue; 4335 bt = &cx->bt1; 4336 } 4337 4338 is_24g = (dm->corx_map[BTC_RF_S0][i] || 4339 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_2G); 4340 is_56g = (dm->corx_map[BTC_RF_S0][i] || 4341 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_5G); 4342 4343 /* 4344 * Request Hi-LNA only when that band is co-rx and enabled. 4345 * Evaluate each band bit independently against the BT-mirrored 4346 * state so the request can still be cleared once a CO-RX band 4347 * disappears (e.g. 2.4 GHz disconnect), avoiding a latched 4348 * Hi-LNA request. 4349 */ 4350 en_24g = is_24g && en; 4351 en_56g = is_56g && en; 4352 4353 if (en_24g != (!!bt->hi_lna_rx)) 4354 _write_scbd(rtwdev, i, BTC_WSCB_BT_HILNA, en_24g); 4355 4356 if (en_56g != (!!bt->hi_lna_rx_6g)) 4357 _write_scbd(rtwdev, i, BTC_WSCB_BT_HILNA_56G, en_56g); 4358 } 4359 } 4360 4361 static void _set_rf_trx_para_v9(struct rtw89_dev *rtwdev) 4362 { 4363 struct rtw89_btc *btc = &rtwdev->btc; 4364 struct rtw89_btc_cx *cx = &btc->cx; 4365 struct rtw89_btc_wl_smap *wl_smap = &cx->wl.status.map; 4366 struct rtw89_btc_dm *dm = &btc->dm; 4367 bool bt_2r = false; 4368 u8 wl_stb_chg = 0; 4369 4370 if (wl_smap->rf_off || wl_smap->lps == BTC_LPS_RF_OFF) 4371 return; 4372 4373 /* must call after _set_halbb_btg_ctrl() */ 4374 if (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK) { 4375 wl_stb_chg = 1; 4376 if (dm->wl_btg_rx) 4377 bt_2r = true; 4378 } 4379 4380 _set_bt_corx_table(rtwdev, bt_2r); 4381 4382 if (wl_stb_chg != dm->wl_stb_chg) { 4383 dm->wl_stb_chg = wl_stb_chg; 4384 dm->ost_info.wl_btg_standby_chg = wl_stb_chg; 4385 rtwdev->chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 4386 } 4387 } 4388 4389 static void _set_rf_trx_para(struct rtw89_dev *rtwdev) 4390 { 4391 const struct rtw89_chip_info *chip = rtwdev->chip; 4392 struct rtw89_btc *btc = &rtwdev->btc; 4393 const struct rtw89_btc_ver *ver = btc->ver; 4394 struct rtw89_btc_dm *dm = &btc->dm; 4395 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4396 struct rtw89_btc_wl_role_info *r = &wl->role_info; 4397 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 4398 struct rtw89_btc_bt_link_info *b = &bt->link_info; 4399 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 4400 struct rtw89_btc_rf_trx_para_v9 para; 4401 u8 bmode = dm->tdd_bind.wl_link_mode; 4402 u8 rf_band = dm->tdd_bind.rf_band; 4403 u8 i, ul_para_num, dl_para_num; 4404 u8 mode = BTC_WLINK_NOLINK; 4405 u8 bid = BTC_BT_1ST, lv; 4406 u32 wl_stb_chg; 4407 4408 if (ver->fcxtrx == 9) { 4409 /* Early v9 need to assign UL/DL RF para at driver */ 4410 if (chip->rf_para_ulink_v9) { 4411 ul_para_num = chip->rf_para_ulink_num_v9; 4412 dl_para_num = chip->rf_para_dlink_num_v9; 4413 } else { 4414 _set_rf_trx_para_v9(rtwdev); 4415 return; 4416 } 4417 } else if ((ver->fcxtrx == 0 || ver->fcxtrx == 7 || ver->fcxtrx == 107) && 4418 chip->rf_para_ulink_v0) { 4419 ul_para_num = chip->rf_para_ulink_num_v0; 4420 dl_para_num = chip->rf_para_dlink_num_v0; 4421 } else { 4422 rtw89_warn(rtwdev, "[BTC]%s(), No rf_para for version %d\n", 4423 __func__, ver->fcxtrx); 4424 goto next; 4425 } 4426 4427 if (bmode == BTC_WLINK_NOLINK) { 4428 return; 4429 } else if (rf_band == BIT(RTW89_BAND_5G)) { 4430 mode = BTC_WLINK_V0_5G; 4431 } else if (rf_band == BIT(RTW89_BAND_2G) && bmode == BTC_WLINK_STA) { 4432 mode = BTC_WLINK_V0_2G_STA; 4433 } 4434 4435 /* decide trx_para_level */ 4436 if (btc->ant_type == BTC_ANT_SHARED) { 4437 /* fix LNA2 + TIA gain not change by GNT_BT */ 4438 if ((btc->dm.wl_btg_rx && b->link_cnt.now != 0) || 4439 dm->bt_only == 1) 4440 dm->trx_para_level = 1; /* for better BT ACI issue */ 4441 else 4442 dm->trx_para_level = 0; 4443 } else { /* non-shared antenna */ 4444 dm->trx_para_level = 5; 4445 /* modify trx_para if WK 2.4G-STA-DL + bt link */ 4446 if (b->link_cnt.now != 0 && 4447 mode == BTC_WLINK_V0_2G_STA && 4448 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */ 4449 if (wl->rssi_level == 4 && bt->rssi_level > 2) 4450 dm->trx_para_level = 6; 4451 else if (wl->rssi_level == 3 && bt->rssi_level > 3) 4452 dm->trx_para_level = 7; 4453 } 4454 } 4455 4456 lv = dm->trx_para_level; 4457 if (lv >= ul_para_num || 4458 lv >= dl_para_num) { 4459 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4460 "[BTC], %s(): invalid level_id: %d\n", 4461 __func__, lv); 4462 return; 4463 } 4464 4465 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4466 if (ver->fcxtrx == 9) { 4467 para = chip->rf_para_ulink_v9[lv]; 4468 } else { 4469 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 4470 para.wl_tx_power[i] = chip->rf_para_ulink_v0[lv].wl_tx_power; 4471 para.wl_rx_gain[i] = chip->rf_para_ulink_v0[lv].wl_rx_gain; 4472 } 4473 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) { 4474 para.bt_tx_power[i] = chip->rf_para_ulink_v0[lv].bt_tx_power; 4475 para.bt_rx_gain[i] = chip->rf_para_ulink_v0[lv].bt_rx_gain; 4476 } 4477 } 4478 } else { 4479 if (ver->fcxtrx == 9) { 4480 para = chip->rf_para_dlink_v9[lv]; 4481 } else { 4482 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 4483 para.wl_tx_power[i] = chip->rf_para_dlink_v0[lv].wl_tx_power; 4484 para.wl_rx_gain[i] = chip->rf_para_dlink_v0[lv].wl_rx_gain; 4485 } 4486 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) { 4487 para.bt_tx_power[i] = chip->rf_para_dlink_v0[lv].bt_tx_power; 4488 para.bt_rx_gain[i] = chip->rf_para_dlink_v0[lv].bt_rx_gain; 4489 } 4490 } 4491 } 4492 4493 if (dm->fddt_train) { 4494 _set_wl_rx_gain(rtwdev, 1, RTW89_PHY_0); 4495 _write_scbd(rtwdev, bid, BTC_WSCB_RXGAIN, true); 4496 } else { 4497 _set_wl_tx_power(rtwdev, para.wl_tx_power[RTW89_PHY_0], RTW89_PHY_0); 4498 _set_wl_rx_gain(rtwdev, para.wl_rx_gain[RTW89_PHY_0], RTW89_PHY_0); 4499 _set_bt_tx_power(rtwdev, true, bid, rf_band, para.bt_tx_power[BTC_BT_1ST]); 4500 _set_bt_rx_gain(rtwdev, true, bid, rf_band, para.bt_rx_gain[BTC_BT_1ST]); 4501 } 4502 4503 next: 4504 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off || 4505 wl_smap->lps == BTC_LPS_RF_OFF || mode == BTC_WLINK_V0_5G || 4506 (rtwdev->dbcc_en && r->dbcc_2g_phy != RTW89_PHY_1)) 4507 wl_stb_chg = 0; 4508 else 4509 wl_stb_chg = 1; 4510 4511 if (wl_stb_chg != dm->wl_stb_chg) { 4512 dm->wl_stb_chg = wl_stb_chg; 4513 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 4514 } 4515 } 4516 4517 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 4518 { 4519 struct rtw89_btc *btc = &rtwdev->btc; 4520 struct rtw89_btc_cx *cx = &btc->cx; 4521 struct rtw89_btc_wl_info *wl = &cx->wl; 4522 struct rtw89_btc_bt_info *bt = &cx->bt0; 4523 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4524 4525 if (wl->status.map.dhcp || wl->status.map._4way || 4526 wl->status.map.roaming || wl->status.map.transacting || 4527 wl->status.map.handshake) { 4528 cx->state_map = BTC_WLINKING; 4529 } else if (wl->status.map.scan) { /* wl scan */ 4530 if (bt_linfo->status.map.inq_pag) 4531 cx->state_map = BTC_WSCAN_BSCAN; 4532 else 4533 cx->state_map = BTC_WSCAN_BNOSCAN; 4534 } else if (wl->status.map.busy) { /* only busy */ 4535 if (bt_linfo->status.map.inq_pag) 4536 cx->state_map = BTC_WBUSY_BSCAN; 4537 else 4538 cx->state_map = BTC_WBUSY_BNOSCAN; 4539 } else { /* wl idle */ 4540 cx->state_map = BTC_WIDLE; 4541 } 4542 } 4543 4544 static u8 _get_wl_guard_bw(struct rtw89_dev *rtwdev, u8 index) 4545 { 4546 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4547 u8 guard_ch = rtwdev->chip->afh_guard_ch; 4548 u8 bw = 0; 4549 4550 /* default AFH channel sapn = center-ch +- 6MHz */ 4551 switch (index) { 4552 case RTW89_CHANNEL_WIDTH_20: 4553 if (dm->freerun || dm->fddt_train) 4554 bw = 48; 4555 else 4556 bw = 20 + guard_ch * 2; 4557 break; 4558 case RTW89_CHANNEL_WIDTH_40: 4559 bw = 40 + guard_ch * 2; 4560 break; 4561 case RTW89_CHANNEL_WIDTH_80: 4562 bw = 80 + guard_ch * 2; 4563 break; 4564 case RTW89_CHANNEL_WIDTH_160: 4565 case RTW89_CHANNEL_WIDTH_80_80: 4566 bw = 160 + guard_ch * 2; 4567 break; 4568 case RTW89_CHANNEL_WIDTH_320: 4569 bw = 320 + guard_ch * 2; 4570 break; 4571 case RTW89_CHANNEL_WIDTH_5: 4572 bw = 5 + guard_ch * 2; 4573 break; 4574 case RTW89_CHANNEL_WIDTH_10: 4575 bw = 10 + guard_ch * 2; 4576 break; 4577 default: 4578 bw = 0; 4579 break; 4580 } 4581 4582 return bw; 4583 } 4584 4585 static void _set_wl_ch_map(struct rtw89_dev *rtwdev) 4586 { 4587 struct rtw89_btc *btc = &rtwdev->btc; 4588 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4589 struct rtw89_btc_wl_afh_info *afh; 4590 u16 ch_start, ch_end, i; 4591 u8 b_group, b_pos; /* byte-group, bit-position */ 4592 u8 hwb; 4593 4594 if (wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].en && 4595 wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) { 4596 /* select wilder bw if 1+1 */ 4597 if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].bw > 4598 wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].bw) 4599 hwb = RTW89_MAC_1; 4600 else 4601 hwb = RTW89_MAC_0; 4602 } else if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) { 4603 hwb = RTW89_MAC_1; 4604 } else { 4605 hwb = RTW89_MAC_0; 4606 } 4607 4608 afh = &wl->afh_info[hwb][RTW89_BAND_2G]; 4609 4610 /* focus on WL 2.4GHz link */ 4611 if (!afh->en || afh->band != RTW89_BAND_2G) 4612 return; 4613 4614 memset(wl->ch_map, 0x0, sizeof(wl->ch_map)); 4615 memset(wl->ch_map_le, 0x0, sizeof(wl->ch_map_le)); 4616 4617 ch_start = afh->ch * 5 + 2407 - afh->bw / 2; 4618 ch_end = ch_start + afh->bw; 4619 4620 for (i = ch_start; i < ch_end; i++) { 4621 if (i < 2402 || i > 2480) 4622 continue; 4623 b_group = (i - 2402) / 8; 4624 b_pos = 7 - ((i - 2402) % 8); 4625 wl->ch_map[b_group] |= BIT(b_pos); 4626 4627 if (i % 2) /* BLE ch = even-freq (ex:2402,2404) */ 4628 continue; 4629 4630 b_group = (i - 2402) / 16; 4631 b_pos = 7 - (((i - 2402) / 2) % 8); 4632 wl->ch_map_le[b_group] |= BIT(b_pos); 4633 } 4634 } 4635 4636 static u8 _get_w2b_fbd_ch(struct rtw89_dev *rtwdev, 4637 u8 bt_fb_band, u32 wl_vco_freq, 4638 u32 *ch_lo_bound, u32 *ch_up_bound) 4639 { 4640 u32 ch_lo, ch_pup, ch_min, ch_max; 4641 u8 out_of_range = 0; 4642 s32 val_lo, val_up; 4643 u32 vco_lo_in_KHz; /* VCO pulling lower bound */ 4644 u32 vco_up_in_KHz; /* VCO pulling Upper bound */ 4645 u32 freq_start; 4646 4647 vco_lo_in_KHz = wl_vco_freq - BTC_VCO_GUARD_W2B * 1000; /* KHz */ 4648 vco_up_in_KHz = wl_vco_freq + BTC_VCO_GUARD_W2B * 1000; 4649 4650 switch (bt_fb_band) { 4651 default: 4652 case BTC_BT_B2G: /* BT 2GHz forbiddened Channel */ 4653 val_lo = vco_lo_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR; 4654 val_up = vco_up_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR; 4655 freq_start = BTC_FREQ_B2G * 1000; /* KHz */ 4656 ch_min = BTC_CH_B2G_MIN; 4657 ch_max = BTC_CH_B2G_MAX; 4658 break; 4659 case BTC_BT_B5G: /* BT 5/6GHz forbiddened Channel */ 4660 val_lo = vco_lo_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR; 4661 val_up = vco_up_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR; 4662 freq_start = BTC_FREQ_B6G * 1000; /* KHz */ 4663 ch_min = BTC_CH_B5G_MIN; 4664 ch_max = BTC_CH_B5G_MAX; 4665 break; 4666 } 4667 4668 /* Search forbiddened Channel (un-process range)*/ 4669 ch_lo = (val_lo - freq_start) / 1000; 4670 if ((val_lo - freq_start) % 1000 != 0) /* Round-UP */ 4671 ch_lo++; 4672 4673 ch_pup = (val_up - freq_start) / 1000; /* Round-down */ 4674 4675 /* Search forbiddened Channel */ 4676 if (ch_lo > ch_max || ch_pup < ch_min) { /* out-of-range -> NA */ 4677 out_of_range = 1; 4678 *ch_lo_bound = 0; 4679 *ch_up_bound = 0; 4680 } 4681 4682 if (ch_lo < ch_min) 4683 *ch_lo_bound = ch_min; 4684 else if (ch_lo <= ch_max) 4685 *ch_lo_bound = ch_lo; 4686 4687 if (ch_pup > ch_max) 4688 *ch_up_bound = ch_max; 4689 else if (ch_pup >= ch_min) 4690 *ch_up_bound = ch_pup; 4691 4692 if (bt_fb_band == BTC_BT_B5G) { /* BT ch is 8MHz-spacing for 5/6GHz */ 4693 *ch_lo_bound = *ch_lo_bound / 8; /* low-bound -> Round-down */ 4694 4695 if (*ch_up_bound % 8 != 0) /* Up-bound -> cover wider range */ 4696 *ch_up_bound = *ch_up_bound / 8 + 1; 4697 else 4698 *ch_up_bound = *ch_up_bound / 8; 4699 } 4700 4701 return out_of_range; 4702 } 4703 4704 static void _set_wl_ch_info(struct rtw89_dev *rtwdev) 4705 { 4706 static const u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 4707 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4708 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 4709 struct rtw89_btc_wl_info *wl = &cx->wl; 4710 u32 vco_freq, ch_lo = 0, ch_up = 0; 4711 u16 rf_band, freq, f_diff; 4712 u8 i, j, ch; 4713 4714 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) /* only new-PTA require setup */ 4715 return; 4716 4717 for (i = RTW89_PHY_0; i <= RTW89_PHY_1; i++) { 4718 if (wl->mlo_info.wmode[i] == RTW89_MR_WMODE_NONE) { /* no-connect */ 4719 dm->ost_info.rf_center_freq[i] = 0; 4720 dm->ost_info.fbd_group_en[i][0] = 0; 4721 dm->ost_info.fbd_group_en[i][1] = 0; 4722 dm->ost_info.fbd_group_bound[i][0] = 0; 4723 dm->ost_info.fbd_group_bound[i][1] = 0; 4724 continue; 4725 } 4726 4727 ch = wl->rf_ch_info[i].center_ch; 4728 switch (wl->rf_ch_info[i].band) { 4729 case RTW89_BAND_2G: 4730 default: 4731 rf_band = 0; 4732 if (ch == 14) 4733 freq = BTC_FREQ_W2G_CH14; 4734 else 4735 freq = BTC_FREQ_W2G + (ch - 1) * 5; 4736 vco_freq = freq * 1000 * BTC_LO_2G_NMR / BTC_LO_2G_DNM; 4737 break; 4738 case RTW89_BAND_5G: 4739 rf_band = BIT(15); 4740 freq = BTC_FREQ_W5G + (ch - 1) * 5; 4741 vco_freq = freq * 1000 * BTC_LO_5G_NMR / BTC_LO_5G_DNM; 4742 break; 4743 case RTW89_BAND_6G: 4744 rf_band = BIT(15); 4745 freq = BTC_FREQ_W6G + (ch - 1) * 5; 4746 vco_freq = freq * 1000 * BTC_LO_6G_NMR / BTC_LO_6G_DNM; 4747 break; 4748 } 4749 4750 dm->ost_info.rf_center_freq[i] = rf_band + freq; 4751 4752 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) { 4753 /* no WL->BT forbidden channel */ 4754 if (_get_w2b_fbd_ch(rtwdev, j, vco_freq, &ch_lo, &ch_up)) { 4755 dm->ost_info.fbd_group_en[i][j] = j << 1; 4756 dm->ost_info.fbd_group_bound[i][j] = 0; 4757 continue; 4758 } 4759 4760 dm->ost_info.fbd_group_en[i][j] = (j << 1) + 0x1; 4761 dm->ost_info.fbd_group_bound[i][j] = (ch_up << 8) + ch_lo; 4762 } 4763 } 4764 4765 for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) { 4766 for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) { 4767 /* 4768 * If WL & BT share same ANT/Path, set freq-diff > 2GHz, 4769 * because TDD will always run in 5/6GHz band. 4770 * Otherwise, the frq-diff thres is decided by the RF 4771 * out-of-channel rejection capability. 4772 */ 4773 if (dm->ant_xmap[i][j]) 4774 f_diff = 0x7ff; /* 2047MHz */ 4775 else 4776 f_diff = rtwdev->chip->fdd_iso_freq; 4777 4778 dm->ost_info.freq_diff_thres[path_hwb[i]][j] = f_diff; 4779 } 4780 } 4781 } 4782 4783 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 4784 { 4785 struct rtw89_btc *btc = &rtwdev->btc; 4786 struct rtw89_btc_cx *cx = &btc->cx; 4787 struct rtw89_btc_wl_info *wl = &cx->wl; 4788 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4789 struct rtw89_btc_wl_rlink *rlink; 4790 u8 h2c_func, hwb, bt_link_chg; 4791 u8 i, j, sz, bw; 4792 u8 buf[4]; 4793 4794 if (btc->manual_ctrl || wl->status.map.rf_off || 4795 (wl->status.val & btc_scanning_map.val)) 4796 return; 4797 4798 memset(wl->afh_info, 0, sizeof(wl->afh_info)); 4799 4800 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) { 4801 /* skip HW-Band if no fdd/fdd bind */ 4802 if ((!(btc->dm.tdd_bind.wl_hwb_sel & BIT(j))) && 4803 (!(btc->dm.fdd_bind.wl_hwb_sel & BIT(j)))) 4804 continue; 4805 4806 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 4807 rlink = &wl_rinfo->rlink[i][j]; 4808 4809 /* Skip no-active case */ 4810 if (!rlink->connected || !rlink->active || 4811 rlink->rf_band >= RTW89_BAND_NUM) 4812 continue; 4813 4814 /* In addition to AP/P2P, skip if same-rf-band*/ 4815 if (wl->afh_info[j][rlink->rf_band].en && 4816 (rlink->role != RTW89_WIFI_ROLE_AP && 4817 rlink->role != RTW89_WIFI_ROLE_P2P_GO && 4818 rlink->role != RTW89_WIFI_ROLE_P2P_CLIENT)) 4819 continue; 4820 4821 bw = _get_wl_guard_bw(rtwdev, rlink->bw); 4822 wl->afh_info[j][rlink->rf_band].en = 1; 4823 wl->afh_info[j][rlink->rf_band].ch = rlink->ch; 4824 wl->afh_info[j][rlink->rf_band].bw = bw; 4825 wl->afh_info[j][rlink->rf_band].band = rlink->rf_band; 4826 } 4827 } 4828 4829 for (j = RTW89_BAND_2G; j < RTW89_BAND_NUM; j++) { 4830 /* skip non-2.4GHz if BT is 2.4GHz only*/ 4831 if (!(rtwdev->chip->para_ver & BTC_FEAT_BT_6G)) { 4832 if (j != RTW89_BAND_2G) 4833 continue; 4834 sz = 3; 4835 } else { 4836 sz = 4; 4837 } 4838 4839 if (wl->afh_info[RTW89_MAC_0][j].en && 4840 wl->afh_info[RTW89_MAC_1][j].en) { 4841 /* select wilder bw if 1+1 */ 4842 if (wl->afh_info[RTW89_MAC_1][j].bw > 4843 wl->afh_info[RTW89_MAC_0][j].bw) 4844 hwb = RTW89_MAC_1; 4845 else 4846 hwb = RTW89_MAC_0; 4847 } else if (wl->afh_info[RTW89_MAC_1][j].en) { 4848 hwb = RTW89_MAC_1; 4849 } else { 4850 hwb = RTW89_MAC_0; 4851 } 4852 4853 if (j == RTW89_BAND_2G) { 4854 if (cx->bt0.link_info.link_cnt.chg || 4855 cx->bt1.link_info.link_cnt.chg) 4856 bt_link_chg = 1; 4857 else 4858 bt_link_chg = 0; 4859 } else { 4860 if (cx->bt0.link_info_56g.link_cnt.chg || 4861 cx->bt1.link_info_56g.link_cnt.chg) 4862 bt_link_chg = 1; 4863 else 4864 bt_link_chg = 0; 4865 } 4866 4867 /* return if no-afh-info-change/no wl-bt link change */ 4868 if (!memcmp(&wl->afh_info_last[hwb][j], 4869 &wl->afh_info[hwb][j], 4870 sizeof(struct rtw89_btc_wl_afh_info)) && 4871 !bt_link_chg && 4872 !wl->link_mode_chg) 4873 continue; 4874 4875 memcpy(&wl->afh_info_last[hwb][j], 4876 &wl->afh_info[hwb][j], 4877 sizeof(struct rtw89_btc_wl_afh_info)); 4878 4879 buf[0] = wl->afh_info[hwb][j].en; 4880 buf[1] = wl->afh_info[hwb][j].ch; 4881 buf[2] = wl->afh_info[hwb][j].bw; 4882 buf[3] = wl->afh_info[hwb][j].band; 4883 4884 h2c_func = SET_BT_WL_CH_INFO; 4885 if (cx->bt0.enable.now) 4886 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz); 4887 4888 /* send mailbox to 2nd-BT if exist */ 4889 if (cx->bt1.enable.now) { 4890 h2c_func |= BT_H2C_FUNC_BT2ND; 4891 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz); 4892 } 4893 4894 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4895 "[BTC], %s(): en=%d, ch=%d, bw=%d, rf_band=%d\n", 4896 __func__, buf[0], buf[1], buf[2], buf[3]); 4897 4898 wl->wcnt[BTC_WCNT_CH_UPDATE]++; 4899 4900 /* ToDo: Remove if BT update new-define to support 6GHz */ 4901 if (j == RTW89_BAND_2G) 4902 break; 4903 } 4904 4905 /* for AFH map display in coex log */ 4906 _set_wl_ch_map(rtwdev); 4907 4908 /* set HWB center-ch/forbidden group to ost_info for CR setup in FW */ 4909 _set_wl_ch_info(rtwdev); 4910 } 4911 4912 static bool _check_freerun(struct rtw89_dev *rtwdev) 4913 { 4914 struct rtw89_btc *btc = &rtwdev->btc; 4915 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4916 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 4917 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4918 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4919 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 4920 struct rtw89_btc_module *md = &btc->mdinfo; 4921 4922 if (btc->ant_type == BTC_ANT_SHARED) { 4923 btc->dm.trx_para_level = 0; 4924 return false; 4925 } 4926 4927 /* The below is dedicated antenna case */ 4928 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) { 4929 btc->dm.trx_para_level = 5; 4930 return true; 4931 } 4932 4933 if (bt_linfo->link_cnt.now == 0) { 4934 btc->dm.trx_para_level = 5; 4935 return true; 4936 } 4937 4938 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 4939 btc->dm.trx_para_level = 5; 4940 return true; 4941 } 4942 4943 /* TODO get isolation by BT psd */ 4944 if (md->ant.isolation >= BTC_FREERUN_ANTISO_MIN) { 4945 btc->dm.trx_para_level = 5; 4946 return true; 4947 } 4948 4949 if (!wl->status.map.busy) {/* wl idle -> freerun */ 4950 btc->dm.trx_para_level = 5; 4951 return true; 4952 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 4953 btc->dm.trx_para_level = 0; 4954 return false; 4955 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4956 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 4957 btc->dm.trx_para_level = 6; 4958 return true; 4959 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 4960 btc->dm.trx_para_level = 7; 4961 return true; 4962 } 4963 btc->dm.trx_para_level = 0; 4964 return false; 4965 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 4966 if (bt_linfo->rssi > 28) { 4967 btc->dm.trx_para_level = 6; 4968 return true; 4969 } 4970 } 4971 4972 btc->dm.trx_para_level = 0; 4973 return false; 4974 } 4975 4976 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 4977 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 4978 #define _tdma_set_rxflctrl(btc, rxflc) ({(btc)->dm.tdma.rxflctrl = rxflc; }) 4979 #define _tdma_set_txflctrl(btc, txflc) ({(btc)->dm.tdma.txflctrl = txflc; }) 4980 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 4981 4982 struct btc_btinfo_lb2 { 4983 u8 connect: 1; 4984 u8 sco_busy: 1; 4985 u8 inq_pag: 1; 4986 u8 acl_busy: 1; 4987 u8 hfp: 1; 4988 u8 hid: 1; 4989 u8 a2dp: 1; 4990 u8 pan: 1; 4991 }; 4992 4993 struct btc_btinfo_lb3 { 4994 u8 retry: 4; 4995 u8 cqddr: 1; 4996 u8 inq: 1; 4997 u8 mesh_busy: 1; 4998 u8 pag: 1; 4999 }; 5000 5001 struct btc_btinfo_hb0 { 5002 s8 rssi; 5003 }; 5004 5005 struct btc_btinfo_hb1 { 5006 u8 ble_connect: 1; 5007 u8 reinit: 1; 5008 u8 relink: 1; 5009 u8 igno_wl: 1; 5010 u8 voice: 1; 5011 u8 ble_scan: 1; 5012 u8 role_sw: 1; 5013 u8 multi_link: 1; 5014 }; 5015 5016 struct btc_btinfo_hb2 { 5017 u8 pan_active: 1; 5018 u8 afh_update: 1; 5019 u8 a2dp_active: 1; 5020 u8 slave: 1; 5021 u8 hid_slot: 2; 5022 u8 hid_cnt: 2; 5023 }; 5024 5025 struct btc_btinfo_hb3 { 5026 u8 a2dp_bitpool: 6; 5027 u8 tx_3m: 1; 5028 u8 a2dp_sink: 1; 5029 }; 5030 5031 union btc_btinfo { 5032 u8 val; 5033 struct btc_btinfo_lb2 lb2; 5034 struct btc_btinfo_lb3 lb3; 5035 struct btc_btinfo_hb0 hb0; 5036 struct btc_btinfo_hb1 hb1; 5037 struct btc_btinfo_hb2 hb2; 5038 struct btc_btinfo_hb3 hb3; 5039 }; 5040 5041 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 5042 enum btc_reason_and_action action) 5043 { 5044 const struct rtw89_chip_info *chip = rtwdev->chip; 5045 5046 chip->ops->btc_set_policy(rtwdev, policy_type); 5047 _fw_set_policy(rtwdev, policy_type, action); 5048 } 5049 5050 static void _set_tdma_bind(struct rtw89_dev *rtwdev, bool tdma_on) 5051 { 5052 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5053 struct rtw89_btc_bind_info *bind; 5054 u8 null_role = RTW89_WIFI_ROLE_STATION; 5055 u8 bt_sel; 5056 5057 if (dm->tdd_en) 5058 bind = &dm->tdd_bind; /* tdd = 1 && fdd = 0 or 1 */ 5059 else 5060 bind = &dm->fdd_bind; /* tdd = 0 && fdd = 1 */ 5061 5062 if (bind->bt_sel >= (BIT(BTC_BT_1ST) | BIT(BTC_BT_2ND))) 5063 bt_sel = BTC_ALL_BT; 5064 else if (bind->bt_sel == BIT(BTC_BT_2ND)) 5065 bt_sel = BTC_BT_2ND; 5066 else 5067 bt_sel = BTC_BT_1ST; 5068 5069 /* notify BT TDMA on/off by scoreboard for ACL/Scan schedule */ 5070 _write_scbd(rtwdev, bt_sel, BTC_WSCB_TDMA, tdma_on); 5071 5072 /* 5073 * set hwb/bt bind to TDMA policy parameter 5074 * FW-BTC will setup related hwbx vs. BTx coex tables by slot toggle 5075 * ex: HWb0 + BT0 + BT1, HWB0-BT0/HWB0-BT1 coex by WL/BT slot toggle 5076 */ 5077 dm->tdma.bind = ((bind->bt_sel & 0xf) << 4) + (bind->wl_hwb_sel & 0x3); 5078 if (dm->tdd_en) 5079 dm->tdma.bind |= BIT(2); 5080 if (dm->fdd_en) 5081 dm->tdma.bind |= BIT(3); 5082 if (rtwdev->btc.ver->fcxtdma != 8) 5083 dm->tdma.bind |= 0; 5084 5085 /* set Null-tx role for 2 HW-BAND TDMA (MLMR) */ 5086 if (!dm->eslot_ctrl.en && dm->tdma.rxflctrl && 5087 (bind->wl_hwb_sel == (BIT(RTW89_PHY_1) | BIT(RTW89_PHY_0)))) { 5088 null_role = (null_role << 4) + null_role; 5089 _tdma_set_flctrl_role(&rtwdev->btc, null_role); 5090 } 5091 } 5092 5093 #define BTC_B1_MAX 250 /* unit ms */ 5094 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 5095 { 5096 struct rtw89_btc *btc = &rtwdev->btc; 5097 struct rtw89_btc_dm *dm = &btc->dm; 5098 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 5099 u8 type; 5100 u32 tbl_w1, tbl_b1, tbl_b4; 5101 bool tdma_on = false; 5102 5103 if (btc->ant_type == BTC_ANT_SHARED) { 5104 if (btc->cx.wl.status.map._4way) 5105 tbl_w1 = cxtbl[1]; 5106 else 5107 tbl_w1 = cxtbl[8]; 5108 tbl_b1 = cxtbl[3]; 5109 tbl_b4 = cxtbl[3]; 5110 } else { 5111 tbl_w1 = cxtbl[16]; 5112 tbl_b1 = cxtbl[17]; 5113 tbl_b4 = cxtbl[17]; 5114 } 5115 5116 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 5117 btc->bt_req_en = false; 5118 5119 switch (type) { 5120 case BTC_CXP_USERDEF0: 5121 *t = t_def[CXTD_OFF]; 5122 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5123 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5124 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5125 btc->update_policy_force = true; 5126 break; 5127 case BTC_CXP_OFF: /* TDMA off */ 5128 tdma_on = false; 5129 *t = t_def[CXTD_OFF]; 5130 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5131 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5132 5133 switch (policy_type) { 5134 case BTC_CXP_OFF_BT: 5135 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5136 break; 5137 case BTC_CXP_OFF_WL: 5138 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 5139 break; 5140 case BTC_CXP_OFF_EQ0: 5141 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 5142 break; 5143 case BTC_CXP_OFF_EQ1: 5144 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 5145 break; 5146 case BTC_CXP_OFF_EQ2: 5147 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 5148 break; 5149 case BTC_CXP_OFF_EQ3: 5150 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 5151 break; 5152 case BTC_CXP_OFF_BWB0: 5153 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5154 break; 5155 case BTC_CXP_OFF_BWB1: 5156 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5157 break; 5158 case BTC_CXP_OFF_BWB3: 5159 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5160 break; 5161 } 5162 break; 5163 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 5164 tdma_on = false; 5165 *t = t_def[CXTD_OFF_B2]; 5166 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5167 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5168 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO); 5169 5170 switch (policy_type) { 5171 case BTC_CXP_OFFB_BWB0: 5172 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5173 break; 5174 case BTC_CXP_OFFB_BWB1: 5175 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5176 break; 5177 case BTC_CXP_OFFB_BWB2: 5178 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 5179 break; 5180 case BTC_CXP_OFFB_BWB3: 5181 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5182 break; 5183 case BTC_CXP_OFFB_BWB4: 5184 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5185 break; 5186 } 5187 break; 5188 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 5189 btc->bt_req_en = true; 5190 tdma_on = true; 5191 *t = t_def[CXTD_OFF_EXT]; 5192 switch (policy_type) { 5193 case BTC_CXP_OFFE_DEF: 5194 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 5195 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 5196 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5197 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5198 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5199 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5200 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5201 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5202 break; 5203 case BTC_CXP_OFFE_DEF2: 5204 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 5205 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5206 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5207 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5208 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5209 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5210 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5211 break; 5212 } 5213 break; 5214 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 5215 tdma_on = true; 5216 *t = t_def[CXTD_FIX]; 5217 switch (policy_type) { 5218 case BTC_CXP_FIX_TD3030: 5219 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5220 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5221 break; 5222 case BTC_CXP_FIX_TD5050: 5223 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5224 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5225 break; 5226 case BTC_CXP_FIX_TD2030: 5227 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5228 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5229 break; 5230 case BTC_CXP_FIX_TD4010: 5231 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 5232 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5233 break; 5234 case BTC_CXP_FIX_TD4010ISO: 5235 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 5236 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5237 break; 5238 case BTC_CXP_FIX_TD4010ISO_DL: 5239 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 5240 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 5241 break; 5242 case BTC_CXP_FIX_TD4010ISO_UL: 5243 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 5244 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 5245 break; 5246 case BTC_CXP_FIX_TD7010: 5247 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 5248 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5249 break; 5250 case BTC_CXP_FIX_TD2060: 5251 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5252 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5253 break; 5254 case BTC_CXP_FIX_TD3060: 5255 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5256 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5257 break; 5258 case BTC_CXP_FIX_TD2080: 5259 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5260 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5261 break; 5262 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 5263 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5264 tbl_w1, SLOT_ISO); 5265 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5266 tbl_b1, SLOT_MIX); 5267 break; 5268 } 5269 break; 5270 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 5271 tdma_on = true; 5272 *t = t_def[CXTD_PFIX]; 5273 if (btc->cx.wl.role_info.role_map[RTW89_MAC_0] & BIT(RTW89_WIFI_ROLE_AP)) 5274 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 5275 5276 switch (policy_type) { 5277 case BTC_CXP_PFIX_TD3030: 5278 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5279 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5280 break; 5281 case BTC_CXP_PFIX_TD5050: 5282 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5283 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5284 break; 5285 case BTC_CXP_PFIX_TD2030: 5286 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5287 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5288 break; 5289 case BTC_CXP_PFIX_TD2060: 5290 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5291 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5292 break; 5293 case BTC_CXP_PFIX_TD3070: 5294 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5295 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5296 break; 5297 case BTC_CXP_PFIX_TD2080: 5298 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5299 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5300 break; 5301 } 5302 break; 5303 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 5304 tdma_on = true; 5305 *t = t_def[CXTD_AUTO]; 5306 switch (policy_type) { 5307 case BTC_CXP_AUTO_TD50B1: 5308 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5309 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5310 break; 5311 case BTC_CXP_AUTO_TD60B1: 5312 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5313 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5314 break; 5315 case BTC_CXP_AUTO_TD20B1: 5316 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5317 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5318 break; 5319 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 5320 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5321 tbl_w1, SLOT_ISO); 5322 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5323 tbl_b1, SLOT_MIX); 5324 break; 5325 } 5326 break; 5327 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 5328 tdma_on = true; 5329 *t = t_def[CXTD_PAUTO]; 5330 switch (policy_type) { 5331 case BTC_CXP_PAUTO_TD50B1: 5332 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5333 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5334 break; 5335 case BTC_CXP_PAUTO_TD60B1: 5336 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5337 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5338 break; 5339 case BTC_CXP_PAUTO_TD20B1: 5340 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5341 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5342 break; 5343 case BTC_CXP_PAUTO_TDW1B1: 5344 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5345 tbl_w1, SLOT_ISO); 5346 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5347 tbl_b1, SLOT_MIX); 5348 break; 5349 } 5350 break; 5351 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 5352 tdma_on = true; 5353 *t = t_def[CXTD_AUTO2]; 5354 switch (policy_type) { 5355 case BTC_CXP_AUTO2_TD3050: 5356 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5357 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5358 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5359 break; 5360 case BTC_CXP_AUTO2_TD3070: 5361 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5362 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5363 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5364 break; 5365 case BTC_CXP_AUTO2_TD5050: 5366 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5367 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5368 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5369 break; 5370 case BTC_CXP_AUTO2_TD6060: 5371 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5372 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5373 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5374 break; 5375 case BTC_CXP_AUTO2_TD2080: 5376 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5377 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5378 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5379 break; 5380 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 5381 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5382 tbl_w1, SLOT_ISO); 5383 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5384 tbl_b4, SLOT_MIX); 5385 break; 5386 } 5387 break; 5388 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 5389 tdma_on = true; 5390 *t = t_def[CXTD_PAUTO2]; 5391 switch (policy_type) { 5392 case BTC_CXP_PAUTO2_TD3050: 5393 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5394 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5395 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5396 break; 5397 case BTC_CXP_PAUTO2_TD3070: 5398 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5399 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5400 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5401 break; 5402 case BTC_CXP_PAUTO2_TD5050: 5403 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5404 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5405 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5406 break; 5407 case BTC_CXP_PAUTO2_TD6060: 5408 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5409 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5410 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5411 break; 5412 case BTC_CXP_PAUTO2_TD2080: 5413 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5414 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5415 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5416 break; 5417 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 5418 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5419 tbl_w1, SLOT_ISO); 5420 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5421 tbl_b4, SLOT_MIX); 5422 break; 5423 } 5424 break; 5425 } 5426 _set_tdma_bind(rtwdev, tdma_on); 5427 } 5428 EXPORT_SYMBOL(rtw89_btc_set_policy); 5429 5430 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 5431 { 5432 struct rtw89_btc *btc = &rtwdev->btc; 5433 struct rtw89_btc_dm *dm = &btc->dm; 5434 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 5435 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 5436 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt0.link_info.hid_desc; 5437 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt0.link_info.hfp_desc; 5438 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5439 u8 type, null_role; 5440 u32 tbl_w1, tbl_b1, tbl_b4; 5441 bool tdma_on = false; 5442 u16 dur_1 = 0, dur_2; 5443 5444 if (wl->status.map.lps) { 5445 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 5446 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 5447 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5448 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5449 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5450 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5451 } 5452 5453 type = FIELD_GET(BTC_CXP_MASK, policy_type); 5454 5455 if (btc->ant_type == BTC_ANT_SHARED) { 5456 if (btc->cx.wl.status.map._4way) 5457 tbl_w1 = cxtbl[1]; 5458 else if (hid->exist && hid->type == BTC_HID_218) 5459 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 5460 else 5461 tbl_w1 = cxtbl[8]; 5462 5463 if (dm->leak_ap && 5464 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 5465 tbl_b1 = cxtbl[3]; 5466 tbl_b4 = cxtbl[3]; 5467 } else if (hid->exist && hid->type == BTC_HID_218) { 5468 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 5469 tbl_b4 = cxtbl[4]; 5470 } else { 5471 tbl_b1 = cxtbl[2]; 5472 tbl_b4 = cxtbl[2]; 5473 } 5474 } else { 5475 tbl_b1 = cxtbl[17]; 5476 tbl_b4 = cxtbl[17]; 5477 5478 if (wl->bg_mode[RTW89_MAC_0]) 5479 tbl_w1 = cxtbl[8]; 5480 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) && 5481 hid->exist) 5482 tbl_w1 = cxtbl[19]; 5483 else 5484 tbl_w1 = cxtbl[16]; 5485 } 5486 5487 switch (type) { 5488 case BTC_CXP_USERDEF0: 5489 btc->update_policy_force = true; 5490 *t = t_def[CXTD_OFF]; 5491 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5492 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5493 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5494 break; 5495 case BTC_CXP_OFF: /* TDMA off */ 5496 tdma_on = false; 5497 *t = t_def[CXTD_OFF]; 5498 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5499 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5500 5501 switch (policy_type) { 5502 case BTC_CXP_OFF_BT: 5503 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5504 break; 5505 case BTC_CXP_OFF_WL: 5506 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 5507 break; 5508 case BTC_CXP_OFF_WL2: 5509 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 5510 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 5511 break; 5512 case BTC_CXP_OFF_EQ0: 5513 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 5514 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 5515 break; 5516 case BTC_CXP_OFF_EQ1: 5517 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 5518 break; 5519 case BTC_CXP_OFF_EQ2: 5520 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 5521 break; 5522 case BTC_CXP_OFF_EQ3: 5523 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); 5524 break; 5525 case BTC_CXP_OFF_EQ4: 5526 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); 5527 break; 5528 case BTC_CXP_OFF_EQ5: 5529 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); 5530 break; 5531 case BTC_CXP_OFF_BWB0: 5532 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5533 break; 5534 case BTC_CXP_OFF_BWB1: 5535 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5536 break; 5537 case BTC_CXP_OFF_BWB2: 5538 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 5539 break; 5540 case BTC_CXP_OFF_BWB3: 5541 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5542 break; 5543 default: 5544 break; 5545 } 5546 break; 5547 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 5548 tdma_on = false; 5549 *t = t_def[CXTD_OFF_B2]; 5550 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5551 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5552 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO); 5553 5554 switch (policy_type) { 5555 case BTC_CXP_OFFB_BWB0: 5556 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 5557 break; 5558 case BTC_CXP_OFFB_BWB1: 5559 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 5560 break; 5561 case BTC_CXP_OFFB_BWB2: 5562 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 5563 break; 5564 case BTC_CXP_OFFB_BWB3: 5565 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 5566 break; 5567 case BTC_CXP_OFFB_BWB4: 5568 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 5569 break; 5570 } 5571 break; 5572 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 5573 tdma_on = true; 5574 *t = t_def[CXTD_OFF_EXT]; 5575 5576 /* To avoid wl-s0 tx break by hid/hfp tx */ 5577 if (hid->exist || hfp->exist) 5578 tbl_w1 = cxtbl[16]; 5579 5580 if (dm->eslot_ctrl.en) { 5581 null_role = u8_encode_bits(dm->eslot_ctrl.nulltx_role1, 0x0f) | 5582 u8_encode_bits(dm->eslot_ctrl.nulltx_role2, 0xf0); 5583 _tdma_set_flctrl_role(btc, null_role); 5584 _tdma_set_rxflctrl(btc, 1); 5585 _tdma_set_txflctrl(btc, 1); 5586 /* Set Null-Tx time-tick by E2G duration */ 5587 dm->eslot_ctrl.nulltx_pre_time = 5; /* TODO: BIS COEX */ 5588 dur_1 = dm->eslot_ctrl.nulltx_pre_time; 5589 } 5590 5591 dur_2 = dm->e2g_slot_limit; 5592 5593 switch (policy_type) { 5594 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */ 5595 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_ISO); 5596 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5597 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5598 _slot_set_dur(btc, CXST_EBT, dur_2); 5599 break; 5600 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */ 5601 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_ISO); 5602 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5603 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5604 _slot_set_dur(btc, CXST_EBT, dur_2); 5605 break; 5606 case BTC_CXP_OFFE_DEF: 5607 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 5608 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 5609 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5610 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5611 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5612 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5613 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5614 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5615 _slot_set_dur(btc, CXST_EBT, dur_2); 5616 break; 5617 case BTC_CXP_OFFE_DEF2: 5618 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 5619 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5620 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5621 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 5622 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5623 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 5624 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 5625 _slot_set_dur(btc, CXST_EBT, dur_2); 5626 break; 5627 case BTC_CXP_OFFE_2GBWMIXB: 5628 if (a2dp->exist) 5629 _slot_set(btc, CXST_E2G, dur_1, cxtbl[2], SLOT_MIX); 5630 else 5631 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_MIX); 5632 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40), 5633 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 5634 _slot_set_dur(btc, CXST_EBT, dur_2); 5635 break; 5636 case BTC_CXP_OFFE_WL: /* for 4-way */ 5637 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_MIX); 5638 _slot_set(btc, CXST_EBT, dur_1, cxtbl[1], SLOT_MIX); 5639 break; 5640 default: 5641 break; 5642 } 5643 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 5644 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 5645 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 5646 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 5647 break; 5648 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 5649 tdma_on = true; 5650 *t = t_def[CXTD_FIX]; 5651 5652 switch (policy_type) { 5653 case BTC_CXP_FIX_TD3030: 5654 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5655 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5656 break; 5657 case BTC_CXP_FIX_TD5050: 5658 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5659 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5660 break; 5661 case BTC_CXP_FIX_TD2030: 5662 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5663 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5664 break; 5665 case BTC_CXP_FIX_TD4010: 5666 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 5667 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5668 break; 5669 case BTC_CXP_FIX_TD4010ISO: 5670 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 5671 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5672 break; 5673 case BTC_CXP_FIX_TD4010ISO_DL: 5674 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 5675 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 5676 break; 5677 case BTC_CXP_FIX_TD4010ISO_UL: 5678 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 5679 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 5680 break; 5681 case BTC_CXP_FIX_TD7010: 5682 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 5683 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 5684 break; 5685 case BTC_CXP_FIX_TD2060: 5686 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5687 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5688 break; 5689 case BTC_CXP_FIX_TD3060: 5690 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5691 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5692 break; 5693 case BTC_CXP_FIX_TD2080: 5694 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5695 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5696 break; 5697 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 5698 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5699 tbl_w1, SLOT_ISO); 5700 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5701 tbl_b1, SLOT_MIX); 5702 break; 5703 default: 5704 break; 5705 } 5706 break; 5707 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 5708 tdma_on = true; 5709 *t = t_def[CXTD_PFIX]; 5710 5711 switch (policy_type) { 5712 case BTC_CXP_PFIX_TD3030: 5713 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5714 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5715 break; 5716 case BTC_CXP_PFIX_TD5050: 5717 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5718 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 5719 break; 5720 case BTC_CXP_PFIX_TD2030: 5721 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5722 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 5723 break; 5724 case BTC_CXP_PFIX_TD2060: 5725 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5726 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5727 break; 5728 case BTC_CXP_PFIX_TD3070: 5729 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5730 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 5731 break; 5732 case BTC_CXP_PFIX_TD2080: 5733 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5734 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 5735 break; 5736 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 5737 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5738 tbl_w1, SLOT_ISO); 5739 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5740 tbl_b1, SLOT_MIX); 5741 break; 5742 default: 5743 break; 5744 } 5745 break; 5746 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 5747 tdma_on = true; 5748 *t = t_def[CXTD_AUTO]; 5749 5750 switch (policy_type) { 5751 case BTC_CXP_AUTO_TD50B1: 5752 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5753 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5754 break; 5755 case BTC_CXP_AUTO_TD60B1: 5756 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5757 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5758 break; 5759 case BTC_CXP_AUTO_TD20B1: 5760 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5761 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5762 break; 5763 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 5764 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5765 tbl_w1, SLOT_ISO); 5766 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5767 tbl_b1, SLOT_MIX); 5768 break; 5769 default: 5770 break; 5771 } 5772 break; 5773 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 5774 tdma_on = true; 5775 *t = t_def[CXTD_PAUTO]; 5776 5777 switch (policy_type) { 5778 case BTC_CXP_PAUTO_TD50B1: 5779 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5780 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5781 break; 5782 case BTC_CXP_PAUTO_TD60B1: 5783 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5784 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5785 break; 5786 case BTC_CXP_PAUTO_TD20B1: 5787 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5788 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5789 break; 5790 case BTC_CXP_PAUTO_TDW1B1: 5791 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5792 tbl_w1, SLOT_ISO); 5793 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5794 tbl_b1, SLOT_MIX); 5795 break; 5796 default: 5797 break; 5798 } 5799 break; 5800 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 5801 tdma_on = true; 5802 *t = t_def[CXTD_AUTO2]; 5803 5804 switch (policy_type) { 5805 case BTC_CXP_AUTO2_TD3050: 5806 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5807 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5808 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5809 break; 5810 case BTC_CXP_AUTO2_TD3070: 5811 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5812 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5813 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5814 break; 5815 case BTC_CXP_AUTO2_TD5050: 5816 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5817 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5818 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5819 break; 5820 case BTC_CXP_AUTO2_TD6060: 5821 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5822 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5823 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5824 break; 5825 case BTC_CXP_AUTO2_TD2080: 5826 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5827 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5828 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5829 break; 5830 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 5831 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5832 tbl_w1, SLOT_ISO); 5833 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5834 tbl_b1, SLOT_MIX); 5835 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5836 tbl_b4, SLOT_MIX); 5837 break; 5838 default: 5839 break; 5840 } 5841 break; 5842 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 5843 tdma_on = true; 5844 *t = t_def[CXTD_PAUTO2]; 5845 5846 switch (policy_type) { 5847 case BTC_CXP_PAUTO2_TD3050: 5848 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5849 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5850 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5851 break; 5852 case BTC_CXP_PAUTO2_TD3070: 5853 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 5854 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5855 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 5856 break; 5857 case BTC_CXP_PAUTO2_TD5050: 5858 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 5859 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5860 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 5861 break; 5862 case BTC_CXP_PAUTO2_TD6060: 5863 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 5864 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5865 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 5866 break; 5867 case BTC_CXP_PAUTO2_TD2080: 5868 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 5869 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 5870 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 5871 break; 5872 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 5873 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 5874 tbl_w1, SLOT_ISO); 5875 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 5876 tbl_b1, SLOT_MIX); 5877 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 5878 tbl_b4, SLOT_MIX); 5879 break; 5880 default: 5881 break; 5882 } 5883 break; 5884 } 5885 5886 /* enter leak_slot after each null-1 */ 5887 if (dm->leak_ap && dm->tdma.leak_n > 1) 5888 _tdma_set_lek(btc, 1); 5889 5890 if (dm->tdma_instant_excute || 5891 dm->error.map.tdma_no_sync || 5892 dm->error.map.slot_no_sync || 5893 dm->lps_ctrl_change) { 5894 btc->dm.tdma.option_ctrl |= BIT(0); 5895 btc->update_policy_force = true; 5896 } 5897 5898 if (btc->cli_h2c_cmd) 5899 btc->update_policy_force = true; 5900 5901 _set_tdma_bind(rtwdev, tdma_on); 5902 } 5903 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 5904 5905 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 5906 u8 tx_val, u8 rx_val) 5907 { 5908 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 5909 struct rtw89_mac_ax_plt plt; 5910 5911 plt.tx = tx_val; 5912 plt.rx = rx_val; 5913 5914 if (rtwdev->btc.ver->fwlrole == 8) { 5915 plt.band = wl->pta_req_mac; 5916 if (wl->bt_polut_type[plt.band] == tx_val) 5917 return; 5918 5919 wl->bt_polut_type[plt.band] = tx_val; 5920 rtw89_mac_cfg_plt(rtwdev, &plt); 5921 } else { 5922 plt.band = RTW89_MAC_0; 5923 5924 if (phy_map & BTC_PHY_0) 5925 rtw89_mac_cfg_plt(rtwdev, &plt); 5926 5927 if (!rtwdev->dbcc_en) 5928 return; 5929 5930 plt.band = RTW89_MAC_1; 5931 if (phy_map & BTC_PHY_1) 5932 rtw89_mac_cfg_plt(rtwdev, &plt); 5933 } 5934 } 5935 5936 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 5937 u8 phy_map, u8 type) 5938 { 5939 struct rtw89_btc *btc = &rtwdev->btc; 5940 struct rtw89_btc_cx *cx = &btc->cx; 5941 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5942 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5943 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type); 5944 struct rtw89_btc_dm *dm = &btc->dm; 5945 u8 gwl = BTC_GNT_HW, gwl0, gwl1, gbt; 5946 bool cx_ctrl; 5947 5948 if (btc->cli_h2c_cmd || wl_rinfo->dbcc_chg || 5949 dm->run_reason == BTC_RSN_NTFY_POWEROFF || 5950 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 5951 dm->run_reason == BTC_RSN_CMD_SET_COEX) 5952 force_exec = FC_EXEC; 5953 5954 if (wl_rinfo->link_mode[RTW89_MAC_0] != BTC_WLINK_DB_MCC && 5955 btc->dm.wl_btg_rx == 2) 5956 force_exec = FC_EXEC; 5957 5958 if (!force_exec && ant_path_type == dm->set_ant_path) { 5959 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5960 "[BTC], %s(): return by no change!!\n", 5961 __func__); 5962 return; 5963 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 5964 wl->rfk_info.state != BTC_WRFK_STOP) { 5965 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5966 "[BTC], %s(): return by wl rfk!!\n", __func__); 5967 return; 5968 } 5969 5970 dm->set_ant_path = ant_path_type; 5971 5972 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5973 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 5974 __func__, phy_map, dm->set_ant_path & 0xff); 5975 5976 switch (type) { 5977 case BTC_ANT_WPOWERON: 5978 cx_ctrl = BTC_CTRL_BY_BT; 5979 break; 5980 case BTC_ANT_WINIT: 5981 cx_ctrl = BTC_CTRL_BY_WL; 5982 /* To avoid BT MP driver case (bt_enable but no mailbox) */ 5983 if ((cx->bt0.enable.now && cx->bt0.run_patch_code) || 5984 (cx->bt1.enable.now && cx->bt1.run_patch_code)) 5985 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 5986 BTC_WLACT_SW_LO); 5987 else 5988 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5989 BTC_WLACT_SW_HI); 5990 break; 5991 case BTC_ANT_WONLY: 5992 cx_ctrl = BTC_CTRL_BY_WL; 5993 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 5994 BTC_WLACT_SW_HI); 5995 break; 5996 case BTC_ANT_WOFF: 5997 cx_ctrl = BTC_CTRL_BY_BT; 5998 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 5999 BTC_WLACT_SW_LO); 6000 break; 6001 case BTC_ANT_PTA: 6002 default: 6003 cx_ctrl = BTC_CTRL_BY_WL; 6004 gbt = BTC_GNT_HW; 6005 if ((rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA) || 6006 !wl_rinfo->dbcc_en) { 6007 gwl = BTC_GNT_HW; 6008 _set_gnt(rtwdev, BTC_PHY_ALL, gwl, gbt, BTC_WLACT_HW); 6009 } else { 6010 /* for DBCC Only-1-PTA */ 6011 if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_0) { 6012 gwl0 = BTC_GNT_HW; 6013 gwl1 = BTC_GNT_SW_HI; 6014 } else { 6015 gwl0 = BTC_GNT_SW_HI; 6016 gwl1 = BTC_GNT_HW; 6017 } 6018 _set_gnt(rtwdev, BTC_PHY_0, gwl0, gbt, BTC_WLACT_HW); 6019 _set_gnt(rtwdev, BTC_PHY_1, gwl1, gbt, BTC_WLACT_HW); 6020 } 6021 break; 6022 case BTC_ANT_FDD: 6023 cx_ctrl = BTC_CTRL_BY_WL; 6024 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_HW, 6025 BTC_WLACT_HW); 6026 break; 6027 case BTC_ANT_FREERUN: 6028 cx_ctrl = BTC_CTRL_BY_WL; 6029 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_HI, 6030 BTC_WLACT_SW_LO); 6031 break; 6032 case BTC_ANT_WRFK: 6033 cx_ctrl = BTC_CTRL_BY_WL; 6034 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 6035 BTC_WLACT_HW); 6036 break; 6037 case BTC_ANT_WRFK2: 6038 cx_ctrl = BTC_CTRL_BY_WL; 6039 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 6040 BTC_WLACT_SW_HI); /* no BT-Tx */ 6041 break; 6042 } 6043 6044 rtw89_chip_cfg_ctrl_path(rtwdev, cx_ctrl); 6045 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 6046 } 6047 6048 static void _action_wl_only(struct rtw89_dev *rtwdev) 6049 { 6050 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 6051 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 6052 } 6053 6054 static void _action_wl_init(struct rtw89_dev *rtwdev) 6055 { 6056 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 6057 6058 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 6059 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 6060 } 6061 6062 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode) 6063 { 6064 struct rtw89_btc *btc = &rtwdev->btc; 6065 struct rtw89_btc_dm *dm = &btc->dm; 6066 struct rtw89_btc_cx *cx = &btc->cx; 6067 struct rtw89_btc_wl_info *wl = &cx->wl; 6068 6069 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 6070 6071 if (wl->status.map.rf_off || btc->dm.bt_only) 6072 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 6073 else if (wl->status.map.lps == BTC_LPS_RF_ON || 6074 cx->bt0.whql_test || cx->bt1.whql_test) 6075 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6076 6077 if (dm->out_of_band) 6078 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF); 6079 else if (cx->bt0.whql_test || cx->bt1.whql_test) 6080 _set_policy(rtwdev, BTC_CXP_OFFB_BWB4, BTC_ACT_WL_OFF); 6081 else 6082 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 6083 } 6084 6085 static void _action_freerun(struct rtw89_dev *rtwdev) 6086 { 6087 struct rtw89_btc *btc = &rtwdev->btc; 6088 6089 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 6090 6091 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 6092 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 6093 6094 btc->dm.freerun = true; 6095 } 6096 6097 static void _action_bt_whql(struct rtw89_dev *rtwdev) 6098 { 6099 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 6100 6101 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6102 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 6103 } 6104 6105 static void _action_bt_off(struct rtw89_dev *rtwdev) 6106 { 6107 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 6108 6109 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 6110 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 6111 } 6112 6113 static void _action_bt_idle(struct rtw89_dev *rtwdev) 6114 { 6115 struct rtw89_btc *btc = &rtwdev->btc; 6116 struct rtw89_btc_bt_link_info *b = &btc->cx.bt0.link_info; 6117 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6118 6119 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6120 6121 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6122 switch (btc->cx.state_map) { 6123 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 6124 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 6125 if (b->status.map.connect) 6126 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE); 6127 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 6128 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE); 6129 else 6130 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE); 6131 break; 6132 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 6133 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 6134 BTC_ACT_BT_IDLE); 6135 break; 6136 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 6137 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 6138 BTC_ACT_BT_IDLE); 6139 break; 6140 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 6141 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 6142 BTC_ACT_BT_IDLE); 6143 break; 6144 case BTC_WIDLE: /* wl-idle + bt-idle */ 6145 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 6146 break; 6147 } 6148 } else { /* dedicated-antenna */ 6149 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 6150 } 6151 } 6152 6153 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 6154 { 6155 struct rtw89_btc *btc = &rtwdev->btc; 6156 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6157 6158 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6159 6160 if (btc->ant_type == BTC_ANT_SHARED) { 6161 if (btc->cx.wl.status.map._4way) { 6162 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 6163 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 6164 btc->cx.bt0.scan_rx_low_pri = true; 6165 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 6166 } else { 6167 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 6168 } 6169 } else { 6170 if (wl->bg_mode[RTW89_MAC_0]) 6171 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 6172 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 6173 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP); 6174 else 6175 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 6176 } 6177 } 6178 6179 static void _action_bt_hid(struct rtw89_dev *rtwdev) 6180 { 6181 const struct rtw89_chip_info *chip = rtwdev->chip; 6182 struct rtw89_btc *btc = &rtwdev->btc; 6183 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6184 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6185 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 6186 u16 policy_type = BTC_CXP_OFF_BT; 6187 6188 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6189 6190 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6191 if (wl->status.map._4way) { 6192 policy_type = BTC_CXP_OFF_WL; 6193 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 6194 btc->cx.bt0.scan_rx_low_pri = true; 6195 if (hid->type & BTC_HID_BLE) 6196 policy_type = BTC_CXP_OFF_BWB0; 6197 else 6198 policy_type = BTC_CXP_OFF_BWB2; 6199 } else if (hid->type == BTC_HID_218) { 6200 bt->scan_rx_low_pri = true; 6201 policy_type = BTC_CXP_OFF_BWB2; 6202 } else if (chip->para_ver == 0x1) { 6203 policy_type = BTC_CXP_OFF_BWB3; 6204 } else { 6205 policy_type = BTC_CXP_OFF_BWB1; 6206 } 6207 } else { /* dedicated-antenna */ 6208 if (wl->bg_mode[RTW89_MAC_0]) 6209 policy_type = BTC_CXP_OFF_BWB1; 6210 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 6211 policy_type = BTC_CXP_OFF_EQ4; 6212 else 6213 policy_type = BTC_CXP_OFF_EQ3; 6214 } 6215 6216 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 6217 } 6218 6219 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 6220 { 6221 struct rtw89_btc *btc = &rtwdev->btc; 6222 struct rtw89_btc_dm *dm = &btc->dm; 6223 6224 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6225 6226 dm->slot_dur[CXST_W1] = 20; 6227 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 6228 6229 switch (btc->cx.state_map) { 6230 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 6231 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 6232 break; 6233 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 6234 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 6235 break; 6236 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 6237 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 6238 break; 6239 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 6240 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 6241 if (btc->cx.wl.rfk_info.con_rfk) 6242 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP); 6243 else 6244 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP); 6245 break; 6246 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 6247 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 6248 break; 6249 } 6250 } 6251 6252 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 6253 { 6254 struct rtw89_btc *btc = &rtwdev->btc; 6255 6256 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6257 6258 switch (btc->cx.state_map) { 6259 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 6260 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 6261 break; 6262 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 6263 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 6264 break; 6265 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 6266 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 6267 break; 6268 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 6269 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 6270 break; 6271 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 6272 if (btc->cx.wl.rfk_info.con_rfk) 6273 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK); 6274 else 6275 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 6276 break; 6277 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 6278 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 6279 break; 6280 } 6281 } 6282 6283 static void _action_bt_pan(struct rtw89_dev *rtwdev) 6284 { 6285 struct rtw89_btc *btc = &rtwdev->btc; 6286 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 6287 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 6288 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 6289 6290 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6291 6292 switch (btc->cx.state_map) { 6293 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 6294 if (a2dp.active || !pan.exist) { 6295 btc->dm.slot_dur[CXST_W1] = 80; 6296 btc->dm.slot_dur[CXST_B1] = 20; 6297 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); 6298 } else { 6299 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 6300 } 6301 break; 6302 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 6303 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 6304 break; 6305 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 6306 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 6307 break; 6308 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 6309 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 6310 break; 6311 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 6312 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN); 6313 break; 6314 case BTC_WIDLE: /* wl-idle + bt-pan */ 6315 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 6316 break; 6317 } 6318 } 6319 6320 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 6321 { 6322 struct rtw89_btc *btc = &rtwdev->btc; 6323 struct rtw89_btc_dm *dm = &btc->dm; 6324 6325 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6326 6327 dm->slot_dur[CXST_W1] = 20; 6328 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 6329 6330 switch (btc->cx.state_map) { 6331 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 6332 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 6333 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 6334 break; 6335 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 6336 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID); 6337 break; 6338 6339 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 6340 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 6341 break; 6342 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 6343 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 6344 if (btc->cx.wl.rfk_info.con_rfk) 6345 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID); 6346 else 6347 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 6348 break; 6349 } 6350 } 6351 6352 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 6353 { 6354 struct rtw89_btc *btc = &rtwdev->btc; 6355 6356 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6357 6358 switch (btc->cx.state_map) { 6359 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 6360 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6361 break; 6362 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 6363 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6364 break; 6365 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 6366 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 6367 break; 6368 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 6369 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 6370 break; 6371 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 6372 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 6373 break; 6374 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 6375 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 6376 break; 6377 } 6378 } 6379 6380 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 6381 { 6382 struct rtw89_btc *btc = &rtwdev->btc; 6383 6384 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6385 6386 switch (btc->cx.state_map) { 6387 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 6388 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 6389 break; 6390 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 6391 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 6392 break; 6393 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 6394 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 6395 break; 6396 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 6397 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 6398 break; 6399 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 6400 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 6401 break; 6402 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 6403 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 6404 break; 6405 } 6406 } 6407 6408 static void _action_bt_bis(struct rtw89_dev *rtwdev) 6409 { 6410 struct rtw89_btc *btc = &rtwdev->btc; 6411 struct rtw89_btc_dm *dm = &btc->dm; 6412 u16 policy_type; 6413 6414 if (dm->bis_tdma) 6415 policy_type = BTC_CXP_OFFE_2GBWISOB; 6416 else 6417 policy_type = BTC_CXP_OFF_EQ0; 6418 6419 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6420 _set_policy(rtwdev, policy_type, BTC_ACT_BT_BIS); 6421 } 6422 6423 static void _action_bt_cis(struct rtw89_dev *rtwdev) 6424 { 6425 struct rtw89_btc *btc = &rtwdev->btc; 6426 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 6427 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6428 struct rtw89_btc_dm *dm = &btc->dm; 6429 u16 policy_type; 6430 6431 if (bt_linfo->a2dp_desc.active) { 6432 dm->slot_dur[CXST_W1] = 80; 6433 dm->slot_dur[CXST_B1] = 20; 6434 policy_type = BTC_CXP_PFIX_TDW1B1; 6435 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 6436 policy_type = BTC_CXP_OFF_BWB0; 6437 } else { 6438 policy_type = BTC_CXP_OFF_BWB1; 6439 } 6440 6441 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 6442 _set_policy(rtwdev, policy_type, BTC_ACT_BT_CIS); 6443 } 6444 6445 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 6446 { 6447 struct rtw89_btc *btc = &rtwdev->btc; 6448 6449 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6450 6451 switch (btc->cx.state_map) { 6452 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 6453 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 6454 BTC_ACT_BT_A2DP_PAN_HID); 6455 break; 6456 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 6457 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 6458 BTC_ACT_BT_A2DP_PAN_HID); 6459 break; 6460 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 6461 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 6462 BTC_ACT_BT_A2DP_PAN_HID); 6463 break; 6464 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 6465 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 6466 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 6467 BTC_ACT_BT_A2DP_PAN_HID); 6468 break; 6469 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 6470 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 6471 BTC_ACT_BT_A2DP_PAN_HID); 6472 break; 6473 } 6474 } 6475 6476 static void _action_wl_5g(struct rtw89_dev *rtwdev) 6477 { 6478 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_FDD); 6479 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 6480 } 6481 6482 static void _action_wl_other(struct rtw89_dev *rtwdev) 6483 { 6484 struct rtw89_btc *btc = &rtwdev->btc; 6485 6486 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6487 6488 if (btc->ant_type == BTC_ANT_SHARED) 6489 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 6490 else 6491 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 6492 } 6493 6494 static void _action_wl_nc(struct rtw89_dev *rtwdev) 6495 { 6496 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6497 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 6498 } 6499 6500 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 6501 { 6502 struct rtw89_btc *btc = &rtwdev->btc; 6503 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 6504 6505 if (rfk.state != BTC_WRFK_START) 6506 return; 6507 6508 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 6509 __func__, rfk.band); 6510 6511 btc->dm.tdma_instant_excute = 1; 6512 6513 if (rfk.state == BTC_WRFK_ONESHOT_START || 6514 btc->ant_type == BTC_ANT_SHARED) { 6515 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); 6516 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); 6517 } else { 6518 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 6519 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 6520 } 6521 } 6522 6523 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 6524 { 6525 struct rtw89_btc *btc = &rtwdev->btc; 6526 struct rtw89_btc_dm *dm = &btc->dm; 6527 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &dm->ost_info; 6528 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6529 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6530 const struct rtw89_chip_info *chip = rtwdev->chip; 6531 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6532 u32 is_btg = BTC_BTGCTRL_DISABLE; 6533 6534 if (btc->manual_ctrl) 6535 return; 6536 6537 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ 6538 if (btc->ant_type == BTC_ANT_SHARED) { 6539 if (!(bt->run_patch_code && bt->enable.now)) 6540 is_btg = BTC_BTGCTRL_DISABLE; 6541 else if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) || 6542 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) 6543 is_btg = BTC_BTGCTRL_ENABLE; 6544 else 6545 is_btg = BTC_BTGCTRL_DISABLE; 6546 6547 /* bb call ctrl_btg() in WL FW by slot */ 6548 if (!btc->ver->fcxosi && 6549 wl_rinfo->link_mode[RTW89_MAC_0] == BTC_WLINK_DB_MCC) 6550 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; 6551 } 6552 6553 if (is_btg == dm->wl_btg_rx) 6554 return; 6555 else 6556 dm->wl_btg_rx = is_btg; 6557 6558 /* skip setup if btg_ctrl set by wl fw */ 6559 if (!btc->ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE) 6560 return; 6561 6562 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */ 6563 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 6564 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 6565 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE; 6566 else 6567 o_info->btg_rx[BTC_RF_S0] = is_btg; 6568 6569 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 6570 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE; 6571 else 6572 o_info->btg_rx[BTC_RF_S1] = is_btg; 6573 } else { /* 2+0 or 0+2 */ 6574 o_info->btg_rx[BTC_RF_S0] = is_btg; 6575 o_info->btg_rx[BTC_RF_S1] = is_btg; 6576 } 6577 6578 if (btc->ver->fcxosi) 6579 return; 6580 6581 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0], 6582 RTW89_PHY_0); 6583 if (chip->chip_id != RTL8922A) 6584 return; 6585 6586 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1], 6587 RTW89_PHY_1); 6588 } 6589 6590 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) 6591 { 6592 struct rtw89_btc *btc = &rtwdev->btc; 6593 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; 6594 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info; 6595 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6596 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 6597 const struct rtw89_chip_info *chip = rtwdev->chip; 6598 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6599 struct rtw89_btc_dm *dm = &btc->dm; 6600 u8 is_preagc, val; 6601 6602 if (btc->manual_ctrl) 6603 return; 6604 6605 if (!(bt->run_patch_code && bt->enable.now)) { 6606 is_preagc = BTC_PREAGC_DISABLE; 6607 } else if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) { 6608 is_preagc = BTC_PREAGC_DISABLE; 6609 } else if (rinfo->link_mode[RTW89_MAC_0] == BTC_WLINK_NOLINK || 6610 btc->cx.bt0.link_info.link_cnt.now == 0) { 6611 is_preagc = BTC_PREAGC_DISABLE; 6612 } else if (dm->tdma_now.type != CXTDMA_OFF && 6613 !bt_linfo->hfp_desc.exist && 6614 !bt_linfo->hid_desc.exist && 6615 dm->fddt_train == BTC_FDDT_DISABLE) { 6616 is_preagc = BTC_PREAGC_DISABLE; 6617 } else if (rinfo->dbcc_en && (rinfo->dbcc_2g_phy != RTW89_PHY_1)) { 6618 is_preagc = BTC_PREAGC_DISABLE; 6619 } else if (btc->ant_type == BTC_ANT_SHARED) { 6620 is_preagc = BTC_PREAGC_DISABLE; 6621 } else { 6622 is_preagc = BTC_PREAGC_ENABLE; 6623 } 6624 6625 if (!btc->ver->fcxosi && rinfo->link_mode[RTW89_MAC_0] == BTC_WLINK_DB_MCC) 6626 is_preagc = BTC_PREAGC_BB_FWCTRL; 6627 6628 if (dm->wl_pre_agc_rb != dm->wl_pre_agc && 6629 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { 6630 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); 6631 dm->wl_pre_agc_rb = val; 6632 } 6633 6634 if ((wl->coex_mode == BTC_MODE_NORMAL && 6635 (dm->run_reason == BTC_RSN_NTFY_INIT || 6636 dm->run_reason == BTC_RSN_NTFY_SWBAND || 6637 dm->wl_pre_agc_rb != dm->wl_pre_agc)) || 6638 is_preagc != dm->wl_pre_agc) { 6639 dm->wl_pre_agc = is_preagc; 6640 6641 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE) 6642 return; 6643 6644 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 6645 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 6646 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE; 6647 else 6648 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 6649 6650 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 6651 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE; 6652 else 6653 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 6654 6655 } else { /* 2+0 or 0+2 */ 6656 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 6657 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 6658 } 6659 6660 if (btc->ver->fcxosi) 6661 return; 6662 6663 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0], 6664 RTW89_PHY_0); 6665 if (chip->chip_id != RTL8922A) 6666 return; 6667 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1], 6668 RTW89_PHY_1); 6669 } 6670 } 6671 6672 struct rtw89_txtime_data { 6673 struct rtw89_dev *rtwdev; 6674 int type; 6675 u32 tx_time; 6676 u8 tx_retry; 6677 u16 enable; 6678 bool reenable; 6679 }; 6680 6681 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, 6682 struct rtw89_sta_link *rtwsta_link, 6683 struct rtw89_txtime_data *iter_data) 6684 { 6685 struct rtw89_dev *rtwdev = iter_data->rtwdev; 6686 struct rtw89_btc *btc = &rtwdev->btc; 6687 struct rtw89_btc_cx *cx = &btc->cx; 6688 struct rtw89_btc_wl_info *wl = &cx->wl; 6689 struct rtw89_btc_wl_link_info *plink = NULL; 6690 u8 port = rtwvif_link->port; 6691 u32 tx_time = iter_data->tx_time; 6692 u8 tx_retry = iter_data->tx_retry; 6693 u16 enable = iter_data->enable; 6694 bool reenable = iter_data->reenable; 6695 6696 plink = &wl->rlink_info[port][rtwsta_link->link_id]; 6697 6698 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6699 "[BTC], %s(): port = %d\n", __func__, port); 6700 6701 if (!plink->connected) { 6702 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6703 "[BTC], %s(): connected = %d\n", 6704 __func__, plink->connected); 6705 return; 6706 } 6707 6708 /* backup the original tx time before tx-limit on */ 6709 if (reenable) { 6710 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); 6711 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); 6712 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6713 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 6714 __func__, plink->tx_time, plink->tx_retry); 6715 } 6716 6717 /* restore the original tx time if no tx-limit */ 6718 if (!enable) { 6719 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); 6720 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, 6721 plink->tx_retry); 6722 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6723 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 6724 __func__, plink->tx_time, plink->tx_retry); 6725 6726 } else { 6727 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); 6728 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); 6729 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6730 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 6731 __func__, tx_time, tx_retry); 6732 } 6733 } 6734 6735 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 6736 { 6737 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 6738 struct rtw89_txtime_data *iter_data = 6739 (struct rtw89_txtime_data *)data; 6740 struct rtw89_vif_link *rtwvif_link; 6741 struct rtw89_sta_link *rtwsta_link; 6742 unsigned int link_id; 6743 6744 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 6745 rtwvif_link = rtwsta_link->rtwvif_link; 6746 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); 6747 } 6748 } 6749 6750 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 6751 { 6752 struct rtw89_btc *btc = &rtwdev->btc; 6753 struct rtw89_btc_cx *cx = &btc->cx; 6754 struct rtw89_btc_dm *dm = &btc->dm; 6755 struct rtw89_btc_wl_info *wl = &cx->wl; 6756 struct rtw89_btc_bt_info *bt = &cx->bt0; 6757 struct rtw89_btc_bt_link_info *b = &bt->link_info; 6758 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 6759 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 6760 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6761 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 6762 bool reenable = false; 6763 u8 tx_retry; 6764 u32 tx_time; 6765 u16 enable; 6766 6767 if (btc->manual_ctrl) 6768 return; 6769 6770 if (btc->dm.freerun || btc->ctrl.igno_bt || b->link_cnt.now == 0 || 6771 dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G) || 6772 wl_rinfo->link_mode[RTW89_MAC_0] == BTC_WLINK_NOLINK) { 6773 enable = 0; 6774 tx_time = BTC_MAX_TX_TIME_DEF; 6775 tx_retry = BTC_MAX_TX_RETRY_DEF; 6776 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 6777 enable = 1; 6778 tx_time = BTC_MAX_TX_TIME_L2; 6779 tx_retry = BTC_MAX_TX_RETRY_L1; 6780 } else if (hfp->exist || hid->exist) { 6781 enable = 1; 6782 tx_time = BTC_MAX_TX_TIME_L3; 6783 tx_retry = BTC_MAX_TX_RETRY_L1; 6784 } else { 6785 enable = 0; 6786 tx_time = BTC_MAX_TX_TIME_DEF; 6787 tx_retry = BTC_MAX_TX_RETRY_DEF; 6788 } 6789 6790 if (dm->wl_tx_limit.enable == enable && 6791 dm->wl_tx_limit.tx_time == tx_time && 6792 dm->wl_tx_limit.tx_retry == tx_retry) 6793 return; 6794 6795 if (!dm->wl_tx_limit.enable && enable) 6796 reenable = true; 6797 6798 dm->wl_tx_limit.enable = enable; 6799 dm->wl_tx_limit.tx_time = tx_time; 6800 dm->wl_tx_limit.tx_retry = tx_retry; 6801 6802 data.enable = enable; 6803 data.tx_time = tx_time; 6804 data.tx_retry = tx_retry; 6805 data.reenable = reenable; 6806 6807 ieee80211_iterate_stations_atomic(rtwdev->hw, 6808 rtw89_tx_time_iter, 6809 &data); 6810 } 6811 6812 static void _set_phl_bt_slot_req(struct rtw89_dev *rtwdev) 6813 { 6814 struct rtw89_btc *btc = &rtwdev->btc; 6815 struct rtw89_btc_cx *cx = &btc->cx; 6816 struct rtw89_btc_wl_info *wl = &cx->wl; 6817 struct rtw89_btc_dm *dm = &btc->dm; 6818 u8 len = 0; 6819 u8 i; 6820 6821 /* don't change bt slot req state during RFK for p2p/mcc case */ 6822 if (dm->run_reason == BTC_RSN_NTFY_WL_RFK || 6823 wl->status.map.transacting) 6824 return; 6825 6826 /* enable bt-slot req if ext-slot-control */ 6827 if (dm->tdma_now.type == CXTDMA_OFF && 6828 dm->tdma_now.ext_ctrl == CXECTL_EXT && 6829 dm->tdd_bind.bt_sel != 0) { 6830 if (btc->cx.wl.status.val & btc_scanning_map.val) 6831 btc->bt_req_en = false; 6832 else 6833 btc->bt_req_en = true; 6834 } else { 6835 btc->bt_req_en = false; 6836 } 6837 6838 if (dm->slot_req_more) { 6839 len = BTC_BSLOT_A2DP_HID; 6840 } else { 6841 if (dm->tdd_bind.bt_link_weight >= BTC_BSLOT_A2DP_HID) 6842 len = BTC_BSLOT_A2DP_HID; 6843 else if (dm->tdd_bind.bt_link_weight <= BTC_BSLOT_IDLE) 6844 len = BTC_BSLOT_IDLE; 6845 else 6846 len = dm->tdd_bind.bt_link_weight; 6847 } 6848 6849 if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) 6850 len = 100 - len; 6851 6852 if (!btc->bt_req_en) 6853 len = 0; 6854 6855 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) { 6856 if (!(dm->tdd_bind.wl_hwb_sel & BIT(i))) 6857 continue; 6858 6859 if (len == btc->bt_req_len[i]) 6860 continue; 6861 6862 btc->bt_req_len[i] = len; 6863 6864 rtw89_core_ntfy_btc_event(rtwdev, 6865 RTW89_BTC_HMSG_SET_BT_REQ_SLOT, i); 6866 6867 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6868 "[BTC], %s(): HWB%d bt_req_len = %d\n", 6869 __func__, i, btc->bt_req_len[i]); 6870 } 6871 } 6872 6873 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 6874 { 6875 struct rtw89_btc *btc = &rtwdev->btc; 6876 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6877 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6878 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6879 bool bt_hi_lna_rx = false; 6880 6881 if (wl_rinfo->link_mode[RTW89_MAC_0] != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 6882 bt_hi_lna_rx = true; 6883 6884 if (bt_hi_lna_rx == bt->hi_lna_rx) 6885 return; 6886 6887 _write_scbd(rtwdev, BTC_BT_1ST, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 6888 } 6889 6890 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 6891 { 6892 struct rtw89_btc *btc = &rtwdev->btc; 6893 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 6894 6895 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_RXSCAN_PRI, 6896 (bool)(!!bt->scan_rx_low_pri)); 6897 } 6898 6899 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) 6900 { 6901 struct rtw89_btc *btc = &rtwdev->btc; 6902 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6903 struct rtw89_btc_dm *dm = &btc->dm; 6904 u32 add; 6905 6906 if (mac == wl->pta_req_mac) 6907 return; 6908 6909 dm->ost_info.pta_req_hw_band = mac; 6910 wl->pta_req_mac = mac; 6911 wl->pta_reg_mac_chg = true; 6912 6913 if (btc->ver->fcxosi) 6914 return; 6915 6916 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) 6917 add = R_BE_BTC_CFG; 6918 else 6919 add = R_AX_BTC_CFG; 6920 6921 if (mac == RTW89_MAC_0) 6922 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC); 6923 else 6924 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC); 6925 } 6926 6927 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev) 6928 { 6929 struct rtw89_btc *btc = &rtwdev->btc; 6930 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a; 6931 u8 link_mode_chg = btc->cx.wl.link_mode_chg; 6932 u8 mode = btc->cx.wl.role_info.link_mode[RTW89_MAC_0]; 6933 6934 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && !link_mode_chg) 6935 return; 6936 6937 if (!(btc->mdinfo.wa_type & BTC_WA_HFP_ZB)) 6938 return; 6939 6940 if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G) || 6941 rtwdev->btc.dm.freerun) { 6942 zb_tbl0 = 0xffffffff; 6943 zb_tbl1 = 0xffffffff; 6944 } else if (mode == BTC_WLINK_DB_MCC) { 6945 zb_tbl0 = 0xffffffff; /* for E5G slot */ 6946 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */ 6947 } 6948 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0); 6949 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1); 6950 } 6951 6952 static void _set_fw_report_map(struct rtw89_dev *rtwdev) 6953 { 6954 struct rtw89_btc *btc = &rtwdev->btc; 6955 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map; 6956 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 6957 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 6958 u32 rpt_map = btc->fwinfo.rpt_en_map; 6959 u32 bt_rom_code_id, bt_fw_ver; 6960 bool bt_ver_unknown = false; 6961 u32 bitmap; 6962 6963 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) { 6964 rtw89_btc_fw_en_rpt(rtwdev, false, 0); 6965 return; 6966 } 6967 6968 rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_TDMA); 6969 rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_CYCLE); 6970 rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_MREG); 6971 6972 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_SCAN_INFO); 6973 if ((bt0->run_patch_code && bt0->enable.now) || 6974 (bt1->run_patch_code && bt1->enable.now)) 6975 rpt_map |= bitmap; 6976 else 6977 rpt_map &= ~bitmap; 6978 6979 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id); 6980 bt_fw_ver = bt0->ver_info.fw & 0xffff; 6981 if (bt_fw_ver == 0 || 6982 (bt_fw_ver == bt_rom_code_id && bt0->run_patch_code)) 6983 bt_ver_unknown = true; 6984 6985 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_VER_INFO); 6986 if (bt0->enable.now && bt_ver_unknown) 6987 rpt_map |= bitmap; 6988 else 6989 rpt_map &= ~bitmap; 6990 6991 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP) | 6992 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP_LE) | 6993 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_TX_PWR_LVL); 6994 if (bt0->link_info.link_cnt.now || 6995 bt0->link_info_56g.link_cnt.now || 6996 bt1->link_info.link_cnt.now || 6997 bt1->link_info_56g.link_cnt.now) 6998 rpt_map |= bitmap; 6999 else 7000 rpt_map &= ~bitmap; 7001 7002 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_DEVICE_INFO); 7003 if ((bt0->link_info.a2dp_desc.exist && 7004 bt0->link_info.a2dp_desc.play_latency) || 7005 (bt1->link_info.a2dp_desc.exist && 7006 bt1->link_info.a2dp_desc.play_latency)) 7007 rpt_map |= bitmap; 7008 else 7009 rpt_map &= ~bitmap; 7010 7011 rtw89_btc_fw_en_rpt(rtwdev, false, rpt_map); 7012 } 7013 7014 static void _set_trx_nss(struct rtw89_dev *rtwdev) 7015 { 7016 struct rtw89_btc *btc = &rtwdev->btc; 7017 struct rtw89_btc_dm *dm = &btc->dm; 7018 struct rtw89_btc_bind_bt_status *btdd = &dm->tdd_bind.bt_smap; 7019 struct rtw89_btc_bind_bt_status *bfdd = &dm->fdd_bind.bt_smap; 7020 struct rtw89_btc_wl_trx_nss_para *trx_nss = &dm->wl_trx_nss; 7021 struct rtw89_btc_module *module = &btc->mdinfo; 7022 struct rtw89_btc_cx *cx = &btc->cx; 7023 struct rtw89_btc_wl_info *wl = &cx->wl; 7024 bool bt0_cis = cx->bt0.link_info.leaudio_desc.cis_exist; 7025 bool bt1_cis = cx->bt1.link_info.leaudio_desc.cis_exist; 7026 u8 tx_ss, rx_ss, tx_path, rx_path, limit_path; 7027 u8 tx_limit = 0, rx_limit = 0; 7028 7029 /* tx/rx_limit: 1 = 1ss, 0 = HW default */ 7030 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7031 "[BTC], %s(): wl_rinfo->link_mode=%d, dm->wl_trx_nss_en=%d\n", 7032 __func__, wl->role_info.link_mode[RTW89_MAC_0], dm->wl_trx_nss_en); 7033 7034 /* 7035 * Skip 1SS MIMO-PS if: 7036 * - manual mode or DBCC enabled 7037 * - !wl_trx_nss_en: no MIMO-PS capability. The RFE configs that share 7038 * a WL path with BT are selected in ops->set_rfe() (e.g. 8922D only 7039 * sets it for ant.num=2), so this flag is the single gate here, no 7040 * extra ant.num/bt1_sw_type check. 7041 * - non-LNV vendor and no DUAL_BT. Dual-BT chips run MIMO-PS for every 7042 * vendor, single-BT chips only for LNV (LNV: PCIE-12223) 7043 */ 7044 if (btc->manual_ctrl || wl->role_info.dbcc_en || !dm->wl_trx_nss_en || 7045 (dm->vid != RTW89_CUSTID_LENOVO && 7046 !(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))) 7047 return; 7048 7049 /* 7050 * Disable 1SS limit when: 7051 * - No WiFi link (WL idle state) 7052 * - Out-of-band scenario (no BT coex needed) 7053 */ 7054 if (wl->role_info.link_mode[RTW89_MAC_0] == BTC_WLINK_NOLINK || 7055 wl->role_info.link_mode[RTW89_MAC_1] == BTC_WLINK_NOLINK || 7056 dm->out_of_band) { 7057 tx_limit = 0; 7058 rx_limit = 0; 7059 } else if (bt0_cis || bt1_cis || btdd->cis_exist || bfdd->cis_exist) { 7060 /* 7061 * Enable 2T1R when BT CIS profile exists (low latency audio). 7062 * tx_limit=1 (1T1R full isolation) reserved for future use 7063 * when WL needs to fully isolate Tx from BT on shared antenna. 7064 */ 7065 tx_limit = 0; 7066 rx_limit = 1; 7067 } 7068 7069 /* 7070 * BT1 at S0 has CIS -> WL must use S1 (path B) 7071 * BT0 at S1 has CIS -> WL must use S0 (path A) 7072 */ 7073 limit_path = bt1_cis ? RF_PATH_B : RF_PATH_A; 7074 7075 /* 7076 * Re-arm the exit-LPS one-shot once the event is over. lps_exiting is 7077 * held for a while by the LPS-exit timer, so it must not be used as 7078 * the force-exec condition directly. 7079 */ 7080 if (!wl->status.map.lps_exiting) 7081 dm->trx_nss_lps_done = 0; 7082 7083 if (trx_nss->rx_limit == rx_limit && trx_nss->tx_limit == tx_limit && 7084 (!rx_limit || trx_nss->rx_path == limit_path)) { 7085 /* 7086 * WL just exited LPS: LPS may have cleared the BB/RF 1SS 7087 * setup, so re-issue cfg_1ss/cfg_trx_path/set_rfe once per 7088 * exit-LPS event. They are heavy (set_rfe() re-reads efuse and 7089 * does several RF I/O), so a one-shot flag instead of lps_exiting. 7090 */ 7091 if (wl->status.map.lps_exiting && !dm->trx_nss_lps_done) 7092 goto force_exec; 7093 7094 return; 7095 } 7096 7097 force_exec: 7098 /* one-shot consumed, no re-exec until the next exit-LPS event */ 7099 dm->trx_nss_lps_done = wl->status.map.lps_exiting; 7100 7101 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7102 "[BTC], %s(): stream_cnt=0x%02x, path_pos=0x%02x\n", 7103 __func__, module->ant.stream_cnt, module->ant.path_pos); 7104 7105 /* 7106 * Reduce TX to 1SS on the isolated path to avoid BT interference, 7107 * else restore TX to HW default stream count and path. 7108 */ 7109 if (tx_limit) { 7110 tx_ss = 1; 7111 tx_path = limit_path; 7112 } else { 7113 tx_ss = FIELD_GET(BTC_ANT_TX_MASK, module->ant.stream_cnt); 7114 tx_path = FIELD_GET(BTC_ANT_TX_MASK, module->ant.path_pos); 7115 } 7116 7117 /* 7118 * Reduce RX to 1SS on the isolated path to protect WL Rx stream, 7119 * else restore RX to HW default stream count and path. 7120 */ 7121 if (rx_limit) { 7122 rx_ss = 1; 7123 rx_path = limit_path; 7124 } else { 7125 rx_ss = FIELD_GET(BTC_ANT_RX_MASK, module->ant.stream_cnt); 7126 rx_path = FIELD_GET(BTC_ANT_RX_MASK, module->ant.path_pos); 7127 } 7128 7129 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7130 "[BTC], %s(): tx_ss=%d, rx_ss=%d, tx_path=%d, rx_path=%d\n", 7131 __func__, tx_ss, rx_ss, tx_path, rx_path); 7132 7133 /* 7134 * TODO: no driver API to apply tx_limit/rx_limit/tx_ss/rx_ss/tx_path/ 7135 * rx_path to the BB/RF 1SS MIMO-PS HW state yet. Stop here so 7136 * trx_nss/always_freerun/ant.type/set_rfe()/_update_sdm_map() below 7137 * never run from a decision that was never applied to HW. 7138 */ 7139 } 7140 7141 static void _action_common(struct rtw89_dev *rtwdev) 7142 { 7143 struct rtw89_btc *btc = &rtwdev->btc; 7144 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7145 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 7146 struct rtw89_btc_dm *dm = &btc->dm; 7147 u8 i; 7148 7149 _wl_req_mac(rtwdev, rinfo->pta_req_band); 7150 _set_trx_nss(rtwdev); 7151 _update_zb_coex_tbl(rtwdev); 7152 _set_btg_ctrl(rtwdev); 7153 _set_wl_preagc_ctrl(rtwdev); 7154 _set_wl_tx_limit(rtwdev); 7155 _set_phl_bt_slot_req(rtwdev); 7156 _set_bt_afh_info(rtwdev); 7157 _set_bt_rx_agc(rtwdev); 7158 _set_rf_trx_para(rtwdev); 7159 _set_bt_rx_scan_pri(rtwdev); 7160 _set_fw_report_map(rtwdev); 7161 7162 if (dm->run_reason == BTC_RSN_NTFY_INIT || 7163 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 7164 dm->run_reason == BTC_RSN_NTFY_POWEROFF) 7165 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 7166 7167 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) 7168 _sned_h2c_w2bscbd(rtwdev, false, i); 7169 7170 if (btc->ver->fcxosi) { 7171 if (memcmp(&dm->ost_info_last, &dm->ost_info, 7172 sizeof(dm->ost_info_last)) || 7173 dm->run_reason == BTC_RSN_NTFY_INIT || 7174 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) { 7175 dm->ost_info_last = dm->ost_info; 7176 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI); 7177 } 7178 } 7179 dm->tdma_instant_excute = 0; 7180 dm->lps_ctrl_change = false; 7181 wl->role_info.link_mode_chg = 0; 7182 wl->pta_reg_mac_chg = false; 7183 dm->pre_agc_chg = false; 7184 wl->dbcc_chg = 0; 7185 } 7186 7187 static void _action_by_bt(struct rtw89_dev *rtwdev) 7188 { 7189 struct rtw89_btc *btc = &rtwdev->btc; 7190 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 7191 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 7192 struct rtw89_btc_bt_leaudio_desc leaudio = bt_linfo->leaudio_desc; 7193 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 7194 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 7195 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 7196 struct rtw89_btc_dm *dm = &btc->dm; 7197 u8 profile_map = 0; 7198 7199 if (dm->freerun_chk) { 7200 _action_freerun(rtwdev); 7201 return; 7202 } 7203 7204 if (bt_linfo->hfp_desc.exist) 7205 profile_map |= BTC_BT_HFP; 7206 7207 if (bt_linfo->hid_desc.exist) 7208 profile_map |= BTC_BT_HID; 7209 7210 if (bt_linfo->a2dp_desc.exist) 7211 profile_map |= BTC_BT_A2DP; 7212 7213 if (bt_linfo->pan_desc.exist) 7214 profile_map |= BTC_BT_PAN; 7215 7216 if (leaudio.bis_exist) 7217 profile_map |= BTC_BT_BIS; 7218 7219 if (leaudio.cis_exist) 7220 profile_map |= BTC_BT_CIS; 7221 7222 switch (profile_map) { 7223 case BTC_BT_NOPROFILE: 7224 if (pan.active) 7225 _action_bt_pan(rtwdev); 7226 else 7227 _action_bt_idle(rtwdev); 7228 break; 7229 case BTC_BT_HFP: 7230 _action_bt_hfp(rtwdev); 7231 break; 7232 case BTC_BT_HFP | BTC_BT_HID: 7233 case BTC_BT_HID: 7234 _action_bt_hid(rtwdev); 7235 break; 7236 case BTC_BT_A2DP: 7237 if (a2dp.sink) 7238 _action_bt_a2dpsink(rtwdev); 7239 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 7240 _action_bt_a2dp_pan(rtwdev); 7241 else 7242 _action_bt_a2dp(rtwdev); 7243 break; 7244 case BTC_BT_PAN: 7245 _action_bt_pan(rtwdev); 7246 break; 7247 case BTC_BT_BIS: 7248 _action_bt_bis(rtwdev); 7249 break; 7250 case BTC_BT_CIS: 7251 case BTC_BT_CIS | BTC_BT_HID: 7252 _action_bt_cis(rtwdev); 7253 break; 7254 case BTC_BT_A2DP | BTC_BT_HFP: 7255 case BTC_BT_A2DP | BTC_BT_HID: 7256 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 7257 if (a2dp.sink) 7258 _action_bt_a2dpsink(rtwdev); 7259 else if (pan.active) 7260 _action_bt_a2dp_pan_hid(rtwdev); 7261 else 7262 _action_bt_a2dp_hid(rtwdev); 7263 break; 7264 case BTC_BT_A2DP | BTC_BT_PAN: 7265 if (a2dp.sink) 7266 _action_bt_a2dpsink(rtwdev); 7267 else 7268 _action_bt_a2dp_pan(rtwdev); 7269 break; 7270 case BTC_BT_PAN | BTC_BT_HFP: 7271 case BTC_BT_PAN | BTC_BT_HID: 7272 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 7273 _action_bt_pan_hid(rtwdev); 7274 break; 7275 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 7276 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 7277 default: 7278 if (a2dp.sink) 7279 _action_bt_a2dpsink(rtwdev); 7280 else 7281 _action_bt_a2dp_pan_hid(rtwdev); 7282 break; 7283 } 7284 } 7285 7286 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 7287 { 7288 _action_by_bt(rtwdev); 7289 } 7290 7291 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 7292 { 7293 struct rtw89_btc *btc = &rtwdev->btc; 7294 u16 policy_type = BTC_CXP_OFF_BT; 7295 7296 if (btc->ant_type == BTC_ANT_SHARED) { 7297 if (btc->cx.wl.status.map._4way) 7298 policy_type = BTC_CXP_OFFE_WL; 7299 else if (btc->cx.wl.status.val & btc_scanning_map.val) 7300 policy_type = BTC_CXP_OFFE_2GBWMIXB; 7301 else if (btc->cx.bt0.link_info.status.map.connect == 0) 7302 policy_type = BTC_CXP_OFFE_2GISOB; 7303 else 7304 policy_type = BTC_CXP_OFFE_2GBWISOB; 7305 } else { /* dedicated-antenna */ 7306 policy_type = BTC_CXP_OFF_EQ0; 7307 } 7308 7309 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF; 7310 7311 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 7312 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC); 7313 } 7314 7315 static void _action_wl_scan(struct rtw89_dev *rtwdev) 7316 { 7317 struct rtw89_btc *btc = &rtwdev->btc; 7318 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7319 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 7320 7321 if (btc->cx.state_map != BTC_WLINKING && 7322 btc->ctrl.wl_ctrl_info.fw_scan) { 7323 _action_wl_25g_mcc(rtwdev); 7324 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 7325 } else if (rtwdev->dbcc_en) { 7326 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 7327 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 7328 _action_wl_5g(rtwdev); 7329 else 7330 _action_by_bt(rtwdev); 7331 } else { 7332 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 7333 _action_wl_5g(rtwdev); 7334 else 7335 _action_by_bt(rtwdev); 7336 } 7337 } 7338 7339 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 7340 { struct rtw89_btc *btc = &rtwdev->btc; 7341 7342 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 7343 7344 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 7345 if (btc->cx.bt0.link_info.link_cnt.now == 0) 7346 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 7347 BTC_ACT_WL_2G_MCC); 7348 else 7349 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 7350 BTC_ACT_WL_2G_MCC); 7351 } else { /* dedicated-antenna */ 7352 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 7353 } 7354 } 7355 7356 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 7357 { 7358 struct rtw89_btc *btc = &rtwdev->btc; 7359 struct rtw89_btc_dm *dm = &btc->dm; 7360 u16 policy_type; 7361 7362 if (!dm->tdd_bind.bt_smap.connect) 7363 policy_type = BTC_CXP_OFFE_2GISOB; 7364 else 7365 policy_type = BTC_CXP_OFFE_2GBWISOB; 7366 7367 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA); 7368 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 7369 } 7370 7371 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 7372 { 7373 struct rtw89_btc *btc = &rtwdev->btc; 7374 7375 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 7376 7377 if (btc->ant_type == BTC_ANT_SHARED) { 7378 if (btc->cx.bt0.link_info.link_cnt.now == 0) 7379 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 7380 BTC_ACT_WL_2G_AP); 7381 else 7382 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 7383 } else {/* dedicated-antenna */ 7384 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 7385 } 7386 } 7387 7388 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 7389 { 7390 struct rtw89_btc *btc = &rtwdev->btc; 7391 7392 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 7393 7394 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 7395 if (btc->cx.bt0.link_info.link_cnt.now == 0) 7396 _set_policy(rtwdev, 7397 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 7398 else 7399 _set_policy(rtwdev, 7400 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 7401 } else { /* dedicated-antenna */ 7402 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 7403 } 7404 } 7405 7406 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 7407 { 7408 struct rtw89_btc *btc = &rtwdev->btc; 7409 7410 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 7411 7412 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 7413 _action_by_bt(rtwdev); 7414 } else {/* dedicated-antenna */ 7415 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 7416 } 7417 } 7418 7419 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 7420 { 7421 struct rtw89_btc *btc = &rtwdev->btc; 7422 7423 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 7424 7425 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 7426 if (btc->cx.bt0.link_info.link_cnt.now == 0) 7427 _set_policy(rtwdev, 7428 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 7429 else 7430 _set_policy(rtwdev, 7431 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 7432 } else { /* dedicated-antenna */ 7433 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 7434 } 7435 } 7436 7437 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid) 7438 { 7439 struct rtw89_btc *btc = &rtwdev->btc; 7440 struct rtw89_btc_cx *cx = &btc->cx; 7441 struct rtw89_btc_wl_info *wl = &cx->wl; 7442 u8 cnt_idx = BTC_WCNT_SCBDUPDATE; 7443 u8 h2c_func = SET_IOFLD_SCBD; 7444 u8 buf[4]; 7445 7446 if (bid == BTC_BT_2ND) { 7447 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 7448 return 0; 7449 7450 h2c_func |= BT_H2C_FUNC_BT2ND; 7451 cnt_idx = BTC_WCNT_SCBDUPDATE2; 7452 } 7453 7454 if (wl->scbd_chg[bid] || force_exec) { 7455 /* Add delay to avoid BT FW loss information */ 7456 7457 btc_dw2b(buf, 0, (wl->scbd[bid] | BIT(31))); /* trig */ 7458 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) { 7459 if (!_send_fw_cmd(rtwdev, BTFC_SET, 7460 h2c_func, buf, sizeof(buf))) 7461 return 0; 7462 } else { 7463 rtw89_mac_cfg_sb(rtwdev, wl->scbd[bid]); 7464 } 7465 wl->scbd_chg[bid] = 0; 7466 wl->wcnt[cnt_idx]++; 7467 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7468 "[BTC], %s() write BT%d scbd:0x%08x\n", 7469 __func__, bid, wl->scbd[bid]); 7470 } 7471 return 1; 7472 } 7473 7474 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state) 7475 { 7476 const struct rtw89_chip_info *chip = rtwdev->chip; 7477 struct rtw89_btc *btc = &rtwdev->btc; 7478 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7479 struct rtw89_btc_dm *dm = &btc->dm; 7480 u8 force_exec, id, id_start, id_stop; 7481 u32 scbd = 0; 7482 7483 if (!chip->scbd) 7484 return; 7485 7486 if (bid == BTC_ALL_BT) { 7487 id_start = BTC_BT_1ST; 7488 id_stop = BTC_BT_2ND; 7489 } else { 7490 id_start = bid; 7491 id_stop = bid; 7492 } 7493 7494 for (id = id_start; id <= id_stop; id++) { 7495 force_exec = false; 7496 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && 7497 id == BTC_BT_2ND) 7498 continue; 7499 7500 if (state) 7501 scbd = wl->scbd[id] | val; 7502 else 7503 scbd = wl->scbd[id] & (~val); 7504 7505 if (val & BTC_WSCB_CTCODE || 7506 val & BTC_WSCB_RXGAIN || 7507 val & BTC_WSCB_RXGAIN_56G) { /* instant exec */ 7508 force_exec = true; 7509 wl->scbd[id] = scbd; 7510 dm->scbd_write_instant = 1; 7511 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) 7512 _sned_h2c_w2bscbd(rtwdev, force_exec, id); 7513 else 7514 rtw89_mac_cfg_sb(rtwdev, wl->scbd[id]); 7515 dm->scbd_write_instant = 0; 7516 } else if ((val & BTC_WSCB_ACTIVE || 7517 val & BTC_WSCB_ON || 7518 val & BTC_WSCB_WLRFK) || 7519 scbd != wl->scbd[id]) { 7520 /* 7521 * Just update wl->scbd[] and set wl->scbd_chg[], 7522 * moved "Write scoreboard I/O" to _action_common() 7523 * _write_scbd will be executed if run_coex() 7524 */ 7525 wl->scbd[id] = scbd; 7526 wl->scbd_chg[id] = 1; 7527 } 7528 } 7529 } 7530 7531 static u8 7532 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 7533 { 7534 const struct rtw89_chip_info *chip = rtwdev->chip; 7535 u8 next_state, tol = chip->rssi_tol; 7536 7537 if (pre_state == BTC_RSSI_ST_LOW || 7538 pre_state == BTC_RSSI_ST_STAY_LOW) { 7539 if (rssi >= (thresh + tol)) 7540 next_state = BTC_RSSI_ST_HIGH; 7541 else 7542 next_state = BTC_RSSI_ST_STAY_LOW; 7543 } else { 7544 if (rssi < thresh) 7545 next_state = BTC_RSSI_ST_LOW; 7546 else 7547 next_state = BTC_RSSI_ST_STAY_HIGH; 7548 } 7549 7550 return next_state; 7551 } 7552 7553 static 7554 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 7555 { 7556 struct rtw89_btc *btc = &rtwdev->btc; 7557 7558 btc->cx.wl.dbcc_info.real_band[phy_idx] = 7559 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 7560 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 7561 btc->cx.wl.dbcc_info.op_band[phy_idx]; 7562 } 7563 7564 #define BTC_CHK_HANG_MAX 3 7565 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 7566 7567 static u8 _get_role_link_mode(u8 role) 7568 { 7569 switch (role) { 7570 case RTW89_WIFI_ROLE_STATION: 7571 default: 7572 return BTC_WLINK_STA; 7573 case RTW89_WIFI_ROLE_P2P_GO: 7574 return BTC_WLINK_GO; 7575 case RTW89_WIFI_ROLE_P2P_CLIENT: 7576 return BTC_WLINK_GC; 7577 case RTW89_WIFI_ROLE_AP: 7578 return BTC_WLINK_AP; 7579 } 7580 } 7581 7582 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1, 7583 const struct rtw89_btc_chdef *r2) 7584 { 7585 if (r1->chan != r2->chan) { /* primary ch is different */ 7586 return false; 7587 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 && 7588 r2->bw == RTW89_CHANNEL_WIDTH_40) { 7589 if (r1->offset != r2->offset) 7590 return false; 7591 } 7592 return true; 7593 } 7594 7595 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, 7596 u8 *phy, u8 *role, u8 link_cnt) 7597 { 7598 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7599 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info; 7600 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false; 7601 u8 j, k, dbcc_2g_cid = 0, dbcc_2g_cid2 = 0; 7602 7603 /* find out the 2G-PHY by connect-id ->ch */ 7604 for (j = 0; j < link_cnt; j++) { 7605 if (ch[j].center_ch <= 14) { 7606 is_2g_ch_exist = true; 7607 break; 7608 } 7609 } 7610 7611 /* If no any 2G-port exist, it's impossible because 5G-exclude */ 7612 if (!is_2g_ch_exist) 7613 return BTC_WLINK_SB_MCC; 7614 7615 dbcc_2g_cid = j; 7616 rinfo->dbcc_2g_phy = phy[dbcc_2g_cid]; 7617 7618 if (rinfo->dbcc_2g_phy == RTW89_PHY_1) 7619 rinfo->pta_req_band = RTW89_PHY_1; 7620 else 7621 rinfo->pta_req_band = RTW89_PHY_0; 7622 7623 /* connect_cnt <= 2 */ 7624 if (link_cnt < BTC_TDMA_WLROLE_MAX) 7625 return _get_role_link_mode(role[dbcc_2g_cid]); 7626 7627 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */ 7628 for (k = 0; k < link_cnt; k++) { 7629 if (k == dbcc_2g_cid) 7630 continue; 7631 7632 if (phy[k] == rinfo->dbcc_2g_phy) { 7633 is_multi_role_in_2g_phy = true; 7634 dbcc_2g_cid2 = k; 7635 break; 7636 } 7637 } 7638 7639 /* Single-role in 2G-PHY */ 7640 if (!is_multi_role_in_2g_phy) 7641 return _get_role_link_mode(role[dbcc_2g_cid]); 7642 7643 /* 2-role in 2G-PHY */ 7644 if (ch[dbcc_2g_cid2].center_ch > 14) 7645 return BTC_WLINK_DB_MCC; 7646 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2])) 7647 return BTC_WLINK_SCC; 7648 else 7649 return BTC_WLINK_SB_MCC; 7650 } 7651 7652 static void _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type) 7653 { 7654 struct rtw89_btc *btc = &rtwdev->btc; 7655 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7656 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 7657 struct rtw89_btc_wl_role_info *r = &wl->role_info; 7658 u8 p2p_exist = wl->role_info.p2p_exist[hw_band]; 7659 7660 /* MLD: nLmR --> 2L1R: 2-Link by 1-RF, 2L2R: 2-link by 2-RF */ 7661 switch (type) { 7662 case RTW89_MR_WTYPE_NONE: /* no-link */ 7663 r->link_mode[hw_band] = BTC_WLINK_NOLINK; 7664 break; 7665 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */ 7666 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */ 7667 if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { 7668 r->link_mode[hw_band] = BTC_WLINK_GO; 7669 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT && 7670 p2p_exist) { 7671 r->link_mode[hw_band] = BTC_WLINK_GC; 7672 } else { 7673 r->link_mode[hw_band] = BTC_WLINK_STA; 7674 } 7675 break; 7676 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */ 7677 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */ 7678 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ || 7679 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) { 7680 r->link_mode[hw_band] = BTC_WLINK_DB_MCC; 7681 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ || 7682 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ || 7683 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_6GHZ || 7684 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ_6GHZ) { 7685 r->link_mode[hw_band] = BTC_WLINK_SB_MCC; 7686 } else { 7687 r->link_mode[hw_band] = BTC_WLINK_SCC; 7688 } 7689 break; 7690 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */ 7691 if (p2p_exist) /* MLO_MLSR only support STA/GC */ 7692 r->link_mode[hw_band] = BTC_WLINK_GC; 7693 else 7694 r->link_mode[hw_band] = BTC_WLINK_STA; 7695 break; 7696 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */ 7697 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2*/ 7698 /* driver may doze 1-link (1+1) or 2+0->0+2->1+1 7699 * 2G+5G -> TDMA slot switch by E2G/E5G 7700 * 5G only -> TDMA slot switch by E5G 7701 */ 7702 r->link_mode[hw_band] = BTC_WLINK_DB_MCC; 7703 break; 7704 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */ 7705 /* MLMR only support STA now (2024) */ 7706 r->link_mode[hw_band] = BTC_WLINK_STA; 7707 break; 7708 } 7709 } 7710 7711 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev, u8 hw_band) 7712 { 7713 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7714 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7715 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 7716 struct rtw89_mr_chanctx_info qinfo; 7717 struct rtw89_chanctx *ch; 7718 u8 rf_band = RTW89_BAND_2G; 7719 u8 i, type; 7720 7721 /* parse MLO info form PHL API for each HW-band */ 7722 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { 7723 memset(&qinfo, 0, sizeof(qinfo)); 7724 7725 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo); 7726 7727 switch (qinfo.ctxtype) { 7728 default: 7729 mlo_info->hwb_rf_band[i] = 0; 7730 break; 7731 case RTW89_MR_CTX1_2GHZ: 7732 case RTW89_MR_CTX2_2GHZ: 7733 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G); 7734 break; 7735 case RTW89_MR_CTX1_5GHZ: 7736 case RTW89_MR_CTX2_5GHZ: 7737 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G); 7738 break; 7739 case RTW89_MR_CTX1_6GHZ: 7740 case RTW89_MR_CTX2_6GHZ: 7741 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_6G); 7742 break; 7743 case RTW89_MR_CTX2_2GHZ_5GHZ: 7744 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) | 7745 BIT(RTW89_BAND_5G); 7746 break; 7747 case RTW89_MR_CTX2_2GHZ_6GHZ: 7748 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) | 7749 BIT(RTW89_BAND_6G); 7750 break; 7751 case RTW89_MR_CTX2_5GHZ_6GHZ: 7752 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G) | 7753 BIT(RTW89_BAND_6G); 7754 break; 7755 } 7756 mlo_info->wmode[i] = qinfo.wmode; 7757 mlo_info->ch_type[i] = qinfo.ctxtype; 7758 mlo_info->wtype = qinfo.wtype; 7759 wl->rf_band_map[i] = mlo_info->hwb_rf_band[i]; 7760 ch = &rtwdev->hal.chanctx[i]; 7761 wl->rf_ch_info[i].center_ch = ch->chan.channel; 7762 wl->rf_ch_info[i].band = ch->chan.band_type; 7763 wl->rf_ch_info[i].chan = ch->chan.channel; 7764 wl->rf_ch_info[i].offset = ch->chan.pri_ch_idx; 7765 wl->rf_ch_info[i].bw = ch->chan.band_width; 7766 } 7767 7768 mlo_info->link_status = rtwdev->mlo_dbcc_mode; 7769 type = mlo_info->wtype; 7770 7771 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R || 7772 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R || 7773 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R || 7774 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD || 7775 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD || 7776 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD) 7777 mlo_info->mlo_en = 1; 7778 else 7779 mlo_info->mlo_en = 0; 7780 7781 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE && 7782 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN && 7783 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE && 7784 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN) 7785 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */ 7786 else 7787 mlo_info->dual_hw_band_en = 0; 7788 7789 if (mlo_info->link_status == MLO_2_PLUS_0_2RF || 7790 mlo_info->link_status == MLO_0_PLUS_2_2RF || 7791 mlo_info->link_status == MLO_2_PLUS_2_2RF) 7792 mlo_info->mlo_adie = 2; 7793 else 7794 mlo_info->mlo_adie = 1; 7795 7796 switch (mlo_info->link_status) { 7797 default: 7798 case MLO_2_PLUS_0_1RF: /* 2+0 */ 7799 case MLO_2_PLUS_0_2RF: 7800 _update_wl_link_mode(rtwdev, RTW89_MAC_0, type); 7801 wl_rinfo->link_mode[RTW89_MAC_1] = wl_rinfo->link_mode[RTW89_MAC_0]; 7802 wl_rinfo->pta_req_band = RTW89_MAC_0; 7803 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7804 wl_rinfo->dbcc_en = 0; 7805 7806 rf_band = wl->rf_band_map[RTW89_PHY_0]; 7807 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7808 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7809 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0; 7810 break; 7811 case MLO_0_PLUS_2_1RF: /* 0+2 */ 7812 case MLO_0_PLUS_2_2RF: 7813 _update_wl_link_mode(rtwdev, RTW89_MAC_1, type); 7814 wl_rinfo->link_mode[RTW89_MAC_0] = wl_rinfo->link_mode[RTW89_MAC_1]; 7815 wl_rinfo->pta_req_band = RTW89_MAC_1; 7816 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7817 wl_rinfo->dbcc_en = 0; 7818 7819 rf_band = wl->rf_band_map[RTW89_PHY_1]; 7820 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7821 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7822 mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2; 7823 break; 7824 case MLO_1_PLUS_1_1RF: /* 1+1 */ 7825 case MLO_1_PLUS_1_2RF: /* 1+1 */ 7826 case MLO_2_PLUS_2_2RF: /* 2+2 */ 7827 case DBCC_LEGACY: /* DBCC 1+1 */ 7828 /* Check ch count from ch_type and modify type*/ 7829 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ || 7830 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_5GHZ || 7831 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_6GHZ) 7832 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role */ 7833 else 7834 type = RTW89_MR_WTYPE_NONMLD_NONMLD; 7835 7836 rf_band = wl->rf_band_map[hw_band]; 7837 _update_wl_link_mode(rtwdev, hw_band, type); 7838 7839 if (hw_band == RTW89_MAC_0) { 7840 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7841 } else { 7842 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7843 } 7844 7845 /* set pta_req_band for 1-PTA architecture */ 7846 if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G)) { 7847 wl_rinfo->pta_req_band = RTW89_MAC_0; 7848 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7849 } else if (wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) { 7850 wl_rinfo->pta_req_band = RTW89_MAC_1; 7851 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7852 } else { /* Both HW-BAND are not on 2.4G*/ 7853 wl_rinfo->pta_req_band = RTW89_MAC_0; 7854 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7855 } 7856 7857 wl_rinfo->dbcc_en = 1; /* two HW-band both active */ 7858 7859 if (mlo_info->link_status == MLO_2_PLUS_2_2RF) 7860 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2; 7861 else 7862 mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1; 7863 break; 7864 } 7865 7866 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), link_mode(HWB0=%s/HWB1=%s), pta_band=%d", 7867 __func__, 7868 id_to_linkmode(wl_rinfo->link_mode[RTW89_MAC_0]), 7869 id_to_linkmode(wl_rinfo->link_mode[RTW89_MAC_1]), 7870 wl_rinfo->pta_req_band); 7871 } 7872 7873 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) 7874 { 7875 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7876 struct rtw89_btc_wl_rlink *rlink = NULL; 7877 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7878 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7879 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7880 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7881 bool b2g = false, b5g = false, outloop = false; 7882 u8 mode = BTC_WLINK_NOLINK; 7883 u8 cnt_2g = 0, cnt_5g = 0; 7884 u8 i, j, cnt = 0; 7885 7886 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) { 7887 wl->rf_band_map[j] = 0; /* j=link id, is the link use which band */ 7888 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 7889 rlink = &wl_rinfo->rlink[i][j]; 7890 7891 if (!rlink->active || !rlink->connected) 7892 continue; 7893 7894 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) { 7895 outloop = true; 7896 break; 7897 } 7898 7899 cid_ch[cnt] = wl->rlink_info[i][j].chdef; 7900 cid_phy[cnt] = rlink->phy; 7901 cid_role[cnt] = rlink->role; 7902 cnt++; 7903 7904 if (rlink->rf_band != RTW89_BAND_2G) { 7905 cnt_5g++; 7906 b5g = true; 7907 } else { 7908 cnt_2g++; 7909 b2g = true; 7910 } 7911 wl->rf_band_map[j] |= BIT(rlink->rf_band); 7912 } 7913 if (outloop) 7914 break; 7915 } 7916 7917 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7918 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g); 7919 7920 wl_rinfo->pta_req_band = RTW89_PHY_0; /* no 0+2 for non-MLO */ 7921 wl_rinfo->dbcc_en = rtwdev->dbcc_en; 7922 7923 /* Be careful to change the following sequence!! */ 7924 if (cnt == 0) { 7925 mode = BTC_WLINK_NOLINK; 7926 } else if (wl_rinfo->dbcc_en) { 7927 /* update pta_req_band to 2.4GHz HW-BAND for DBCC = 1*/ 7928 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); 7929 } else if (!b2g && b5g) { 7930 mode = _get_role_link_mode(cid_role[0]); 7931 } else if (b2g && b5g) { 7932 mode = BTC_WLINK_DB_MCC; 7933 } else if (cnt >= 2) { 7934 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1])) 7935 mode = BTC_WLINK_SCC; 7936 else 7937 mode = BTC_WLINK_SB_MCC; 7938 } else { 7939 mode = _get_role_link_mode(cid_role[0]); 7940 } 7941 7942 wl_rinfo->link_mode[RTW89_MAC_0] = mode; 7943 wl_rinfo->link_mode[RTW89_MAC_1] = mode; 7944 } 7945 7946 static void _sync_wl_link_mode_v0(struct rtw89_dev *rtwdev) 7947 { 7948 struct rtw89_btc_wl_role_info *r = &rtwdev->btc.cx.wl.role_info; 7949 bool has_2g = false; 7950 int i, j; 7951 7952 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER && !has_2g; i++) 7953 for (j = 0; j < RTW89_MAC_NUM && !has_2g; j++) 7954 if (r->rlink[i][j].connected && 7955 r->rlink[i][j].rf_band == RTW89_BAND_2G) 7956 has_2g = true; 7957 7958 if (!has_2g && r->link_mode[RTW89_MAC_0] != BTC_WLINK_NOLINK) { 7959 r->link_mode_v0 = BTC_WLINK_V0_5G; 7960 return; 7961 } 7962 7963 switch (r->link_mode[RTW89_MAC_0]) { 7964 case BTC_WLINK_NOLINK: 7965 r->link_mode_v0 = BTC_WLINK_V0_NOLINK; 7966 break; 7967 case BTC_WLINK_STA: 7968 r->link_mode_v0 = BTC_WLINK_V0_2G_STA; 7969 break; 7970 case BTC_WLINK_AP: 7971 r->link_mode_v0 = BTC_WLINK_V0_2G_AP; 7972 break; 7973 case BTC_WLINK_GO: 7974 r->link_mode_v0 = BTC_WLINK_V0_2G_GO; 7975 break; 7976 case BTC_WLINK_GC: 7977 r->link_mode_v0 = BTC_WLINK_V0_2G_GC; 7978 break; 7979 case BTC_WLINK_SCC: 7980 r->link_mode_v0 = BTC_WLINK_V0_2G_SCC; 7981 break; 7982 case BTC_WLINK_SB_MCC: 7983 r->link_mode_v0 = BTC_WLINK_V0_2G_MCC; 7984 break; 7985 case BTC_WLINK_DB_MCC: 7986 r->link_mode_v0 = BTC_WLINK_V0_25G_MCC; 7987 break; 7988 default: 7989 r->link_mode_v0 = BTC_WLINK_V0_OTHER; 7990 break; 7991 } 7992 } 7993 7994 static void _modify_role_link_mode(struct rtw89_dev *rtwdev, u8 hw_band) 7995 { 7996 struct rtw89_btc *btc = &rtwdev->btc; 7997 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7998 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7999 u8 go_cleint_exist = wl->go_client_exist[hw_band]; 8000 u8 *link_mode = &wl_rinfo->link_mode[hw_band]; 8001 u32 role_map = wl_rinfo->role_map[hw_band]; 8002 u8 noa_exist = wl->noa_exist[hw_band]; 8003 u32 mrole = BTC_WLMROLE_NONE; 8004 8005 /* if no client_joined, don't care P2P-GO/AP role */ 8006 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 8007 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) { 8008 if (*link_mode == BTC_WLINK_SCC) { 8009 *link_mode = BTC_WLINK_STA; 8010 } else if (*link_mode == BTC_WLINK_GO || 8011 *link_mode == BTC_WLINK_AP) { 8012 *link_mode = BTC_WLINK_NOLINK; 8013 } 8014 } 8015 8016 /* Identify 2-Role type */ 8017 if (*link_mode == BTC_WLINK_SCC || 8018 *link_mode == BTC_WLINK_SB_MCC || 8019 *link_mode == BTC_WLINK_DB_MCC) { 8020 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 8021 (role_map & BIT(RTW89_WIFI_ROLE_AP))) { 8022 if (noa_exist) 8023 mrole = BTC_WLMROLE_STA_GO_NOA; 8024 else 8025 mrole = BTC_WLMROLE_STA_GO; 8026 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) { 8027 if (noa_exist) 8028 mrole = BTC_WLMROLE_STA_GC_NOA; 8029 else 8030 mrole = BTC_WLMROLE_STA_GC; 8031 } else { 8032 mrole = BTC_WLMROLE_STA_STA; 8033 } 8034 8035 if (hw_band == RTW89_PHY_0) { 8036 wl_rinfo->mrole_type &= GENMASK(31, 16); /* clear Low-Word */ 8037 wl_rinfo->mrole_type |= mrole; 8038 } else { 8039 wl_rinfo->mrole_type &= GENMASK(15, 0); /* clear high-Word */ 8040 wl_rinfo->mrole_type |= (mrole << 16); 8041 } 8042 } else { 8043 wl_rinfo->mrole_type = BTC_WLMROLE_NONE; 8044 } 8045 8046 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8047 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__, 8048 id_to_linkmode(*link_mode), wl_rinfo->mrole_type); 8049 } 8050 8051 static void _update_wl_info(struct rtw89_dev *rtwdev, struct rtw89_btc_wl_link_info *wl_linfo) 8052 { 8053 struct rtw89_btc *btc = &rtwdev->btc; 8054 struct rtw89_btc_dm *dm = &btc->dm; 8055 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8056 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 8057 struct rtw89_btc_wl_rlink *rlink = NULL; 8058 u8 dbcc_en_ori, is_5g_hi_ch = 0, bg_mode = 0, p2p_exist = 0; 8059 u8 go_client_exist = 0, noa_exist = 0; 8060 u8 rlink_id = wl_linfo->phy; 8061 u8 role_id = wl_linfo->pid; 8062 u8 i, link_mode_ori; 8063 u32 role_map = 0; 8064 8065 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM) 8066 return; 8067 8068 /* 8069 * Extract wl->link_info[role_id][rlink_id] to wl->role_info 8070 * role_id: role index 8071 * rlink_id: rlink index (= HW-band index) 8072 * pid: port_index 8073 */ 8074 rlink = &wl_rinfo->rlink[role_id][rlink_id]; 8075 8076 rlink->role = wl_linfo->role; 8077 rlink->active = wl_linfo->active; /* Doze or not */ 8078 rlink->pid = wl_linfo->pid; 8079 rlink->mac_id = wl_linfo->mac_id; 8080 rlink->phy = wl_linfo->phy; 8081 rlink->rf_band = wl_linfo->chdef.band; 8082 rlink->ch = wl_linfo->chdef.center_ch; 8083 rlink->bw = wl_linfo->chdef.bw; 8084 rlink->noa = wl_linfo->noa; 8085 rlink->noa_dur = wl_linfo->noa_duration / 1000; 8086 rlink->client_cnt = wl_linfo->client_cnt; 8087 rlink->mode = wl_linfo->mode; 8088 8089 /* check if rlink connect? */ 8090 switch (wl_linfo->connected) { 8091 case MLME_NO_LINK: 8092 rlink->connected = 0; 8093 break; 8094 case MLME_LINKED: 8095 rlink->connected = 1; 8096 8097 /* reset special-AP flag if station mode linked */ 8098 dm->leak_ap = 0; 8099 break; 8100 default: 8101 return; 8102 } 8103 8104 /* update by HW-Band */ 8105 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { /* i = role_id */ 8106 rlink = &wl_rinfo->rlink[i][rlink_id]; 8107 8108 if (!rlink->active || !rlink->connected) 8109 continue; 8110 8111 role_map |= BIT(rlink->role); 8112 8113 /* Identify if P2P-Go (GO/GC/AP) exist at 2GHz band */ 8114 if (((rlink->role == RTW89_WIFI_ROLE_P2P_GO || 8115 rlink->role == RTW89_WIFI_ROLE_AP) && 8116 rlink->client_cnt > 1)) { 8117 p2p_exist = 1; 8118 go_client_exist = 1; 8119 } 8120 8121 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT) 8122 p2p_exist = 1; 8123 8124 /* only one noa-role exist */ 8125 if (rlink->noa && rlink->noa_dur > 0) 8126 noa_exist = 1; 8127 8128 /* for WL 5G-Rx interfered with BT issue */ 8129 if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100) 8130 is_5g_hi_ch = 1; 8131 8132 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || 8133 (rlink->mode & BIT(BTC_WL_MODE_11G))) 8134 bg_mode = 1; 8135 } 8136 8137 link_mode_ori = wl_rinfo->link_mode[rlink_id]; 8138 wl->is_5g_hi_ch[rlink_id] = is_5g_hi_ch; 8139 wl->bg_mode[rlink_id] = bg_mode; 8140 wl->go_client_exist[rlink_id] = go_client_exist; 8141 wl->noa_exist[rlink_id] = noa_exist; 8142 wl_rinfo->p2p_exist[rlink_id] = p2p_exist; 8143 wl_rinfo->role_map[rlink_id] = role_map; 8144 8145 dbcc_en_ori = wl_rinfo->dbcc_en; 8146 8147 /* for MLO-supported, link-mode from driver directly */ 8148 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { 8149 _update_wl_mlo_info(rtwdev, rlink_id); 8150 } else { /* for non-MLO-supported, link-mode by BTC */ 8151 _update_wl_non_mlo_info(rtwdev); 8152 } 8153 8154 _modify_role_link_mode(rtwdev, rlink_id); 8155 _sync_wl_link_mode_v0(rtwdev); 8156 8157 if (wl_rinfo->link_mode[rlink_id] != link_mode_ori) { 8158 wl_rinfo->link_mode_chg = 1; 8159 wl->link_mode_chg = 1; 8160 } 8161 8162 if (wl_rinfo->dbcc_en != dbcc_en_ori) { 8163 wl->dbcc_chg = 1; 8164 wl->role_info.dbcc_chg = 1; 8165 wl->wcnt[BTC_WCNT_DBCC_CHG]++; 8166 } 8167 } 8168 8169 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work) 8170 { 8171 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8172 coex_act1_work.work); 8173 struct rtw89_btc *btc = &rtwdev->btc; 8174 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8175 struct rtw89_btc_cx *cx = &btc->cx; 8176 struct rtw89_btc_wl_info *wl = &cx->wl; 8177 8178 lockdep_assert_wiphy(wiphy); 8179 8180 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 8181 dm->cnt_notify[BTC_NCNT_TIMER]++; 8182 if (wl->status.map.handshake || 8183 wl->status.map._4way || 8184 wl->status.map.dhcp) { 8185 wl->status.map._4way = 0; 8186 wl->status.map.dhcp = 0; 8187 wl->status.map.handshake = 0; 8188 } 8189 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 8190 } 8191 8192 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work) 8193 { 8194 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8195 coex_bt_devinfo_work.work); 8196 struct rtw89_btc *btc = &rtwdev->btc; 8197 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8198 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 8199 8200 lockdep_assert_wiphy(wiphy); 8201 8202 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 8203 dm->cnt_notify[BTC_NCNT_TIMER]++; 8204 a2dp->play_latency = 0; 8205 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 8206 } 8207 8208 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work) 8209 { 8210 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 8211 coex_rfk_chk_work.work); 8212 struct rtw89_btc *btc = &rtwdev->btc; 8213 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8214 struct rtw89_btc_cx *cx = &btc->cx; 8215 struct rtw89_btc_wl_info *wl = &cx->wl; 8216 8217 lockdep_assert_wiphy(wiphy); 8218 8219 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 8220 dm->cnt_notify[BTC_NCNT_TIMER]++; 8221 if (wl->rfk_info.state != BTC_WRFK_STOP) { 8222 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8223 "[BTC], %s(): RFK timeout\n", __func__); 8224 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]++; 8225 dm->error.map.wl_rfk_timeout = true; 8226 wl->rfk_info.state = BTC_WRFK_STOP; 8227 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false); 8228 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 8229 } 8230 } 8231 8232 static void _update_bt_ctrl_lps(struct rtw89_dev *rtwdev) 8233 { 8234 struct rtw89_btc *btc = &rtwdev->btc; 8235 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 8236 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 8237 struct rtw89_btc_dm *dm = &btc->dm; 8238 bool lps_ctrl = false; 8239 8240 if (dm->out_of_band || dm->freerun) 8241 lps_ctrl = false; 8242 else if (bt0->whql_test || bt1->whql_test) 8243 lps_ctrl = true; 8244 else if (bt0->link_info.a2dp_desc.exist || 8245 bt0->link_info.hfp_desc.exist || 8246 bt0->link_info.pan_desc.exist) 8247 lps_ctrl = true; 8248 else if (bt1->link_info.a2dp_desc.exist || 8249 bt1->link_info.hfp_desc.exist || 8250 bt1->link_info.pan_desc.exist) 8251 lps_ctrl = true; 8252 8253 if (dm->lps_ctrl_scbd != lps_ctrl) { 8254 dm->lps_ctrl_scbd = lps_ctrl; 8255 dm->lps_ctrl_change = true; 8256 } else { 8257 dm->lps_ctrl_change = false; 8258 } 8259 } 8260 8261 static u32 _read_scbd(struct rtw89_dev *rtwdev, u8 id) 8262 { 8263 const struct rtw89_chip_info *chip = rtwdev->chip; 8264 u32 val; 8265 8266 if (!chip->scbd) 8267 return 0; 8268 8269 val = rtw89_read32(rtwdev, chip->btc_sb.n[id].get); 8270 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8271 "[BTC], read scbd bt%d: 0x%08x\n", id, val); 8272 return val; 8273 } 8274 8275 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid, bool is_c2h) 8276 { 8277 struct rtw89_btc_bt_link_info *bt_2g, *bt_56g; 8278 struct rtw89_btc *btc = &rtwdev->btc; 8279 struct rtw89_btc_cx *cx = &btc->cx; 8280 struct rtw89_btc_dm *dm = &btc->dm; 8281 struct rtw89_btc_bt_info *bt; 8282 u32 val, any_bt_connect, any_bt_6g_connect = 0; 8283 bool bt_link_change = false; 8284 u8 id, id_start, id_stop; 8285 8286 if (!rtwdev->chip->scbd || bid > BTC_ALL_BT) 8287 return; 8288 8289 if (bid == BTC_ALL_BT) { 8290 id_start = BTC_BT_1ST; 8291 id_stop = BTC_BT_2ND; 8292 } else { 8293 id_start = bid; 8294 id_stop = bid; 8295 } 8296 8297 dm->lps_ctrl_change = false; 8298 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s()\n", __func__); 8299 8300 for (id = id_start; id <= id_stop; id++) { 8301 bt = (id == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 8302 bt_2g = &bt->link_info; 8303 bt_56g = &bt->link_info_56g; 8304 8305 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && id == BTC_BT_2ND) 8306 break; 8307 8308 val = is_c2h ? bt->scbd_c2h : _read_scbd(rtwdev, id); 8309 8310 if (val == 0xffffffff) { 8311 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8312 "[BTC], %s return by invalid scbd value\n", 8313 __func__); 8314 return; 8315 } 8316 8317 if (!(val & BTC_BSCB_ON)) 8318 bt->enable.now = 0; 8319 else 8320 bt->enable.now = 1; 8321 8322 if (bt->enable.now != bt->enable.last) 8323 bt_link_change = true; 8324 8325 /* reset bt info if bt re-enable */ 8326 if (bt->enable.now && !bt->enable.last) { 8327 if (id == BTC_BT_1ST) 8328 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 8329 else 8330 _reset_btc_var(rtwdev, BTC_RESET_BTINFO2); 8331 8332 bt->bcnt[BTC_BCNT_REENABLE]++; 8333 bt->enable.now = 1; 8334 bt->rf_band_map = BIT(RTW89_BAND_2G); 8335 bt->link_weight[BTC_BT_B2G] = 5; /* no-profile */ 8336 } 8337 bt->enable.last = bt->enable.now; 8338 8339 /* if BT will disconnect and adopt protect plan */ 8340 if ((val & BTC_BSCB_BT_PROTECT) && 8341 !(bt->scbd & BTC_BSCB_BT_PROTECT)) 8342 bt->bcnt[BTC_BCNT_PROTECT]++; 8343 8344 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 8345 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 8346 bt_link_change = true; 8347 8348 bt->whql_test = !!(val & BTC_BSCB_WHQL); 8349 bt->btg_type = (val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE); 8350 8351 bt_2g->a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 8352 bt_2g->pan_desc.exist = !!(val & BTC_BSCB_PAN_ACT); 8353 bt_2g->hfp_desc.exist = !!(val & BTC_BSCB_HFP_ACT); 8354 bt_2g->hid_desc.exist = !!(val & BTC_BSCB_HID_ACT); 8355 8356 bt->lna_constrain = 4 + !!(val & BTC_BSCB_BT_LNAB0) + 8357 !!(val & BTC_BSCB_BT_LNAB1) * 2; 8358 8359 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 8360 if ((val & BTC_BSCB_BT_15DOT4_TRX) != 8361 (bt->scbd & BTC_BSCB_BT_15DOT4_TRX)) 8362 _update_sdm_map(rtwdev); 8363 8364 if (val & BTC_BSCB_BT_15DOT4) 8365 bt->func_type |= (BTC_BTF_THREAD | BTC_BTF_ZB); 8366 else 8367 bt->func_type &= ~(BTC_BTF_THREAD | BTC_BTF_ZB); 8368 } 8369 8370 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 8371 any_bt_connect = !!(val & BTC_BSCB_BT_CONNECT); 8372 8373 /* if connect change */ 8374 if (bt_2g->status.map.connect != any_bt_connect || 8375 bt_56g->status.map.connect != any_bt_6g_connect) { 8376 bt_link_change = true; 8377 bt_2g->status.map.connect = any_bt_connect; 8378 bt_56g->status.map.connect = any_bt_6g_connect; 8379 } 8380 8381 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 8382 bt->scbd = val; 8383 } 8384 8385 _update_bt_ctrl_lps(rtwdev); 8386 8387 if (bt_link_change) { 8388 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8389 "[BTC], %s: bt status change!!\n", __func__); 8390 /* TODO: Need to notify driver to update EXT-CTRL-BT-SLOT */ 8391 } 8392 } 8393 8394 static void _update_bt_link_cnt(struct rtw89_dev *rtwdev, 8395 struct rtw89_btc_bt_info *bt, bool b56g) 8396 { 8397 struct rtw89_btc_bt_link_info *b = b56g ? &bt->link_info_56g : 8398 &bt->link_info; 8399 struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc; 8400 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 8401 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 8402 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 8403 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 8404 u8 bt_rf_band = b56g ? BTC_BT_B5G : BTC_BT_B2G; 8405 u8 val; 8406 8407 b->link_cnt.last = b->link_cnt.now; 8408 b->link_cnt.now = 0; 8409 b->link_cnt.chg = 0; 8410 8411 b->link_cnt.now += hfp->exist; 8412 b->link_cnt.now += hid->exist; 8413 b->link_cnt.now += a2dp->exist; 8414 b->link_cnt.now += pan->exist; 8415 b->link_cnt.now += leaudio->bis_exist; 8416 b->link_cnt.now += leaudio->cis_exist; 8417 8418 if (leaudio->bis_exist || a2dp->sink) { 8419 val = 70; 8420 } else if (a2dp->exist) { 8421 val = 40; 8422 if (a2dp->vendor_id == 0x4c) 8423 val += 10; 8424 if (hid->exist) 8425 val += 10; 8426 } else if (pan->exist || pan->active || a2dp->active || 8427 b->status.map.inq_pag) { 8428 val = 30; 8429 } else if (b->link_cnt.now == 0) { 8430 val = 5; 8431 } else { 8432 val = 9; 8433 } 8434 bt->link_weight[bt_rf_band] = val; 8435 8436 if (b->link_cnt.last != b->link_cnt.now) 8437 b->link_cnt.chg = 1; 8438 } 8439 8440 static void _update_bt_leaudio_info(struct rtw89_dev *rtwdev, u8 bid, 8441 void *buf, u32 len) 8442 { 8443 const struct rtw89_chip_info *chip = rtwdev->chip; 8444 struct rtw89_btc *btc = &rtwdev->btc; 8445 struct rtw89_btc_cx *cx = &btc->cx; 8446 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 8447 struct rtw89_btc_bt_link_info *b = &bt->link_info; 8448 struct rtw89_btc_bt_leaudio_info *src = buf; 8449 struct rtw89_btc_bt_leaudio_desc *leaudio; 8450 bool bt_56g = false, cis_exist, bis_exist; 8451 u8 bis_cnt, cis_cnt; 8452 8453 if ((src->len & BIT(7)) && bt->band_56G_support) { 8454 b = &bt->link_info_56g; 8455 bt_56g = true; 8456 } 8457 8458 leaudio = &b->leaudio_desc; 8459 8460 if (!memcmp(b->leaudio_raw_info, src, BTC_BTINFO_MAX)) { 8461 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8462 "[BTC], %s return by leaudio-info duplicate!\n", 8463 __func__); 8464 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; 8465 return; 8466 } 8467 8468 memcpy(b->leaudio_raw_info, src, BTC_BTINFO_MAX); 8469 8470 bis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_EX); 8471 cis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_EX); 8472 bis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_CNT); 8473 cis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_CNT); 8474 8475 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8476 "[BTC], %s: bis_exist:%d bis_cnt:%d cis_exist:%d cis_cnt:%d rssi:%d\n", 8477 __func__, bis_exist, bis_cnt, cis_exist, cis_cnt, src->rssi); 8478 8479 if (!bis_exist && !cis_exist) 8480 memset(leaudio, 0, sizeof(*leaudio)); 8481 8482 leaudio->bis_cnt = bis_cnt; 8483 leaudio->bis_exist = bis_exist; 8484 leaudio->cis_cnt = cis_cnt; 8485 leaudio->cis_exist = cis_exist; 8486 8487 if (leaudio->bis_exist) 8488 b->status.map.profile_map |= BTC_BT_BIS; 8489 else 8490 b->status.map.profile_map &= ~BTC_BT_BIS; 8491 8492 if (leaudio->cis_exist) 8493 b->status.map.profile_map |= BTC_BT_CIS; 8494 else 8495 b->status.map.profile_map &= ~BTC_BT_CIS; 8496 8497 _update_bt_link_cnt(rtwdev, bt, bt_56g); 8498 8499 leaudio->rssi = chip->ops->btc_get_bt_rssi(rtwdev, src->rssi); 8500 8501 leaudio->bis_cnt_last = leaudio->bis_cnt; 8502 leaudio->bis_exist_last = leaudio->bis_exist; 8503 leaudio->cis_cnt_last = leaudio->cis_cnt; 8504 leaudio->cis_exist_last = leaudio->cis_exist; 8505 } 8506 8507 static void _update_bt_bistdma_info(struct rtw89_dev *rtwdev, u8 bid, 8508 void *buf, u32 len) 8509 { 8510 struct rtw89_btc *btc = &rtwdev->btc; 8511 struct rtw89_btc_cx *cx = &btc->cx; 8512 struct rtw89_btc_dm *dm = &btc->dm; 8513 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 8514 struct rtw89_btc_bt_link_info *b = &bt->link_info; 8515 struct rtw89_btc_bt_bistdma_info_le *src = buf; 8516 struct rtw89_btc_bt_leaudio_desc *leaudio; 8517 8518 if ((src->len & BIT(7)) && bt->band_56G_support) 8519 b = &bt->link_info_56g; 8520 8521 leaudio = &b->leaudio_desc; 8522 8523 if (!memcmp(b->bistdma_raw_info, src, BTC_BTINFO_MAX)) { 8524 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8525 "[BTC], %s return by bistdma-info duplicate!\n", 8526 __func__); 8527 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++; 8528 return; 8529 } 8530 8531 memcpy(b->bistdma_raw_info, src, BTC_BTINFO_MAX); 8532 8533 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8534 "[BTC], %s: bis_start_end:%d bis_trx:%d\n", 8535 __func__, 8536 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_START_END), 8537 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX)); 8538 8539 leaudio->bis_trx = u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX); 8540 leaudio->bis_start_end = u8_get_bits(src->bis, 8541 RTW89_BTC_BIS_INFO_L2_START_END); 8542 8543 leaudio->diff_t = (src->diff_t_hb * 256 + src->diff_t_lb) * 625 / 1000; 8544 8545 if (btc->ant_type == BTC_ANT_SHARED && leaudio->diff_t > 13) 8546 dm->bis_tdma = true; 8547 else 8548 dm->bis_tdma = false; 8549 } 8550 8551 #define BTC_BTINFO_PWR_LEN 5 8552 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 bid, u8 *buf, 8553 u32 len) 8554 { 8555 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 8556 struct rtw89_btc_bt_link_info *b; 8557 struct rtw89_btc_bt_info *bt; 8558 8559 if (len != BTC_BTINFO_PWR_LEN) 8560 return; 8561 8562 bt = bid == BTC_BT_1ST ? &cx->bt0 : &cx->bt1; 8563 8564 if ((buf[BTC_BTINFO_L1] & BIT(7)) && bt->band_56G_support) 8565 b = &bt->link_info_56g; 8566 else 8567 b = &bt->link_info; 8568 8569 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) { 8570 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8571 "[BTC], %s return by info duplicate!\n", __func__); 8572 return; 8573 } 8574 8575 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX); 8576 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc)); 8577 } 8578 8579 static void _set_bind_info(struct rtw89_btc *btc, u8 type) 8580 { 8581 struct rtw89_btc_cx *cx = &btc->cx; 8582 struct rtw89_btc_dm *dm = &btc->dm; 8583 struct rtw89_btc_wl_info *wl = &cx->wl; 8584 struct rtw89_btc_bt_info *bt = &cx->bt0; 8585 struct rtw89_btc_bt_link_info *b; 8586 struct rtw89_btc_bind_info *bd; 8587 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 8588 u8 link_weight[BTC_ALL_BT_EZL][BTC_BT_BMAX]; 8589 u8 map[BTC_RF_NUM][BTC_ALL_BT_EZL]; 8590 u8 b2g_score = 0, b5g_score = 0; 8591 u8 i, j, rf_band_map, thres; 8592 u8 weight[BTC_BT_BMAX] = {}; 8593 8594 if (type == BTC_MECH_TDD) { 8595 bd = &dm->tdd_bind; 8596 memcpy(map, dm->tdd_map, sizeof(map)); 8597 thres = 30; /* BT profile score threshold for TDMA */ 8598 } else { 8599 bd = &dm->fdd_bind; 8600 memcpy(map, dm->fdd_map, sizeof(map)); 8601 thres = 5; 8602 } 8603 8604 memset(bd, 0, sizeof(*bd)); 8605 /* compare BT 2GHz/5GHz profile by link-weighting */ 8606 for (i = 0; i < BTC_BT_BMAX; i++) { 8607 if (!cx->bt0.enable.now) 8608 cx->bt0.link_weight[i] = 0; 8609 if (!cx->bt1.enable.now) 8610 cx->bt1.link_weight[i] = 0; 8611 link_weight[BTC_BT_1ST][i] = cx->bt0.link_weight[i]; 8612 link_weight[BTC_BT_2ND][i] = cx->bt1.link_weight[i]; 8613 link_weight[BTC_BT_EXT][i] = cx->bt_ext.link_weight[i]; 8614 } 8615 8616 /* 8617 * get 2GHz/5GHz link weight score by "band-overlap" map 8618 * link_weight from _update_bt_link_cnt(), 8619 * if link_weight >30 --> TDMA-required 8620 */ 8621 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8622 rf_band_map = map[BTC_RF_S0][j] | map[BTC_RF_S1][j]; 8623 if (rf_band_map & BIT(RTW89_BAND_2G)) 8624 b2g_score += link_weight[j][BTC_BT_B2G]; 8625 if (rf_band_map & BIT(RTW89_BAND_5G)) 8626 b5g_score += link_weight[j][BTC_BT_B5G]; 8627 } 8628 8629 /* 8630 * Consider WL RFK band for coex (avoid missing RFK case) 8631 * If WL is doing RFK, check RFK band vs BT band overlap 8632 * Only add score when RFK band matches BT band 8633 */ 8634 if (wl->rfk_info.state != BTC_WRFK_STOP) { 8635 if (wl->rfk_info.band == RTW89_BAND_2G) { 8636 /* RFK on 2.4GHz, check if any BT is also on 2.4GHz */ 8637 if ((cx->bt0.rf_band_map & BIT(RTW89_BAND_2G)) || 8638 (cx->bt1.rf_band_map & BIT(RTW89_BAND_2G))) 8639 b2g_score = thres; 8640 } else if (wl->rfk_info.band == RTW89_BAND_5G || 8641 wl->rfk_info.band == RTW89_BAND_6G) { 8642 /* RFK on 5/6GHz, check if any BT is also on 5GHz */ 8643 if ((cx->bt0.rf_band_map & BIT(RTW89_BAND_5G)) || 8644 (cx->bt1.rf_band_map & BIT(RTW89_BAND_5G))) 8645 b5g_score = thres; 8646 } 8647 } 8648 8649 /* rf-band bound by comparing link weight */ 8650 if (b2g_score == 0 && b5g_score == 0) /* no-rf-band overlap */ 8651 bd->rf_band = 0; 8652 else if (b5g_score > b2g_score) 8653 bd->rf_band = BIT(BTC_BT_B5G); 8654 else 8655 bd->rf_band = BIT(BTC_BT_B2G); 8656 8657 /* 8658 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1 8659 * Therefore, BTC_MLO_RF_xxx is not real-time state. 8660 * In this case, RF_S0->HWB0, RF_S1->HWB1 8661 * If link-mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO) 8662 * HW-Band is decided by wl->mlo_info.mrcx_act_hwb_map 8663 */ 8664 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) { 8665 if (wl->role_info.link_mode[RTW89_MAC_0] != BTC_WLINK_DB_MCC) { /* mode chg */ 8666 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_MAC_1)) 8667 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* S0/1->HWB1 */ 8668 else 8669 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* S0/1->HWB0 */ 8670 } 8671 } else { 8672 /* 8673 * Dual-RF_band(HWB)TDMA if BT-profile is TDMA-type at both 8674 * 2GHz and 5GHz. 8675 * ex: 1+1: HWB0 5GHz + BT0 5GHz (BIS, HDT) 8676 * && HWB1 2.4GHz + BT1 2.4GHz(PAN) 8677 * for TDD: the link score must > 30 (from _bt_link_cnt) 8678 * for FDD: the link score must > 5 (bt enable) 8679 */ 8680 if ((wl->mlo_info.rf_combination == BTC_MLO_RF_1_PLUS_1 || 8681 wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_2) && 8682 (b2g_score >= thres && b5g_score >= thres)) { 8683 bd->rf_band = BIT(BTC_BT_B2G) | BIT(BTC_BT_B5G); 8684 } 8685 8686 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0) 8687 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */ 8688 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2) 8689 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */ 8690 } 8691 8692 /* Get HWB-sel and BT-sel by rf-band-binding */ 8693 for (i = 0; i < BTC_RF_NUM; i++) { 8694 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8695 if (!(map[i][j] & bd->rf_band)) /* no-overlap */ 8696 continue; 8697 8698 bd->wl_hwb_sel |= BIT(path_hwb[i]); 8699 bd->bt_sel |= BIT(j); 8700 } 8701 } 8702 8703 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L2R && 8704 (bd->wl_hwb_sel == (BIT(RTW89_MAC_1) | BIT(RTW89_MAC_0)))) { 8705 if (wl->role_info.link_mode[RTW89_MAC_0] == BTC_WLINK_AP || 8706 wl->role_info.link_mode[RTW89_MAC_1] == BTC_WLINK_AP) 8707 bd->wl_link_mode = BTC_WLINK_DB_MCC; 8708 else 8709 bd->wl_link_mode = BTC_WLINK_STA; 8710 bd->wl_bg_mode = wl->bg_mode[RTW89_MAC_0] | wl->bg_mode[RTW89_MAC_1]; 8711 } else if (bd->wl_hwb_sel == (BIT(RTW89_MAC_1))) { 8712 bd->wl_link_mode = wl->role_info.link_mode[RTW89_MAC_1]; 8713 bd->wl_bg_mode = wl->bg_mode[RTW89_MAC_1]; 8714 } else {/* HW-BAND-0 or no-hw-band */ 8715 bd->wl_hwb_sel = BIT(RTW89_MAC_0); 8716 bd->wl_link_mode = wl->role_info.link_mode[RTW89_MAC_0]; 8717 bd->wl_bg_mode = wl->bg_mode[RTW89_MAC_0]; 8718 } 8719 8720 /* update Bind-BT status map for BT0/BT1 */ 8721 for (i = BTC_BT_1ST; i < BTC_ALL_BT_EZL; i++) { 8722 if (!(bd->bt_sel & BIT(i))) 8723 continue; 8724 8725 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) { 8726 if (!(bd->rf_band & BIT(j))) 8727 continue; 8728 8729 if (i == BTC_BT_EXT) { 8730 bd->bt_profile |= cx->bt_ext.profile_map[j]; 8731 weight[j] = cx->bt_ext.link_weight[j]; 8732 if (weight[j] > bd->bt_link_weight) /* max */ 8733 bd->bt_link_weight = weight[j]; 8734 continue; 8735 } else if (i == BTC_BT_1ST) { 8736 bt = &cx->bt0; 8737 } else { 8738 bt = &cx->bt1; 8739 } 8740 8741 if (j == BTC_BT_B2G) 8742 b = &bt->link_info; 8743 else 8744 b = &bt->link_info_56g; 8745 8746 bd->bt_profile |= b->status.map.profile_map; 8747 bd->bt_smap.a2dp_active |= b->a2dp_desc.active; 8748 bd->bt_smap.a2dp_sink |= b->a2dp_desc.sink; 8749 bd->bt_smap.pan_active |= b->pan_desc.active; 8750 bd->bt_smap.connect |= b->status.map.connect; 8751 bd->bt_smap.hid_cnt += b->hid_desc.pair_cnt; 8752 bd->bt_smap.hid_type |= b->hid_desc.type; 8753 bd->bt_smap.cis_cnt += b->leaudio_desc.cis_cnt; 8754 bd->bt_smap.link_cnt += b->link_cnt.now; 8755 bd->bt_smap.inq_page |= b->status.map.inq_pag; 8756 bd->bt_smap.page |= b->pag; 8757 8758 if (bt->link_weight[j] > bd->bt_link_weight) /* max */ 8759 bd->bt_link_weight = bt->link_weight[j]; 8760 8761 if (b->slave_role) 8762 bd->bt_smap.slave_role = b->slave_role; 8763 8764 if (b->a2dp_desc.vendor_id != 0) 8765 bd->bt_smap.a2dp_vendor_id = 8766 b->a2dp_desc.vendor_id; 8767 } 8768 } 8769 8770 if (bd->bt_profile & BTC_BT_HFP) 8771 bd->bt_smap.hfp_exist = 1; 8772 if (bd->bt_profile & BTC_BT_HID) 8773 bd->bt_smap.hid_exist = 1; 8774 if (bd->bt_profile & BTC_BT_A2DP) 8775 bd->bt_smap.a2dp_exist = 1; 8776 if (bd->bt_profile & BTC_BT_PAN) 8777 bd->bt_smap.pan_exist = 1; 8778 if (bd->bt_profile & BTC_BT_BIS) 8779 bd->bt_smap.bis_exist = 1; 8780 if (bd->bt_profile & BTC_BT_CIS) 8781 bd->bt_smap.cis_exist = 1; 8782 if (bd->bt_profile & BTC_BT_THREAD) 8783 bd->bt_smap.thread_exist = 1; 8784 if (bd->bt_profile & BTC_BT_ULL) 8785 bd->bt_smap.ull_exist = 1; 8786 } 8787 8788 /* 8789 * Get the only WL RF-path that still receives under 1SS MIMO-PS. 8790 * 8791 * Single source of truth for "is WL Rx confined to one RF-path, and which 8792 * one". Both _update_sdm_map() (xtk_xmap) and _set_coex_binding() (fit_map) 8793 * must agree, otherwise the two maps describe different WL Rx topologies. 8794 * 8795 * Conditions: 8796 * - rx_limit: the BB/RF was actually programmed to 1SS by _set_trx_nss() 8797 * - DL only: rx_limit shrinks the Rx stream, WL Tx still runs 2SS/2TX on both 8798 * paths for UL, so every path stays BT-interactive there 8799 * - 2+0/0+2 only: both RF-path serve the same link on one HW-band, so there 8800 * is an unused path. In 1+1/2+2 each RF-path serves its own link on its own 8801 * HW-band and none of them can be dropped 8802 * 8803 * Return dm->wl_trx_nss.rx_path (RF_PATH_A/B, == BTC_RF_S0/S1) if 1SS 8804 * MIMO-PS is active, RF_PATH_AB if WL keeps both Rx paths. 8805 */ 8806 static u8 _get_sdm_1ss_path(struct rtw89_dev *rtwdev) 8807 { 8808 struct rtw89_btc_wl_trx_nss_para *trx_nss = &rtwdev->btc.dm.wl_trx_nss; 8809 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 8810 8811 if (!trx_nss->rx_limit || 8812 !(wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))) 8813 return RF_PATH_AB; 8814 8815 if (wl->mlo_info.rf_combination != BTC_MLO_RF_2_PLUS_0 && 8816 wl->mlo_info.rf_combination != BTC_MLO_RF_0_PLUS_2) 8817 return RF_PATH_AB; 8818 8819 /* 8820 * rx_path is what _set_trx_nss() passed to cfg_trx_path(), it must be 8821 * a single path to be used as an RF-path index below 8822 */ 8823 if (trx_nss->rx_path != RF_PATH_A && trx_nss->rx_path != RF_PATH_B) 8824 return RF_PATH_AB; 8825 8826 return trx_nss->rx_path; 8827 } 8828 8829 static void _update_sdm_map(struct rtw89_dev *rtwdev) 8830 { 8831 struct rtw89_btc *btc = &rtwdev->btc; 8832 struct rtw89_btc_module *module = &btc->mdinfo; 8833 struct rtw89_btc_cx *cx = &btc->cx; 8834 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 8835 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 8836 struct rtw89_btc_wl_info *wl = &cx->wl; 8837 struct rtw89_btc_dm *dm = &btc->dm; 8838 u8 map[BTC_RF_NUM][BTC_ALL_BT_EZL]; 8839 bool mlo_1_plus_1 = false; 8840 u8 used_path; 8841 u8 i, j; 8842 8843 /* 8844 * xtk_xmap(Cross-talk map)-> 1: interaction, 0: no-interaction 8845 * calculate WL/BT interference by SIR 8846 * ==>1:If WL_RSSI < (BT-Pin -SIR), it means BT-Tx interfer with WL-Rx 8847 * ==>BT-pin = BT-Tx-Power - Ant-isolation 8848 */ 8849 if (wl->mlo_info.wtype != RTW89_MR_WTYPE_MLD2L1R_NONMLD && 8850 (wl->mlo_info.rf_combination == BTC_MLO_RF_1_PLUS_1 || 8851 wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_2)) 8852 mlo_1_plus_1 = true; 8853 8854 /* 8855 * WL running 1SS MIMO-PS (CIS LE-audio): WL Rx is confined to a single 8856 * path. The used path co-Rx with its co-ant BT (=1) or follows RSSI vs. 8857 * the other BT; the unused path no longer co-Rx with any BT (=0). 8858 * RF_PATH_AB -> not 1SS, keep the original per-path logic. 8859 * 8860 * Record it: this function also runs at the _set_trx_nss() exit, after 8861 * rx_limit/rx_path changed, so dm->fit_used_path stays the up-to-date 8862 * 1SS state for the _action_common() consumers that run later in the 8863 * same coex cycle (_set_wl_preagc_ctrl, _set_bt_corx_table). 8864 */ 8865 used_path = _get_sdm_1ss_path(rtwdev); 8866 dm->fit_used_path = used_path; 8867 8868 memset(map, 0, sizeof(map)); 8869 for (i = 0; i < BTC_RF_NUM; i++) { 8870 if (module->ant.num == 1 && i == BTC_RF_S1) 8871 break; 8872 8873 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 8874 if ((bt0->scbd_c2h & BTC_BSCB_BT_15DOT4_TRX) || 8875 (bt1->scbd_c2h & BTC_BSCB_BT_15DOT4_TRX)) { 8876 /* 15.4 TRX active: force BT0/BT1 to TDD */ 8877 if (j < BTC_ALL_BT) 8878 dm->xtk_xmap[i][j] = 1; 8879 else 8880 continue; /* j == EXT: not force TDD */ 8881 } else if (used_path != RF_PATH_AB && j < BTC_ALL_BT) { 8882 /* 1SS MIMO-PS: only the used WL path co-Rx */ 8883 if (i != used_path) 8884 dm->xtk_xmap[i][j] = 0; 8885 else if (dm->ant_xmap[i][j] == 1) 8886 dm->xtk_xmap[i][j] = 1; 8887 else 8888 dm->xtk_xmap[i][j] = 8889 BTC_RSSI_LOW(dm->sir_state[j]) ? 1 : 0; 8890 } else if (dm->ant_xmap[i][j] == 1) { 8891 /* if WL RF-pathx co-ant with BTx */ 8892 dm->xtk_xmap[i][j] = 1; 8893 } else if (((j == BTC_BT_1ST && 8894 module->bt0_sw_type != BTC_SWITCH_V1_NONE) || 8895 (j == BTC_BT_2ND && 8896 module->bt1_sw_type != BTC_SWITCH_V1_NONE)) && 8897 !mlo_1_plus_1) { 8898 /* 8899 * if WL RF-pathx not co-ant/path with BTx 8900 * but BTx co-ant/path with the other WL-path 8901 * and WL is 2+0/0+2 8902 * ex: WL-S0 + (WL-S1 & BT0-S1) -> 8903 * BT0-S1 vs. WL-S0 = 1 8904 */ 8905 dm->xtk_xmap[i][j] = 1; 8906 } else if (BTC_RSSI_LOW(dm->sir_state[j])) { 8907 /* if WL_RSSI below BT-Tx interference thres */ 8908 dm->xtk_xmap[i][j] = 1; 8909 } else { 8910 dm->xtk_xmap[i][j] = 0; 8911 } 8912 8913 map[i][j] = dm->ant_xmap[i][j] | dm->xtk_xmap[i][j]; 8914 } 8915 } 8916 8917 memcpy(dm->sit_xmap, map, sizeof(map)); 8918 } 8919 8920 static void _set_bttrx_en(struct rtw89_dev *rtwdev) 8921 { 8922 struct rtw89_btc_wl_smap *wl_smap = &rtwdev->btc.cx.wl.status.map; 8923 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 8924 u8 state = dm->ost_info.bt_enable_state; 8925 u8 i, want, done; 8926 8927 /* only dual-BT chips drive the BT TX/RX enable from the driver */ 8928 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 8929 return; 8930 8931 /* 8932 * RF is not accessible, leave the shadow alone. Leaving this state is 8933 * a radio-state run, which drops the shadow and re-programs below. 8934 */ 8935 if (wl_smap->rf_off || wl_smap->lps == BTC_LPS_RF_OFF) 8936 return; 8937 8938 /* 8939 * RF may have been re-initialized, drop the shadow and re-program. 8940 * Power-off is not listed, it is always followed by an init run 8941 * before the next RF access. 8942 */ 8943 if (dm->run_reason == BTC_RSN_NTFY_INIT || 8944 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) 8945 dm->bttrx_en_ack = 0; 8946 8947 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) { 8948 want = !!(state & BIT(i)); 8949 done = !!(dm->bttrx_en_done & BIT(i)); 8950 8951 if (dm->bttrx_en_ack & BIT(i) && want == done) 8952 continue; 8953 8954 if (rtw89_phy_btc_bttrx_en(rtwdev, i, want)) { 8955 /* leave the bit un-acked, the next run retries it */ 8956 dm->bttrx_en_ack &= ~BIT(i); 8957 8958 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8959 "[BTC], %s(): BT%d trx_en=%d write fail\n", 8960 __func__, i, want); 8961 continue; 8962 } 8963 8964 dm->bttrx_en_ack |= BIT(i); 8965 8966 if (want) 8967 dm->bttrx_en_done |= BIT(i); 8968 else 8969 dm->bttrx_en_done &= ~BIT(i); 8970 } 8971 } 8972 8973 #define _bind_is_btonly 0x7 8974 static void _set_coex_binding(struct rtw89_dev *rtwdev) 8975 { 8976 struct rtw89_btc *btc = &rtwdev->btc; 8977 struct rtw89_btc_cx *cx = &btc->cx; 8978 struct rtw89_btc_extsoc_info *bt2 = &cx->bt_ext; 8979 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 8980 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 8981 struct rtw89_btc_wl_info *wl = &cx->wl; 8982 struct rtw89_btc_dm *dm = &btc->dm; 8983 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1}; 8984 u8 wl_rf_band[RTW89_BAND_NUM] = {}; 8985 u8 i, j, val = 0, fit, used_path; 8986 8987 /* 8988 * sit_xmap(Space-Interaction) = ant_xmap | xtk_xmap 8989 * 1: WL-BT space-interference, always 1 if BTG/BTA/SPDT = 1 8990 * if dedicated-ant, it may be 1 if BT-TX is bigger than WL-Rx(xtk_xmap) 8991 * 8992 * ant_xmap(ANT-Division-Multiplexing) 8993 * ==> dedicated-ant->0, BTG/BTA/SPDT->1 8994 * 8995 * xtk_xmap(Cross-talk map)-> calculate WL/BT interference by SIR 8996 * ==> 1: interference, 0: no-interference 8997 * 8998 * fdm_map(Frequency-Division-Multiplexing): WL/BT RF_Band overlap-map 8999 * 2bit-map: bit[1]:5/6GHz, bit[0]:2.4GHz 9000 */ 9001 for (i = 0; i < RTW89_PHY_NUM; i++) { 9002 if (wl->rf_band_map[i] & BIT(RTW89_BAND_2G)) 9003 wl_rf_band[i] |= BIT(RTW89_BAND_2G); 9004 9005 if (wl->rf_band_map[i] & (BIT(RTW89_BAND_5G) | BIT(RTW89_BAND_6G))) 9006 wl_rf_band[i] |= BIT(RTW89_BAND_5G); 9007 9008 dm->fit_xmap[i][BTC_BT_1ST] = wl_rf_band[i] & bt0->rf_band_map; 9009 dm->fit_xmap[i][BTC_BT_2ND] = wl_rf_band[i] & bt1->rf_band_map; 9010 dm->fit_xmap[i][BTC_BT_EXT] = wl_rf_band[i] & bt2->rf_band_map; 9011 } 9012 9013 /* 9014 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1 9015 * Therefore, BTC_MLO_RF_xxx is not real-time state. 9016 * if link mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO) 9017 * the HW-BAND is decided by wl->mlo_info.mrcx_act_hwb_map 9018 * In this case, BTC_RF_S0->HWB0, BTC_RF_S1->HWB1 9019 */ 9020 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) { 9021 if (wl->role_info.link_mode[RTW89_MAC_0] != BTC_WLINK_DB_MCC) {/* mode chg */ 9022 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_PHY_1)) 9023 path_hwb[BTC_RF_S0] = RTW89_PHY_1;/* S0/1->HWB1 */ 9024 else 9025 path_hwb[BTC_RF_S1] = RTW89_PHY_0;/* S0/1->HWB0 */ 9026 } 9027 } else { 9028 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0) 9029 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */ 9030 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2) 9031 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */ 9032 } 9033 9034 /* 9035 * WL 1SS MIMO-PS: WL RX is confined to a single path, so the unused 9036 * path has no WL-RX frequency interference with any BT. 9037 * RF_PATH_AB -> not 1SS, both paths keep their real fit_xmap. 9038 * Same helper as _update_sdm_map(), so xtk_xmap and fit_map always 9039 * agree on which RF-path is the unused one. 9040 * e.g. CIS@BT_2ND -> rx_path=RF_PATH_B, used_path=S1: 9041 * RF-S1 keeps its real fit_xmap, RF-S0 is cleared. 9042 */ 9043 used_path = _get_sdm_1ss_path(rtwdev); 9044 dm->fit_used_path = used_path; /* record for dbg cmd "xmap" */ 9045 9046 /* 9047 * tdd_map = sit_xmap * fdm_map, 1: WL-RF-Sx vs. BTx take TDD-Action 9048 * fdd_map =(!sit_xmap) * fdm_map, 1: WL-RF-Sx vs.BTx take FDD-Action 9049 * co-rx map = ant_xmap * fdm_map 1:WL/BT co-rx (for halbb-btg-ctrl) 9050 * sit_xmap,ant_xmap = 0 or 1, so tdd/fdd use multiplication (*) 9051 * 9052 * fit: WL-BT freq-interact(2bit band-map) of RF-Sx vs. BTx, 9053 * = fit_xmap[HWB][BTx], the used_path keeps this real band-map, 9054 * the unused path is cleared to 0 if 1SS MIMO-PS. 9055 */ 9056 9057 for (i = 0; i < BTC_RF_NUM; i++) 9058 for (j = 0; j < BTC_ALL_BT_EZL; j++) { 9059 fit = dm->fit_xmap[path_hwb[i]][j]; 9060 9061 /* 9062 * 1SS MIMO-PS: no WL-Rx on the unused path. 9063 * Only the local fit is dropped, dm->fit_xmap keeps 9064 * the real per-HW-band map: it is indexed by HW-band, 9065 * and both RF-path may map to the same HW-band, so 9066 * clearing it there would also drop used_path's entry 9067 * (and the other MLO link's entry in DB_MCC). 9068 */ 9069 if (used_path != RF_PATH_AB && i != used_path) 9070 fit = 0; 9071 9072 dm->fit_map[i][j] = fit; /* for dbg cmd "xmap" */ 9073 9074 dm->tdd_map[i][j] = dm->sit_xmap[i][j] * fit; 9075 dm->fdd_map[i][j] = !dm->sit_xmap[i][j] * fit; 9076 dm->corx_map[i][j] = dm->ant_xmap[i][j] * fit; 9077 } 9078 9079 /* TDD-Binding */ 9080 _set_bind_info(btc, BTC_MECH_TDD); 9081 9082 /* FDD-Binding */ 9083 _set_bind_info(btc, BTC_MECH_FDD); 9084 9085 dm->out_of_band = !dm->tdd_bind.rf_band && !dm->fdd_bind.rf_band; 9086 dm->fdd_en = !!dm->fdd_bind.rf_band; 9087 dm->tdd_en = !!dm->tdd_bind.rf_band; 9088 9089 /* set BT on/off state for GNT_WL Combined-MUX control */ 9090 if (bt0->enable.now) 9091 val |= BIT(BTC_BT_1ST); 9092 9093 if (bt1->enable.now) 9094 val |= BIT(BTC_BT_2ND); 9095 9096 if (bt2->func_type) 9097 val |= BIT(BTC_BT_EXT); 9098 9099 dm->ost_info.bt_enable_state = dm->bt_only ? _bind_is_btonly : val; 9100 9101 /* 9102 * Turn the BT TX/RX on/off by the BTG control in WL RF. Driven by 9103 * bt_enable_state shadow instead of its change, so a write the RF 9104 * layer rejects is retried in the next run. Call it every time, the 9105 * shadow compare inside is what suppresses the redundant RF I/O. 9106 */ 9107 _set_bttrx_en(rtwdev); 9108 } 9109 9110 static void _update_run_ctrl_info(struct rtw89_dev *rtwdev) 9111 { 9112 struct rtw89_btc *btc = &rtwdev->btc; 9113 struct rtw89_btc_dm *dm = &btc->dm; 9114 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9115 struct rtw89_btc_ctrl ctrl = btc->ctrl; 9116 struct rtw89_fbtc_wl_ctrl_info *wl_ctrl_info = &ctrl.wl_ctrl_info; 9117 u8 i; 9118 9119 ctrl.wl_only = dm->wl_only; 9120 ctrl.bt_only = dm->bt_only; 9121 ctrl.ntfy_type = dm->run_reason; 9122 9123 wl_ctrl_info->smap_val = wl->status.val; 9124 wl_ctrl_info->rfk_state = wl->rfk_info.state; 9125 wl_ctrl_info->rfk_type = wl->rfk_info.type; 9126 wl_ctrl_info->client_pstdma_on = dm->client_ps_tdma_on; 9127 wl_ctrl_info->fw_scan = wl->scan_info.fw_scan; 9128 9129 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { 9130 wl_ctrl_info->rf_band_map[i] = wl->rf_band_map[i]; 9131 wl_ctrl_info->rf_ch[i] = wl->rf_ch_info[i].center_ch; 9132 } 9133 9134 if (memcmp(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl))) { 9135 memcpy(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl)); 9136 if (btc->ver->fcxctrl >= 9) 9137 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 9138 } 9139 } 9140 9141 static 9142 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 9143 { 9144 struct rtw89_btc *btc = &rtwdev->btc; 9145 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 9146 struct rtw89_btc_cx *cx = &btc->cx; 9147 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9148 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 9149 u8 mode = btc->dm.tdd_bind.wl_link_mode; 9150 u8 mode_v0 = BTC_WLINK_V0_OTHER; 9151 bool has_2ghz; 9152 9153 lockdep_assert_wiphy(rtwdev->hw->wiphy); 9154 9155 dm->run_reason = reason; 9156 _update_dm_step(rtwdev, reason); 9157 9158 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 9159 __func__, reason, mode); 9160 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 9161 __func__, dm->wl_only, dm->bt_only); 9162 9163 /* Be careful to change the following function sequence!! */ 9164 if (btc->manual_ctrl) { 9165 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9166 "[BTC], %s(): return for Manual CTRL!!\n", 9167 __func__); 9168 return; 9169 } 9170 9171 if (!wl->status.map.init_ok) { 9172 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9173 "[BTC], %s(): return for WL init fail!!\n", 9174 __func__); 9175 return; 9176 } 9177 9178 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 9179 wl->status.map.lps_pre == wl->status.map.lps && 9180 !dm->lps_ctrl_change && !dm->lps_ctrl_scbd) { 9181 if (reason == BTC_RSN_NTFY_POWEROFF || 9182 reason == BTC_RSN_NTFY_RADIO_STATE) { 9183 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9184 "[BTC], %s(): return for WL rf off state no change!!\n", 9185 __func__); 9186 return; 9187 } 9188 if (wl->status.map.rf_off == 1 || 9189 wl->status.map.lps == BTC_LPS_RF_OFF) { 9190 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9191 "[BTC], %s(): return for WL rf off state!!\n", 9192 __func__); 9193 return; 9194 } 9195 } 9196 9197 _update_run_ctrl_info(rtwdev); 9198 9199 if (reason == BTC_RSN_NTFY_RADIO_STATE) 9200 _update_bt_scbd(rtwdev, BTC_ALL_BT, false); 9201 9202 dm->freerun = false; 9203 dm->cnt_dm[BTC_DCNT_RUN]++; 9204 dm->fddt_train = BTC_FDDT_DISABLE; 9205 bt->scan_rx_low_pri = false; 9206 9207 _set_coex_binding(rtwdev); 9208 _update_btc_state_map(rtwdev); 9209 9210 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ 9211 9212 if (btc->ctrl.always_freerun) { 9213 _action_freerun(rtwdev); 9214 goto exit; 9215 } 9216 9217 if (dm->wl_only) { 9218 _action_wl_only(rtwdev); 9219 goto exit; 9220 } 9221 9222 if (wl->status.map.rf_off || dm->bt_only || wl->status.map.lps) { 9223 _action_wl_off(rtwdev, mode); 9224 goto exit; 9225 } 9226 9227 if (reason == BTC_RSN_NTFY_INIT) { 9228 _action_wl_init(rtwdev); 9229 goto exit; 9230 } 9231 9232 if (!cx->bt0.enable.now && !cx->bt_ext.func_type) { 9233 _action_bt_off(rtwdev); 9234 goto exit; 9235 } 9236 9237 if (cx->bt0.whql_test) { 9238 _action_bt_whql(rtwdev); 9239 goto exit; 9240 } 9241 9242 if (wl->rfk_info.state != BTC_WRFK_STOP) { 9243 _action_wl_rfk(rtwdev); 9244 goto exit; 9245 } 9246 9247 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) { 9248 _action_wl_scan(rtwdev); 9249 bt->scan_rx_low_pri = true; 9250 goto exit; 9251 } 9252 9253 if (mode == BTC_WLINK_NOLINK) { 9254 mode_v0 = BTC_WLINK_V0_NOLINK; 9255 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G)) { 9256 mode_v0 = BTC_WLINK_V0_5G; 9257 } else if (btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_5G) && 9258 btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_2G)) { 9259 mode_v0 = BTC_WLINK_V0_25G_MCC; 9260 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_2G)) { 9261 switch (mode) { 9262 case BTC_WLINK_STA: 9263 mode_v0 = BTC_WLINK_V0_2G_STA; 9264 break; 9265 case BTC_WLINK_AP: 9266 mode_v0 = BTC_WLINK_V0_2G_AP; 9267 break; 9268 case BTC_WLINK_GO: 9269 mode_v0 = BTC_WLINK_V0_2G_GO; 9270 break; 9271 case BTC_WLINK_GC: 9272 mode_v0 = BTC_WLINK_V0_2G_GC; 9273 break; 9274 case BTC_WLINK_SCC: 9275 mode_v0 = BTC_WLINK_V0_2G_SCC; 9276 break; 9277 case BTC_WLINK_SB_MCC: 9278 mode_v0 = BTC_WLINK_V0_2G_MCC; 9279 break; 9280 default: 9281 mode_v0 = BTC_WLINK_V0_OTHER; 9282 break; 9283 } 9284 } else { 9285 /* No binding (out_of_band): derive mode_v0 from link_mode + rf_band_map */ 9286 has_2ghz = wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) || 9287 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G); 9288 9289 if (!has_2ghz) { 9290 mode_v0 = BTC_WLINK_V0_5G; 9291 } else if (mode == BTC_WLINK_DB_MCC) { 9292 mode_v0 = BTC_WLINK_V0_25G_MCC; 9293 } else { 9294 switch (mode) { 9295 case BTC_WLINK_STA: 9296 mode_v0 = BTC_WLINK_V0_2G_STA; 9297 break; 9298 case BTC_WLINK_AP: 9299 mode_v0 = BTC_WLINK_V0_2G_AP; 9300 break; 9301 case BTC_WLINK_GO: 9302 mode_v0 = BTC_WLINK_V0_2G_GO; 9303 break; 9304 case BTC_WLINK_GC: 9305 mode_v0 = BTC_WLINK_V0_2G_GC; 9306 break; 9307 case BTC_WLINK_SCC: 9308 mode_v0 = BTC_WLINK_V0_2G_SCC; 9309 break; 9310 case BTC_WLINK_SB_MCC: 9311 mode_v0 = BTC_WLINK_V0_2G_MCC; 9312 break; 9313 default: 9314 mode_v0 = BTC_WLINK_V0_OTHER; 9315 break; 9316 } 9317 } 9318 } 9319 9320 switch (mode_v0) { 9321 case BTC_WLINK_NOLINK: 9322 _action_wl_nc(rtwdev); 9323 break; 9324 case BTC_WLINK_V0_2G_STA: 9325 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 9326 bt->scan_rx_low_pri = true; 9327 _action_wl_2g_sta(rtwdev); 9328 break; 9329 case BTC_WLINK_V0_2G_AP: 9330 bt->scan_rx_low_pri = true; 9331 _action_wl_2g_ap(rtwdev); 9332 break; 9333 case BTC_WLINK_V0_2G_GO: 9334 bt->scan_rx_low_pri = true; 9335 _action_wl_2g_go(rtwdev); 9336 break; 9337 case BTC_WLINK_V0_2G_GC: 9338 bt->scan_rx_low_pri = true; 9339 _action_wl_2g_gc(rtwdev); 9340 break; 9341 case BTC_WLINK_V0_2G_SCC: 9342 bt->scan_rx_low_pri = true; 9343 _action_wl_2g_scc(rtwdev); 9344 break; 9345 case BTC_WLINK_V0_2G_MCC: 9346 bt->scan_rx_low_pri = true; 9347 _action_wl_2g_mcc(rtwdev); 9348 break; 9349 case BTC_WLINK_V0_25G_MCC: 9350 bt->scan_rx_low_pri = true; 9351 _action_wl_25g_mcc(rtwdev); 9352 break; 9353 case BTC_WLINK_V0_5G: 9354 _action_wl_5g(rtwdev); 9355 break; 9356 case BTC_WLINK_V0_2G_NAN: 9357 _action_wl_2g_nan(rtwdev); 9358 break; 9359 default: 9360 _action_wl_other(rtwdev); 9361 break; 9362 } 9363 9364 exit: 9365 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 9366 _action_common(rtwdev); 9367 } 9368 9369 void rtw89_btc_init(struct rtw89_dev *rtwdev) 9370 { 9371 const struct rtw89_chip_info *chip = rtwdev->chip; 9372 struct rtw89_btc *btc = &rtwdev->btc; 9373 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9374 9375 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9376 "[BTC], %s(): Init %s !!\n", __func__, 9377 chip_id_str(chip->chip_id)); 9378 9379 _reset_btc_var(rtwdev, BTC_RESET_ALL); 9380 9381 btc->dm.run_reason = BTC_RSN_NONE; 9382 btc->dm.run_action = BTC_ACT_NONE; 9383 wl->status.map.init_ok = true; 9384 } 9385 9386 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 9387 { 9388 struct rtw89_btc *btc = &rtwdev->btc; 9389 9390 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 9391 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 9392 } 9393 9394 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 9395 { 9396 struct rtw89_btc *btc = &rtwdev->btc; 9397 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9398 9399 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 9400 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 9401 9402 btc->cx.wl.status.map.rf_off = 1; 9403 btc->cx.wl.status.map.busy = 0; 9404 wl->status.map.lps = BTC_LPS_OFF; 9405 9406 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false); 9407 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 9408 9409 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 9410 } 9411 9412 #define BTC_PLATFORM_LITTLE_ENDIAN 0 9413 static void _set_init_info(struct rtw89_dev *rtwdev) 9414 { 9415 const struct rtw89_chip_info *chip = rtwdev->chip; 9416 struct rtw89_btc *btc = &rtwdev->btc; 9417 struct rtw89_btc_dm *dm = &btc->dm; 9418 struct rtw89_btc_cx *cx = &btc->cx; 9419 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9420 9421 dm->init_info.init_mode = wl->coex_mode; 9422 dm->init_info.wl_init_ok = wl->status.map.init_ok; 9423 dm->init_info.endian_type = BTC_PLATFORM_LITTLE_ENDIAN; 9424 dm->init_info.bt0_function = cx->bt0.func_type; 9425 dm->init_info.bt1_function = cx->bt1.func_type; 9426 dm->init_info.bt2_function = cx->bt_ext.func_type; 9427 dm->init_info.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE; 9428 dm->init_info.pta_direction = RTW89_MAC_AX_COEX_INNER; 9429 dm->init_info.wl_only = dm->wl_only; 9430 dm->init_info.bt_only = dm->bt_only; 9431 dm->init_info.wl_init_ok = wl->status.map.init_ok; 9432 dm->init_info.cx_other = btc->cx.bt_ext.func_type; 9433 dm->init_info.wl_guard_ch = chip->afh_guard_ch; 9434 dm->init_info.dbcc_en = rtwdev->dbcc_en; 9435 9436 dm->init_info.module = btc->mdinfo; 9437 9438 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 9439 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 9440 rtw89_btc_fw_set_slots(rtwdev); 9441 btc_fw_set_monreg(rtwdev); 9442 _set_ext_interface(rtwdev); 9443 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0); 9444 9445 _update_sdm_map(rtwdev); 9446 } 9447 9448 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 9449 { 9450 struct rtw89_btc *btc = &rtwdev->btc; 9451 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 9452 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9453 const struct rtw89_chip_info *chip = rtwdev->chip; 9454 9455 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9456 "[BTC], %s(): mode=%d\n", __func__, mode); 9457 9458 wl->coex_mode = mode; 9459 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 9460 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 9461 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 9462 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 9463 dm->vid = rtwdev->custid; 9464 btc->ctrl.always_freerun = mode == BTC_MODE_COTX; 9465 9466 if (!wl->status.map.init_ok) { 9467 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9468 "[BTC], %s(): return for WL init fail!!\n", 9469 __func__); 9470 dm->error.map.init = true; 9471 return; 9472 } 9473 9474 btc->cx.bt0.enable.now = 1; 9475 btc->cx.bt0.run_patch_code = 1; 9476 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 9477 btc->cx.bt1.enable.now = 1; 9478 btc->cx.bt1.run_patch_code = 1; 9479 } 9480 9481 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) 9482 btc->io_oflld_type = BTC_IO_OFLD_BTC_H2C; 9483 else 9484 btc->io_oflld_type = BTC_IO_OFLD_NO_SUPPORT; 9485 9486 chip->ops->btc_set_rfe(rtwdev); 9487 chip->ops->btc_init_cfg(rtwdev); 9488 9489 _write_scbd(rtwdev, BTC_ALL_BT, 9490 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 9491 9492 if (rtw89_mac_get_ctrl_path(rtwdev)) { 9493 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9494 "[BTC], %s(): PTA owner warning!!\n", 9495 __func__); 9496 dm->error.map.pta_owner = true; 9497 } 9498 9499 _set_init_info(rtwdev); 9500 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0); 9501 btc_fw_set_monreg(rtwdev); 9502 rtw89_btc_fw_set_slots(rtwdev); 9503 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 9504 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 9505 9506 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 9507 } 9508 9509 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 9510 { 9511 struct rtw89_btc *btc = &rtwdev->btc; 9512 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9513 9514 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9515 "[BTC], %s(): phy_idx=%d, band=%d\n", 9516 __func__, phy_idx, band); 9517 9518 if (phy_idx >= RTW89_PHY_NUM) 9519 return; 9520 9521 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 9522 wl->status.map.scan = true; 9523 wl->scan_info.band[phy_idx] = band; 9524 wl->scan_info.phy_map |= BIT(phy_idx); 9525 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 9526 9527 if (rtwdev->dbcc_en) { 9528 wl->dbcc_info.scan_band[phy_idx] = band; 9529 _update_dbcc_band(rtwdev, phy_idx); 9530 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 9531 } 9532 9533 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) 9534 btc->ctrl.wl_ctrl_info.fw_scan = 1; 9535 9536 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 9537 } 9538 9539 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 9540 { 9541 struct rtw89_btc *btc = &rtwdev->btc; 9542 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9543 9544 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9545 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 9546 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 9547 9548 wl->status.map.scan = false; 9549 wl->scan_info.phy_map &= ~BIT(phy_idx); 9550 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 9551 9552 if (rtwdev->dbcc_en) { 9553 _update_dbcc_band(rtwdev, phy_idx); 9554 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 9555 } 9556 9557 btc->dm.tdma_instant_excute = 1; 9558 9559 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 9560 } 9561 9562 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 9563 { 9564 struct rtw89_btc *btc = &rtwdev->btc; 9565 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9566 9567 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9568 "[BTC], %s(): phy_idx=%d, band=%d\n", 9569 __func__, phy_idx, band); 9570 9571 if (phy_idx >= RTW89_PHY_NUM) 9572 return; 9573 9574 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 9575 9576 if (rtwdev->dbcc_en) { 9577 wl->dbcc_info.scan_band[phy_idx] = band; 9578 _update_dbcc_band(rtwdev, phy_idx); 9579 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 9580 } 9581 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 9582 } 9583 9584 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 9585 enum btc_pkt_type pkt_type) 9586 { 9587 struct rtw89_btc *btc = &rtwdev->btc; 9588 struct rtw89_btc_cx *cx = &btc->cx; 9589 struct rtw89_btc_wl_info *wl = &cx->wl; 9590 struct rtw89_btc_bt_link_info *b = &cx->bt0.link_info; 9591 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 9592 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 9593 u32 cnt; 9594 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 9595 bool delay_work = false; 9596 9597 switch (pkt_type) { 9598 case PACKET_DHCP: 9599 cnt = ++wl->wcnt[BTC_WCNT_DHCP]; 9600 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9601 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 9602 wl->status.map.handshake = 0; 9603 wl->status.map._4way = 0; 9604 wl->status.map.dhcp = 1; 9605 delay_work = true; 9606 break; 9607 case PACKET_EAPOL: 9608 cnt = ++wl->wcnt[BTC_WCNT_EAPOL]; 9609 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9610 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 9611 wl->status.map.handshake = 0; 9612 wl->status.map._4way = 1; 9613 wl->status.map.dhcp = 0; 9614 delay_work = true; 9615 if (hfp->exist || hid->exist) 9616 delay /= 2; 9617 break; 9618 case PACKET_EAPOL_END: 9619 cnt = ++wl->wcnt[BTC_WCNT_EAPOL]; 9620 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9621 "[BTC], %s(): EAPOL_End cnt=%d\n", 9622 __func__, cnt); 9623 wl->status.map._4way = 0; 9624 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 9625 break; 9626 case PACKET_ARP: 9627 cnt = ++wl->wcnt[BTC_WCNT_ARP]; 9628 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9629 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 9630 return; 9631 case PACKET_ICMP: 9632 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9633 "[BTC], %s(): ICMP pkt\n", __func__); 9634 return; 9635 default: 9636 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9637 "[BTC], %s(): unknown packet type %d\n", 9638 __func__, pkt_type); 9639 return; 9640 } 9641 9642 if (delay_work) { 9643 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 9644 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9645 &rtwdev->coex_act1_work, delay); 9646 } 9647 9648 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 9649 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 9650 } 9651 9652 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 9653 { 9654 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 9655 btc.eapol_notify_work); 9656 9657 lockdep_assert_wiphy(wiphy); 9658 9659 rtw89_leave_ps_mode(rtwdev); 9660 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 9661 } 9662 9663 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 9664 { 9665 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 9666 btc.arp_notify_work); 9667 9668 lockdep_assert_wiphy(wiphy); 9669 9670 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 9671 } 9672 9673 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 9674 { 9675 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 9676 btc.dhcp_notify_work); 9677 9678 lockdep_assert_wiphy(wiphy); 9679 9680 rtw89_leave_ps_mode(rtwdev); 9681 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 9682 } 9683 9684 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 9685 { 9686 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 9687 btc.icmp_notify_work); 9688 9689 lockdep_assert_wiphy(wiphy); 9690 9691 rtw89_leave_ps_mode(rtwdev); 9692 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 9693 } 9694 9695 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi) 9696 { 9697 const struct rtw89_chip_info *chip = rtwdev->chip; 9698 struct rtw89_btc *btc = &rtwdev->btc; 9699 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 9700 u8 *rssi_st, rssi_th, rssi_level = 0; 9701 u8 i; 9702 9703 /* for rssi locate in which {40, 36, 31, 28} 9704 * if rssi >= 40% (-60dBm) --> rssi_level = 4 9705 * if 36% <= rssi < 40% --> rssi_level = 3 9706 * if 31% <= rssi < 36% --> rssi_level = 2 9707 * if 28% <= rssi < 31% --> rssi_level = 1 9708 * if rssi < 28% --> rssi_level = 0 9709 */ 9710 9711 /* check if rssi across bt_rssi_thres boundary */ 9712 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) { 9713 rssi_th = chip->bt_rssi_thres[i]; 9714 rssi_st = &bt->link_info.rssi_state[i]; 9715 9716 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th); 9717 9718 if (BTC_RSSI_HIGH(*rssi_st)) { 9719 rssi_level = BTC_BT_RSSI_THMAX - i; 9720 break; 9721 } 9722 } 9723 return rssi_level; 9724 } 9725 9726 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 9727 9728 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 bid, u8 *buf, u32 len) 9729 { 9730 const struct rtw89_chip_info *chip = rtwdev->chip; 9731 struct rtw89_btc *btc = &rtwdev->btc; 9732 struct rtw89_btc_bt_a2dp_desc *a2dp; 9733 struct rtw89_btc_cx *cx = &btc->cx; 9734 struct rtw89_btc_bt_hfp_desc *hfp; 9735 struct rtw89_btc_bt_hid_desc *hid; 9736 struct rtw89_btc_bt_pan_desc *pan; 9737 struct rtw89_btc_bt_link_info *b; 9738 struct rtw89_btc_bt_info *bt; 9739 union btc_btinfo btinfo; 9740 u8 is_bt_56g = 0; 9741 u8 *raw_info; 9742 9743 /* Bit7 is used for RF-band: 0:BT_2.4 GHz, 1:BT_5/6 GHz */ 9744 if ((buf[BTC_BTINFO_L1] & 0x7f) != 6) 9745 return; 9746 9747 bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 9748 9749 if ((buf[BTC_BTINFO_L1] & BIT(7)) && bt->band_56G_support) { 9750 b = &bt->link_info_56g; 9751 is_bt_56g = 1; 9752 if (b->status.map.connect) 9753 bt->rf_band_map |= BIT(RTW89_BAND_5G); 9754 else 9755 bt->rf_band_map &= ~BIT(RTW89_BAND_5G); 9756 } else { 9757 b = &bt->link_info; 9758 bt->rf_band_map |= BIT(RTW89_BAND_2G); 9759 } 9760 9761 hfp = &b->hfp_desc; 9762 hid = &b->hid_desc; 9763 a2dp = &b->a2dp_desc; 9764 pan = &b->pan_desc; 9765 raw_info = is_bt_56g ? bt->raw_info_56g : bt->raw_info; 9766 9767 if (!memcmp(raw_info, buf, BTC_BTINFO_MAX)) { 9768 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9769 "[BTC], %s(): return by bt-info duplicate!!\n", 9770 __func__); 9771 bt->bcnt[BTC_BCNT_INFOSAME]++; 9772 return; 9773 } 9774 9775 memcpy(raw_info, buf, BTC_BTINFO_MAX); 9776 9777 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9778 "[BTC], %s(): bt_info[2]=0x%02x\n", 9779 __func__, raw_info[2]); 9780 9781 hid->type = 0; 9782 9783 /* parse raw info low-Byte2 */ 9784 btinfo.val = raw_info[BTC_BTINFO_L2]; 9785 b->status.map.connect = btinfo.lb2.connect; 9786 b->status.map.sco_busy = btinfo.lb2.sco_busy; 9787 b->status.map.acl_busy = btinfo.lb2.acl_busy; 9788 b->status.map.inq_pag = btinfo.lb2.inq_pag; 9789 bt->inq_pag.now = btinfo.lb2.inq_pag; 9790 bt->bcnt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 9791 9792 hfp->exist = btinfo.lb2.hfp; 9793 hid->exist = btinfo.lb2.hid; 9794 a2dp->exist = btinfo.lb2.a2dp; 9795 pan->exist = btinfo.lb2.pan; 9796 _update_bt_link_cnt(rtwdev, bt, is_bt_56g); 9797 if (bid == BTC_BT_1ST) 9798 btc->dm.trx_info.bt0_profile = 9799 u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 9800 else 9801 btc->dm.trx_info.bt1_profile = 9802 u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 9803 9804 /* parse raw info low-Byte3 */ 9805 btinfo.val = raw_info[BTC_BTINFO_L3]; 9806 if (btinfo.lb3.retry != 0) 9807 bt->bcnt[BTC_BCNT_RETRY]++; 9808 b->cqddr = btinfo.lb3.cqddr; 9809 bt->bcnt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 9810 bt->inq = btinfo.lb3.inq; 9811 bt->bcnt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 9812 bt->pag = btinfo.lb3.pag; 9813 9814 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 9815 /* parse raw info high-Byte0 */ 9816 btinfo.val = raw_info[BTC_BTINFO_H0]; 9817 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 9818 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 9819 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi); 9820 btc->dm.trx_info.bt_rssi = bt->rssi_level; 9821 9822 /* parse raw info high-Byte1 */ 9823 btinfo.val = raw_info[BTC_BTINFO_H1]; 9824 b->status.map.ble_connect = btinfo.hb1.ble_connect; 9825 if (btinfo.hb1.ble_connect) { 9826 if (hid->exist) 9827 hid->type |= BTC_HID_BLE; 9828 else if (btinfo.hb1.voice) 9829 hid->type |= BTC_HID_RCU_VOICE; 9830 else 9831 hid->type |= BTC_HID_RCU; 9832 } 9833 9834 bt->bcnt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 9835 bt->reinit = btinfo.hb1.reinit; 9836 bt->bcnt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 9837 b->relink.now = btinfo.hb1.relink; 9838 bt->bcnt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 9839 bt->igno_wl = btinfo.hb1.igno_wl; 9840 9841 if (bt->igno_wl && !cx->wl.status.map.rf_off) 9842 _set_bt_ignore_wlan_act(rtwdev, false); 9843 9844 bt->ble_scan_en = btinfo.hb1.ble_scan; 9845 9846 bt->bcnt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 9847 b->role_sw = btinfo.hb1.role_sw; 9848 9849 b->multi_link.now = btinfo.hb1.multi_link; 9850 9851 /* parse raw info high-Byte2 */ 9852 btinfo.val = raw_info[BTC_BTINFO_H2]; 9853 pan->active = !!btinfo.hb2.pan_active; 9854 9855 bt->bcnt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 9856 b->afh_update = btinfo.hb2.afh_update; 9857 a2dp->active = btinfo.hb2.a2dp_active; 9858 b->slave_role = btinfo.hb2.slave; 9859 hid->slot_info = btinfo.hb2.hid_slot; 9860 hid->pair_cnt = btinfo.hb2.hid_cnt; 9861 if (!b->status.map.ble_connect || hid->pair_cnt > 1) 9862 hid->type |= (hid->slot_info == BTC_HID_218 ? 9863 BTC_HID_218 : BTC_HID_418); 9864 /* parse raw info high-Byte3 */ 9865 btinfo.val = raw_info[BTC_BTINFO_H3]; 9866 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 9867 9868 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 9869 bt->bcnt[BTC_BCNT_RATECHG]++; 9870 b->tx_3m = (u32)btinfo.hb3.tx_3m; 9871 9872 a2dp->sink = btinfo.hb3.a2dp_sink; 9873 9874 if (!a2dp->exist_last && a2dp->exist) { 9875 a2dp->vendor_id = 0; 9876 a2dp->flush_time = 0; 9877 a2dp->play_latency = 1; 9878 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9879 &rtwdev->coex_bt_devinfo_work, 9880 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 9881 } 9882 9883 _update_bt_ctrl_lps(rtwdev); 9884 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 9885 } 9886 9887 static void _ntfy_role_info(struct rtw89_dev *rtwdev, u8 rid, 9888 struct rtw89_btc_wl_link_info *info, 9889 enum btc_role_state reason) 9890 { 9891 struct rtw89_btc *btc = &rtwdev->btc; 9892 struct rtw89_btc_wl_link_info *wlinfo = NULL; 9893 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9894 const struct rtw89_btc_ver *ver = btc->ver; 9895 u8 rlink_id = info->phy; /* 1 role_id has 2 rlink_id(by HW_Band0/1) */ 9896 bool refresh_role = false; 9897 9898 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9899 "[BTC], %s(), role_id=%d, reason=%d\n", 9900 __func__, rid, reason); 9901 9902 if (rid >= ver->max_role_num || rlink_id >= RTW89_PHY_NUM) 9903 return; 9904 9905 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 9906 9907 wlinfo = &wl->rlink_info[rid][rlink_id]; 9908 memcpy(wlinfo, info, sizeof(struct rtw89_btc_wl_link_info)); 9909 9910 switch (reason) { 9911 case BTC_ROLE_START: 9912 wlinfo->active = true; 9913 return; 9914 case BTC_ROLE_STOP: 9915 wlinfo->active = false; 9916 return; 9917 case BTC_ROLE_MSTS_STA_CONN_START: 9918 wl->status.map.transacting = 1; 9919 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, 9920 &rtwdev->coex_act1_work); 9921 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9922 &rtwdev->coex_act1_work, 9923 RTW89_COEX_ACT1_WORK_PERIOD); 9924 break; 9925 case BTC_ROLE_MSTS_STA_CONN_END: 9926 wl->status.map.transacting = 0; 9927 refresh_role = true; 9928 break; 9929 case BTC_ROLE_MSTS_STA_DIS_CONN: 9930 wl->status.map.transacting = 1; 9931 refresh_role = false; 9932 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, 9933 &rtwdev->coex_act1_work); 9934 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 9935 &rtwdev->coex_act1_work, 9936 RTW89_COEX_ACT1_WORK_PERIOD); 9937 break; 9938 case BTC_ROLE_MSTS_AP_START: 9939 case BTC_ROLE_MSTS_AP_STOP: 9940 refresh_role = true; 9941 break; 9942 case BTC_ROLE_STATE_UNKNOWN: 9943 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9944 "[BTC], %s(), role_id=%d, Unknown reason return!\n", 9945 __func__, rid); 9946 return; 9947 default: 9948 return; 9949 } 9950 9951 if (refresh_role) { 9952 _update_wl_info(rtwdev, wlinfo); 9953 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 9954 } 9955 9956 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 9957 } 9958 9959 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, 9960 struct rtw89_vif_link *rtwvif_link, 9961 struct rtw89_sta_link *rtwsta_link, 9962 enum btc_role_state state) 9963 { 9964 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 9965 rtwvif_link->chanctx_idx); 9966 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); 9967 struct ieee80211_p2p_noa_attr *noa_attr; 9968 struct ieee80211_p2p_noa_desc *noa_desc; 9969 struct ieee80211_bss_conf *bss_conf; 9970 struct ieee80211_link_sta *link_sta; 9971 struct rtw89_btc_wl_link_info r = {0}; 9972 u8 i, role_id, mode = 0; 9973 9974 rcu_read_lock(); 9975 9976 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); 9977 9978 role_id = rtwvif_link->port; 9979 9980 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 9981 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9982 "[BTC], role is STA=%d\n", 9983 vif->type == NL80211_IFTYPE_STATION); 9984 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", role_id); 9985 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 9986 chan->band_type, chan->channel, chan->band_width); 9987 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 9988 state == BTC_ROLE_MSTS_STA_CONN_END); 9989 rtw89_debug(rtwdev, RTW89_DBG_BTC, 9990 "[BTC], bcn_period=%d dtim_period=%d\n", 9991 bss_conf->beacon_int, bss_conf->dtim_period); 9992 9993 if (rtwsta_link) { 9994 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); 9995 9996 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 9997 rtwsta_link->mac_id); 9998 9999 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10000 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 10001 link_sta->he_cap.has_he, 10002 link_sta->vht_cap.vht_supported, 10003 link_sta->ht_cap.ht_supported); 10004 if (link_sta->he_cap.has_he) 10005 mode |= BIT(BTC_WL_MODE_HE); 10006 if (link_sta->vht_cap.vht_supported) 10007 mode |= BIT(BTC_WL_MODE_VHT); 10008 if (link_sta->ht_cap.ht_supported) 10009 mode |= BIT(BTC_WL_MODE_HT); 10010 10011 r.mode = mode; 10012 } 10013 10014 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { 10015 rcu_read_unlock(); 10016 return; 10017 } 10018 10019 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10020 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); 10021 10022 if (vif->type == NL80211_IFTYPE_P2P_GO || 10023 vif->type == NL80211_IFTYPE_P2P_CLIENT) { 10024 noa_attr = &bss_conf->p2p_noa_attr; 10025 10026 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { 10027 noa_desc = &noa_attr->desc[i]; 10028 if (noa_desc->count != 0) { 10029 r.noa = 1; 10030 r.noa_duration = le32_to_cpu(noa_desc->duration); 10031 break; 10032 } 10033 } 10034 } 10035 10036 r.mode = mode; 10037 r.role = rtwvif_link->wifi_role; 10038 r.phy = rtwvif_link->phy_idx; 10039 r.pid = role_id; 10040 r.active = true; 10041 if (vif->active_links) { 10042 if (rtwvif_link->link_id < 16) 10043 r.active = !!(vif->active_links & BIT(rtwvif_link->link_id)); 10044 } 10045 r.bcn_period = bss_conf->beacon_int; 10046 r.dtim_period = bss_conf->dtim_period; 10047 r.band = chan->band_type; 10048 r.ch = chan->channel; 10049 r.bw = chan->band_width; 10050 r.chdef.band = chan->band_type; 10051 r.chdef.center_ch = chan->channel; 10052 r.chdef.bw = chan->band_width; 10053 r.chdef.chan = chan->primary_channel; 10054 10055 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) { 10056 r.mac_id = rtwsta_link->mac_id; 10057 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); 10058 } 10059 10060 switch (state) { 10061 case BTC_ROLE_MSTS_STA_CONN_END: 10062 case BTC_ROLE_MSTS_AP_START: 10063 r.connected = MLME_LINKED; 10064 break; 10065 default: 10066 r.connected = MLME_NO_LINK; 10067 break; 10068 } 10069 10070 rcu_read_unlock(); 10071 10072 _ntfy_role_info(rtwdev, role_id, &r, state); 10073 } 10074 10075 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 10076 { 10077 const struct rtw89_chip_info *chip = rtwdev->chip; 10078 struct rtw89_btc *btc = &rtwdev->btc; 10079 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10080 u32 val; 10081 10082 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 10083 __func__, rf_state); 10084 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 10085 10086 switch (rf_state) { 10087 case BTC_RFCTRL_WL_OFF: 10088 wl->status.map.rf_off = 1; 10089 wl->status.map.lps = BTC_LPS_OFF; 10090 wl->status.map.busy = 0; 10091 break; 10092 case BTC_RFCTRL_FW_CTRL: 10093 wl->status.map.rf_off = 0; 10094 wl->status.map.lps = BTC_LPS_RF_OFF; 10095 wl->status.map.busy = 0; 10096 break; 10097 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 10098 wl->status.map.rf_off = 0; 10099 wl->status.map.lps = BTC_LPS_RF_ON; 10100 wl->status.map.busy = 0; 10101 break; 10102 case BTC_RFCTRL_WL_ON: 10103 default: 10104 wl->status.map.rf_off = 0; 10105 wl->status.map.lps = BTC_LPS_OFF; 10106 break; 10107 } 10108 10109 if (rf_state == BTC_RFCTRL_WL_ON) { 10110 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 10111 _write_scbd(rtwdev, BTC_ALL_BT, val, true); 10112 chip->ops->btc_init_cfg(rtwdev); 10113 } else { 10114 if (rf_state == BTC_RFCTRL_FW_CTRL) 10115 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false); 10116 else if (rf_state == BTC_RFCTRL_WL_OFF) 10117 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false); 10118 else 10119 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false); 10120 } 10121 10122 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 10123 btc->dm.tdma_instant_excute = 1; 10124 10125 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 10126 wl->status.map.rf_off_pre = wl->status.map.rf_off; 10127 wl->status.map.lps_pre = wl->status.map.lps; 10128 } 10129 10130 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 10131 enum btc_wl_rfk_type type, 10132 enum btc_wl_rfk_state state) 10133 { 10134 struct rtw89_btc *btc = &rtwdev->btc; 10135 struct rtw89_btc_cx *cx = &btc->cx; 10136 struct rtw89_btc_wl_info *wl = &cx->wl; 10137 bool result = BTC_WRFK_REJECT; 10138 10139 wl->rfk_info.type = type; 10140 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 10141 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 10142 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 10143 10144 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10145 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 10146 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 10147 type, state); 10148 10149 switch (state) { 10150 case BTC_WRFK_START: 10151 result = BTC_WRFK_ALLOW; 10152 wl->rfk_info.state = BTC_WRFK_START; 10153 10154 btc->cx.wl.wcnt[BTC_WCNT_RFK_REQ]++; 10155 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 10156 10157 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, true); 10158 break; 10159 case BTC_WRFK_ONESHOT_START: 10160 case BTC_WRFK_ONESHOT_STOP: 10161 btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++; 10162 if (type != BTC_WRFKT_RXDCK) 10163 return BTC_WRFK_ALLOW; 10164 break; 10165 case BTC_WRFK_STOP: 10166 result = BTC_WRFK_ALLOW; 10167 wl->rfk_info.state = BTC_WRFK_STOP; 10168 10169 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false); 10170 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work); 10171 break; 10172 default: 10173 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10174 "[BTC], %s() warning state=%d\n", __func__, state); 10175 return result; 10176 } 10177 10178 if (result == BTC_WRFK_ALLOW) { 10179 if (wl->rfk_info.state == BTC_WRFK_START || 10180 wl->rfk_info.state == BTC_WRFK_STOP) 10181 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 10182 10183 if (wl->rfk_info.state == BTC_WRFK_START) 10184 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 10185 &rtwdev->coex_rfk_chk_work, 10186 RTW89_COEX_RFK_CHK_WORK_PERIOD); 10187 } 10188 10189 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10190 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 10191 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 10192 10193 return result; 10194 } 10195 10196 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 10197 enum btc_wl_rfk_type type, 10198 enum btc_wl_rfk_state state) 10199 { 10200 u8 band; 10201 bool allow; 10202 int ret; 10203 10204 lockdep_assert_wiphy(rtwdev->hw->wiphy); 10205 10206 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 10207 10208 rtw89_debug(rtwdev, RTW89_DBG_RFK, 10209 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 10210 band == RTW89_BAND_2G ? "2G" : 10211 band == RTW89_BAND_5G ? "5G" : "6G", 10212 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 10213 type, 10214 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 10215 state == BTC_WRFK_STOP ? "RFK_STOP" : 10216 state == BTC_WRFK_START ? "RFK_START" : 10217 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 10218 "ONE-SHOT_STOP"); 10219 10220 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 10221 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 10222 return; 10223 } 10224 10225 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 10226 rtwdev, phy_map, type, state); 10227 if (ret) { 10228 rtw89_warn(rtwdev, "RFK notify timeout\n"); 10229 rtwdev->is_bt_iqk_timeout = true; 10230 } 10231 } 10232 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 10233 10234 struct rtw89_btc_wl_sta_iter_data { 10235 struct rtw89_dev *rtwdev; 10236 u8 busy_all; 10237 u8 dir_all; 10238 u8 rssi_map_all; 10239 bool is_sta_change; 10240 bool is_traffic_change; 10241 }; 10242 10243 static 10244 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, 10245 struct rtw89_sta_link *rtwsta_link, 10246 struct rtw89_btc_wl_sta_iter_data *iter_data) 10247 { 10248 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 10249 struct rtw89_dev *rtwdev = iter_data->rtwdev; 10250 struct rtw89_btc *btc = &rtwdev->btc; 10251 struct rtw89_btc_dm *dm = &btc->dm; 10252 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10253 struct rtw89_btc_wl_link_info *link_info = NULL; 10254 struct rtw89_traffic_stats *link_info_t = NULL; 10255 struct rtw89_traffic_stats *stats = &rtwvif->stats; 10256 const struct rtw89_chip_info *chip = rtwdev->chip; 10257 struct rtw89_btc_wl_role_info *r; 10258 u32 last_tx_rate, last_rx_rate; 10259 u8 link = rtwvif_link->phy_idx; 10260 u16 last_tx_lvl, last_rx_lvl; 10261 u8 port = rtwvif_link->port; 10262 u8 rssi; 10263 u8 busy = 0; 10264 u8 dir = 0; 10265 u8 rssi_map = 0; 10266 u8 i = 0; 10267 bool is_sta_change = false, is_traffic_change = false; 10268 10269 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; 10270 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 10271 10272 link_info = &wl->rlink_info[port][link]; 10273 10274 link_info->stat.traffic = *stats; 10275 link_info_t = &link_info->stat.traffic; 10276 10277 if (link_info->connected == MLME_NO_LINK) { 10278 link_info->rx_rate_drop_cnt = 0; 10279 return; 10280 } 10281 10282 link_info->stat.rssi = rssi; 10283 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 10284 link_info->rssi_state[i] = 10285 _update_rssi_state(rtwdev, 10286 link_info->rssi_state[i], 10287 link_info->stat.rssi, 10288 chip->wl_rssi_thres[i]); 10289 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 10290 rssi_map |= BIT(i); 10291 10292 if (btc->ant_type == BTC_ANT_DEDICATED && 10293 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 10294 is_sta_change = true; 10295 } 10296 iter_data->rssi_map_all |= rssi_map; 10297 10298 last_tx_rate = link_info_t->tx_rate; 10299 last_rx_rate = link_info_t->rx_rate; 10300 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 10301 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 10302 10303 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 10304 stats->rx_tfc_lv != RTW89_TFC_IDLE) 10305 busy = 1; 10306 10307 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 10308 dir = RTW89_TFC_UL; 10309 else 10310 dir = RTW89_TFC_DL; 10311 10312 if (link_info->busy != busy || link_info->dir != dir) { 10313 is_sta_change = true; 10314 link_info->busy = busy; 10315 link_info->dir = dir; 10316 } 10317 10318 iter_data->busy_all |= busy; 10319 iter_data->dir_all |= BIT(dir); 10320 10321 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 10322 last_rx_rate > RTW89_HW_RATE_CCK2 && 10323 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 10324 link_info->rx_rate_drop_cnt++; 10325 10326 if (last_tx_rate != rtwsta_link->ra_report.hw_rate || 10327 last_rx_rate != rtwsta_link->rx_hw_rate || 10328 last_tx_lvl != link_info_t->tx_tfc_lv || 10329 last_rx_lvl != link_info_t->rx_tfc_lv) 10330 is_traffic_change = true; 10331 10332 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; 10333 link_info_t->rx_rate = rtwsta_link->rx_hw_rate; 10334 10335 if (link_info->role == RTW89_WIFI_ROLE_STATION || 10336 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 10337 dm->trx_info.tx_rate = link_info_t->tx_rate; 10338 dm->trx_info.rx_rate = link_info_t->rx_rate; 10339 } 10340 10341 r = &wl->role_info; 10342 r->rlink[port][link].tx_lvl = stats->tx_tfc_lv; 10343 r->rlink[port][link].rx_lvl = stats->rx_tfc_lv; 10344 r->rlink[port][link].tx_rate = rtwsta_link->ra_report.hw_rate; 10345 r->rlink[port][link].rx_rate = rtwsta_link->rx_hw_rate; 10346 10347 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 10348 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 10349 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; 10350 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; 10351 dm->trx_info.tx_tp = link_info_t->tx_throughput; 10352 dm->trx_info.rx_tp = link_info_t->rx_throughput; 10353 10354 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */ 10355 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx && 10356 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) || 10357 (dm->wl_pre_agc_rb != dm->wl_pre_agc && 10358 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND)) 10359 iter_data->is_sta_change = true; 10360 10361 if (is_sta_change) 10362 iter_data->is_sta_change = true; 10363 10364 if (is_traffic_change) 10365 iter_data->is_traffic_change = true; 10366 } 10367 10368 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 10369 { 10370 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 10371 struct rtw89_btc_wl_sta_iter_data *iter_data = 10372 (struct rtw89_btc_wl_sta_iter_data *)data; 10373 struct rtw89_vif_link *rtwvif_link; 10374 struct rtw89_sta_link *rtwsta_link; 10375 unsigned int link_id; 10376 10377 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 10378 rtwvif_link = rtwsta_link->rtwvif_link; 10379 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); 10380 } 10381 } 10382 10383 #define BTC_NHM_CHK_INTVL 20 10384 10385 static bool _update_wl_rssi_status(struct rtw89_dev *rtwdev) 10386 { 10387 struct rtw89_btc *btc = &rtwdev->btc; 10388 struct rtw89_btc_cx *cx = &btc->cx; 10389 struct rtw89_btc_wl_info *wl = &cx->wl; 10390 struct rtw89_btc_dm *dm = &btc->dm; 10391 struct rtw89_btc_bt_link_info *b; 10392 u8 i, j, ant_iso, th, rssi, nxt, bt_enable; 10393 u8 wl_rf_band = RTW89_BAND_2G, cnt = 0; 10394 bool status_change = false; 10395 s8 bt_pin; 10396 s32 val; 10397 10398 /* Update WL RSSI (search the min value between all role/HW-band) */ 10399 rssi = 110; /* unit: % */ 10400 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 10401 for (j = 0; j < RTW89_MAC_NUM; j++) { 10402 if (!wl->rlink_info[i][j].active || 10403 wl->rlink_info[i][j].connected == MLME_NO_LINK) 10404 continue; 10405 10406 if (wl->rlink_info[i][j].stat.rssi < rssi) { /* find min */ 10407 rssi = wl->rlink_info[i][j].stat.rssi; 10408 wl_rf_band = wl->rlink_info[i][j].band; 10409 cnt++; 10410 } 10411 } 10412 } 10413 10414 if (cnt == 0) /* no wifi link exist */ 10415 wl->rssi = 0; 10416 else 10417 wl->rssi = rssi; 10418 10419 /* SIR state: compare WL_RSSI with each BT-Tx interference */ 10420 for (i = BTC_BT_1ST; i <= BTC_BT_EXT; i++) { 10421 switch (i) { 10422 case BTC_BT_1ST: 10423 default: 10424 bt_enable = cx->bt0.enable.now; 10425 ant_iso = cx->bt0.ant_iso_to_wl; 10426 if (wl_rf_band != RTW89_BAND_2G) /* find same rf-band */ 10427 b = &cx->bt0.link_info_56g; 10428 else 10429 b = &cx->bt0.link_info; 10430 if (b->bt_txpwr_desc.le_dbm > b->bt_txpwr_desc.br_dbm) 10431 bt_pin = b->bt_txpwr_desc.le_dbm; 10432 else 10433 bt_pin = b->bt_txpwr_desc.br_dbm; 10434 break; 10435 case BTC_BT_2ND: 10436 bt_enable = cx->bt1.enable.now; 10437 ant_iso = cx->bt1.ant_iso_to_wl; 10438 if (wl_rf_band != RTW89_BAND_2G) /* find same rf-band */ 10439 b = &cx->bt0.link_info_56g; 10440 else 10441 b = &cx->bt0.link_info; 10442 if (b->bt_txpwr_desc.le_dbm > b->bt_txpwr_desc.br_dbm) 10443 bt_pin = b->bt_txpwr_desc.le_dbm; 10444 else 10445 bt_pin = b->bt_txpwr_desc.br_dbm; 10446 break; 10447 case BTC_BT_EXT: 10448 bt_enable = !!cx->bt_ext.func_type; 10449 ant_iso = cx->bt_ext.ant_iso_to_wl; 10450 bt_pin = cx->bt_ext.max_tx_pwr; 10451 break; 10452 } 10453 10454 val = 110 + bt_pin - ant_iso - dm->sir_thres; 10455 if (!bt_enable || val <= 0) 10456 th = 0; 10457 else if (val >= 110) 10458 th = 110; 10459 else 10460 th = (u8)val; 10461 10462 dm->tdd_rssi_thres = th; 10463 10464 nxt = _update_rssi_state(rtwdev, dm->sir_state[i], wl->rssi, th); 10465 10466 if (nxt != dm->sir_state[i]) { 10467 dm->sir_state[i] = nxt; 10468 status_change = true; 10469 } 10470 } 10471 10472 return status_change; 10473 } 10474 10475 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 10476 { 10477 struct rtw89_btc *btc = &rtwdev->btc; 10478 struct rtw89_btc_dm *dm = &btc->dm; 10479 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10480 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 10481 u8 i; 10482 10483 ieee80211_iterate_stations_atomic(rtwdev->hw, 10484 rtw89_btc_ntfy_wl_sta_iter, 10485 &data); 10486 10487 wl->rssi_level = 0; 10488 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 10489 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 10490 /* set RSSI level 4 ~ 0 if rssi bit map match */ 10491 if (data.rssi_map_all & BIT(i - 1)) { 10492 wl->rssi_level = i; 10493 break; 10494 } 10495 } 10496 10497 if (dm->trx_info.wl_rssi != wl->rssi_level) 10498 dm->trx_info.wl_rssi = wl->rssi_level; 10499 10500 if (_update_wl_rssi_status(rtwdev)) 10501 _update_sdm_map(rtwdev); 10502 10503 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 10504 __func__, !!wl->status.map.busy); 10505 10506 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 10507 10508 if (data.is_traffic_change) 10509 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 10510 if (data.is_sta_change) { 10511 wl->status.map.busy = data.busy_all; 10512 if (wl->status.map.traffic_dir != data.dir_all) { 10513 wl->status.map.traffic_dir = data.dir_all; 10514 /* 10515 * traffic_dir (UL/DL) switch changes the 1SS MIMO-PS 10516 * xtk_xmap, recompute sit_xmap in the same coex cycle 10517 */ 10518 _update_sdm_map(rtwdev); 10519 } 10520 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 10521 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 10522 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 10523 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 10524 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 10525 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 10526 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 10527 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 10528 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 10529 } 10530 } 10531 10532 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) 10533 { 10534 struct rtw89_btc *btc = &rtwdev->btc; 10535 const struct rtw89_btc_ver *ver = btc->ver; 10536 10537 switch (func) { 10538 case BTF_EVNT_RPT: 10539 case BTF_EVNT_BT_INFO: 10540 case BTF_EVNT_BT_SCBD: 10541 case BTF_EVNT_BT_REG: 10542 case BTF_EVNT_CX_RUNINFO: 10543 case BTF_EVNT_BT_PSD: 10544 return func; 10545 case BTF_EVNT_BT_DEV_INFO: 10546 if (ver->fwc2hfunc == 0) 10547 return BTF_EVNT_BUF_OVERFLOW; 10548 else 10549 return BTF_EVNT_BT_DEV_INFO; 10550 case BTF_EVNT_BT_LEAUDIO_INFO: 10551 if (ver->fwc2hfunc == 0) 10552 return BTF_EVNT_C2H_LOOPBACK; 10553 else if (ver->fwc2hfunc == 1) 10554 return BTF_EVNT_BUF_OVERFLOW; 10555 else if (ver->fwc2hfunc == 2) 10556 return func; 10557 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 10558 return BTF_EVNT_BUF_OVERFLOW; 10559 else 10560 return BTF_EVNT_MAX; 10561 case BTF_EVNT_BUF_OVERFLOW: 10562 if (ver->fwc2hfunc == 0) 10563 return BTF_EVNT_MAX; 10564 else if (ver->fwc2hfunc == 1) 10565 return BTF_EVNT_C2H_LOOPBACK; 10566 else if (ver->fwc2hfunc == 2) 10567 return func; 10568 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 10569 return BTF_EVNT_C2H_LOOPBACK; 10570 else 10571 return BTF_EVNT_MAX; 10572 case BTF_EVNT_C2H_LOOPBACK: 10573 if (ver->fwc2hfunc == 2) 10574 return func; 10575 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 10576 return BTF_EVNT_BT_LEAUDIO_INFO; 10577 else 10578 return BTF_EVNT_MAX; 10579 case BTF_EVNT_BT_QUERY_TXPWR: 10580 if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4) 10581 return func; 10582 else 10583 return BTF_EVNT_MAX; 10584 case BTF_EVNT_ZB_INFO: 10585 case BTF_EVNT_ZB_CH: 10586 case BTF_EVNT_ZB_QUERY_TXPWR: 10587 if (ver->fwc2hfunc == 4) 10588 return func; 10589 else 10590 return BTF_EVNT_MAX; 10591 case BTF_EVNT_MAX: 10592 default: 10593 return BTF_EVNT_MAX; 10594 } 10595 } 10596 10597 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 10598 u32 len, u8 class, u8 func) 10599 { 10600 struct rtw89_btc *btc = &rtwdev->btc; 10601 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 10602 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10603 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 10604 u8 bid = BTC_BT_1ST; 10605 10606 len -= RTW89_C2H_HEADER_LEN; 10607 10608 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10609 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 10610 __func__, len, class, func); 10611 10612 if (class != BTFC_FW_EVENT) 10613 return; 10614 10615 if (func & BT_C2H_FUNC_BT2ND) { 10616 bid = BTC_BT_2ND; 10617 func &= ~BT_C2H_FUNC_BT2ND; 10618 bt = &btc->cx.bt1; 10619 } 10620 10621 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); 10622 pfwinfo->cnt_c2h++; 10623 10624 switch (func) { 10625 case BTF_EVNT_BUF_OVERFLOW: 10626 pfwinfo->event[func]++; 10627 break; 10628 case BTF_EVNT_RPT: 10629 pfwinfo->event[func]++; 10630 /* Don't need rtw89_leave_ps_mode() */ 10631 btc_fw_event(rtwdev, func, buf, len); 10632 break; 10633 case BTF_EVNT_BT_INFO: 10634 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10635 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 10636 bt->bcnt[BTC_BCNT_INFOUPDATE]++; 10637 _update_bt_info(rtwdev, bid, buf, len); 10638 break; 10639 case BTF_EVNT_BT_SCBD: 10640 bt->bcnt[BTC_BCNT_SCBDUPDATE]++; 10641 bt->scbd_c2h = ((buf[3] << 24) | (buf[2] << 16) | 10642 (buf[1] << 8) | (buf[0])); 10643 bt->scbd_rb = bt->scbd_c2h; 10644 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10645 "[BTC], handle C2H BT%d SCBD with data 0x%08x\n", 10646 bid, bt->scbd_c2h); 10647 _update_bt_scbd(rtwdev, bid, true); 10648 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 10649 break; 10650 case BTF_EVNT_BT_PSD: 10651 break; 10652 case BTF_EVNT_BT_REG: 10653 btc->dbg.rb_done = true; 10654 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 10655 10656 break; 10657 case BTF_EVNT_C2H_LOOPBACK: 10658 btc->dbg.rb_done = true; 10659 btc->dbg.rb_val = buf[0]; 10660 break; 10661 case BTF_EVNT_CX_RUNINFO: 10662 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 10663 break; 10664 case BTF_EVNT_BT_LEAUDIO_INFO: 10665 bt->bcnt[BTC_BCNT_LEAUDIO_INFOUPDATE]++; 10666 if (buf[BTC_BTINFO_L0] == BTC_BTINFO_BISTDMA) 10667 _update_bt_bistdma_info(rtwdev, bid, buf, len); 10668 else 10669 _update_bt_leaudio_info(rtwdev, bid, buf, len); 10670 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_LEAUDINFO); 10671 break; 10672 case BTF_EVNT_BT_QUERY_TXPWR: 10673 bt->bcnt[BTC_BCNT_TXPWR_UPDATE]++; 10674 _update_bt_txpwr_info(rtwdev, bid, buf, len); 10675 } 10676 } 10677 10678 #define BTC_CX_FW_OFFLOAD 0 10679 10680 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10681 { 10682 struct rtw89_btc_module *md = &rtwdev->btc.mdinfo; 10683 const struct rtw89_chip_info *chip = rtwdev->chip; 10684 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 10685 struct rtw89_hal *hal = &rtwdev->hal; 10686 struct rtw89_btc *btc = &rtwdev->btc; 10687 struct rtw89_btc_dm *dm = &btc->dm; 10688 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 10689 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10690 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 10691 char *p = buf, *end = buf + bufsz; 10692 10693 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 10694 return 0; 10695 10696 p += scnprintf(p, end - p, 10697 "\n========== [BTC COEX INFO (%s)] ==========\n", 10698 chip_id_str(chip->chip_id)); 10699 10700 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 10701 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 10702 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 10703 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 10704 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ", 10705 "[coex_version]", ver_main, ver_sub, ver_hotfix, 10706 id_branch); 10707 10708 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 10709 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 10710 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 10711 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 10712 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)", 10713 ver_main, ver_sub, ver_hotfix, id_branch); 10714 10715 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 10716 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 10717 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 10718 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ", 10719 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 10720 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 10721 10722 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n", 10723 bt->ver_info.fw_coex, 10724 (bt->ver_info.fw_coex >= ver->bt_desired ? 10725 "Match" : "Mismatch"), ver->bt_desired); 10726 10727 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 10728 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 10729 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 10730 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 10731 p += scnprintf(p, end - p, 10732 " %-15s : WL_FW:%d.%d.%d.%d(built:%.12s-%.12s), BT_FW:0x%x(%s)\n", 10733 "[sub_module]", 10734 ver_main, ver_sub, ver_hotfix, id_branch, 10735 wl->ver_info.build_time, wl->ver_info.build_date, 10736 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 10737 10738 p += scnprintf(p, end - p, 10739 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 10740 "[hw_info]", 10741 md->kt_ver, md->rfe_type, md->ant.isolation, 10742 md->ant.num, md->ant.num > 1 ? "" : 10743 md->ant.single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, "); 10744 10745 p += scnprintf(p, end - p, 10746 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 10747 btc->cx.bt_ext.func_type, rtwdev->dbcc_en, hal->tx_nss, 10748 hal->rx_nss); 10749 10750 return p - buf; 10751 } 10752 10753 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10754 { 10755 struct rtw89_btc *btc = &rtwdev->btc; 10756 struct rtw89_btc_wl_link_info *plink = NULL; 10757 struct rtw89_traffic_stats *t; 10758 char *p = buf, *end = buf + bufsz; 10759 u8 i, j; 10760 10761 for (i = 0; i < btc->ver->max_role_num; i++) { 10762 for (j = 0; j < RTW89_MAC_NUM; j++) { 10763 plink = &btc->cx.wl.rlink_info[i][j]; 10764 10765 if (!plink->active) 10766 continue; 10767 10768 p += scnprintf(p, end - p, 10769 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 10770 plink->pid, plink->role, plink->phy, 10771 id_to_mlme_state(plink->connected), 10772 plink->client_cnt - 1, plink->mode, 10773 plink->ch, plink->bw); 10774 10775 if (plink->connected == MLME_NO_LINK) { 10776 p += scnprintf(p, end - p, "\n"); 10777 continue; 10778 } 10779 10780 p += scnprintf(p, end - p, 10781 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 10782 plink->mac_id, plink->tx_time, plink->tx_retry); 10783 10784 p += scnprintf(p, end - p, 10785 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 10786 plink->pid, 110 - plink->stat.rssi, 10787 plink->stat.rssi, plink->busy, 10788 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 10789 10790 t = &plink->stat.traffic; 10791 10792 p += scnprintf(p, end - p, 10793 "tx[rate:%d/busy_level:%d], ", 10794 t->tx_rate, t->tx_tfc_lv); 10795 10796 p += scnprintf(p, end - p, 10797 "rx[rate:%d/busy_level:%d/drop:%d]\n", 10798 t->rx_rate, 10799 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 10800 } 10801 } 10802 return p - buf; 10803 } 10804 10805 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10806 { 10807 struct rtw89_btc *btc = &rtwdev->btc; 10808 struct rtw89_btc_cx *cx = &btc->cx; 10809 struct rtw89_btc_wl_info *wl = &cx->wl; 10810 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 10811 struct rtw89_btc_wl_mlo_info *wl_minfo = &wl->mlo_info; 10812 char *p = buf, *end = buf + bufsz; 10813 u8 mode; 10814 10815 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 10816 return 0; 10817 10818 p += scnprintf(p, end - p, "========== [WL Status] ==========\n"); 10819 10820 mode = wl_rinfo->link_mode[RTW89_MAC_0]; 10821 10822 p += scnprintf(p, end - p, " %-15s : link_mode:%s(HWB0)/%s(HWB1), ", "[status]", 10823 id_to_linkmode(mode), 10824 id_to_linkmode(wl_rinfo->link_mode[RTW89_MAC_1])); 10825 10826 p += scnprintf(p, end - p, 10827 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 10828 wl->status.map.rf_off, wl->status.map.lps, 10829 wl->status.map.scan ? "Y" : "N", 10830 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 10831 10832 p += scnprintf(p, end - p, 10833 "handshake:%s, roam:%s, 4way:%s, init_ok:%s\n", 10834 wl->status.map.handshake ? "Y" : "N", 10835 wl->status.map.roaming ? "Y" : "N", 10836 wl->status.map._4way ? "Y" : "N", 10837 wl->status.map.init_ok ? "Y" : "N"); 10838 10839 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { 10840 p += scnprintf(p, end - p, 10841 " %-15s : type:%d/rf_comb:%d/dbcc_en:%d, ", 10842 "[MLO]", wl_minfo->wtype, wl_minfo->rf_combination, 10843 wl_rinfo->dbcc_en); 10844 p += scnprintf(p, end - p, 10845 "HWB0(wmode:%d/ch:%d/rf_band:%d/p2p:%d), ", 10846 wl_minfo->wmode[RTW89_MAC_0], 10847 wl_minfo->ch_type[RTW89_MAC_0], 10848 wl_minfo->hwb_rf_band[RTW89_MAC_0], 10849 wl_rinfo->p2p_exist[RTW89_MAC_0]); 10850 p += scnprintf(p, end - p, 10851 "HWB1(wmode:%d/ch:%d/rf_band:%d/p2p:%d)\n", 10852 wl_minfo->wmode[RTW89_MAC_1], 10853 wl_minfo->ch_type[RTW89_MAC_1], 10854 wl_minfo->hwb_rf_band[RTW89_MAC_1], 10855 wl_rinfo->p2p_exist[RTW89_MAC_1]); 10856 } 10857 10858 p += _show_wl_role_info(rtwdev, p, end - p); 10859 10860 return p - buf; 10861 } 10862 10863 enum btc_bt_a2dp_type { 10864 BTC_A2DP_LEGACY = 0, 10865 BTC_A2DP_TWS_SNIFF = 1, 10866 BTC_A2DP_TWS_RELAY = 2, 10867 }; 10868 10869 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, 10870 size_t bufsz, u8 bid) 10871 { 10872 struct rtw89_btc *btc = &rtwdev->btc; 10873 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? 10874 &btc->cx.bt0 : &btc->cx.bt1; 10875 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 10876 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 10877 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 10878 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 10879 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 10880 char *p = buf, *end = buf + bufsz; 10881 10882 if (hfp.exist) { 10883 p += scnprintf(p, end - p, 10884 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 10885 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 10886 bt_linfo->sut_pwr_level[0], 10887 bt_linfo->golden_rx_shift[0]); 10888 } 10889 10890 if (hid.exist) { 10891 p += scnprintf(p, end - p, 10892 "\n %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 10893 "[HID]", 10894 hid.type & BTC_HID_218 ? "2/18," : "", 10895 hid.type & BTC_HID_418 ? "4/18," : "", 10896 hid.type & BTC_HID_BLE ? "BLE," : "", 10897 hid.type & BTC_HID_RCU ? "RCU," : "", 10898 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 10899 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 10900 bt_linfo->golden_rx_shift[1]); 10901 } 10902 10903 if (a2dp.exist) { 10904 p += scnprintf(p, end - p, 10905 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 10906 "[A2DP]", 10907 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 10908 a2dp.bitpool, a2dp.flush_time); 10909 10910 p += scnprintf(p, end - p, 10911 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 10912 a2dp.vendor_id, a2dp.device_name, 10913 bt_linfo->sut_pwr_level[2], 10914 bt_linfo->golden_rx_shift[2]); 10915 } 10916 10917 if (pan.exist) { 10918 p += scnprintf(p, end - p, 10919 " %-15s : sut_pwr:%d, golden-rx:%d\n", 10920 "[PAN]", 10921 bt_linfo->sut_pwr_level[3], 10922 bt_linfo->golden_rx_shift[3]); 10923 } 10924 10925 return p - buf; 10926 } 10927 10928 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, u8 bid) 10929 { 10930 struct rtw89_btc *btc = &rtwdev->btc; 10931 const struct rtw89_btc_ver *ver = btc->ver; 10932 struct rtw89_btc_cx *cx = &btc->cx; 10933 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1; 10934 struct rtw89_btc_wl_info *wl = &cx->wl; 10935 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 10936 struct rtw89_btc_module *md = &btc->mdinfo; 10937 u8 bt_pos = (bid == BTC_BT_1ST) ? md->bt0_pos : md->bt1_pos; 10938 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm; 10939 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm; 10940 u8 hw_band = wl->role_info.pta_req_band; 10941 struct rtw89_btc_wl_afh_info *wl_afh; 10942 char *p = buf, *end = buf + bufsz; 10943 u8 *afh = bt_linfo->afh_map; 10944 u8 *afh_le = bt_linfo->afh_map_le; 10945 10946 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 10947 return 0; 10948 10949 if (bid == BTC_BT_2ND) { 10950 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)) 10951 return 0; 10952 if (!bt->enable.now) 10953 return 0; 10954 } 10955 10956 p += scnprintf(p, end - p, "========== [BT_%s Status] ==========\n", 10957 bid == BTC_BT_1ST ? "1ST" : "2ND"); 10958 10959 p += scnprintf(p, end - p, 10960 " %-15s : enable:%s, btg:%s%s, connect:%s, ", 10961 "[status]", bt->enable.now ? "Y" : "N", 10962 bt->btg_type ? "Y" : "N", 10963 (bt->enable.now && (bt->btg_type != bt_pos) ? 10964 "(efuse-mismatch!!)" : ""), 10965 (bt_linfo->status.map.connect ? "Y" : "N")); 10966 10967 p += scnprintf(p, end - p, 10968 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 10969 bt->igno_wl ? "Y" : "N", 10970 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 10971 10972 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ", 10973 "[profile]", 10974 (bt_linfo->link_cnt.now == 0) ? "None," : "", 10975 bt_linfo->hfp_desc.exist ? "HFP," : "", 10976 bt_linfo->hid_desc.exist ? "HID," : "", 10977 bt_linfo->a2dp_desc.exist ? 10978 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 10979 bt_linfo->pan_desc.exist ? "PAN," : ""); 10980 10981 p += scnprintf(p, end - p, 10982 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 10983 bt_linfo->multi_link.now ? "Y" : "N", 10984 bt_linfo->slave_role ? "Slave" : "Master", 10985 bt_linfo->status.map.ble_connect ? "Y" : "N", 10986 bt_linfo->cqddr ? "Y" : "N", 10987 bt_linfo->a2dp_desc.active ? "Y" : "N", 10988 bt_linfo->pan_desc.active ? "Y" : "N"); 10989 10990 p += scnprintf(p, end - p, 10991 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s", 10992 "[link]", bt_linfo->rssi - 100, 10993 bt->rssi_level, 10994 bt_linfo->tx_3m ? 3 : 2, 10995 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 10996 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 10997 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 10998 10999 p += scnprintf(p, end - p, 11000 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 11001 bt_linfo->relink.now ? " ReLink!!" : "", 11002 afh[0], afh[1], afh[2], afh[3], afh[4], 11003 afh[5], afh[6], afh[7], afh[8], afh[9]); 11004 11005 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 11006 p += scnprintf(p, end - p, 11007 "LE[%02x%02x_%02x_%02x%02x]", 11008 afh_le[0], afh_le[1], afh_le[2], 11009 afh_le[3], afh_le[4]); 11010 11011 wl_afh = &wl->afh_info[hw_band][RTW89_BAND_2G]; 11012 p += scnprintf(p, end - p, "wl_ch_map[hwb:%d/en:%d/ch:%d/bw:%d/rf_band:%d]\n", 11013 hw_band, wl_afh->en, wl_afh->ch, wl_afh->bw, wl_afh->band); 11014 11015 p += scnprintf(p, end - p, 11016 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 11017 "[stat_cnt]", bt->bcnt[BTC_BCNT_RETRY], 11018 bt->bcnt[BTC_BCNT_RELINK], 11019 bt->bcnt[BTC_BCNT_RATECHG], 11020 bt->bcnt[BTC_BCNT_REINIT], 11021 bt->bcnt[BTC_BCNT_REENABLE]); 11022 11023 p += scnprintf(p, end - p, 11024 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 11025 bt->bcnt[BTC_BCNT_ROLESW], bt->bcnt[BTC_BCNT_AFH], 11026 bt->bcnt[BTC_BCNT_INQPAG], bt->bcnt[BTC_BCNT_INQ], 11027 bt->bcnt[BTC_BCNT_PAGE], bt->bcnt[BTC_BCNT_IGNOWL]); 11028 11029 p += _show_bt_profile_info(rtwdev, p, end - p, bid); 11030 11031 p += scnprintf(p, end - p, 11032 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 11033 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 11034 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 11035 bt->raw_info[7], 11036 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 11037 bt->bcnt[BTC_BCNT_INFOUPDATE], 11038 bt->bcnt[BTC_BCNT_INFOSAME]); 11039 11040 p += scnprintf(p, end - p, 11041 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 11042 "[trx_req_cnt]", bt->bcnt[BTC_BCNT_HIPRI_RX], 11043 bt->bcnt[BTC_BCNT_HIPRI_TX], 11044 bt->bcnt[BTC_BCNT_LOPRI_RX], 11045 bt->bcnt[BTC_BCNT_LOPRI_TX], 11046 bt->bcnt[BTC_BCNT_POLLUTED]); 11047 11048 if (ver->fcxbtscan == 1) { 11049 p += scnprintf(p, end - p, 11050 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 11051 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 11052 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 11053 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 11054 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 11055 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 11056 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 11057 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 11058 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 11059 } else if (ver->fcxbtscan == 2) { 11060 p += scnprintf(p, end - p, 11061 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 11062 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 11063 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 11064 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 11065 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 11066 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 11067 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 11068 } 11069 p += scnprintf(p, end - p, "\n"); 11070 11071 if (bt->bcnt[BTC_BCNT_TXPWR_UPDATE]) { 11072 p += scnprintf(p, end - p, 11073 " %-15s : br_index:0x%x, le_index:0x%x", 11074 "[bt_txpwr_lvl]", 11075 bt->link_info.bt_txpwr_desc.br_gain_index, 11076 bt->link_info.bt_txpwr_desc.le_gain_index); 11077 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm); 11078 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm); 11079 } else { 11080 p += scnprintf(p, end - p, 11081 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]", 11082 "[bt_txpwr_lvl]", 11083 bt->link_info.bt_txpwr_desc.br_dbm, 11084 bt->link_info.bt_txpwr_desc.le_dbm); 11085 } 11086 p += scnprintf(p, end - p, "\n"); 11087 11088 return p - buf; 11089 } 11090 11091 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 11092 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 11093 #define CASE_BTC_POLICY_STR(e) \ 11094 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 11095 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 11096 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 11097 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e 11098 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e 11099 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e 11100 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e 11101 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e 11102 #define CASE_BTC_H2CCMD(e) case SET_##e: return #e 11103 11104 static const char *id_to_polut(u32 id) 11105 { 11106 switch (id) { 11107 CASE_BTC_POLUT_STR(NONE); 11108 CASE_BTC_POLUT_STR(GNT_BT_TX); 11109 CASE_BTC_POLUT_STR(GNT_BT_RX); 11110 CASE_BTC_POLUT_STR(GNT_WL); 11111 CASE_BTC_POLUT_STR(BT); 11112 CASE_BTC_POLUT_STR(ALL); 11113 default: 11114 return "unknown"; 11115 } 11116 } 11117 11118 static const char *id_to_regtype(u32 id) 11119 { 11120 switch (id) { 11121 CASE_BTC_REGTYPE_STR(MAC); 11122 CASE_BTC_REGTYPE_STR(BB); 11123 CASE_BTC_REGTYPE_STR(RF); 11124 CASE_BTC_REGTYPE_STR(BT_RF); 11125 CASE_BTC_REGTYPE_STR(BT_MODEM); 11126 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE); 11127 CASE_BTC_REGTYPE_STR(BT_VENDOR); 11128 CASE_BTC_REGTYPE_STR(BT_LE); 11129 default: 11130 return "unknown"; 11131 } 11132 } 11133 11134 static const char *id_to_gdbg(u32 id) 11135 { 11136 switch (id) { 11137 CASE_BTC_GDBG_STR(GNT_BT); 11138 CASE_BTC_GDBG_STR(GNT_WL); 11139 CASE_BTC_GDBG_STR(GNT_BT1); 11140 CASE_BTC_GDBG_STR(GNT_WL1); 11141 CASE_BTC_GDBG_STR(BCN_EARLY); 11142 CASE_BTC_GDBG_STR(WL_NULL0); 11143 CASE_BTC_GDBG_STR(WL_NULL1); 11144 CASE_BTC_GDBG_STR(WL_RXISR); 11145 CASE_BTC_GDBG_STR(TDMA_ENTRY); 11146 CASE_BTC_GDBG_STR(A2DP_EMPTY); 11147 CASE_BTC_GDBG_STR(BT_RETRY); 11148 CASE_BTC_GDBG_STR(BT_RELINK); 11149 CASE_BTC_GDBG_STR(SLOT_WL); 11150 CASE_BTC_GDBG_STR(SLOT_BT); 11151 CASE_BTC_GDBG_STR(WL_ERR); 11152 CASE_BTC_GDBG_STR(WL_OK); 11153 CASE_BTC_GDBG_STR(SLOT_B2W); 11154 CASE_BTC_GDBG_STR(SLOT_W1); 11155 CASE_BTC_GDBG_STR(SLOT_W2); 11156 CASE_BTC_GDBG_STR(SLOT_W2B); 11157 CASE_BTC_GDBG_STR(SLOT_B1); 11158 CASE_BTC_GDBG_STR(SLOT_B2); 11159 CASE_BTC_GDBG_STR(SLOT_B3); 11160 CASE_BTC_GDBG_STR(SLOT_B4); 11161 CASE_BTC_GDBG_STR(SLOT_LK); 11162 CASE_BTC_GDBG_STR(SLOT_E2G); 11163 CASE_BTC_GDBG_STR(SLOT_E5G); 11164 CASE_BTC_GDBG_STR(SLOT_EBT); 11165 CASE_BTC_GDBG_STR(SLOT_WLK); 11166 CASE_BTC_GDBG_STR(SLOT_B1FDD); 11167 CASE_BTC_GDBG_STR(BT_CHANGE); 11168 CASE_BTC_GDBG_STR(WL_CCA); 11169 default: 11170 return "unknown"; 11171 } 11172 } 11173 11174 static const char *steps_to_str(u16 step) 11175 { 11176 switch (step) { 11177 CASE_BTC_RSN_STR(NONE); 11178 CASE_BTC_RSN_STR(NTFY_INIT); 11179 CASE_BTC_RSN_STR(NTFY_SWBAND); 11180 CASE_BTC_RSN_STR(NTFY_WL_STA); 11181 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 11182 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 11183 CASE_BTC_RSN_STR(NTFY_WL_RFK); 11184 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 11185 CASE_BTC_RSN_STR(NTFY_SCAN_START); 11186 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 11187 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 11188 CASE_BTC_RSN_STR(NTFY_POWEROFF); 11189 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 11190 CASE_BTC_RSN_STR(CMD_SET_COEX); 11191 CASE_BTC_RSN_STR(ACT1_WORK); 11192 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 11193 CASE_BTC_RSN_STR(RFK_CHK_WORK); 11194 CASE_BTC_RSN_STR(UPDATE_BT_LEAUDINFO); 11195 11196 CASE_BTC_ACT_STR(NONE); 11197 CASE_BTC_ACT_STR(WL_ONLY); 11198 CASE_BTC_ACT_STR(WL_5G); 11199 CASE_BTC_ACT_STR(WL_OTHER); 11200 CASE_BTC_ACT_STR(WL_IDLE); 11201 CASE_BTC_ACT_STR(WL_NC); 11202 CASE_BTC_ACT_STR(WL_RFK); 11203 CASE_BTC_ACT_STR(WL_INIT); 11204 CASE_BTC_ACT_STR(WL_OFF); 11205 CASE_BTC_ACT_STR(FREERUN); 11206 CASE_BTC_ACT_STR(BT_WHQL); 11207 CASE_BTC_ACT_STR(BT_RFK); 11208 CASE_BTC_ACT_STR(BT_OFF); 11209 CASE_BTC_ACT_STR(BT_IDLE); 11210 CASE_BTC_ACT_STR(BT_HFP); 11211 CASE_BTC_ACT_STR(BT_HID); 11212 CASE_BTC_ACT_STR(BT_A2DP); 11213 CASE_BTC_ACT_STR(BT_A2DPSINK); 11214 CASE_BTC_ACT_STR(BT_PAN); 11215 CASE_BTC_ACT_STR(BT_A2DP_HID); 11216 CASE_BTC_ACT_STR(BT_A2DP_PAN); 11217 CASE_BTC_ACT_STR(BT_PAN_HID); 11218 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 11219 CASE_BTC_ACT_STR(BT_BIS); 11220 CASE_BTC_ACT_STR(BT_CIS); 11221 CASE_BTC_ACT_STR(WL_25G_MCC); 11222 CASE_BTC_ACT_STR(WL_2G_MCC); 11223 CASE_BTC_ACT_STR(WL_2G_SCC); 11224 CASE_BTC_ACT_STR(WL_2G_AP); 11225 CASE_BTC_ACT_STR(WL_2G_GO); 11226 CASE_BTC_ACT_STR(WL_2G_GC); 11227 CASE_BTC_ACT_STR(WL_2G_NAN); 11228 11229 CASE_BTC_POLICY_STR(OFF_BT); 11230 CASE_BTC_POLICY_STR(OFF_WL); 11231 CASE_BTC_POLICY_STR(OFF_EQ0); 11232 CASE_BTC_POLICY_STR(OFF_EQ1); 11233 CASE_BTC_POLICY_STR(OFF_EQ2); 11234 CASE_BTC_POLICY_STR(OFF_EQ3); 11235 CASE_BTC_POLICY_STR(OFF_EQ4); 11236 CASE_BTC_POLICY_STR(OFF_EQ5); 11237 CASE_BTC_POLICY_STR(OFF_BWB0); 11238 CASE_BTC_POLICY_STR(OFF_BWB1); 11239 CASE_BTC_POLICY_STR(OFF_BWB2); 11240 CASE_BTC_POLICY_STR(OFF_BWB3); 11241 CASE_BTC_POLICY_STR(OFF_WL2); 11242 CASE_BTC_POLICY_STR(OFFB_BWB0); 11243 CASE_BTC_POLICY_STR(OFFE_DEF); 11244 CASE_BTC_POLICY_STR(OFFE_DEF2); 11245 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 11246 CASE_BTC_POLICY_STR(OFFE_2GISOB); 11247 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 11248 CASE_BTC_POLICY_STR(OFFE_WL); 11249 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 11250 CASE_BTC_POLICY_STR(FIX_TD3030); 11251 CASE_BTC_POLICY_STR(FIX_TD5050); 11252 CASE_BTC_POLICY_STR(FIX_TD2030); 11253 CASE_BTC_POLICY_STR(FIX_TD4010); 11254 CASE_BTC_POLICY_STR(FIX_TD7010); 11255 CASE_BTC_POLICY_STR(FIX_TD2060); 11256 CASE_BTC_POLICY_STR(FIX_TD3060); 11257 CASE_BTC_POLICY_STR(FIX_TD2080); 11258 CASE_BTC_POLICY_STR(FIX_TDW1B1); 11259 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 11260 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL); 11261 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL); 11262 CASE_BTC_POLICY_STR(PFIX_TD3030); 11263 CASE_BTC_POLICY_STR(PFIX_TD5050); 11264 CASE_BTC_POLICY_STR(PFIX_TD2030); 11265 CASE_BTC_POLICY_STR(PFIX_TD2060); 11266 CASE_BTC_POLICY_STR(PFIX_TD3070); 11267 CASE_BTC_POLICY_STR(PFIX_TD2080); 11268 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 11269 CASE_BTC_POLICY_STR(AUTO_TD50B1); 11270 CASE_BTC_POLICY_STR(AUTO_TD60B1); 11271 CASE_BTC_POLICY_STR(AUTO_TD20B1); 11272 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 11273 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 11274 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 11275 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 11276 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 11277 CASE_BTC_POLICY_STR(AUTO2_TD3050); 11278 CASE_BTC_POLICY_STR(AUTO2_TD3070); 11279 CASE_BTC_POLICY_STR(AUTO2_TD5050); 11280 CASE_BTC_POLICY_STR(AUTO2_TD6060); 11281 CASE_BTC_POLICY_STR(AUTO2_TD2080); 11282 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 11283 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 11284 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 11285 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 11286 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 11287 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 11288 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 11289 default: 11290 return "unknown step"; 11291 } 11292 } 11293 11294 static const char *id_to_slot(u32 id) 11295 { 11296 switch (id) { 11297 CASE_BTC_SLOT_STR(OFF); 11298 CASE_BTC_SLOT_STR(B2W); 11299 CASE_BTC_SLOT_STR(W1); 11300 CASE_BTC_SLOT_STR(W2); 11301 CASE_BTC_SLOT_STR(W2B); 11302 CASE_BTC_SLOT_STR(B1); 11303 CASE_BTC_SLOT_STR(B2); 11304 CASE_BTC_SLOT_STR(B3); 11305 CASE_BTC_SLOT_STR(B4); 11306 CASE_BTC_SLOT_STR(LK); 11307 CASE_BTC_SLOT_STR(BLK); 11308 CASE_BTC_SLOT_STR(E2G); 11309 CASE_BTC_SLOT_STR(E5G); 11310 CASE_BTC_SLOT_STR(EBT); 11311 CASE_BTC_SLOT_STR(ENULL); 11312 CASE_BTC_SLOT_STR(WLK); 11313 CASE_BTC_SLOT_STR(W1FDD); 11314 CASE_BTC_SLOT_STR(B1FDD); 11315 default: 11316 return "unknown"; 11317 } 11318 } 11319 11320 static const char *id_to_evt(u32 id) 11321 { 11322 switch (id) { 11323 CASE_BTC_EVT_STR(TDMA_ENTRY); 11324 CASE_BTC_EVT_STR(WL_TMR); 11325 CASE_BTC_EVT_STR(B1_TMR); 11326 CASE_BTC_EVT_STR(B2_TMR); 11327 CASE_BTC_EVT_STR(B3_TMR); 11328 CASE_BTC_EVT_STR(B4_TMR); 11329 CASE_BTC_EVT_STR(W2B_TMR); 11330 CASE_BTC_EVT_STR(B2W_TMR); 11331 CASE_BTC_EVT_STR(BCN_EARLY); 11332 CASE_BTC_EVT_STR(A2DP_EMPTY); 11333 CASE_BTC_EVT_STR(LK_END); 11334 CASE_BTC_EVT_STR(RX_ISR); 11335 CASE_BTC_EVT_STR(RX_FC0); 11336 CASE_BTC_EVT_STR(RX_FC1); 11337 CASE_BTC_EVT_STR(BT_RELINK); 11338 CASE_BTC_EVT_STR(BT_RETRY); 11339 CASE_BTC_EVT_STR(E2G); 11340 CASE_BTC_EVT_STR(E5G); 11341 CASE_BTC_EVT_STR(EBT); 11342 CASE_BTC_EVT_STR(ENULL); 11343 CASE_BTC_EVT_STR(DRV_WLK); 11344 CASE_BTC_EVT_STR(BCN_OK); 11345 CASE_BTC_EVT_STR(BT_CHANGE); 11346 CASE_BTC_EVT_STR(EBT_EXTEND); 11347 CASE_BTC_EVT_STR(E2G_NULL1); 11348 CASE_BTC_EVT_STR(B1FDD_TMR); 11349 default: 11350 return "unknown"; 11351 } 11352 } 11353 11354 static const char *id_to_mode(u8 id) 11355 { 11356 switch (id) { 11357 CASE_BTC_INIT(NORMAL); 11358 CASE_BTC_INIT(WL); 11359 CASE_BTC_INIT(BT); 11360 CASE_BTC_INIT(WLOFF); 11361 default: 11362 return "unknown"; 11363 } 11364 } 11365 11366 static const char *id_to_ant(u32 id) 11367 { 11368 switch (id) { 11369 CASE_BTC_ANTPATH_STR(WPOWERON); 11370 CASE_BTC_ANTPATH_STR(WINIT); 11371 CASE_BTC_ANTPATH_STR(WONLY); 11372 CASE_BTC_ANTPATH_STR(WOFF); 11373 CASE_BTC_ANTPATH_STR(W2G); 11374 CASE_BTC_ANTPATH_STR(FDD); 11375 CASE_BTC_ANTPATH_STR(W25G); 11376 CASE_BTC_ANTPATH_STR(FREERUN); 11377 CASE_BTC_ANTPATH_STR(WRFK); 11378 CASE_BTC_ANTPATH_STR(WRFK2); 11379 CASE_BTC_ANTPATH_STR(PTA); 11380 CASE_BTC_ANTPATH_STR(MAX); 11381 default: 11382 return "unknown"; 11383 } 11384 } 11385 11386 static const char *id_to_h2c(u32 id) 11387 { 11388 switch (id) { 11389 CASE_BTC_H2CCMD(REPORT_EN); 11390 CASE_BTC_H2CCMD(SLOT_TABLE); 11391 CASE_BTC_H2CCMD(MREG_TABLE); 11392 CASE_BTC_H2CCMD(CX_POLICY); 11393 CASE_BTC_H2CCMD(GPIO_DBG); 11394 CASE_BTC_H2CCMD(DRV_INFO); 11395 CASE_BTC_H2CCMD(DRV_EVENT); 11396 CASE_BTC_H2CCMD(BT_WREG_ADDR); 11397 CASE_BTC_H2CCMD(BT_WREG_VAL); 11398 CASE_BTC_H2CCMD(BT_RREG_ADDR); 11399 CASE_BTC_H2CCMD(BT_WL_CH_INFO); 11400 CASE_BTC_H2CCMD(BT_INFO_REPORT); 11401 CASE_BTC_H2CCMD(BT_IGNORE_WLAN_ACT); 11402 CASE_BTC_H2CCMD(BT_TX_PWR); 11403 CASE_BTC_H2CCMD(BT_LNA_CONSTRAIN); 11404 CASE_BTC_H2CCMD(BT_QUERY_DEV_LIST); 11405 CASE_BTC_H2CCMD(BT_QUERY_DEV_INFO); 11406 CASE_BTC_H2CCMD(BT_PSD_REPORT); 11407 CASE_BTC_H2CCMD(H2C_TEST); 11408 CASE_BTC_H2CCMD(IOFLD_RF); 11409 CASE_BTC_H2CCMD(IOFLD_BB); 11410 CASE_BTC_H2CCMD(IOFLD_MAC); 11411 CASE_BTC_H2CCMD(IOFLD_SCBD); 11412 CASE_BTC_H2CCMD(H2C_MACRO); 11413 default: 11414 return "unknown"; 11415 } 11416 } 11417 11418 static 11419 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data, 11420 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 11421 { 11422 char *p = buf, *end = buf + bufsz; 11423 u8 cur_index; 11424 u8 i; 11425 11426 for (i = 0; i < len ; i++) { 11427 if ((i % seg_len) == 0) 11428 p += scnprintf(p, end - p, " %-15s : ", prefix); 11429 cur_index = (start_idx + i) % ring_len; 11430 if (i % 3 == 0) 11431 p += scnprintf(p, end - p, "-> %-20s", 11432 steps_to_str(*(data + cur_index))); 11433 else if (i % 3 == 1) 11434 p += scnprintf(p, end - p, "-> %-15s", 11435 steps_to_str(*(data + cur_index))); 11436 else 11437 p += scnprintf(p, end - p, "-> %-13s", 11438 steps_to_str(*(data + cur_index))); 11439 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 11440 p += scnprintf(p, end - p, "\n"); 11441 } 11442 11443 return p - buf; 11444 } 11445 11446 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11447 { 11448 struct rtw89_btc *btc = &rtwdev->btc; 11449 struct rtw89_btc_dm *dm = &btc->dm; 11450 char *p = buf, *end = buf + bufsz; 11451 u8 start_idx; 11452 u8 len; 11453 11454 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 11455 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 11456 11457 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len, 11458 6, start_idx, ARRAY_SIZE(dm->dm_step.step)); 11459 11460 return p - buf; 11461 } 11462 11463 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11464 { 11465 struct rtw89_btc *btc = &rtwdev->btc; 11466 struct rtw89_btc_dm *dm = &btc->dm; 11467 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 11468 struct rtw89_btc_bt_info *bt = &btc->cx.bt0; 11469 char *p = buf, *end = buf + bufsz; 11470 11471 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 11472 return 0; 11473 11474 p += scnprintf(p, end - p, 11475 "========== [Mechanism Status %s] ==========\n", 11476 (btc->manual_ctrl ? "(Manual)" : "(Auto)")); 11477 11478 p += scnprintf(p, end - p, 11479 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n", 11480 "[status]", 11481 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated", 11482 steps_to_str(dm->run_reason), 11483 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 11484 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)), 11485 id_to_mode(wl->coex_mode), 11486 dm->cnt_dm[BTC_DCNT_RUN]); 11487 11488 p += _show_dm_step(rtwdev, p, end - p); 11489 11490 p += scnprintf(p, end - p, 11491 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 11492 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt, 11493 dm->freerun, btc->btc_ctrl_lps, dm->wl_mimo_ps); 11494 11495 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n", 11496 dm->leak_ap, 11497 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 11498 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 11499 "" : "(Mismatch!!)")); 11500 11501 p += scnprintf(p, end - p, 11502 " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n", 11503 "[dm_rf_ctrl]", 11504 wl->rssi_level, dm->trx_para_level, 11505 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0], 11506 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1], 11507 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0], 11508 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1], 11509 dm->wl_lna2, dm->wl_stb_chg); 11510 11511 p += scnprintf(p, end - p, 11512 " %-15s : pre_agc:%d, btg_rx:%d\n", 11513 "[dm_bb_ctrl]", dm->wl_pre_agc, dm->wl_btg_rx); 11514 11515 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 11516 p += scnprintf(p, end - p, 11517 " %-15s : bt_en_state:0x%x, shadow[done:0x%x/ack:0x%x]\n", 11518 "[dm_bttrx_en]", dm->ost_info.bt_enable_state, 11519 dm->bttrx_en_done, dm->bttrx_en_ack); 11520 11521 p += scnprintf(p, end - p, 11522 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 11523 "[dm_ctrl]", dm->wl_tx_limit.enable, 11524 dm->wl_tx_limit.tx_time, 11525 dm->wl_tx_limit.tx_retry, btc->bt_req_len[RTW89_PHY_0], 11526 bt->scan_rx_low_pri); 11527 11528 return p - buf; 11529 } 11530 11531 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11532 { 11533 struct rtw89_btc *btc = &rtwdev->btc; 11534 const struct rtw89_btc_ver *ver = btc->ver; 11535 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11536 union rtw89_btc_fbtc_cysta_info *pcysta; 11537 char *p = buf, *end = buf + bufsz; 11538 u32 except_cnt, exception_map; 11539 11540 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 11541 if (ver->fcxcysta == 2) { 11542 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 11543 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 11544 exception_map = le32_to_cpu(pcysta->v2.exception); 11545 } else if (ver->fcxcysta == 3) { 11546 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 11547 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 11548 exception_map = le32_to_cpu(pcysta->v3.except_map); 11549 } else if (ver->fcxcysta == 4) { 11550 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 11551 except_cnt = pcysta->v4.except_cnt; 11552 exception_map = le32_to_cpu(pcysta->v4.except_map); 11553 } else if (ver->fcxcysta == 5) { 11554 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 11555 except_cnt = pcysta->v5.except_cnt; 11556 exception_map = le32_to_cpu(pcysta->v5.except_map); 11557 } else if (ver->fcxcysta == 7) { 11558 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 11559 except_cnt = pcysta->v7.except_cnt; 11560 exception_map = le32_to_cpu(pcysta->v7.except_map); 11561 } else if (ver->fcxcysta == 8) { 11562 pcysta->v8 = pfwinfo->rpt_fbtc_cysta.finfo.v8; 11563 except_cnt = pcysta->v8.except_cnt; 11564 exception_map = le32_to_cpu(pcysta->v8.except_map); 11565 } else { 11566 return 0; 11567 } 11568 11569 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 11570 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 11571 return 0; 11572 11573 p += scnprintf(p, end - p, " %-15s : ", "[error]"); 11574 11575 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 11576 p += scnprintf(p, end - p, 11577 "overflow-cnt: %d, ", 11578 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 11579 } 11580 11581 if (pfwinfo->len_mismch) { 11582 p += scnprintf(p, end - p, 11583 "len-mismatch: 0x%x, ", 11584 pfwinfo->len_mismch); 11585 } 11586 11587 if (pfwinfo->fver_mismch) { 11588 p += scnprintf(p, end - p, 11589 "fver-mismatch: 0x%x, ", 11590 pfwinfo->fver_mismch); 11591 } 11592 11593 /* cycle statistics exceptions */ 11594 if (exception_map || except_cnt) { 11595 p += scnprintf(p, end - p, 11596 "exception-type: 0x%x, exception-cnt = %d", 11597 exception_map, except_cnt); 11598 } 11599 p += scnprintf(p, end - p, "\n"); 11600 11601 return p - buf; 11602 } 11603 11604 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11605 { 11606 struct rtw89_btc *btc = &rtwdev->btc; 11607 const struct rtw89_btc_ver *ver = btc->ver; 11608 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11609 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11610 struct rtw89_btc_fbtc_tdma *t = NULL; 11611 char *p = buf, *end = buf + bufsz; 11612 11613 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 11614 if (!pcinfo->valid) 11615 return 0; 11616 11617 if (ver->fcxtdma == 1) 11618 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 11619 else 11620 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 11621 11622 p += scnprintf(p, end - p, 11623 " %-15s : ", "[tdma_policy]"); 11624 p += scnprintf(p, end - p, 11625 "type:%d, rx_flow_ctrl:%d, txflctrl:%d, ", 11626 (u32)t->type, 11627 t->rxflctrl, t->txflctrl); 11628 11629 p += scnprintf(p, end - p, 11630 "bind:%d, leak_n:%d, ext_ctrl:%d, ", 11631 t->bind, t->leak_n, t->ext_ctrl); 11632 11633 p += scnprintf(p, end - p, 11634 "policy_type:%d\n", 11635 (u32)btc->policy_type); 11636 11637 return p - buf; 11638 } 11639 11640 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11641 { 11642 struct rtw89_btc *btc = &rtwdev->btc; 11643 const struct rtw89_btc_ver *ver = btc->ver; 11644 struct rtw89_btc_dm *dm = &btc->dm; 11645 char *p = buf, *end = buf + bufsz; 11646 u16 dur, cxtype; 11647 u32 tbl; 11648 u8 i = 0; 11649 11650 for (i = 0; i < CXST_MAX; i++) { 11651 if (ver->fcxslots == 1) { 11652 dur = le16_to_cpu(dm->slot_now.v1[i].dur); 11653 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl); 11654 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype); 11655 } else if (ver->fcxslots == 2 || ver->fcxslots == 7) { 11656 dur = le16_to_cpu(dm->slot_now.v7[i].dur); 11657 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl); 11658 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype); 11659 } else { 11660 return 0; 11661 } 11662 11663 if (i % 5 == 0) 11664 p += scnprintf(p, end - p, 11665 " %-15s : %5s[%03d/0x%x/%d]", 11666 "[slot_list]", 11667 id_to_slot((u32)i), 11668 dur, tbl, cxtype); 11669 else 11670 p += scnprintf(p, end - p, 11671 ", %5s[%03d/0x%x/%d]", 11672 id_to_slot((u32)i), 11673 dur, tbl, cxtype); 11674 11675 if (i % 5 == 4) 11676 p += scnprintf(p, end - p, "\n"); 11677 } 11678 11679 return p - buf; 11680 } 11681 11682 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11683 { 11684 struct rtw89_btc *btc = &rtwdev->btc; 11685 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11686 struct rtw89_btc_dm *dm = &btc->dm; 11687 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11688 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11689 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 11690 union rtw89_btc_fbtc_rxflct r; 11691 u16 cycle, c_begin, c_end, store_index; 11692 char *p = buf, *end = buf + bufsz; 11693 u8 i, cnt = 0, slot_pair; 11694 11695 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11696 if (!pcinfo->valid) 11697 return 0; 11698 11699 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 11700 p += scnprintf(p, end - p, 11701 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11702 "[cycle_cnt]", 11703 le16_to_cpu(pcysta_le32->cycles), 11704 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 11705 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 11706 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 11707 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 11708 11709 for (i = 0; i < CXST_MAX; i++) { 11710 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 11711 continue; 11712 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i), 11713 le32_to_cpu(pcysta_le32->slot_cnt[i])); 11714 } 11715 11716 if (dm->tdma_now.rxflctrl) { 11717 p += scnprintf(p, end - p, ", leak_rx:%d", 11718 le32_to_cpu(pcysta_le32->leakrx_cnt)); 11719 } 11720 11721 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 11722 p += scnprintf(p, end - p, ", collision:%d", 11723 le32_to_cpu(pcysta_le32->collision_cnt)); 11724 } 11725 11726 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 11727 p += scnprintf(p, end - p, ", skip:%d", 11728 le32_to_cpu(pcysta_le32->skip_cnt)); 11729 } 11730 p += scnprintf(p, end - p, "\n"); 11731 11732 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11733 "[cycle_time]", 11734 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 11735 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 11736 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 11737 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 11738 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 11739 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 11740 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 11741 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 11742 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 11743 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n", 11744 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 11745 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 11746 11747 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 11748 goto out; 11749 11750 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11751 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11752 11753 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 11754 c_begin = 1; 11755 else 11756 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 11757 11758 c_end = le16_to_cpu(pcysta_le32->cycles); 11759 11760 for (cycle = c_begin; cycle <= c_end; cycle++) { 11761 cnt++; 11762 store_index = ((cycle - 1) % slot_pair) * 2; 11763 11764 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 11765 p += scnprintf(p, end - p, 11766 " %-15s : ->b%02d->w%02d", 11767 "[cycle_step]", 11768 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 11769 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 11770 else 11771 p += scnprintf(p, end - p, 11772 "->b%02d->w%02d", 11773 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 11774 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 11775 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 11776 p += scnprintf(p, end - p, "\n"); 11777 } 11778 11779 if (a2dp->exist) { 11780 p += scnprintf(p, end - p, 11781 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11782 "[a2dp_t_sta]", 11783 le16_to_cpu(pcysta_le32->a2dpept), 11784 le16_to_cpu(pcysta_le32->a2dpeptto)); 11785 11786 p += scnprintf(p, end - p, 11787 ", avg_t:%d, max_t:%d", 11788 le16_to_cpu(pcysta_le32->tavg_a2dpept), 11789 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 11790 r.val = dm->tdma_now.rxflctrl; 11791 11792 if (r.type && r.tgln_n) { 11793 p += scnprintf(p, end - p, 11794 ", cycle[PSTDMA:%d/TDMA:%d], ", 11795 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 11796 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 11797 11798 p += scnprintf(p, end - p, 11799 "avg_t[PSTDMA:%d/TDMA:%d], ", 11800 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 11801 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 11802 11803 p += scnprintf(p, end - p, 11804 "max_t[PSTDMA:%d/TDMA:%d]", 11805 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 11806 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 11807 } 11808 p += scnprintf(p, end - p, "\n"); 11809 } 11810 11811 out: 11812 return p - buf; 11813 } 11814 11815 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11816 { 11817 struct rtw89_btc *btc = &rtwdev->btc; 11818 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11819 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11820 struct rtw89_btc_dm *dm = &btc->dm; 11821 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 11822 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 11823 struct rtw89_btc_rpt_cmn_info *pcinfo; 11824 u8 i, cnt = 0, slot_pair, divide_cnt; 11825 u16 cycle, c_begin, c_end, store_index; 11826 char *p = buf, *end = buf + bufsz; 11827 11828 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11829 if (!pcinfo->valid) 11830 return 0; 11831 11832 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 11833 p += scnprintf(p, end - p, 11834 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11835 "[cycle_cnt]", 11836 le16_to_cpu(pcysta->cycles), 11837 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11838 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11839 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11840 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11841 11842 for (i = 0; i < CXST_MAX; i++) { 11843 if (!le32_to_cpu(pcysta->slot_cnt[i])) 11844 continue; 11845 11846 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 11847 le32_to_cpu(pcysta->slot_cnt[i])); 11848 } 11849 11850 if (dm->tdma_now.rxflctrl) 11851 p += scnprintf(p, end - p, ", leak_rx:%d", 11852 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11853 11854 if (le32_to_cpu(pcysta->collision_cnt)) 11855 p += scnprintf(p, end - p, ", collision:%d", 11856 le32_to_cpu(pcysta->collision_cnt)); 11857 11858 if (le32_to_cpu(pcysta->skip_cnt)) 11859 p += scnprintf(p, end - p, ", skip:%d", 11860 le32_to_cpu(pcysta->skip_cnt)); 11861 11862 p += scnprintf(p, end - p, "\n"); 11863 11864 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 11865 "[cycle_time]", 11866 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 11867 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 11868 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 11869 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 11870 p += scnprintf(p, end - p, 11871 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 11872 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 11873 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 11874 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 11875 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 11876 p += scnprintf(p, end - p, 11877 ", maxdiff_t[wl:%d/bt:%d]\n", 11878 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 11879 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 11880 11881 cycle = le16_to_cpu(pcysta->cycles); 11882 if (cycle <= 1) 11883 goto out; 11884 11885 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 11886 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 11887 11888 if (cycle <= slot_pair) 11889 c_begin = 1; 11890 else 11891 c_begin = cycle - slot_pair + 1; 11892 11893 c_end = cycle; 11894 11895 if (a2dp->exist) 11896 divide_cnt = 3; 11897 else 11898 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 11899 11900 for (cycle = c_begin; cycle <= c_end; cycle++) { 11901 cnt++; 11902 store_index = ((cycle - 1) % slot_pair) * 2; 11903 11904 if (cnt % divide_cnt == 1) 11905 p += scnprintf(p, end - p, " %-15s : ", 11906 "[cycle_step]"); 11907 11908 p += scnprintf(p, end - p, "->b%02d", 11909 le16_to_cpu(pcysta->slot_step_time[store_index])); 11910 if (a2dp->exist) { 11911 a2dp_trx = &pcysta->a2dp_trx[store_index]; 11912 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11913 a2dp_trx->empty_cnt, 11914 a2dp_trx->retry_cnt, 11915 a2dp_trx->tx_rate ? 3 : 2, 11916 a2dp_trx->tx_cnt, 11917 a2dp_trx->ack_cnt, 11918 a2dp_trx->nack_cnt); 11919 } 11920 p += scnprintf(p, end - p, "->w%02d", 11921 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 11922 if (a2dp->exist) { 11923 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 11924 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 11925 a2dp_trx->empty_cnt, 11926 a2dp_trx->retry_cnt, 11927 a2dp_trx->tx_rate ? 3 : 2, 11928 a2dp_trx->tx_cnt, 11929 a2dp_trx->ack_cnt, 11930 a2dp_trx->nack_cnt); 11931 } 11932 if (cnt % divide_cnt == 0 || cnt == c_end) 11933 p += scnprintf(p, end - p, "\n"); 11934 } 11935 11936 if (a2dp->exist) { 11937 p += scnprintf(p, end - p, 11938 " %-15s : a2dp_ept:%d, a2dp_late:%d", 11939 "[a2dp_t_sta]", 11940 le16_to_cpu(pcysta->a2dp_ept.cnt), 11941 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 11942 11943 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 11944 le16_to_cpu(pcysta->a2dp_ept.tavg), 11945 le16_to_cpu(pcysta->a2dp_ept.tmax)); 11946 } 11947 11948 out: 11949 return p - buf; 11950 } 11951 11952 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11953 { 11954 struct rtw89_btc *btc = &rtwdev->btc; 11955 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 11956 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11957 struct rtw89_btc_dm *dm = &btc->dm; 11958 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 11959 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 11960 struct rtw89_btc_rpt_cmn_info *pcinfo; 11961 u8 i, cnt = 0, slot_pair, divide_cnt; 11962 u16 cycle, c_begin, c_end, store_index; 11963 char *p = buf, *end = buf + bufsz; 11964 11965 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 11966 if (!pcinfo->valid) 11967 return 0; 11968 11969 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 11970 p += scnprintf(p, end - p, 11971 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 11972 "[cycle_cnt]", 11973 le16_to_cpu(pcysta->cycles), 11974 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 11975 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 11976 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 11977 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 11978 11979 for (i = 0; i < CXST_MAX; i++) { 11980 if (!le16_to_cpu(pcysta->slot_cnt[i])) 11981 continue; 11982 11983 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 11984 le16_to_cpu(pcysta->slot_cnt[i])); 11985 } 11986 11987 if (dm->tdma_now.rxflctrl) 11988 p += scnprintf(p, end - p, ", leak_rx:%d", 11989 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 11990 11991 if (pcysta->collision_cnt) 11992 p += scnprintf(p, end - p, ", collision:%d", 11993 pcysta->collision_cnt); 11994 11995 if (le16_to_cpu(pcysta->skip_cnt)) 11996 p += scnprintf(p, end - p, ", skip:%d", 11997 le16_to_cpu(pcysta->skip_cnt)); 11998 11999 p += scnprintf(p, end - p, "\n"); 12000 12001 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 12002 "[cycle_time]", 12003 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 12004 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 12005 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 12006 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 12007 p += scnprintf(p, end - p, 12008 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 12009 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 12010 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 12011 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 12012 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 12013 p += scnprintf(p, end - p, 12014 ", maxdiff_t[wl:%d/bt:%d]\n", 12015 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 12016 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 12017 12018 cycle = le16_to_cpu(pcysta->cycles); 12019 if (cycle <= 1) 12020 goto out; 12021 12022 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 12023 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 12024 12025 if (cycle <= slot_pair) 12026 c_begin = 1; 12027 else 12028 c_begin = cycle - slot_pair + 1; 12029 12030 c_end = cycle; 12031 12032 if (a2dp->exist) 12033 divide_cnt = 3; 12034 else 12035 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 12036 12037 for (cycle = c_begin; cycle <= c_end; cycle++) { 12038 cnt++; 12039 store_index = ((cycle - 1) % slot_pair) * 2; 12040 12041 if (cnt % divide_cnt == 1) 12042 p += scnprintf(p, end - p, " %-15s : ", 12043 "[cycle_step]"); 12044 12045 p += scnprintf(p, end - p, "->b%02d", 12046 le16_to_cpu(pcysta->slot_step_time[store_index])); 12047 if (a2dp->exist) { 12048 a2dp_trx = &pcysta->a2dp_trx[store_index]; 12049 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12050 a2dp_trx->empty_cnt, 12051 a2dp_trx->retry_cnt, 12052 a2dp_trx->tx_rate ? 3 : 2, 12053 a2dp_trx->tx_cnt, 12054 a2dp_trx->ack_cnt, 12055 a2dp_trx->nack_cnt); 12056 } 12057 p += scnprintf(p, end - p, "->w%02d", 12058 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 12059 if (a2dp->exist) { 12060 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 12061 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12062 a2dp_trx->empty_cnt, 12063 a2dp_trx->retry_cnt, 12064 a2dp_trx->tx_rate ? 3 : 2, 12065 a2dp_trx->tx_cnt, 12066 a2dp_trx->ack_cnt, 12067 a2dp_trx->nack_cnt); 12068 } 12069 if (cnt % divide_cnt == 0 || cnt == c_end) 12070 p += scnprintf(p, end - p, "\n"); 12071 } 12072 12073 if (a2dp->exist) { 12074 p += scnprintf(p, end - p, 12075 " %-15s : a2dp_ept:%d, a2dp_late:%d", 12076 "[a2dp_t_sta]", 12077 le16_to_cpu(pcysta->a2dp_ept.cnt), 12078 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 12079 12080 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 12081 le16_to_cpu(pcysta->a2dp_ept.tavg), 12082 le16_to_cpu(pcysta->a2dp_ept.tmax)); 12083 } 12084 12085 out: 12086 return p - buf; 12087 } 12088 12089 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12090 { 12091 struct rtw89_btc *btc = &rtwdev->btc; 12092 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 12093 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12094 struct rtw89_btc_dm *dm = &btc->dm; 12095 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 12096 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 12097 struct rtw89_btc_rpt_cmn_info *pcinfo; 12098 u8 i, cnt = 0, slot_pair, divide_cnt; 12099 u16 cycle, c_begin, c_end, store_index; 12100 char *p = buf, *end = buf + bufsz; 12101 12102 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 12103 if (!pcinfo->valid) 12104 return 0; 12105 12106 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 12107 p += scnprintf(p, end - p, 12108 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 12109 "[cycle_cnt]", 12110 le16_to_cpu(pcysta->cycles), 12111 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 12112 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 12113 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 12114 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 12115 12116 for (i = 0; i < CXST_MAX; i++) { 12117 if (!le16_to_cpu(pcysta->slot_cnt[i])) 12118 continue; 12119 12120 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 12121 le16_to_cpu(pcysta->slot_cnt[i])); 12122 } 12123 12124 if (dm->tdma_now.rxflctrl) 12125 p += scnprintf(p, end - p, ", leak_rx:%d", 12126 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 12127 12128 if (pcysta->collision_cnt) 12129 p += scnprintf(p, end - p, ", collision:%d", 12130 pcysta->collision_cnt); 12131 12132 if (le16_to_cpu(pcysta->skip_cnt)) 12133 p += scnprintf(p, end - p, ", skip:%d", 12134 le16_to_cpu(pcysta->skip_cnt)); 12135 12136 p += scnprintf(p, end - p, "\n"); 12137 12138 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 12139 "[cycle_time]", 12140 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 12141 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 12142 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 12143 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 12144 p += scnprintf(p, end - p, 12145 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 12146 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 12147 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 12148 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 12149 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 12150 12151 cycle = le16_to_cpu(pcysta->cycles); 12152 if (cycle <= 1) 12153 goto out; 12154 12155 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 12156 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 12157 12158 if (cycle <= slot_pair) 12159 c_begin = 1; 12160 else 12161 c_begin = cycle - slot_pair + 1; 12162 12163 c_end = cycle; 12164 12165 if (a2dp->exist) 12166 divide_cnt = 3; 12167 else 12168 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 12169 12170 if (c_begin > c_end) 12171 goto out; 12172 12173 for (cycle = c_begin; cycle <= c_end; cycle++) { 12174 cnt++; 12175 store_index = ((cycle - 1) % slot_pair) * 2; 12176 12177 if (cnt % divide_cnt == 1) 12178 p += scnprintf(p, end - p, " %-15s : ", 12179 "[cycle_step]"); 12180 12181 p += scnprintf(p, end - p, "->b%02d", 12182 le16_to_cpu(pcysta->slot_step_time[store_index])); 12183 if (a2dp->exist) { 12184 a2dp_trx = &pcysta->a2dp_trx[store_index]; 12185 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12186 a2dp_trx->empty_cnt, 12187 a2dp_trx->retry_cnt, 12188 a2dp_trx->tx_rate ? 3 : 2, 12189 a2dp_trx->tx_cnt, 12190 a2dp_trx->ack_cnt, 12191 a2dp_trx->nack_cnt); 12192 } 12193 p += scnprintf(p, end - p, "->w%02d", 12194 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 12195 if (a2dp->exist) { 12196 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 12197 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12198 a2dp_trx->empty_cnt, 12199 a2dp_trx->retry_cnt, 12200 a2dp_trx->tx_rate ? 3 : 2, 12201 a2dp_trx->tx_cnt, 12202 a2dp_trx->ack_cnt, 12203 a2dp_trx->nack_cnt); 12204 } 12205 if (cnt % divide_cnt == 0 || cnt == c_end) 12206 p += scnprintf(p, end - p, "\n"); 12207 } 12208 12209 if (a2dp->exist) { 12210 p += scnprintf(p, end - p, 12211 " %-15s : a2dp_ept:%d, a2dp_late:%d", 12212 "[a2dp_t_sta]", 12213 le16_to_cpu(pcysta->a2dp_ept.cnt), 12214 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 12215 12216 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 12217 le16_to_cpu(pcysta->a2dp_ept.tavg), 12218 le16_to_cpu(pcysta->a2dp_ept.tmax)); 12219 } 12220 12221 out: 12222 return p - buf; 12223 } 12224 12225 static int _show_fbtc_cysta_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12226 { 12227 struct rtw89_btc *btc = &rtwdev->btc; 12228 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc; 12229 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12230 struct rtw89_btc_dm *dm = &btc->dm; 12231 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 12232 struct rtw89_btc_fbtc_cysta_v105 *pcysta; 12233 struct rtw89_btc_rpt_cmn_info *pcinfo; 12234 u8 i, cnt = 0, slot_pair, divide_cnt; 12235 u16 cycle, c_begin, c_end, store_index; 12236 char *p = buf, *end = buf + bufsz; 12237 12238 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 12239 if (!pcinfo->valid) 12240 return 0; 12241 12242 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v105; 12243 p += scnprintf(p, end - p, 12244 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 12245 "[cycle_cnt]", 12246 le16_to_cpu(pcysta->cycles), 12247 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 12248 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 12249 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 12250 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 12251 12252 for (i = 0; i < CXST_MAX; i++) { 12253 if (!le16_to_cpu(pcysta->slot_cnt[i])) 12254 continue; 12255 12256 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 12257 le16_to_cpu(pcysta->slot_cnt[i])); 12258 } 12259 12260 if (dm->tdma_now.rxflctrl) 12261 p += scnprintf(p, end - p, ", leak_rx:%d", 12262 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 12263 12264 if (pcysta->collision_cnt) 12265 p += scnprintf(p, end - p, ", collision:%d", 12266 pcysta->collision_cnt); 12267 12268 if (le16_to_cpu(pcysta->skip_cnt)) 12269 p += scnprintf(p, end - p, ", skip:%d", 12270 le16_to_cpu(pcysta->skip_cnt)); 12271 12272 p += scnprintf(p, end - p, "\n"); 12273 12274 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 12275 "[cycle_time]", 12276 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 12277 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 12278 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 12279 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 12280 p += scnprintf(p, end - p, 12281 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 12282 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 12283 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 12284 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 12285 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 12286 12287 cycle = le16_to_cpu(pcysta->cycles); 12288 if (cycle <= 1) 12289 goto out; 12290 12291 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 12292 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 12293 12294 if (cycle <= slot_pair) 12295 c_begin = 1; 12296 else 12297 c_begin = cycle - slot_pair + 1; 12298 12299 c_end = cycle; 12300 12301 if (a2dp->exist) 12302 divide_cnt = 3; 12303 else 12304 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 12305 12306 if (c_begin > c_end) 12307 goto out; 12308 12309 for (cycle = c_begin; cycle <= c_end; cycle++) { 12310 cnt++; 12311 store_index = ((cycle - 1) % slot_pair) * 2; 12312 12313 if (cnt % divide_cnt == 1) 12314 p += scnprintf(p, end - p, " %-15s : ", 12315 "[cycle_step]"); 12316 12317 p += scnprintf(p, end - p, "->b%02d", 12318 le16_to_cpu(pcysta->slot_step_time[store_index])); 12319 if (a2dp->exist) { 12320 a2dp_trx = &pcysta->a2dp_trx[store_index]; 12321 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12322 a2dp_trx->empty_cnt, 12323 a2dp_trx->retry_cnt, 12324 a2dp_trx->tx_rate ? 3 : 2, 12325 a2dp_trx->tx_cnt, 12326 a2dp_trx->ack_cnt, 12327 a2dp_trx->nack_cnt); 12328 } 12329 p += scnprintf(p, end - p, "->w%02d", 12330 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 12331 if (a2dp->exist) { 12332 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 12333 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 12334 a2dp_trx->empty_cnt, 12335 a2dp_trx->retry_cnt, 12336 a2dp_trx->tx_rate ? 3 : 2, 12337 a2dp_trx->tx_cnt, 12338 a2dp_trx->ack_cnt, 12339 a2dp_trx->nack_cnt); 12340 } 12341 if (cnt % divide_cnt == 0 || cnt == c_end) 12342 p += scnprintf(p, end - p, "\n"); 12343 } 12344 12345 if (a2dp->exist) { 12346 p += scnprintf(p, end - p, 12347 " %-15s : a2dp_ept:%d, a2dp_late:%d", 12348 "[a2dp_t_sta]", 12349 le16_to_cpu(pcysta->a2dp_ept.cnt), 12350 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 12351 12352 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n", 12353 le16_to_cpu(pcysta->a2dp_ept.tavg), 12354 le16_to_cpu(pcysta->a2dp_ept.tmax)); 12355 } 12356 12357 out: 12358 return p - buf; 12359 } 12360 12361 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12362 { 12363 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 12364 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 12365 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 12366 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL; 12367 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 12368 struct rtw89_btc_rpt_cmn_info *pcinfo; 12369 char *p = buf, *end = buf + bufsz; 12370 u16 cycle, c_begin, c_end, s_id; 12371 u8 i, cnt = 0, divide_cnt; 12372 u8 slot_pair; 12373 12374 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 12375 if (!pcinfo->valid) 12376 return 0; 12377 12378 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 12379 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]", 12380 le16_to_cpu(pcysta->cycles)); 12381 12382 for (i = 0; i < CXST_MAX; i++) { 12383 if (!le16_to_cpu(pcysta->slot_cnt[i])) 12384 continue; 12385 p += scnprintf(p, end - p, ", %s:%d", 12386 id_to_slot(i), 12387 le16_to_cpu(pcysta->slot_cnt[i])); 12388 } 12389 12390 if (dm->tdma_now.rxflctrl) 12391 p += scnprintf(p, end - p, ", leak_rx:%d", 12392 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 12393 12394 if (pcysta->collision_cnt) 12395 p += scnprintf(p, end - p, ", collision:%d", 12396 pcysta->collision_cnt); 12397 12398 if (pcysta->skip_cnt) 12399 p += scnprintf(p, end - p, ", skip:%d", 12400 le16_to_cpu(pcysta->skip_cnt)); 12401 12402 p += scnprintf(p, end - p, 12403 "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 12404 "[cycle_stat]", 12405 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 12406 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 12407 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 12408 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 12409 p += scnprintf(p, end - p, 12410 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]", 12411 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 12412 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 12413 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD], 12414 le16_to_cpu(pcysta->leak_slot.tamx) / 1000, 12415 le16_to_cpu(pcysta->leak_slot.tamx) % 1000); 12416 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]", 12417 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 12418 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 12419 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 12420 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 12421 12422 if (a2dp->exist) { 12423 p += scnprintf(p, end - p, 12424 "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", 12425 "[a2dp_stat]", 12426 le16_to_cpu(pcysta->a2dp_ept.cnt), 12427 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), 12428 a2dp->no_empty_streak_2s, 12429 a2dp->no_empty_streak_max); 12430 12431 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 12432 le16_to_cpu(pcysta->a2dp_ept.tavg), 12433 le16_to_cpu(pcysta->a2dp_ept.tmax)); 12434 } 12435 12436 if (le16_to_cpu(pcysta->cycles) <= 1) 12437 goto out; 12438 12439 /* 1 cycle = 1 wl-slot + 1 bt-slot */ 12440 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 12441 12442 if (le16_to_cpu(pcysta->cycles) <= slot_pair) 12443 c_begin = 1; 12444 else 12445 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1; 12446 12447 c_end = le16_to_cpu(pcysta->cycles); 12448 12449 if (a2dp->exist) 12450 divide_cnt = 2; 12451 else 12452 divide_cnt = 6; 12453 12454 if (c_begin > c_end) 12455 goto out; 12456 12457 for (cycle = c_begin; cycle <= c_end; cycle++) { 12458 cnt++; 12459 s_id = ((cycle - 1) % slot_pair) * 2; 12460 12461 if (cnt % divide_cnt == 1) { 12462 if (a2dp->exist) 12463 p += scnprintf(p, end - p, "\n %-15s : ", 12464 "[slotT_wermtan]"); 12465 else 12466 p += scnprintf(p, end - p, "\n %-15s : ", 12467 "[slotT_rxerr]"); 12468 } 12469 12470 p += scnprintf(p, end - p, "->b%d", 12471 le16_to_cpu(pcysta->slot_step_time[s_id])); 12472 12473 if (a2dp->exist) 12474 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 12475 pcysta->wl_rx_err_ratio[s_id], 12476 pcysta->a2dp_trx[s_id].empty_cnt, 12477 pcysta->a2dp_trx[s_id].retry_cnt, 12478 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2), 12479 pcysta->a2dp_trx[s_id].tx_cnt, 12480 pcysta->a2dp_trx[s_id].ack_cnt, 12481 pcysta->a2dp_trx[s_id].nack_cnt); 12482 else 12483 p += scnprintf(p, end - p, "(%d)", 12484 pcysta->wl_rx_err_ratio[s_id]); 12485 12486 p += scnprintf(p, end - p, "->w%d", 12487 le16_to_cpu(pcysta->slot_step_time[s_id + 1])); 12488 12489 if (a2dp->exist) 12490 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 12491 pcysta->wl_rx_err_ratio[s_id + 1], 12492 pcysta->a2dp_trx[s_id + 1].empty_cnt, 12493 pcysta->a2dp_trx[s_id + 1].retry_cnt, 12494 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2), 12495 pcysta->a2dp_trx[s_id + 1].tx_cnt, 12496 pcysta->a2dp_trx[s_id + 1].ack_cnt, 12497 pcysta->a2dp_trx[s_id + 1].nack_cnt); 12498 else 12499 p += scnprintf(p, end - p, "(%d)", 12500 pcysta->wl_rx_err_ratio[s_id + 1]); 12501 } 12502 12503 out: 12504 return p - buf; 12505 } 12506 12507 static int _show_fbtc_cysta_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12508 { 12509 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0; 12510 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 12511 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 12512 struct rtw89_btc_fbtc_cysta_v8 *pcysta = NULL; 12513 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 12514 struct rtw89_btc_rpt_cmn_info *pcinfo; 12515 char *p = buf, *end = buf + bufsz; 12516 u16 cycle, c_begin, c_end, s_id; 12517 u8 i, cnt = 0, divide_cnt; 12518 u8 slot_pair; 12519 12520 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 12521 if (!pcinfo->valid) 12522 return 0; 12523 12524 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v8; 12525 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]", 12526 le16_to_cpu(pcysta->cycles)); 12527 12528 for (i = 0; i < CXST_MAX; i++) { 12529 if (!le16_to_cpu(pcysta->slot_cnt[i])) 12530 continue; 12531 p += scnprintf(p, end - p, ", %s:%d", 12532 id_to_slot(i), 12533 le16_to_cpu(pcysta->slot_cnt[i])); 12534 } 12535 12536 if (dm->tdma_now.rxflctrl) 12537 p += scnprintf(p, end - p, ", leak_rx:%d", 12538 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 12539 12540 if (pcysta->collision_cnt) 12541 p += scnprintf(p, end - p, ", collision:%d", 12542 pcysta->collision_cnt); 12543 12544 if (pcysta->skip_cnt) 12545 p += scnprintf(p, end - p, ", skip:%d", 12546 le16_to_cpu(pcysta->skip_cnt)); 12547 12548 p += scnprintf(p, end - p, 12549 "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 12550 "[cycle_stat]", 12551 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 12552 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 12553 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 12554 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 12555 p += scnprintf(p, end - p, 12556 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]", 12557 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 12558 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 12559 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD], 12560 le16_to_cpu(pcysta->leak_slot.tamx) / 1000, 12561 le16_to_cpu(pcysta->leak_slot.tamx) % 1000); 12562 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]", 12563 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 12564 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 12565 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 12566 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 12567 12568 if (a2dp->exist) { 12569 p += scnprintf(p, end - p, 12570 "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", 12571 "[a2dp_stat]", 12572 le16_to_cpu(pcysta->a2dp_ept.cnt), 12573 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), 12574 a2dp->no_empty_streak_2s, 12575 a2dp->no_empty_streak_max); 12576 12577 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 12578 le16_to_cpu(pcysta->a2dp_ept.tavg), 12579 le16_to_cpu(pcysta->a2dp_ept.tmax)); 12580 } 12581 12582 if (le16_to_cpu(pcysta->cycles) <= 1) 12583 goto out; 12584 12585 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 12586 12587 if (le16_to_cpu(pcysta->cycles) <= slot_pair) 12588 c_begin = 1; 12589 else 12590 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1; 12591 12592 c_end = le16_to_cpu(pcysta->cycles); 12593 12594 if (a2dp->exist) 12595 divide_cnt = 2; 12596 else 12597 divide_cnt = 6; 12598 12599 if (c_begin > c_end) 12600 goto out; 12601 12602 for (cycle = c_begin; cycle <= c_end; cycle++) { 12603 cnt++; 12604 s_id = ((cycle - 1) % slot_pair) * 2; 12605 12606 if (cnt % divide_cnt == 1) { 12607 if (a2dp->exist) 12608 p += scnprintf(p, end - p, "\n %-15s : ", 12609 "[slotT_wermtan]"); 12610 else 12611 p += scnprintf(p, end - p, "\n %-15s : ", 12612 "[slotT_rxerr]"); 12613 } 12614 12615 p += scnprintf(p, end - p, "->b%d", 12616 le16_to_cpu(pcysta->slot_step_time[s_id])); 12617 12618 if (a2dp->exist) 12619 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 12620 pcysta->wl_rx_err_ratio[s_id], 12621 pcysta->a2dp_trx[s_id].empty_cnt, 12622 pcysta->a2dp_trx[s_id].retry_cnt, 12623 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2), 12624 pcysta->a2dp_trx[s_id].tx_cnt, 12625 pcysta->a2dp_trx[s_id].ack_cnt, 12626 pcysta->a2dp_trx[s_id].nack_cnt); 12627 else 12628 p += scnprintf(p, end - p, "(%d)", 12629 pcysta->wl_rx_err_ratio[s_id]); 12630 12631 p += scnprintf(p, end - p, "->w%d", 12632 le16_to_cpu(pcysta->slot_step_time[s_id + 1])); 12633 12634 if (a2dp->exist) 12635 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 12636 pcysta->wl_rx_err_ratio[s_id + 1], 12637 pcysta->a2dp_trx[s_id + 1].empty_cnt, 12638 pcysta->a2dp_trx[s_id + 1].retry_cnt, 12639 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2), 12640 pcysta->a2dp_trx[s_id + 1].tx_cnt, 12641 pcysta->a2dp_trx[s_id + 1].ack_cnt, 12642 pcysta->a2dp_trx[s_id + 1].nack_cnt); 12643 else 12644 p += scnprintf(p, end - p, "(%d)", 12645 pcysta->wl_rx_err_ratio[s_id + 1]); 12646 } 12647 12648 out: 12649 return p - buf; 12650 } 12651 12652 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12653 { 12654 struct rtw89_btc *btc = &rtwdev->btc; 12655 const struct rtw89_btc_ver *ver = btc->ver; 12656 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12657 struct rtw89_btc_rpt_cmn_info *pcinfo; 12658 union rtw89_btc_fbtc_cynullsta_info *ns; 12659 char *p = buf, *end = buf + bufsz; 12660 u8 i = 0; 12661 12662 if (!btc->dm.tdma_now.rxflctrl) 12663 return 0; 12664 12665 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 12666 if (!pcinfo->valid) 12667 return 0; 12668 12669 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 12670 if (ver->fcxnullsta == 1) { 12671 for (i = 0; i < 2; i++) { 12672 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 12673 p += scnprintf(p, end - p, "null-%d", i); 12674 p += scnprintf(p, end - p, "[ok:%d/", 12675 le32_to_cpu(ns->v1.result[i][1])); 12676 p += scnprintf(p, end - p, "fail:%d/", 12677 le32_to_cpu(ns->v1.result[i][0])); 12678 p += scnprintf(p, end - p, "on_time:%d/", 12679 le32_to_cpu(ns->v1.result[i][2])); 12680 p += scnprintf(p, end - p, "retry:%d/", 12681 le32_to_cpu(ns->v1.result[i][3])); 12682 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 12683 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 12684 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 12685 p += scnprintf(p, end - p, "max_t:%d.%03d]", 12686 le32_to_cpu(ns->v1.max_t[i]) / 1000, 12687 le32_to_cpu(ns->v1.max_t[i]) % 1000); 12688 } 12689 } else if (ver->fcxnullsta == 7) { 12690 for (i = 0; i < 2; i++) { 12691 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 12692 p += scnprintf(p, end - p, "null-%d", i); 12693 p += scnprintf(p, end - p, "[Tx:%d/", 12694 le32_to_cpu(ns->v7.result[i][4])); 12695 p += scnprintf(p, end - p, "[ok:%d/", 12696 le32_to_cpu(ns->v7.result[i][1])); 12697 p += scnprintf(p, end - p, "fail:%d/", 12698 le32_to_cpu(ns->v7.result[i][0])); 12699 p += scnprintf(p, end - p, "on_time:%d/", 12700 le32_to_cpu(ns->v7.result[i][2])); 12701 p += scnprintf(p, end - p, "retry:%d/", 12702 le32_to_cpu(ns->v7.result[i][3])); 12703 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 12704 le32_to_cpu(ns->v7.tavg[i]) / 1000, 12705 le32_to_cpu(ns->v7.tavg[i]) % 1000); 12706 p += scnprintf(p, end - p, "max_t:%d.%03d]", 12707 le32_to_cpu(ns->v7.tmax[i]) / 1000, 12708 le32_to_cpu(ns->v7.tmax[i]) % 1000); 12709 } 12710 } else { 12711 for (i = 0; i < 2; i++) { 12712 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]"); 12713 p += scnprintf(p, end - p, "null-%d", i); 12714 p += scnprintf(p, end - p, "[Tx:%d/", 12715 le32_to_cpu(ns->v2.result[i][4])); 12716 p += scnprintf(p, end - p, "[ok:%d/", 12717 le32_to_cpu(ns->v2.result[i][1])); 12718 p += scnprintf(p, end - p, "fail:%d/", 12719 le32_to_cpu(ns->v2.result[i][0])); 12720 p += scnprintf(p, end - p, "on_time:%d/", 12721 le32_to_cpu(ns->v2.result[i][2])); 12722 p += scnprintf(p, end - p, "retry:%d/", 12723 le32_to_cpu(ns->v2.result[i][3])); 12724 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 12725 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 12726 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 12727 p += scnprintf(p, end - p, "max_t:%d.%03d]", 12728 le32_to_cpu(ns->v2.max_t[i]) / 1000, 12729 le32_to_cpu(ns->v2.max_t[i]) % 1000); 12730 } 12731 } 12732 12733 return p - buf; 12734 } 12735 12736 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12737 { 12738 struct rtw89_btc *btc = &rtwdev->btc; 12739 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12740 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12741 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 12742 const struct rtw89_btc_ver *ver = btc->ver; 12743 char *p = buf, *end = buf + bufsz; 12744 u8 type, val, cnt = 0, state = 0; 12745 bool outloop = false; 12746 u16 i, diff_t, n_start = 0, n_stop = 0; 12747 u16 pos_old, pos_new, trace_step; 12748 12749 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 12750 if (!pcinfo->valid) 12751 return 0; 12752 12753 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 12754 pos_old = le16_to_cpu(pstep->pos_old); 12755 pos_new = le16_to_cpu(pstep->pos_new); 12756 12757 if (pcinfo->req_fver != pstep->fver) 12758 return 0; 12759 12760 /* store step info by using ring instead of FIFO*/ 12761 do { 12762 switch (state) { 12763 case 0: 12764 if (ver->fcxctrl == 7 || ver->fcxctrl == 1) 12765 trace_step = 50; 12766 else 12767 trace_step = btc->ctrl.trace_step; 12768 12769 n_start = pos_old; 12770 if (pos_new >= pos_old) 12771 n_stop = pos_new; 12772 else 12773 n_stop = trace_step - 1; 12774 12775 state = 1; 12776 break; 12777 case 1: 12778 for (i = n_start; i <= n_stop; i++) { 12779 type = pstep->step[i].type; 12780 val = pstep->step[i].val; 12781 diff_t = le16_to_cpu(pstep->step[i].difft); 12782 12783 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 12784 continue; 12785 12786 if (cnt % 10 == 0) 12787 p += scnprintf(p, end - p, 12788 " %-15s : ", "[steps]"); 12789 12790 p += scnprintf(p, end - p, 12791 "-> %s(%02d)(%02d)", 12792 (type == CXSTEP_SLOT ? "SLT" : 12793 "EVT"), (u32)val, diff_t); 12794 if (cnt % 10 == 9) 12795 p += scnprintf(p, end - p, "\n"); 12796 cnt++; 12797 } 12798 12799 state = 2; 12800 break; 12801 case 2: 12802 if (pos_new < pos_old && n_start != 0) { 12803 n_start = 0; 12804 n_stop = pos_new; 12805 state = 1; 12806 } else { 12807 outloop = true; 12808 } 12809 break; 12810 } 12811 } while (!outloop); 12812 12813 return p - buf; 12814 } 12815 12816 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12817 { 12818 struct rtw89_btc *btc = &rtwdev->btc; 12819 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 12820 struct rtw89_btc_rpt_cmn_info *pcinfo; 12821 struct rtw89_btc_fbtc_steps_v3 *pstep; 12822 u32 i, n_begin, n_end, array_idx, cnt = 0; 12823 char *p = buf, *end = buf + bufsz; 12824 u8 type, val; 12825 u16 diff_t; 12826 12827 if ((pfwinfo->rpt_en_map & 12828 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 12829 return 0; 12830 12831 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 12832 if (!pcinfo->valid) 12833 return 0; 12834 12835 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 12836 if (pcinfo->req_fver != pstep->fver) 12837 return 0; 12838 12839 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 12840 n_begin = 1; 12841 else 12842 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 12843 12844 n_end = le32_to_cpu(pstep->cnt); 12845 12846 if (n_begin > n_end) 12847 return 0; 12848 12849 /* restore step info by using ring instead of FIFO */ 12850 for (i = n_begin; i <= n_end; i++) { 12851 array_idx = (i - 1) % FCXDEF_STEP; 12852 type = pstep->step[array_idx].type; 12853 val = pstep->step[array_idx].val; 12854 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 12855 12856 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 12857 continue; 12858 12859 if (cnt % 10 == 0) 12860 p += scnprintf(p, end - p, " %-15s : ", "[steps]"); 12861 12862 p += scnprintf(p, end - p, "-> %s(%02d)", 12863 (type == CXSTEP_SLOT ? 12864 id_to_slot((u32)val) : 12865 id_to_evt((u32)val)), diff_t); 12866 12867 if (cnt % 10 == 9) 12868 p += scnprintf(p, end - p, "\n"); 12869 12870 cnt++; 12871 } 12872 12873 return p - buf; 12874 } 12875 12876 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12877 { 12878 struct rtw89_btc *btc = &rtwdev->btc; 12879 const struct rtw89_btc_ver *ver = btc->ver; 12880 char *p = buf, *end = buf + bufsz; 12881 12882 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 12883 goto out; 12884 12885 p += _show_error(rtwdev, p, end - p); 12886 p += _show_fbtc_tdma(rtwdev, p, end - p); 12887 p += _show_fbtc_slots(rtwdev, p, end - p); 12888 12889 if (ver->fcxcysta == 2) 12890 p += _show_fbtc_cysta_v2(rtwdev, p, end - p); 12891 else if (ver->fcxcysta == 3) 12892 p += _show_fbtc_cysta_v3(rtwdev, p, end - p); 12893 else if (ver->fcxcysta == 4) 12894 p += _show_fbtc_cysta_v4(rtwdev, p, end - p); 12895 else if (ver->fcxcysta == 5) 12896 p += _show_fbtc_cysta_v5(rtwdev, p, end - p); 12897 else if (ver->fcxcysta == 105) 12898 p += _show_fbtc_cysta_v105(rtwdev, p, end - p); 12899 else if (ver->fcxcysta == 7) 12900 p += _show_fbtc_cysta_v7(rtwdev, p, end - p); 12901 else if (ver->fcxcysta == 8) 12902 p += _show_fbtc_cysta_v8(rtwdev, p, end - p); 12903 12904 p += _show_fbtc_nullsta(rtwdev, p, end - p); 12905 12906 if (ver->fcxstep == 2) 12907 p += _show_fbtc_step_v2(rtwdev, p, end - p); 12908 else if (ver->fcxstep == 3) 12909 p += _show_fbtc_step_v3(rtwdev, p, end - p); 12910 12911 out: 12912 return p - buf; 12913 } 12914 12915 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 12916 { 12917 const struct rtw89_chip_info *chip = rtwdev->chip; 12918 struct rtw89_mac_ax_wl_act *bt; 12919 struct rtw89_mac_ax_gnt *gnt; 12920 u32 val, status; 12921 12922 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || 12923 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) { 12924 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 12925 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 12926 12927 gnt = &gnt_cfg->band[0]; 12928 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 12929 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 12930 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 12931 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 12932 12933 gnt = &gnt_cfg->band[1]; 12934 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 12935 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 12936 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 12937 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 12938 } else if (chip->chip_id == RTL8852C) { 12939 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 12940 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 12941 12942 gnt = &gnt_cfg->band[0]; 12943 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 12944 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 12945 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 12946 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 12947 12948 gnt = &gnt_cfg->band[1]; 12949 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 12950 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 12951 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 12952 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 12953 12954 bt = &gnt_cfg->bt[0]; 12955 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL); 12956 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL); 12957 12958 bt = &gnt_cfg->bt[1]; 12959 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL); 12960 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL); 12961 } else if (chip->chip_id == RTL8922A) { 12962 val = rtw89_read32(rtwdev, R_BE_GNT_SW_CTRL); 12963 status = rtw89_read32(rtwdev, R_BE_PTA_GNT_VAL); 12964 12965 gnt = &gnt_cfg->band[0]; 12966 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB0_SWCTRL); 12967 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB0_VAL); 12968 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB0_SWCTRL); 12969 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB0_VAL); 12970 12971 gnt = &gnt_cfg->band[1]; 12972 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB1_SWCTRL); 12973 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB1_VAL); 12974 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB1_SWCTRL); 12975 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB1_VAL); 12976 12977 bt = &gnt_cfg->bt[0]; 12978 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL); 12979 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL); 12980 12981 bt = &gnt_cfg->bt[1]; 12982 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL); 12983 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL); 12984 } else if (chip->chip_id == RTL8922D) { 12985 /* Get from firmware */ 12986 return; 12987 } 12988 } 12989 12990 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 12991 { 12992 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 12993 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 12994 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 12995 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 12996 char *p = buf, *end = buf + bufsz; 12997 u32 en_map_raw, en_map; 12998 u8 *gpio_map, i, sig; 12999 13000 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 13001 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo; 13002 if (!pcinfo->valid) { 13003 rtw89_debug(rtwdev, RTW89_DBG_BTC, 13004 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 13005 __func__); 13006 goto out; 13007 } 13008 13009 if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) { 13010 en_map_raw = le32_to_cpu(gdbg->v7.en_map); 13011 gpio_map = gdbg->v7.gpio_map; 13012 } else { 13013 en_map_raw = le32_to_cpu(gdbg->v1.en_map); 13014 gpio_map = gdbg->v1.gpio_map; 13015 } 13016 13017 en_map = _convert_gpio_enmap_from_ver(rtwdev, en_map_raw); 13018 if (!en_map) 13019 goto out; 13020 13021 p += scnprintf(p, end - p, "\n %-15s : enable_map:0x%08x", 13022 "[gpio_dbg]", en_map); 13023 13024 for (i = 0; i < BTC_DBG_NUM; i++) { 13025 if (!(en_map & BIT(i))) 13026 continue; 13027 13028 sig = ver->fcxgpiodbg >= 8 ? i : _get_gpiosig_for_ver(rtwdev, i); 13029 if (sig >= BTC_DBG_NUM) 13030 continue; 13031 13032 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i), 13033 gpio_map[sig]); 13034 } 13035 13036 out: 13037 return p - buf; 13038 } 13039 13040 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13041 { 13042 const struct rtw89_chip_info *chip = rtwdev->chip; 13043 struct rtw89_btc *btc = &rtwdev->btc; 13044 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13045 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 13046 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 13047 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 13048 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13049 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 13050 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 13051 struct rtw89_mac_ax_gnt gnt; 13052 char *p = buf, *end = buf + bufsz; 13053 u8 i = 0, type = 0, cnt = 0; 13054 u32 val, offset; 13055 13056 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 13057 return 0; 13058 13059 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 13060 13061 p += scnprintf(p, end - p, 13062 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 13063 "[scoreboard]", wl->scbd[BTC_BT_1ST], 13064 wl->wcnt[BTC_WCNT_SCBDUPDATE], 13065 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 13066 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 13067 13068 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 13069 p += scnprintf(p, end - p, 13070 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 13071 "[scoreboard]", wl->scbd[BTC_BT_2ND], 13072 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 13073 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 13074 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 13075 } 13076 13077 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 13078 _get_gnt(rtwdev, &gnt_cfg); 13079 13080 gnt = gnt_cfg.band[0]; 13081 p += scnprintf(p, end - p, 13082 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 13083 "[gnt_status]", 13084 chip->chip_id == RTL8852C ? "HW" : 13085 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 13086 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 13087 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 13088 13089 gnt = gnt_cfg.band[1]; 13090 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 13091 gnt.gnt_wl_sw_en ? "SW" : "HW", 13092 gnt.gnt_wl, 13093 gnt.gnt_bt_sw_en ? "SW" : "HW", 13094 gnt.gnt_bt); 13095 13096 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 13097 if (!pcinfo->valid) { 13098 rtw89_debug(rtwdev, RTW89_DBG_BTC, 13099 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 13100 __func__); 13101 goto out; 13102 } 13103 13104 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 13105 rtw89_debug(rtwdev, RTW89_DBG_BTC, 13106 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 13107 __func__, pmreg->reg_num); 13108 13109 for (i = 0; i < pmreg->reg_num; i++) { 13110 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 13111 offset = le32_to_cpu(chip->mon_reg[i].offset); 13112 val = le32_to_cpu(pmreg->mreg_val[i]); 13113 13114 if (cnt % 6 == 0) 13115 p += scnprintf(p, end - p, 13116 " %-15s : %d_0x%04x=0x%08x", 13117 "[reg]", (u32)type, offset, val); 13118 else 13119 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 13120 (u32)type, 13121 offset, val); 13122 if (cnt % 6 == 5) 13123 p += scnprintf(p, end - p, "\n"); 13124 cnt++; 13125 13126 if (i >= pmreg->reg_num) 13127 p += scnprintf(p, end - p, "\n"); 13128 } 13129 13130 out: 13131 return p - buf; 13132 } 13133 13134 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13135 { 13136 const struct rtw89_chip_info *chip = rtwdev->chip; 13137 struct rtw89_btc *btc = &rtwdev->btc; 13138 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13139 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 13140 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0; 13141 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1; 13142 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13143 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 13144 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 13145 struct rtw89_mac_ax_gnt gnt; 13146 char *p = buf, *end = buf + bufsz; 13147 u8 i = 0, type = 0, cnt = 0; 13148 u32 val, offset; 13149 13150 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 13151 return 0; 13152 13153 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 13154 13155 p += scnprintf(p, end - p, 13156 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 13157 "[scoreboard]", wl->scbd[BTC_BT_1ST], 13158 wl->wcnt[BTC_WCNT_SCBDUPDATE], 13159 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 13160 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 13161 13162 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 13163 p += scnprintf(p, end - p, 13164 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 13165 "[scoreboard]", wl->scbd[BTC_BT_2ND], 13166 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 13167 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 13168 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 13169 } 13170 13171 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 13172 _get_gnt(rtwdev, &gnt_cfg); 13173 13174 gnt = gnt_cfg.band[0]; 13175 p += scnprintf(p, end - p, 13176 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s", 13177 "[gnt_status]", 13178 chip->chip_id == RTL8852C ? "HW" : 13179 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 13180 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 13181 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt, 13182 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 13183 13184 gnt = gnt_cfg.band[1]; 13185 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 13186 gnt.gnt_wl_sw_en ? "SW" : "HW", 13187 gnt.gnt_wl, 13188 gnt.gnt_bt_sw_en ? "SW" : "HW", 13189 gnt.gnt_bt); 13190 13191 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 13192 if (!pcinfo->valid) { 13193 rtw89_debug(rtwdev, RTW89_DBG_BTC, 13194 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 13195 __func__); 13196 goto out; 13197 } 13198 13199 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 13200 rtw89_debug(rtwdev, RTW89_DBG_BTC, 13201 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 13202 __func__, pmreg->reg_num); 13203 13204 for (i = 0; i < pmreg->reg_num; i++) { 13205 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 13206 offset = le32_to_cpu(chip->mon_reg[i].offset); 13207 val = le32_to_cpu(pmreg->mreg_val[i]); 13208 13209 if (cnt % 6 == 0) 13210 p += scnprintf(p, end - p, 13211 " %-15s : %d_0x%04x=0x%08x", 13212 "[reg]", (u32)type, offset, val); 13213 else 13214 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 13215 (u32)type, 13216 offset, val); 13217 if (cnt % 6 == 5) 13218 p += scnprintf(p, end - p, "\n"); 13219 cnt++; 13220 13221 if (i >= pmreg->reg_num) 13222 p += scnprintf(p, end - p, "\n"); 13223 } 13224 13225 out: 13226 return p - buf; 13227 } 13228 13229 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13230 { 13231 struct rtw89_btc *btc = &rtwdev->btc; 13232 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13233 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL; 13234 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13235 struct rtw89_btc_cx *cx = &btc->cx; 13236 struct rtw89_btc_bt_info *bt0 = &cx->bt0; 13237 struct rtw89_btc_bt_info *bt1 = &cx->bt1; 13238 struct rtw89_btc_wl_info *wl = &cx->wl; 13239 struct rtw89_btc_dm *dm = &btc->dm; 13240 char *p = buf, *end = buf + bufsz; 13241 u8 i, type, cnt = 0; 13242 u32 val, offset; 13243 13244 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG)) 13245 return 0; 13246 13247 p += scnprintf(p, end - p, "\n========== [HW Status] ==========\n"); 13248 13249 p += scnprintf(p, end - p, 13250 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n", 13251 "[scoreboard]", wl->scbd[BTC_BT_1ST], 13252 wl->wcnt[BTC_WCNT_SCBDUPDATE], 13253 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD], 13254 bt0->bcnt[BTC_BCNT_SCBDUPDATE]); 13255 13256 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) { 13257 p += scnprintf(p, end - p, 13258 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n", 13259 "[scoreboard]", wl->scbd[BTC_BT_2ND], 13260 wl->wcnt[BTC_WCNT_SCBDUPDATE2], 13261 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD], 13262 bt1->bcnt[BTC_BCNT_SCBDUPDATE]); 13263 } 13264 13265 /* To avoid I/O if WL LPS or power-off */ 13266 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 13267 13268 p += scnprintf(p, end - p, 13269 " %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s\n", 13270 "[gnt_status]", 13271 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" : 13272 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 13273 wl->pta_req_mac, 13274 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 13275 13276 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 13277 p += scnprintf(p, end - p, 13278 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", 13279 "[gnt_status]", 13280 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", 13281 dm->gnt_set[RTW89_PHY_0].gnt_wl, 13282 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", 13283 dm->gnt_set[RTW89_PHY_0].gnt_bt0, 13284 dm->gnt_set[RTW89_PHY_0].gnt_bt1_sw_en ? "SW" : "HW", 13285 dm->gnt_set[RTW89_PHY_0].gnt_bt1); 13286 else 13287 p += scnprintf(p, end - p, 13288 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", 13289 "[gnt_status]", 13290 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW", 13291 dm->gnt_set[RTW89_PHY_0].gnt_wl, 13292 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW", 13293 dm->gnt_set[RTW89_PHY_0].gnt_bt0); 13294 13295 if (rtwdev->dbcc_en) { 13296 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) 13297 p += scnprintf(p, end - p, 13298 ", phy-1[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]", 13299 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", 13300 dm->gnt_set[RTW89_PHY_1].gnt_wl, 13301 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", 13302 dm->gnt_set[RTW89_PHY_1].gnt_bt0, 13303 dm->gnt_set[RTW89_PHY_1].gnt_bt1_sw_en ? "SW" : "HW", 13304 dm->gnt_set[RTW89_PHY_1].gnt_bt1); 13305 else 13306 p += scnprintf(p, end - p, 13307 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", 13308 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW", 13309 dm->gnt_set[RTW89_PHY_1].gnt_wl, 13310 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW", 13311 dm->gnt_set[RTW89_PHY_1].gnt_bt0); 13312 } 13313 13314 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 13315 if (!pcinfo->valid) 13316 goto out; 13317 13318 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 13319 13320 for (i = 0; i < pmreg->reg_num; i++) { 13321 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type); 13322 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset); 13323 val = le32_to_cpu(pmreg->mreg_val[i]); 13324 13325 if (cnt % 6 == 0) 13326 p += scnprintf(p, end - p, 13327 "\n %-15s : %s_0x%x=0x%x", "[reg]", 13328 id_to_regtype(type), offset, val); 13329 else 13330 p += scnprintf(p, end - p, ", %s_0x%x=0x%x", 13331 id_to_regtype(type), offset, val); 13332 cnt++; 13333 } 13334 13335 out: 13336 return p - buf; 13337 } 13338 13339 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13340 { 13341 struct rtw89_btc *btc = &rtwdev->btc; 13342 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13343 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13344 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 13345 struct rtw89_btc_cx *cx = &btc->cx; 13346 struct rtw89_btc_dm *dm = &btc->dm; 13347 struct rtw89_btc_wl_info *wl = &cx->wl; 13348 struct rtw89_btc_bt_info *bt = &cx->bt0; 13349 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 13350 char *p = buf, *end = buf + bufsz; 13351 u8 i; 13352 13353 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13354 return 0; 13355 13356 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 13357 13358 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13359 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 13360 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 13361 13362 p += scnprintf(p, end - p, 13363 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 13364 "[summary]", pfwinfo->cnt_h2c, 13365 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 13366 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 13367 13368 p += scnprintf(p, end - p, 13369 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 13370 pfwinfo->event[BTF_EVNT_RPT], 13371 prptctrl->rpt_cnt, 13372 prptctrl->rpt_enable, dm->error.val); 13373 13374 if (dm->error.map.wl_fw_hang) 13375 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13376 p += scnprintf(p, end - p, "\n"); 13377 p += scnprintf(p, end - p, 13378 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 13379 "[mailbox]", prptctrl->mb_send_ok_cnt, 13380 prptctrl->mb_send_fail_cnt, 13381 prptctrl->mb_recv_cnt); 13382 13383 p += scnprintf(p, end - p, 13384 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 13385 prptctrl->mb_a2dp_empty_cnt, 13386 prptctrl->mb_a2dp_flct_cnt, 13387 prptctrl->mb_a2dp_full_cnt); 13388 13389 p += scnprintf(p, end - p, 13390 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 13391 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ], 13392 wl->wcnt[BTC_WCNT_RFK_GO], 13393 wl->wcnt[BTC_WCNT_RFK_REJECT], 13394 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 13395 13396 p += scnprintf(p, end - p, 13397 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 13398 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 13399 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 13400 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 13401 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 13402 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 13403 13404 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 13405 bt->rfk_info.map.timeout = 1; 13406 else 13407 bt->rfk_info.map.timeout = 0; 13408 13409 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 13410 } else { 13411 p += scnprintf(p, end - p, 13412 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 13413 "[summary]", pfwinfo->cnt_h2c, 13414 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 13415 pfwinfo->event[BTF_EVNT_RPT], 13416 btc->fwinfo.rpt_en_map); 13417 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 13418 } 13419 13420 for (i = 0; i < BTC_NCNT_NUM; i++) 13421 cnt_sum += dm->cnt_notify[i]; 13422 13423 p += scnprintf(p, end - p, 13424 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13425 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13426 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13427 13428 p += scnprintf(p, end - p, 13429 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13430 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13431 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13432 cnt[BTC_NCNT_WL_STA]); 13433 13434 p += scnprintf(p, end - p, 13435 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 13436 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 13437 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 13438 cnt[BTC_NCNT_SPECIAL_PACKET]); 13439 13440 p += scnprintf(p, end - p, 13441 "timer=%d, control=%d, customerize=%d\n", 13442 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 13443 cnt[BTC_NCNT_CUSTOMERIZE]); 13444 13445 return p - buf; 13446 } 13447 13448 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13449 { 13450 struct rtw89_btc *btc = &rtwdev->btc; 13451 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13452 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 13453 struct rtw89_btc_rpt_cmn_info *pcinfo; 13454 struct rtw89_btc_cx *cx = &btc->cx; 13455 struct rtw89_btc_dm *dm = &btc->dm; 13456 struct rtw89_btc_wl_info *wl = &cx->wl; 13457 struct rtw89_btc_bt_info *bt = &cx->bt0; 13458 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 13459 char *p = buf, *end = buf + bufsz; 13460 u8 i; 13461 13462 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13463 return 0; 13464 13465 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 13466 13467 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13468 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 13469 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 13470 13471 p += scnprintf(p, end - p, 13472 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 13473 "[summary]", pfwinfo->cnt_h2c, 13474 pfwinfo->cnt_h2c_fail, 13475 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 13476 pfwinfo->cnt_c2h, 13477 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 13478 13479 p += scnprintf(p, end - p, 13480 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 13481 pfwinfo->event[BTF_EVNT_RPT], 13482 le32_to_cpu(prptctrl->rpt_info.cnt), 13483 le32_to_cpu(prptctrl->rpt_info.en), 13484 dm->error.val); 13485 13486 if (dm->error.map.wl_fw_hang) 13487 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13488 p += scnprintf(p, end - p, "\n"); 13489 p += scnprintf(p, end - p, 13490 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13491 "[mailbox]", 13492 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13493 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13494 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13495 13496 p += scnprintf(p, end - p, 13497 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 13498 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13499 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13500 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13501 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13502 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13503 13504 p += scnprintf(p, end - p, 13505 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 13506 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ], 13507 wl->wcnt[BTC_WCNT_RFK_GO], 13508 wl->wcnt[BTC_WCNT_RFK_REJECT], 13509 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 13510 13511 p += scnprintf(p, end - p, 13512 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 13513 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 13514 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 13515 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 13516 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 13517 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 13518 13519 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 13520 bt->rfk_info.map.timeout = 1; 13521 else 13522 bt->rfk_info.map.timeout = 0; 13523 13524 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 13525 } else { 13526 p += scnprintf(p, end - p, 13527 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 13528 "[summary]", pfwinfo->cnt_h2c, 13529 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 13530 pfwinfo->event[BTF_EVNT_RPT], 13531 btc->fwinfo.rpt_en_map); 13532 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 13533 } 13534 13535 for (i = 0; i < BTC_NCNT_NUM; i++) 13536 cnt_sum += dm->cnt_notify[i]; 13537 13538 p += scnprintf(p, end - p, 13539 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13540 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13541 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13542 13543 p += scnprintf(p, end - p, 13544 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13545 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13546 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13547 cnt[BTC_NCNT_WL_STA]); 13548 13549 p += scnprintf(p, end - p, 13550 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 13551 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 13552 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 13553 cnt[BTC_NCNT_SPECIAL_PACKET]); 13554 13555 p += scnprintf(p, end - p, 13556 "timer=%d, control=%d, customerize=%d\n", 13557 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 13558 cnt[BTC_NCNT_CUSTOMERIZE]); 13559 13560 return p - buf; 13561 } 13562 13563 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13564 { 13565 struct rtw89_btc *btc = &rtwdev->btc; 13566 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13567 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 13568 struct rtw89_btc_rpt_cmn_info *pcinfo; 13569 struct rtw89_btc_cx *cx = &btc->cx; 13570 struct rtw89_btc_dm *dm = &btc->dm; 13571 struct rtw89_btc_wl_info *wl = &cx->wl; 13572 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 13573 char *p = buf, *end = buf + bufsz; 13574 u8 i; 13575 13576 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13577 return 0; 13578 13579 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 13580 13581 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13582 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 13583 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 13584 13585 p += scnprintf(p, end - p, 13586 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 13587 "[summary]", pfwinfo->cnt_h2c, 13588 pfwinfo->cnt_h2c_fail, 13589 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13590 pfwinfo->cnt_c2h, 13591 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13592 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 13593 13594 p += scnprintf(p, end - p, 13595 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13596 pfwinfo->event[BTF_EVNT_RPT], 13597 le16_to_cpu(prptctrl->rpt_info.cnt), 13598 le32_to_cpu(prptctrl->rpt_info.en)); 13599 13600 if (dm->error.map.wl_fw_hang) 13601 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13602 p += scnprintf(p, end - p, "\n"); 13603 p += scnprintf(p, end - p, 13604 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13605 "[mailbox]", 13606 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13607 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13608 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13609 13610 p += scnprintf(p, end - p, 13611 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 13612 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13613 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13614 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13615 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13616 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13617 13618 p += scnprintf(p, end - p, 13619 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 13620 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13621 wl->wcnt[BTC_WCNT_RFK_GO], 13622 wl->wcnt[BTC_WCNT_RFK_REJECT], 13623 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 13624 13625 p += scnprintf(p, end - p, 13626 ", bt_rfk[req:%d]", 13627 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 13628 13629 p += scnprintf(p, end - p, 13630 ", AOAC[RF_on:%d/RF_off:%d]", 13631 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13632 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13633 } else { 13634 p += scnprintf(p, end - p, 13635 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 13636 "[summary]", pfwinfo->cnt_h2c, 13637 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 13638 } 13639 13640 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 13641 pfwinfo->err[BTFRE_EXCEPTION]) { 13642 p += scnprintf(p, end - p, "\n"); 13643 p += scnprintf(p, end - p, 13644 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 13645 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 13646 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 13647 pfwinfo->fver_mismch, 13648 pfwinfo->err[BTFRE_EXCEPTION], 13649 wl->status.map.lps, wl->status.map.rf_off); 13650 } 13651 13652 for (i = 0; i < BTC_NCNT_NUM; i++) 13653 cnt_sum += dm->cnt_notify[i]; 13654 13655 p += scnprintf(p, end - p, "\n"); 13656 p += scnprintf(p, end - p, 13657 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13658 "[notify_cnt]", 13659 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13660 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13661 13662 p += scnprintf(p, end - p, 13663 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13664 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13665 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13666 cnt[BTC_NCNT_WL_STA]); 13667 13668 p += scnprintf(p, end - p, 13669 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 13670 "[notify_cnt]", 13671 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13672 cnt[BTC_NCNT_SWITCH_BAND], 13673 cnt[BTC_NCNT_SPECIAL_PACKET]); 13674 13675 p += scnprintf(p, end - p, 13676 "timer=%d, control=%d, customerize=%d", 13677 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 13678 cnt[BTC_NCNT_CUSTOMERIZE]); 13679 13680 return p - buf; 13681 } 13682 13683 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13684 { 13685 struct rtw89_btc *btc = &rtwdev->btc; 13686 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 13687 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 13688 struct rtw89_btc_rpt_cmn_info *pcinfo; 13689 struct rtw89_btc_cx *cx = &btc->cx; 13690 struct rtw89_btc_dm *dm = &btc->dm; 13691 struct rtw89_btc_wl_info *wl = &cx->wl; 13692 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 13693 char *p = buf, *end = buf + bufsz; 13694 u8 i; 13695 13696 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13697 return 0; 13698 13699 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 13700 13701 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13702 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 13703 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 13704 13705 p += scnprintf(p, end - p, 13706 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 13707 "[summary]", pfwinfo->cnt_h2c, 13708 pfwinfo->cnt_h2c_fail, 13709 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13710 pfwinfo->cnt_c2h, 13711 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13712 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 13713 13714 p += scnprintf(p, end - p, 13715 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13716 pfwinfo->event[BTF_EVNT_RPT], 13717 le16_to_cpu(prptctrl->rpt_info.cnt), 13718 le32_to_cpu(prptctrl->rpt_info.en)); 13719 13720 if (dm->error.map.wl_fw_hang) 13721 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13722 p += scnprintf(p, end - p, "\n"); 13723 p += scnprintf(p, end - p, 13724 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13725 "[mailbox]", 13726 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13727 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13728 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13729 13730 p += scnprintf(p, end - p, 13731 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 13732 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13733 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13734 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13735 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13736 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13737 13738 p += scnprintf(p, end - p, 13739 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 13740 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13741 wl->wcnt[BTC_WCNT_RFK_GO], 13742 wl->wcnt[BTC_WCNT_RFK_REJECT], 13743 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 13744 13745 p += scnprintf(p, end - p, 13746 ", bt_rfk[req:%d]", 13747 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 13748 13749 p += scnprintf(p, end - p, 13750 ", AOAC[RF_on:%d/RF_off:%d]", 13751 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13752 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13753 } else { 13754 p += scnprintf(p, end - p, 13755 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 13756 "[summary]", pfwinfo->cnt_h2c, 13757 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 13758 } 13759 13760 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 13761 pfwinfo->err[BTFRE_EXCEPTION]) { 13762 p += scnprintf(p, end - p, "\n"); 13763 p += scnprintf(p, end - p, 13764 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 13765 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 13766 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 13767 pfwinfo->fver_mismch, 13768 pfwinfo->err[BTFRE_EXCEPTION], 13769 wl->status.map.lps, wl->status.map.rf_off); 13770 } 13771 13772 for (i = 0; i < BTC_NCNT_NUM; i++) 13773 cnt_sum += dm->cnt_notify[i]; 13774 13775 p += scnprintf(p, end - p, "\n"); 13776 p += scnprintf(p, end - p, 13777 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13778 "[notify_cnt]", 13779 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13780 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13781 13782 p += scnprintf(p, end - p, 13783 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13784 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13785 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13786 cnt[BTC_NCNT_WL_STA]); 13787 13788 p += scnprintf(p, end - p, 13789 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 13790 "[notify_cnt]", 13791 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13792 cnt[BTC_NCNT_SWITCH_BAND], 13793 cnt[BTC_NCNT_SPECIAL_PACKET]); 13794 13795 p += scnprintf(p, end - p, 13796 "timer=%d, control=%d, customerize=%d", 13797 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 13798 cnt[BTC_NCNT_CUSTOMERIZE]); 13799 13800 return p - buf; 13801 } 13802 13803 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13804 { 13805 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 13806 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL; 13807 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13808 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 13809 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 13810 struct rtw89_btc_wl_info *wl = &cx->wl; 13811 u32 *cnt = rtwdev->btc.dm.cnt_notify; 13812 char *p = buf, *end = buf + bufsz; 13813 u32 cnt_sum = 0; 13814 u8 i; 13815 13816 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13817 return 0; 13818 13819 p += scnprintf(p, end - p, "%s", 13820 "\n========== [Statistics] ==========\n"); 13821 13822 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13823 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 13824 !wl->status.map.rf_off) { 13825 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7; 13826 13827 p += scnprintf(p, end - p, 13828 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," 13829 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ", 13830 "[summary]", pfwinfo->cnt_h2c, 13831 pfwinfo->cnt_h2c_fail, 13832 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13833 pfwinfo->cnt_c2h, 13834 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13835 le16_to_cpu(prptctrl->rpt_info.len_c2h), 13836 rtwdev->btc.ver->info_buf); 13837 13838 p += scnprintf(p, end - p, 13839 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13840 pfwinfo->event[BTF_EVNT_RPT], 13841 le16_to_cpu(prptctrl->rpt_info.cnt), 13842 le32_to_cpu(prptctrl->rpt_info.en)); 13843 13844 if (dm->error.map.wl_fw_hang) 13845 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13846 p += scnprintf(p, end - p, "\n"); 13847 13848 p += scnprintf(p, end - p, 13849 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13850 "[mailbox]", 13851 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13852 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13853 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13854 13855 p += scnprintf(p, end - p, 13856 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 13857 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13858 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13859 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13860 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13861 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13862 13863 p += scnprintf(p, end - p, 13864 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 13865 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13866 wl->wcnt[BTC_WCNT_RFK_GO], 13867 wl->wcnt[BTC_WCNT_RFK_REJECT], 13868 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 13869 wl->rfk_info.proc_time); 13870 13871 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 13872 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 13873 13874 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 13875 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13876 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13877 } else { 13878 p += scnprintf(p, end - p, 13879 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 13880 "[summary]", 13881 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 13882 pfwinfo->cnt_c2h, 13883 wl->status.map.lps, wl->status.map.rf_off); 13884 } 13885 13886 for (i = 0; i < BTC_NCNT_NUM; i++) 13887 cnt_sum += dm->cnt_notify[i]; 13888 13889 p += scnprintf(p, end - p, 13890 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 13891 "[notify_cnt]", 13892 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 13893 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 13894 13895 p += scnprintf(p, end - p, 13896 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 13897 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 13898 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 13899 cnt[BTC_NCNT_WL_STA]); 13900 13901 p += scnprintf(p, end - p, 13902 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 13903 "[notify_cnt]", 13904 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 13905 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 13906 cnt[BTC_NCNT_SPECIAL_PACKET]); 13907 13908 p += scnprintf(p, end - p, 13909 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 13910 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 13911 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 13912 cnt[BTC_NCNT_COUNTRYCODE]); 13913 13914 return p - buf; 13915 } 13916 13917 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 13918 { 13919 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 13920 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 13921 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL; 13922 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 13923 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 13924 struct rtw89_btc_wl_info *wl = &cx->wl; 13925 u32 *cnt = rtwdev->btc.dm.cnt_notify; 13926 char *p = buf, *end = buf + bufsz; 13927 u32 cnt_sum = 0; 13928 u8 i; 13929 13930 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 13931 return 0; 13932 13933 p += scnprintf(p, end - p, "%s", 13934 "\n========== [Statistics] ==========\n"); 13935 13936 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 13937 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 13938 !wl->status.map.rf_off) { 13939 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8; 13940 13941 p += scnprintf(p, end - p, 13942 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 13943 "[summary]", pfwinfo->cnt_h2c, 13944 pfwinfo->cnt_h2c_fail, 13945 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 13946 pfwinfo->cnt_c2h, 13947 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 13948 le16_to_cpu(prptctrl->rpt_info.len_c2h), 13949 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 13950 rtwdev->btc.ver->info_buf); 13951 13952 p += scnprintf(p, end - p, 13953 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 13954 pfwinfo->event[BTF_EVNT_RPT], 13955 le16_to_cpu(prptctrl->rpt_info.cnt), 13956 le32_to_cpu(prptctrl->rpt_info.en)); 13957 13958 if (dm->error.map.wl_fw_hang) 13959 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 13960 p += scnprintf(p, end - p, "\n"); 13961 13962 p += scnprintf(p, end - p, 13963 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 13964 "[mailbox]", 13965 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 13966 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 13967 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 13968 13969 p += scnprintf(p, end - p, 13970 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 13971 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 13972 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 13973 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 13974 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 13975 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 13976 13977 p += scnprintf(p, end - p, 13978 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 13979 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 13980 wl->wcnt[BTC_WCNT_RFK_GO], 13981 wl->wcnt[BTC_WCNT_RFK_REJECT], 13982 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 13983 wl->rfk_info.proc_time); 13984 13985 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 13986 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 13987 13988 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 13989 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 13990 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 13991 } else { 13992 p += scnprintf(p, end - p, 13993 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 13994 "[summary]", 13995 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 13996 pfwinfo->cnt_c2h, 13997 wl->status.map.lps, wl->status.map.rf_off); 13998 } 13999 14000 for (i = 0; i < BTC_NCNT_NUM; i++) 14001 cnt_sum += dm->cnt_notify[i]; 14002 14003 p += scnprintf(p, end - p, 14004 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 14005 "[notify_cnt]", 14006 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 14007 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 14008 14009 p += scnprintf(p, end - p, 14010 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 14011 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 14012 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 14013 cnt[BTC_NCNT_WL_STA]); 14014 14015 p += scnprintf(p, end - p, 14016 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 14017 "[notify_cnt]", 14018 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 14019 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 14020 cnt[BTC_NCNT_SPECIAL_PACKET]); 14021 14022 p += scnprintf(p, end - p, 14023 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 14024 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 14025 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 14026 cnt[BTC_NCNT_COUNTRYCODE]); 14027 14028 return p - buf; 14029 } 14030 14031 static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 14032 { 14033 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 14034 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 14035 struct rtw89_btc_fbtc_rpt_ctrl_v9 *prptctrl = NULL; 14036 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 14037 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 14038 struct rtw89_btc_wl_info *wl = &cx->wl; 14039 u32 *cnt = rtwdev->btc.dm.cnt_notify; 14040 char *p = buf, *end = buf + bufsz; 14041 u32 cnt_sum = 0; 14042 u8 i; 14043 14044 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 14045 return 0; 14046 14047 p += scnprintf(p, end - p, "%s", 14048 "\n========== [Statistics] ==========\n"); 14049 14050 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 14051 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 14052 !wl->status.map.rf_off) { 14053 prptctrl = &pfwinfo->rpt_ctrl.finfo.v9; 14054 14055 p += scnprintf(p, end - p, 14056 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ", 14057 "[summary]", pfwinfo->cnt_h2c, 14058 pfwinfo->cnt_h2c_fail, 14059 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 14060 pfwinfo->cnt_c2h, 14061 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 14062 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 14063 14064 p += scnprintf(p, end - p, 14065 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 14066 pfwinfo->event[BTF_EVNT_RPT], 14067 le16_to_cpu(prptctrl->rpt_info.cnt), 14068 le32_to_cpu(prptctrl->rpt_info.en)); 14069 14070 if (dm->error.map.wl_fw_hang) 14071 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 14072 p += scnprintf(p, end - p, "\n"); 14073 14074 p += scnprintf(p, end - p, 14075 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 14076 "[mailbox]", 14077 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 14078 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 14079 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 14080 14081 p += scnprintf(p, end - p, 14082 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 14083 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 14084 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 14085 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 14086 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 14087 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 14088 14089 p += scnprintf(p, end - p, 14090 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 14091 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 14092 wl->wcnt[BTC_WCNT_RFK_GO], 14093 wl->wcnt[BTC_WCNT_RFK_REJECT], 14094 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 14095 wl->rfk_info.proc_time); 14096 14097 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 14098 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 14099 14100 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 14101 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 14102 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 14103 } else { 14104 p += scnprintf(p, end - p, 14105 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 14106 "[summary]", 14107 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 14108 pfwinfo->cnt_c2h, 14109 wl->status.map.lps, wl->status.map.rf_off); 14110 } 14111 14112 for (i = 0; i < BTC_NCNT_NUM; i++) 14113 cnt_sum += dm->cnt_notify[i]; 14114 14115 p += scnprintf(p, end - p, 14116 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 14117 "[notify_cnt]", 14118 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 14119 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 14120 14121 p += scnprintf(p, end - p, 14122 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 14123 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 14124 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 14125 cnt[BTC_NCNT_WL_STA]); 14126 14127 p += scnprintf(p, end - p, 14128 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 14129 "[notify_cnt]", 14130 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 14131 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 14132 cnt[BTC_NCNT_SPECIAL_PACKET]); 14133 14134 p += scnprintf(p, end - p, 14135 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 14136 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 14137 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 14138 cnt[BTC_NCNT_COUNTRYCODE]); 14139 14140 return p - buf; 14141 } 14142 14143 static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 14144 { 14145 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 14146 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 14147 struct rtw89_btc_fbtc_rpt_ctrl_v11 *prptctrl = NULL; 14148 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 14149 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 14150 struct rtw89_btc_wl_info *wl = &cx->wl; 14151 u32 *cnt = rtwdev->btc.dm.cnt_notify; 14152 char *p = buf, *end = buf + bufsz; 14153 u32 cnt_sum = 0; 14154 u8 i; 14155 14156 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 14157 return 0; 14158 14159 p += scnprintf(p, end - p, "%s", 14160 "\n========== [Statistics] ==========\n"); 14161 14162 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 14163 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 14164 !wl->status.map.rf_off) { 14165 prptctrl = &pfwinfo->rpt_ctrl.finfo.v11; 14166 14167 p += scnprintf(p, end - p, 14168 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 14169 "[summary]", pfwinfo->cnt_h2c, 14170 pfwinfo->cnt_h2c_fail, 14171 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 14172 pfwinfo->cnt_c2h, 14173 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 14174 le16_to_cpu(prptctrl->rpt_info.len_c2h), 14175 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 14176 rtwdev->btc.ver->info_buf); 14177 14178 p += scnprintf(p, end - p, 14179 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 14180 pfwinfo->event[BTF_EVNT_RPT], 14181 le16_to_cpu(prptctrl->rpt_info.cnt), 14182 le32_to_cpu(prptctrl->rpt_info.en)); 14183 14184 if (dm->error.map.wl_fw_hang) 14185 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 14186 p += scnprintf(p, end - p, "\n"); 14187 14188 p += scnprintf(p, end - p, 14189 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 14190 "[mailbox]", 14191 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 14192 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 14193 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 14194 14195 p += scnprintf(p, end - p, 14196 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n", 14197 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 14198 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 14199 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 14200 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 14201 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 14202 14203 p += scnprintf(p, end - p, 14204 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 14205 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ], 14206 wl->wcnt[BTC_WCNT_RFK_GO], 14207 wl->wcnt[BTC_WCNT_RFK_REJECT], 14208 wl->wcnt[BTC_WCNT_RFK_TIMEOUT], 14209 wl->rfk_info.proc_time); 14210 14211 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n", 14212 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 14213 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 14214 } else { 14215 p += scnprintf(p, end - p, 14216 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n", 14217 "[summary]", 14218 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 14219 pfwinfo->cnt_c2h, 14220 wl->status.map.lps, wl->status.map.rf_off); 14221 } 14222 14223 for (i = 0; i < BTC_NCNT_NUM; i++) 14224 cnt_sum += dm->cnt_notify[i]; 14225 14226 p += scnprintf(p, end - p, 14227 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 14228 "[notify_cnt]", 14229 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 14230 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 14231 14232 p += scnprintf(p, end - p, 14233 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 14234 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 14235 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 14236 cnt[BTC_NCNT_WL_STA]); 14237 14238 p += scnprintf(p, end - p, 14239 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 14240 "[notify_cnt]", 14241 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 14242 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 14243 cnt[BTC_NCNT_SPECIAL_PACKET]); 14244 14245 p += scnprintf(p, end - p, 14246 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 14247 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 14248 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 14249 cnt[BTC_NCNT_COUNTRYCODE]); 14250 14251 return p - buf; 14252 } 14253 14254 static int _show_summary_v205(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 14255 { 14256 struct rtw89_btc *btc = &rtwdev->btc; 14257 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 14258 struct rtw89_btc_fbtc_rpt_ctrl_v205 *prptctrl; 14259 struct rtw89_btc_rpt_cmn_info *pcinfo; 14260 struct rtw89_btc_cx *cx = &btc->cx; 14261 struct rtw89_btc_dm *dm = &btc->dm; 14262 struct rtw89_btc_wl_info *wl = &cx->wl; 14263 struct rtw89_btc_bt_info *bt = &cx->bt0; 14264 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 14265 char *p = buf, *end = buf + bufsz; 14266 u8 i; 14267 14268 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 14269 return 0; 14270 14271 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 14272 14273 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 14274 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 14275 prptctrl = &pfwinfo->rpt_ctrl.finfo.v205; 14276 14277 p += scnprintf(p, end - p, 14278 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 14279 "[summary]", pfwinfo->cnt_h2c, 14280 pfwinfo->cnt_h2c_fail, 14281 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 14282 pfwinfo->cnt_c2h, 14283 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 14284 14285 p += scnprintf(p, end - p, 14286 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 14287 pfwinfo->event[BTF_EVNT_RPT], 14288 le32_to_cpu(prptctrl->rpt_info.cnt), 14289 le32_to_cpu(prptctrl->rpt_info.en), 14290 dm->error.val); 14291 14292 if (dm->error.map.wl_fw_hang) 14293 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 14294 p += scnprintf(p, end - p, "\n"); 14295 p += scnprintf(p, end - p, 14296 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 14297 "[mailbox]", 14298 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 14299 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 14300 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 14301 14302 p += scnprintf(p, end - p, 14303 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 14304 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 14305 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 14306 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 14307 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 14308 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 14309 14310 p += scnprintf(p, end - p, 14311 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 14312 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ], 14313 wl->wcnt[BTC_WCNT_RFK_GO], 14314 wl->wcnt[BTC_WCNT_RFK_REJECT], 14315 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]); 14316 14317 p += scnprintf(p, end - p, 14318 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 14319 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 14320 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 14321 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 14322 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 14323 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 14324 14325 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 14326 bt->rfk_info.map.timeout = 1; 14327 else 14328 bt->rfk_info.map.timeout = 0; 14329 14330 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 14331 } else { 14332 p += scnprintf(p, end - p, 14333 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 14334 "[summary]", pfwinfo->cnt_h2c, 14335 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 14336 pfwinfo->event[BTF_EVNT_RPT], 14337 btc->fwinfo.rpt_en_map); 14338 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 14339 } 14340 14341 for (i = 0; i < BTC_NCNT_NUM; i++) 14342 cnt_sum += dm->cnt_notify[i]; 14343 14344 p += scnprintf(p, end - p, 14345 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 14346 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 14347 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 14348 14349 p += scnprintf(p, end - p, 14350 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 14351 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 14352 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 14353 cnt[BTC_NCNT_WL_STA]); 14354 14355 p += scnprintf(p, end - p, 14356 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 14357 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 14358 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 14359 cnt[BTC_NCNT_SPECIAL_PACKET]); 14360 14361 p += scnprintf(p, end - p, 14362 "timer=%d, control=%d, customerize=%d\n", 14363 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 14364 cnt[BTC_NCNT_CUSTOMERIZE]); 14365 14366 return p - buf; 14367 } 14368 14369 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 14370 { 14371 struct rtw89_btc *btc = &rtwdev->btc; 14372 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 14373 const struct rtw89_btc_ver *ver = btc->ver; 14374 struct rtw89_btc_dm *dm = &btc->dm; 14375 char *p = buf, *end = buf + bufsz; 14376 14377 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 14378 14379 p += scnprintf(p, end - p, 14380 "\n\n\n** Page:%3d/RunCNT:%3d **", 14381 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO], 14382 dm->cnt_dm[BTC_DCNT_RUN]); 14383 p += scnprintf(p, end - p, 14384 "\n========== [BTC FEATURE SUB VER] =========="); 14385 p += scnprintf(p, end - p, 14386 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]", 14387 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt, 14388 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots, 14389 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta); 14390 p += scnprintf(p, end - p, 14391 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]", 14392 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep, 14393 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg, 14394 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg); 14395 p += scnprintf(p, end - p, 14396 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]", 14397 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver, 14398 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh, 14399 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo); 14400 p += scnprintf(p, end - p, 14401 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],", 14402 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi, 14403 fwsubver->fcxmlo, ver->fcxmlo); 14404 14405 p += _show_cx_info(rtwdev, p, end - p); 14406 p += _show_wl_info(rtwdev, p, end - p); 14407 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_1ST); 14408 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_2ND); 14409 p += _show_dm_info(rtwdev, p, end - p); 14410 p += _show_fw_dm_msg(rtwdev, p, end - p); 14411 14412 if (ver->fcxmreg == 1) 14413 p += _show_mreg_v1(rtwdev, p, end - p); 14414 else if (ver->fcxmreg == 2) 14415 p += _show_mreg_v2(rtwdev, p, end - p); 14416 else if (ver->fcxmreg == 7) 14417 p += _show_mreg_v7(rtwdev, p, end - p); 14418 14419 p += _show_gpio_dbg(rtwdev, p, end - p); 14420 14421 if (ver->fcxbtcrpt == 1) 14422 p += _show_summary_v1(rtwdev, p, end - p); 14423 else if (ver->fcxbtcrpt == 4) 14424 p += _show_summary_v4(rtwdev, p, end - p); 14425 else if (ver->fcxbtcrpt == 5) 14426 p += _show_summary_v5(rtwdev, p, end - p); 14427 else if (ver->fcxbtcrpt == 105) 14428 p += _show_summary_v105(rtwdev, p, end - p); 14429 else if (ver->fcxbtcrpt == 205) 14430 p += _show_summary_v205(rtwdev, p, end - p); 14431 else if (ver->fcxbtcrpt == 7) 14432 p += _show_summary_v7(rtwdev, p, end - p); 14433 else if (ver->fcxbtcrpt == 8) 14434 p += _show_summary_v8(rtwdev, p, end - p); 14435 else if (ver->fcxbtcrpt == 9) 14436 p += _show_summary_v9(rtwdev, p, end - p); 14437 else if (ver->fcxbtcrpt == 11) 14438 p += _show_summary_v11(rtwdev, p, end - p); 14439 14440 p += scnprintf(p, end - p, "\n"); 14441 14442 return p - buf; 14443 } 14444 14445 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 14446 { 14447 const struct rtw89_chip_info *chip = rtwdev->chip; 14448 struct rtw89_btc *btc = &rtwdev->btc; 14449 const struct rtw89_btc_ver *btc_ver_def; 14450 const struct rtw89_fw_suit *fw_suit; 14451 u32 suit_ver_code; 14452 int i; 14453 14454 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 14455 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 14456 14457 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 14458 btc_ver_def = &rtw89_btc_ver_defs[i]; 14459 14460 if (chip->chip_id != btc_ver_def->chip_id) 14461 continue; 14462 14463 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 14464 btc->ver = btc_ver_def; 14465 goto out; 14466 } 14467 } 14468 14469 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 14470 14471 out: 14472 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 14473 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 14474 } 14475 14476 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms) 14477 { 14478 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt0.link_info; 14479 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 14480 14481 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) 14482 return; 14483 14484 if (!a2dp.exist) 14485 return; 14486 14487 fsleep(ms * 1000); 14488 } 14489 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time); 14490 14491 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state) 14492 { 14493 rtwdev->btc.cx.wl.rfk_info.con_rfk = state; 14494 } 14495 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk); 14496