Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C
@ 2026-09-23  7:13 Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping Ping-Ke Shih
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

Patches to support newer firmware formats, especially for RTL8852C, and
use IO pack to offload IO to firmware to speed initialization.

Ching-Te Ku (6):
  wifi: rtw89: coex: log FCX report version mismatch without dropping
  wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling
  wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C
  wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths
  wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack
    region
  wifi: rtw89: coex: batch PTA init with masked IO offload

Zong-Zhe Yang (1):
  wifi: rtw89: add instance of IO ops for (un)pack and [um]delay

 drivers/net/wireless/realtek/rtw89/coex.c     | 236 +++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/core.h     | 170 ++++++++++---
 drivers/net/wireless/realtek/rtw89/fw.c       | 122 ++++++++-
 drivers/net/wireless/realtek/rtw89/fw.h       |   8 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  12 +
 5 files changed, 491 insertions(+), 57 deletions(-)


base-commit: 2f77c66694108785a1f6ae6c5de06453e7f7a91f
-- 
2.25.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-30  2:14   ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 2/7] wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling Ping-Ke Shih
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

_chk_btc_report() validated the reported firmware struct version only
for the control report, so a version mismatch on any other report type
was copied in silently and left no trace, making a ver_defs or firmware
version error hard to diagnose.

Read the reported fver, which is the leading field of every report
struct, and when it differs from the driver-selected version set the
per-type bit in fver_mismch and emit a debug line. The length-valid
report is still processed, because the driver must stay compatible with
every released firmware and a mismatch usually points at a ver_defs
entry that needs fixing rather than a report that should be discarded.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/coex.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 305d8edb0d4d..d3f9ef02e982 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -1866,6 +1866,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
 	u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
 	u8 i, j, val = 0, val1, val2;
 	u32 *bt_cnt, start_idx;
+	const u8 *rpt_fver;
 
 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
 		    "[BTC], %s(): index:%d\n",
@@ -2181,6 +2182,21 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
 	memcpy(pfinfo, rpt_content, pcinfo->req_len);
 	pcinfo->valid = 1;
 
+	/*
+	 * fver is the leading field of every report struct. A mismatch
+	 * vs the driver-selected version means ver_defs needs a fix, so
+	 * flag it for debug but keep processing the length-valid report.
+	 */
+	rpt_fver = pfinfo;
+	pcinfo->rsp_fver = rpt_fver[0];
+	if (pcinfo->rsp_fver != pcinfo->req_fver) {
+		pfwinfo->fver_mismch |= BIT(rpt_type);
+		rtw89_debug(rtwdev, RTW89_DBG_BTC,
+			    "[BTC], %s(): %d rsp_fver:%d!=req_fver:%d\n",
+			    __func__, rpt_type, pcinfo->rsp_fver,
+			    pcinfo->req_fver);
+	}
+
 	switch (rpt_type) {
 	case BTC_RPT_TYPE_CTRL:
 		if (ver->fcxbtcrpt == 1) {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 2/7] wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 3/7] wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C Ping-Ke Shih
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

Define struct rtw89_btc_fbtc_rpt_ctrl_v205 and add it to the
rtw89_btc_fbtc_rpt_ctrl_ver_info union. Wire up the v205 dispatch
path in _chk_btc_report() including req_len, fver extraction, and
rsp_fver assignment (H2C fver=5). Decode the v205 report block for
rpt_en_map, fw_coex/fw version, cx_offload, build timestamps, gnt_val,
and BT counters. Add fw_ver_match checking for fcxbtcrpt=205, and add
BTTX_HANG detection in the v205 error-check block.

Also add _show_summary_v205() and wire it into the coex info dump so
the fcxbtcrpt=205 statistics block is printed instead of skipped.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/coex.c | 179 +++++++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/core.h |  14 ++
 2 files changed, 191 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index d3f9ef02e982..0f3347fdbb01 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -1910,6 +1910,14 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
 			pcinfo->req_fver = 5;
 			break;
+		} else if (ver->fcxbtcrpt == 205) {
+			pfinfo = &pfwinfo->rpt_ctrl.finfo.v205;
+			pcinfo->req_len =
+				sizeof(pfwinfo->rpt_ctrl.finfo.v205);
+			fwsubver->fcxbtcrpt =
+				pfwinfo->rpt_ctrl.finfo.v205.fver;
+			pcinfo->req_fver = 5;
+			break;
 		} else if (ver->fcxbtcrpt == 8) {
 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
@@ -2304,6 +2312,52 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
 				     pfwinfo->event[BTF_EVNT_RPT]);
 
