public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO
@ 2026-03-10  8:01 Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC Ping-Ke Shih
                   ` (12 more replies)
  0 siblings, 13 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

Mainly, this patchset is to add hardware settings, and tweak code related
to hardware MLO mode value. Others are almost random fixes.

The first four patches are to configure hardware settings, which are
written according to internal patches.

Patches 5-8 are to refine hardware MLO mode.

Patch 9 is WoWLAN related, which is to add retry times to let WoWLAN
being reliable.

Patch 10 is to remove mutex lock from driver. Since driver has used
wiphy_lock, it should be not necessary.

Patch 11 is a workaround to deal with AP interoperability problem.

Patch 12 is to recalculate AMSDU length to improve performance.

The last patch is for firmware crash simulation.

Chin-Yen Lee (1):
  wifi: rtw89: wow: add retry for ensuring packet are processed

Ping-Ke Shih (4):
  wifi: rtw89: mac: finish active TX immediately without waiting for
    DMAC
  wifi: rtw89: pci: update SER parameters for suspend/resume
  wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A
  wifi: rtw89: phy: limit AMPDU number for RA try rate

Po-Hao Huang (2):
  wifi: rtw89: Drop malformed AMPDU frames with abnormal PN
  wifi: rtw89: Recalculate station aggregates when AMSDU length changes
    for MLO links

Zong-Zhe Yang (6):
  wifi: rtw89: move disabling dynamic mechanism functions to core
  wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7
  wifi: rtw89: chan: simplify link handling related to ROC
  wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode
  wifi: rtw89: replace RF mutex with wiphy lock assertion
  wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode

 drivers/net/wireless/realtek/rtw89/chan.c     |  72 +++++----
 drivers/net/wireless/realtek/rtw89/core.c     | 150 +++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/core.h     |  29 ++--
 drivers/net/wireless/realtek/rtw89/debug.c    |  45 ++----
 drivers/net/wireless/realtek/rtw89/mac.c      |  17 +-
 drivers/net/wireless/realtek/rtw89/mac.h      |   2 +
 drivers/net/wireless/realtek/rtw89/mac80211.c |   6 +
 drivers/net/wireless/realtek/rtw89/mac_be.c   |   5 +
 drivers/net/wireless/realtek/rtw89/pci.h      |   1 +
 drivers/net/wireless/realtek/rtw89/pci_be.c   |  52 +++++-
 drivers/net/wireless/realtek/rtw89/phy.c      |  46 +++++-
 drivers/net/wireless/realtek/rtw89/phy.h      |   1 +
 drivers/net/wireless/realtek/rtw89/reg.h      |  28 ++++
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |   2 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |   2 +-
 drivers/net/wireless/realtek/rtw89/util.h     |  17 ++
 drivers/net/wireless/realtek/rtw89/wow.c      |   2 +
 drivers/net/wireless/realtek/rtw89/wow.h      |   7 -
 18 files changed, 386 insertions(+), 98 deletions(-)


base-commit: 039cd522dc70151da13329a5e3ae19b1736f468a
-- 
2.25.1


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

* [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-12  3:00   ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume Ping-Ke Shih
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

Currently active TX only finishes after ensuring PCIE and DMAC become idle.
However, the waiting time might be long. Since the packet is already
transmitted over the air, update the registers to finish active TX
immediately, regardless of the PCIE/DMAC status.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/mac_be.c |  3 +++
 drivers/net/wireless/realtek/rtw89/reg.h    | 28 +++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index dc66b1ee851a..ed1ea13bb98d 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -1173,6 +1173,9 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
 	if (ret)
 		return ret;
 
+	reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_MISC_1, mac_idx);
+	rtw89_write32_set(rtwdev, reg, B_BE_EN_TX_FINISH_PRD_RESP);
+
 	if (chip->chip_id == RTL8922D) {
 		reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EXT_CTRL, mac_idx);
 		rtw89_write32_set(rtwdev, reg, B_BE_CWCNT_PLUS_MODE);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 9b605617c3f0..66ed847c9009 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -6745,6 +6745,34 @@
 #define B_BE_MUEDCA_EN_MASK GENMASK(1, 0)
 #define B_BE_MUEDCA_EN_0 BIT(0)
 
+#define R_BE_MISC_1 0x1037C
+#define R_BE_MISC_1_C1 0x1437C
+#define B_BE_PPS_REMAIN_TIME_MODE BIT(31)
+#define B_BE_PPS_IDLE_SORT_EN BIT(30)
+#define B_BE_SR_TXOP_USE_SR_PERIOD_EN BIT(29)
+#define B_BE_SCH_CCA_PIFS_CLK_GATING_DIS BIT(28)
+#define B_BE_SR_TXOP_EN BIT(27)
+#define B_BE_SCH_ABORT_CNT_SIFS_EN BIT(26)
+#define B_BE_SCH_ABORT_CNT_TB_EN BIT(25)
+#define B_BE_SCH_ABORT_CNT_CTN_EN BIT(24)
+#define B_BE_SR_CCA_PER20_BITMAP_EN BIT(23)
+#define B_BE_SR_CCA_S80_EN BIT(22)
+#define B_BE_SR_CCA_S40_EN BIT(21)
+#define B_BE_SR_CCA_S20_EN BIT(20)
+#define B_BE_EN_TX_FINISH_PRD_RESP BIT(18)
+#define B_BE_RESP_TX_ABORT_NON_IDLE BIT(17)
+#define B_BE_RESP_TX_ABORT_QUICK_EN BIT(16)
+#define B_BE_PREBKF_CHK_LINK_BUSY BIT(15)
+#define B_BE_SCH_MSD_PRD_RST_EDCA_EN BIT(14)
+#define B_BE_LINK_BUSY_RST_EDCA_EN_MASK GENMASK(13, 12)
+#define B_BE_RX_TSFT_SYNC_BYPASS_FCS BIT(11)
+#define B_BE_RX_TSFT_DIFF_THD_MASK GENMASK(10, 8)
+#define B_BE_CAL_TBTT_OV_EN BIT(5)
+#define B_BE_SUBBCN_MS_CNT_MODE BIT(3)
+#define B_BE_CAL_ALWAYS_EN BIT(2)
+#define B_BE_SIFS_TIMER_AUTO_RST_EN BIT(1)
+#define B_BE_CHK_HAS_SIFS_TX_ABORT BIT(0)
+
 #define R_BE_CTN_DRV_TXEN 0x10398
 #define R_BE_CTN_DRV_TXEN_C1 0x14398
 #define B_BE_CTN_TXEN_TWT_3 BIT(17)
-- 
2.25.1


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

* [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-16  6:53   ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 03/13] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A Ping-Ke Shih
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

In suspend mode, SER timer unit is different from normal mode. Set proper
value to prevent expected SER happened during suspend.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/pci.h    |  1 +
 drivers/net/wireless/realtek/rtw89/pci_be.c | 52 +++++++++++++++++++--
 2 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index ccfa6d33623a..dc488d9a8884 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -1016,6 +1016,7 @@
 #define B_BE_PL1_IGNORE_HOT_RST BIT(30)
 #define B_BE_PL1_TIMER_UNIT_MASK GENMASK(19, 17)
 #define PCIE_SER_TIMER_UNIT 0x2
+#define PCIE_SER_WOW_TIMER_UNIT 0x4
 #define B_BE_PL1_TIMER_CLEAR BIT(0)
 
 #define R_BE_REG_PL1_MASK 0x34B0
diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c
index 114f40c6c31b..dea01d9e57fd 100644
--- a/drivers/net/wireless/realtek/rtw89/pci_be.c
+++ b/drivers/net/wireless/realtek/rtw89/pci_be.c
@@ -721,12 +721,24 @@ static int __maybe_unused rtw89_pci_suspend_be(struct device *dev)
 {
 	struct ieee80211_hw *hw = dev_get_drvdata(dev);
 	struct rtw89_dev *rtwdev = hw->priv;
+	u32 val32;
 
 	rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
 	rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
 	rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
 	rtw89_write32_set(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
-	rtw89_write32_clr(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
+
+	val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+	if (val32 & B_BE_PL1_SER_PL1_EN) {
+		val32 = u32_replace_bits(val32, PCIE_SER_WOW_TIMER_UNIT,
+					 B_BE_PL1_TIMER_UNIT_MASK);
+		rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32);
+
+		if (rtwdev->chip->chip_id == RTL8922A)
+			rtw89_write32_clr(rtwdev, R_BE_REG_PL1_MASK,
+					  B_BE_SER_PM_MASTER_IMR);
+	}
+
 	return 0;
 }
 
@@ -735,12 +747,19 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
 	struct ieee80211_hw *hw = dev_get_drvdata(dev);
 	struct rtw89_dev *rtwdev = hw->priv;
 	u32 polling;
+	u32 val32;
+	u16 val16;
 	int ret;
 
 	rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
 	rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_R_DIS_PRST);
 	rtw89_write32_clr(rtwdev, R_BE_RSV_CTRL, B_BE_WLOCK_1C_BIT6);
 	rtw89_write32_clr(rtwdev, R_BE_PCIE_FRZ_CLK, B_BE_PCIE_FRZ_REG_RST);
+
+	val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+	if (!(val32 & B_BE_PL1_SER_PL1_EN))
+		goto clear_phy_isr;
+
 	rtw89_write32_clr(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
 
 	ret = read_poll_timeout_atomic(rtw89_read32, polling, !polling, 1, 1000,
@@ -748,8 +767,35 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
 	if (ret)
 		rtw89_warn(rtwdev, "[ERR] PCIE SER clear polling fail\n");
 
-	rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
-	rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
+	if (rtwdev->chip->chip_id == RTL8922A)
+		rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK,
+				  B_BE_SER_PM_MASTER_IMR | B_BE_SER_PCLKREQ_ACK_MASK);
+
+	val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL);
+	val32 = u32_replace_bits(val32, PCIE_SER_TIMER_UNIT, B_BE_PL1_TIMER_UNIT_MASK);
+	val32 |= B_BE_PL1_SER_PL1_EN;
+	rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32);
+
+clear_phy_isr:
+	if (rtwdev->chip->chip_id == RTL8922D) {
+		val16 = rtw89_read16(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+					     RAC_ANA41 * RAC_MULT);
+		if (val16 & PHY_ERR_FLAG_EN) {
+			rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+						  RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+			rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G2 +
+						  RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+		}
+
+		val16 = rtw89_read16(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+					     RAC_ANA41 * RAC_MULT);
+		if (val16 & PHY_ERR_FLAG_EN) {
+			rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+						  RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+			rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G1 +
+						  RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN);
+		}
+	}
 
 	rtw89_pci_basic_cfg(rtwdev, true);
 
-- 
2.25.1


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

* [PATCH rtw-next 03/13] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 04/13] wifi: rtw89: phy: limit AMPDU number for RA try rate Ping-Ke Shih
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

Fix timing issue of A-die off followed by XTAL off. Otherwise, device might
get lost potentially.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8852c.c | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index e62a7288c8aa..7ea0a8905282 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -463,7 +463,7 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev)
 	else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
 		rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_EDSWR);
 
-	rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_XTAL_OFF_A_DIE);
+	rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_XTAL_OFF_A_DIE);
 	rtw89_write32_set(rtwdev, R_AX_SYS_SWR_CTRL1, B_AX_SYM_CTRL_SPS_PWMFREQ);
 	rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
 			   B_AX_REG_ZCDC_H_MASK, 0x3);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 36ef36110602..a489aaf90f23 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -492,7 +492,7 @@ static int rtw8922a_pwr_off_func(struct rtw89_dev *rtwdev)
 		return ret;
 
 	rtw89_write32(rtwdev, R_BE_WLLPS_CTRL, 0x0000A1B2);
-	rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_XTAL_OFF_A_DIE);
+	rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_XTAL_OFF_A_DIE);
 	rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
 	rtw89_write32(rtwdev, R_BE_UDM1, 0);
 
-- 
2.25.1


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

* [PATCH rtw-next 04/13] wifi: rtw89: phy: limit AMPDU number for RA try rate
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (2 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 03/13] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 05/13] wifi: rtw89: move disabling dynamic mechanism functions to core Ping-Ke Shih
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

When RA (Rate Adaptive) does try higher rate, a TRY bit is flagged, and
hardware will reference registers configured by this patch as maximum
number of AMPDU. To prevent aggregate too many MPDU over peer's capability
causing loss in peer side, set the minimum values across all stations and
TID since there is single one register per hardware band. Consider MLD
case, a BA session can run across two hardware bands, so set the same
value as well.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c      |  2 ++
 drivers/net/wireless/realtek/rtw89/mac.h      |  1 +
 drivers/net/wireless/realtek/rtw89/mac80211.c |  3 +++
 drivers/net/wireless/realtek/rtw89/mac_be.c   |  2 ++
 drivers/net/wireless/realtek/rtw89/phy.c      | 27 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/phy.h      |  1 +
 6 files changed, 36 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 234928613ef4..a292a14394b2 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -7319,6 +7319,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
 	},
 	.wow_ctrl = {.addr = R_AX_WOW_CTRL, .mask = B_AX_WOW_WOWEN,},
 	.agg_limit = {.addr = R_AX_AMPDU_AGG_LIMIT, .mask = B_AX_AMPDU_MAX_TIME_MASK,},
+	.ra_agg_limit = {.addr = R_AX_AMPDU_AGG_LIMIT,
+			 .mask = B_AX_RA_TRY_RATE_AGG_LMT_MASK,},
 	.txcnt_limit = {.addr = R_AX_TXCNT, .mask = B_AX_L_TXCNT_LMT_MASK,},
 
 	.check_mac_en = rtw89_mac_check_mac_en_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index e6b715b95409..9c77bfaa34ee 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1037,6 +1037,7 @@ struct rtw89_mac_gen_def {
 	struct rtw89_reg_def narrow_bw_ru_dis;
 	struct rtw89_reg_def wow_ctrl;
 	struct rtw89_reg_def agg_limit;
+	struct rtw89_reg_def ra_agg_limit;
 	struct rtw89_reg_def txcnt_limit;
 
 	int (*check_mac_en)(struct rtw89_dev *rtwdev, u8 band,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 1ef73bfc40d1..cd8e2c8de888 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -1005,6 +1005,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
 		clear_bit(tid, rtwsta->ampdu_map);
 		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		rtw89_leave_ps_mode(rtwdev);
+		rtw89_phy_ra_recalc_agg_limit(rtwdev);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
@@ -1013,6 +1015,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
 		set_bit(tid, rtwsta->ampdu_map);
 		rtw89_leave_ps_mode(rtwdev);
 		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
+		rtw89_phy_ra_recalc_agg_limit(rtwdev);
 		break;
 	case IEEE80211_AMPDU_RX_START:
 		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params);
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index ed1ea13bb98d..b9e8f4fa366b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -3196,6 +3196,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
 	},
 	.wow_ctrl = {.addr = R_BE_WOW_CTRL, .mask = B_BE_WOW_WOWEN,},
 	.agg_limit = {.addr = R_BE_AMPDU_AGG_LIMIT, .mask = B_BE_AMPDU_MAX_TIME_MASK,},
+	.ra_agg_limit = {.addr = R_BE_AMPDU_AGG_LIMIT,
+			 .mask = B_BE_RA_TRY_RATE_AGG_LMT_MASK,},
 	.txcnt_limit = {.addr = R_BE_TXCNT, .mask = B_BE_L_TXCNT_LMT_MASK,},
 
 	.check_mac_en = rtw89_mac_check_mac_en_be,
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 74f5d5562848..0fa4d8d791f1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -775,6 +775,33 @@ void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
 	rtw89_fw_h2c_ra(rtwdev, ra, csi);
 }
 
+void rtw89_phy_ra_recalc_agg_limit(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+	const struct rtw89_reg_def *ra_limit = &mac->ra_agg_limit;
+	struct ieee80211_sta *sta;
+	struct rtw89_sta *rtwsta;
+	u16 agg_num = U16_MAX;
+	u8 tid;
+
+	for_each_station(sta, rtwdev->hw) {
+		rtwsta = sta_to_rtwsta(sta);
+
+		for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS)
+			agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num);
+	}
+
+	if (agg_num == U16_MAX)
+		agg_num = 0x3F;
+	else
+		agg_num = clamp(agg_num, 1, 256) - 1;
+
+	rtw89_write32_idx(rtwdev, ra_limit->addr, ra_limit->mask, agg_num, RTW89_MAC_0);
+	if (!rtwdev->dbcc_en)
+		return;
+	rtw89_write32_idx(rtwdev, ra_limit->addr, ra_limit->mask, agg_num, RTW89_MAC_1);
+}
+
 u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
 		      const struct rtw89_chan *chan,
 		      enum rtw89_bandwidth dbw)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 094c7e45f254..bde419edf744 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -1006,6 +1006,7 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta
 void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
 				  struct rtw89_sta_link *rtwsta_link,
 				  u32 changed);
+void rtw89_phy_ra_recalc_agg_limit(struct rtw89_dev *rtwdev);
 void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
 				struct ieee80211_vif *vif,
 				const struct cfg80211_bitrate_mask *mask);
-- 
2.25.1


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

* [PATCH rtw-next 05/13] wifi: rtw89: move disabling dynamic mechanism functions to core
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (3 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 04/13] wifi: rtw89: phy: limit AMPDU number for RA try rate Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 06/13] wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7 Ping-Ke Shih
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

Some dynamic mechanism (DM) may need to be disabled during some normal
processes rather than debugging. For example, should not do MLSR switch
during SCAN/ROC or even MCC. So, move the disabling DM functions to core
for impending uses.

No logic changes.

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.c  | 29 ++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/core.h  |  3 ++
 drivers/net/wireless/realtek/rtw89/debug.c | 35 ++--------------------
 3 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 9d9b91570989..81004ef18168 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -4713,6 +4713,35 @@ static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work)
 		rtw89_enter_lps_track(rtwdev);
 }
 
+void rtw89_core_dm_disable_cfg(struct rtw89_dev *rtwdev, u32 new)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u32 old = hal->disabled_dm_bitmap;
+
+	if (new == old)
+		return;
+
+	hal->disabled_dm_bitmap = new;
+
+	rtw89_debug(rtwdev, RTW89_DBG_STATE, "Disable DM: 0x%x -> 0x%x\n", old, new);
+}
+
+void rtw89_core_dm_disable_set(struct rtw89_dev *rtwdev, enum rtw89_dm_type type)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u32 cur = hal->disabled_dm_bitmap;
+
+	rtw89_core_dm_disable_cfg(rtwdev, cur | BIT(type));
+}
+
+void rtw89_core_dm_disable_clr(struct rtw89_dev *rtwdev, enum rtw89_dm_type type)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u32 cur = hal->disabled_dm_bitmap;
+
+	rtw89_core_dm_disable_cfg(rtwdev, cur & ~BIT(type));
+}
+
 u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size)
 {
 	unsigned long bit;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index cf0cc718f41c..05f8ad6d3034 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -7862,5 +7862,8 @@ void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,
 void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event);
 int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 			   unsigned int link_id);
+void rtw89_core_dm_disable_cfg(struct rtw89_dev *rtwdev, u32 new);
+void rtw89_core_dm_disable_set(struct rtw89_dev *rtwdev, enum rtw89_dm_type type);
+void rtw89_core_dm_disable_clr(struct rtw89_dev *rtwdev, enum rtw89_dm_type type);
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 3e16ed2c4570..aee0f25e036a 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -4333,35 +4333,6 @@ static ssize_t rtw89_debug_priv_stations_get(struct rtw89_dev *rtwdev,
 	return p - buf;
 }
 
-static void rtw89_debug_disable_dm_cfg_bmap(struct rtw89_dev *rtwdev, u32 new)
-{
-	struct rtw89_hal *hal = &rtwdev->hal;
-	u32 old = hal->disabled_dm_bitmap;
-
-	if (new == old)
-		return;
-
-	hal->disabled_dm_bitmap = new;
-
-	rtw89_debug(rtwdev, RTW89_DBG_STATE, "Disable DM: 0x%x -> 0x%x\n", old, new);
-}
-
-static void rtw89_debug_disable_dm_set_flag(struct rtw89_dev *rtwdev, u8 flag)
-{
-	struct rtw89_hal *hal = &rtwdev->hal;
-	u32 cur = hal->disabled_dm_bitmap;
-
-	rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur | BIT(flag));
-}
-
-static void rtw89_debug_disable_dm_clr_flag(struct rtw89_dev *rtwdev, u8 flag)
-{
-	struct rtw89_hal *hal = &rtwdev->hal;
-	u32 cur = hal->disabled_dm_bitmap;
-
-	rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur & ~BIT(flag));
-}
-
 #define DM_INFO(type) {RTW89_DM_ ## type, #type}
 
 static const struct rtw89_disabled_dm_info {
@@ -4412,7 +4383,7 @@ rtw89_debug_priv_disable_dm_set(struct rtw89_dev *rtwdev,
 	if (ret)
 		return -EINVAL;
 
-	rtw89_debug_disable_dm_cfg_bmap(rtwdev, conf);
+	rtw89_core_dm_disable_cfg(rtwdev, conf);
 
 	return count;
 }
@@ -4475,7 +4446,7 @@ rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev,
 	if (num != 2)
 		return -EINVAL;
 
-	rtw89_debug_disable_dm_set_flag(rtwdev, RTW89_DM_MLO);
+	rtw89_core_dm_disable_set(rtwdev, RTW89_DM_MLO);
 
 	rtw89_debug(rtwdev, RTW89_DBG_STATE, "Set MLO mode to %x\n", mlo_mode);
 
@@ -4485,7 +4456,7 @@ rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev,
 		break;
 	default:
 		rtw89_debug(rtwdev, RTW89_DBG_STATE, "Unsupported MLO mode\n");
-		rtw89_debug_disable_dm_clr_flag(rtwdev, RTW89_DM_MLO);
+		rtw89_core_dm_disable_clr(rtwdev, RTW89_DM_MLO);
 
 		return -EOPNOTSUPP;
 	}
-- 
2.25.1


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

* [PATCH rtw-next 06/13] wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (4 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 05/13] wifi: rtw89: move disabling dynamic mechanism functions to core Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 07/13] wifi: rtw89: chan: simplify link handling related to ROC Ping-Ke Shih
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

The support_mlo flag depends on FW features, so it's determined at runtime.
Since Wi-Fi 7 chip now needs to initialize second HW band, if support_mlo
is not allowed, second HW band might act without settings of TX power and
channel. So, set that for Wi-Fi 7 chip.

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.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 81004ef18168..6ab99a3577f3 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -463,7 +463,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
 	chan = rtw89_mgnt_chan_get(rtwdev, 0);
 	__rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_0);
 
-	if (!rtwdev->support_mlo)
+	if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
 		return;
 
 	chan = rtw89_mgnt_chan_get(rtwdev, 1);
@@ -558,7 +558,7 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev)
 	chan = rtw89_mgnt_chan_get(rtwdev, 0);
 	__rtw89_set_channel(rtwdev, chan, RTW89_MAC_0, RTW89_PHY_0);
 
-	if (!rtwdev->support_mlo)
+	if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
 		return 0;
 
 	chan = rtw89_mgnt_chan_get(rtwdev, 1);
-- 
2.25.1


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

* [PATCH rtw-next 07/13] wifi: rtw89: chan: simplify link handling related to ROC
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (5 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 06/13] wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7 Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 08/13] wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode Ping-Ke Shih
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

The original channel is swapped out for the target channel during ROC.
And, all vifs/links accessing the original channel will be marked with
off-channel. So, it doesn't seem necessary for chan.c to determine which
link instance it is.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/chan.c | 11 -----------
 drivers/net/wireless/realtek/rtw89/core.h |  1 -
 2 files changed, 12 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 9b2f6f0a00fd..def9e4f3af59 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -276,7 +276,6 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
 		}
 
 		hal->roc_chandef = *chandef;
-		hal->roc_link_index = rtw89_vif_link_inst_get_index(rtwvif_link);
 	} else {
 		cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx,
 				     RTW89_CHANCTX_IDLE);
@@ -389,7 +388,6 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
 	struct rtw89_hal *hal = &rtwdev->hal;
 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
 	enum rtw89_chanctx_idx chanctx_idx;
-	enum rtw89_chanctx_idx roc_idx;
 	enum rtw89_entity_mode mode;
 	u8 role_index;
 
@@ -419,15 +417,6 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
 	if (chanctx_idx == RTW89_CHANCTX_IDLE)
 		goto dflt;
 
-	roc_idx = atomic_read(&hal->roc_chanctx_idx);
-	if (roc_idx != RTW89_CHANCTX_IDLE) {
-		/* ROC is ongoing (given ROC runs on @hal->roc_link_index).
-		 * If @link_index is the same, get the ongoing ROC chanctx.
-		 */
-		if (link_index == hal->roc_link_index)
-			chanctx_idx = roc_idx;
-	}
-
 	return rtw89_chan_get(rtwdev, chanctx_idx);
 
 dflt:
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 05f8ad6d3034..01573150ab3c 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5170,7 +5170,6 @@ struct rtw89_hal {
 	bool no_eht;
 
 	atomic_t roc_chanctx_idx;
-	u8 roc_link_index;
 
 	DECLARE_BITMAP(changes, NUM_OF_RTW89_CHANCTX_CHANGES);
 	DECLARE_BITMAP(entity_map, NUM_OF_RTW89_CHANCTX);
-- 
2.25.1


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

* [PATCH rtw-next 08/13] wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (6 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 07/13] wifi: rtw89: chan: simplify link handling related to ROC Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 09/13] wifi: rtw89: wow: add retry for ensuring packet are processed Ping-Ke Shih
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

Since MLD vif can do MLSR switch, it may not always run on HW band 0.
But when preparing MCC for MLD + P2P, P2P vif needs to use HW band 0
to handle connection, i.e. uses of HW bands may be different by vif.

The current major role/vif can be indicated through entity mode. So,
based on it, recalculate MLO DBCC mode to change use of HW band.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/chan.c | 61 +++++++++++++++--------
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index def9e4f3af59..ceb399fc2b94 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -381,6 +381,23 @@ static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
 	rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
 }
 
+static u8 rtw89_entity_role_get_index(struct rtw89_dev *rtwdev)
+{
+	enum rtw89_entity_mode mode;
+
+	mode = rtw89_get_entity_mode(rtwdev);
+	switch (mode) {
+	default:
+		WARN(1, "Invalid ent mode: %d\n", mode);
+		fallthrough;
+	case RTW89_ENTITY_MODE_SCC_OR_SMLD:
+	case RTW89_ENTITY_MODE_MCC:
+		return 0;
+	case RTW89_ENTITY_MODE_MCC_PREPARE:
+		return 1;
+	}
+}
+
 const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
 					       const char *caller_message,
 					       u8 link_index, bool nullchk)
@@ -388,7 +405,6 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
 	struct rtw89_hal *hal = &rtwdev->hal;
 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
 	enum rtw89_chanctx_idx chanctx_idx;
-	enum rtw89_entity_mode mode;
 	u8 role_index;
 
 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
@@ -399,19 +415,7 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
 		goto dflt;
 	}
 
-	mode = rtw89_get_entity_mode(rtwdev);
-	switch (mode) {
-	case RTW89_ENTITY_MODE_SCC_OR_SMLD:
-	case RTW89_ENTITY_MODE_MCC:
-		role_index = 0;
-		break;
-	case RTW89_ENTITY_MODE_MCC_PREPARE:
-		role_index = 1;
-		break;
-	default:
-		WARN(1, "Invalid ent mode: %d\n", mode);
-		goto dflt;
-	}
+	role_index = rtw89_entity_role_get_index(rtwdev);
 
 	chanctx_idx = mgnt->chanctx_tbl[role_index][link_index];
 	if (chanctx_idx == RTW89_CHANCTX_IDLE)
@@ -479,10 +483,28 @@ rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
 	}
 }
 
-static
-void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
+static void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev)
 {
+	struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
 	enum rtw89_mlo_dbcc_mode mode;
+	struct rtw89_vif *role;
+	u8 active_hws = 0;
+	u8 ridx;
+
+	ridx = rtw89_entity_role_get_index(rtwdev);
+	role = mgnt->active_roles[ridx];
+	if (role) {
+		struct rtw89_vif_link *link;
+		int i;
+
+		for (i = 0; i < role->links_inst_valid_num; i++) {
+			link = rtw89_vif_get_link_inst(role, i);
+			if (!link || !link->chanctx_assigned)
+				continue;
+
+			active_hws |= BIT(i);
+		}
+	}
 
 	mode = rtw89_entity_sel_mlo_dbcc_mode(rtwdev, active_hws);
 	rtwdev->mlo_dbcc_mode = mode;
@@ -496,7 +518,6 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
 	struct rtw89_vif_link *link;
 	struct rtw89_vif *role;
-	u8 active_hws = 0;
 	u8 pos = 0;
 	int i, j;
 
@@ -545,13 +566,10 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
 				continue;
 
 			mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
-			active_hws |= BIT(i);
 		}
 
 		mgnt->active_roles[pos++] = role;
 	}
-
-	rtw89_entity_recalc_mlo_dbcc_mode(rtwdev, active_hws);
 }
 
 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
@@ -621,6 +639,9 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
 		return rtw89_get_entity_mode(rtwdev);
 
 	rtw89_set_entity_mode(rtwdev, mode);
+
+	rtw89_entity_recalc_mlo_dbcc_mode(rtwdev);
+
 	return mode;
 }
 
-- 
2.25.1


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

* [PATCH rtw-next 09/13] wifi: rtw89: wow: add retry for ensuring packet are processed
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (7 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 08/13] wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 10/13] wifi: rtw89: replace RF mutex with wiphy lock assertion Ping-Ke Shih
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

From: Chin-Yen Lee <timlee@realtek.com>

Before entering WoWLAN mode, the driver must ensure that
all received packets have been processed to prevent packet
loss. Consequently, a retry mechanism has been implemented
to guarantee completion.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c | 15 ++++++++++++++-
 drivers/net/wireless/realtek/rtw89/mac.h |  1 +
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index a292a14394b2..35fd18fe6470 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -7183,7 +7183,7 @@ int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
 	return ret;
 }
 
-int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
+static int _rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
 {
 	struct rtw89_mac_h2c_info h2c_info = {};
 	struct rtw89_mac_c2h_info c2h_info = {};
@@ -7206,6 +7206,19 @@ int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
 	return ret;
 }
 
+int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
+{
+	int i, ret;
+
+	for (i = 0; i < CPU_IO_RX_RETRY_CNT; i++) {
+		ret = _rtw89_mac_cpu_io_rx(rtwdev, wow_enable);
+		if (!ret)
+			return 0;
+	}
+
+	return ret;
+}
+
 static int rtw89_wow_config_mac_ax(struct rtw89_dev *rtwdev, bool enable_wow)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 9c77bfaa34ee..88a877556cb3 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -17,6 +17,7 @@
 #define BSSID_CAM_ENT_SIZE 0x08
 #define HFC_PAGE_UNIT 64
 #define RPWM_TRY_CNT 3
+#define CPU_IO_RX_RETRY_CNT 3
 
 enum rtw89_mac_hwmod_sel {
 	RTW89_DMAC_SEL = 0,
-- 
2.25.1


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

* [PATCH rtw-next 10/13] wifi: rtw89: replace RF mutex with wiphy lock assertion
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (8 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 09/13] wifi: rtw89: wow: add retry for ensuring packet are processed Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 11/13] wifi: rtw89: Drop malformed AMPDU frames with abnormal PN Ping-Ke Shih
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

Now, stack has introduced wiphy lock. And, the normal paths calling
RF read/write should be under wiphy lock. So, replace RF mutex with
wiphy lock assertion. Besides, in dbgfs paths, add the corresponding
lock option.

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.c  |  2 --
 drivers/net/wireless/realtek/rtw89/core.h  | 14 ++++----------
 drivers/net/wireless/realtek/rtw89/debug.c |  6 +++---
 3 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 6ab99a3577f3..18dbf3664f0a 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -6147,7 +6147,6 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
 		return -ENOMEM;
 	spin_lock_init(&rtwdev->ba_lock);
 	spin_lock_init(&rtwdev->rpwm_lock);
-	mutex_init(&rtwdev->rf_mutex);
 	rtwdev->total_sta_assoc = 0;
 
 	rtw89_init_wait(&rtwdev->mcc.wait);
@@ -6206,7 +6205,6 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev)
 	__rtw89_fw_free_all_early_h2c(rtwdev);
 
 	destroy_workqueue(rtwdev->txq_wq);
-	mutex_destroy(&rtwdev->rf_mutex);
 }
 EXPORT_SYMBOL(rtw89_core_deinit);
 
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 01573150ab3c..ce04ecaa3a5e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -6182,8 +6182,6 @@ struct rtw89_dev {
 	refcount_t refcount_ap_info;
 
 	struct list_head rtwvifs_list;
-	/* used to protect rf read write */
-	struct mutex rf_mutex;
 	struct workqueue_struct *txq_wq;
 	struct work_struct txq_work;
 	struct delayed_work txq_reinvoke_work;
@@ -6808,22 +6806,18 @@ static inline u32
 rtw89_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 	      u32 addr, u32 mask)
 {
-	u32 val;
-
-	mutex_lock(&rtwdev->rf_mutex);
-	val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
-	mutex_unlock(&rtwdev->rf_mutex);
+	lockdep_assert_wiphy(rtwdev->hw->wiphy);
 
-	return val;
+	return rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
 }
 
 static inline void
 rtw89_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 	       u32 addr, u32 mask, u32 data)
 {
-	mutex_lock(&rtwdev->rf_mutex);
+	lockdep_assert_wiphy(rtwdev->hw->wiphy);
+
 	rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
-	mutex_unlock(&rtwdev->rf_mutex);
 }
 
 static inline u32 rtw89_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr)
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index aee0f25e036a..d461ffc6dc9e 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -4859,9 +4859,9 @@ rtw89_debug_priv_beacon_info_get(struct rtw89_dev *rtwdev,
 static const struct rtw89_debugfs rtw89_debugfs_templ = {
 	.read_reg = rtw89_debug_priv_select_and_get(read_reg),
 	.write_reg = rtw89_debug_priv_set(write_reg),
-	.read_rf = rtw89_debug_priv_select_and_get(read_rf),
-	.write_rf = rtw89_debug_priv_set(write_rf),
-	.rf_reg_dump = rtw89_debug_priv_get(rf_reg_dump, RSIZE_8K),
+	.read_rf = rtw89_debug_priv_select_and_get(read_rf, RLOCK),
+	.write_rf = rtw89_debug_priv_set(write_rf, WLOCK),
+	.rf_reg_dump = rtw89_debug_priv_get(rf_reg_dump, RSIZE_8K, RLOCK),
 	.txpwr_table = rtw89_debug_priv_get(txpwr_table, RSIZE_20K, RLOCK),
 	.mac_reg_dump = rtw89_debug_priv_select_and_get(mac_reg_dump, RSIZE_128K),
 	.mac_mem_dump = rtw89_debug_priv_select_and_get(mac_mem_dump, RSIZE_16K, RLOCK),
-- 
2.25.1


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

* [PATCH rtw-next 11/13] wifi: rtw89: Drop malformed AMPDU frames with abnormal PN
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (9 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 10/13] wifi: rtw89: replace RF mutex with wiphy lock assertion Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 12/13] wifi: rtw89: Recalculate station aggregates when AMSDU length changes for MLO links Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 13/13] wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode Ping-Ke Shih
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

From: Po-Hao Huang <phhuang@realtek.com>

Fix connection issue caused by AMPDU frames with abnormal PN patterns
(out-of-order packets with correct MPDU sequence numbers but paired
with abnormal PN values, which is next PN of previous in-order packet).
This is causing packet drops, low throughput and disconnections. It is
observed in fields with some specific AP firmwares. Do this workaround for
better interoperability since some APs could never receive a proper FW
update.

Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.c     | 115 ++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/core.h     |  11 ++
 drivers/net/wireless/realtek/rtw89/mac80211.c |   3 +
 drivers/net/wireless/realtek/rtw89/util.h     |  17 +++
 drivers/net/wireless/realtek/rtw89/wow.c      |   2 +
 drivers/net/wireless/realtek/rtw89/wow.h      |   7 --
 6 files changed, 148 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 18dbf3664f0a..9d3f651798ff 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -3272,6 +3272,114 @@ static void rtw89_core_correct_mcc_chan(struct rtw89_dev *rtwdev,
 	rcu_read_unlock();
 }
 
+static void __rtw89_core_tid_rx_stats_reset(struct rtw89_tid_stats *tid_stats)
+{
+	tid_stats->last_pn = -1LL;
+	tid_stats->last_sn = IEEE80211_SN_MASK;
+}
+
+void rtw89_core_tid_rx_stats_ctrl(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+				  struct ieee80211_ampdu_params *params, bool enable)
+{
+	struct rtw89_tid_stats *tid_stats;
+	u16 tid = params->tid;
+
+	tid_stats = &rtwsta->tid_rx_stats[tid];
+
+	if (enable) {
+		__rtw89_core_tid_rx_stats_reset(tid_stats);
+		tid_stats->started = true;
+	} else {
+		tid_stats->started = false;
+	}
+}
+
+void rtw89_core_tid_rx_stats_reset(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_tid_stats *tid_stats;
+	struct ieee80211_sta *sta;
+	struct rtw89_sta *rtwsta;
+	u16 tid;
+
+	for_each_station(sta, rtwdev->hw) {
+		rtwsta = sta_to_rtwsta(sta);
+
+		for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
+			tid_stats = &rtwsta->tid_rx_stats[tid];
+
+			if (!tid_stats->started)
+				continue;
+
+			__rtw89_core_tid_rx_stats_reset(tid_stats);
+		}
+	}
+}
+
+static bool rtw89_core_skb_pn_valid(struct rtw89_dev *rtwdev,
+				    struct rtw89_rx_desc_info *desc_info,
+				    struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_tid_stats *tid_stats;
+	struct rtw89_sta *rtwsta;
+	u8 tid, *ccmp_hdr_ptr;
+	s64 pn, last_pn;
+	u16 mpdu_sn;
+	int hdrlen;
+
+	if (chip->chip_gen != RTW89_CHIP_AX)
+		return true;
+
+	if (!ieee80211_is_data_qos(hdr->frame_control))
+		return true;
+
+	if (!desc_info->hw_dec || !desc_info->addr1_match)
+		return true;
+
+	guard(rcu)();
+
+	rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, desc_info->mac_id);
+	if (!rtwsta_link)
+		return true;
+
+	rtwsta = rtwsta_link->rtwsta;
+	tid = ieee80211_get_tid(hdr);
+	tid_stats = &rtwsta->tid_rx_stats[tid];
+
+	if (!tid_stats->started)
+		return true;
+
+	switch (desc_info->sec_type) {
+	case RTW89_SEC_KEY_TYPE_CCMP128:
+	case RTW89_SEC_KEY_TYPE_CCMP256:
+	case RTW89_SEC_KEY_TYPE_GCMP128:
+	case RTW89_SEC_KEY_TYPE_GCMP256:
+		mpdu_sn = ieee80211_get_sn(hdr);
+		hdrlen = ieee80211_hdrlen(hdr->frame_control);
+		ccmp_hdr_ptr = skb->data + hdrlen;
+		ccmp_hdr2pn(&pn, ccmp_hdr_ptr);
+		last_pn = tid_stats->last_pn;
+
+		if (pn > last_pn) {
+			if (ieee80211_sn_less(mpdu_sn, tid_stats->last_sn)) {
+				dev_kfree_skb_any(skb);
+
+				return false;
+			}
+
+			tid_stats->last_sn = mpdu_sn;
+			tid_stats->last_pn = pn;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
 static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
 				      struct rtw89_rx_phy_ppdu *phy_ppdu,
 				      struct rtw89_rx_desc_info *desc_info,
@@ -3421,6 +3529,7 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev,
 	desc_info->sec_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_SEC_CAM_IDX_MASK);
 	desc_info->mac_id = le32_get_bits(rxd_l->dword5, AX_RXD_MAC_ID_MASK);
 	desc_info->rx_pl_id = le32_get_bits(rxd_l->dword5, AX_RXD_RX_PL_ID_MASK);
+	desc_info->sec_type = le32_get_bits(rxd_l->dword7, AX_RXD_SEC_TYPE_MASK);
 }
 EXPORT_SYMBOL(rtw89_core_query_rxdesc);
 
@@ -3450,6 +3559,7 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
 	desc_info->mac_id = le32_get_bits(rxd_s->dword2, BE_RXD_MAC_ID_MASK);
 	desc_info->addr_cam_valid = le32_get_bits(rxd_s->dword2, BE_RXD_ADDR_CAM_VLD);
 
+	desc_info->sec_type = le32_get_bits(rxd_s->dword3, BE_RXD_SEC_TYPE_MASK);
 	desc_info->icv_err = le32_get_bits(rxd_s->dword3, BE_RXD_ICV_ERR);
 	desc_info->crc32_err = le32_get_bits(rxd_s->dword3, BE_RXD_CRC32_ERR);
 	desc_info->hw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_HW_DEC);
@@ -3523,6 +3633,7 @@ void rtw89_core_query_rxdesc_v3(struct rtw89_dev *rtwdev,
 	desc_info->mac_id = le32_get_bits(rxd_s->dword2, BE_RXD_MAC_ID_V1);
 	desc_info->addr_cam_valid = le32_get_bits(rxd_s->dword2, BE_RXD_ADDR_CAM_VLD);
 
+	desc_info->sec_type = le32_get_bits(rxd_s->dword3, BE_RXD_SEC_TYPE_MASK);
 	desc_info->icv_err = le32_get_bits(rxd_s->dword3, BE_RXD_ICV_ERR);
 	desc_info->crc32_err = le32_get_bits(rxd_s->dword3, BE_RXD_CRC32_ERR);
 	desc_info->hw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_HW_DEC);
@@ -3802,6 +3913,10 @@ void rtw89_core_rx(struct rtw89_dev *rtwdev,
 	memset(rx_status, 0, sizeof(*rx_status));
 	rtw89_core_update_rx_status(rtwdev, skb, desc_info, rx_status);
 	rtw89_core_rx_pkt_hdl(rtwdev, skb, desc_info);
+
+	if (!rtw89_core_skb_pn_valid(rtwdev, desc_info, skb))
+		return;
+
 	if (desc_info->long_rxdesc &&
 	    BIT(desc_info->frame_type) & PPDU_FILTER_BITMAP)
 		skb_queue_tail(&ppdu_sts->rx_queue[band], skb);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index ce04ecaa3a5e..94e4faf70e12 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -1126,6 +1126,7 @@ struct rtw89_rx_desc_info {
 	bool addr_cam_valid;
 	u8 addr_cam_id;
 	u8 sec_cam_id;
+	u8 sec_type;
 	u8 mac_id;
 	u16 offset;
 	u16 rxd_len;
@@ -6153,6 +6154,12 @@ struct rtw89_beacon_track_info {
 	u32 tbtt_diff_th;
 };
 
+struct rtw89_tid_stats {
+	s64 last_pn;
+	u16 last_sn;
+	bool started;
+};
+
 struct rtw89_dev {
 	struct ieee80211_hw *hw;
 	struct device *dev;
@@ -6359,6 +6366,7 @@ struct rtw89_sta {
 	struct sk_buff_head roc_queue;
 
 	struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
+	struct rtw89_tid_stats tid_rx_stats[IEEE80211_NUM_TIDS];
 	DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
 
 	DECLARE_BITMAP(pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
@@ -7769,6 +7777,9 @@ int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev,
 void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
 			       struct ieee80211_sta *sta,
 			       struct cfg80211_tid_config *tid_config);
+void rtw89_core_tid_rx_stats_ctrl(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+				  struct ieee80211_ampdu_params *params, bool enable);
+void rtw89_core_tid_rx_stats_reset(struct rtw89_dev *rtwdev);
 void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force);
 void rtw89_check_quirks(struct rtw89_dev *rtwdev, const struct dmi_system_id *quirks);
 int rtw89_core_init(struct rtw89_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index cd8e2c8de888..501c3af1da01 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -964,6 +964,7 @@ static int rtw89_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			rtw89_err(rtwdev, "failed to add key to sec cam\n");
 			return ret;
 		}
+		rtw89_core_tid_rx_stats_reset(rtwdev);
 		break;
 	case DISABLE_KEY:
 		flush_work(&rtwdev->txq_work);
@@ -1018,9 +1019,11 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
 		rtw89_phy_ra_recalc_agg_limit(rtwdev);
 		break;
 	case IEEE80211_AMPDU_RX_START:
+		rtw89_core_tid_rx_stats_ctrl(rtwdev, rtwsta, params, true);
 		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params);
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
+		rtw89_core_tid_rx_stats_ctrl(rtwdev, rtwsta, params, false);
 		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, false, params);
 		break;
 	default:
diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h
index bd08495301e4..c16e7a7f8bc9 100644
--- a/drivers/net/wireless/realtek/rtw89/util.h
+++ b/drivers/net/wireless/realtek/rtw89/util.h
@@ -6,6 +6,13 @@
 
 #include "core.h"
 
+#define RTW89_KEY_PN_0 GENMASK_ULL(7, 0)
+#define RTW89_KEY_PN_1 GENMASK_ULL(15, 8)
+#define RTW89_KEY_PN_2 GENMASK_ULL(23, 16)
+#define RTW89_KEY_PN_3 GENMASK_ULL(31, 24)
+#define RTW89_KEY_PN_4 GENMASK_ULL(39, 32)
+#define RTW89_KEY_PN_5 GENMASK_ULL(47, 40)
+
 #define rtw89_iterate_vifs_bh(rtwdev, iterator, data)                          \
 	ieee80211_iterate_active_interfaces_atomic((rtwdev)->hw,               \
 			IEEE80211_IFACE_ITER_NORMAL, iterator, data)
@@ -73,6 +80,16 @@ static inline void ether_addr_copy_mask(u8 *dst, const u8 *src, u8 mask)
 	}
 }
 
+static inline void ccmp_hdr2pn(s64 *pn, const u8 *hdr)
+{
+	*pn = u64_encode_bits(hdr[0], RTW89_KEY_PN_0) |
+	      u64_encode_bits(hdr[1], RTW89_KEY_PN_1) |
+	      u64_encode_bits(hdr[4], RTW89_KEY_PN_2) |
+	      u64_encode_bits(hdr[5], RTW89_KEY_PN_3) |
+	      u64_encode_bits(hdr[6], RTW89_KEY_PN_4) |
+	      u64_encode_bits(hdr[7], RTW89_KEY_PN_5);
+}
+
 s32 rtw89_linear_to_db_quarter(u64 val);
 s32 rtw89_linear_to_db(u64 val);
 u64 rtw89_db_quarter_to_linear(s32 db);
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 368e08826f1e..8dadd8df4fc6 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -1741,6 +1741,8 @@ static int rtw89_wow_disable(struct rtw89_dev *rtwdev)
 
 	rtw89_wow_leave_ps(rtwdev, false);
 
+	rtw89_core_tid_rx_stats_reset(rtwdev);
+
 	ret = rtw89_wow_fw_stop(rtwdev);
 	if (ret) {
 		rtw89_err(rtwdev, "wow: failed to swap to normal fw\n");
diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h
index 71e07f482174..d7e67632efeb 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.h
+++ b/drivers/net/wireless/realtek/rtw89/wow.h
@@ -8,13 +8,6 @@
 #define RTW89_KEY_TKIP_PN_IV16 GENMASK_ULL(15, 0)
 #define RTW89_KEY_TKIP_PN_IV32 GENMASK_ULL(47, 16)
 
-#define RTW89_KEY_PN_0 GENMASK_ULL(7, 0)
-#define RTW89_KEY_PN_1 GENMASK_ULL(15, 8)
-#define RTW89_KEY_PN_2 GENMASK_ULL(23, 16)
-#define RTW89_KEY_PN_3 GENMASK_ULL(31, 24)
-#define RTW89_KEY_PN_4 GENMASK_ULL(39, 32)
-#define RTW89_KEY_PN_5 GENMASK_ULL(47, 40)
-
 #define RTW89_IGTK_IPN_0 GENMASK_ULL(7, 0)
 #define RTW89_IGTK_IPN_1 GENMASK_ULL(15, 8)
 #define RTW89_IGTK_IPN_2 GENMASK_ULL(23, 16)
-- 
2.25.1


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

* [PATCH rtw-next 12/13] wifi: rtw89: Recalculate station aggregates when AMSDU length changes for MLO links
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (10 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 11/13] wifi: rtw89: Drop malformed AMPDU frames with abnormal PN Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  2026-03-10  8:01 ` [PATCH rtw-next 13/13] wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode Ping-Ke Shih
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

