Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 1/3] Fix overread in PREQ frame processing
From: Masashi Honma @ 2026-05-11  8:58 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <ecb7aef2f18cc7c04817be155017a54a45fa579e.camel@sipsolutions.net>

Thank you for your reviews!

> Please send new versions with a version tag ('v2' in the subject etc.),

Yes. I used --subject-prefix incorrectly, so I will correct it from next time.

> and not in the old thread, that just messes up the threads.

Yes.

> Ideally tag which tree these should go to, though I think given the many other
> things I'll put this into wireless-next anyway, unless you strongly feel
> it needs to be in wireless?

I'm happy to put this into wireless-next.

> Also, please use appropriate "wifi: mac80211: " prefix in the subject.

Yes.

> This isn't really right since u32_field_get() exists only within
> mesh_hwmp.c ... it's probably better to modernise all this while at it:

Ah, yes. Both the build and tests passed, so I overlooked it.

> and restructure the code accordingly?
> Anyway, I dunno. Maybe we should just go with your original patch for
> now. Maybe I'm also asking more of you than others because you have an
> LLM to help ;-)

If it is not urgent, I would like to proceed with the requested restructuring.
Actually, I only used the LLM to find potential vulnerabilities, and I wrote
the code myself :)

2026年5月11日(月) 16:47 Johannes Berg <johannes@sipsolutions.net>:
>
> Hi,
>
> Please send new versions with a version tag ('v2' in the subject etc.),
> and not in the old thread, that just messes up the threads. Ideally tag
> which tree these should go to, though I think given the many other
> things I'll put this into wireless-next anyway, unless you strongly feel
> it needs to be in wireless?
>
> Also, please use appropriate "wifi: mac80211: " prefix in the subject.
>
> > +#define PREQ_IE_PREQ_ID(x)   u32_field_get(x, 3, 0)
>
> This isn't really right since u32_field_get() exists only within
> mesh_hwmp.c ... it's probably better to modernise all this while at it:
>
> #define IEEE80211_MESH_HWMP_FLAGS_AE    0x40
>
> struct ieee80211_mesh_hwmp_target {
>         u8 flags;
>         u8 addr[ETH_ALEN];
>         __le32 sn;
> } __packed;
>
> struct ieee80211_mesh_hwmp_element {
>         u8 flags;
>         u8 hopcount;
>         u8 ttl;
>         __le32 preq_id;
>         u8 orig_addr[ETH_ALEN];
>         __le32 orig_sn;
>
>         /* optional AE, lifetime, metric, target */
>         u8 variable[];
> } __packed;
>
> and then some inlines like
>
> static inline const struct ieee80211_mesh_hwmp_target *
> ieee80211_mesh_hwmp_get_target(const struct ieee80211_mesh_hwmp_element *elem)
> {
>         int offs = 8; // seems wrong
>
>         if (elem->flags & IEEE80211_MESH_HWMP_FLAGS_AE)
>                 offs += ETH_ALEN;
>
>         return (const void *)&elem->variable[offs];
> }
>
> static inline u32
> ieee80211_mesh_hwmp_get_lifetime(const struct ieee80211_mesh_hwmp_element *elem)
> {
>         int offs = FIXME; // not sure
>
>         if (elem->flags & IEEE80211_MESH_HWMP_FLAGS_AE)
>                 offs += ETH_ALEN;
>
>         return (const void *)&elem->variable[offs];
> }
>
> and restructure the code accordingly?
>
> Anyway, I dunno. Maybe we should just go with your original patch for
> now. Maybe I'm also asking more of you than others because you have an
> LLM to help ;-)
>
> johannes

^ permalink raw reply

* Re: [PATCH wireless-next] wifi: mac80211: Fix ADDBA request rejection after MLD link removal
From: Johannes Berg @ 2026-05-11  8:46 UTC (permalink / raw)
  To: Manish Dharanenthiran; +Cc: linux-wireless, Hari Naraayana Desikan Kannan
In-Reply-To: <dbb28e3e-5022-4915-93e3-dd428ea59507@oss.qualcomm.com>

On Mon, 2026-05-11 at 11:56 +0530, Manish Dharanenthiran wrote:
> No, there is no implementations that combine these two, but there are 
> cases where the update AddBA request can be received from the station 
> with link reconfiguration.
> 
> For instance, if a station associated in 2 GHz, later with link 
> reconfiguration station can either move to 5 GHz or it can add 5 GHz (as 
> MLD). Station then can send a AddBA request to update the window size or 
> other related parameters.

Ah, well, OK - technically an implementation can do that all the time
(and technically we can refuse it all the time), but I guess then that
some implementations do it with link reconfiguration, and also don't
like the refusal :)

> 
> We believe that a no-op update is not required (or at-least we couldn't 
> think of a case in which that is actually needed) as there can might be 
> an actual change in the subsequent AddBA request.

I just think that once we require an UPDATE call from the driver, that
raises the question of whether we should even call it for a no-op. This
seems a bit strange? And if we don't then we wouldn't require it for no-
ops either, which is probably generally good for drivers that don't
(immediately) implement the UPDATE.

johannes

^ permalink raw reply

* Re: [syzbot] [wireless?] WARNING in ieee80211_sta_current_bw
From: Johannes Berg @ 2026-05-11  8:42 UTC (permalink / raw)
  To: Lachlan Hodges, syzbot
  Cc: linux-kernel, linux-wireless, netdev, syzkaller-bugs
In-Reply-To: <64ddfb37q7ll3uyxbf3vuaicurz2p2lwqf5shnoepk53bucsll@o6uvujysizof>

Hi Lachlan,

On Mon, 2026-05-11 at 12:22 +1000, Lachlan Hodges wrote:
> > WARNING: ./include/net/mac80211.h:8114 at ieee80211_chan_width_to_rx_bw include/net/mac80211.h:8114 [inline], CPU#1: syz.4.4769/22510
> > WARNING: ./include/net/mac80211.h:8114 at ieee80211_sta_current_bw_tx_to_sta net/mac80211/sta_info.c:3719 [inline], CPU#1: syz.4.4769/22510
> > WARNING: ./include/net/mac80211.h:8114 at ieee80211_sta_current_bw+0x36d/0x510 net/mac80211/sta_info.c:3745, CPU#1: syz.4.4769/22510
> > Modules linked in:
> > CPU: 1 UID: 0 PID: 22510 Comm: syz.4.4769 Not tainted syzkaller #0 PREEMPT(full) 
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
> > RIP: 0010:ieee80211_chan_width_to_rx_bw include/net/mac80211.h:8114 [inline]
> > RIP: 0010:ieee80211_sta_current_bw_tx_to_sta net/mac80211/sta_info.c:3719 [inline]
> > RIP: 0010:ieee80211_sta_current_bw+0x36d/0x510 net/mac80211/sta_info.c:3745
> > Code: 00 00 00 eb 49 41 83 fe 05 74 30 41 83 fe 0d 75 13 e8 47 8f af f6 b8 04 00 00 00 eb 31 e8 3b 8f af f6 eb 28 e8 34 8f af f6 90 <0f> 0b 90 eb 1d e8 29 8f af f6 b8 02 00 00 00 eb 13 e8 1d 8f af f6
> > RSP: 0018:ffffc90006f4eed8 EFLAGS: 00010283
> > RAX: ffffffff8b161cfc RBX: 1ffff1100d1da030 RCX: 0000000000080000
> > RDX: ffffc9000e5d2000 RSI: 0000000000000e31 RDI: 0000000000000e32
> > RBP: 0000000000000004 R08: ffff888054ad5c40 R09: 0000000000000007
> > R10: 000000000000000d R11: 0000000000000002 R12: ffff888068ed0180
> > R13: dffffc0000000000 R14: 0000000000000007 R15: 0000000000000000
> > FS:  00007fe58f5f66c0(0000) GS:ffff888125389000(0000) knlGS:0000000000000000
> > CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > CR2: 000000110c2c8823 CR3: 0000000038486000 CR4: 00000000003526f0
> 
> This looks to be 10MHz given R14 = 7 which seems to be the operand
> being compared I think. The 2 patches I sent the other week should
> fix this occuring for any S1G bandwidths, not sure about 5 and 10MHz.

Thanks for taking a look at this! I'll apply those soon, seems the test
bot got stuck again.

> Atleast for this situation, it would be the same - we don't wanna
> recalc the mindef for 5 and 10MHz since the mindef isn't recalculated
> for 5/10MHz like S1G. But then I'm not sure the S1G workaround for
> ieee80211_sta_init_nss_bw_capa since maybe nss might be greater than
> 1 for 5/10MHz?

Technically, yes. However, 5/10 is pretty much unreachable in practice.
I had proposed removing it a long time ago, we should probably just do
that...

johannes

^ permalink raw reply

* [PATCH wireless-next] wifi: p54: Use flexible array for channel list
From: Rosen Penev @ 2026-05-11  7:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Christian Lamparter, Kees Cook, Gustavo A. R. Silva, open list,
	open list:KERNEL HARDENING (not covered by other areas):Keyword:b__counted_by(_le|_be)?b

Store generated channel entries in the p54 channel list allocation
instead of allocating them separately.

This ties the temporary channel entries to the list lifetime, removes a
separate allocation failure path, and lets __counted_by() describe the
array bounds.

Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/net/wireless/intersil/p54/eeprom.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c
index 95580921d933..c617bec787a3 100644
--- a/drivers/net/wireless/intersil/p54/eeprom.c
+++ b/drivers/net/wireless/intersil/p54/eeprom.c
@@ -77,10 +77,10 @@ struct p54_channel_entry {
 };
 
 struct p54_channel_list {
-	struct p54_channel_entry *channels;
 	size_t entries;
 	size_t max_entries;
 	size_t band_channel_num[NUM_NL80211_BANDS];
+	struct p54_channel_entry channels[] __counted_by(max_entries);
 };
 
 static int p54_get_band_from_freq(u16 freq)
@@ -335,24 +335,21 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
 	max_channel_num = max_t(unsigned int, max_channel_num,
 				priv->curve_data->entries);
 
-	list = kzalloc_obj(*list);
+	list = kzalloc_flex(*list, channels, max_channel_num);
 	if (!list) {
 		ret = -ENOMEM;
 		goto free;
 	}
-	priv->chan_num = max_channel_num;
+
+	list->max_entries = max_channel_num;
+
 	priv->survey = kzalloc_objs(struct survey_info, max_channel_num);
 	if (!priv->survey) {
 		ret = -ENOMEM;
 		goto free;
 	}
 
-	list->max_entries = max_channel_num;
-	list->channels = kzalloc_objs(struct p54_channel_entry, max_channel_num);
-	if (!list->channels) {
-		ret = -ENOMEM;
-		goto free;
-	}
+	priv->chan_num = max_channel_num;
 
 	for (i = 0; i < max_channel_num; i++) {
 		if (i < priv->iq_autocal_len) {
@@ -401,10 +398,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
 	}
 
 free:
-	if (list) {
-		kfree(list->channels);
-		kfree(list);
-	}
+	kfree(list);
 	if (ret) {
 		kfree(priv->survey);
 		priv->survey = NULL;
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH 1/3] Fix overread in PREQ frame processing
From: Johannes Berg @ 2026-05-11  7:47 UTC (permalink / raw)
  To: Masashi Honma, linux-wireless
In-Reply-To: <20260509234143.101237-1-masashi.honma@gmail.com>

Hi,

Please send new versions with a version tag ('v2' in the subject etc.),
and not in the old thread, that just messes up the threads. Ideally tag
which tree these should go to, though I think given the many other
things I'll put this into wireless-next anyway, unless you strongly feel
it needs to be in wireless?

Also, please use appropriate "wifi: mac80211: " prefix in the subject.

> +#define PREQ_IE_PREQ_ID(x)	u32_field_get(x, 3, 0)

This isn't really right since u32_field_get() exists only within
mesh_hwmp.c ... it's probably better to modernise all this while at it:

#define IEEE80211_MESH_HWMP_FLAGS_AE	0x40

struct ieee80211_mesh_hwmp_target {
	u8 flags;
	u8 addr[ETH_ALEN];
	__le32 sn;
} __packed;

struct ieee80211_mesh_hwmp_element {
	u8 flags;
	u8 hopcount;
	u8 ttl;
	__le32 preq_id;
	u8 orig_addr[ETH_ALEN];
	__le32 orig_sn;

	/* optional AE, lifetime, metric, target */
	u8 variable[];
} __packed;

and then some inlines like

static inline const struct ieee80211_mesh_hwmp_target *
ieee80211_mesh_hwmp_get_target(const struct ieee80211_mesh_hwmp_element *elem)
{
	int offs = 8; // seems wrong

	if (elem->flags & IEEE80211_MESH_HWMP_FLAGS_AE)
		offs += ETH_ALEN;
	
	return (const void *)&elem->variable[offs];
}

static inline u32
ieee80211_mesh_hwmp_get_lifetime(const struct ieee80211_mesh_hwmp_element *elem)
{
	int offs = FIXME; // not sure

	if (elem->flags & IEEE80211_MESH_HWMP_FLAGS_AE)
		offs += ETH_ALEN;
	
	return (const void *)&elem->variable[offs];
}

and restructure the code accordingly?

Anyway, I dunno. Maybe we should just go with your original patch for
now. Maybe I'm also asking more of you than others because you have an
LLM to help ;-)

johannes

^ permalink raw reply

* Re: iwlwifi: network not back after resuming from suspend since v6.15-rc2
From: Grumbach, Emmanuel @ 2026-05-11  7:17 UTC (permalink / raw)
  To: coiby.xu@gmail.com, linux-wireless@vger.kernel.org
  Cc: Korenblit, Miriam Rachel
In-Reply-To: <agFzc-Ngf_ZFXJ3o@Rk>

Hi,


On Mon, 2026-05-11 at 14:49 +0800, Coiby Xu wrote:
> Hi Emmanuel,
> 
> I notice since v6.15-rc2, most of the times the network won't be back
> again after resuming from suspend. And sometimes I need to run
> "systemctl suspend" for 8 or 9 consecutive times to make WIFI
> available
> again. bisect and manual reverting show 15220a257319 ("wifi: iwlwifi:
> don't warn if the NIC is gone in resume") is the 1st bad commit. 
> 

This is ... strange.
Can you try to use our backport tree?
https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/backport-iwlwifi.git/log/

I am pretty sure it won't solve anything, but at least, it'll make it
easier for us to work together on this issue.

Also, may I suggest you open a bugzilla ticket on the drivers /
wireless-intel component?
As a starting point, I'll absolutely need the kernel log.


> Here are some other clues that may help resolve this issue,
> 
>      1. An iwlwifi setting [1] can make this issue disappear,
>         options iwlwifi swcrypto=0
>         options iwlwifi bt_coex_active=0
>         options iwlwifi power_save=0
>         options iwlwifi uapsd_disable=1
>         options iwlmvm power_scheme=1

This is even more strange.

> 
>      2. Before v6.15-rc2, the issue rarely happens. And if it
> happens,
>         simply suspending once can bring the network online again.
> Other
>         users seem to have experienced the same issue e.g. [2][3][4].
> 
>      3. Suspending by "rtcwake -m mem -s 5" instead of by "systemcl
> suspend"
>         can make it much easier to reproduce this issue for kernels
> older
>         than v6.15-rc2.
> 
> If you need more details from me, feel free to let me know! And I'll
> very happy to test any possible solutions. Thanks!

My problem here is that we seem to be talking about "the issue" but we
don't know exactly which one... Let's start with a bugzilla ticket with
logs.


<snip>

> I can't bisect against upstream kernel directly because v6.15-rc2
> won't
> be able to mount my root partition. So I manually reverted upstream
> 15220a257319 ("wifi: iwlwifi: don't warn if the NIC is gone in
> resume")
> in v6.15 to confirm it's indeed the bad commit.
> 
> [1] https://bbs.archlinux.org/viewtopic.php?pid=2227202#p2227202
> [2] https://bbs.archlinux.org/viewtopic.php?id=301971
> [3]
> https://discussion.fedoraproject.org/t/random-wi-fi-adapter-loss-on-fedora-42-intel-alder-lake-p-cnvi/152878
> [4]
> https://forums.opensuse.org/t/wifi-suddenly-no-more-available/184399
> [5]
> https://github.com/coiby/kernel-auto-bisect/tree/random_issue_bisect
> [6] https://github.com/rhkdump/kernel-auto-bisect
> [7]
> https://gitlab.com/cki-project/kernel-ark/-/commit/6453e892cf86c900d51f5884e9013e0dbeeea4ad
> 

Those tickets are all over the place and unfortunately, nothing very
conclusive comes up from those links.

^ permalink raw reply

* [PATCH rtw-next 11/11] wifi: rtw89: phy: add BB wrapper generation 3 for RTL8922D variant
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

The BB wrapper generation 3 support more settings to fine tune power
threshold and CCK CFIR/filter per RFSI band. Add them accordingly.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      |  18 +++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 112 +++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/reg.h      |  70 +++++++++++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  17 +++
 4 files changed, 212 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index ab3c8bb2e851..0a119b5f8159 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -600,6 +600,16 @@ enum rtw89_rfsi_ctrl_modulation {
 	RFSI_MAX,
 };
 
+enum rtw89_cfir_onoff {
+	CFIR_ON = 1,
+	CFIR_OFF = 0,
+};
+
+enum rtw89_filter_onoff {
+	FILTER_A_ON = 1,
+	FILTER_A_OFF = 0,
+};
+
 #define MAX_TX_RFSI_CTRL_OPT 10
 
 #define _8nibble(n0, n1, n2, n3, n4, n5, n6, n7) \
@@ -626,8 +636,16 @@ struct rtw89_bb_wrap_common_data {
 	u8 qam_th[6];
 };
 
+struct rtw89_bb_wrap_common_data_gen3 {
+	struct {
+		u8 qam_th[6];
+	} bands[RFSI_CTRL_BAND_NUM];
+	u8 cck_val[2];
+};
+
 struct rtw89_bb_wrap_data {
 	const struct rtw89_bb_wrap_common_data *common;
+	const struct rtw89_bb_wrap_common_data_gen3 *common_gen3;
 	struct {
 		u16 qam_comp_th0[MAX_TX_RFSI_CTRL_OPT];
 		u16 qam_comp_th1[MAX_TX_RFSI_CTRL_OPT]; /* encoded */
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 387a3e5fd15a..54c91ed4f73d 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -769,6 +769,75 @@ static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(struct rtw89_dev *rtwdev,
 	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH2_BE4, 0x2, mac_idx);
 }
 
+static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_gen3_init(struct rtw89_dev *rtwdev,
+							    const struct rtw89_chan *chan,
+							    enum rtw89_mac_idx mac_idx)
+{
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const struct rtw89_bb_wrap_common_data_gen3 *common_gen3;
+	const u8 *ths;
+
+	if (!d || !d->common_gen3)
+		return;
+
+	common_gen3 = d->common_gen3;
+	ths = common_gen3->bands[chan->rfsi_band].qam_th;
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_0_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_1_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_2_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_3_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_4_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_5_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_6_BE4, ths[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH0_7_BE4, ths[0], mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH1_0_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH0_BE4, B_QAM3_TH1_1_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_2_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_3_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_4_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_5_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_6_BE4, ths[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH1_7_BE4, ths[1], mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH2_0_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH2_1_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH2_2_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH1_BE4, B_QAM3_TH2_3_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH2_4_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH2_5_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH2_6_BE4, ths[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH2_7_BE4, ths[2], mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_0_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_1_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_2_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_3_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_4_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH2_BE4, B_QAM3_TH3_5_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH3_6_BE4, ths[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH3_7_BE4, ths[3], mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_0_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_1_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_2_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_3_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_4_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_5_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_6_BE4, ths[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_TH4_7_BE4, ths[4], mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_0_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_1_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_2_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_3_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_4_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_5_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_6_BE4, ths[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH3_BE4, B_QAM3_TH5_7_BE4, ths[5], mac_idx);
+}
+
 static void rtw89_phy_bb_wrap_tx_rfsi_scenario_def(struct rtw89_dev *rtwdev,
 						   enum rtw89_mac_idx mac_idx)
 {
@@ -987,6 +1056,39 @@ static void rtw89_phy_bb_set_cim3k_val(struct rtw89_dev *rtwdev,
 	rtw89_write32_idx(rtwdev, R_CIM3K_SU_FORCE, B_CIM3K_SU_FORCE_VAL, 0, mac_idx);
 }
 
+static void rtw89_phy_bb_set_cck_cfir_filter_val_gen3(struct rtw89_dev *rtwdev,
+						      enum rtw89_mac_idx mac_idx)
+{
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const struct rtw89_bb_wrap_common_data_gen3 *common_gen3;
+	u8 cck0, cck1;
+
+	if (!d || !d->common_gen3)
+		return;
+
+	common_gen3 = d->common_gen3;
+	cck0 = common_gen3->cck_val[0];
+	cck1 = common_gen3->cck_val[1];
+
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR0_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR1_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR2_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR3_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR4_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR5_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR6_BE4, cck0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_TH4_BE4, B_QAM3_CFIR7_BE4, cck0, mac_idx);
+
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR0_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR1_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR2_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR3_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR4_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR5_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR6_BE4, cck1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM3_FLTR_BE4, B_QAM3_FLTR7_BE4, cck1, mac_idx);
+}
+
 static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev,
 						enum rtw89_mac_idx mac_idx)
 {
@@ -998,18 +1100,18 @@ static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev,
 	if (chip_id != RTL8922D)
 		return;
 
+	rtw89_entity_get_conf(rtwdev, &conf);
+	chan = conf.chans[phy_idx];
+
 	rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(rtwdev, mac_idx);
+	rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_gen3_init(rtwdev, chan, mac_idx);
 	rtw89_phy_bb_wrap_tx_rfsi_scenario_def(rtwdev, mac_idx);
 	rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(rtwdev, mac_idx);
 	rtw89_phy_bb_set_oob_dpd_qam_comp_val(rtwdev, mac_idx);
 	rtw89_phy_bb_set_mdpd_qam_comp_val(rtwdev, mac_idx);
 	rtw89_phy_bb_set_cim3k_val(rtwdev, mac_idx);
-
+	rtw89_phy_bb_set_cck_cfir_filter_val_gen3(rtwdev, mac_idx);
 	rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, 0, phy_idx);
-
-	rtw89_entity_get_conf(rtwdev, &conf);
-	chan = conf.chans[phy_idx];
-
 	rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(rtwdev, chan, phy_idx);
 }
 
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index e46c32ec8e90..c9bfb163c32e 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10599,6 +10599,17 @@
 #define R_CIM3K_SU_FORCE 0x119F8
 #define B_CIM3K_SU_FORCE_EN BIT(17)
 #define B_CIM3K_SU_FORCE_VAL BIT(18)
+#define R_QAM3_TH0_BE4 0x119FC
+#define B_QAM3_TH0_0_BE4 GENMASK(2, 0)
+#define B_QAM3_TH0_1_BE4 GENMASK(5, 3)
+#define B_QAM3_TH0_2_BE4 GENMASK(8, 6)
+#define B_QAM3_TH0_3_BE4 GENMASK(11, 9)
+#define B_QAM3_TH0_4_BE4 GENMASK(14, 12)
+#define B_QAM3_TH0_5_BE4 GENMASK(17, 15)
+#define B_QAM3_TH0_6_BE4 GENMASK(20, 18)
+#define B_QAM3_TH0_7_BE4 GENMASK(23, 21)
+#define B_QAM3_TH1_0_BE4 GENMASK(26, 24)
+#define B_QAM3_TH1_1_BE4 GENMASK(29, 27)
 #define R_RFSI_CT_OPT_0_BE4 0x11A94
 #define R_RFSI_CT_OPT_8_BE4 0x11A98
 #define R_QAM_COMP_TH0_BE4 0x11A9C
@@ -10634,6 +10645,65 @@
 #define B_BANDEDGE_DBW80_BE4 BIT(31)
 #define R_BANDEDGE_DBWY_BE4 0x11AD0
 #define B_BANDEDGE_DBW160_BE4 BIT(0)
+#define R_QAM3_TH1_BE4 0x11BE8
+#define B_QAM3_TH1_2_BE4 GENMASK(2, 0)
+#define B_QAM3_TH1_3_BE4 GENMASK(5, 3)
+#define B_QAM3_TH1_4_BE4 GENMASK(8, 6)
+#define B_QAM3_TH1_5_BE4 GENMASK(11, 9)
+#define B_QAM3_TH1_6_BE4 GENMASK(14, 12)
+#define B_QAM3_TH1_7_BE4 GENMASK(17, 15)
+#define B_QAM3_TH2_0_BE4 GENMASK(20, 18)
+#define B_QAM3_TH2_1_BE4 GENMASK(23, 21)
+#define B_QAM3_TH2_2_BE4 GENMASK(26, 24)
+#define B_QAM3_TH2_3_BE4 GENMASK(29, 27)
+#define R_QAM3_TH2_BE4 0x11BEC
+#define B_QAM3_TH2_4_BE4 GENMASK(2, 0)
+#define B_QAM3_TH2_5_BE4 GENMASK(5, 3)
+#define B_QAM3_TH2_6_BE4 GENMASK(8, 6)
+#define B_QAM3_TH2_7_BE4 GENMASK(11, 9)
+#define B_QAM3_TH3_0_BE4 GENMASK(14, 12)
+#define B_QAM3_TH3_1_BE4 GENMASK(17, 15)
+#define B_QAM3_TH3_2_BE4 GENMASK(20, 18)
+#define B_QAM3_TH3_3_BE4 GENMASK(23, 21)
+#define B_QAM3_TH3_4_BE4 GENMASK(26, 24)
+#define B_QAM3_TH3_5_BE4 GENMASK(29, 27)
+#define R_QAM3_TH3_BE4 0x11BF4
+#define B_QAM3_TH3_6_BE4 GENMASK(2, 0)
+#define B_QAM3_TH3_7_BE4 GENMASK(5, 3)
+#define B_QAM3_TH5_0_BE4 GENMASK(8, 6)
+#define B_QAM3_TH5_1_BE4 GENMASK(11, 9)
+#define B_QAM3_TH5_2_BE4 GENMASK(14, 12)
+#define B_QAM3_TH5_3_BE4 GENMASK(17, 15)
+#define B_QAM3_TH5_4_BE4 GENMASK(20, 18)
+#define B_QAM3_TH5_5_BE4 GENMASK(23, 21)
+#define B_QAM3_TH5_6_BE4 GENMASK(26, 24)
+#define B_QAM3_TH5_7_BE4 GENMASK(29, 27)
+#define R_QAM3_TH4_BE4 0x11BF8
+#define B_QAM3_TH4_0_BE4 GENMASK(2, 0)
+#define B_QAM3_TH4_1_BE4 GENMASK(5, 3)
+#define B_QAM3_TH4_2_BE4 GENMASK(8, 6)
+#define B_QAM3_TH4_3_BE4 GENMASK(11, 9)
+#define B_QAM3_TH4_4_BE4 GENMASK(14, 12)
+#define B_QAM3_TH4_5_BE4 GENMASK(17, 15)
+#define B_QAM3_TH4_6_BE4 GENMASK(20, 18)
+#define B_QAM3_TH4_7_BE4 GENMASK(23, 21)
+#define B_QAM3_CFIR0_BE4 BIT(24)
+#define B_QAM3_CFIR1_BE4 BIT(25)
+#define B_QAM3_CFIR2_BE4 BIT(26)
+#define B_QAM3_CFIR3_BE4 BIT(27)
+#define B_QAM3_CFIR4_BE4 BIT(28)
+#define B_QAM3_CFIR5_BE4 BIT(29)
+#define B_QAM3_CFIR6_BE4 BIT(30)
+#define B_QAM3_CFIR7_BE4 BIT(31)
+#define R_QAM3_FLTR_BE4 0x11BFC
+#define B_QAM3_FLTR0_BE4 GENMASK(1, 0)
+#define B_QAM3_FLTR1_BE4 GENMASK(3, 2)
+#define B_QAM3_FLTR2_BE4 GENMASK(5, 4)
+#define B_QAM3_FLTR3_BE4 GENMASK(7, 6)
+#define B_QAM3_FLTR4_BE4 GENMASK(9, 8)
+#define B_QAM3_FLTR5_BE4 GENMASK(11, 10)
+#define B_QAM3_FLTR6_BE4 GENMASK(13, 12)
+#define B_QAM3_FLTR7_BE4 GENMASK(15, 14)
 
 #define R_SYS_DBCC_BE4 0x20000
 #define B_SYS_DBCC_BE4 BIT(0)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index ade89234afd6..c6c37e25e4c8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -320,8 +320,23 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090
 	.qam_th = {RFSI_BPSK, RFSI_QPSK, RFSI_256QAM, RFSI_MAX, RFSI_MAX, RFSI_MAX},
 };
 
+static const
+struct rtw89_bb_wrap_common_data_gen3 rtw8922d_bb_wrap_common_data_gen3_7090 = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.qam_th = {RFSI_QPSK, RFSI_BPSK, RFSI_256QAM, RFSI_MAX,
+			   RFSI_MAX, RFSI_MAX},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.qam_th = {RFSI_MAX, RFSI_MAX, RFSI_256QAM, RFSI_MAX,
+			   RFSI_MAX, RFSI_MAX},
+	}},
+	.cck_val = {CFIR_OFF, FILTER_A_OFF},
+};
+
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
 	.common = &rtw8922d_bb_wrap_common_data_7025,
+	.common_gen3 = NULL,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.qam_comp_th0 = {0x4000, 0x6400, 0x6500, 0x6000, 0, 0, 0, 0, 0, 0},
@@ -348,6 +363,7 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
 	.common = &rtw8922d_bb_wrap_common_data_7090,
+	.common_gen3 = &rtw8922d_bb_wrap_common_data_gen3_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.qam_comp_th0 = {0x4000, 0x6420, 0x6520, 0x6000, 0, 0, 0, 0, 0, 0},
@@ -374,6 +390,7 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 = {
 	.common = &rtw8922d_bb_wrap_common_data_7090,
+	.common_gen3 = &rtw8922d_bb_wrap_common_data_gen3_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.qam_comp_th0 = {0x4000, 0x6420, 0x6520, 0x6000, 0, 0, 0, 0, 0, 0},
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 10/11] wifi: rtw89: phy: configure control options of BB wrapper by RFSI band
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

The settings of control options are predefined per RFSI band (2GHz band or
not 5/6GHz band) and used for fine-tuning transmit power. Calculate and set
the RFSI band once creating channel context, and use it by BB wrapper
configurations.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/chan.c     | 2 ++
 drivers/net/wireless/realtek/rtw89/core.h     | 8 ++++++++
 drivers/net/wireless/realtek/rtw89/phy.h      | 8 +-------
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 5 +++--
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 2 +-
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index cd846cb81f0c..6f11335b4968 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -150,6 +150,8 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
 						      primary_freq);
 	chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan,
 						    bandwidth);
+	chan->rfsi_band = band == RTW89_BAND_2G ? RFSI_CTRL_BAND_2GHZ :
+						  RFSI_CTRL_BAND_5_6GHZ;
 }
 
 static void _rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index ab9165fcaf7d..205087fd0161 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -993,6 +993,13 @@ enum rtw89_sc_offset {
 	RTW89_SC_40_LOWER	= 10,
 };
 
+enum rtw89_rfsi_ctrl_band {
+	RFSI_CTRL_BAND_5_6GHZ,
+	RFSI_CTRL_BAND_2GHZ,
+
+	RFSI_CTRL_BAND_NUM,
+};
+
 /* only mgd features can be added to the enum */
 enum rtw89_wow_flags {
 	RTW89_WOW_FLAG_EN_MAGIC_PKT,
@@ -1016,6 +1023,7 @@ struct rtw89_chan {
 	enum rtw89_tx_comp_band tx_comp_band;
 	enum rtw89_sc_offset pri_ch_idx;
 	u8 pri_sb_idx;
+	enum rtw89_rfsi_ctrl_band rfsi_band;
 };
 
 struct rtw89_chan_rcd {
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index bfe647b2de25..ab3c8bb2e851 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -569,13 +569,6 @@ struct rtw89_phy_rfk_log_fmt {
 	const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
 };
 
-enum rtw89_rfsi_ctrl_band {
-	RFSI_CTRL_BAND_5_6GHZ,
-	RFSI_CTRL_BAND_2GHZ,
-
-	RFSI_CTRL_BAND_NUM,
-};
-
 enum rtw89_mdpd_onoff {
 	MDPD_ON = 0,
 	MDPD_OFF = 1,
@@ -1026,6 +1019,7 @@ static inline void rtw89_phy_bb_wrap_init(struct rtw89_dev *rtwdev)
 }
 
 void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
+				       enum rtw89_rfsi_ctrl_band ctrl_band,
 				       enum rtw89_phy_idx phy_idx);
 void rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(struct rtw89_dev *rtwdev,
 					    const struct rtw89_chan *chan,
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 23ed170f6d38..387a3e5fd15a 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -646,6 +646,7 @@ static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev,
 }
 
 void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
+				       enum rtw89_rfsi_ctrl_band rfsi_band,
 				       enum rtw89_phy_idx phy_idx)
 {
 	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
@@ -655,7 +656,7 @@ void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
 	if (!d || !d->common)
 		return;
 
-	val = d->common->bands[0].rfsi_ct_opt;
+	val = d->common->bands[rfsi_band].rfsi_ct_opt;
 
 	reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_0_BE4, phy_idx);
 	rtw89_write32(rtwdev, reg, val[0]);
@@ -1004,7 +1005,7 @@ static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev,
 	rtw89_phy_bb_set_mdpd_qam_comp_val(rtwdev, mac_idx);
 	rtw89_phy_bb_set_cim3k_val(rtwdev, mac_idx);
 
-	rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, phy_idx);
+	rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, 0, phy_idx);
 
 	rtw89_entity_get_conf(rtwdev, &conf);
 	chan = conf.chans[phy_idx];
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index ec94067aa1a5..ade89234afd6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2284,7 +2284,7 @@ static void rtw8922d_set_channel_bb(struct rtw89_dev *rtwdev,
 	u8 pri_sb = chan->pri_sb_idx;
 	u32 val;
 
-	rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, phy_idx);
+	rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, chan->rfsi_band, phy_idx);
 	rtw8922d_ctrl_ch(rtwdev, chan, phy_idx);
 	rtw8922d_ctrl_bw(rtwdev, pri_sb, chan->band_width, phy_idx);
 	rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(rtwdev, chan, phy_idx);
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 09/11] wifi: rtw89: phy: change order to align register order
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Change the order to align what vendor driver does.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy_be.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index f8e25167b44d..23ed170f6d38 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -587,8 +587,8 @@ static void rtw89_phy_bb_wrap_force_cr_init(struct rtw89_dev *rtwdev,
 
 	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_FORCE_LMT, mac_idx);
 	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_LMT_ON, 0);
-	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_BOOST, mac_idx);
-	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RATE_ON, 0);
+	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_RATE_CTRL, mac_idx);
+	rtw89_write32_mask(rtwdev, addr, B_BE_FORCE_PWR_BY_RATE_EN, 0);
 	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_OFST_RULMT, mac_idx);
 	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RU_ENON, 0);
 	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RU_ON, 0);
@@ -596,8 +596,8 @@ static void rtw89_phy_bb_wrap_force_cr_init(struct rtw89_dev *rtwdev,
 	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_MACID_ALL, 0);
 	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_COEX_CTRL, mac_idx);
 	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_COEX_ON, 0);
-	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_RATE_CTRL, mac_idx);
-	rtw89_write32_mask(rtwdev, addr, B_BE_FORCE_PWR_BY_RATE_EN, 0);
+	addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_BOOST, mac_idx);
+	rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RATE_ON, 0);
 }
 
 static void rtw89_phy_bb_wrap_ftm_init(struct rtw89_dev *rtwdev,
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 08/11] wifi: rtw89: phy: set BB wrap of CIM3K
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

The options to enable calibrations of CIM 3rd-order for threshold,
non-bandedge and bandedge.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      | 13 ++++++++++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 24 +++++++++++++++----
 drivers/net/wireless/realtek/rtw89/reg.h      |  3 +++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  4 ++++
 4 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 51495701b102..bfe647b2de25 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -586,6 +586,16 @@ enum rtw89_oob_dpd_onoff {
 	OOB_DPD_ON = 1,
 };
 
+enum rtw89_cim3k_onoff {
+	CIM3K_ON = 1,
+	CIM3K_OFF = 0,
+};
+
+enum rtw89_cim3k_en_dis {
+	CIM3K_ENABLE = 1,
+	CIM3K_DISABLE = 0,
+};
+
 enum rtw89_rfsi_ctrl_modulation {
 	RFSI_BPSK = 0,
 	RFSI_QPSK = 1,
@@ -614,6 +624,9 @@ enum rtw89_rfsi_ctrl_modulation {
 
 struct rtw89_bb_wrap_common_data {
 	struct {
+		struct rtw89_bb_wrap_data_cim3k {
+			u8 th, ow, non_bandedge, bandedge;
+		} cim3k;
 		u32 rfsi_ct_opt[2];
 		u8 pb_tb;
 	} bands[RFSI_CTRL_BAND_NUM];
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 75806ffc6242..f8e25167b44d 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -964,10 +964,26 @@ static void rtw89_phy_bb_set_mdpd_qam_comp_val(struct rtw89_dev *rtwdev,
 static void rtw89_phy_bb_set_cim3k_val(struct rtw89_dev *rtwdev,
 				       enum rtw89_mac_idx mac_idx)
 {
-	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_OW_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_NONBE_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_BANDEDGE_BE4, 0x1, mac_idx);
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const struct rtw89_bb_wrap_data_cim3k *p;
+
+	if (!d || !d->common)
+		return;
+
+	p = &d->common->bands[0].cim3k;
+
+	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH_BE4, p->th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_OW_BE4, p->ow, mac_idx);
+	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_NONBE_BE4,
+			  p->non_bandedge, mac_idx);
+	rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_BANDEDGE_BE4,
+			  p->bandedge, mac_idx);
+
+	if (rtwdev->chip->chip_id != RTL8922D)
+		return;
+
+	rtw89_write32_idx(rtwdev, R_CIM3K_SU_FORCE, B_CIM3K_SU_FORCE_EN, 1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_CIM3K_SU_FORCE, B_CIM3K_SU_FORCE_VAL, 0, mac_idx);
 }
 
 static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 716747c3a10e..e46c32ec8e90 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10596,6 +10596,9 @@
 #define B_FBTB_CT_MUMIMO_BE4 GENMASK(19, 16)
 #define B_FBTB_CT_FTM_BE4 GENMASK(23, 20)
 #define B_FBTB_CT_SENS_BE4 GENMASK(27, 24)
+#define R_CIM3K_SU_FORCE 0x119F8
+#define B_CIM3K_SU_FORCE_EN BIT(17)
+#define B_CIM3K_SU_FORCE_VAL BIT(18)
 #define R_RFSI_CT_OPT_0_BE4 0x11A94
 #define R_RFSI_CT_OPT_8_BE4 0x11A98
 #define R_QAM_COMP_TH0_BE4 0x11A9C
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 15c44dd0d9fa..ec94067aa1a5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -289,11 +289,13 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
 static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7025 = {
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.cim3k = {CIM3K_OFF, CIM3K_OFF, CIM3K_ENABLE, CIM3K_ENABLE},
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 		.pb_tb = 3,
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
+		.cim3k = {CIM3K_OFF, CIM3K_OFF, CIM3K_ENABLE, CIM3K_ENABLE},
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 		.pb_tb = 0,
@@ -304,11 +306,13 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7025
 static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090 = {
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.cim3k = {CIM3K_OFF, CIM3K_OFF, CIM3K_DISABLE, CIM3K_ENABLE},
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 		.pb_tb = 3,
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
+		.cim3k = {CIM3K_OFF, CIM3K_OFF, CIM3K_DISABLE, CIM3K_ENABLE},
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 		.pb_tb = 0,
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 07/11] wifi: rtw89: phy: set BB wrap of trigger-base partial band
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Apply options to trigger-base partial band. For example, TX at RU-106 on
a 160MHz bandwidth.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      | 1 +
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 8 +++++++-
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 4 ++++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 5a0ffc51ece2..51495701b102 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -615,6 +615,7 @@ enum rtw89_rfsi_ctrl_modulation {
 struct rtw89_bb_wrap_common_data {
 	struct {
 		u32 rfsi_ct_opt[2];
+		u8 pb_tb;
 	} bands[RFSI_CTRL_BAND_NUM];
 	u8 qam_th[6];
 };
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index fc7f481783c0..75806ffc6242 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -771,13 +771,19 @@ static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(struct rtw89_dev *rtwdev,
 static void rtw89_phy_bb_wrap_tx_rfsi_scenario_def(struct rtw89_dev *rtwdev,
 						   enum rtw89_mac_idx mac_idx)
 {
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	u8 pb_tb = 0;
+
+	if (d && d->common)
+		pb_tb = d->common->bands[0].pb_tb;
+
 	rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_ER_BE4, 0x0, mac_idx);
 	rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SUBF_BE4, 0x0, mac_idx);
 	rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_FTM_BE4, 0x0, mac_idx);
 	rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SENS_BE4, 0x0, mac_idx);
 
 	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DEF_BE, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_PB_BE4, 0x0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_PB_BE4, pb_tb, mac_idx);
 	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_WO_BE4, 0x0, mac_idx);
 	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_BF_BE4, 0x0, mac_idx);
 	rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_MUMIMO_BE4, 0x0, mac_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 114f53ab9f7c..15c44dd0d9fa 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -291,10 +291,12 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7025
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+		.pb_tb = 3,
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+		.pb_tb = 0,
 	}},
 	.qam_th = {RFSI_BPSK, RFSI_QPSK, RFSI_256QAM, RFSI_MAX, RFSI_MAX, RFSI_MAX},
 };
@@ -304,10 +306,12 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+		.pb_tb = 3,
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+		.pb_tb = 0,
 	}},
 	.qam_th = {RFSI_BPSK, RFSI_QPSK, RFSI_256QAM, RFSI_MAX, RFSI_MAX, RFSI_MAX},
 };
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 06/11] wifi: rtw89: phy: set BB wrap of QAM options
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Apply these options to selected QAM to TX signal under requirements.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      | 15 ++++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 79 +++++++++++--------
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 36 +++++++++
 3 files changed, 96 insertions(+), 34 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index d2f443c98412..5a0ffc51ece2 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -597,10 +597,21 @@ enum rtw89_rfsi_ctrl_modulation {
 	RFSI_MAX,
 };
 
+#define MAX_TX_RFSI_CTRL_OPT 10
+
 #define _8nibble(n0, n1, n2, n3, n4, n5, n6, n7) \
 	((n0) << 0  | (n1) << 4  | (n2) << 8  | (n3) << 12 | \
 	 (n4) << 16 | (n5) << 20 | (n6) << 24 | (n7) << 28)
 
+#define _qam_comp_code(c) ((((c) & (BIT(15) | BIT(14))) >> 11) | \
+			   (((c) & BIT(12)) >> 10) | \
+			   (((c) & (BIT(9) | BIT(8))) >> 8))
+
+#define _10qam_comp_code(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) \
+	_qam_comp_code(c0), _qam_comp_code(c1),  _qam_comp_code(c2),  _qam_comp_code(c3), \
+	_qam_comp_code(c4), _qam_comp_code(c5),  _qam_comp_code(c6),  _qam_comp_code(c7), \
+	_qam_comp_code(c8), _qam_comp_code(c9)
+
 struct rtw89_bb_wrap_common_data {
 	struct {
 		u32 rfsi_ct_opt[2];
@@ -611,6 +622,10 @@ struct rtw89_bb_wrap_common_data {
 struct rtw89_bb_wrap_data {
 	const struct rtw89_bb_wrap_common_data *common;
 	struct {
+		u16 qam_comp_th0[MAX_TX_RFSI_CTRL_OPT];
+		u16 qam_comp_th1[MAX_TX_RFSI_CTRL_OPT]; /* encoded */
+		u16 qam_comp_th2[MAX_TX_RFSI_CTRL_OPT]; /* encoded */
+		u16 qam_comp_ow[MAX_TX_RFSI_CTRL_OPT];
 		u8 oob_dpd_by_cbw[8];
 	} bands[RFSI_CTRL_BAND_NUM];
 	u8 mdpd_by_dbw[4];
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index ca3cfdc90445..fc7f481783c0 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -788,40 +788,51 @@ static void rtw89_phy_bb_wrap_tx_rfsi_scenario_def(struct rtw89_dev *rtwdev,
 static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(struct rtw89_dev *rtwdev,
 						   enum rtw89_mac_idx mac_idx)
 {
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, 0x4010, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, 0x4410, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_L, 0x8, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_M, 0x8, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_H, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_L, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_M, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_H, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_L, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_M, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2L, 0x8, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2M, 0x8, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2H, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2L, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2M, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2H, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2L, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2M, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, 0x4010, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, 0x4010, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, 0x0, mac_idx);
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const u16 *th;
+
+	if (!d || !d->common)
+		return;
+
+	th = d->bands[0].qam_comp_th0;
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, th[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, th[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, th[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, th[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, th[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, th[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, th[6], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, th[7], mac_idx);
+
+	th = d->bands[0].qam_comp_th1;
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_L, th[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_M, th[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_H, th[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_L, th[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_M, th[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_H, th[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_L, th[6], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_M, th[7], mac_idx);
+
+	th = d->bands[0].qam_comp_th2;
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2L, th[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2M, th[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2H, th[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2L, th[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2M, th[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2H, th[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2L, th[6], mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2M, th[7], mac_idx);
+
+	th = d->bands[0].qam_comp_ow;
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, th[0], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, th[1], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, th[2], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, th[3], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, th[4], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, th[5], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, th[6], mac_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, th[7], mac_idx);
 }
 
 static void rtw89_phy_bb_set_oob_dpd_qam_comp_val(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index a867652907bc..114f53ab9f7c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -316,10 +316,22 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
 	.common = &rtw8922d_bb_wrap_common_data_7025,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x6400, 0x6500, 0x6000, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x6400, 0x6500, 0x6000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0x4000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4400, 0x4400, 0x4000, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x4400, 0x4500, 0, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x4400, 0x4500, 0,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4400, 0x4400, 0, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	}},
@@ -330,10 +342,22 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
 	.common = &rtw8922d_bb_wrap_common_data_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x6420, 0x6520, 0x6000, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x6400, 0x6500, 0x6000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0x4000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4000, 0x4000, 0x4000, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x4400, 0x4500, 0, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x4400, 0x4500, 0, 0,
+						  0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0, 0,
+						  0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4000, 0x4000, 0, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	}},
@@ -344,10 +368,22 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 =
 	.common = &rtw8922d_bb_wrap_common_data_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x6420, 0x6520, 0x6000, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x6400, 0x6500, 0x6000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0x4000,
+						  0, 0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4000, 0x4000, 0x4000, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	},
 	[RFSI_CTRL_BAND_2GHZ] = {
+		.qam_comp_th0 = {0x4000, 0x4400, 0x4500, 0, 0, 0, 0, 0, 0, 0},
+		.qam_comp_th1 = {_10qam_comp_code(0x4000, 0x4400, 0x4500, 0, 0,
+						  0, 0, 0, 0, 0)},
+		.qam_comp_th2 = {_10qam_comp_code(0x4000, 0x4400, 0x4400, 0, 0,
+						  0, 0, 0, 0, 0)},
+		.qam_comp_ow = {0x4000, 0x4000, 0x4000, 0, 0, 0, 0, 0, 0, 0},
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
 				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
 	}},
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 05/11] wifi: rtw89: phy: set BB wrap of QAM threshold
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Make hardware to consider which QAM (data rate) to apply BB wrapper
parameters, which are set by other registers.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      | 12 +++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 74 +++++++++++--------
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  2 +
 3 files changed, 56 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index a3e12590f473..d2f443c98412 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -586,6 +586,17 @@ enum rtw89_oob_dpd_onoff {
 	OOB_DPD_ON = 1,
 };
 
+enum rtw89_rfsi_ctrl_modulation {
+	RFSI_BPSK = 0,
+	RFSI_QPSK = 1,
+	RFSI_16QAM = 2,
+	RFSI_64QAM = 3,
+	RFSI_256QAM = 4,
+	RFSI_1024QAM = 5,
+	RFSI_4096QAM = 6,
+	RFSI_MAX,
+};
+
 #define _8nibble(n0, n1, n2, n3, n4, n5, n6, n7) \
 	((n0) << 0  | (n1) << 4  | (n2) << 8  | (n3) << 12 | \
 	 (n4) << 16 | (n5) << 20 | (n6) << 24 | (n7) << 28)
@@ -594,6 +605,7 @@ struct rtw89_bb_wrap_common_data {
 	struct {
 		u32 rfsi_ct_opt[2];
 	} bands[RFSI_CTRL_BAND_NUM];
+	u8 qam_th[6];
 };
 
 struct rtw89_bb_wrap_data {
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index c52306b9fec4..ca3cfdc90445 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -691,42 +691,52 @@ EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_bandedge_ch);
 static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(struct rtw89_dev *rtwdev,
 						       enum rtw89_mac_idx mac_idx)
 {
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	u8 th0, th1, th2;
+
+	if (!d || !d->common)
+		return;
+
+	th0 = d->common->qam_th[0];
+	th1 = d->common->qam_th[1];
+	th2 = d->common->qam_th[2];
+
 	/* TH0 */
-	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_0_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_3_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_1_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_4_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_7_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_0_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_3_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_6_BE4, 0x1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_0_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_3_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_1_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_4_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_7_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_0_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_3_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_6_BE4, th0, mac_idx);
 	/* TH1 */
-	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_1_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_4_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_2_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_5_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_8_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_1_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_4_BE4, 0x2, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_7_BE4, 0x2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_1_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_4_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_2_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_5_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_8_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_1_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_4_BE4, th1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_7_BE4, th1, mac_idx);
 	/* TH2 */
-	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_2_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_0_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_3_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_6_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_9_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_2_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_5_BE4, 0x4, mac_idx);
-	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_8_BE4, 0x4, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_2_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_0_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_3_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_6_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_9_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_2_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_5_BE4, th2, mac_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_8_BE4, th2, mac_idx);
 	/* DPD 160M */
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_0_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_1_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_2_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_3_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_4_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_5_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_6_BE4, 0x1, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_7_BE4, 0x1, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_0_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_1_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_2_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_3_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_4_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_5_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_6_BE4, th0, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_7_BE4, th0, mac_idx);
 	/* DPD 20M */
 	rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_0_BE4, 0x2, mac_idx);
 	rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_1_BE4, 0x2, mac_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 18d75184f82b..a867652907bc 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -296,6 +296,7 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7025
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 	}},
+	.qam_th = {RFSI_BPSK, RFSI_QPSK, RFSI_256QAM, RFSI_MAX, RFSI_MAX, RFSI_MAX},
 };
 
 static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090 = {
@@ -308,6 +309,7 @@ static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090
 		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
 				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
 	}},
+	.qam_th = {RFSI_BPSK, RFSI_QPSK, RFSI_256QAM, RFSI_MAX, RFSI_MAX, RFSI_MAX},
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 04/11] wifi: rtw89: phy: set BB wrap of control options
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Set main options to control BB wrap functions. For example, enable options
by data bandwidth or channel bandwidth.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      | 11 ++++++++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 11 ++++++--
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 27 +++++++++++++++++++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index c7cf99fe46fb..a3e12590f473 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -586,7 +586,18 @@ enum rtw89_oob_dpd_onoff {
 	OOB_DPD_ON = 1,
 };
 
+#define _8nibble(n0, n1, n2, n3, n4, n5, n6, n7) \
+	((n0) << 0  | (n1) << 4  | (n2) << 8  | (n3) << 12 | \
+	 (n4) << 16 | (n5) << 20 | (n6) << 24 | (n7) << 28)
+
+struct rtw89_bb_wrap_common_data {
+	struct {
+		u32 rfsi_ct_opt[2];
+	} bands[RFSI_CTRL_BAND_NUM];
+};
+
 struct rtw89_bb_wrap_data {
+	const struct rtw89_bb_wrap_common_data *common;
 	struct {
 		u8 oob_dpd_by_cbw[8];
 	} bands[RFSI_CTRL_BAND_NUM];
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 4ba18e821578..c52306b9fec4 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -648,13 +648,20 @@ static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev,
 void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev,
 				       enum rtw89_phy_idx phy_idx)
 {
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const u32 *val;
 	u32 reg;
 
+	if (!d || !d->common)
+		return;
+
+	val = d->common->bands[0].rfsi_ct_opt;
+
 	reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_0_BE4, phy_idx);
-	rtw89_write32(rtwdev, reg, 0x00010001);
+	rtw89_write32(rtwdev, reg, val[0]);
 
 	reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_8_BE4, phy_idx);
-	rtw89_write32(rtwdev, reg, 0x00010001);
+	rtw89_write32(rtwdev, reg, val[1]);
 }
 EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_ct_opt);
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 2e5e264e75db..18d75184f82b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -286,7 +286,32 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
 	[RTW89_EFUSE_BLOCK_ADIE]		= {.offset = 0x70000, .size = 0x10},
 };
 
+static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7025 = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
+				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
+				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+	}},
+};
+
+static const struct rtw89_bb_wrap_common_data rtw8922d_bb_wrap_common_data_7090 = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
+				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.rfsi_ct_opt = {_8nibble(2, 2, 2, 2, 1, 1, 1, 1),
+				_8nibble(2, 2, 2, 2, 1, 1, 1, 1)},
+	}},
+};
+
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
+	.common = &rtw8922d_bb_wrap_common_data_7025,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
@@ -300,6 +325,7 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
+	.common = &rtw8922d_bb_wrap_common_data_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
@@ -313,6 +339,7 @@ static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 = {
+	.common = &rtw8922d_bb_wrap_common_data_7090,
 	.bands = {
 	[RFSI_CTRL_BAND_5_6GHZ] = {
 		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 03/11] wifi: rtw89: phy: set BB wrap of DPD by bandwidth
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Apply different settings to out-of-band DPD (digital pre-distortion) by
bandwidth, as hardware defines separate registers.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      |  15 ++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 156 ++++++++++--------
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  27 +++
 3 files changed, 127 insertions(+), 71 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 0851a56cfe61..c7cf99fe46fb 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -569,12 +569,27 @@ struct rtw89_phy_rfk_log_fmt {
 	const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
 };
 
+enum rtw89_rfsi_ctrl_band {
+	RFSI_CTRL_BAND_5_6GHZ,
+	RFSI_CTRL_BAND_2GHZ,
+
+	RFSI_CTRL_BAND_NUM,
+};
+
 enum rtw89_mdpd_onoff {
 	MDPD_ON = 0,
 	MDPD_OFF = 1,
 };
 
+enum rtw89_oob_dpd_onoff {
+	OOB_DPD_OFF = 0,
+	OOB_DPD_ON = 1,
+};
+
 struct rtw89_bb_wrap_data {
+	struct {
+		u8 oob_dpd_by_cbw[8];
+	} bands[RFSI_CTRL_BAND_NUM];
 	u8 mdpd_by_dbw[4];
 };
 
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 94b977d29518..4ba18e821578 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -810,77 +810,91 @@ static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(struct rtw89_dev *rtwdev,
 static void rtw89_phy_bb_set_oob_dpd_qam_comp_val(struct rtw89_dev *rtwdev,
 						  enum rtw89_mac_idx mac_idx)
 {
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW7_BE4, 0x0, mac_idx);
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	u8 th;
+
+	if (!d)
+		return;
+
+	th = d->bands[0].oob_dpd_by_cbw[0];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[1];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[2];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[3];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[4];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[5];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[6];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW7_BE4, th, mac_idx);
+
+	th = d->bands[0].oob_dpd_by_cbw[7];
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW7_BE4, th, mac_idx);
 }
 
 static void rtw89_phy_bb_set_mdpd_qam_comp_val(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 326d12da2962..2e5e264e75db 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -287,14 +287,41 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	}},
 	.mdpd_by_dbw = {MDPD_ON, MDPD_ON, MDPD_ON, MDPD_ON},
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	}},
 	.mdpd_by_dbw = {MDPD_OFF, MDPD_OFF, MDPD_ON, MDPD_ON},
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 = {
+	.bands = {
+	[RFSI_CTRL_BAND_5_6GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	},
+	[RFSI_CTRL_BAND_2GHZ] = {
+		.oob_dpd_by_cbw = {OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF,
+				   OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF, OOB_DPD_OFF},
+	}},
 	.mdpd_by_dbw = {MDPD_OFF, MDPD_OFF, MDPD_ON, MDPD_ON},
 };
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 02/11] wifi: rtw89: phy: set BB wrap of out-of-band DPD
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

Control the out-of-band DPD (digital pre-distortion) to ensure out-of-band
signal under requirement.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      |  6 +++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 42 +++++++++++--------
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  3 ++
 3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index e4933bd522b2..0851a56cfe61 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -569,7 +569,13 @@ struct rtw89_phy_rfk_log_fmt {
 	const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
 };
 
+enum rtw89_mdpd_onoff {
+	MDPD_ON = 0,
+	MDPD_OFF = 1,
+};
+
 struct rtw89_bb_wrap_data {
+	u8 mdpd_by_dbw[4];
 };
 
 struct rtw89_phy_gen_def {
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 5cd298a2c91b..94b977d29518 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -886,23 +886,31 @@ static void rtw89_phy_bb_set_oob_dpd_qam_comp_val(struct rtw89_dev *rtwdev,
 static void rtw89_phy_bb_set_mdpd_qam_comp_val(struct rtw89_dev *rtwdev,
 					       enum rtw89_mac_idx mac_idx)
 {
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH7_BE4, 0x0, mac_idx);
-
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW0_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW1_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW2_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW3_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW4_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW5_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW6_BE4, 0x0, mac_idx);
-	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW7_BE4, 0x0, mac_idx);
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	u8 th;
+
+	if (!d)
+		return;
+
+	th = d->mdpd_by_dbw[0];
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH7_BE4, th, mac_idx);
+
+	th = d->mdpd_by_dbw[2];
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW0_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW1_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW2_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW3_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW4_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW5_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW6_BE4, th, mac_idx);
+	rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW7_BE4, th, mac_idx);
 }
 
 static void rtw89_phy_bb_set_cim3k_val(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 66b05aedcf11..326d12da2962 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -287,12 +287,15 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
+	.mdpd_by_dbw = {MDPD_ON, MDPD_ON, MDPD_ON, MDPD_ON},
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
+	.mdpd_by_dbw = {MDPD_OFF, MDPD_OFF, MDPD_ON, MDPD_ON},
 };
 
 static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 = {
+	.mdpd_by_dbw = {MDPD_OFF, MDPD_OFF, MDPD_ON, MDPD_ON},
 };
 
 static void rtw8922d_sel_bt_rx_path(struct rtw89_dev *rtwdev, u8 val,
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 01/11] wifi: rtw89: phy: define BB wrap data for RTL8922D variants
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20260511070148.25257-1-pkshih@realtek.com>

The BB wrap is a hardware block to control TX power. Since RTL8922D has
many variants with different CID and RFE types, prepare flow and dummy
struct adopt to configuration functions for coming patches.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.c     |  4 ++
 drivers/net/wireless/realtek/rtw89/core.h     | 13 +++++++
 drivers/net/wireless/realtek/rtw89/phy.h      |  3 ++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 38 +++++++++++++++++++
 10 files changed, 64 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index b85728ceb63c..dafe71aa4876 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -6778,6 +6778,10 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
 	if (ret)
 		goto out;
 
+	ret = rtw89_chip_data_setup(rtwdev);
+	if (ret)
+		goto out;
+
 	rtw89_core_setup_rfe_parms(rtwdev);
 	rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev);
 
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index bccfee7535a7..ab9165fcaf7d 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -27,6 +27,7 @@ struct rtw89_phy_calc_efuse_gain;
 struct rtw89_debugfs;
 struct rtw89_regd_data;
 struct rtw89_wow_cam_info;
+struct rtw89_bb_wrap_data;
 struct rtw89_fw_cmd_ofld_info;
 
 extern const struct ieee80211_ops rtw89_ops;
@@ -3828,6 +3829,7 @@ struct rtw89_chip_ops {
 			  enum rtw89_efuse_block block);
 	int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
 	void (*fem_setup)(struct rtw89_dev *rtwdev);
+	int (*data_setup)(struct rtw89_dev *rtwdev);
 	void (*rfe_gpio)(struct rtw89_dev *rtwdev);
 	void (*rfk_hw_init)(struct rtw89_dev *rtwdev);
 	void (*rfk_init)(struct rtw89_dev *rtwdev);
@@ -4574,6 +4576,7 @@ struct rtw89_bb_stat_cfg {
 };
 
 struct rtw89_phy_info {
+	const struct rtw89_bb_wrap_data *bb_wrap_data;
 	struct rtw89_bb_stat_cfg bb_stat_cfg;
 };
 
@@ -7461,6 +7464,16 @@ static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
 		chip->ops->fem_setup(rtwdev);
 }
 
+static inline int rtw89_chip_data_setup(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+
+	if (!chip->ops->data_setup)
+		return 0;
+
+	return chip->ops->data_setup(rtwdev);
+}
+
 static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index a6e685654037..e4933bd522b2 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -569,6 +569,9 @@ struct rtw89_phy_rfk_log_fmt {
 	const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
 };
 
+struct rtw89_bb_wrap_data {
+};
+
 struct rtw89_phy_gen_def {
 	u32 cr_base;
 	u32 physt_bmp_start;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index e047e716d9e3..2fb54e1fc7ab 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2556,6 +2556,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
 	.read_efuse		= rtw8851b_read_efuse,
 	.read_phycap		= rtw8851b_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= NULL,
 	.rfe_gpio		= rtw8851b_rfe_gpio,
 	.rfk_hw_init		= NULL,
 	.rfk_init		= rtw8851b_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 686e489d42f2..d3b6e8a7f5bd 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2302,6 +2302,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
 	.read_efuse		= rtw8852a_read_efuse,
 	.read_phycap		= rtw8852a_read_phycap,
 	.fem_setup		= rtw8852a_fem_setup,
+	.data_setup		= NULL,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= NULL,
 	.rfk_init		= rtw8852a_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 6ab99f72fda7..989ac38fe359 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -883,6 +883,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
 	.read_efuse		= rtw8852bx_read_efuse,
 	.read_phycap		= rtw8852bx_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= NULL,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= NULL,
 	.rfk_init		= rtw8852b_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 83de26273100..b58561e141cb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -729,6 +729,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
 	.read_efuse		= rtw8852bx_read_efuse,
 	.read_phycap		= rtw8852bx_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= NULL,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= NULL,
 	.rfk_init		= rtw8852bt_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index cc278587b532..9ecd140dcdd5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3091,6 +3091,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
 	.read_efuse		= rtw8852c_read_efuse,
 	.read_phycap		= rtw8852c_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= NULL,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= NULL,
 	.rfk_init		= rtw8852c_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index e6f15ee2a86b..07270e83b778 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -3086,6 +3086,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
 	.read_efuse		= rtw8922a_read_efuse,
 	.read_phycap		= rtw8922a_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= NULL,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= rtw8922a_rfk_hw_init,
 	.rfk_init		= rtw8922a_rfk_init,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index b8b75fca0a1b..66b05aedcf11 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -286,6 +286,15 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
 	[RTW89_EFUSE_BLOCK_ADIE]		= {.offset = 0x70000, .size = 0x10},
 };
 
+static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7025_default = {
+};
+
+static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_default = {
+};
+
+static const struct rtw89_bb_wrap_data rtw8922d_bb_wrap_data_7090_rfe35_41_44 = {
+};
+
 static void rtw8922d_sel_bt_rx_path(struct rtw89_dev *rtwdev, u8 val,
 				    enum rtw89_rf_path rx_path)
 {
@@ -918,6 +927,34 @@ static void rtw8922d_power_trim(struct rtw89_dev *rtwdev)
 	rtw8922d_pad_bias_trim(rtwdev);
 }
 
+static int rtw8922d_data_setup(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_bb_wrap_data *data;
+	struct rtw89_hal *hal = &rtwdev->hal;
+	bool rfe35_41_44 = false;
+
+	switch (rtwdev->efuse.rfe_type) {
+	case 35:
+	case 41:
+	case 44:
+		rfe35_41_44 = true;
+		break;
+	}
+
+	if (hal->cid == RTL8922D_CID7025) {
+		data = &rtw8922d_bb_wrap_data_7025_default;
+	} else {
+		if (rfe35_41_44)
+			data = &rtw8922d_bb_wrap_data_7090_rfe35_41_44;
+		else
+			data = &rtw8922d_bb_wrap_data_7090_default;
+	}
+
+	rtwdev->phy_info.bb_wrap_data = data;
+
+	return 0;
+}
+
 static void rtw8922d_set_channel_mac(struct rtw89_dev *rtwdev,
 				     const struct rtw89_chan *chan,
 				     u8 mac_idx)
@@ -2933,6 +2970,7 @@ static const struct rtw89_chip_ops rtw8922d_chip_ops = {
 	.read_efuse		= rtw8922d_read_efuse,
 	.read_phycap		= rtw8922d_read_phycap,
 	.fem_setup		= NULL,
+	.data_setup		= rtw8922d_data_setup,
 	.rfe_gpio		= NULL,
 	.rfk_hw_init		= rtw8922d_rfk_hw_init,
 	.rfk_init		= rtw8922d_rfk_init,
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 00/11] wifi: rtw89: update BB wrap for RTL8922D
From: Ping-Ke Shih @ 2026-05-11  7:01 UTC (permalink / raw)
  To: linux-wireless

The BB wrap is a set of registers to control TX power and shape.

The RTL8922D add more registers to fine tune performance by QAM, bandwidth
and etc. Add them according to hardware design.

Ping-Ke Shih (11):
  wifi: rtw89: phy: define BB wrap data for RTL8922D variants
  wifi: rtw89: phy: set BB wrap of out-of-band DPD
  wifi: rtw89: phy: set BB wrap of DPD by bandwidth
  wifi: rtw89: phy: set BB wrap of control options
  wifi: rtw89: phy: set BB wrap of QAM threshold
  wifi: rtw89: phy: set BB wrap of QAM options
  wifi: rtw89: phy: set BB wrap of trigger-base partial band
  wifi: rtw89: phy: set BB wrap of CIM3K
  wifi: rtw89: phy: change order to align register order
  wifi: rtw89: phy: configure control options of BB wrapper by RFSI band
  wifi: rtw89: phy: add BB wrapper generation 3 for RTL8922D variant

 drivers/net/wireless/realtek/rtw89/chan.c     |   2 +
 drivers/net/wireless/realtek/rtw89/core.c     |   4 +
 drivers/net/wireless/realtek/rtw89/core.h     |  21 +
 drivers/net/wireless/realtek/rtw89/phy.h      |  88 +++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 517 ++++++++++++------
 drivers/net/wireless/realtek/rtw89/reg.h      |  73 +++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |   1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 160 +++++-
 13 files changed, 699 insertions(+), 172 deletions(-)


base-commit: c1ed02655f9134d6af6a01a58b734329c2f4f22c
-- 
2.25.1


^ permalink raw reply

* [PATCH] wifi: wilc1000: Fix memory leak in wilc_wlan_firmware_download()
From: Abdun Nihaal @ 2026-05-11  6:57 UTC (permalink / raw)
  To: ajay.kathat
  Cc: Abdun Nihaal, claudiu.beznea, linux-wireless, linux-kernel, marex,
	stable

The memory allocated for dma_buffer is not freed in the error path
following the acquire_bus() call. Fix that by jumping to the error
unwind path which frees the dma_buffer.

Fixes: 1241c5650ff7 ("wifi: wilc1000: Fill in missing error handling")
Cc: stable@vger.kernel.org
Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
---
Compile tested only. Issue found using static analysis.

 drivers/net/wireless/microchip/wilc1000/wlan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index 3fa8592eb250..4b116fe6f9ea 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -1265,7 +1265,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
 
 	ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 	if (ret)
-		return ret;
+		goto fail;
 
 	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 	reg &= ~BIT(10);
-- 
2.43.0


^ permalink raw reply related

* iwlwifi: network not back after resuming from suspend since v6.15-rc2
From: Coiby Xu @ 2026-05-11  6:49 UTC (permalink / raw)
  To: linux-wireless, Emmanuel Grumbach; +Cc: Miri Korenblit

Hi Emmanuel,

I notice since v6.15-rc2, most of the times the network won't be back
again after resuming from suspend. And sometimes I need to run
"systemctl suspend" for 8 or 9 consecutive times to make WIFI available
again. bisect and manual reverting show 15220a257319 ("wifi: iwlwifi:
don't warn if the NIC is gone in resume") is the 1st bad commit. 

Here are some other clues that may help resolve this issue,

     1. An iwlwifi setting [1] can make this issue disappear,
        options iwlwifi swcrypto=0
        options iwlwifi bt_coex_active=0
        options iwlwifi power_save=0
        options iwlwifi uapsd_disable=1
        options iwlmvm power_scheme=1

     2. Before v6.15-rc2, the issue rarely happens. And if it happens,
        simply suspending once can bring the network online again. Other
        users seem to have experienced the same issue e.g. [2][3][4].

     3. Suspending by "rtcwake -m mem -s 5" instead of by "systemcl suspend"
        can make it much easier to reproduce this issue for kernels older
        than v6.15-rc2.

If you need more details from me, feel free to let me know! And I'll
very happy to test any possible solutions. Thanks!

## Notes on bisect

The bisect is done with an experimental branch [5] of
kernel-auto-bisect tool [6].

1. bisect conf file
    TEST_STRATEGY="simple"
    RUNS_PER_COMMIT=6
    RUNS_PER_GOOD_COMMIT=3
    GOOD_COMMIT=6.14.4-300.fc42.x86_64
    BAD_COMMIT=6.19.14-200.fc43.x86_64
    REPRODUCER_SCRIPT=reproducer_wifi.sh

2. Reproducer 
    on_test() {
            # If sleep only 5 or 10 s, somehow the system will get suspended forever i.e.
            # "rtcwake -m on won't wake up the system .
            sleep 15
            ip --brief addr show wlp4s0 
            # "rtcwake -m mem -s 5" will quite often makes wifi unavailable. So use
            # systemctl suspend instead
            #rtcwake -m mem -s 5
            # Wake up the system after 4s
            rtcwake -m on -s 4 &
            systemctl suspend
            sleep 12
            ip --brief addr show wlp4s0 | grep -q " UP "
    }

kernel-auto-bisect went through a two-phase bisection,
     1. find 6.14.6-300.fc42.x86_64 as the 1st bad build
     2. find Fedora kernel commit 6453e892cf86c [7] as 1st bad commit

I can't bisect against upstream kernel directly because v6.15-rc2 won't
be able to mount my root partition. So I manually reverted upstream
15220a257319 ("wifi: iwlwifi: don't warn if the NIC is gone in resume")
in v6.15 to confirm it's indeed the bad commit.

[1] https://bbs.archlinux.org/viewtopic.php?pid=2227202#p2227202
[2] https://bbs.archlinux.org/viewtopic.php?id=301971
[3] https://discussion.fedoraproject.org/t/random-wi-fi-adapter-loss-on-fedora-42-intel-alder-lake-p-cnvi/152878
[4] https://forums.opensuse.org/t/wifi-suddenly-no-more-available/184399
[5] https://github.com/coiby/kernel-auto-bisect/tree/random_issue_bisect
[6] https://github.com/rhkdump/kernel-auto-bisect
[7] https://gitlab.com/cki-project/kernel-ark/-/commit/6453e892cf86c900d51f5884e9013e0dbeeea4ad


-- 
Best regards,
Coiby

^ permalink raw reply

* Re: [PATCH wireless-next] wifi: mac80211: Fix ADDBA request rejection after MLD link removal
From: Manish Dharanenthiran @ 2026-05-11  6:26 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Hari Naraayana Desikan Kannan
In-Reply-To: <a5b6798819178dd2995c34ec817457e90985708e.camel@sipsolutions.net>



On 5/7/2026 11:56 PM, Johannes Berg wrote:
> Hi,
> 
> Sorry, I've definitely fallen behind on some topics.
> 
No problem :)

>> With link reconfiguration, not handling the update requests sent on the
>> remaining links causes throughput drop, that's why went with handling
>> the update requests even-though the session is valid.
> 
> I'm not sure I see the relation right now, how does link reconfiguration
> relate to AddBA re-negotiation? Are there implementations that
> necessarily combine the two somehow?
> 

No, there is no implementations that combine these two, but there are 
cases where the update AddBA request can be received from the station 
with link reconfiguration.

For instance, if a station associated in 2 GHz, later with link 
reconfiguration station can either move to 5 GHz or it can add 5 GHz (as 
MLD). Station then can send a AddBA request to update the window size or 
other related parameters. Current change tries to address this by 
treating the request as START and ath12k driver internally takes care of 
updating the existing session. But, as you mentioned, we feel that it 
should be treated as an UPDATE instead of START.

>> Please let us know if we need to clear the old session and then proceed
>> with the update request to avoid breaking the other drivers.
> 
> I'm not sure what you're trying to achieve, so I'm not entirely sure
> what to say. I thought we were starting from "we should accept no-op
> updates".
> 
>>>> Note: A similar fix has been proposed in [1]. This patch also fixes the
>>>> issue mentioned there. The difference in approach is to keep a similar
>>>> flow when the dialog_token matches. Previously only the timeout value
>>>> is checked, updated that to check the timeout only for the hardware that
>>>> doesn't set SUPPORT_REORDERING_BUFFER. In [1], it was changed to invoke
>>>> driver unconditionally when SUPPORT_REORDERING_BUFFER is set.
>>>>
>>>> https://lore.kernel.org/all/5806bab7e46506d3c300ab4eb66989d42936aeb0.1771323902.git.repk@triplefau.lt/
>>>>
>>> What was wrong with the approach we discussed there, other than nobody
>>> implementing it?
>>>
>>> johannes
>>
>> Not a major different between the other change, thought of keeping the
>> similar version that we validated in the internal tree.
> 
> I don't think it _is_ that similar though? Or maybe it is, but I didn't
> think the other patch was correct (either).
> 
> Basically I'm concerned that calling drv_ampdu_action() with
> IEEE80211_AMPDU_RX_START when the session is already active may break
> things depending on the driver.
> 
> If you think there's a need to _really_ update parameters, then we
> should probably add a IEEE80211_AMPDU_RX_UPDATE operation, and implement
> it in drivers, and of course in some drivers that might just be
> equivalent to IEEE80211_AMPDU_RX_START (though that seems unlikely in
> general, given you may have to allocate reorder buffers etc.)
> 
Agree.

> Regardless of that, if you think we need to accept no-op updates (I
> don't think we've seen the need so far), then the code shouldn't really
> (need to) call the driver at all, since things don't really change. For
> that I'd argue we should go with the approached discussed in the thread
> of [1], but not really that change itself.
> 
> [1] https://lore.kernel.org/all/5806bab7e46506d3c300ab4eb66989d42936aeb0.1771323902.git.repk@triplefau.lt/
> 
We believe that a no-op update is not required (or at-least we couldn't 
think of a case in which that is actually needed) as there can might be 
an actual change in the subsequent AddBA request.

> I'm perfectly willing to believe the need for both, but I'd argue that
>   - no-op updates can be handled by mac80211 entirely by itself, as
>     discussed in that thread, just someone needs to implement it
>   - updates with changes need a separate call to the driver, which might
>     fail (either because of the change, or because it's not implemented)
> 
> As is, I don't think the code is safe in general. It may be that you
> validated it against your driver, but then I'd argue that it worked for
> your driver only because a new IEEE80211_AMPDU_RX_UPDATE would be
> equivalent to IEEE80211_AMPDU_RX_START for that driver for some reason,
> not because there's a general reason that this should work.
> 
> johannes

Yes, based on the case that we encountered, IEEE80211_AMPDU_RX_UPDATE is 
the right approach for the handling those requests safely for other 
driver(s) as well instead of relying on IEEE80211_AMPDU_RX_START

Regards
Manish Dharanenthiran

^ permalink raw reply

* Re: [PATCH v2 0/3] fix leaks in some WMI error path
From: Baochen Qiang @ 2026-05-11  4:56 UTC (permalink / raw)
  To: Nicolas Escande, ath11k; +Cc: linux-wireless
In-Reply-To: <20260506134240.2284016-1-nico.escande@gmail.com>



On 5/6/2026 9:42 PM, Nicolas Escande wrote:
> So this is similar work to what has been posted here [0] for ath12k.
> 
> When we use the pattern 'return ath11k_wmi_cmd_send(...)' without
> explicitly checking the return value we fail to free the allocated skb.
> 
> This has been split into 2 patches per Jeff's guidance to hopefully
> ease the backporting process.
> 
> [0] https://lore.kernel.org/linux-wireless/20260422163258.3013872-1-nico.escande@gmail.com/
> 
> ---
> Changes from v1:
>   - Added patch to also fix ath11k_tm_cmd_wmi_ftm() as per Rameshkumar's remark
> 
> Nicolas Escande (3):
>   wifi: ath11k: fix leak in error path of some WOW related WMI commands
>   wifi: ath11k: fix error path leaks in some WMI calls
>   wifi: ath11k: fix error path leak in ath11k_tm_cmd_wmi_ftm()
> 
>  drivers/net/wireless/ath/ath11k/testmode.c |   1 +
>  drivers/net/wireless/ath/ath11k/wmi.c      | 131 ++++++++++++++++++---
>  2 files changed, 113 insertions(+), 19 deletions(-)
> 

Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>


^ permalink raw reply

* Testing MT7921e: MT7902 TX stuck at 6Mbps on 5Ghz VHT connection; only stable at 802.11n or lower at 2.4GHz Non-dual band AP.
From: MobyGaming @ 2026-05-11  4:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: lorenzo, nbd

Hi. I'm using linux on a laptop with an MT7902 wifi card. It's been
years since I wanted to get proper connectivity on this OS and with
the announcement of Kernel 7.1, it was pure bliss to finally see some
support pop up.

Here are some data I gathered as I tested Mt7902 on my laptop, an Acer
Aspire 315-24p. If you need anything, let me know.

Kernel: 7.1.0-070100rc3-generic

Hardware: Azurwave AW-XB552NF

lspci output:

peppermintcapsicum@pop-os:~$ sudo lspci -vnn | grep -A8 7902
pcilib: Error reading /sys/bus/pci/devices/0000:00:08.3/label:
Operation not permitted
01:00.0 Network controller [0280]: MEDIATEK Corp. Device [14c3:7902]
Subsystem: AzureWave Device [1a3b:5524]
Flags: bus master, fast devsel, latency 0, IRQ 75, IOMMU group 8
Memory at 7ef0200000 (64-bit, prefetchable) [size=1M]
Memory at c0500000 (64-bit, non-prefetchable) [size=32K]
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [e0] MSI: Enable+ Count=1/32 Maskable+ 64bit+
Capabilities: [f8] Power Management version 3
Capabilities: [100] Vendor Specific Information: ID=1556 Rev=1 Len=008 "<?>"
dmesg:

[ 9.599861] mt7921e 0000:01:00.0: enabling device (0000 -> 0002)
[ 9.600227] mt7921e 0000:01:00.0: disabling ASPM L1
[ 9.606554] mt7921e 0000:01:00.0: ASIC revision: 79020000
[ 9.722020] mt7921e 0000:01:00.0: HW/SW Version: 0x8a108a10, Build
Time: 20251212032046a
[ 9.913603] mt7921e 0000:01:00.0: WM Firmware Version: ____000000,
Build Time: 20251212032127
[ 10.942072] mt7921e 0000:01:00.0 wlp1s0: renamed from wlan0

iw link info:

SSID: dlink-5798-5GHz freq: 5765.0 RX: 4382 bytes (33 packets) TX:
8464 bytes (53 packets) signal: -72 dBm tx bitrate: 6.0 MBit/s bss
flags: short-slot-time dtim period: 1 beacon int: 100

SSID: dlink-5798-5GHz freq: 5765.0 RX: 39910 bytes (273 packets) TX:
24409 bytes (161 packets) signal: -73 dBm rx bitrate: 58.5 MBit/s
VHT-MCS 1 80MHz VHT-NSS 1 tx bitrate: 6.0 MBit/s bss flags:
short-slot-time dtim period: 1 beacon int: 100

iw phy info:

Wiphy phy0
wiphy index: 0
max # scan SSIDs: 4
max scan IEs length: 482 bytes
max # sched scan SSIDs: 10
max # match sets: 16
Retry short limit: 7
Retry long limit: 4
Coverage class: 0 (up to 0m)
Device supports AP-side u-APSD.
Device supports T-DLS.
Supported Ciphers:
WEP40 (00-0f-ac:1)
WEP104 (00-0f-ac:5)
TKIP (00-0f-ac:2)
CCMP-128 (00-0f-ac:4)
CCMP-256 (00-0f-ac:10)
GCMP-128 (00-0f-ac:8)
GCMP-256 (00-0f-ac:9)
CMAC (00-0f-ac:6)
CMAC-256 (00-0f-ac:13)
GMAC-128 (00-0f-ac:11)
GMAC-256 (00-0f-ac:12)
Available Antennas: TX 0x1 RX 0x1
Configured Antennas: TX 0x1 RX 0x1
Supported interface modes:
managed
AP
AP/VLAN
monitor
P2P-client
P2P-GO
P2P-device
Band 1:
Capabilities: 0x97f
RX LDPC
HT20/HT40
SM Power Save disabled
RX Greenfield
RX HT20 SGI
RX HT40 SGI
RX STBC 1-stream
Max AMSDU length: 7935 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-7
HE Iftypes: managed
HE MAC Capabilities (0x08011a000040):
+HTC HE Supported
Trigger Frame MAC Padding Duration: 2
OM Control
Maximum A-MPDU Length Exponent: 3
A-MSDU in A-MPDU
HE PHY Capabilities: (0x2270ce120dc0b306423f00):
HE40/2.4GHz
242 tone RUs/2.4GHz
Device Class: 1
LDPC Coding in Payload
HE SU PPDU with 1x HE-LTF and 0.8us GI
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
SU Beamformee
Beamformee STS <= 80Mhz: 3
Ng = 16 SU Feedback
Ng = 16 MU Feedback
Codebook Size SU Feedback
Codebook Size MU Feedback
Triggered CQI Feedback
Partial Bandwidth Extended Range
PPE Threshold Present
Power Boost Factor ar
HE SU PPDU & HE PPDU 4x HE-LTF 0.8us GI
20MHz in 40MHz HE PPDU 2.4GHz
DCM Max BW: 1
Longer Than 16HE SIG-B OFDM Symbols
Non-Triggered CQI Feedback
TX 1024-QAM
RX 1024-QAM
RX Full BW SU Using HE MU PPDU with Compression SIGB
RX Full BW SU Using HE MU PPDU with Non-Compression SIGB
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x18 0x1c 0x07
HE Iftypes: AP
HE MAC Capabilities (0x00011a081044):
+HTC HE Supported
BSR
OM Control
Maximum A-MPDU Length Exponent: 3
BQR
A-MSDU in A-MPDU
OM Control UL MU Data Disable RX
HE PHY Capabilities: (0x0220ce120000a000000c00):
HE40/2.4GHz
LDPC Coding in Payload
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
Partial Bandwidth Extended Range
PPE Threshold Present
TX 1024-QAM
RX 1024-QAM
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x18 0x1c 0x07
Bitrates (non-HT):
1.0 Mbps (short preamble supported)
2.0 Mbps (short preamble supported)
5.5 Mbps (short preamble supported)
11.0 Mbps (short preamble supported)
6.0 Mbps
9.0 Mbps
12.0 Mbps
18.0 Mbps
24.0 Mbps
36.0 Mbps
48.0 Mbps
54.0 Mbps
Frequencies:
2412.0 MHz [1] (20.0 dBm)
2417.0 MHz [2] (20.0 dBm)
2422.0 MHz [3] (20.0 dBm)
2427.0 MHz [4] (20.0 dBm)
2432.0 MHz [5] (20.0 dBm)
2437.0 MHz [6] (20.0 dBm)
2442.0 MHz [7] (20.0 dBm)
2447.0 MHz [8] (20.0 dBm)
2452.0 MHz [9] (20.0 dBm)
2457.0 MHz [10] (20.0 dBm)
2462.0 MHz [11] (20.0 dBm)
2467.0 MHz [12] (20.0 dBm)
2472.0 MHz [13] (20.0 dBm)
2484.0 MHz [14] (disabled)
Band 2:
Capabilities: 0x97f
RX LDPC
HT20/HT40
SM Power Save disabled
RX Greenfield
RX HT20 SGI
RX HT40 SGI
RX STBC 1-stream
Max AMSDU length: 7935 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-7
VHT Capabilities (0x33907132):
Max MPDU length: 11454
Supported Channel Width: neither 160 nor 80+80
RX LDPC
short GI (80 MHz)
SU Beamformee
MU Beamformee
RX antenna pattern consistency
TX antenna pattern consistency
VHT RX MCS set:
1 streams: MCS 0-9
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT RX highest supported: 0 Mbps
VHT TX MCS set:
1 streams: MCS 0-9
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT TX highest supported: 0 Mbps
VHT extended NSS: supported
HE Iftypes: managed
HE MAC Capabilities (0x08011a000040):
+HTC HE Supported
Trigger Frame MAC Padding Duration: 2
OM Control
Maximum A-MPDU Length Exponent: 3
A-MSDU in A-MPDU
HE PHY Capabilities: (0x4470ce120dc0b306423f00):
HE40/HE80/5GHz
242 tone RUs/5GHz
Device Class: 1
LDPC Coding in Payload
HE SU PPDU with 1x HE-LTF and 0.8us GI
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
SU Beamformee
Beamformee STS <= 80Mhz: 3
Ng = 16 SU Feedback
Ng = 16 MU Feedback
Codebook Size SU Feedback
Codebook Size MU Feedback
Triggered CQI Feedback
Partial Bandwidth Extended Range
PPE Threshold Present
Power Boost Factor ar
HE SU PPDU & HE PPDU 4x HE-LTF 0.8us GI
20MHz in 40MHz HE PPDU 2.4GHz
DCM Max BW: 1
Longer Than 16HE SIG-B OFDM Symbols
Non-Triggered CQI Feedback
TX 1024-QAM
RX 1024-QAM
RX Full BW SU Using HE MU PPDU with Compression SIGB
RX Full BW SU Using HE MU PPDU with Non-Compression SIGB
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x78 0x1c 0xc7 0x71
HE Iftypes: AP
HE MAC Capabilities (0x00011a081044):
+HTC HE Supported
BSR
OM Control
Maximum A-MPDU Length Exponent: 3
BQR
A-MSDU in A-MPDU
OM Control UL MU Data Disable RX
HE PHY Capabilities: (0x0420ce120000a000000c00):
HE40/HE80/5GHz
LDPC Coding in Payload
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
Partial Bandwidth Extended Range
PPE Threshold Present
TX 1024-QAM
RX 1024-QAM
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x78 0x1c 0xc7 0x71
Bitrates (non-HT):
6.0 Mbps
9.0 Mbps
12.0 Mbps
18.0 Mbps
24.0 Mbps
36.0 Mbps
48.0 Mbps
54.0 Mbps
Frequencies:
5180.0 MHz [36] (23.0 dBm)
5200.0 MHz [40] (23.0 dBm)
5220.0 MHz [44] (23.0 dBm)
5240.0 MHz [48] (23.0 dBm)
5260.0 MHz [52] (23.0 dBm) (radar detection)
5280.0 MHz [56] (23.0 dBm) (radar detection)
5300.0 MHz [60] (23.0 dBm) (radar detection)
5320.0 MHz [64] (23.0 dBm) (radar detection)
5500.0 MHz [100] (24.0 dBm) (radar detection)
5520.0 MHz [104] (24.0 dBm) (radar detection)
5540.0 MHz [108] (24.0 dBm) (radar detection)
5560.0 MHz [112] (24.0 dBm) (radar detection)
5580.0 MHz [116] (24.0 dBm) (radar detection)
5600.0 MHz [120] (24.0 dBm) (radar detection)
5620.0 MHz [124] (24.0 dBm) (radar detection)
5640.0 MHz [128] (24.0 dBm) (radar detection)
5660.0 MHz [132] (24.0 dBm) (radar detection)
5680.0 MHz [136] (24.0 dBm) (radar detection)
5700.0 MHz [140] (24.0 dBm) (radar detection)
5720.0 MHz [144] (24.0 dBm) (radar detection)
5745.0 MHz [149] (24.0 dBm)
5765.0 MHz [153] (24.0 dBm)
5785.0 MHz [157] (24.0 dBm)
5805.0 MHz [161] (24.0 dBm)
5825.0 MHz [165] (24.0 dBm)
5845.0 MHz [169] (disabled)
5865.0 MHz [173] (disabled)
5885.0 MHz [177] (disabled)
Band 4:
HE Iftypes: managed
HE MAC Capabilities (0x08011a000040):
+HTC HE Supported
Trigger Frame MAC Padding Duration: 2
OM Control
Maximum A-MPDU Length Exponent: 3
A-MSDU in A-MPDU
HE PHY Capabilities: (0x4470ce120dc0b306423f00):
HE40/HE80/5GHz
242 tone RUs/5GHz
Device Class: 1
LDPC Coding in Payload
HE SU PPDU with 1x HE-LTF and 0.8us GI
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
SU Beamformee
Beamformee STS <= 80Mhz: 3
Ng = 16 SU Feedback
Ng = 16 MU Feedback
Codebook Size SU Feedback
Codebook Size MU Feedback
Triggered CQI Feedback
Partial Bandwidth Extended Range
PPE Threshold Present
Power Boost Factor ar
HE SU PPDU & HE PPDU 4x HE-LTF 0.8us GI
20MHz in 40MHz HE PPDU 2.4GHz
DCM Max BW: 1
Longer Than 16HE SIG-B OFDM Symbols
Non-Triggered CQI Feedback
TX 1024-QAM
RX 1024-QAM
RX Full BW SU Using HE MU PPDU with Compression SIGB
RX Full BW SU Using HE MU PPDU with Non-Compression SIGB
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x78 0x1c 0xc7 0x71
HE Iftypes: AP
HE MAC Capabilities (0x00011a081044):
+HTC HE Supported
BSR
OM Control
Maximum A-MPDU Length Exponent: 3
BQR
A-MSDU in A-MPDU
OM Control UL MU Data Disable RX
HE PHY Capabilities: (0x0420ce120000a000000c00):
HE40/HE80/5GHz
LDPC Coding in Payload
NDP with 4x HE-LTF and 3.2us GI
STBC Tx <= 80MHz
STBC Rx <= 80MHz
Full Bandwidth UL MU-MIMO
Partial Bandwidth UL MU-MIMO
DCM Max Constellation: 2
DCM Max Constellation Rx: 2
Partial Bandwidth Extended Range
PPE Threshold Present
TX 1024-QAM
RX 1024-QAM
HE RX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
HE TX MCS and NSS set <= 80 MHz
1 streams: MCS 0-11
2 streams: not supported
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
PPE Threshold 0x78 0x1c 0xc7 0x71
Bitrates (non-HT):
6.0 Mbps
9.0 Mbps
12.0 Mbps
18.0 Mbps
24.0 Mbps
36.0 Mbps
48.0 Mbps
54.0 Mbps
Frequencies:
5955.0 MHz [1] (disabled)
5975.0 MHz [5] (disabled)
5995.0 MHz [9] (disabled)
6015.0 MHz [13] (disabled)
6035.0 MHz [17] (disabled)
6055.0 MHz [21] (disabled)
6075.0 MHz [25] (disabled)
6095.0 MHz [29] (disabled)
6115.0 MHz [33] (disabled)
6135.0 MHz [37] (disabled)
6155.0 MHz [41] (disabled)
6175.0 MHz [45] (disabled)
6195.0 MHz [49] (disabled)
6215.0 MHz [53] (disabled)
6235.0 MHz [57] (disabled)
6255.0 MHz [61] (disabled)
6275.0 MHz [65] (disabled)
6295.0 MHz [69] (disabled)
6315.0 MHz [73] (disabled)
6335.0 MHz [77] (disabled)
6355.0 MHz [81] (disabled)
6375.0 MHz [85] (disabled)
6395.0 MHz [89] (disabled)
6415.0 MHz [93] (disabled)
6435.0 MHz [97] (disabled)
6455.0 MHz [101] (disabled)
6475.0 MHz [105] (disabled)
6495.0 MHz [109] (disabled)
6515.0 MHz [113] (disabled)
6535.0 MHz [117] (disabled)
6555.0 MHz [121] (disabled)
6575.0 MHz [125] (disabled)
6595.0 MHz [129] (disabled)
6615.0 MHz [133] (disabled)
6635.0 MHz [137] (disabled)
6655.0 MHz [141] (disabled)
6675.0 MHz [145] (disabled)
6695.0 MHz [149] (disabled)
6715.0 MHz [153] (disabled)
6735.0 MHz [157] (disabled)
6755.0 MHz [161] (disabled)
6775.0 MHz [165] (disabled)
6795.0 MHz [169] (disabled)
6815.0 MHz [173] (disabled)
6835.0 MHz [177] (disabled)
6855.0 MHz [181] (disabled)
6875.0 MHz [185] (disabled)
6895.0 MHz [189] (disabled)
6915.0 MHz [193] (disabled)
6935.0 MHz [197] (disabled)
6955.0 MHz [201] (disabled)
6975.0 MHz [205] (disabled)
6995.0 MHz [209] (disabled)
7015.0 MHz [213] (disabled)
7035.0 MHz [217] (disabled)
7055.0 MHz [221] (disabled)
7075.0 MHz [225] (disabled)
7095.0 MHz [229] (disabled)
7115.0 MHz [233] (disabled)
Supported commands:
new_interface
set_interface
new_key
start_ap
new_station
new_mpath
set_mesh_config
set_bss
authenticate
associate
deauthenticate
disassociate
join_ibss
join_mesh
set_tx_bitrate_mask
frame
frame_wait_cancel
set_wiphy_netns
set_channel
tdls_mgmt
tdls_oper
start_sched_scan
probe_client
set_noack_map
register_beacons
start_p2p_device
set_mcast_rate
connect
disconnect
channel_switch
set_qos_map
set_multicast_to_unicast
set_sar_specs
Unknown command (156)
WoWLAN support:
wake up on disconnect
wake up on magic packet
wake up on pattern match, up to 1 patterns of 1-128 bytes,
maximum packet offset 0 bytes
can do GTK rekeying
wake up on network detection, up to 10 match sets
software interface modes (can always be added):
AP/VLAN
monitor
valid interface combinations:
#{ managed } <= 4, #{ AP } <= 1,
total <= 4, #channels <= 1, STA/AP BI must match
HT Capability overrides:
MCS: ff ff ff ff ff ff ff ff ff ff
maximum A-MSDU length
supported channel width
short GI for 40 MHz
max A-MPDU length exponent
min MPDU start spacing
Device supports TX status socket option.
Device supports HT-IBSS.
Device supports SAE with AUTHENTICATE command
Device supports scan flush.
Device supports per-vif TX power setting
P2P GO supports CT window setting
P2P GO supports opportunistic powersave setting
Driver supports full state transitions for AP/GO clients
Driver supports a userspace MPM
Device supports active monitor (which will ACK incoming frames)
Driver/device bandwidth changes during BSS lifetime (AP/GO mode)
Device supports configuring vdev MAC-addr on create.
Device supports randomizing MAC-addr in scans.
Device supports randomizing MAC-addr in sched scans.
max # scan plans: 1
max scan plan interval: 65535
max scan plan iterations: 0
Supported TX frame types:
IBSS: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0
0xd0 0xe0 0xf0
managed: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0
0xc0 0xd0 0xe0 0xf0
AP: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0
0xd0 0xe0 0xf0
AP/VLAN: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0
0xc0 0xd0 0xe0 0xf0
mesh point: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0
0xb0 0xc0 0xd0 0xe0 0xf0
P2P-client: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0
0xb0 0xc0 0xd0 0xe0 0xf0
P2P-GO: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0
0xc0 0xd0 0xe0 0xf0
P2P-device: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0
0xb0 0xc0 0xd0 0xe0 0xf0
NAN: 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x90 0xa0 0xb0 0xc0
0xd0 0xe0 0xf0
Supported RX frame types:
IBSS: 0x40 0xb0 0xc0 0xd0
managed: 0x40 0xb0 0xd0
AP: 0x00 0x20 0x40 0xa0 0xb0 0xc0 0xd0
AP/VLAN: 0x00 0x20 0x40 0xa0 0xb0 0xc0 0xd0
mesh point: 0xb0 0xc0 0xd0
P2P-client: 0x40 0xd0
P2P-GO: 0x00 0x20 0x40 0xa0 0xb0 0xc0 0xd0
P2P-device: 0x40 0xb0 0xd0
NAN: 0xb0 0xd0
Supported extended features:
[ RRM ]: RRM
[ SET_SCAN_DWELL ]: scan dwell setting
[ BEACON_RATE_LEGACY ]: legacy beacon rate setting
[ BEACON_RATE_HT ]: HT beacon rate setting
[ BEACON_RATE_VHT ]: VHT beacon rate setting
[ FILS_STA ]: STA FILS (Fast Initial Link Setup)
[ CQM_RSSI_LIST ]: multiple CQM_RSSI_THOLD records
[ CONTROL_PORT_OVER_NL80211 ]: control port over nl80211
[ ACK_SIGNAL_SUPPORT ]: ack signal level support
[ TXQS ]: FQ-CoDel-enabled intermediate TXQs
[ CAN_REPLACE_PTK0 ]: can safely replace PTK 0 when rekeying
[ AIRTIME_FAIRNESS ]: airtime fairness scheduling
[ AQL ]: Airtime Queue Limits (AQL)
[ CONTROL_PORT_NO_PREAUTH ]: disable pre-auth over nl80211 control port support
[ SCAN_FREQ_KHZ ]: scan on kHz frequency support
[ CONTROL_PORT_OVER_NL80211_TX_STATUS ]: tx status for nl80211 control
port support
[ BEACON_RATE_HE ]: HE beacon rate support (AP/mesh)
* [ POWERED_ADDR_CHANGE ]: can change MAC address while up

hex form:
pcilib: Error reading /sys/bus/pci/devices/0000:00:08.3/label:
Operation not permitted
01:00.0 Network controller [0280]: MEDIATEK Corp. Device [14c3:7902]
Subsystem: AzureWave Device [1a3b:5524]
Flags: bus master, fast devsel, latency 0, IRQ 75, IOMMU group 8
Memory at 7ef0200000 (64-bit, prefetchable) [size=1M]
Memory at c0500000 (64-bit, non-prefetchable) [size=32K]

^ permalink raw reply

* Re: [PATCH] wifi: wilc1000: fix dma_buffer leak on bus acquire failure
From: Shitalkumar Gandhi @ 2026-05-11  4:32 UTC (permalink / raw)
  To: ajay.kathat
  Cc: claudiu.beznea, kvalo, linux-wireless, netdev, linux-kernel,
	Shitalkumar Gandhi
In-Reply-To: <20260510112520.977360-1-shitalkumar.gandhi@cambiumnetworks.com>

Please disregard v1. The author attribution and Signed-off-by were
incorrect due to a local git config mistake. v2 with the corrected
identity has been sent and is threaded as a reply to this message.

Sorry for the noise.

Thanks,
Shital

^ permalink raw reply

* [PATCH v2 v2] wifi: wilc1000: fix dma_buffer leak on bus acquire failure
From: Shitalkumar Gandhi @ 2026-05-11  4:27 UTC (permalink / raw)
  To: ajay.kathat, claudiu.beznea
  Cc: kvalo, linux-wireless, netdev, linux-kernel, Shitalkumar Gandhi
In-Reply-To: <20260510112520.977360-1-shitalkumar.gandhi@cambiumnetworks.com>

wilc_wlan_firmware_download() allocates dma_buffer with kmalloc() at
the top of the function and uses a 'fail:' label to free it via
kfree(dma_buffer) on error.

All later error paths correctly use 'goto fail' to route through this
cleanup. However, the early failure path after the first acquire_bus()
call uses a bare 'return ret;', which leaks dma_buffer whenever the bus
acquire fails.

Replace the early return with goto fail so the existing cleanup path
runs.

Found via a custom Coccinelle semantic patch hunting for kmalloc'd
locals leaked on early-return error paths in driver firmware-download
code.

Fixes: 1241c5650ff7 ("wifi: wilc1000: Fill in missing error handling")
Signed-off-by: Shitalkumar Gandhi <shitalkumar.gandhi@cambiumnetworks.com>
---
Changes since v1:
  - Corrected From: and Signed-off-by: to author's real identity
    (Shitalkumar Gandhi <shitalkumar.gandhi@cambiumnetworks.com>).
    v1 was sent with incorrect author attribution due to a local
    git config mistake. No code changes.

 drivers/net/wireless/microchip/wilc1000/wlan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index 3fa8592eb250..4b116fe6f9ea 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -1265,7 +1265,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
 
 	ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 	if (ret)
-		return ret;
+		goto fail;
 
 	wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
 	reg &= ~BIT(10);
-- 
2.25.1


^ permalink raw reply related


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