+			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
+		} else if (ver->fcxbtcrpt == 205) {
+			prpt->v205 = pfwinfo->rpt_ctrl.finfo.v205;
+			pfwinfo->rpt_en_map =
+				le32_to_cpu(prpt->v205.rpt_info.en);
+			wl->ver_info.fw_coex =
+				le32_to_cpu(prpt->v205.wl_fw_info.cx_ver);
+			wl->ver_info.fw =
+				le32_to_cpu(prpt->v205.wl_fw_info.fw_ver);
+			dm->wl_fw_cx_offload =
+				!!le32_to_cpu(prpt->v205.wl_fw_info.cx_offload);
+
+			memcpy(wl->ver_info.build_time,
+			       prpt->v205.build_time,
+			       sizeof(wl->ver_info.build_time));
+			memcpy(wl->ver_info.build_date,
+			       prpt->v205.build_date,
+			       sizeof(wl->ver_info.build_date));
+
+			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
+				memcpy(&dm->gnt_val[i],
+				       &prpt->v205.gnt_val[i],
+				       sizeof(prpt->v205.gnt_val[i]));
+
+			bt->bcnt[BTC_BCNT_HIPRI_TX] =
+				le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_HI_TX]);
+			bt->bcnt[BTC_BCNT_HIPRI_RX] =
+				le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_HI_RX]);
+			bt->bcnt[BTC_BCNT_LOPRI_TX] =
+				le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_LO_TX]);
+			bt->bcnt[BTC_BCNT_LOPRI_RX] =
+				le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_LO_RX]);
+			bt->bcnt[BTC_BCNT_POLLUTED] =
+				le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_POLLUTED]);
+
+			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
+			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
+				     pfwinfo->event[BTF_EVNT_RPT]);
+			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
+			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
+
+			if (le32_to_cpu(prpt->v205.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
+				bt->rfk_info.map.timeout = 1;
+			else
+				bt->rfk_info.map.timeout = 0;
+
 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
 		} else if (ver->fcxbtcrpt == 7) {
 			prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
@@ -3332,9 +3386,13 @@ static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
 	if (btc->ver->fcxbtcrpt == 7 ||
 	    btc->ver->fcxbtcrpt == 8 ||
 	    btc->ver->fcxbtcrpt == 9 ||
-	    btc->ver->fcxbtcrpt == 11) {
+	    btc->ver->fcxbtcrpt == 11 ||
+	    btc->ver->fcxbtcrpt == 205) {
 		r.v8.type = SET_REPORT_EN;
-		r.v8.fver = btc->ver->fcxbtcrpt;
+		if (btc->ver->fcxbtcrpt == 205)
+			r.v8.fver = 5;
+		else
+			r.v8.fver = btc->ver->fcxbtcrpt;
 		r.v8.len = sizeof(r.v8.map);
 		r.v8.map = cpu_to_le32(rpt_map);
 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
@@ -13644,6 +13702,121 @@ static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
 	return p - buf;
 }
 
+static int _show_summary_v205(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
+{
+	struct rtw89_btc *btc = &rtwdev->btc;
+	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
+	struct rtw89_btc_fbtc_rpt_ctrl_v205 *prptctrl;
+	struct rtw89_btc_rpt_cmn_info *pcinfo;
+	struct rtw89_btc_cx *cx = &btc->cx;
+	struct rtw89_btc_dm *dm = &btc->dm;
+	struct rtw89_btc_wl_info *wl = &cx->wl;
+	struct rtw89_btc_bt_info *bt = &cx->bt0;
+	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
+	char *p = buf, *end = buf + bufsz;
+	u8 i;
+
+	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
+		return 0;
+
+	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
+
+	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
+	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
+		prptctrl = &pfwinfo->rpt_ctrl.finfo.v205;
+
+		p += scnprintf(p, end - p,
+			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
+			       "[summary]", pfwinfo->cnt_h2c,
+			       pfwinfo->cnt_h2c_fail,
+			       le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
+			       pfwinfo->cnt_c2h,
+			       le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
+
+		p += scnprintf(p, end - p,
+			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
+			       pfwinfo->event[BTF_EVNT_RPT],
+			       le32_to_cpu(prptctrl->rpt_info.cnt),
+			       le32_to_cpu(prptctrl->rpt_info.en),
+			       dm->error.val);
+
+		if (dm->error.map.wl_fw_hang)
+			p += scnprintf(p, end - p, " (WL FW Hang!!)");
+		p += scnprintf(p, end - p, "\n");
+		p += scnprintf(p, end - p,
+			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
+			       "[mailbox]",
+			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
+			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
+			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
+
+		p += scnprintf(p, end - p,
+			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
+			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
+			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
+			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
+			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
+			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
+
+		p += scnprintf(p, end - p,
+			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
+			       "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ],
+			       wl->wcnt[BTC_WCNT_RFK_GO],
+			       wl->wcnt[BTC_WCNT_RFK_REJECT],
+			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
+
+		p += scnprintf(p, end - p,
+			       ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
+			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
+			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
+			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
+			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
+			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
+
+		if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
+			bt->rfk_info.map.timeout = 1;
+		else
+			bt->rfk_info.map.timeout = 0;
+
+		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
+	} else {
+		p += scnprintf(p, end - p,
+			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
+			       "[summary]", pfwinfo->cnt_h2c,
+			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
+			       pfwinfo->event[BTF_EVNT_RPT],
+			       btc->fwinfo.rpt_en_map);
+		p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
+	}
+
+	for (i = 0; i < BTC_NCNT_NUM; i++)
+		cnt_sum += dm->cnt_notify[i];
+
+	p += scnprintf(p, end - p,
+		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
+		       "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
+		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
+
+	p += scnprintf(p, end - p,
+		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
+		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
+		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
+		       cnt[BTC_NCNT_WL_STA]);
+
+	p += scnprintf(p, end - p,
+		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
+		       "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
+		       cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
+		       cnt[BTC_NCNT_SPECIAL_PACKET]);
+
+	p += scnprintf(p, end - p,
+		       "timer=%d, control=%d, customerize=%d\n",
+		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
+		       cnt[BTC_NCNT_CUSTOMERIZE]);
+
+	return p - buf;
+}
+
 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
 {
 	struct rtw89_btc *btc = &rtwdev->btc;
@@ -13704,6 +13877,8 @@ ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
 		p += _show_summary_v5(rtwdev, p, end - p);
 	else if (ver->fcxbtcrpt == 105)
 		p += _show_summary_v105(rtwdev, p, end - p);
+	else if (ver->fcxbtcrpt == 205)
+		p += _show_summary_v205(rtwdev, p, end - p);
 	else if (ver->fcxbtcrpt == 7)
 		p += _show_summary_v7(rtwdev, p, end - p);
 	else if (ver->fcxbtcrpt == 8)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 3a6099386b09..fc51419a1782 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3006,6 +3006,19 @@ struct rtw89_btc_fbtc_rpt_ctrl_v11 {
 	__le32 scbd_b2w[2];
 } __packed;
 
+struct rtw89_btc_fbtc_rpt_ctrl_v205 {
+	u8 fver;
+	u8 rsvd;
+	u8 build_time[RTW89_BTC_TIME_DATE_FMT];
+	u8 build_date[RTW89_BTC_TIME_DATE_FMT];
+	__le16 rsvd1;
+	struct rtw89_btc_fbtc_rpt_ctrl_info rpt_info;
+	struct rtw89_btc_fbtc_rpt_ctrl_wl_fw_info wl_fw_info;
+	struct rtw89_btc_fbtc_rpt_ctrl_bt_mailbox bt_mbx_info;
+	__le32 bt_cnt[BTC_BCNT_STA_MAX];
+	u8 gnt_val[RTW89_PHY_NUM][4];
+} __packed;
+
 union rtw89_btc_fbtc_rpt_ctrl_ver_info {
 	struct rtw89_btc_fbtc_rpt_ctrl_v1 v1;
 	struct rtw89_btc_fbtc_rpt_ctrl_v4 v4;
@@ -3015,6 +3028,7 @@ union rtw89_btc_fbtc_rpt_ctrl_ver_info {
 	struct rtw89_btc_fbtc_rpt_ctrl_v8 v8;
 	struct rtw89_btc_fbtc_rpt_ctrl_v9 v9;
 	struct rtw89_btc_fbtc_rpt_ctrl_v11 v11;
+	struct rtw89_btc_fbtc_rpt_ctrl_v205 v205;
 };
 
 enum rtw89_fbtc_ext_ctrl_type {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 3/7] wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 2/7] wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 4/7] wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths Ping-Ke Shih
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

Add a new entry in rtw89_btc_ver_defs for RTL8852C firmware version
0.27.130.1, which introduces fcxbtcrpt=205. The new entry activates
the v205 coexistence report path added in the preceding commit.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/coex.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 0f3347fdbb01..b80e7979a1ae 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -146,7 +146,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
 	 .fcxbtcrpt = 11, .fcxtdma = 8,    .fcxslots = 7, .fcxcysta = 8,
 	 .fcxstep = 7,    .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
 	 .fcxbtver = 8,   .fcxbtscan = 8,  .fcxbtafh = 8, .fcxbtdevinfo = 8,
-	 .fwlrole = 10,    .frptmap = 5,    .fcxctrl = 9,  .fcxinit = 10,
+	 .fwlrole = 10,    .frptmap = 5,   .fcxctrl = 9,  .fcxinit = 10,
 	 .fwevntrptl = 1,  .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
 	 .max_role_num = 6, .fcxosi = 6,   .fcxmlo = 2,   .bt_desired = 8,
 	 .fcxtrx = 9,     .fcxtxpwr = 1,
@@ -224,7 +224,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
 	 .fcxtrx = 107,  .fcxtxpwr = 0,
 	},
 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
-	 .fcxbtcrpt = 105, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 5,
+	 .fcxbtcrpt = 105, .fcxtdma = 3,  .fcxslots = 1, .fcxcysta = 5,
 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
@@ -232,6 +232,15 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
 	 .fcxtrx = 0,    .fcxtxpwr = 0,
 	},
+	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 130, 1),
+	 .fcxbtcrpt = 205, .fcxtdma = 4,  .fcxslots = 2, .fcxcysta = 105,
+	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
+	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
+	 .fwlrole = 101, .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
+	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
+	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
+	 .fcxtrx = 107,  .fcxtxpwr = 0,
+	},
 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 97, 0),
 	 .fcxbtcrpt = 4, .fcxtdma = 4,    .fcxslots = 2, .fcxcysta = 105,
 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 4/7] wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
                   ` (2 preceding siblings ...)
  2026-09-23  7:13 ` [PATCH rtw-next 3/7] wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 5/7] wifi: rtw89: add instance of IO ops for (un)pack and [um]delay Ping-Ke Shih
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

The scoreboard update function was changed to always read from
scbd_c2h, which is populated only by BTF_EVNT_BT_SCBD C2H events from
the BT firmware. This caused two problems.

First, calling _update_bt_scbd at the NTFY_INIT notification with
scbd_c2h still zero would set bt->enable.now to 0, overwriting the
bt-on assumption that _ntfy_init_coex establishes for all chips. Remove
the NTFY_INIT call to preserve that default.

Second, chips whose BT firmware does not send BTF_EVNT_BT_SCBD events
have scbd_c2h stuck at zero indefinitely, making scoreboard updates
non-functional. Restore a hardware register read path by adding
_read_scbd() and an is_c2h flag to _update_bt_scbd. The
NTFY_RADIO_STATE path passes is_c2h=false to read the hardware
scoreboard register directly, ensuring correct BT state even without
C2H support. Pass BTC_ALL_BT so both BT devices are refreshed on
dual-BT chips.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/coex.c | 28 +++++++++++++++++------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index b80e7979a1ae..6b72e2c80d14 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -1010,7 +1010,7 @@ static void _run_coex(struct rtw89_dev *rtwdev,
 		      enum btc_reason_and_action reason);
 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state);
 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid);
-static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid);
+static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid, bool is_c2h);
 static const char *id_to_h2c(u32 id);
 
 static void _reset_h2c_macro(struct rtw89_btc *btc)
@@ -3902,7 +3902,7 @@ void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
 				    "[BTC], %s() bt%d:c2h->0x%08x, rb->0x%08x\n",
 				    __func__, i, bt->scbd_c2h, bt->scbd_rb);
 			bt->scbd_c2h = bt->scbd_rb;
-			_update_bt_scbd(rtwdev, i);
+			_update_bt_scbd(rtwdev, i, true);
 			btc->dm.scbd_b2w_update = false;
 		}
 	}
@@ -8116,7 +8116,21 @@ static void _update_bt_ctrl_lps(struct rtw89_dev *rtwdev)
 	}
 }
 
-static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid)
+static u32 _read_scbd(struct rtw89_dev *rtwdev, u8 id)
+{
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	u32 val;
+
+	if (!chip->scbd)
+		return 0;
+
+	val = rtw89_read32(rtwdev, chip->btc_sb.n[id].get);
+	rtw89_debug(rtwdev, RTW89_DBG_BTC,
+		    "[BTC], read scbd bt%d: 0x%08x\n", id, val);
+	return val;
+}
+
+static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid, bool is_c2h)
 {
 	struct rtw89_btc_bt_link_info *bt_2g, *bt_56g;
 	struct rtw89_btc *btc = &rtwdev->btc;
@@ -8149,7 +8163,7 @@ static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid)
 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && id == BTC_BT_2ND)
 			break;
 
-		val = bt->scbd_c2h;
+		val = is_c2h ? bt->scbd_c2h : _read_scbd(rtwdev, id);
 
 		if (val == 0xffffffff) {
 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -8785,8 +8799,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
 
 	_update_run_ctrl_info(rtwdev);
 
-	if (reason == BTC_RSN_NTFY_INIT || reason == BTC_RSN_NTFY_RADIO_STATE)
-		_update_bt_scbd(rtwdev, false);
+	if (reason == BTC_RSN_NTFY_RADIO_STATE)
+		_update_bt_scbd(rtwdev, BTC_ALL_BT, false);
 
 	dm->freerun = false;
 	dm->cnt_dm[BTC_DCNT_RUN]++;
@@ -10131,7 +10145,7 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
 			    "[BTC], handle C2H BT%d SCBD with data 0x%08x\n",
 			    bid, bt->scbd_c2h);
-		_update_bt_scbd(rtwdev, bid);
+		_update_bt_scbd(rtwdev, bid, true);
 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
 		break;
 	case BTF_EVNT_BT_PSD:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 5/7] wifi: rtw89: add instance of IO ops for (un)pack and [um]delay
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
                   ` (3 preceding siblings ...)
  2026-09-23  7:13 ` [PATCH rtw-next 4/7] wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 6/7] wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack region Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 7/7] wifi: rtw89: coex: batch PTA init with masked IO offload Ping-Ke Shih
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Zong-Zhe Yang <kevin_yang@realtek.com>

To make IO wrappers of pack/unpack/udely/mdely can intuitively call
the loaded IO ops as others do, add corresponding instances for them.
And, expect all rtw89_io_ops initializers should assign all members.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h | 38 ++++++++++++++---------
 drivers/net/wireless/realtek/rtw89/fw.c   | 10 +++---
 2 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index fc51419a1782..128667fb95b0 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -8097,36 +8097,44 @@ struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
 	return (struct rtw89_tx_skb_data *)info->driver_data;
 }
 
-static inline int rtw89_io_pack(struct rtw89_dev *rtwdev)
+static inline int rtw89_raw_io_pack(struct rtw89_dev *rtwdev)
 {
-	if (rtwdev->io->pack)
-		return rtwdev->io->pack(rtwdev);
+	return 0;
+}
 
+static inline int rtw89_raw_io_unpack(struct rtw89_dev *rtwdev)
+{
 	return 0;
 }
 
-static inline int rtw89_io_unpack(struct rtw89_dev *rtwdev)
+static inline void rtw89_raw_io_udelay(struct rtw89_dev *rtwdev, u32 us)
 {
-	if (rtwdev->io->unpack)
-		return rtwdev->io->unpack(rtwdev);
+	udelay(us);
+}
 
-	return 0;
+static inline void rtw89_raw_io_mdelay(struct rtw89_dev *rtwdev, u32 ms)
+{
+	mdelay(ms);
+}
+
+static inline int rtw89_io_pack(struct rtw89_dev *rtwdev)
+{
+	return rtwdev->io->pack(rtwdev);
+}
+
+static inline int rtw89_io_unpack(struct rtw89_dev *rtwdev)
+{
+	return rtwdev->io->unpack(rtwdev);
 }
 
 static inline void rtw89_io_udelay(struct rtw89_dev *rtwdev, u32 us)
 {
-	if (rtwdev->io->do_udelay)
-		rtwdev->io->do_udelay(rtwdev, us);
-	else
-		udelay(us);
+	rtwdev->io->do_udelay(rtwdev, us);
 }
 
 static inline void rtw89_io_mdelay(struct rtw89_dev *rtwdev, u32 ms)
 {
-	if (rtwdev->io->do_mdelay)
-		rtwdev->io->do_mdelay(rtwdev, ms);
-	else
-		mdelay(ms);
+	rtwdev->io->do_mdelay(rtwdev, ms);
 }
 
 static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 535cc2ad8611..7cf51e78ce98 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -12916,8 +12916,10 @@ static int rtw89_fw_cmd_ofld_enqueue(struct rtw89_dev *rtwdev,
 }
 
 static const struct rtw89_io_ops rtw89_raw_io = {
-	.pack = NULL,
-	.unpack = NULL,
+	.pack = rtw89_raw_io_pack,
+	.unpack = rtw89_raw_io_unpack,
+	.do_udelay = rtw89_raw_io_udelay,
+	.do_mdelay = rtw89_raw_io_mdelay,
 	.write8 = rtw89_raw_write8,
 	.write16 = rtw89_raw_write16,
 	.write32 = rtw89_raw_write32,
@@ -13096,7 +13098,7 @@ static void rtw89_fw_cmd_ofld_udelay(struct rtw89_dev *rtwdev, u32 us)
 
 	ret = rtw89_fw_cmd_ofld_enqueue(rtwdev, &cmd);
 	if (ret)
-		udelay(us);
+		rtw89_raw_io.do_udelay(rtwdev, us);
 }
 
 static void rtw89_fw_cmd_ofld_mdelay(struct rtw89_dev *rtwdev, u32 ms)
@@ -13110,7 +13112,7 @@ static void rtw89_fw_cmd_ofld_mdelay(struct rtw89_dev *rtwdev, u32 ms)
 
 	ret = rtw89_fw_cmd_ofld_enqueue(rtwdev, &cmd);
 	if (ret)
-		mdelay(ms);
+		rtw89_raw_io.do_mdelay(rtwdev, ms);
 }
 
 static const struct rtw89_io_ops rtw89_fw_cmd_ofld_io = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 6/7] wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack region
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
                   ` (4 preceding siblings ...)
  2026-09-23  7:13 ` [PATCH rtw-next 5/7] wifi: rtw89: add instance of IO ops for (un)pack and [um]delay Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  2026-09-23  7:13 ` [PATCH rtw-next 7/7] wifi: rtw89: coex: batch PTA init with masked IO offload Ping-Ke Shih
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

On USB, 8852C is the only chip with .support_fw_cmd_ofld set, which
routes register writes through the FW command offload path via the
transparent io_ops indirection. The coex layer never entered an
rtw89_io_pack() region, so its register writes were always issued
individually instead of being batched to the firmware.

Wrap the RF LUT and GNT write sequences in rtw8852c_btc_init_cfg(),
rtw8852c_btc_wl_s1_standby() and rtw8852c_set_wl_lna2() with
rtw89_io_pack()/rtw89_io_unpack() so that on USB these writes are
enqueued and flushed as a single FW command batch. On PCIe the pack
region is a no-op and raw MMIO proceeds unchanged.

Only write_rf partial-mask, write-only sequences are offloaded, for
which the firmware performs the read-modify-write. Driver-side
same-register read-modify-write helpers and BB phy_write32 flows are
kept outside the pack region to avoid the offload full-dword
overwrite hazard.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8852c.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index c68959b63a01..7649706b67e6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2706,6 +2706,8 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
 	chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true);
 	chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true);
 
+	rtw89_io_pack(rtwdev);
+
 	/* set rf gnt debug off */
 	rtw89_write_rf(rtwdev, RF_PATH_A, RR_WLSEL, RFREG_MASK, 0x0);
 	rtw89_write_rf(rtwdev, RF_PATH_B, RR_WLSEL, RFREG_MASK, 0x0);
@@ -2733,6 +2735,8 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
 	rtw89_write32_set(rtwdev,
 			  R_AX_BT_CNT_CFG, B_AX_BT_CNT_EN |
 			  B_AX_BT_CNT_RST_V1);
+
+	rtw89_io_unpack(rtwdev);
 }
 
 static
@@ -2888,6 +2892,8 @@ void rtw8852c_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
 static
 void rtw8852c_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
 {
+	rtw89_io_pack(rtwdev);
+
 	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, 0x620);
@@ -2901,6 +2907,8 @@ void rtw8852c_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
 			       RFREG_MASK, 0x208);
 
 	rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
+
+	rtw89_io_unpack(rtwdev);
 }
 
 static void rtw8852c_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level)
@@ -2910,6 +2918,8 @@ static void rtw8852c_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level)
 	 * To improve BT ACI in co-rx
 	 */
 
+	rtw89_io_pack(rtwdev);
+
 	switch (level) {
 	case 0: /* default */
 		rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x1000);
@@ -2936,6 +2946,8 @@ static void rtw8852c_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level)
 		rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
 		break;
 	}
+
+	rtw89_io_unpack(rtwdev);
 }
 
 static void rtw8852c_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH rtw-next 7/7] wifi: rtw89: coex: batch PTA init with masked IO offload
  2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
                   ` (5 preceding siblings ...)
  2026-09-23  7:13 ` [PATCH rtw-next 6/7] wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack region Ping-Ke Shih
@ 2026-09-23  7:13 ` Ping-Ke Shih
  6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-23  7:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: ku920601, kevin_yang

From: Ching-Te Ku <ku920601@realtek.com>

On USB, the register writes in coex init cannot be fully batched
into a single H2C because the write32 IO offload only carries
MASKDWORD, i.e. a full-dword overwrite. Read-modify-write helpers
derive the new value from a driver-side read that cannot observe
other writes still queued in the same pack region, so packing a
same-register sequence would drop bits. mac_coex_init_v1() and
btc_set_wl_pri() were thus left outside the pack region and issued
as separate H2C commands, costing hundreds of ms.

Add write8_mask/write16_mask/write32_mask to the IO ops. For the raw
IO path, these ops are implemented as direct read-modify-write on the
hardware. For the firmware offload path, they forward the field mask
to the FW so it can perform the read-modify-write server-side,
removing the dependency on a driver-side read of a register whose
new value may still be queued.

Extract the raw read-modify-write bodies of write8_set, write16_set,
write32_set, write8_clr, write16_clr, write32_clr, write8_mask,
write16_mask, and write32_mask into rtw89_raw_write*() helpers,
grouping raw_* variants before the io-dispatching thin wrappers.
Replace the original functions with thin wrappers that dispatch
through rtwdev->io, removing the inline capability checks. With that
in place, extend the 8852c PTA init pack region to cover
mac_coex_init_v1() and btc_set_wl_pri().

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     | 118 ++++++++++++++----
 drivers/net/wireless/realtek/rtw89/fw.c       | 112 +++++++++++++++++
 drivers/net/wireless/realtek/rtw89/fw.h       |   8 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |   4 +-
 4 files changed, 213 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 128667fb95b0..762d0db8b721 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -7591,6 +7591,18 @@ struct rtw89_io_ops {
 	void (*phy_write32)(struct rtw89_dev *rtwdev, u32 addr, u32 data);
 	void (*write_rf)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 			 u32 addr, u32 mask, u32 data);
+	void (*write8_set)(struct rtw89_dev *rtwdev, u32 addr, u8 bit);
+	void (*write16_set)(struct rtw89_dev *rtwdev, u32 addr, u16 bit);
+	void (*write32_set)(struct rtw89_dev *rtwdev, u32 addr, u32 bit);
+	void (*write8_clr)(struct rtw89_dev *rtwdev, u32 addr, u8 bit);
+	void (*write16_clr)(struct rtw89_dev *rtwdev, u32 addr, u16 bit);
+	void (*write32_clr)(struct rtw89_dev *rtwdev, u32 addr, u32 bit);
+	void (*write8_mask)(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			    u8 data);
+	void (*write16_mask)(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			     u16 data);
+	void (*write32_mask)(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			     u32 data);
 };
 
 struct rtw89_dev {
@@ -8183,57 +8195,93 @@ static inline void rtw89_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data)
 }
 
 static inline void
-rtw89_write8_set(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+rtw89_raw_write8_set(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
 {
 	u8 val;
 
 	val = rtw89_read8(rtwdev, addr);
-	rtw89_write8(rtwdev, addr, val | bit);
+	rtw89_raw_write8(rtwdev, addr, val | bit);
 }
 
 static inline void
-rtw89_write16_set(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+rtw89_raw_write16_set(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
 {
 	u16 val;
 
 	val = rtw89_read16(rtwdev, addr);
-	rtw89_write16(rtwdev, addr, val | bit);
+	rtw89_raw_write16(rtwdev, addr, val | bit);
 }
 
 static inline void
-rtw89_write32_set(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+rtw89_raw_write32_set(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
 {
 	u32 val;
 
 	val = rtw89_read32(rtwdev, addr);
-	rtw89_write32(rtwdev, addr, val | bit);
+	rtw89_raw_write32(rtwdev, addr, val | bit);
 }
 
 static inline void
-rtw89_write8_clr(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+rtw89_write8_set(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+{
+	rtwdev->io->write8_set(rtwdev, addr, bit);
+}
+
+static inline void
+rtw89_write16_set(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+{
+	rtwdev->io->write16_set(rtwdev, addr, bit);
+}
+
+static inline void
+rtw89_write32_set(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+{
+	rtwdev->io->write32_set(rtwdev, addr, bit);
+}
+
+static inline void
+rtw89_raw_write8_clr(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
 {
 	u8 val;
 
 	val = rtw89_read8(rtwdev, addr);
-	rtw89_write8(rtwdev, addr, val & ~bit);
+	rtw89_raw_write8(rtwdev, addr, val & ~bit);
 }
 
 static inline void
-rtw89_write16_clr(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+rtw89_raw_write16_clr(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
 {
 	u16 val;
 
 	val = rtw89_read16(rtwdev, addr);
-	rtw89_write16(rtwdev, addr, val & ~bit);
+	rtw89_raw_write16(rtwdev, addr, val & ~bit);
 }
 
 static inline void
-rtw89_write32_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+rtw89_raw_write32_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
 {
 	u32 val;
 
 	val = rtw89_read32(rtwdev, addr);
-	rtw89_write32(rtwdev, addr, val & ~bit);
+	rtw89_raw_write32(rtwdev, addr, val & ~bit);
+}
+
+static inline void
+rtw89_write8_clr(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+{
+	rtwdev->io->write8_clr(rtwdev, addr, bit);
+}
+
+static inline void
+rtw89_write16_clr(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+{
+	rtwdev->io->write16_clr(rtwdev, addr, bit);
+}
+
+static inline void
+rtw89_write32_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+{
+	rtwdev->io->write32_clr(rtwdev, addr, bit);
 }
 
 static inline u32
@@ -8275,46 +8323,66 @@ rtw89_read8_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask)
 	return ret;
 }
 
+static inline void
+rtw89_raw_write8_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u8 data)
+{
+	u8 orig, set;
+
+	orig = rtw89_read8(rtwdev, addr);
+	set = (orig & ~mask) | (data & mask);
+	rtw89_raw_write8(rtwdev, addr, set);
+}
+
+static inline void
+rtw89_raw_write16_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u16 data)
+{
+	u16 orig, set;
+
+	orig = rtw89_read16(rtwdev, addr);
+	set = (orig & ~mask) | (data & mask);
+	rtw89_raw_write16(rtwdev, addr, set);
+}
+
+static inline void
+rtw89_raw_write32_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data)
+{
+	u32 orig, set;
+
+	orig = rtw89_read32(rtwdev, addr);
+	set = (orig & ~mask) | (data & mask);
+	rtw89_raw_write32(rtwdev, addr, set);
+}
+
 static inline void
 rtw89_write32_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data)
 {
 	u32 shift = __ffs(mask);
-	u32 orig;
-	u32 set;
 
 	WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr);
 
-	orig = rtw89_read32(rtwdev, addr);
-	set = (orig & ~mask) | ((data << shift) & mask);
-	rtw89_write32(rtwdev, addr, set);
+	rtwdev->io->write32_mask(rtwdev, addr, mask, (data << shift) & mask);
 }
 
 static inline void
 rtw89_write16_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u16 data)
 {
 	u32 shift;
-	u16 orig, set;
 
 	mask &= 0xffff;
 	shift = __ffs(mask);
 
-	orig = rtw89_read16(rtwdev, addr);
-	set = (orig & ~mask) | ((data << shift) & mask);
-	rtw89_write16(rtwdev, addr, set);
+	rtwdev->io->write16_mask(rtwdev, addr, mask, (data << shift) & mask);
 }
 
 static inline void
 rtw89_write8_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u8 data)
 {
 	u32 shift;
-	u8 orig, set;
 
 	mask &= 0xff;
 	shift = __ffs(mask);
 
-	orig = rtw89_read8(rtwdev, addr);
-	set = (orig & ~mask) | ((data << shift) & mask);
-	rtw89_write8(rtwdev, addr, set);
+	rtwdev->io->write8_mask(rtwdev, addr, mask, (data << shift) & mask);
 }
 
 static inline u32
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 7cf51e78ce98..b1cfde6278c3 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -12923,6 +12923,15 @@ static const struct rtw89_io_ops rtw89_raw_io = {
 	.write8 = rtw89_raw_write8,
 	.write16 = rtw89_raw_write16,
 	.write32 = rtw89_raw_write32,
+	.write8_set = rtw89_raw_write8_set,
+	.write16_set = rtw89_raw_write16_set,
+	.write32_set = rtw89_raw_write32_set,
+	.write8_clr = rtw89_raw_write8_clr,
+	.write16_clr = rtw89_raw_write16_clr,
+	.write32_clr = rtw89_raw_write32_clr,
+	.write8_mask = rtw89_raw_write8_mask,
+	.write16_mask = rtw89_raw_write16_mask,
+	.write32_mask = rtw89_raw_write32_mask,
 	.phy_write8 = rtw89_raw_phy_write8,
 	.phy_write16 = rtw89_raw_phy_write16,
 	.phy_write32 = rtw89_raw_phy_write32,
@@ -13031,6 +13040,100 @@ void rtw89_fw_cmd_ofld_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data)
 		rtw89_raw_io.write32(rtwdev, addr, data);
 }
 
+static void
+rtw89_fw_cmd_ofld_write8_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			      u8 data)
+{
+	u32 dword_mask = RTW89_W8_MASK_OF_ALIGNED_ADDR(addr);
+	u32 shift = RTW89_W8_SHIFT_OF_ALIGNED_ADDR(addr);
+	struct rtw89_fw_cmd_ofld_arg cmd = {
+		.src = RTW89_FW_CMD_OFLD_SRC_MAC,
+		.type = RTW89_FW_CMD_OFLD_WRITE,
+		.offset = ALIGN_DOWN(addr, 4),
+		.mask = (mask << shift) & dword_mask,
+		.value = (data << shift) & dword_mask,
+	};
+	int ret;
+
+	ret = rtw89_fw_cmd_ofld_enqueue(rtwdev, &cmd);
+	if (ret)
+		rtw89_raw_io.write8_mask(rtwdev, addr, mask, data);
+}
+
+static void
+rtw89_fw_cmd_ofld_write16_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			       u16 data)
+{
+	u32 dword_mask = RTW89_W16_MASK_OF_ALIGNED_ADDR(addr);
+	u32 shift = RTW89_W16_SHIFT_OF_ALIGNED_ADDR(addr);
+	struct rtw89_fw_cmd_ofld_arg cmd = {
+		.src = RTW89_FW_CMD_OFLD_SRC_MAC,
+		.type = RTW89_FW_CMD_OFLD_WRITE,
+		.offset = ALIGN_DOWN(addr, 4),
+		.mask = (mask << shift) & dword_mask,
+		.value = (data << shift) & dword_mask,
+	};
+	int ret;
+
+	ret = rtw89_fw_cmd_ofld_enqueue(rtwdev, &cmd);
+	if (ret)
+		rtw89_raw_io.write16_mask(rtwdev, addr, mask, data);
+}
+
+static void
+rtw89_fw_cmd_ofld_write32_mask(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
+			       u32 data)
+{
+	struct rtw89_fw_cmd_ofld_arg cmd = {
+		.src = RTW89_FW_CMD_OFLD_SRC_MAC,
+		.type = RTW89_FW_CMD_OFLD_WRITE,
+		.offset = addr,
+		.mask = mask,
+		.value = data,
+	};
+	int ret;
+
+	ret = rtw89_fw_cmd_ofld_enqueue(rtwdev, &cmd);
+	if (ret)
+		rtw89_raw_io.write32_mask(rtwdev, addr, mask, data);
+}
+
+static void
+rtw89_fw_cmd_ofld_write8_set(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+{
+	rtw89_fw_cmd_ofld_write8_mask(rtwdev, addr, bit, bit);
+}
+
+static void
+rtw89_fw_cmd_ofld_write16_set(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+{
+	rtw89_fw_cmd_ofld_write16_mask(rtwdev, addr, bit, bit);
+}
+
+static void
+rtw89_fw_cmd_ofld_write32_set(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+{
+	rtw89_fw_cmd_ofld_write32_mask(rtwdev, addr, bit, bit);
+}
+
+static void
+rtw89_fw_cmd_ofld_write8_clr(struct rtw89_dev *rtwdev, u32 addr, u8 bit)
+{
+	rtw89_fw_cmd_ofld_write8_mask(rtwdev, addr, bit, 0);
+}
+
+static void
+rtw89_fw_cmd_ofld_write16_clr(struct rtw89_dev *rtwdev, u32 addr, u16 bit)
+{
+	rtw89_fw_cmd_ofld_write16_mask(rtwdev, addr, bit, 0);
+}
+
+static void
+rtw89_fw_cmd_ofld_write32_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bit)
+{
+	rtw89_fw_cmd_ofld_write32_mask(rtwdev, addr, bit, 0);
+}
+
 static void rtw89_fw_cmd_ofld_write_rf_ddv(struct rtw89_dev *rtwdev,
 					   struct rtw89_fw_cmd_ofld_arg *cmd,
 					   enum rtw89_rf_path rf_path, u32 addr, u32 mask,
@@ -13127,6 +13230,15 @@ static const struct rtw89_io_ops rtw89_fw_cmd_ofld_io = {
 	.phy_write16 = rtw89_fw_cmd_ofld_phy_write16,
 	.phy_write32 = rtw89_fw_cmd_ofld_phy_write32,
 	.write_rf = rtw89_fw_cmd_ofld_write_rf,
+	.write8_set = rtw89_fw_cmd_ofld_write8_set,
+	.write16_set = rtw89_fw_cmd_ofld_write16_set,
+	.write32_set = rtw89_fw_cmd_ofld_write32_set,
+	.write8_clr = rtw89_fw_cmd_ofld_write8_clr,
+	.write16_clr = rtw89_fw_cmd_ofld_write16_clr,
+	.write32_clr = rtw89_fw_cmd_ofld_write32_clr,
+	.write8_mask = rtw89_fw_cmd_ofld_write8_mask,
+	.write16_mask = rtw89_fw_cmd_ofld_write16_mask,
+	.write32_mask = rtw89_fw_cmd_ofld_write32_mask,
 };
 
 const struct rtw89_io_ops *
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 473278f6bbea..f8839d6cd3bb 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -3281,8 +3281,12 @@ struct rtw89_h2c_cmd_ofld {
 #define RTW89_H2C_CMD_OFLD_W1_BASE_OFFSET GENMASK(31, 16)
 #define RTW89_H2C_CMD_OFLD_W2_VALUE GENMASK(31, 0)
 #define RTW89_H2C_CMD_OFLD_W3_MASK GENMASK(31, 0)
-#define RTW89_W8_MASK_OF_ALIGNED_ADDR(offset) (0xff << (((offset) & 0x3) << 3))
-#define RTW89_W16_MASK_OF_ALIGNED_ADDR(offset) (0xffff << (((offset) & 0x2) * 8))
+#define RTW89_W8_SHIFT_OF_ALIGNED_ADDR(offset) (((offset) & 0x3) << 3)
+#define RTW89_W16_SHIFT_OF_ALIGNED_ADDR(offset) (((offset) & 0x2) << 3)
+#define RTW89_W8_MASK_OF_ALIGNED_ADDR(offset) \
+	(0xff << RTW89_W8_SHIFT_OF_ALIGNED_ADDR(offset))
+#define RTW89_W16_MASK_OF_ALIGNED_ADDR(offset) \
+	(0xffff << RTW89_W16_SHIFT_OF_ALIGNED_ADDR(offset))
 
 #define RTW89_FW_CMD_OFLD_NR 125
 struct rtw89_fw_cmd_ofld_info {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 7649706b67e6..624f23b3f2a1 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2699,6 +2699,8 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
 		.direction = RTW89_MAC_AX_COEX_INNER,
 	};
 
+	rtw89_io_pack(rtwdev);
+
 	/* PTA init  */
 	rtw89_mac_coex_init_v1(rtwdev, &coex_params);
 
@@ -2706,8 +2708,6 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev)
 	chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true);
 	chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true);
 
-	rtw89_io_pack(rtwdev);
-
 	/* set rf gnt debug off */
 	rtw89_write_rf(rtwdev, RF_PATH_A, RR_WLSEL, RFREG_MASK, 0x0);
 	rtw89_write_rf(rtwdev, RF_PATH_B, RR_WLSEL, RFREG_MASK, 0x0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping
  2026-09-23  7:13 ` [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping Ping-Ke Shih
@ 2026-09-30  2:14   ` Ping-Ke Shih
  0 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-09-30  2:14 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless; +Cc: ku920601, kevin_yang

Ping-Ke Shih <pkshih@realtek.com> wrote:

> From: Ching-Te Ku <ku920601@realtek.com>
> 
> _chk_btc_report() validated the reported firmware struct version only
> for the control report, so a version mismatch on any other report type
> was copied in silently and left no trace, making a ver_defs or firmware
> version error hard to diagnose.
> 
> Read the reported fver, which is the leading field of every report
> struct, and when it differs from the driver-selected version set the
> per-type bit in fver_mismch and emit a debug line. The length-valid
> report is still processed, because the driver must stay compatible with
> every released firmware and a mismatch usually points at a ver_defs
> entry that needs fixing rather than a report that should be discarded.
> 
> Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>

7 patch(es) applied to rtw-next branch of rtw.git, thanks.

0266773d404b wifi: rtw89: coex: log FCX report version mismatch without dropping
0104c69ba225 wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling
6047d2f7efd0 wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C
d6c34b67ad5c wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths
5f57e5453946 wifi: rtw89: add instance of IO ops for (un)pack and [um]delay
6d0c77424034 wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack region
6c095c657b31 wifi: rtw89: coex: batch PTA init with masked IO offload

---
https://github.com/pkshih/rtw.git


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-09-30  2:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23  7:13 [PATCH rtw-next 0/7] wifi: rtw89: coex: update to support newer firmware especially RTL8852C Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 1/7] wifi: rtw89: coex: log FCX report version mismatch without dropping Ping-Ke Shih
2026-09-30  2:14   ` Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 2/7] wifi: rtw89: coex: add fbtc_rpt_ctrl v205 report struct and handling Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 3/7] wifi: rtw89: coex: Add firmware 0.27.130.1 support for RTL8852C Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 4/7] wifi: rtw89: coex: fix BT scoreboard update for non-C2H paths Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 5/7] wifi: rtw89: add instance of IO ops for (un)pack and [um]delay Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 6/7] wifi: rtw89: coex: offload 8852C IO writes via firmware CMD pack region Ping-Ke Shih
2026-09-23  7:13 ` [PATCH rtw-next 7/7] wifi: rtw89: coex: batch PTA init with masked IO offload Ping-Ke Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox