2024-03-12 01:38:39

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 0/6] wifi: rtw89: add BT-coexistence materials for 8922A and enable 8922AE

The more BT-coexistence materials are added by this patchset to have
initial basic functions, and WiFi features of STA, AP and monitor modes
are also ready now, so we can enable 8922AE.

Since new files are added to Kconfig/Makefile, apply checkers of sparse
and smatch to this patchset, and no any error/warning is reported.

v2:
- (patch 1/6) fix unused-but-set-variable warning reported by
kernel test robot <[email protected]>.

Ching-Te Ku (5):
wifi: rtw89: coex: Add WiFi role info format version 8
wifi: rtw89: coex: Add antenna setting function for RTL8922A
wifi: rtw89: coex: Add TDMA version 7
wifi: rtw89: coex: Add TDMA slot parameter setting version 7
wifi: rtw89: 8922a: update chip parameter for coex

Ping-Ke Shih (1):
wifi: rtw89: 8922a: add 8922ae to Makefile and Kconfig

drivers/net/wireless/realtek/rtw89/Kconfig | 15 +
drivers/net/wireless/realtek/rtw89/Makefile | 12 +-
drivers/net/wireless/realtek/rtw89/coex.c | 964 ++++++++++++++++--
drivers/net/wireless/realtek/rtw89/coex.h | 72 ++
drivers/net/wireless/realtek/rtw89/core.h | 108 +-
drivers/net/wireless/realtek/rtw89/fw.c | 42 +
drivers/net/wireless/realtek/rtw89/fw.h | 27 +
drivers/net/wireless/realtek/rtw89/rtw8922a.c | 156 ++-
8 files changed, 1285 insertions(+), 111 deletions(-)

--
2.25.1



2024-03-12 01:38:50

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 1/6] wifi: rtw89: coex: Add WiFi role info format version 8

From: Ching-Te Ku <[email protected]>

In order to control the hardware band and related protocol control,
add version 8 format and related logic to control the mechanism.

Signed-off-by: Ching-Te Ku <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.c | 460 +++++++++++++++++-
drivers/net/wireless/realtek/rtw89/coex.h | 19 +
drivers/net/wireless/realtek/rtw89/core.h | 62 +++
drivers/net/wireless/realtek/rtw89/fw.c | 42 ++
drivers/net/wireless/realtek/rtw89/fw.h | 27 +
drivers/net/wireless/realtek/rtw89/rtw8922a.c | 5 +
6 files changed, 590 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index d9b66d43f32e..955664fbcbc2 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -12,6 +12,7 @@

#define RTW89_COEX_VERSION 0x07000113
#define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
+#define BTC_E2G_LIMIT_DEF 80

enum btc_fbtc_tdma_template {
CXTD_OFF = 0x0,
@@ -133,7 +134,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
.fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
.fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
.fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
- .fwlrole = 2, .frptmap = 7, .fcxctrl = 7, .fcxinit = 7,
+ .fwlrole = 8, .frptmap = 7, .fcxctrl = 7, .fcxinit = 7,
.drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6,
},
{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
@@ -739,7 +740,7 @@ static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
- struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
+ struct rtw89_btc_wl_link_info *wl_linfo;
u8 i;

rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
@@ -761,10 +762,13 @@ static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
if (type & BTC_RESET_DM) {
memset(&btc->dm, 0, sizeof(btc->dm));
memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
-
- for (i = 0; i < RTW89_PORT_NUM; i++)
- memset(wl_linfo[i].rssi_state, 0,
- sizeof(wl_linfo[i].rssi_state));
+ for (i = 0; i < RTW89_PORT_NUM; i++) {
+ if (btc->ver->fwlrole == 8)
+ wl_linfo = &wl->rlink_info[i][0];
+ else
+ wl_linfo = &wl->link_info[i];
+ memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
+ }

/* set the slot_now table to original */
btc->dm.tdma_now = t_def[CXTD_OFF];
@@ -2622,25 +2626,35 @@ static bool _check_freerun(struct rtw89_dev *rtwdev)
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
+ struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
union rtw89_btc_module_info *md = &btc->mdinfo;
const struct rtw89_btc_ver *ver = btc->ver;
- u8 isolation;
+ u8 isolation, connect_cnt = 0;

if (ver->fcxinit == 7)
isolation = md->md_v7.ant.isolation;
else
isolation = md->md.ant.isolation;

+ if (ver->fwlrole == 0)
+ connect_cnt = wl_rinfo->connect_cnt;
+ else if (ver->fwlrole == 1)
+ connect_cnt = wl_rinfo_v1->connect_cnt;
+ else if (ver->fwlrole == 2)
+ connect_cnt = wl_rinfo_v2->connect_cnt;
+ else if (ver->fwlrole == 8)
+ connect_cnt = wl_rinfo_v8->connect_cnt;
+
if (btc->ant_type == BTC_ANT_SHARED) {
btc->dm.trx_para_level = 0;
return false;
}

/* The below is dedicated antenna case */
- if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX ||
- wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) {
+ if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
btc->dm.trx_para_level = 5;
return true;
}
@@ -3508,13 +3522,21 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
struct rtw89_btc_bt_info *bt = &cx->bt;
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
+ bool dbcc_chg = false;
u32 ant_path_type;

ant_path_type = ((phy_map << 8) + type);

+ if (btc->ver->fwlrole == 1)
+ dbcc_chg = wl->role_info_v1.dbcc_chg;
+ else if (btc->ver->fwlrole == 2)
+ dbcc_chg = wl->role_info_v2.dbcc_chg;
+ else if (btc->ver->fwlrole == 8)
+ dbcc_chg = wl->role_info_v8.dbcc_chg;
+
if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
- btc->dm.run_reason == BTC_RSN_CMD_SET_COEX)
+ btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
force_exec = FC_EXEC;

if (!force_exec && ant_path_type == dm->set_ant_path) {
@@ -3641,7 +3663,7 @@ static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
if (wl->status.map.rf_off || btc->dm.bt_only) {
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
- if (wl->role_info.link_mode == BTC_WLINK_5G)
+ if (mode == BTC_WLINK_5G)
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
else
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
@@ -4223,7 +4245,10 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
u16 enable = iter_data->enable;
bool reenable = iter_data->reenable;

- plink = &wl->link_info[port];
+ if (btc->ver->fwlrole == 8)
+ plink = &wl->rlink_info[port][0];
+ else
+ plink = &wl->link_info[port];

rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): port = %d\n", __func__, port);
@@ -4276,6 +4301,7 @@ static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
struct rtw89_txtime_data data = {.rtwdev = rtwdev};
u8 mode, igno_bt, tx_retry;
u32 tx_time;
@@ -4291,6 +4317,8 @@ static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
mode = wl_rinfo_v1->link_mode;
else if (ver->fwlrole == 2)
mode = wl_rinfo_v2->link_mode;
+ else if (ver->fwlrole == 8)
+ mode = wl_rinfo_v8->link_mode;
else
return;

@@ -4348,6 +4376,7 @@ static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
bool bt_hi_lna_rx = false;
u8 mode;
@@ -4358,6 +4387,8 @@ static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
mode = wl_rinfo_v1->link_mode;
else if (ver->fwlrole == 2)
mode = wl_rinfo_v2->link_mode;
+ else if (ver->fwlrole == 8)
+ mode = wl_rinfo_v8->link_mode;
else
return;

@@ -4695,6 +4726,31 @@ static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
}

+static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ u16 policy_type = BTC_CXP_OFF_BT;
+
+ if (btc->ant_type == BTC_ANT_SHARED) {
+ if (wl->status.map._4way)
+ policy_type = BTC_CXP_OFFE_WL;
+ else if (bt->link_info.status.map.connect == 0)
+ policy_type = BTC_CXP_OFFE_2GISOB;
+ else
+ policy_type = BTC_CXP_OFFE_2GBWISOB;
+ } else {
+ policy_type = BTC_CXP_OFF_EQ0;
+ }
+
+ dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
+
+ _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
+ _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
+}
+
static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
@@ -5287,6 +5343,312 @@ static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
#define BTC_CHK_HANG_MAX 3
#define BTC_SCB_INV_VALUE GENMASK(31, 0)