From: Po-Hao Huang <phhuang@realtek.com>

Currently, AMSDU length is updated per-link for MLO but not propagated
to the station aggregates, causing suboptimal TX throughput. This change
ensures station aggregates are recalculated when any link's AMSDU length
changes.

Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 0fa4d8d791f1..3a241738ac06 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -3213,7 +3213,8 @@ struct rtw89_phy_iter_ra_data {
 
 static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
 					struct ieee80211_link_sta *link_sta,
-					struct rtw89_phy_iter_ra_data *ra_data)
+					struct rtw89_phy_iter_ra_data *ra_data,
+					bool *changed)
 {
 	struct rtw89_dev *rtwdev = ra_data->rtwdev;
 	const struct rtw89_c2h_ra_rpt *c2h =
@@ -3222,7 +3223,7 @@ static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	bool format_v1 = chip->chip_gen == RTW89_CHIP_BE;
 	u8 mode, rate, bw, giltf, mac_id;
-	u16 legacy_bitrate;
+	u16 legacy_bitrate, amsdu_len;
 	bool valid;
 	u8 mcs = 0;
 	u8 t;
@@ -3319,7 +3320,13 @@ static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
 			     u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) |
 			     u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL);
 	ra_report->might_fallback_legacy = mcs <= 2;
-	link_sta->agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
+
+	amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
+	if (link_sta->agg.max_rc_amsdu_len != amsdu_len) {
+		link_sta->agg.max_rc_amsdu_len = amsdu_len;
+		*changed = true;
+	}
+
 	rtwsta_link->max_agg_wait = link_sta->agg.max_rc_amsdu_len / 1500 - 1;
 }
 
@@ -3330,14 +3337,18 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
 	struct rtw89_sta_link *rtwsta_link;
 	struct ieee80211_link_sta *link_sta;
 	unsigned int link_id;
+	bool changed = false;
 
 	rcu_read_lock();
 
 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
 		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
-		__rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data);
+		__rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data, &changed);
 	}
 
+	if (changed)
+		ieee80211_sta_recalc_aggregates(sta);
+
 	rcu_read_unlock();
 }
 
-- 
2.25.1


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

* [PATCH rtw-next 13/13] wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode
  2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
                   ` (11 preceding siblings ...)
  2026-03-10  8:01 ` [PATCH rtw-next 12/13] wifi: rtw89: Recalculate station aggregates when AMSDU length changes for MLO links Ping-Ke Shih
@ 2026-03-10  8:01 ` Ping-Ke Shih
  12 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-10  8:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

Current triggers of Wi-Fi 7 SER (system error recovery) L0/L1 simulation
don't yet guarantee working with PS mode. So, leave PS mode first before
triggering them for now.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/debug.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index d461ffc6dc9e..82849d109cc3 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -3552,6 +3552,8 @@ static int rtw89_dbg_trigger_l1_error_by_halt_h2c_be(struct rtw89_dev *rtwdev)
 	if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
 		return -EBUSY;
 
+	rtw89_leave_ps_mode(rtwdev);
+
 	rtw89_write32_set(rtwdev, R_BE_FW_TRIGGER_IDCT_ISR,
 			  B_BE_DMAC_FW_TRIG_IDCT | B_BE_DMAC_FW_ERR_IDCT_IMR);
 
@@ -3654,6 +3656,8 @@ static int rtw89_dbg_trigger_l0_error_by_halt_h2c_be(struct rtw89_dev *rtwdev)
 	if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
 		return -EBUSY;
 
+	rtw89_leave_ps_mode(rtwdev);
+
 	rtw89_write32_set(rtwdev, R_BE_CMAC_FW_TRIGGER_IDCT_ISR,
 			  B_BE_CMAC_FW_TRIG_IDCT | B_BE_CMAC_FW_ERR_IDCT_IMR);
 
-- 
2.25.1


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

* Re: [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC
  2026-03-10  8:01 ` [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC Ping-Ke Shih
@ 2026-03-12  3:00   ` Ping-Ke Shih
  0 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-12  3:00 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

> Currently active TX only finishes after ensuring PCIE and DMAC become idle.
> However, the waiting time might be long. Since the packet is already
> transmitted over the air, update the registers to finish active TX
> immediately, regardless of the PCIE/DMAC status.
> 
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>

As internal test, this will affect performance, so drop this. Still keep
remaining patches.

Set patchset state to Not Applicable

[rtw-next,01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC

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


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

* Re: [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume
  2026-03-10  8:01 ` [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume Ping-Ke Shih
@ 2026-03-16  6:53   ` Ping-Ke Shih
  0 siblings, 0 replies; 16+ messages in thread
From: Ping-Ke Shih @ 2026-03-16  6:53 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless; +Cc: timlee, phhuang, kevin_yang

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

> In suspend mode, SER timer unit is different from normal mode. Set proper
> value to prevent expected SER happened during suspend.
> 
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>

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

177520960c01 wifi: rtw89: pci: update SER parameters for suspend/resume
9a38ef92aaa2 wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A
84f5e0eaf84e wifi: rtw89: phy: limit AMPDU number for RA try rate
be28b2c4eed4 wifi: rtw89: move disabling dynamic mechanism functions to core
4516621686cb wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7
2fed8de4eb98 wifi: rtw89: chan: simplify link handling related to ROC
cf3cd3687d8a wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode
72dbc78594a1 wifi: rtw89: wow: add retry for ensuring packet are processed
829b89c2b08f wifi: rtw89: replace RF mutex with wiphy lock assertion
bda294ed0ed0 wifi: rtw89: Drop malformed AMPDU frames with abnormal PN
45ba9226b108 wifi: rtw89: Recalculate station aggregates when AMSDU length changes for MLO links
a1488456f706 wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode

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


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

end of thread, other threads:[~2026-03-16  6:53 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10  8:01 [PATCH rtw-next 00/13] wifi: rtw89: update hardware settings and tweak for MLO Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 01/13] wifi: rtw89: mac: finish active TX immediately without waiting for DMAC Ping-Ke Shih
2026-03-12  3:00   ` Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 02/13] wifi: rtw89: pci: update SER parameters for suspend/resume Ping-Ke Shih
2026-03-16  6:53   ` Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 03/13] wifi: rtw89: mac: remove A-die off setting for RTL8852C and RTL8922A Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 04/13] wifi: rtw89: phy: limit AMPDU number for RA try rate Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 05/13] wifi: rtw89: move disabling dynamic mechanism functions to core Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 06/13] wifi: rtw89: tweak settings of TX power and channel for Wi-Fi 7 Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 07/13] wifi: rtw89: chan: simplify link handling related to ROC Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 08/13] wifi: rtw89: chan: recalc MLO DBCC mode based on current entity mode Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 09/13] wifi: rtw89: wow: add retry for ensuring packet are processed Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 10/13] wifi: rtw89: replace RF mutex with wiphy lock assertion Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 11/13] wifi: rtw89: Drop malformed AMPDU frames with abnormal PN Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 12/13] wifi: rtw89: Recalculate station aggregates when AMSDU length changes for MLO links Ping-Ke Shih
2026-03-10  8:01 ` [PATCH rtw-next 13/13] wifi: rtw89: debug: simulate Wi-Fi 7 SER L0/L1 without PS mode 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