+static u8 _get_role_link_mode(u8 role)
+{
+ switch (role) {
+ case RTW89_WIFI_ROLE_STATION:
+ return BTC_WLINK_2G_STA;
+ case RTW89_WIFI_ROLE_P2P_GO:
+ return BTC_WLINK_2G_GO;
+ case RTW89_WIFI_ROLE_P2P_CLIENT:
+ return BTC_WLINK_2G_GC;
+ case RTW89_WIFI_ROLE_AP:
+ return BTC_WLINK_2G_AP;
+ default:
+ return BTC_WLINK_OTHER;
+ }
+}
+
+static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
+ const struct rtw89_btc_chdef *r2)
+{
+ if (r1->chan != r2->chan) { /* primary ch is different */
+ return false;
+ } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
+ r2->bw == RTW89_CHANNEL_WIDTH_40) {
+ if (r1->offset != r2->offset)
+ return false;
+ }
+ return true;
+}
+
+static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
+ u8 *phy, u8 *role, u8 *dbcc_2g_phy)
+{
+ struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
+ bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
+ u8 j, k, dbcc_2g_cid, dbcc_2g_cid2;
+
+ /* find out the 2G-PHY by connect-id ->ch */
+ for (j = 0; j < wl_rinfo->connect_cnt; j++) {
+ if (ch[j].center_ch <= 14) {
+ is_2g_ch_exist = true;
+ break;
+ }
+ }
+
+ /* If no any 2G-port exist, it's impossible because 5G-exclude */
+ if (!is_2g_ch_exist)
+ return BTC_WLINK_OTHER;
+
+ dbcc_2g_cid = j;
+ *dbcc_2g_phy = phy[dbcc_2g_cid];
+
+ /* connect_cnt <= 2 */
+ if (wl_rinfo->connect_cnt < BTC_TDMA_WLROLE_MAX)
+ return (_get_role_link_mode((role[dbcc_2g_cid])));
+
+ /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
+ for (k = 0; k < wl_rinfo->connect_cnt; k++) {
+ if (k == dbcc_2g_cid)
+ continue;
+
+ if (phy[k] == *dbcc_2g_phy) {
+ is_multi_role_in_2g_phy = true;
+ dbcc_2g_cid2 = k;
+ break;
+ }
+ }
+
+ /* Single-role in 2G-PHY */
+ if (!is_multi_role_in_2g_phy)
+ return (_get_role_link_mode(role[dbcc_2g_cid]));
+
+ /* 2-role in 2G-PHY */
+ if (ch[dbcc_2g_cid2].center_ch > 14)
+ return BTC_WLINK_25G_MCC;
+ else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
+ return BTC_WLINK_2G_SCC;
+ else
+ return BTC_WLINK_2G_MCC;
+}
+
+static void _update_role_link_mode(struct rtw89_dev *rtwdev,
+ bool client_joined, u32 noa)
+{
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &rtwdev->btc.cx.wl.role_info_v8;
+ u32 type = BTC_WLMROLE_NONE, dur = 0;
+ u32 wl_role = wl_rinfo->role_map;
+
+ /* if no client_joined, don't care P2P-GO/AP role */
+ if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
+ (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
+ if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC) {
+ wl_rinfo->link_mode = BTC_WLINK_2G_STA;
+ wl_rinfo->connect_cnt--;
+ } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
+ wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
+ wl_rinfo->link_mode = BTC_WLINK_NOLINK;
+ wl_rinfo->connect_cnt--;
+ }
+ }
+
+ /* Identify 2-Role type */
+ if (wl_rinfo->connect_cnt >= 2 &&
+ (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
+ wl_rinfo->link_mode == BTC_WLINK_2G_MCC ||
+ wl_rinfo->link_mode == BTC_WLINK_25G_MCC ||
+ wl_rinfo->link_mode == BTC_WLINK_5G)) {
+ if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
+ (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
+ type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
+ else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
+ type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
+ else
+ type = BTC_WLMROLE_STA_STA;
+
+ dur = noa;
+ }
+
+ wl_rinfo->mrole_type = type;
+ wl_rinfo->mrole_noa_duration = dur;
+}
+
+static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
+ enum btc_role_state state)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
+ struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
+ bool client_joined = false, b2g = false, b5g = false;
+ u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
+ u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
+ u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0;
+ u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0;
+ struct rtw89_btc_wl_link_info *wl_linfo;
+ struct rtw89_btc_wl_rlink *rlink = NULL;
+ u8 dbcc_2g_phy = RTW89_PHY_0;
+ u8 mode = BTC_WLINK_NOLINK;
+ u32 noa_dur = 0;
+
+ if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1)
+ return;
+
+ /* Extract wl->link_info[role_id][rlink_id] to wl->role_info
+ * role_id: role index
+ * rlink_id: rlink index (= HW-band index)
+ * pid: port_index
+ */
+
+ wl_linfo = &wl->rlink_info[role_id][rlink_id];
+ if (wl_linfo->connected == MLME_LINKING)
+ return;
+
+ rlink = &wl_rinfo->rlink[role_id][rlink_id];
+ rlink->role = wl_linfo->role;
+ rlink->active = wl_linfo->active; /* Doze or not */
+ rlink->pid = wl_linfo->pid;
+ rlink->phy = wl_linfo->phy;
+ rlink->rf_band = wl_linfo->band;
+ rlink->ch = wl_linfo->ch;
+ rlink->bw = wl_linfo->bw;
+ rlink->noa = wl_linfo->noa;
+ rlink->noa_dur = wl_linfo->noa_duration / 1000;
+ rlink->client_cnt = wl_linfo->client_cnt;
+ rlink->mode = wl_linfo->mode;
+
+ switch (wl_linfo->connected) {
+ case MLME_NO_LINK:
+ rlink->connected = 0;
+ if (rlink->role == RTW89_WIFI_ROLE_STATION)
+ btc->dm.leak_ap = 0;
+ break;
+ case MLME_LINKED:
+ rlink->connected = 1;
+ break;
+ default:
+ return;
+ }
+
+ wl->is_5g_hi_channel = false;
+ wl->bg_mode = false;
+ wl_rinfo->role_map = 0;
+ wl_rinfo->p2p_2g = 0;
+ memset(cid_ch, 0, sizeof(cid_ch));
+
+ for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
+ for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
+ rlink = &wl_rinfo->rlink[i][j];
+
+ if (!rlink->active || !rlink->connected)
+ continue;
+
+ cnt++;
+ wl_rinfo->role_map |= BIT(rlink->role);
+
+ /* only if client connect for p2p-Go/AP */
+ if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
+ rlink->role == RTW89_WIFI_ROLE_AP) &&
+ rlink->client_cnt > 1)
+ client_joined = true;
+
+ /* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/
+ if (rlink->rf_band == RTW89_BAND_2G &&
+ (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT))
+ wl_rinfo->p2p_2g = 1;
+
+ /* only one noa-role exist */
+ if (rlink->noa && rlink->noa_dur > 0)
+ noa_dur = rlink->noa_dur;
+
+ /* for WL 5G-Rx interfered with BT issue */
+ if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
+ wl->is_5g_hi_channel = 1;
+
+ if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
+ (rlink->mode & BIT(BTC_WL_MODE_11G)))
+ wl->bg_mode = 1;
+
+ if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT)
+ continue;
+
+ cid_ch[cnt - 1] = wl_linfo->chdef;
+ cid_phy[cnt - 1] = rlink->phy;
+ cid_role[cnt - 1] = rlink->role;
+
+ if (rlink->rf_band != RTW89_BAND_2G) {
+ cnt_5g++;
+ b5g = true;
+ } else {
+ cnt_2g++;
+ b2g = true;
+ }
+ }
+ }
+
+ if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
+ rtw89_warn(rtwdev, "not support MLO feature yet");
+ } else {
+ dbcc_en = rtwdev->dbcc_en;
+
+ /* Be careful to change the following sequence!! */
+ if (cnt == 0) {
+ mode = BTC_WLINK_NOLINK;
+ } else if (!b2g && b5g) {
+ mode = BTC_WLINK_5G;
+ } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
+ mode = BTC_WLINK_2G_NAN;
+ } else if (cnt > BTC_TDMA_WLROLE_MAX) {
+ mode = BTC_WLINK_OTHER;
+ } else if (dbcc_en) {
+ mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role,
+ &dbcc_2g_phy);
+ } else if (b2g && b5g && cnt == 2) {
+ mode = BTC_WLINK_25G_MCC;
+ } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
+ if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
+ mode = BTC_WLINK_2G_SCC;
+ else
+ mode = BTC_WLINK_2G_MCC;
+ } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
+ mode = _get_role_link_mode(cid_role[0]);
+ }
+ }
+
+ wl_rinfo->link_mode = mode;
+ wl_rinfo->connect_cnt = cnt;
+ if (wl_rinfo->connect_cnt == 0)
+ wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
+ _update_role_link_mode(rtwdev, client_joined, noa_dur);
+
+ wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
+ if (wl_rinfo->dbcc_en != dbcc_en) {
+ wl_rinfo->dbcc_en = dbcc_en;
+ wl_rinfo->dbcc_chg = 1;
+ btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
+ } else {
+ wl_rinfo->dbcc_chg = 0;
+ }
+
+ if (wl_rinfo->dbcc_en) {
+ memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info));
+
+ if (mode == BTC_WLINK_5G) {
+ pta_req_band = RTW89_PHY_0;
+ wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
+ wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
+ } else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) {
+ pta_req_band = RTW89_PHY_1;
+ wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
+ wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
+ } else {
+ pta_req_band = RTW89_PHY_0;
+ wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G;
+ wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G;
+ }
+ _update_dbcc_band(rtwdev, RTW89_PHY_0);
+ _update_dbcc_band(rtwdev, RTW89_PHY_1);
+ }
+
+ wl_rinfo->pta_req_band = pta_req_band;
+ _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
+}
+
void rtw89_coex_act1_work(struct work_struct *work)
{
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
@@ -5445,6 +5807,7 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
u8 mode, igno_bt, always_freerun;

lockdep_assert_held(&rtwdev->mutex);
@@ -5459,6 +5822,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
mode = wl_rinfo_v1->link_mode;
else if (ver->fwlrole == 2)
mode = wl_rinfo_v2->link_mode;
+ else if (ver->fwlrole == 8)
+ mode = wl_rinfo_v8->link_mode;
else
return;

@@ -5605,6 +5970,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
_action_wl_2g_scc_v1(rtwdev);
else if (ver->fwlrole == 2)
_action_wl_2g_scc_v2(rtwdev);
+ else if (ver->fwlrole == 8)
+ _action_wl_2g_scc_v8(rtwdev);
break;
case BTC_WLINK_2G_MCC:
bt->scan_rx_low_pri = true;
@@ -5956,6 +6323,22 @@ static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
return rssi_level;
}

+static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
+{
+ u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
+ u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
+
+ if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
+ zb_tbl0 = 0xffffffff;
+ zb_tbl1 = 0xffffffff;
+ } else if (mode == BTC_WLINK_25G_MCC) {
+ zb_tbl0 = 0xffffffff; /* for E5G slot */
+ zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
+ }
+ rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
+ rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
+}
+
#define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)

static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
@@ -6093,13 +6476,6 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
}

-enum btc_wl_mode {
- BTC_WL_MODE_HT = 0,
- BTC_WL_MODE_VHT = 1,
- BTC_WL_MODE_HE = 2,
- BTC_WL_MODE_NUM,
-};
-
void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta, enum btc_role_state state)
{
@@ -6112,7 +6488,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_wl_link_info r = {0};
struct rtw89_btc_wl_link_info *wlinfo = NULL;
- u8 mode = 0;
+ u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;

rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -6162,6 +6538,10 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
r.band = chan->band_type;
r.ch = chan->channel;
r.bw = chan->band_width;
+ r.chdef.band = chan->band_type;
+ r.chdef.center_ch = chan->channel;
+ r.chdef.bw = chan->band_width;
+ r.chdef.chan = chan->primary_channel;
ether_addr_copy(r.mac_addr, rtwvif->mac_addr);

if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
@@ -6171,13 +6551,37 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif

wlinfo = &wl->link_info[r.pid];

- memcpy(wlinfo, &r, sizeof(*wlinfo));
- if (ver->fwlrole == 0)
+ rlink_id = 0; /* to do */
+ if (ver->fwlrole == 0) {
+ *wlinfo = r;
_update_wl_info(rtwdev);
- else if (ver->fwlrole == 1)
+ } else if (ver->fwlrole == 1) {
+ *wlinfo = r;
_update_wl_info_v1(rtwdev);
- else if (ver->fwlrole == 2)
+ } else if (ver->fwlrole == 2) {
+ *wlinfo = r;
_update_wl_info_v2(rtwdev);
+ } else if (ver->fwlrole == 8) {
+ wlinfo = &wl->rlink_info[r.pid][rlink_id];
+ *wlinfo = r;
+ link_mode_ori = wl->role_info_v8.link_mode;
+ pta_req_mac_ori = wl->pta_req_mac;
+ _update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
+
+ if (wl->role_info_v8.link_mode != link_mode_ori) {
+ wl->role_info_v8.link_mode_chg = 1;
+ if (ver->fcxinit == 7)
+ wa_type = btc->mdinfo.md_v7.wa_type;
+ else
+ wa_type = btc->mdinfo.md.wa_type;
+
+ if (wa_type & BTC_WA_HFP_ZB)
+ _update_zb_coex_tbl(rtwdev);
+ }
+
+ if (wl->pta_req_mac != pta_req_mac_ori)
+ wl->pta_reg_mac_chg = 1;
+ }

if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
wlinfo->connected == MLME_NO_LINK)
@@ -6715,7 +7119,10 @@ static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
}

for (i = 0; i < RTW89_PORT_NUM; i++) {
- plink = &btc->cx.wl.link_info[i];
+ if (btc->ver->fwlrole == 8)
+ plink = &btc->cx.wl.rlink_info[i][0];
+ else
+ plink = &btc->cx.wl.link_info[i];

if (!plink->active)
continue;
@@ -6760,6 +7167,7 @@ static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
u8 mode;

if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
@@ -6773,6 +7181,8 @@ static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
mode = wl_rinfo_v1->link_mode;
else if (ver->fwlrole == 2)
mode = wl_rinfo_v2->link_mode;
+ else if (ver->fwlrole == 8)
+ mode = wl_rinfo_v8->link_mode;
else
return;

diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h
index 13303830684e..32c95022d6ee 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.h
+++ b/drivers/net/wireless/realtek/rtw89/coex.h
@@ -201,6 +201,25 @@ enum btc_3cx_type {
BTC_3CX_MAX,
};

+enum btc_chip_feature {
+ BTC_FEAT_PTA_ONOFF_CTRL = BIT(0), /* on/off ctrl by HW (not 0x73[2]) */
+ BTC_FEAT_NONBTG_GWL_THRU = BIT(1), /* non-BTG GNT_WL!=0 if GNT_BT = 1 */
+ BTC_FEAT_WLAN_ACT_MUX = BIT(2), /* separate wlan_act/gnt mux */
+ BTC_FEAT_NEW_BBAPI_FLOW = BIT(3), /* new btg_ctrl/pre_agc_ctrl */
+ BTC_FEAT_MLO_SUPPORT = BIT(4),
+ BTC_FEAT_H2C_MACRO = BIT(5),
+};
+
+enum btc_wl_mode {
+ BTC_WL_MODE_11B = 0,
+ BTC_WL_MODE_11A = 1,
+ BTC_WL_MODE_11G = 2,
+ BTC_WL_MODE_HT = 3,
+ BTC_WL_MODE_VHT = 4,
+ BTC_WL_MODE_HE = 5,
+ BTC_WL_MODE_NUM,
+};
+
void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 2e854c9af709..8617c65ff60e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -799,6 +799,7 @@ struct rtw89_rx_phy_ppdu {
enum rtw89_mac_idx {
RTW89_MAC_0 = 0,
RTW89_MAC_1 = 1,
+ RTW89_MAC_NUM,
};

enum rtw89_phy_idx {
@@ -1230,6 +1231,13 @@ enum rtw89_btc_wl_state_cnt {
BTC_WCNT_RFK_REJECT,
BTC_WCNT_RFK_TIMEOUT,
BTC_WCNT_CH_UPDATE,
+ BTC_WCNT_DBCC_ALL_2G,
+ BTC_WCNT_DBCC_CHG,
+ BTC_WCNT_RX_OK_LAST,
+ BTC_WCNT_RX_OK_LAST2S,
+ BTC_WCNT_RX_ERR_LAST,
+ BTC_WCNT_RX_ERR_LAST2S,
+ BTC_WCNT_RX_LAST,
BTC_WCNT_NUM
};

@@ -1349,6 +1357,14 @@ struct rtw89_traffic_stats {
u16 rx_rate;
};

+struct rtw89_btc_chdef {
+ u8 center_ch;
+ u8 band;
+ u8 chan;
+ enum rtw89_sc_offset offset;
+ enum rtw89_bandwidth bw;
+};
+
struct rtw89_btc_statistic {
u8 rssi; /* 0%~110% (dBm = rssi -110) */
struct rtw89_traffic_stats traffic;
@@ -1357,6 +1373,7 @@ struct rtw89_btc_statistic {
#define BTC_WL_RSSI_THMAX 4

struct rtw89_btc_wl_link_info {
+ struct rtw89_btc_chdef chdef;
struct rtw89_btc_statistic stat;
enum rtw89_tfc_dir dir;
u8 rssi_state[BTC_WL_RSSI_THMAX];
@@ -1370,6 +1387,7 @@ struct rtw89_btc_wl_link_info {
u8 phy;
u8 dtim_period;
u8 mode;
+ u8 tx_1ss_limit;

u8 mac_id;
u8 tx_retry;
@@ -1379,6 +1397,7 @@ struct rtw89_btc_wl_link_info {
u32 tx_time;
u32 client_cnt;
u32 rx_rate_drop_cnt;
+ u32 noa_duration;

u32 active: 1;
u32 noa: 1;
@@ -1589,6 +1608,42 @@ struct rtw89_btc_wl_role_info_v2 { /* struct size must be n*4 bytes */
u32 rsvd: 27;
};

+struct rtw89_btc_wl_rlink { /* H2C info, struct size must be n*4 bytes */
+ u8 connected;
+ u8 pid;
+ u8 phy;
+ u8 noa;
+
+ u8 rf_band; /* enum band_type RF band: 2.4G/5G/6G */
+ u8 active; /* 0:rlink is under doze */
+ u8 bw; /* enum channel_width */
+ u8 role; /*enum role_type */
+
+ u8 ch;
+ u8 noa_dur; /* ms */
+ u8 client_cnt; /* for Role = P2P-Go/AP */
+ u8 mode; /* wifi protocol */
+} __packed;
+
+#define RTW89_BE_BTC_WL_MAX_ROLE_NUMBER 6
+struct rtw89_btc_wl_role_info_v8 { /* H2C info, struct size must be n*4 bytes */
+ u8 connect_cnt;
+ u8 link_mode;
+ u8 link_mode_chg;
+ u8 p2p_2g;
+
+ u8 pta_req_band;
+ u8 dbcc_en; /* 1+1 and 2.4G-included */
+ u8 dbcc_chg;
+ u8 dbcc_2g_phy; /* which phy operate in 2G, HW_PHY_0 or HW_PHY_1 */
+
+ struct rtw89_btc_wl_rlink rlink[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
+
+ u32 role_map;
+ u32 mrole_type; /* btc_wl_mrole_type */
+ u32 mrole_noa_duration; /* ms */
+} __packed;
+
struct rtw89_btc_wl_ver_info {
u32 fw_coex; /* match with which coex_ver */
u32 fw;
@@ -1724,12 +1779,14 @@ struct rtw89_btc_wl_nhm {

struct rtw89_btc_wl_info {
struct rtw89_btc_wl_link_info link_info[RTW89_PORT_NUM];
+ struct rtw89_btc_wl_link_info rlink_info[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
struct rtw89_btc_wl_rfk_info rfk_info;
struct rtw89_btc_wl_ver_info ver_info;
struct rtw89_btc_wl_afh_info afh_info;
struct rtw89_btc_wl_role_info role_info;
struct rtw89_btc_wl_role_info_v1 role_info_v1;
struct rtw89_btc_wl_role_info_v2 role_info_v2;
+ struct rtw89_btc_wl_role_info_v8 role_info_v8;
struct rtw89_btc_wl_scan_info scan_info;
struct rtw89_btc_wl_dbcc_info dbcc_info;
struct rtw89_btc_rf_para rf_para;
@@ -1740,7 +1797,10 @@ struct rtw89_btc_wl_info {
u8 rssi_level;
u8 cn_report;
u8 coex_mode;
+ u8 pta_req_mac;

+ bool is_5g_hi_channel;
+ bool pta_reg_mac_chg;
bool bg_mode;
bool scbd_change;
u32 scbd;
@@ -2569,6 +2629,8 @@ struct rtw89_btc_dm {

u32 update_slot_map;
u32 set_ant_path;
+ u32 e2g_slot_limit;
+ u32 e2g_slot_nulltx_time;

u32 wl_only: 1;
u32 wl_fw_cx_offload: 1;
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 185cd339c085..f27486d35cbc 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -4120,6 +4120,48 @@ int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type)
return ret;
}

+int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_role_info_v8 *role = &btc->cx.wl.role_info_v8;
+ struct rtw89_h2c_cxrole_v8 *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cxrole_v8 *)skb->data;
+
+ h2c->hdr.type = type;
+ h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7;
+ memcpy(&h2c->_u8, role, sizeof(h2c->_u8));
+ h2c->_u32.role_map = cpu_to_le32(role->role_map);
+ h2c->_u32.mrole_type = cpu_to_le32(role->mrole_type);
+ h2c->_u32.mrole_noa_duration = cpu_to_le32(role->mrole_noa_duration);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, BTFC_SET,
+ SET_DRV_INFO, 0, 0,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
#define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type)
{
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 44311f65b4fa..d7666c3d6a89 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -2395,6 +2395,32 @@ struct rtw89_h2c_cxctrl_v7 {
#define H2C_LEN_CXDRVHDR sizeof(struct rtw89_h2c_cxhdr)
#define H2C_LEN_CXDRVHDR_V7 sizeof(struct rtw89_h2c_cxhdr_v7)

+struct rtw89_btc_wl_role_info_v8_u8 {
+ u8 connect_cnt;
+ u8 link_mode;
+ u8 link_mode_chg;
+ u8 p2p_2g;
+
+ u8 pta_req_band;
+ u8 dbcc_en;
+ u8 dbcc_chg;
+ u8 dbcc_2g_phy;
+
+ struct rtw89_btc_wl_rlink rlink[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
+} __packed;
+
+struct rtw89_btc_wl_role_info_v8_u32 {
+ __le32 role_map;
+ __le32 mrole_type;
+ __le32 mrole_noa_duration;
+} __packed;
+
+struct rtw89_h2c_cxrole_v8 {
+ struct rtw89_h2c_cxhdr hdr;
+ struct rtw89_btc_wl_role_info_v8_u8 _u8;
+ struct rtw89_btc_wl_role_info_v8_u32 _u32;
+} __packed;
+
struct rtw89_h2c_cxinit {
struct rtw89_h2c_cxhdr hdr;
u8 ant_type;
@@ -4568,6 +4594,7 @@ int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type);
+int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_ctrl_v7(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_trx(struct rtw89_dev *rtwdev, u8 type);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 367459bd1345..948eeb6755fd 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2436,6 +2436,11 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.efuse_blocks = rtw8922a_efuse_blocks,
.phycap_addr = 0x1700,
.phycap_size = 0x38,
+ .para_ver = 0xf,
+ .wlcx_desired = 0x07110000,
+ .btcx_desired = 0x7,
+ .scbd = 0x1,
+ .mailbox = 0x1,

.ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) |
BIT(RTW89_PS_MODE_CLK_GATED) |
--
2.25.1


2024-03-12 01:39:03

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 6/6] wifi: rtw89: 8922a: add 8922ae to Makefile and Kconfig

Add 8922AE to Makefile and Kconfig. Currently, it can support STA, AP and
monitor modes with good performance. Implemented initial BT-coexistence
function only, and will to fine tune this component.

Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/Kconfig | 15 +++++++++++++++
drivers/net/wireless/realtek/rtw89/Makefile | 12 +++++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig
index 90ffbab7cc4c..eaea4eaeb361 100644
--- a/drivers/net/wireless/realtek/rtw89/Kconfig
+++ b/drivers/net/wireless/realtek/rtw89/Kconfig
@@ -28,6 +28,9 @@ config RTW89_8852B
config RTW89_8852C
tristate

+config RTW89_8922A
+ tristate
+
config RTW89_8851BE
tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
@@ -72,6 +75,18 @@ config RTW89_8852CE

802.11ax PCIe wireless network (Wi-Fi 6E) adapter

+config RTW89_8922AE
+ tristate "Realtek 8922AE PCI wireless network (Wi-Fi 7) adapter"
+ depends on PCI
+ select RTW89_CORE
+ select RTW89_PCI
+ select RTW89_8922A
+ help
+ Select this option will enable support for 8922AE chipset
+
+ 802.11be PCIe wireless network (Wi-Fi 7) adapter
+ supporting 2x2 2GHz/5GHz/6GHz 4096-QAM 160MHz channels.
+
config RTW89_DEBUG
bool

diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile
index 41940099af1b..86a553fb0136 100644
--- a/drivers/net/wireless/realtek/rtw89/Makefile
+++ b/drivers/net/wireless/realtek/rtw89/Makefile
@@ -4,10 +4,13 @@ obj-$(CONFIG_RTW89_CORE) += rtw89_core.o
rtw89_core-y += core.o \
mac80211.o \
mac.o \
+ mac_be.o \
phy.o \
+ phy_be.o \
fw.o \
cam.o \
efuse.o \
+ efuse_be.o \
regd.o \
sar.o \
coex.o \
@@ -54,8 +57,15 @@ rtw89_8852c-objs := rtw8852c.o \
obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
rtw89_8852ce-objs := rtw8852ce.o

+obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o
+rtw89_8922a-objs := rtw8922a.o \
+ rtw8922a_rfk.o
+
+obj-$(CONFIG_RTW89_8922AE) += rtw89_8922ae.o
+rtw89_8922ae-objs := rtw8922ae.o
+
rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o

obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
-rtw89_pci-y := pci.o
+rtw89_pci-y := pci.o pci_be.o

--
2.25.1


2024-03-12 01:39:05

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 3/6] wifi: rtw89: coex: Add TDMA version 7

From: Ching-Te Ku <[email protected]>

In order to packet up the slots information, the TLV header has updated.
TDMA also use the TLV header to packet up to H2C, so upgrade to version 7.

Signed-off-by: Ching-Te Ku <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 57bf23d1adc7..306846f3ef11 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -219,6 +219,13 @@ struct rtw89_btc_btf_tlv {
u8 val[];
} __packed;

+struct rtw89_btc_btf_tlv_v7 {
+ u8 type;
+ u8 ver;
+ u8 len;
+ u8 val[];
+} __packed;
+
enum btc_btf_set_report_en {
RPT_EN_TDMA,
RPT_EN_CYCLE,
@@ -1210,7 +1217,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
if (ver->fcxtdma == 1) {
pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
- } else if (ver->fcxtdma == 3) {
+ } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
} else {
@@ -1486,7 +1493,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
memcmp(&dm->tdma_now,
&pfwinfo->rpt_fbtc_tdma.finfo.v1,
sizeof(dm->tdma_now)));
- else if (ver->fcxtdma == 3)
+ else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
memcmp(&dm->tdma_now,
&pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
@@ -1727,6 +1734,7 @@ static void _parse_btc_report(struct rtw89_dev *rtwdev,
}

#define BTC_TLV_HDR_LEN 2
+#define BTC_TLV_HDR_LEN_V7 3

static void _append_tdma(struct rtw89_dev *rtwdev)
{
@@ -1734,6 +1742,7 @@ static void _append_tdma(struct rtw89_dev *rtwdev)
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_btc_btf_tlv *tlv;
+ struct rtw89_btc_btf_tlv_v7 *tlv_v7;
struct rtw89_btc_fbtc_tdma *v;
struct rtw89_btc_fbtc_tdma_v3 *v3;
u16 len = btc->policy_len;
@@ -1753,6 +1762,13 @@ static void _append_tdma(struct rtw89_dev *rtwdev)
tlv->len = sizeof(*v);
*v = dm->tdma;
btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
+ } else if (ver->fcxtdma == 7) {
+ tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
+ tlv_v7->len = sizeof(dm->tdma);
+ tlv_v7->ver = ver->fcxtdma;
+ tlv_v7->type = CXPOLICY_TDMA;
+ memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
+ btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
} else {
tlv->len = sizeof(*v3);
v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
--
2.25.1


2024-03-12 01:39:13

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 4/6] wifi: rtw89: coex: Add TDMA slot parameter setting version 7

From: Ching-Te Ku <[email protected]>

In order to packet up the slots information, the TLV header has updated.
TDMA slot parameters also use the TLV header to packet up to H2C, so
upgrade to version 7.

Signed-off-by: Ching-Te Ku <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.c | 291 ++++++++++++++++------
drivers/net/wireless/realtek/rtw89/coex.h | 48 ++++
drivers/net/wireless/realtek/rtw89/core.h | 45 +++-
3 files changed, 304 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 306846f3ef11..e4f70d62b32f 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -55,7 +55,6 @@ enum btc_mlme_state {
MLME_LINKED,
};

-#define FCXONESLOT_VER 1
struct btc_fbtc_1slot {
u8 fver;
u8 sid; /* slot id */
@@ -257,6 +256,13 @@ struct rtw89_btc_btf_set_slot_table {
struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
} __packed;

+struct rtw89_btc_btf_set_slot_table_v7 {
+ u8 type;
+ u8 ver;
+ u8 len;
+ struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
+} __packed;
+
struct rtw89_btc_btf_set_mon_reg {
u8 fver;
u8 reg_num;
@@ -1227,8 +1233,15 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_SLOT:
pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
- pfinfo = &pfwinfo->rpt_fbtc_slots.finfo;
- pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
+ if (ver->fcxslots == 1) {
+ pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
+ } else if (ver->fcxslots == 7) {
+ pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
+ } else {
+ goto err;
+ }
pcinfo->req_fver = ver->fcxslots;
break;
case BTC_RPT_TYPE_CYSTA:
@@ -1502,14 +1515,25 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
goto err;
break;
case BTC_RPT_TYPE_SLOT:
- rtw89_debug(rtwdev, RTW89_DBG_BTC,
- "[BTC], %s(): check %d %zu\n",
- __func__, BTC_DCNT_SLOT_NONSYNC,
- sizeof(dm->slot_now));
- _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
- memcmp(dm->slot_now,
- pfwinfo->rpt_fbtc_slots.finfo.slot,
- sizeof(dm->slot_now)));
+ if (ver->fcxslots == 7) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): check %d %zu\n",
+ __func__, BTC_DCNT_SLOT_NONSYNC,
+ sizeof(dm->slot_now.v7));
+ _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
+ memcmp(dm->slot_now.v7,
+ pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
+ sizeof(dm->slot_now.v7)));
+ } else if (ver->fcxslots == 1) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): check %d %zu\n",
+ __func__, BTC_DCNT_SLOT_NONSYNC,
+ sizeof(dm->slot_now.v1));
+ _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
+ memcmp(dm->slot_now.v1,
+ pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
+ sizeof(dm->slot_now.v1)));
+ }
break;
case BTC_RPT_TYPE_CYSTA:
if (ver->fcxcysta == 2) {
@@ -1525,10 +1549,17 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,

/* Check diff time between WL slot and W1/E2G slot */
if (dm->tdma_now.type == CXTDMA_OFF &&
- dm->tdma_now.ext_ctrl == CXECTL_EXT)
- wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur);
- else
- wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+ dm->tdma_now.ext_ctrl == CXECTL_EXT) {
+ if (ver->fcxslots == 1)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
+ else if (ver->fcxslots == 7)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
+ } else {
+ if (ver->fcxslots == 1)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+ else if (ver->fcxslots == 7)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
+ }

if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
@@ -1558,7 +1589,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,

/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
- wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+ if (ver->fcxslots == 1)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+ else if (ver->fcxslots == 7)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
if (wl_slot_real > wl_slot_set) {
diff_t = wl_slot_real - wl_slot_set;
@@ -1599,7 +1633,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,

/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
- wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+ if (ver->fcxslots == 1)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+ else if (ver->fcxslots == 7)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
if (wl_slot_real > wl_slot_set) {
diff_t = wl_slot_real - wl_slot_set;
@@ -1641,7 +1678,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,

/* Check diff time between real WL slot and W1 slot */
if (dm->tdma_now.type == CXTDMA_OFF) {
- wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+ if (ver->fcxslots == 1)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
+ else if (ver->fcxslots == 7)
+ wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);

if (wl_slot_real > wl_slot_set)
@@ -1784,7 +1824,7 @@ static void _append_tdma(struct rtw89_dev *rtwdev)
dm->tdma.ext_ctrl);
}

-static void _append_slot(struct rtw89_dev *rtwdev)
+static void _append_slot_v1(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
@@ -1799,8 +1839,8 @@ static void _append_slot(struct rtw89_dev *rtwdev)

for (i = 0; i < CXST_MAX; i++) {
if (!btc->update_policy_force &&
- !memcmp(&dm->slot[i], &dm->slot_now[i],
- sizeof(dm->slot[i])))
+ !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
+ sizeof(dm->slot.v1[i])))
continue;

len = btc->policy_len;
@@ -1810,14 +1850,14 @@ static void _append_slot(struct rtw89_dev *rtwdev)
tlv->type = CXPOLICY_SLOT;
tlv->len = sizeof(*v);

- v->fver = FCXONESLOT_VER;
+ v->fver = btc->ver->fcxslots;
v->sid = i;
- v->slot = dm->slot[i];
+ v->slot = dm->slot.v1[i];

rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
- __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl,
- dm->slot[i].cxtype);
+ __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
+ dm->slot.v1[i].cxtype);
cnt++;

btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
@@ -1829,6 +1869,71 @@ static void _append_slot(struct rtw89_dev *rtwdev)
__func__, cnt);
}

+static void _append_slot_v7(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ u8 i, cnt = 0;
+ u16 len;
+
+ for (i = 0; i < CXST_MAX; i++) {
+ if (!btc->update_policy_force &&
+ !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
+ sizeof(dm->slot.v7[i])))
+ continue;
+
+ len = btc->policy_len;
+
+ if (!tlv) {
+ if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): buff overflow!\n", __func__);
+ break;
+ }
+
+ tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
+ tlv->type = CXPOLICY_SLOT;
+ tlv->ver = btc->ver->fcxslots;
+ tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
+ len += BTC_TLV_HDR_LEN_V7;
+ }
+
+ if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): buff overflow!\n", __func__);
+ break;
+ }
+
+ btc->policy[len] = i; /* slot-id */
+ memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
+ sizeof(dm->slot.v7[0]));
+ len += tlv->len;
+
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
+ __func__, btc->policy_len, i, dm->slot.v7[i].dur,
+ dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
+ cnt++;
+ btc->policy_len = len; /* update total length */
+ }
+
+ if (cnt > 0)
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
+ __func__, cnt, btc->policy_len);
+}
+
+static void _append_slot(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+
+ if (btc->ver->fcxslots == 7)
+ _append_slot_v7(rtwdev);
+ else
+ _append_slot_v1(rtwdev);
+}
+
static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
{
struct rtw89_btc *btc = &rtwdev->btc;
@@ -1974,6 +2079,45 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
return bit_map;
}

+static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ const struct rtw89_btc_ver *ver = btc->ver;
+ struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
+ struct rtw89_btc_btf_set_slot_table *tbl;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ u16 n, len;
+
+ if (ver->fcxslots == 7) {
+ len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
+ tlv_v7 = kmalloc(len, GFP_KERNEL);
+ if (!tlv_v7)
+ return;
+
+ tlv_v7->type = SET_SLOT_TABLE;
+ tlv_v7->ver = ver->fcxslots;
+ tlv_v7->len = sizeof(dm->slot.v7);
+ memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
+
+ _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
+
+ kfree(tlv_v7);
+ } else {
+ n = struct_size(tbl, tbls, CXST_MAX);
+ tbl = kmalloc(n, GFP_KERNEL);
+ if (!tbl)
+ return;
+
+ tbl->fver = BTF_SET_SLOT_TABLE_VER;
+ tbl->tbl_num = CXST_MAX;
+ memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
+
+ _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
+
+ kfree(tbl);
+ }
+}
+
static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
u32 rpt_map, bool rpt_state)
{
@@ -2010,26 +2154,6 @@ static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
fwinfo->rpt_en_map = val;
}

-static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num,
- struct rtw89_btc_fbtc_slot *s)
-{
- struct rtw89_btc_btf_set_slot_table *tbl;
- u16 n;
-
- n = struct_size(tbl, tbls, num);
- tbl = kmalloc(n, GFP_KERNEL);
- if (!tbl)
- return;
-
- tbl->fver = BTF_SET_SLOT_TABLE_VER;
- tbl->tbl_num = num;
- memcpy(tbl->tbls, s, flex_array_size(tbl, tbls, num));
-
- _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
-
- kfree(tbl);
-}
-
static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -2128,7 +2252,10 @@ static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
btc->policy, btc->policy_len);
if (!ret) {
memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
- memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now));
+ if (btc->ver->fcxslots == 7)
+ memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
+ else
+ memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
}

if (btc->update_policy_force)
@@ -2801,19 +2928,6 @@ static bool _check_freerun(struct rtw89_dev *rtwdev)
#define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
#define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })

-#define _slot_set(btc, sid, dura, tbl, type) \
- do { \
- typeof(sid) _sid = (sid); \
- typeof(btc) _btc = (btc); \
- _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\
- _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \
- _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \
- } while (0)
-
-#define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura)
-#define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl)
-#define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type)
-
struct btc_btinfo_lb2 {
u8 connect: 1;
u8 sco_busy: 1;
@@ -2888,7 +3002,7 @@ void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
- struct rtw89_btc_fbtc_slot *s = dm->slot;
+ struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
u8 type;
u32 tbl_w1, tbl_b1, tbl_b4;

@@ -3199,7 +3313,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
- struct rtw89_btc_fbtc_slot *s = dm->slot;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
@@ -3247,13 +3360,15 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_USERDEF0:
btc->update_policy_force = true;
*t = t_def[CXTD_OFF];
- s[CXST_OFF] = s_def[CXST_OFF];
+ _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+ s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
break;
case BTC_CXP_OFF: /* TDMA off */
_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
*t = t_def[CXTD_OFF];
- s[CXST_OFF] = s_def[CXST_OFF];
+ _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+ s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);

switch (policy_type) {
case BTC_CXP_OFF_BT:
@@ -3294,7 +3409,8 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_OFFB: /* TDMA off + beacon protect */
_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
*t = t_def[CXTD_OFF_B2];
- s[CXST_OFF] = s_def[CXST_OFF];
+ _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+ s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);

switch (policy_type) {
case BTC_CXP_OFFB_BWB0:
@@ -3315,21 +3431,29 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)

switch (policy_type) {
case BTC_CXP_OFFE_DEF:
- s[CXST_E2G] = s_def[CXST_E2G];
- s[CXST_E5G] = s_def[CXST_E5G];
- s[CXST_EBT] = s_def[CXST_EBT];
- s[CXST_ENULL] = s_def[CXST_ENULL];
+ _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
+ s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
+ _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
+ s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
+ _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
+ s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
+ _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
+ s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
break;
case BTC_CXP_OFFE_DEF2:
_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
- s[CXST_E5G] = s_def[CXST_E5G];
- s[CXST_EBT] = s_def[CXST_EBT];
- s[CXST_ENULL] = s_def[CXST_ENULL];
+ _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
+ s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
+ _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
+ s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
+ _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
+ s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
break;
default:
break;
}
- s[CXST_OFF] = s_def[CXST_OFF];
+ _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
+ s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
break;
case BTC_CXP_FIX: /* TDMA Fix-Slot */
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
@@ -6308,8 +6432,8 @@ void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)

_set_init_info(rtwdev);
_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
- rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
btc_fw_set_monreg(rtwdev);
+ rtw89_btc_fw_set_slots(rtwdev);
_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);

@@ -8045,22 +8169,35 @@ static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
- struct rtw89_btc_fbtc_slot *s;
+ u16 dur, cxtype;
+ u32 tbl;
u8 i = 0;

for (i = 0; i < CXST_MAX; i++) {
- s = &dm->slot_now[i];
+ if (btc->ver->fcxslots == 1) {
+ dur = le16_to_cpu(dm->slot_now.v1[i].dur);
+ tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
+ cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
+ } else if (btc->ver->fcxslots == 7) {
+ dur = le16_to_cpu(dm->slot_now.v7[i].dur);
+ tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
+ cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
+ } else {
+ return;
+ }
+
if (i % 5 == 0)
seq_printf(m,
" %-15s : %5s[%03d/0x%x/%d]",
"[slot_list]",
id_to_slot((u32)i),
- s->dur, s->cxtbl, s->cxtype);
+ dur, tbl, cxtype);
else
seq_printf(m,
", %5s[%03d/0x%x/%d]",
id_to_slot((u32)i),
- s->dur, s->cxtbl, s->cxtype);
+ dur, tbl, cxtype);
+
if (i % 5 == 4)
seq_puts(m, "\n");
}
diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h
index 671f52fe8931..43c5e3626121 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.h
+++ b/drivers/net/wireless/realtek/rtw89/coex.h
@@ -8,6 +8,7 @@
#include "core.h"

#define BTC_H2C_MAXLEN 2020
+#define BTC_TLV_SLOT_ID_LEN_V7 1

enum btc_mode {
BTC_MODE_NORMAL,
@@ -285,4 +286,51 @@ static inline u32 rtw89_get_antpath_type(u8 phy_map, u8 type)
return ((phy_map << 8) + type);
}

+static inline
+void _slot_set_le(struct rtw89_btc *btc, u8 sid, __le16 dura, __le32 tbl, __le16 type)
+{
+ if (btc->ver->fcxslots == 1) {
+ btc->dm.slot.v1[sid].dur = dura;
+ btc->dm.slot.v1[sid].cxtbl = tbl;
+ btc->dm.slot.v1[sid].cxtype = type;
+ } else if (btc->ver->fcxslots == 7) {
+ btc->dm.slot.v7[sid].dur = dura;
+ btc->dm.slot.v7[sid].cxtype = type;
+ btc->dm.slot.v7[sid].cxtbl = tbl;
+ }
+}
+
+static inline
+void _slot_set(struct rtw89_btc *btc, u8 sid, u16 dura, u32 tbl, u16 type)
+{
+ _slot_set_le(btc, sid, cpu_to_le16(dura), cpu_to_le32(tbl), cpu_to_le16(type));
+}
+
+static inline
+void _slot_set_dur(struct rtw89_btc *btc, u8 sid, u16 dura)
+{
+ if (btc->ver->fcxslots == 1)
+ btc->dm.slot.v1[sid].dur = cpu_to_le16(dura);
+ else if (btc->ver->fcxslots == 7)
+ btc->dm.slot.v7[sid].dur = cpu_to_le16(dura);
+}
+
+static inline
+void _slot_set_type(struct rtw89_btc *btc, u8 sid, u16 type)
+{
+ if (btc->ver->fcxslots == 1)
+ btc->dm.slot.v1[sid].cxtype = cpu_to_le16(type);
+ else if (btc->ver->fcxslots == 7)
+ btc->dm.slot.v7[sid].cxtype = cpu_to_le16(type);
+}
+
+static inline
+void _slot_set_tbl(struct rtw89_btc *btc, u8 sid, u32 tbl)
+{
+ if (btc->ver->fcxslots == 1)
+ btc->dm.slot.v1[sid].cxtbl = cpu_to_le32(tbl);
+ else if (btc->ver->fcxslots == 7)
+ btc->dm.slot.v7[sid].cxtbl = cpu_to_le32(tbl);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index bc10ebb785a2..fc1ed8612cf1 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -2293,6 +2293,40 @@ struct rtw89_btc_fbtc_slots {
struct rtw89_btc_fbtc_slot slot[CXST_MAX];
} __packed;

+struct rtw89_btc_fbtc_slot_v7 {
+ __le16 dur; /* slot duration */
+ __le16 cxtype;
+ __le32 cxtbl;
+} __packed;
+
+struct rtw89_btc_fbtc_slot_u16 {
+ __le16 dur; /* slot duration */
+ __le16 cxtype;
+ __le16 cxtbl_l16; /* coex table [15:0] */
+ __le16 cxtbl_h16; /* coex table [31:16] */
+} __packed;
+
+struct rtw89_btc_fbtc_1slot_v7 {
+ u8 fver;
+ u8 sid; /* slot id */
+ __le16 rsvd;
+ struct rtw89_btc_fbtc_slot_v7 slot;
+} __packed;
+
+struct rtw89_btc_fbtc_slots_v7 {
+ u8 fver;
+ u8 slot_cnt;
+ u8 rsvd0;
+ u8 rsvd1;
+ struct rtw89_btc_fbtc_slot_u16 slot[CXST_MAX];
+ __le32 update_map;
+} __packed;
+
+union rtw89_btc_fbtc_slots_info {
+ struct rtw89_btc_fbtc_slots v1;
+ struct rtw89_btc_fbtc_slots_v7 v7;
+} __packed;
+
struct rtw89_btc_fbtc_step {
u8 type;
u8 val;
@@ -2611,9 +2645,14 @@ struct rtw89_btc_trx_info {
u32 rx_err_ratio;
};

+union rtw89_btc_fbtc_slot_u {
+ struct rtw89_btc_fbtc_slot v1[CXST_MAX];
+ struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
+};
+
struct rtw89_btc_dm {
- struct rtw89_btc_fbtc_slot slot[CXST_MAX];
- struct rtw89_btc_fbtc_slot slot_now[CXST_MAX];
+ union rtw89_btc_fbtc_slot_u slot;
+ union rtw89_btc_fbtc_slot_u slot_now;
struct rtw89_btc_fbtc_tdma tdma;
struct rtw89_btc_fbtc_tdma tdma_now;
struct rtw89_mac_ax_coex_gnt gnt;
@@ -2754,7 +2793,7 @@ struct rtw89_btc_rpt_fbtc_tdma {

struct rtw89_btc_rpt_fbtc_slots {
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
- struct rtw89_btc_fbtc_slots finfo; /* info from fw */
+ union rtw89_btc_fbtc_slots_info finfo; /* info from fw */
};

struct rtw89_btc_rpt_fbtc_cysta {
--
2.25.1


2024-03-12 01:47:29

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 2/6] wifi: rtw89: coex: Add antenna setting function for RTL8922A

From: Ching-Te Ku <[email protected]>

Because there is new hardware structure and Wi-Fi 7 protocol,
the antenna settings need to concern more complex for Wi-Fi 7
using. The antenna setting included grant control signal, they
decide which MAC/Port or Bluetooth can do traffic.

Signed-off-by: Ching-Te Ku <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.c | 193 +++++++++++++++++++++-
drivers/net/wireless/realtek/rtw89/coex.h | 5 +
drivers/net/wireless/realtek/rtw89/core.h | 1 +
3 files changed, 197 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 955664fbcbc2..57bf23d1adc7 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -311,6 +311,7 @@ enum btc_ant_phase {
BTC_ANT_W25G,
BTC_ANT_FREERUN,
BTC_ANT_WRFK,
+ BTC_ANT_WRFK2,
BTC_ANT_BRFK,
BTC_ANT_MAX
};
@@ -615,6 +616,13 @@ enum btc_ctr_path {
BTC_CTRL_BY_WL
};

+enum btc_wlact_state {
+ BTC_WLACT_HW = 0,
+ BTC_WLACT_SW_LO,
+ BTC_WLACT_SW_HI,
+ BTC_WLACT_MAX,
+};
+
enum btc_wl_max_tx_time {
BTC_MAX_TX_TIME_L1 = 500,
BTC_MAX_TX_TIME_L2 = 1000,
@@ -2247,6 +2255,76 @@ static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_st
rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
}

+static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
+ u8 wl_state, u8 bt_state, u8 wlact_state)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ struct rtw89_mac_ax_gnt *g = dm->gnt.band;
+ u8 i, bt_idx = dm->bt_select + 1;
+
+ if (phy_map > BTC_PHY_ALL)
+ return;
+
+ for (i = 0; i < RTW89_PHY_MAX; i++) {
+ if (!(phy_map & BIT(i)))
+ continue;
+
+ switch (wl_state) {
+ case BTC_GNT_HW:
+ g[i].gnt_wl_sw_en = 0;
+ g[i].gnt_wl = 0;
+ break;
+ case BTC_GNT_SW_LO:
+ g[i].gnt_wl_sw_en = 1;
+ g[i].gnt_wl = 0;
+ break;
+ case BTC_GNT_SW_HI:
+ g[i].gnt_wl_sw_en = 1;
+ g[i].gnt_wl = 1;
+ break;
+ }
+
+ switch (bt_state) {
+ case BTC_GNT_HW:
+ g[i].gnt_bt_sw_en = 0;
+ g[i].gnt_bt = 0;
+ break;
+ case BTC_GNT_SW_LO:
+ g[i].gnt_bt_sw_en = 1;
+ g[i].gnt_bt = 0;
+ break;
+ case BTC_GNT_SW_HI:
+ g[i].gnt_bt_sw_en = 1;
+ g[i].gnt_bt = 1;
+ break;
+ }
+ }
+
+ if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
+ for (i = 0; i < 2; i++) {
+ if (!(bt_idx & BIT(i)))
+ continue;
+
+ switch (wlact_state) {
+ case BTC_WLACT_HW:
+ dm->gnt.bt[i].wlan_act_en = 0;
+ dm->gnt.bt[i].wlan_act = 0;
+ break;
+ case BTC_WLACT_SW_LO:
+ dm->gnt.bt[i].wlan_act_en = 1;
+ dm->gnt.bt[i].wlan_act = 0;
+ break;
+ case BTC_WLACT_SW_HI:
+ dm->gnt.bt[i].wlan_act_en = 1;
+ dm->gnt.bt[i].wlan_act = 1;
+ break;
+ }
+ }
+ }
+ rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
+}
+
#define BTC_TDMA_WLROLE_MAX 2

static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
@@ -3512,8 +3590,8 @@ static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
rtw89_mac_cfg_plt(rtwdev, &plt);
}

-static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
- u8 phy_map, u8 type)
+static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
+ u8 phy_map, u8 type)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
@@ -3639,6 +3717,117 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
}
}

+static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
+ u8 phy_map, u8 type)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+ struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
+ u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
+ struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ u8 gwl = BTC_GNT_HW;
+
+ if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
+ btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
+ btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
+ force_exec = FC_EXEC;
+
+ if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
+ btc->dm.wl_btg_rx == 2)
+ force_exec = FC_EXEC;
+
+ if (!force_exec && ant_path_type == dm->set_ant_path) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): return by no change!!\n",
+ __func__);
+ return;
+ } else if (bt->rfk_info.map.run) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): return by bt rfk!!\n", __func__);
+ return;
+ } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
+ wl->rfk_info.state != BTC_WRFK_STOP) {
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): return by wl rfk!!\n", __func__);
+ return;
+ }
+
+ dm->set_ant_path = ant_path_type;
+
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC], %s(): path=0x%x, set_type=0x%x\n",
+ __func__, phy_map, dm->set_ant_path & 0xff);
+
+ switch (type) {
+ case BTC_ANT_WINIT:
+ /* To avoid BT MP driver case (bt_enable but no mailbox) */
+ if (bt->enable.now && bt->run_patch_code)
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
+ BTC_WLACT_SW_LO);
+ else
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
+ BTC_WLACT_SW_HI);
+ break;
+ case BTC_ANT_WONLY:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
+ BTC_WLACT_SW_HI);
+ break;
+ case BTC_ANT_WOFF:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
+ BTC_WLACT_SW_LO);
+ break;
+ case BTC_ANT_W2G:
+ case BTC_ANT_W25G:
+ if (wl_rinfo->dbcc_en) {
+ if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
+ gwl = BTC_GNT_HW;
+ else
+ gwl = BTC_GNT_SW_HI;
+ _set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
+
+ if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
+ gwl = BTC_GNT_HW;
+ else
+ gwl = BTC_GNT_SW_HI;
+ _set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
+ } else {
+ gwl = BTC_GNT_HW;
+ _set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
+ }
+ break;
+ case BTC_ANT_W5G:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
+ break;
+ case BTC_ANT_FREERUN:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
+ BTC_WLACT_SW_LO);
+ break;
+ case BTC_ANT_WRFK:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
+ BTC_WLACT_HW);
+ break;
+ case BTC_ANT_WRFK2:
+ _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
+ BTC_WLACT_SW_HI); /* no BT-Tx */
+ break;
+ default:
+ return;
+ }
+
+ _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
+}
+
+static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
+ u8 phy_map, u8 type)
+{
+ if (rtwdev->chip->chip_id == RTL8922A)
+ _set_ant_v1(rtwdev, force_exec, phy_map, type);
+ else
+ _set_ant_v0(rtwdev, force_exec, phy_map, type);
+}
+
static void _action_wl_only(struct rtw89_dev *rtwdev)
{
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h
index 32c95022d6ee..671f52fe8931 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.h
+++ b/drivers/net/wireless/realtek/rtw89/coex.h
@@ -280,4 +280,9 @@ static inline u16 rtw89_coex_query_bt_req_len(struct rtw89_dev *rtwdev,
return btc->bt_req_len;
}

+static inline u32 rtw89_get_antpath_type(u8 phy_map, u8 type)
+{
+ return ((phy_map << 8) + type);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 8617c65ff60e..bc10ebb785a2 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -2658,6 +2658,7 @@ struct rtw89_btc_dm {
u8 wl_pre_agc: 2;
u8 wl_lna2: 1;
u8 wl_pre_agc_rb: 2;
+ u8 bt_select: 2; /* 0:s0, 1:s1, 2:s0 & s1, refer to enum btc_bt_index */
};

struct rtw89_btc_ctrl {
--
2.25.1


2024-03-12 01:47:34

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH v2 5/6] wifi: rtw89: 8922a: update chip parameter for coex

From: Ching-Te Ku <[email protected]>

Implement the chip operation function for 8922a, it related to TX power,
RX gain, antenna position, packet priority and so on. Also assign
coexistence priority table for hardware PTA using. Add settings to avoid
uncertainties propagation when Wi-Fi Rx due to RF gain mismatch.

Signed-off-by: Ching-Te Ku <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/rtw8922a.c | 149 ++++++++++++++++++
1 file changed, 149 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 948eeb6755fd..0a5dc429b46d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2257,6 +2257,138 @@ static void rtw8922a_btc_init_cfg(struct rtw89_dev *rtwdev)
btc->cx.wl.status.map.init_ok = true;
}

+static void
+rtw8922a_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
+{
+ u16 ctrl_all_time = u32_get_bits(txpwr_val, GENMASK(15, 0));
+ u16 ctrl_gnt_bt = u32_get_bits(txpwr_val, GENMASK(31, 16));
+
+ switch (ctrl_all_time) {
+ case 0xffff:
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
+ B_BE_FORCE_PWR_BY_RATE_EN, 0x0);
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
+ B_BE_FORCE_PWR_BY_RATE_VAL, 0x0);
+ break;
+ default:
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
+ B_BE_FORCE_PWR_BY_RATE_VAL, ctrl_all_time);
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
+ B_BE_FORCE_PWR_BY_RATE_EN, 0x1);
+ break;
+ }
+
+ switch (ctrl_gnt_bt) {
+ case 0xffff:
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_REG_CTRL,
+ B_BE_PWR_BT_EN, 0x0);
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_COEX_CTRL,
+ B_BE_PWR_BT_VAL, 0x0);
+ break;
+ default:
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_COEX_CTRL,
+ B_BE_PWR_BT_VAL, ctrl_gnt_bt);
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_REG_CTRL,
+ B_BE_PWR_BT_EN, 0x1);
+ break;
+ }
+}
+
+static
+s8 rtw8922a_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
+{
+ return clamp_t(s8, val, -100, 0) + 100;
+}
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8922a_rf_ul[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {6, 1, 0, 7},
+ {13, 1, 0, 7},
+ {13, 1, 0, 7}
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8922a_rf_dl[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {255, 1, 0, 7},
+ {255, 1, 0, 7},
+ {255, 1, 0, 7}
+};
+
+static const u8 rtw89_btc_8922a_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {60, 50, 40, 30};
+static const u8 rtw89_btc_8922a_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20};
+
+static const struct rtw89_btc_fbtc_mreg rtw89_btc_8922a_mon_reg[] = {
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe300),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe320),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe324),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe328),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe32c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe330),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe334),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe338),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe344),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe348),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe34c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe350),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x11a2c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x11a50),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x660),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x1660),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x418c),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x518c),
+};
+
+static
+void rtw8922a_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
+{
+ /* Feature move to firmware */
+}
+
+static
+void rtw8922a_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
+{
+ if (!state) {
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD1, RFREG_MASK, 0x0c110);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x01018);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x00000);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c110);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x01018);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
+ } else {
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD1, RFREG_MASK, 0x0c110);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x09018);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x00000);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c110);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x09018);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
+ }
+}
+
+static void rtw8922a_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
+{
+}
+
static void rtw8922a_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status)
@@ -2367,6 +2499,13 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {

.btc_set_rfe = rtw8922a_btc_set_rfe,
.btc_init_cfg = rtw8922a_btc_init_cfg,
+ .btc_set_wl_pri = NULL,
+ .btc_set_wl_txpwr_ctrl = rtw8922a_btc_set_wl_txpwr_ctrl,
+ .btc_get_bt_rssi = rtw8922a_btc_get_bt_rssi,
+ .btc_update_bt_cnt = rtw8922a_btc_update_bt_cnt,
+ .btc_wl_s1_standby = rtw8922a_btc_wl_s1_standby,
+ .btc_set_wl_rx_gain = rtw8922a_btc_set_wl_rx_gain,
+ .btc_set_policy = rtw89_btc_set_policy_v1,
};

const struct rtw89_chip_info rtw8922a_chip_info = {
@@ -2442,6 +2581,16 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.scbd = 0x1,
.mailbox = 0x1,

+ .afh_guard_ch = 6,
+ .wl_rssi_thres = rtw89_btc_8922a_wl_rssi_thres,
+ .bt_rssi_thres = rtw89_btc_8922a_bt_rssi_thres,
+ .rssi_tol = 2,
+ .mon_reg_num = ARRAY_SIZE(rtw89_btc_8922a_mon_reg),
+ .mon_reg = rtw89_btc_8922a_mon_reg,
+ .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8922a_rf_ul),
+ .rf_para_ulink = rtw89_btc_8922a_rf_ul,
+ .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8922a_rf_dl),
+ .rf_para_dlink = rtw89_btc_8922a_rf_dl,
.ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) |
BIT(RTW89_PS_MODE_CLK_GATED) |
BIT(RTW89_PS_MODE_PWR_GATED),
--
2.25.1


2024-03-14 08:57:54

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 1/6] wifi: rtw89: coex: Add WiFi role info format version 8

Ping-Ke Shih <[email protected]> wrote:

> From: Ching-Te Ku <[email protected]>
>
> In order to control the hardware band and related protocol control,
> add version 8 format and related logic to control the mechanism.
>
> Signed-off-by: Ching-Te Ku <[email protected]>
> Signed-off-by: Ping-Ke Shih <[email protected]>

6 patches applied to wireless-next.git, thanks.

4e430ca43032 wifi: rtw89: coex: Add WiFi role info format version 8
bd120fa34f77 wifi: rtw89: coex: Add antenna setting function for RTL8922A
69cf60501642 wifi: rtw89: coex: Add TDMA version 7
a7d6f8d0c6d2 wifi: rtw89: coex: Add TDMA slot parameter setting version 7
89d58c931b59 wifi: rtw89: 8922a: update chip parameter for coex
f95d9045b987 wifi: rtw89: 8922a: add 8922ae to Makefile and Kconfig

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches